// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

// This file was generated. Do not modify!
//
// To update this code, run: `cargo run --release -p diem-framework`.

//! Conversion library between a structured representation of a Move script call (`ScriptCall`) and the
//! standard BCS-compatible representation used in Diem transactions (`Script`).
//!
//! This code was generated by compiling known Script interfaces ("ABIs") with the tool `transaction-builder-generator`.

#![allow(clippy::unnecessary_wraps)]
#![allow(unused_imports)]
use diem_types::{
    account_address::AccountAddress,
    transaction::{Script, ScriptFunction, TransactionArgument, TransactionPayload},
};
use move_core_types::{
    ident_str,
    language_storage::{ModuleId, TypeTag},
};
use std::collections::BTreeMap as Map;

type Bytes = Vec<u8>;

/// Structured representation of a call into a known Move script.
/// ```ignore
/// impl ScriptCall {
///     pub fn encode(self) -> Script { .. }
///     pub fn decode(&Script) -> Option<ScriptCall> { .. }
/// }
/// ```
#[derive(Clone, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "fuzzing", derive(proptest_derive::Arbitrary))]
#[cfg_attr(feature = "fuzzing", proptest(no_params))]
pub enum ScriptCall {
    /// # Summary
    /// Adds a zero `Currency` balance to the sending `account`. This will enable `account` to
    /// send, receive, and hold `Diem::Diem<Currency>` coins. This transaction can be
    /// successfully sent by any account that is allowed to hold balances
    /// (e.g., VASP, Designated Dealer).
    ///
    /// # Technical Description
    /// After the successful execution of this transaction the sending account will have a
    /// `DiemAccount::Balance<Currency>` resource with zero balance published under it. Only
    /// accounts that can hold balances can send this transaction, the sending account cannot
    /// already have a `DiemAccount::Balance<Currency>` published under it.
    ///
    /// # Parameters
    /// | Name       | Type      | Description                                                                                                                                         |
    /// | ------     | ------    | -------------                                                                                                                                       |
    /// | `Currency` | Type      | The Move type for the `Currency` being added to the sending account of the transaction. `Currency` must be an already-registered currency on-chain. |
    /// | `account`  | `&signer` | The signer of the sending account of the transaction.                                                                                               |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                             | Description                                                                |
    /// | ----------------            | --------------                           | -------------                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                  | The `Currency` is not a registered currency on-chain.                      |
    /// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::EROLE_CANT_STORE_BALANCE` | The sending `account`'s role does not permit balances.                     |
    /// | `Errors::ALREADY_PUBLISHED` | `DiemAccount::EADD_EXISTING_CURRENCY`   | A balance for `Currency` is already published under the sending `account`. |
    ///
    /// # Related Scripts
    /// * `Script::create_child_vasp_account`
    /// * `Script::create_parent_vasp_account`
    /// * `Script::peer_to_peer_with_metadata`
    AddCurrencyToAccount { currency: TypeTag },

    /// # Summary
    /// Stores the sending accounts ability to rotate its authentication key with a designated recovery
    /// account. Both the sending and recovery accounts need to belong to the same VASP and
    /// both be VASP accounts. After this transaction both the sending account and the
    /// specified recovery account can rotate the sender account's authentication key.
    ///
    /// # Technical Description
    /// Adds the `DiemAccount::KeyRotationCapability` for the sending account
    /// (`to_recover_account`) to the `RecoveryAddress::RecoveryAddress` resource under
    /// `recovery_address`. After this transaction has been executed successfully the account at
    /// `recovery_address` and the `to_recover_account` may rotate the authentication key of
    /// `to_recover_account` (the sender of this transaction).
    ///
    /// The sending account of this transaction (`to_recover_account`) must not have previously given away its unique key
    /// rotation capability, and must be a VASP account. The account at `recovery_address`
    /// must also be a VASP account belonging to the same VASP as the `to_recover_account`.
    /// Additionally the account at `recovery_address` must have already initialized itself as
    /// a recovery account address using the `Script::create_recovery_address` transaction script.
    ///
    /// The sending account's (`to_recover_account`) key rotation capability is
    /// removed in this transaction and stored in the `RecoveryAddress::RecoveryAddress`
    /// resource stored under the account at `recovery_address`.
    ///
    /// # Parameters
    /// | Name                 | Type      | Description                                                                                                |
    /// | ------               | ------    | -------------                                                                                              |
    /// | `to_recover_account` | `&signer` | The signer reference of the sending account of this transaction.                                           |
    /// | `recovery_address`   | `address` | The account address where the `to_recover_account`'s `DiemAccount::KeyRotationCapability` will be stored. |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                              | Description                                                                                       |
    /// | ----------------           | --------------                                            | -------------                                                                                     |
    /// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `to_recover_account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.    |
    /// | `Errors::NOT_PUBLISHED`    | `RecoveryAddress::ERECOVERY_ADDRESS`                      | `recovery_address` does not have a `RecoveryAddress` resource published under it.                 |
    /// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::EINVALID_KEY_ROTATION_DELEGATION`       | `to_recover_account` and `recovery_address` do not belong to the same VASP.                       |
    /// | `Errors::LIMIT_EXCEEDED`   | ` RecoveryAddress::EMAX_KEYS_REGISTERED`                  | `RecoveryAddress::MAX_REGISTERED_KEYS` have already been registered with this `recovery_address`. |
    ///
    /// # Related Scripts
    /// * `Script::create_recovery_address`
    /// * `Script::rotate_authentication_key_with_recovery_address`
    AddRecoveryRotationCapability { recovery_address: AccountAddress },

    /// # Summary
    /// Adds a validator account to the validator set, and triggers a
    /// reconfiguration of the system to admit the account to the validator set for the system. This
    /// transaction can only be successfully called by the Diem Root account.
    ///
    /// # Technical Description
    /// This script adds the account at `validator_address` to the validator set.
    /// This transaction emits a `DiemConfig::NewEpochEvent` event and triggers a
    /// reconfiguration. Once the reconfiguration triggered by this script's
    /// execution has been performed, the account at the `validator_address` is
    /// considered to be a validator in the network.
    ///
    /// This transaction script will fail if the `validator_address` address is already in the validator set
    /// or does not have a `ValidatorConfig::ValidatorConfig` resource already published under it.
    ///
    /// # Parameters
    /// | Name                | Type         | Description                                                                                                                        |
    /// | ------              | ------       | -------------                                                                                                                      |
    /// | `dr_account`        | `&signer`    | The signer reference of the sending account of this transaction. Must be the Diem Root signer.                                    |
    /// | `sliding_nonce`     | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                         |
    /// | `validator_name`    | `vector<u8>` | ASCII-encoded human name for the validator. Must match the human name in the `ValidatorConfig::ValidatorConfig` for the validator. |
    /// | `validator_address` | `address`    | The validator account address to be added to the validator set.                                                                    |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                  | Description                                                                                                                               |
    /// | ----------------           | --------------                                | -------------                                                                                                                             |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `dr_account`.                                                                            |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                                                                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                                                                         |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                  | The sending account is not the Diem Root account.                                                                                        |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EDIEM_ROOT`                          | The sending account is not the Diem Root account.                                                                                        |
    /// | 0                          | 0                                             | The provided `validator_name` does not match the already-recorded human name for the validator.                                           |
    /// | `Errors::INVALID_ARGUMENT` | `DiemSystem::EINVALID_PROSPECTIVE_VALIDATOR` | The validator to be added does not have a `ValidatorConfig::ValidatorConfig` resource published under it, or its `config` field is empty. |
    /// | `Errors::INVALID_ARGUMENT` | `DiemSystem::EALREADY_A_VALIDATOR`           | The `validator_address` account is already a registered validator.                                                                        |
    /// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`            | An invalid time value was encountered in reconfiguration. Unlikely to occur.                                                              |
    ///
    /// # Related Scripts
    /// * `Script::create_validator_account`
    /// * `Script::create_validator_operator_account`
    /// * `Script::register_validator_config`
    /// * `Script::remove_validator_and_reconfigure`
    /// * `Script::set_validator_operator`
    /// * `Script::set_validator_operator_with_nonce_admin`
    /// * `Script::set_validator_config_and_reconfigure`
    AddValidatorAndReconfigure {
        sliding_nonce: u64,
        validator_name: Bytes,
        validator_address: AccountAddress,
    },

    /// # Summary
    /// Burns all coins held in the preburn resource at the specified
    /// preburn address and removes them from the system. The sending account must
    /// be the Treasury Compliance account.
    /// The account that holds the preburn resource will normally be a Designated
    /// Dealer, but there are no enforced requirements that it be one.
    ///
    /// # Technical Description
    /// This transaction permanently destroys all the coins of `Token` type
    /// stored in the `Diem::Preburn<Token>` resource published under the
    /// `preburn_address` account address.
    ///
    /// This transaction will only succeed if the sending `account` has a
    /// `Diem::BurnCapability<Token>`, and a `Diem::Preburn<Token>` resource
    /// exists under `preburn_address`, with a non-zero `to_burn` field. After the successful execution
    /// of this transaction the `total_value` field in the
    /// `Diem::CurrencyInfo<Token>` resource published under `0xA550C18` will be
    /// decremented by the value of the `to_burn` field of the preburn resource
    /// under `preburn_address` immediately before this transaction, and the
    /// `to_burn` field of the preburn resource will have a zero value.
    ///
    /// ## Events
    /// The successful execution of this transaction will emit a `Diem::BurnEvent` on the event handle
    /// held in the `Diem::CurrencyInfo<Token>` resource's `burn_events` published under
    /// `0xA550C18`.
    ///
    /// # Parameters
    /// | Name              | Type      | Description                                                                                                                  |
    /// | ------            | ------    | -------------                                                                                                                |
    /// | `Token`           | Type      | The Move type for the `Token` currency being burned. `Token` must be an already-registered currency on-chain.                |
    /// | `tc_account`      | `&signer` | The signer reference of the sending account of this transaction, must have a burn capability for `Token` published under it. |
    /// | `sliding_nonce`   | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                   |
    /// | `preburn_address` | `address` | The address where the coins to-be-burned are currently held.                                                                 |
    ///
    /// # Common Abort Conditions
    /// | Error Category                | Error Reason                            | Description                                                                                           |
    /// | ----------------              | --------------                          | -------------                                                                                         |
    /// | `Errors::NOT_PUBLISHED`       | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `account`.                                           |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.            |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                                         |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                                     |
    /// | `Errors::REQUIRES_CAPABILITY` | `Diem::EBURN_CAPABILITY`               | The sending `account` does not have a `Diem::BurnCapability<Token>` published under it.              |
    /// | `Errors::NOT_PUBLISHED`       | `Diem::EPREBURN`                       | The account at `preburn_address` does not have a `Diem::Preburn<Token>` resource published under it. |
    /// | `Errors::INVALID_STATE`       | `Diem::EPREBURN_EMPTY`                 | The `Diem::Preburn<Token>` resource is empty (has a value of 0).                                     |
    /// | `Errors::NOT_PUBLISHED`       | `Diem::ECURRENCY_INFO`                 | The specified `Token` is not a registered currency on-chain.                                          |
    ///
    /// # Related Scripts
    /// * `Script::burn_txn_fees`
    /// * `Script::cancel_burn`
    /// * `Script::preburn`
    Burn {
        token: TypeTag,
        sliding_nonce: u64,
        preburn_address: AccountAddress,
    },

    /// # Summary
    /// Burns the transaction fees collected in the `CoinType` currency so that the
    /// Diem association may reclaim the backing coins off-chain. May only be sent
    /// by the Treasury Compliance account.
    ///
    /// # Technical Description
    /// Burns the transaction fees collected in `CoinType` so that the
    /// association may reclaim the backing coins. Once this transaction has executed
    /// successfully all transaction fees that will have been collected in
    /// `CoinType` since the last time this script was called with that specific
    /// currency. Both `balance` and `preburn` fields in the
    /// `TransactionFee::TransactionFee<CoinType>` resource published under the `0xB1E55ED`
    /// account address will have a value of 0 after the successful execution of this script.
    ///
    /// ## Events
    /// The successful execution of this transaction will emit a `Diem::BurnEvent` on the event handle
    /// held in the `Diem::CurrencyInfo<CoinType>` resource's `burn_events` published under
    /// `0xA550C18`.
    ///
    /// # Parameters
    /// | Name         | Type      | Description                                                                                                                                         |
    /// | ------       | ------    | -------------                                                                                                                                       |
    /// | `CoinType`   | Type      | The Move type for the `CoinType` being added to the sending account of the transaction. `CoinType` must be an already-registered currency on-chain. |
    /// | `tc_account` | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.                                           |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                          | Description                                                 |
    /// | ----------------           | --------------                        | -------------                                               |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE` | The sending account is not the Treasury Compliance account. |
    /// | `Errors::NOT_PUBLISHED`    | `TransactionFee::ETRANSACTION_FEE`    | `CoinType` is not an accepted transaction fee currency.     |
    /// | `Errors::INVALID_ARGUMENT` | `Diem::ECOIN`                        | The collected fees in `CoinType` are zero.                  |
    ///
    /// # Related Scripts
    /// * `Script::burn`
    /// * `Script::cancel_burn`
    BurnTxnFees { coin_type: TypeTag },

    /// # Summary
    /// Cancels and returns all coins held in the preburn area under
    /// `preburn_address` and returns the funds to the `preburn_address`'s balance.
    /// Can only be successfully sent by an account with Treasury Compliance role.
    ///
    /// # Technical Description
    /// Cancels and returns all coins held in the `Diem::Preburn<Token>` resource under the `preburn_address` and
    /// return the funds to the `preburn_address` account's `DiemAccount::Balance<Token>`.
    /// The transaction must be sent by an `account` with a `Diem::BurnCapability<Token>`
    /// resource published under it. The account at `preburn_address` must have a
    /// `Diem::Preburn<Token>` resource published under it, and its value must be nonzero. The transaction removes
    /// the entire balance held in the `Diem::Preburn<Token>` resource, and returns it back to the account's
    /// `DiemAccount::Balance<Token>` under `preburn_address`. Due to this, the account at
    /// `preburn_address` must already have a balance in the `Token` currency published
    /// before this script is called otherwise the transaction will fail.
    ///
    /// ## Events
    /// The successful execution of this transaction will emit:
    /// * A `Diem::CancelBurnEvent` on the event handle held in the `Diem::CurrencyInfo<Token>`
    /// resource's `burn_events` published under `0xA550C18`.
    /// * A `DiemAccount::ReceivedPaymentEvent` on the `preburn_address`'s
    /// `DiemAccount::DiemAccount` `received_events` event handle with both the `payer` and `payee`
    /// being `preburn_address`.
    ///
    /// # Parameters
    /// | Name              | Type      | Description                                                                                                                          |
    /// | ------            | ------    | -------------                                                                                                                        |
    /// | `Token`           | Type      | The Move type for the `Token` currenty that burning is being cancelled for. `Token` must be an already-registered currency on-chain. |
    /// | `account`         | `&signer` | The signer reference of the sending account of this transaction, must have a burn capability for `Token` published under it.         |
    /// | `preburn_address` | `address` | The address where the coins to-be-burned are currently held.                                                                         |
    ///
    /// # Common Abort Conditions
    /// | Error Category                | Error Reason                                     | Description                                                                                           |
    /// | ----------------              | --------------                                   | -------------                                                                                         |
    /// | `Errors::REQUIRES_CAPABILITY` | `Diem::EBURN_CAPABILITY`                        | The sending `account` does not have a `Diem::BurnCapability<Token>` published under it.              |
    /// | `Errors::NOT_PUBLISHED`       | `Diem::EPREBURN`                                | The account at `preburn_address` does not have a `Diem::Preburn<Token>` resource published under it. |
    /// | `Errors::NOT_PUBLISHED`       | `Diem::ECURRENCY_INFO`                          | The specified `Token` is not a registered currency on-chain.                                          |
    /// | `Errors::INVALID_ARGUMENT`    | `DiemAccount::ECOIN_DEPOSIT_IS_ZERO`            | The value held in the preburn resource was zero.                                                      |
    /// | `Errors::INVALID_ARGUMENT`    | `DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE` | The account at `preburn_address` doesn't have a balance resource for `Token`.                         |
    /// | `Errors::LIMIT_EXCEEDED`      | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`          | The depositing of the funds held in the prebun area would exceed the `account`'s account limits.      |
    /// | `Errors::INVALID_STATE`       | `DualAttestation::EPAYEE_COMPLIANCE_KEY_NOT_SET` | The `account` does not have a compliance key set on it but dual attestion checking was performed.     |
    ///
    /// # Related Scripts
    /// * `Script::burn_txn_fees`
    /// * `Script::burn`
    /// * `Script::preburn`
    CancelBurn {
        token: TypeTag,
        preburn_address: AccountAddress,
    },

    /// # Summary
    /// Creates a Child VASP account with its parent being the sending account of the transaction.
    /// The sender of the transaction must be a Parent VASP account.
    ///
    /// # Technical Description
    /// Creates a `ChildVASP` account for the sender `parent_vasp` at `child_address` with a balance of
    /// `child_initial_balance` in `CoinType` and an initial authentication key of
    /// `auth_key_prefix | child_address`.
    ///
    /// If `add_all_currencies` is true, the child address will have a zero balance in all available
    /// currencies in the system.
    ///
    /// The new account will be a child account of the transaction sender, which must be a
    /// Parent VASP account. The child account will be recorded against the limit of
    /// child accounts of the creating Parent VASP account.
    ///
    /// ## Events
    /// Successful execution with a `child_initial_balance` greater than zero will emit:
    /// * A `DiemAccount::SentPaymentEvent` with the `payer` field being the Parent VASP's address,
    /// and payee field being `child_address`. This is emitted on the Parent VASP's
    /// `DiemAccount::DiemAccount` `sent_events` handle.
    /// * A `DiemAccount::ReceivedPaymentEvent` with the  `payer` field being the Parent VASP's address,
    /// and payee field being `child_address`. This is emitted on the new Child VASPS's
    /// `DiemAccount::DiemAccount` `received_events` handle.
    ///
    /// # Parameters
    /// | Name                    | Type         | Description                                                                                                                                 |
    /// | ------                  | ------       | -------------                                                                                                                               |
    /// | `CoinType`              | Type         | The Move type for the `CoinType` that the child account should be created with. `CoinType` must be an already-registered currency on-chain. |
    /// | `parent_vasp`           | `&signer`    | The signer reference of the sending account. Must be a Parent VASP account.                                                                 |
    /// | `child_address`         | `address`    | Address of the to-be-created Child VASP account.                                                                                            |
    /// | `auth_key_prefix`       | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                    |
    /// | `add_all_currencies`    | `bool`       | Whether to publish balance resources for all known currencies when the account is created.                                                  |
    /// | `child_initial_balance` | `u64`        | The initial balance in `CoinType` to give the child account when it's created.                                                              |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                                             | Description                                                                              |
    /// | ----------------            | --------------                                           | -------------                                                                            |
    /// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`            | The `auth_key_prefix` was not of length 32.                                              |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::EPARENT_VASP`                                    | The sending account wasn't a Parent VASP account.                                        |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                                        | The `child_address` address is already taken.                                            |
    /// | `Errors::LIMIT_EXCEEDED`    | `VASP::ETOO_MANY_CHILDREN`                               | The sending account has reached the maximum number of allowed child accounts.            |
    /// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                                  | The `CoinType` is not a registered currency on-chain.                                    |
    /// | `Errors::INVALID_STATE`     | `DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED` | The withdrawal capability for the sending account has already been extracted.            |
    /// | `Errors::NOT_PUBLISHED`     | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`              | The sending account doesn't have a balance in `CoinType`.                                |
    /// | `Errors::LIMIT_EXCEEDED`    | `DiemAccount::EINSUFFICIENT_BALANCE`                    | The sending account doesn't have at least `child_initial_balance` of `CoinType` balance. |
    /// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::ECANNOT_CREATE_AT_VM_RESERVED`            | The `child_address` is the reserved address 0x0.                                         |
    ///
    /// # Related Scripts
    /// * `Script::create_parent_vasp_account`
    /// * `Script::add_currency_to_account`
    /// * `Script::rotate_authentication_key`
    /// * `Script::add_recovery_rotation_capability`
    /// * `Script::create_recovery_address`
    CreateChildVaspAccount {
        coin_type: TypeTag,
        child_address: AccountAddress,
        auth_key_prefix: Bytes,
        add_all_currencies: bool,
        child_initial_balance: u64,
    },

    /// # Summary
    /// Creates a Designated Dealer account with the provided information, and initializes it with
    /// default mint tiers. The transaction can only be sent by the Treasury Compliance account.
    ///
    /// # Technical Description
    /// Creates an account with the Designated Dealer role at `addr` with authentication key
    /// `auth_key_prefix` | `addr` and a 0 balance of type `Currency`. If `add_all_currencies` is true,
    /// 0 balances for all available currencies in the system will also be added. This can only be
    /// invoked by an account with the TreasuryCompliance role.
    ///
    /// At the time of creation the account is also initialized with default mint tiers of (500_000,
    /// 5000_000, 50_000_000, 500_000_000), and preburn areas for each currency that is added to the
    /// account.
    ///
    /// # Parameters
    /// | Name                 | Type         | Description                                                                                                                                         |
    /// | ------               | ------       | -------------                                                                                                                                       |
    /// | `Currency`           | Type         | The Move type for the `Currency` that the Designated Dealer should be initialized with. `Currency` must be an already-registered currency on-chain. |
    /// | `tc_account`         | `&signer`    | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.                                           |
    /// | `sliding_nonce`      | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                                          |
    /// | `addr`               | `address`    | Address of the to-be-created Designated Dealer account.                                                                                             |
    /// | `auth_key_prefix`    | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                            |
    /// | `human_name`         | `vector<u8>` | ASCII-encoded human name for the Designated Dealer.                                                                                                 |
    /// | `add_all_currencies` | `bool`       | Whether to publish preburn, balance, and tier info resources for all known (SCS) currencies or just `Currency` when the account is created.         |
    ///

    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                            | Description                                                                                |
    /// | ----------------            | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::ETREASURY_COMPLIANCE`           | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                 | The `Currency` is not a registered currency on-chain.                                      |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `addr` address is already taken.                                                       |
    ///
    /// # Related Scripts
    /// * `Script::tiered_mint`
    /// * `Script::peer_to_peer_with_metadata`
    /// * `Script::rotate_dual_attestation_info`
    CreateDesignatedDealer {
        currency: TypeTag,
        sliding_nonce: u64,
        addr: AccountAddress,
        auth_key_prefix: Bytes,
        human_name: Bytes,
        add_all_currencies: bool,
    },

    /// # Summary
    /// Creates a Parent VASP account with the specified human name. Must be called by the Treasury Compliance account.
    ///
    /// # Technical Description
    /// Creates an account with the Parent VASP role at `address` with authentication key
    /// `auth_key_prefix` | `new_account_address` and a 0 balance of type `CoinType`. If
    /// `add_all_currencies` is true, 0 balances for all available currencies in the system will
    /// also be added. This can only be invoked by an TreasuryCompliance account.
    /// `sliding_nonce` is a unique nonce for operation, see `SlidingNonce` for details.
    ///
    /// # Parameters
    /// | Name                  | Type         | Description                                                                                                                                                    |
    /// | ------                | ------       | -------------                                                                                                                                                  |
    /// | `CoinType`            | Type         | The Move type for the `CoinType` currency that the Parent VASP account should be initialized with. `CoinType` must be an already-registered currency on-chain. |
    /// | `tc_account`          | `&signer`    | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.                                                      |
    /// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                                                     |
    /// | `new_account_address` | `address`    | Address of the to-be-created Parent VASP account.                                                                                                              |
    /// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                                       |
    /// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the Parent VASP.                                                                                                                  |
    /// | `add_all_currencies`  | `bool`       | Whether to publish balance resources for all known currencies when the account is created.                                                                     |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                            | Description                                                                                |
    /// | ----------------            | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::ETREASURY_COMPLIANCE`           | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                 | The `CoinType` is not a registered currency on-chain.                                      |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
    ///
    /// # Related Scripts
    /// * `Script::create_child_vasp_account`
    /// * `Script::add_currency_to_account`
    /// * `Script::rotate_authentication_key`
    /// * `Script::add_recovery_rotation_capability`
    /// * `Script::create_recovery_address`
    /// * `Script::rotate_dual_attestation_info`
    CreateParentVaspAccount {
        coin_type: TypeTag,
        sliding_nonce: u64,
        new_account_address: AccountAddress,
        auth_key_prefix: Bytes,
        human_name: Bytes,
        add_all_currencies: bool,
    },

    /// # Summary
    /// Initializes the sending account as a recovery address that may be used by
    /// the VASP that it belongs to. The sending account must be a VASP account.
    /// Multiple recovery addresses can exist for a single VASP, but accounts in
    /// each must be disjoint.
    ///
    /// # Technical Description
    /// Publishes a `RecoveryAddress::RecoveryAddress` resource under `account`. It then
    /// extracts the `DiemAccount::KeyRotationCapability` for `account` and adds
    /// it to the resource. After the successful execution of this transaction
    /// other accounts may add their key rotation to this resource so that `account`
    /// may be used as a recovery account for those accounts.
    ///
    /// # Parameters
    /// | Name      | Type      | Description                                           |
    /// | ------    | ------    | -------------                                         |
    /// | `account` | `&signer` | The signer of the sending account of the transaction. |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                                               | Description                                                                                   |
    /// | ----------------            | --------------                                             | -------------                                                                                 |
    /// | `Errors::INVALID_STATE`     | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.          |
    /// | `Errors::INVALID_ARGUMENT`  | `RecoveryAddress::ENOT_A_VASP`                             | `account` is not a VASP account.                                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `RecoveryAddress::EKEY_ROTATION_DEPENDENCY_CYCLE`          | A key rotation recovery cycle would be created by adding `account`'s key rotation capability. |
    /// | `Errors::ALREADY_PUBLISHED` | `RecoveryAddress::ERECOVERY_ADDRESS`                       | A `RecoveryAddress::RecoveryAddress` resource has already been published under `account`.     |
    ///
    /// # Related Scripts
    /// * `Script::add_recovery_rotation_capability`
    /// * `Script::rotate_authentication_key_with_recovery_address`
    CreateRecoveryAddress {},

    /// # Summary
    /// Creates a Validator account. This transaction can only be sent by the Diem
    /// Root account.
    ///
    /// # Technical Description
    /// Creates an account with a Validator role at `new_account_address`, with authentication key
    /// `auth_key_prefix` | `new_account_address`. It publishes a
    /// `ValidatorConfig::ValidatorConfig` resource with empty `config`, and
    /// `operator_account` fields. The `human_name` field of the
    /// `ValidatorConfig::ValidatorConfig` is set to the passed in `human_name`.
    /// This script does not add the validator to the validator set or the system,
    /// but only creates the account.
    ///
    /// # Parameters
    /// | Name                  | Type         | Description                                                                                     |
    /// | ------                | ------       | -------------                                                                                   |
    /// | `dr_account`          | `&signer`    | The signer reference of the sending account of this transaction. Must be the Diem Root signer. |
    /// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
    /// | `new_account_address` | `address`    | Address of the to-be-created Validator account.                                                 |
    /// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.        |
    /// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the validator.                                                     |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                            | Description                                                                                |
    /// | ----------------            | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                             |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                         |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                         |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
    ///
    /// # Related Scripts
    /// * `Script::add_validator_and_reconfigure`
    /// * `Script::create_validator_operator_account`
    /// * `Script::register_validator_config`
    /// * `Script::remove_validator_and_reconfigure`
    /// * `Script::set_validator_operator`
    /// * `Script::set_validator_operator_with_nonce_admin`
    /// * `Script::set_validator_config_and_reconfigure`
    CreateValidatorAccount {
        sliding_nonce: u64,
        new_account_address: AccountAddress,
        auth_key_prefix: Bytes,
        human_name: Bytes,
    },

    /// # Summary
    /// Creates a Validator Operator account. This transaction can only be sent by the Diem
    /// Root account.
    ///
    /// # Technical Description
    /// Creates an account with a Validator Operator role at `new_account_address`, with authentication key
    /// `auth_key_prefix` | `new_account_address`. It publishes a
    /// `ValidatorOperatorConfig::ValidatorOperatorConfig` resource with the specified `human_name`.
    /// This script does not assign the validator operator to any validator accounts but only creates the account.
    ///
    /// # Parameters
    /// | Name                  | Type         | Description                                                                                     |
    /// | ------                | ------       | -------------                                                                                   |
    /// | `dr_account`          | `&signer`    | The signer reference of the sending account of this transaction. Must be the Diem Root signer. |
    /// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
    /// | `new_account_address` | `address`    | Address of the to-be-created Validator account.                                                 |
    /// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.        |
    /// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the validator.                                                     |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                            | Description                                                                                |
    /// | ----------------            | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                             |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                         |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                         |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
    ///
    /// # Related Scripts
    /// * `Script::create_validator_account`
    /// * `Script::add_validator_and_reconfigure`
    /// * `Script::register_validator_config`
    /// * `Script::remove_validator_and_reconfigure`
    /// * `Script::set_validator_operator`
    /// * `Script::set_validator_operator_with_nonce_admin`
    /// * `Script::set_validator_config_and_reconfigure`
    CreateValidatorOperatorAccount {
        sliding_nonce: u64,
        new_account_address: AccountAddress,
        auth_key_prefix: Bytes,
        human_name: Bytes,
    },

    /// # Summary
    /// Freezes the account at `address`. The sending account of this transaction
    /// must be the Treasury Compliance account. The account being frozen cannot be
    /// the Diem Root or Treasury Compliance account. After the successful
    /// execution of this transaction no transactions may be sent from the frozen
    /// account, and the frozen account may not send or receive coins.
    ///
    /// # Technical Description
    /// Sets the `AccountFreezing::FreezingBit` to `true` and emits a
    /// `AccountFreezing::FreezeAccountEvent`. The transaction sender must be the
    /// Treasury Compliance account, but the account at `to_freeze_account` must
    /// not be either `0xA550C18` (the Diem Root address), or `0xB1E55ED` (the
    /// Treasury Compliance address). Note that this is a per-account property
    /// e.g., freezing a Parent VASP will not effect the status any of its child
    /// accounts and vice versa.
    ///

    /// ## Events
    /// Successful execution of this transaction will emit a `AccountFreezing::FreezeAccountEvent` on
    /// the `freeze_event_handle` held in the `AccountFreezing::FreezeEventsHolder` resource published
    /// under `0xA550C18` with the `frozen_address` being the `to_freeze_account`.
    ///
    /// # Parameters
    /// | Name                | Type      | Description                                                                                               |
    /// | ------              | ------    | -------------                                                                                             |
    /// | `tc_account`        | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account. |
    /// | `sliding_nonce`     | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                |
    /// | `to_freeze_account` | `address` | The account address to be frozen.                                                                         |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                 | Description                                                                                |
    /// | ----------------           | --------------                               | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`        | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`                | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::INVALID_ARGUMENT` | `AccountFreezing::ECANNOT_FREEZE_TC`         | `to_freeze_account` was the Treasury Compliance account (`0xB1E55ED`).                     |
    /// | `Errors::INVALID_ARGUMENT` | `AccountFreezing::ECANNOT_FREEZE_DIEM_ROOT` | `to_freeze_account` was the Diem Root account (`0xA550C18`).                              |
    ///
    /// # Related Scripts
    /// * `Script::unfreeze_account`
    FreezeAccount {
        sliding_nonce: u64,
        to_freeze_account: AccountAddress,
    },

    /// # Summary
    /// Transfers a given number of coins in a specified currency from one account to another.
    /// Transfers over a specified amount defined on-chain that are between two different VASPs, or
    /// other accounts that have opted-in will be subject to on-chain checks to ensure the receiver has
    /// agreed to receive the coins.  This transaction can be sent by any account that can hold a
    /// balance, and to any account that can hold a balance. Both accounts must hold balances in the
    /// currency being transacted.
    ///
    /// # Technical Description
    ///
    /// Transfers `amount` coins of type `Currency` from `payer` to `payee` with (optional) associated
    /// `metadata` and an (optional) `metadata_signature` on the message
    /// `metadata` | `Signer::address_of(payer)` | `amount` | `DualAttestation::DOMAIN_SEPARATOR`.
    /// The `metadata` and `metadata_signature` parameters are only required if `amount` >=
    /// `DualAttestation::get_cur_microdiem_limit` XDX and `payer` and `payee` are distinct VASPs.
    /// However, a transaction sender can opt in to dual attestation even when it is not required
    /// (e.g., a DesignatedDealer -> VASP payment) by providing a non-empty `metadata_signature`.
    /// Standardized `metadata` BCS format can be found in `diem_types::transaction::metadata::Metadata`.
    ///
    /// ## Events
    /// Successful execution of this script emits two events:
    /// * A `DiemAccount::SentPaymentEvent` on `payer`'s `DiemAccount::DiemAccount` `sent_events` handle; and
    /// * A `DiemAccount::ReceivedPaymentEvent` on `payee`'s `DiemAccount::DiemAccount` `received_events` handle.
    ///
    /// # Parameters
    /// | Name                 | Type         | Description                                                                                                                  |
    /// | ------               | ------       | -------------                                                                                                                |
    /// | `Currency`           | Type         | The Move type for the `Currency` being sent in this transaction. `Currency` must be an already-registered currency on-chain. |
    /// | `payer`              | `&signer`    | The signer reference of the sending account that coins are being transferred from.                                           |
    /// | `payee`              | `address`    | The address of the account the coins are being transferred to.                                                               |
    /// | `metadata`           | `vector<u8>` | Optional metadata about this payment.                                                                                        |
    /// | `metadata_signature` | `vector<u8>` | Optional signature over `metadata` and payment information. See                                                              |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                     | Description                                                                                                                         |
    /// | ----------------           | --------------                                   | -------------                                                                                                                       |
    /// | `Errors::NOT_PUBLISHED`    | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`      | `payer` doesn't hold a balance in `Currency`.                                                                                       |
    /// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EINSUFFICIENT_BALANCE`            | `amount` is greater than `payer`'s balance in `Currency`.                                                                           |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::ECOIN_DEPOSIT_IS_ZERO`            | `amount` is zero.                                                                                                                   |
    /// | `Errors::NOT_PUBLISHED`    | `DiemAccount::EPAYEE_DOES_NOT_EXIST`            | No account exists at the `payee` address.                                                                                           |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE` | An account exists at `payee`, but it does not accept payments in `Currency`.                                                        |
    /// | `Errors::INVALID_STATE`    | `AccountFreezing::EACCOUNT_FROZEN`               | The `payee` account is frozen.                                                                                                      |
    /// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EMALFORMED_METADATA_SIGNATURE` | `metadata_signature` is not 64 bytes.                                                                                               |
    /// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EINVALID_METADATA_SIGNATURE`   | `metadata_signature` does not verify on the against the `payee'`s `DualAttestation::Credential` `compliance_public_key` public key. |
    /// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EWITHDRAWAL_EXCEEDS_LIMITS`       | `payer` has exceeded its daily withdrawal limits for the backing coins of XDX.                                                      |
    /// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`          | `payee` has exceeded its daily deposit limits for XDX.                                                                              |
    ///
    /// # Related Scripts
    /// * `Script::create_child_vasp_account`
    /// * `Script::create_parent_vasp_account`
    /// * `Script::add_currency_to_account`
    PeerToPeerWithMetadata {
        currency: TypeTag,
        payee: AccountAddress,
        amount: u64,
        metadata: Bytes,
        metadata_signature: Bytes,
    },

    /// # Summary
    /// Moves a specified number of coins in a given currency from the account's
    /// balance to its preburn area after which the coins may be burned. This
    /// transaction may be sent by any account that holds a balance and preburn area
    /// in the specified currency.
    ///
    /// # Technical Description
    /// Moves the specified `amount` of coins in `Token` currency from the sending `account`'s
    /// `DiemAccount::Balance<Token>` to the `Diem::Preburn<Token>` published under the same
    /// `account`. `account` must have both of these resources published under it at the start of this
    /// transaction in order for it to execute successfully.
    ///
    /// ## Events
    /// Successful execution of this script emits two events:
    /// * `DiemAccount::SentPaymentEvent ` on `account`'s `DiemAccount::DiemAccount` `sent_events`
    /// handle with the `payee` and `payer` fields being `account`'s address; and
    /// * A `Diem::PreburnEvent` with `Token`'s currency code on the
    /// `Diem::CurrencyInfo<Token`'s `preburn_events` handle for `Token` and with
    /// `preburn_address` set to `account`'s address.
    ///
    /// # Parameters
    /// | Name      | Type      | Description                                                                                                                      |
    /// | ------    | ------    | -------------                                                                                                                    |
    /// | `Token`   | Type      | The Move type for the `Token` currency being moved to the preburn area. `Token` must be an already-registered currency on-chain. |
    /// | `account` | `&signer` | The signer reference of the sending account.                                                                                     |
    /// | `amount`  | `u64`     | The amount in `Token` to be moved to the preburn area.                                                                           |
    ///
    /// # Common Abort Conditions
    /// | Error Category           | Error Reason                                             | Description                                                                             |
    /// | ----------------         | --------------                                           | -------------                                                                           |
    /// | `Errors::NOT_PUBLISHED`  | `Diem::ECURRENCY_INFO`                                  | The `Token` is not a registered currency on-chain.                                      |
    /// | `Errors::INVALID_STATE`  | `DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED` | The withdrawal capability for `account` has already been extracted.                     |
    /// | `Errors::LIMIT_EXCEEDED` | `DiemAccount::EINSUFFICIENT_BALANCE`                    | `amount` is greater than `payer`'s balance in `Token`.                                  |
    /// | `Errors::NOT_PUBLISHED`  | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`              | `account` doesn't hold a balance in `Token`.                                            |
    /// | `Errors::NOT_PUBLISHED`  | `Diem::EPREBURN`                                        | `account` doesn't have a `Diem::Preburn<Token>` resource published under it.           |
    /// | `Errors::INVALID_STATE`  | `Diem::EPREBURN_OCCUPIED`                               | The `value` field in the `Diem::Preburn<Token>` resource under the sender is non-zero. |
    /// | `Errors::NOT_PUBLISHED`  | `Roles::EROLE_ID`                                        | The `account` did not have a role assigned to it.                                       |
    /// | `Errors::REQUIRES_ROLE`  | `Roles::EDESIGNATED_DEALER`                              | The `account` did not have the role of DesignatedDealer.                                |
    ///
    /// # Related Scripts
    /// * `Script::cancel_burn`
    /// * `Script::burn`
    /// * `Script::burn_txn_fees`
    Preburn { token: TypeTag, amount: u64 },

    /// # Summary
    /// Rotates the authentication key of the sending account to the
    /// newly-specified public key and publishes a new shared authentication key
    /// under the sender's account. Any account can send this transaction.
    ///
    /// # Technical Description
    /// Rotates the authentication key of the sending account to `public_key`,
    /// and publishes a `SharedEd25519PublicKey::SharedEd25519PublicKey` resource
    /// containing the 32-byte ed25519 `public_key` and the `DiemAccount::KeyRotationCapability` for
    /// `account` under `account`.
    ///
    /// # Parameters
    /// | Name         | Type         | Description                                                                               |
    /// | ------       | ------       | -------------                                                                             |
    /// | `account`    | `&signer`    | The signer reference of the sending account of the transaction.                           |
    /// | `public_key` | `vector<u8>` | 32-byte Ed25519 public key for `account`' authentication key to be rotated to and stored. |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                                               | Description                                                                                         |
    /// | ----------------            | --------------                                             | -------------                                                                                       |
    /// | `Errors::INVALID_STATE`     | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability` resource.       |
    /// | `Errors::ALREADY_PUBLISHED` | `SharedEd25519PublicKey::ESHARED_KEY`                      | The `SharedEd25519PublicKey::SharedEd25519PublicKey` resource is already published under `account`. |
    /// | `Errors::INVALID_ARGUMENT`  | `SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY`            | `public_key` is an invalid ed25519 public key.                                                      |
    ///
    /// # Related Scripts
    /// * `Script::rotate_shared_ed25519_public_key`
    PublishSharedEd25519PublicKey { public_key: Bytes },

    /// # Summary
    /// Updates a validator's configuration. This does not reconfigure the system and will not update
    /// the configuration in the validator set that is seen by other validators in the network. Can
    /// only be successfully sent by a Validator Operator account that is already registered with a
    /// validator.
    ///
    /// # Technical Description
    /// This updates the fields with corresponding names held in the `ValidatorConfig::ValidatorConfig`
    /// config resource held under `validator_account`. It does not emit a `DiemConfig::NewEpochEvent`
    /// so the copy of this config held in the validator set will not be updated, and the changes are
    /// only "locally" under the `validator_account` account address.
    ///
    /// # Parameters
    /// | Name                          | Type         | Description                                                                                                                  |
    /// | ------                        | ------       | -------------                                                                                                                |
    /// | `validator_operator_account`  | `&signer`    | Signer reference of the sending account. Must be the registered validator operator for the validator at `validator_address`. |
    /// | `validator_account`           | `address`    | The address of the validator's `ValidatorConfig::ValidatorConfig` resource being updated.                                    |
    /// | `consensus_pubkey`            | `vector<u8>` | New Ed25519 public key to be used in the updated `ValidatorConfig::ValidatorConfig`.                                         |
    /// | `validator_network_addresses` | `vector<u8>` | New set of `validator_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.                       |
    /// | `fullnode_network_addresses`  | `vector<u8>` | New set of `fullnode_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.                        |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                   | Description                                                                                           |
    /// | ----------------           | --------------                                 | -------------                                                                                         |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`           | `validator_address` does not have a `ValidatorConfig::ValidatorConfig` resource published under it.   |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_TRANSACTION_SENDER` | `validator_operator_account` is not the registered operator for the validator at `validator_address`. |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_CONSENSUS_KEY`      | `consensus_pubkey` is not a valid ed25519 public key.                                                 |
    ///
    /// # Related Scripts
    /// * `Script::create_validator_account`
    /// * `Script::create_validator_operator_account`
    /// * `Script::add_validator_and_reconfigure`
    /// * `Script::remove_validator_and_reconfigure`
    /// * `Script::set_validator_operator`
    /// * `Script::set_validator_operator_with_nonce_admin`
    /// * `Script::set_validator_config_and_reconfigure`
    RegisterValidatorConfig {
        validator_account: AccountAddress,
        consensus_pubkey: Bytes,
        validator_network_addresses: Bytes,
        fullnode_network_addresses: Bytes,
    },

    /// # Summary
    /// This script removes a validator account from the validator set, and triggers a reconfiguration
    /// of the system to remove the validator from the system. This transaction can only be
    /// successfully called by the Diem Root account.
    ///
    /// # Technical Description
    /// This script removes the account at `validator_address` from the validator set. This transaction
    /// emits a `DiemConfig::NewEpochEvent` event. Once the reconfiguration triggered by this event
    /// has been performed, the account at `validator_address` is no longer considered to be a
    /// validator in the network. This transaction will fail if the validator at `validator_address`
    /// is not in the validator set.
    ///
    /// # Parameters
    /// | Name                | Type         | Description                                                                                                                        |
    /// | ------              | ------       | -------------                                                                                                                      |
    /// | `dr_account`        | `&signer`    | The signer reference of the sending account of this transaction. Must be the Diem Root signer.                                    |
    /// | `sliding_nonce`     | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                         |
    /// | `validator_name`    | `vector<u8>` | ASCII-encoded human name for the validator. Must match the human name in the `ValidatorConfig::ValidatorConfig` for the validator. |
    /// | `validator_address` | `address`    | The validator account address to be removed from the validator set.                                                                |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                            | Description                                                                                     |
    /// | ----------------           | --------------                          | -------------                                                                                   |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                                  |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.      |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                                   |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                               |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | The sending account is not the Diem Root account or Treasury Compliance account                |
    /// | 0                          | 0                                       | The provided `validator_name` does not match the already-recorded human name for the validator. |
    /// | `Errors::INVALID_ARGUMENT` | `DiemSystem::ENOT_AN_ACTIVE_VALIDATOR` | The validator to be removed is not in the validator set.                                        |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                              |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                              |
    /// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`      | An invalid time value was encountered in reconfiguration. Unlikely to occur.                    |
    ///
    /// # Related Scripts
    /// * `Script::create_validator_account`
    /// * `Script::create_validator_operator_account`
    /// * `Script::register_validator_config`
    /// * `Script::add_validator_and_reconfigure`
    /// * `Script::set_validator_operator`
    /// * `Script::set_validator_operator_with_nonce_admin`
    /// * `Script::set_validator_config_and_reconfigure`
    RemoveValidatorAndReconfigure {
        sliding_nonce: u64,
        validator_name: Bytes,
        validator_address: AccountAddress,
    },

    /// # Summary
    /// Rotates the transaction sender's authentication key to the supplied new authentication key. May
    /// be sent by any account.
    ///
    /// # Technical Description
    /// Rotate the `account`'s `DiemAccount::DiemAccount` `authentication_key` field to `new_key`.
    /// `new_key` must be a valid ed25519 public key, and `account` must not have previously delegated
    /// its `DiemAccount::KeyRotationCapability`.
    ///
    /// # Parameters
    /// | Name      | Type         | Description                                                 |
    /// | ------    | ------       | -------------                                               |
    /// | `account` | `&signer`    | Signer reference of the sending account of the transaction. |
    /// | `new_key` | `vector<u8>` | New ed25519 public key to be used for `account`.            |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                               | Description                                                                              |
    /// | ----------------           | --------------                                             | -------------                                                                            |
    /// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.     |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                         |
    ///
    /// # Related Scripts
    /// * `Script::rotate_authentication_key_with_nonce`
    /// * `Script::rotate_authentication_key_with_nonce_admin`
    /// * `Script::rotate_authentication_key_with_recovery_address`
    RotateAuthenticationKey { new_key: Bytes },

    /// # Summary
    /// Rotates the sender's authentication key to the supplied new authentication key. May be sent by
    /// any account that has a sliding nonce resource published under it (usually this is Treasury
    /// Compliance or Diem Root accounts).
    ///
    /// # Technical Description
    /// Rotates the `account`'s `DiemAccount::DiemAccount` `authentication_key` field to `new_key`.
    /// `new_key` must be a valid ed25519 public key, and `account` must not have previously delegated
    /// its `DiemAccount::KeyRotationCapability`.
    ///
    /// # Parameters
    /// | Name            | Type         | Description                                                                |
    /// | ------          | ------       | -------------                                                              |
    /// | `account`       | `&signer`    | Signer reference of the sending account of the transaction.                |
    /// | `sliding_nonce` | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
    /// | `new_key`       | `vector<u8>` | New ed25519 public key to be used for `account`.                           |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                               | Description                                                                                |
    /// | ----------------           | --------------                                             | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                             | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                             | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                             | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`                    | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.       |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                           |
    ///
    /// # Related Scripts
    /// * `Script::rotate_authentication_key`
    /// * `Script::rotate_authentication_key_with_nonce_admin`
    /// * `Script::rotate_authentication_key_with_recovery_address`
    RotateAuthenticationKeyWithNonce { sliding_nonce: u64, new_key: Bytes },

    /// # Summary
    /// Rotates the specified account's authentication key to the supplied new authentication key. May
    /// only be sent by the Diem Root account as a write set transaction.
    ///
    /// # Technical Description
    /// Rotate the `account`'s `DiemAccount::DiemAccount` `authentication_key` field to `new_key`.
    /// `new_key` must be a valid ed25519 public key, and `account` must not have previously delegated
    /// its `DiemAccount::KeyRotationCapability`.
    ///
    /// # Parameters
    /// | Name            | Type         | Description                                                                                                  |
    /// | ------          | ------       | -------------                                                                                                |
    /// | `dr_account`    | `&signer`    | The signer reference of the sending account of the write set transaction. May only be the Diem Root signer. |
    /// | `account`       | `&signer`    | Signer reference of account specified in the `execute_as` field of the write set transaction.                |
    /// | `sliding_nonce` | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction for Diem Root.                    |
    /// | `new_key`       | `vector<u8>` | New ed25519 public key to be used for `account`.                                                             |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                               | Description                                                                                                |
    /// | ----------------           | --------------                                             | -------------                                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                             | A `SlidingNonce` resource is not published under `dr_account`.                                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                             | The `sliding_nonce` in `dr_account` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                             | The `sliding_nonce` in `dr_account` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`                    | The `sliding_nonce` in` dr_account` has been previously recorded.                                          |
    /// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.                       |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                                           |
    ///
    /// # Related Scripts
    /// * `Script::rotate_authentication_key`
    /// * `Script::rotate_authentication_key_with_nonce`
    /// * `Script::rotate_authentication_key_with_recovery_address`
    RotateAuthenticationKeyWithNonceAdmin { sliding_nonce: u64, new_key: Bytes },

    /// # Summary
    /// Rotates the authentication key of a specified account that is part of a recovery address to a
    /// new authentication key. Only used for accounts that are part of a recovery address (see
    /// `Script::add_recovery_rotation_capability` for account restrictions).
    ///
    /// # Technical Description
    /// Rotates the authentication key of the `to_recover` account to `new_key` using the
    /// `DiemAccount::KeyRotationCapability` stored in the `RecoveryAddress::RecoveryAddress` resource
    /// published under `recovery_address`. This transaction can be sent either by the `to_recover`
    /// account, or by the account where the `RecoveryAddress::RecoveryAddress` resource is published
    /// that contains `to_recover`'s `DiemAccount::KeyRotationCapability`.
    ///
    /// # Parameters
    /// | Name               | Type         | Description                                                                                                                    |
    /// | ------             | ------       | -------------                                                                                                                  |
    /// | `account`          | `&signer`    | Signer reference of the sending account of the transaction.                                                                    |
    /// | `recovery_address` | `address`    | Address where `RecoveryAddress::RecoveryAddress` that holds `to_recover`'s `DiemAccount::KeyRotationCapability` is published. |
    /// | `to_recover`       | `address`    | The address of the account whose authentication key will be updated.                                                           |
    /// | `new_key`          | `vector<u8>` | New ed25519 public key to be used for the account at the `to_recover` address.                                                 |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                  | Description                                                                                                                                          |
    /// | ----------------           | --------------                                | -------------                                                                                                                                        |
    /// | `Errors::NOT_PUBLISHED`    | `RecoveryAddress::ERECOVERY_ADDRESS`          | `recovery_address` does not have a `RecoveryAddress::RecoveryAddress` resource published under it.                                                   |
    /// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::ECANNOT_ROTATE_KEY`         | The address of `account` is not `recovery_address` or `to_recover`.                                                                                  |
    /// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::EACCOUNT_NOT_RECOVERABLE`   | `to_recover`'s `DiemAccount::KeyRotationCapability`  is not in the `RecoveryAddress::RecoveryAddress`  resource published under `recovery_address`. |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY` | `new_key` was an invalid length.                                                                                                                     |
    ///
    /// # Related Scripts
    /// * `Script::rotate_authentication_key`
    /// * `Script::rotate_authentication_key_with_nonce`
    /// * `Script::rotate_authentication_key_with_nonce_admin`
    RotateAuthenticationKeyWithRecoveryAddress {
        recovery_address: AccountAddress,
        to_recover: AccountAddress,
        new_key: Bytes,
    },

    /// # Summary
    /// Updates the url used for off-chain communication, and the public key used to verify dual
    /// attestation on-chain. Transaction can be sent by any account that has dual attestation
    /// information published under it. In practice the only such accounts are Designated Dealers and
    /// Parent VASPs.
    ///
    /// # Technical Description
    /// Updates the `base_url` and `compliance_public_key` fields of the `DualAttestation::Credential`
    /// resource published under `account`. The `new_key` must be a valid ed25519 public key.
    ///
    /// ## Events
    /// Successful execution of this transaction emits two events:
    /// * A `DualAttestation::ComplianceKeyRotationEvent` containing the new compliance public key, and
    /// the blockchain time at which the key was updated emitted on the `DualAttestation::Credential`
    /// `compliance_key_rotation_events` handle published under `account`; and
    /// * A `DualAttestation::BaseUrlRotationEvent` containing the new base url to be used for
    /// off-chain communication, and the blockchain time at which the url was updated emitted on the
    /// `DualAttestation::Credential` `base_url_rotation_events` handle published under `account`.
    ///
    /// # Parameters
    /// | Name      | Type         | Description                                                               |
    /// | ------    | ------       | -------------                                                             |
    /// | `account` | `&signer`    | Signer reference of the sending account of the transaction.               |
    /// | `new_url` | `vector<u8>` | ASCII-encoded url to be used for off-chain communication with `account`.  |
    /// | `new_key` | `vector<u8>` | New ed25519 public key to be used for on-chain dual attestation checking. |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                           | Description                                                                |
    /// | ----------------           | --------------                         | -------------                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `DualAttestation::ECREDENTIAL`         | A `DualAttestation::Credential` resource is not published under `account`. |
    /// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EINVALID_PUBLIC_KEY` | `new_key` is not a valid ed25519 public key.                               |
    ///
    /// # Related Scripts
    /// * `Script::create_parent_vasp_account`
    /// * `Script::create_designated_dealer`
    /// * `Script::rotate_dual_attestation_info`
    RotateDualAttestationInfo { new_url: Bytes, new_key: Bytes },

    /// # Summary
    /// Rotates the authentication key in a `SharedEd25519PublicKey`. This transaction can be sent by
    /// any account that has previously published a shared ed25519 public key using
    /// `Script::publish_shared_ed25519_public_key`.
    ///
    /// # Technical Description
    /// This first rotates the public key stored in `account`'s
    /// `SharedEd25519PublicKey::SharedEd25519PublicKey` resource to `public_key`, after which it
    /// rotates the authentication key using the capability stored in `account`'s
    /// `SharedEd25519PublicKey::SharedEd25519PublicKey` to a new value derived from `public_key`
    ///
    /// # Parameters
    /// | Name         | Type         | Description                                                     |
    /// | ------       | ------       | -------------                                                   |
    /// | `account`    | `&signer`    | The signer reference of the sending account of the transaction. |
    /// | `public_key` | `vector<u8>` | 32-byte Ed25519 public key.                                     |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                    | Description                                                                                   |
    /// | ----------------           | --------------                                  | -------------                                                                                 |
    /// | `Errors::NOT_PUBLISHED`    | `SharedEd25519PublicKey::ESHARED_KEY`           | A `SharedEd25519PublicKey::SharedEd25519PublicKey` resource is not published under `account`. |
    /// | `Errors::INVALID_ARGUMENT` | `SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY` | `public_key` is an invalid ed25519 public key.                                                |
    ///
    /// # Related Scripts
    /// * `Script::publish_shared_ed25519_public_key`
    RotateSharedEd25519PublicKey { public_key: Bytes },

    /// # Summary
    /// Updates a validator's configuration, and triggers a reconfiguration of the system to update the
    /// validator set with this new validator configuration.  Can only be successfully sent by a
    /// Validator Operator account that is already registered with a validator.
    ///
    /// # Technical Description
    /// This updates the fields with corresponding names held in the `ValidatorConfig::ValidatorConfig`
    /// config resource held under `validator_account`. It then emits a `DiemConfig::NewEpochEvent` to
    /// trigger a reconfiguration of the system.  This reconfiguration will update the validator set
    /// on-chain with the updated `ValidatorConfig::ValidatorConfig`.
    ///
    /// # Parameters
    /// | Name                          | Type         | Description                                                                                                                  |
    /// | ------                        | ------       | -------------                                                                                                                |
    /// | `validator_operator_account`  | `&signer`    | Signer reference of the sending account. Must be the registered validator operator for the validator at `validator_address`. |
    /// | `validator_account`           | `address`    | The address of the validator's `ValidatorConfig::ValidatorConfig` resource being updated.                                    |
    /// | `consensus_pubkey`            | `vector<u8>` | New Ed25519 public key to be used in the updated `ValidatorConfig::ValidatorConfig`.                                         |
    /// | `validator_network_addresses` | `vector<u8>` | New set of `validator_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.                       |
    /// | `fullnode_network_addresses`  | `vector<u8>` | New set of `fullnode_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.                        |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                   | Description                                                                                           |
    /// | ----------------           | --------------                                 | -------------                                                                                         |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`           | `validator_address` does not have a `ValidatorConfig::ValidatorConfig` resource published under it.   |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR_OPERATOR`                   | `validator_operator_account` does not have a Validator Operator role.                                 |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_TRANSACTION_SENDER` | `validator_operator_account` is not the registered operator for the validator at `validator_address`. |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_CONSENSUS_KEY`      | `consensus_pubkey` is not a valid ed25519 public key.                                                 |
    /// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`             | An invalid time value was encountered in reconfiguration. Unlikely to occur.                          |
    ///
    /// # Related Scripts
    /// * `Script::create_validator_account`
    /// * `Script::create_validator_operator_account`
    /// * `Script::add_validator_and_reconfigure`
    /// * `Script::remove_validator_and_reconfigure`
    /// * `Script::set_validator_operator`
    /// * `Script::set_validator_operator_with_nonce_admin`
    /// * `Script::register_validator_config`
    SetValidatorConfigAndReconfigure {
        validator_account: AccountAddress,
        consensus_pubkey: Bytes,
        validator_network_addresses: Bytes,
        fullnode_network_addresses: Bytes,
    },

    /// # Summary
    /// Sets the validator operator for a validator in the validator's configuration resource "locally"
    /// and does not reconfigure the system. Changes from this transaction will not picked up by the
    /// system until a reconfiguration of the system is triggered. May only be sent by an account with
    /// Validator role.
    ///
    /// # Technical Description
    /// Sets the account at `operator_account` address and with the specified `human_name` as an
    /// operator for the sending validator account. The account at `operator_account` address must have
    /// a Validator Operator role and have a `ValidatorOperatorConfig::ValidatorOperatorConfig`
    /// resource published under it. The sending `account` must be a Validator and have a
    /// `ValidatorConfig::ValidatorConfig` resource published under it. This script does not emit a
    /// `DiemConfig::NewEpochEvent` and no reconfiguration of the system is initiated by this script.
    ///
    /// # Parameters
    /// | Name               | Type         | Description                                                                                  |
    /// | ------             | ------       | -------------                                                                                |
    /// | `account`          | `&signer`    | The signer reference of the sending account of the transaction.                              |
    /// | `operator_name`    | `vector<u8>` | Validator operator's human name.                                                             |
    /// | `operator_account` | `address`    | Address of the validator operator account to be added as the `account` validator's operator. |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                          | Description                                                                                                                                                  |
    /// | ----------------           | --------------                                        | -------------                                                                                                                                                |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG` | The `ValidatorOperatorConfig::ValidatorOperatorConfig` resource is not published under `operator_account`.                                                   |
    /// | 0                          | 0                                                     | The `human_name` field of the `ValidatorOperatorConfig::ValidatorOperatorConfig` resource under `operator_account` does not match the provided `human_name`. |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR`                                   | `account` does not have a Validator account role.                                                                                                            |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR`          | The account at `operator_account` does not have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource.                                               |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`                  | A `ValidatorConfig::ValidatorConfig` is not published under `account`.                                                                                       |
    ///
    /// # Related Scripts
    /// * `Script::create_validator_account`
    /// * `Script::create_validator_operator_account`
    /// * `Script::register_validator_config`
    /// * `Script::remove_validator_and_reconfigure`
    /// * `Script::add_validator_and_reconfigure`
    /// * `Script::set_validator_operator_with_nonce_admin`
    /// * `Script::set_validator_config_and_reconfigure`
    SetValidatorOperator {
        operator_name: Bytes,
        operator_account: AccountAddress,
    },

    /// # Summary
    /// Sets the validator operator for a validator in the validator's configuration resource "locally"
    /// and does not reconfigure the system. Changes from this transaction will not picked up by the
    /// system until a reconfiguration of the system is triggered. May only be sent by the Diem Root
    /// account as a write set transaction.
    ///
    /// # Technical Description
    /// Sets the account at `operator_account` address and with the specified `human_name` as an
    /// operator for the validator `account`. The account at `operator_account` address must have a
    /// Validator Operator role and have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource
    /// published under it. The account represented by the `account` signer must be a Validator and
    /// have a `ValidatorConfig::ValidatorConfig` resource published under it. No reconfiguration of
    /// the system is initiated by this script.
    ///
    /// # Parameters
    /// | Name               | Type         | Description                                                                                                  |
    /// | ------             | ------       | -------------                                                                                                |
    /// | `dr_account`       | `&signer`    | The signer reference of the sending account of the write set transaction. May only be the Diem Root signer. |
    /// | `account`          | `&signer`    | Signer reference of account specified in the `execute_as` field of the write set transaction.                |
    /// | `sliding_nonce`    | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction for Diem Root.                    |
    /// | `operator_name`    | `vector<u8>` | Validator operator's human name.                                                                             |
    /// | `operator_account` | `address`    | Address of the validator operator account to be added as the `account` validator's operator.                 |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                          | Description                                                                                                                                                  |
    /// | ----------------           | --------------                                        | -------------                                                                                                                                                |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                        | A `SlidingNonce` resource is not published under `dr_account`.                                                                                               |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                        | The `sliding_nonce` in `dr_account` is too old and it's impossible to determine if it's duplicated or not.                                                   |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                        | The `sliding_nonce` in `dr_account` is too far in the future.                                                                                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`               | The `sliding_nonce` in` dr_account` has been previously recorded.                                                                                            |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                        | The sending account is not the Diem Root account or Treasury Compliance account                                                                             |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG` | The `ValidatorOperatorConfig::ValidatorOperatorConfig` resource is not published under `operator_account`.                                                   |
    /// | 0                          | 0                                                     | The `human_name` field of the `ValidatorOperatorConfig::ValidatorOperatorConfig` resource under `operator_account` does not match the provided `human_name`. |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR`                                   | `account` does not have a Validator account role.                                                                                                            |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR`          | The account at `operator_account` does not have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource.                                               |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`                  | A `ValidatorConfig::ValidatorConfig` is not published under `account`.                                                                                       |
    ///
    /// # Related Scripts
    /// * `Script::create_validator_account`
    /// * `Script::create_validator_operator_account`
    /// * `Script::register_validator_config`
    /// * `Script::remove_validator_and_reconfigure`
    /// * `Script::add_validator_and_reconfigure`
    /// * `Script::set_validator_operator`
    /// * `Script::set_validator_config_and_reconfigure`
    SetValidatorOperatorWithNonceAdmin {
        sliding_nonce: u64,
        operator_name: Bytes,
        operator_account: AccountAddress,
    },

    /// # Summary
    /// Mints a specified number of coins in a currency to a Designated Dealer. The sending account
    /// must be the Treasury Compliance account, and coins can only be minted to a Designated Dealer
    /// account.
    ///
    /// # Technical Description
    /// Mints `mint_amount` of coins in the `CoinType` currency to Designated Dealer account at
    /// `designated_dealer_address`. The `tier_index` parameter specifies which tier should be used to
    /// check verify the off-chain approval policy, and is based in part on the on-chain tier values
    /// for the specific Designated Dealer, and the number of `CoinType` coins that have been minted to
    /// the dealer over the past 24 hours. Every Designated Dealer has 4 tiers for each currency that
    /// they support. The sending `tc_account` must be the Treasury Compliance account, and the
    /// receiver an authorized Designated Dealer account.
    ///
    /// ## Events
    /// Successful execution of the transaction will emit two events:
    /// * A `Diem::MintEvent` with the amount and currency code minted is emitted on the
    /// `mint_event_handle` in the stored `Diem::CurrencyInfo<CoinType>` resource stored under
    /// `0xA550C18`; and
    /// * A `DesignatedDealer::ReceivedMintEvent` with the amount, currency code, and Designated
    /// Dealer's address is emitted on the `mint_event_handle` in the stored `DesignatedDealer::Dealer`
    /// resource published under the `designated_dealer_address`.
    ///
    /// # Parameters
    /// | Name                        | Type      | Description                                                                                                |
    /// | ------                      | ------    | -------------                                                                                              |
    /// | `CoinType`                  | Type      | The Move type for the `CoinType` being minted. `CoinType` must be an already-registered currency on-chain. |
    /// | `tc_account`                | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.  |
    /// | `sliding_nonce`             | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                 |
    /// | `designated_dealer_address` | `address` | The address of the Designated Dealer account being minted to.                                              |
    /// | `mint_amount`               | `u64`     | The number of coins to be minted.                                                                          |
    /// | `tier_index`                | `u64`     | The mint tier index to use for the Designated Dealer account.                                              |
    ///
    /// # Common Abort Conditions
    /// | Error Category                | Error Reason                                 | Description                                                                                                                  |
    /// | ----------------              | --------------                               | -------------                                                                                                                |
    /// | `Errors::NOT_PUBLISHED`       | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `tc_account`.                                                               |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                   |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                                                                |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                                                            |
    /// | `Errors::REQUIRES_ADDRESS`    | `CoreAddresses::ETREASURY_COMPLIANCE`        | `tc_account` is not the Treasury Compliance account.                                                                         |
    /// | `Errors::REQUIRES_ROLE`       | `Roles::ETREASURY_COMPLIANCE`                | `tc_account` is not the Treasury Compliance account.                                                                         |
    /// | `Errors::INVALID_ARGUMENT`    | `DesignatedDealer::EINVALID_MINT_AMOUNT`     | `mint_amount` is zero.                                                                                                       |
    /// | `Errors::NOT_PUBLISHED`       | `DesignatedDealer::EDEALER`                  | `DesignatedDealer::Dealer` or `DesignatedDealer::TierInfo<CoinType>` resource does not exist at `designated_dealer_address`. |
    /// | `Errors::INVALID_ARGUMENT`    | `DesignatedDealer::EINVALID_TIER_INDEX`      | The `tier_index` is out of bounds.                                                                                           |
    /// | `Errors::INVALID_ARGUMENT`    | `DesignatedDealer::EINVALID_AMOUNT_FOR_TIER` | `mint_amount` exceeds the maximum allowed amount for `tier_index`.                                                           |
    /// | `Errors::REQUIRES_CAPABILITY` | `Diem::EMINT_CAPABILITY`                    | `tc_account` does not have a `Diem::MintCapability<CoinType>` resource published under it.                                  |
    /// | `Errors::INVALID_STATE`       | `Diem::EMINTING_NOT_ALLOWED`                | Minting is not currently allowed for `CoinType` coins.                                                                       |
    /// | `Errors::LIMIT_EXCEEDED`      | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`      | The depositing of the funds would exceed the `account`'s account limits.                                                     |
    ///
    /// # Related Scripts
    /// * `Script::create_designated_dealer`
    /// * `Script::peer_to_peer_with_metadata`
    /// * `Script::rotate_dual_attestation_info`
    TieredMint {
        coin_type: TypeTag,
        sliding_nonce: u64,
        designated_dealer_address: AccountAddress,
        mint_amount: u64,
        tier_index: u64,
    },

    /// # Summary
    /// Unfreezes the account at `address`. The sending account of this transaction must be the
    /// Treasury Compliance account. After the successful execution of this transaction transactions
    /// may be sent from the previously frozen account, and coins may be sent and received.
    ///
    /// # Technical Description
    /// Sets the `AccountFreezing::FreezingBit` to `false` and emits a
    /// `AccountFreezing::UnFreezeAccountEvent`. The transaction sender must be the Treasury Compliance
    /// account. Note that this is a per-account property so unfreezing a Parent VASP will not effect
    /// the status any of its child accounts and vice versa.
    ///
    /// ## Events
    /// Successful execution of this script will emit a `AccountFreezing::UnFreezeAccountEvent` with
    /// the `unfrozen_address` set the `to_unfreeze_account`'s address.
    ///
    /// # Parameters
    /// | Name                  | Type      | Description                                                                                               |
    /// | ------                | ------    | -------------                                                                                             |
    /// | `tc_account`          | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account. |
    /// | `sliding_nonce`       | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                |
    /// | `to_unfreeze_account` | `address` | The account address to be frozen.                                                                         |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                            | Description                                                                                |
    /// | ----------------           | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
    ///
    /// # Related Scripts
    /// * `Script::freeze_account`
    UnfreezeAccount {
        sliding_nonce: u64,
        to_unfreeze_account: AccountAddress,
    },

    /// # Summary
    /// Updates the Diem major version that is stored on-chain and is used by the VM.  This
    /// transaction can only be sent from the Diem Root account.
    ///
    /// # Technical Description
    /// Updates the `DiemVersion` on-chain config and emits a `DiemConfig::NewEpochEvent` to trigger
    /// a reconfiguration of the system. The `major` version that is passed in must be strictly greater
    /// than the current major version held on-chain. The VM reads this information and can use it to
    /// preserve backwards compatibility with previous major versions of the VM.
    ///
    /// # Parameters
    /// | Name            | Type      | Description                                                                |
    /// | ------          | ------    | -------------                                                              |
    /// | `account`       | `&signer` | Signer reference of the sending account. Must be the Diem Root account.   |
    /// | `sliding_nonce` | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
    /// | `major`         | `u64`     | The `major` version of the VM to be used from this transaction on.         |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                  | Description                                                                                |
    /// | ----------------           | --------------                                | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                  | `account` is not the Diem Root account.                                                   |
    /// | `Errors::INVALID_ARGUMENT` | `DiemVersion::EINVALID_MAJOR_VERSION_NUMBER` | `major` is less-than or equal to the current major version stored on-chain.                |
    UpdateDiemVersion { sliding_nonce: u64, major: u64 },

    /// # Summary
    /// Update the dual attestation limit on-chain. Defined in terms of micro-XDX.  The transaction can
    /// only be sent by the Treasury Compliance account.  After this transaction all inter-VASP
    /// payments over this limit must be checked for dual attestation.
    ///
    /// # Technical Description
    /// Updates the `micro_xdx_limit` field of the `DualAttestation::Limit` resource published under
    /// `0xA550C18`. The amount is set in micro-XDX.
    ///
    /// # Parameters
    /// | Name                  | Type      | Description                                                                                               |
    /// | ------                | ------    | -------------                                                                                             |
    /// | `tc_account`          | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account. |
    /// | `sliding_nonce`       | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                |
    /// | `new_micro_xdx_limit` | `u64`     | The new dual attestation limit to be used on-chain.                                                       |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                            | Description                                                                                |
    /// | ----------------           | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | `tc_account` is not the Treasury Compliance account.                                       |
    ///
    /// # Related Scripts
    /// * `Script::update_exchange_rate`
    /// * `Script::update_minting_ability`
    UpdateDualAttestationLimit {
        sliding_nonce: u64,
        new_micro_xdx_limit: u64,
    },

    /// # Summary
    /// Update the rough on-chain exchange rate between a specified currency and XDX (as a conversion
    /// to micro-XDX). The transaction can only be sent by the Treasury Compliance account. After this
    /// transaction the updated exchange rate will be used for normalization of gas prices, and for
    /// dual attestation checking.
    ///
    /// # Technical Description
    /// Updates the on-chain exchange rate from the given `Currency` to micro-XDX.  The exchange rate
    /// is given by `new_exchange_rate_numerator/new_exchange_rate_denominator`.
    ///
    /// # Parameters
    /// | Name                            | Type      | Description                                                                                                                        |
    /// | ------                          | ------    | -------------                                                                                                                      |
    /// | `Currency`                      | Type      | The Move type for the `Currency` whose exchange rate is being updated. `Currency` must be an already-registered currency on-chain. |
    /// | `tc_account`                    | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.                          |
    /// | `sliding_nonce`                 | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for the transaction.                                                          |
    /// | `new_exchange_rate_numerator`   | `u64`     | The numerator for the new to micro-XDX exchange rate for `Currency`.                                                               |
    /// | `new_exchange_rate_denominator` | `u64`     | The denominator for the new to micro-XDX exchange rate for `Currency`.                                                             |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                            | Description                                                                                |
    /// | ----------------           | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | `tc_account` is not the Treasury Compliance account.                                       |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`           | `tc_account` is not the Treasury Compliance account.                                       |
    /// | `Errors::INVALID_ARGUMENT` | `FixedPoint32::EDENOMINATOR`            | `new_exchange_rate_denominator` is zero.                                                   |
    /// | `Errors::INVALID_ARGUMENT` | `FixedPoint32::ERATIO_OUT_OF_RANGE`     | The quotient is unrepresentable as a `FixedPoint32`.                                       |
    /// | `Errors::LIMIT_EXCEEDED`   | `FixedPoint32::ERATIO_OUT_OF_RANGE`     | The quotient is unrepresentable as a `FixedPoint32`.                                       |
    ///
    /// # Related Scripts
    /// * `Script::update_dual_attestation_limit`
    /// * `Script::update_minting_ability`
    UpdateExchangeRate {
        currency: TypeTag,
        sliding_nonce: u64,
        new_exchange_rate_numerator: u64,
        new_exchange_rate_denominator: u64,
    },

    /// # Summary
    /// Script to allow or disallow minting of new coins in a specified currency.  This transaction can
    /// only be sent by the Treasury Compliance account.  Turning minting off for a currency will have
    /// no effect on coins already in circulation, and coins may still be removed from the system.
    ///
    /// # Technical Description
    /// This transaction sets the `can_mint` field of the `Diem::CurrencyInfo<Currency>` resource
    /// published under `0xA550C18` to the value of `allow_minting`. Minting of coins if allowed if
    /// this field is set to `true` and minting of new coins in `Currency` is disallowed otherwise.
    /// This transaction needs to be sent by the Treasury Compliance account.
    ///
    /// # Parameters
    /// | Name            | Type      | Description                                                                                                                          |
    /// | ------          | ------    | -------------                                                                                                                        |
    /// | `Currency`      | Type      | The Move type for the `Currency` whose minting ability is being updated. `Currency` must be an already-registered currency on-chain. |
    /// | `account`       | `&signer` | Signer reference of the sending account. Must be the Diem Root account.                                                             |
    /// | `allow_minting` | `bool`    | Whether to allow minting of new coins in `Currency`.                                                                                 |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                          | Description                                          |
    /// | ----------------           | --------------                        | -------------                                        |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE` | `tc_account` is not the Treasury Compliance account. |
    /// | `Errors::NOT_PUBLISHED`    | `Diem::ECURRENCY_INFO`               | `Currency` is not a registered currency on-chain.    |
    ///
    /// # Related Scripts
    /// * `Script::update_dual_attestation_limit`
    /// * `Script::update_exchange_rate`
    UpdateMintingAbility {
        currency: TypeTag,
        allow_minting: bool,
    },
}

/// Structured representation of a call into a known Move script function.
/// ```ignore
/// impl ScriptFunctionCall {
///     pub fn encode(self) -> TransactionPayload { .. }
///     pub fn decode(&TransactionPayload) -> Option<ScriptFunctionCall> { .. }
/// }
/// ```
#[derive(Clone, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "fuzzing", derive(proptest_derive::Arbitrary))]
#[cfg_attr(feature = "fuzzing", proptest(no_params))]
pub enum ScriptFunctionCall {
    /// # Summary
    /// Adds a zero `Currency` balance to the sending `account`. This will enable `account` to
    /// send, receive, and hold `Diem::Diem<Currency>` coins. This transaction can be
    /// successfully sent by any account that is allowed to hold balances
    /// (e.g., VASP, Designated Dealer).
    ///
    /// # Technical Description
    /// After the successful execution of this transaction the sending account will have a
    /// `DiemAccount::Balance<Currency>` resource with zero balance published under it. Only
    /// accounts that can hold balances can send this transaction, the sending account cannot
    /// already have a `DiemAccount::Balance<Currency>` published under it.
    ///
    /// # Parameters
    /// | Name       | Type     | Description                                                                                                                                         |
    /// | ------     | ------   | -------------                                                                                                                                       |
    /// | `Currency` | Type     | The Move type for the `Currency` being added to the sending account of the transaction. `Currency` must be an already-registered currency on-chain. |
    /// | `account`  | `signer` | The signer of the sending account of the transaction.                                                                                               |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                             | Description                                                                |
    /// | ----------------            | --------------                           | -------------                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                  | The `Currency` is not a registered currency on-chain.                      |
    /// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::EROLE_CANT_STORE_BALANCE` | The sending `account`'s role does not permit balances.                     |
    /// | `Errors::ALREADY_PUBLISHED` | `DiemAccount::EADD_EXISTING_CURRENCY`   | A balance for `Currency` is already published under the sending `account`. |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_child_vasp_account`
    /// * `AccountCreationScripts::create_parent_vasp_account`
    /// * `PaymentScripts::peer_to_peer_with_metadata`
    AddCurrencyToAccount {
        currency: TypeTag,
    },

    /// # Summary
    /// Add a DiemID domain to parent VASP account. The transaction can only be sent by
    /// the Treasury Compliance account.
    ///
    /// # Technical Description
    /// Adds a `DiemId::DiemIdDomain` to the `domains` field of the `DiemId::DiemIdDomains` resource published under
    /// the account at `address`.
    ///
    /// # Parameters
    /// | Name         | Type         | Description                                                                                     |
    /// | ------       | ------       | -------------                                                                                   |
    /// | `tc_account` | `signer`     | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
    /// | `address`    | `address`    | The `address` of the parent VASP account that will have have `domain` added to its domains.     |
    /// | `domain`     | `vector<u8>` | The domain to be added.                                                                         |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                             | Description                                                                                                                            |
    /// | ----------------           | --------------                           | -------------                                                                                                                          |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`            | The sending account is not the Treasury Compliance account.                                                                            |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`    | `tc_account` is not the Treasury Compliance account.                                                                                   |
    /// | `Errors::NOT_PUBLISHED`    | `DiemId::EDIEM_ID_DOMAIN_MANAGER`        | The `DiemId::DiemIdDomainManager` resource is not yet published under the Treasury Compliance account.                                 |
    /// | `Errors::NOT_PUBLISHED`    | `DiemId::EDIEM_ID_DOMAINS_NOT_PUBLISHED` | `address` does not have a `DiemId::DiemIdDomains` resource published under it.                                                         |
    /// | `Errors::INVALID_ARGUMENT` | `DiemId::EDOMAIN_ALREADY_EXISTS`         | The `domain` already exists in the list of `DiemId::DiemIdDomain`s  in the `DiemId::DiemIdDomains` resource published under `address`. |
    /// | `Errors::INVALID_ARGUMENT` | `DiemId::EINVALID_DIEM_ID_DOMAIN`        | The `domain` is greater in length than `DiemId::DOMAIN_LENGTH`.                                                                        |
    AddDiemIdDomain {
        address: AccountAddress,
        domain: Bytes,
    },

    /// # Summary
    /// Stores the sending accounts ability to rotate its authentication key with a designated recovery
    /// account. Both the sending and recovery accounts need to belong to the same VASP and
    /// both be VASP accounts. After this transaction both the sending account and the
    /// specified recovery account can rotate the sender account's authentication key.
    ///
    /// # Technical Description
    /// Adds the `DiemAccount::KeyRotationCapability` for the sending account
    /// (`to_recover_account`) to the `RecoveryAddress::RecoveryAddress` resource under
    /// `recovery_address`. After this transaction has been executed successfully the account at
    /// `recovery_address` and the `to_recover_account` may rotate the authentication key of
    /// `to_recover_account` (the sender of this transaction).
    ///
    /// The sending account of this transaction (`to_recover_account`) must not have previously given away its unique key
    /// rotation capability, and must be a VASP account. The account at `recovery_address`
    /// must also be a VASP account belonging to the same VASP as the `to_recover_account`.
    /// Additionally the account at `recovery_address` must have already initialized itself as
    /// a recovery account address using the `AccountAdministrationScripts::create_recovery_address` transaction script.
    ///
    /// The sending account's (`to_recover_account`) key rotation capability is
    /// removed in this transaction and stored in the `RecoveryAddress::RecoveryAddress`
    /// resource stored under the account at `recovery_address`.
    ///
    /// # Parameters
    /// | Name                 | Type      | Description                                                                                               |
    /// | ------               | ------    | -------------                                                                                             |
    /// | `to_recover_account` | `signer`  | The signer of the sending account of this transaction.                                                    |
    /// | `recovery_address`   | `address` | The account address where the `to_recover_account`'s `DiemAccount::KeyRotationCapability` will be stored. |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                              | Description                                                                                       |
    /// | ----------------           | --------------                                            | -------------                                                                                     |
    /// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `to_recover_account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.    |
    /// | `Errors::NOT_PUBLISHED`    | `RecoveryAddress::ERECOVERY_ADDRESS`                      | `recovery_address` does not have a `RecoveryAddress` resource published under it.                 |
    /// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::EINVALID_KEY_ROTATION_DELEGATION`       | `to_recover_account` and `recovery_address` do not belong to the same VASP.                       |
    /// | `Errors::LIMIT_EXCEEDED`   | ` RecoveryAddress::EMAX_KEYS_REGISTERED`                  | `RecoveryAddress::MAX_REGISTERED_KEYS` have already been registered with this `recovery_address`. |
    ///
    /// # Related Scripts
    /// * `AccountAdministrationScripts::create_recovery_address`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_recovery_address`
    AddRecoveryRotationCapability {
        recovery_address: AccountAddress,
    },

    /// # Summary
    /// Adds a validator account to the validator set, and triggers a
    /// reconfiguration of the system to admit the account to the validator set for the system. This
    /// transaction can only be successfully called by the Diem Root account.
    ///
    /// # Technical Description
    /// This script adds the account at `validator_address` to the validator set.
    /// This transaction emits a `DiemConfig::NewEpochEvent` event and triggers a
    /// reconfiguration. Once the reconfiguration triggered by this script's
    /// execution has been performed, the account at the `validator_address` is
    /// considered to be a validator in the network.
    ///
    /// This transaction script will fail if the `validator_address` address is already in the validator set
    /// or does not have a `ValidatorConfig::ValidatorConfig` resource already published under it.
    ///
    /// # Parameters
    /// | Name                | Type         | Description                                                                                                                        |
    /// | ------              | ------       | -------------                                                                                                                      |
    /// | `dr_account`        | `signer`     | The signer of the sending account of this transaction. Must be the Diem Root signer.                                               |
    /// | `sliding_nonce`     | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                         |
    /// | `validator_name`    | `vector<u8>` | ASCII-encoded human name for the validator. Must match the human name in the `ValidatorConfig::ValidatorConfig` for the validator. |
    /// | `validator_address` | `address`    | The validator account address to be added to the validator set.                                                                    |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                 | Description                                                                                                                               |
    /// | ----------------           | --------------                               | -------------                                                                                                                             |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `dr_account`.                                                                            |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                                                                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                                                                         |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                  | The sending account is not the Diem Root account.                                                                                         |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EDIEM_ROOT`                          | The sending account is not the Diem Root account.                                                                                         |
    /// | 0                          | 0                                            | The provided `validator_name` does not match the already-recorded human name for the validator.                                           |
    /// | `Errors::INVALID_ARGUMENT` | `DiemSystem::EINVALID_PROSPECTIVE_VALIDATOR` | The validator to be added does not have a `ValidatorConfig::ValidatorConfig` resource published under it, or its `config` field is empty. |
    /// | `Errors::INVALID_ARGUMENT` | `DiemSystem::EALREADY_A_VALIDATOR`           | The `validator_address` account is already a registered validator.                                                                        |
    /// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`            | An invalid time value was encountered in reconfiguration. Unlikely to occur.                                                              |
    /// | `Errors::LIMIT_EXCEEDED`   | `DiemSystem::EMAX_VALIDATORS`                | The validator set is already at its maximum size. The validator could not be added.                                                       |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_validator_account`
    /// * `AccountCreationScripts::create_validator_operator_account`
    /// * `ValidatorAdministrationScripts::register_validator_config`
    /// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::set_validator_operator`
    /// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
    /// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
    AddValidatorAndReconfigure {
        sliding_nonce: u64,
        validator_name: Bytes,
        validator_address: AccountAddress,
    },

    AutopayCreateInstruction {
        uid: u64,
        in_type: u8,
        payee: AccountAddress,
        end_epoch: u64,
        value: u64,
    },

    AutopayDisable {},

    AutopayEnable {},

    /// # Summary
    /// Burns the transaction fees collected in the `CoinType` currency so that the
    /// Diem association may reclaim the backing coins off-chain. May only be sent
    /// by the Treasury Compliance account.
    ///
    /// # Technical Description
    /// Burns the transaction fees collected in `CoinType` so that the
    /// association may reclaim the backing coins. Once this transaction has executed
    /// successfully all transaction fees that will have been collected in
    /// `CoinType` since the last time this script was called with that specific
    /// currency. Both `balance` and `preburn` fields in the
    /// `TransactionFee::TransactionFee<CoinType>` resource published under the `0xB1E55ED`
    /// account address will have a value of 0 after the successful execution of this script.
    ///
    /// # Events
    /// The successful execution of this transaction will emit a `Diem::BurnEvent` on the event handle
    /// held in the `Diem::CurrencyInfo<CoinType>` resource's `burn_events` published under
    /// `0xA550C18`.
    ///
    /// # Parameters
    /// | Name         | Type     | Description                                                                                                                                         |
    /// | ------       | ------   | -------------                                                                                                                                       |
    /// | `CoinType`   | Type     | The Move type for the `CoinType` being added to the sending account of the transaction. `CoinType` must be an already-registered currency on-chain. |
    /// | `tc_account` | `signer` | The signer of the sending account of this transaction. Must be the Treasury Compliance account.                                                     |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                          | Description                                                 |
    /// | ----------------           | --------------                        | -------------                                               |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE` | The sending account is not the Treasury Compliance account. |
    /// | `Errors::NOT_PUBLISHED`    | `TransactionFee::ETRANSACTION_FEE`    | `CoinType` is not an accepted transaction fee currency.     |
    /// | `Errors::INVALID_ARGUMENT` | `Diem::ECOIN`                        | The collected fees in `CoinType` are zero.                  |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::burn_with_amount`
    /// * `TreasuryComplianceScripts::cancel_burn_with_amount`
    BurnTxnFees {
        coin_type: TypeTag,
    },

    /// # Summary
    /// Burns the coins held in a preburn resource in the preburn queue at the
    /// specified preburn address, which are equal to the `amount` specified in the
    /// transaction. Finds the first relevant outstanding preburn request with
    /// matching amount and removes the contained coins from the system. The sending
    /// account must be the Treasury Compliance account.
    /// The account that holds the preburn queue resource will normally be a Designated
    /// Dealer, but there are no enforced requirements that it be one.
    ///
    /// # Technical Description
    /// This transaction permanently destroys all the coins of `Token` type
    /// stored in the `Diem::Preburn<Token>` resource published under the
    /// `preburn_address` account address.
    ///
    /// This transaction will only succeed if the sending `account` has a
    /// `Diem::BurnCapability<Token>`, and a `Diem::Preburn<Token>` resource
    /// exists under `preburn_address`, with a non-zero `to_burn` field. After the successful execution
    /// of this transaction the `total_value` field in the
    /// `Diem::CurrencyInfo<Token>` resource published under `0xA550C18` will be
    /// decremented by the value of the `to_burn` field of the preburn resource
    /// under `preburn_address` immediately before this transaction, and the
    /// `to_burn` field of the preburn resource will have a zero value.
    ///
    /// # Events
    /// The successful execution of this transaction will emit a `Diem::BurnEvent` on the event handle
    /// held in the `Diem::CurrencyInfo<Token>` resource's `burn_events` published under
    /// `0xA550C18`.
    ///
    /// # Parameters
    /// | Name              | Type      | Description                                                                                                        |
    /// | ------            | ------    | -------------                                                                                                      |
    /// | `Token`           | Type      | The Move type for the `Token` currency being burned. `Token` must be an already-registered currency on-chain.      |
    /// | `tc_account`      | `signer`  | The signer of the sending account of this transaction, must have a burn capability for `Token` published under it. |
    /// | `sliding_nonce`   | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                         |
    /// | `preburn_address` | `address` | The address where the coins to-be-burned are currently held.                                                       |
    /// | `amount`          | `u64`     | The amount to be burned.                                                                                           |
    ///
    /// # Common Abort Conditions
    /// | Error Category                | Error Reason                            | Description                                                                                                                         |
    /// | ----------------              | --------------                          | -------------                                                                                                                       |
    /// | `Errors::NOT_PUBLISHED`       | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `account`.                                                                         |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                          |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                                                                       |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                                                                   |
    /// | `Errors::REQUIRES_CAPABILITY` | `Diem::EBURN_CAPABILITY`                | The sending `account` does not have a `Diem::BurnCapability<Token>` published under it.                                             |
    /// | `Errors::INVALID_STATE`       | `Diem::EPREBURN_NOT_FOUND`              | The `Diem::PreburnQueue<Token>` resource under `preburn_address` does not contain a preburn request with a value matching `amount`. |
    /// | `Errors::NOT_PUBLISHED`       | `Diem::EPREBURN_QUEUE`                  | The account at `preburn_address` does not have a `Diem::PreburnQueue<Token>` resource published under it.                           |
    /// | `Errors::NOT_PUBLISHED`       | `Diem::ECURRENCY_INFO`                  | The specified `Token` is not a registered currency on-chain.                                                                        |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::burn_txn_fees`
    /// * `TreasuryComplianceScripts::cancel_burn_with_amount`
    /// * `TreasuryComplianceScripts::preburn`
    BurnWithAmount {
        token: TypeTag,
        sliding_nonce: u64,
        preburn_address: AccountAddress,
        amount: u64,
    },

    /// # Summary
    /// Cancels and returns the coins held in the preburn area under
    /// `preburn_address`, which are equal to the `amount` specified in the transaction. Finds the first preburn
    /// resource with the matching amount and returns the funds to the `preburn_address`'s balance.
    /// Can only be successfully sent by an account with Treasury Compliance role.
    ///
    /// # Technical Description
    /// Cancels and returns all coins held in the `Diem::Preburn<Token>` resource under the `preburn_address` and
    /// return the funds to the `preburn_address` account's `DiemAccount::Balance<Token>`.
    /// The transaction must be sent by an `account` with a `Diem::BurnCapability<Token>`
    /// resource published under it. The account at `preburn_address` must have a
    /// `Diem::Preburn<Token>` resource published under it, and its value must be nonzero. The transaction removes
    /// the entire balance held in the `Diem::Preburn<Token>` resource, and returns it back to the account's
    /// `DiemAccount::Balance<Token>` under `preburn_address`. Due to this, the account at
    /// `preburn_address` must already have a balance in the `Token` currency published
    /// before this script is called otherwise the transaction will fail.
    ///
    /// # Events
    /// The successful execution of this transaction will emit:
    /// * A `Diem::CancelBurnEvent` on the event handle held in the `Diem::CurrencyInfo<Token>`
    /// resource's `burn_events` published under `0xA550C18`.
    /// * A `DiemAccount::ReceivedPaymentEvent` on the `preburn_address`'s
    /// `DiemAccount::DiemAccount` `received_events` event handle with both the `payer` and `payee`
    /// being `preburn_address`.
    ///
    /// # Parameters
    /// | Name              | Type      | Description                                                                                                                          |
    /// | ------            | ------    | -------------                                                                                                                        |
    /// | `Token`           | Type      | The Move type for the `Token` currenty that burning is being cancelled for. `Token` must be an already-registered currency on-chain. |
    /// | `account`         | `signer`  | The signer of the sending account of this transaction, must have a burn capability for `Token` published under it.                   |
    /// | `preburn_address` | `address` | The address where the coins to-be-burned are currently held.                                                                         |
    /// | `amount`          | `u64`     | The amount to be cancelled.                                                                                                          |
    ///
    /// # Common Abort Conditions
    /// | Error Category                | Error Reason                                     | Description                                                                                                                         |
    /// | ----------------              | --------------                                   | -------------                                                                                                                       |
    /// | `Errors::REQUIRES_CAPABILITY` | `Diem::EBURN_CAPABILITY`                         | The sending `account` does not have a `Diem::BurnCapability<Token>` published under it.                                             |
    /// | `Errors::INVALID_STATE`       | `Diem::EPREBURN_NOT_FOUND`                       | The `Diem::PreburnQueue<Token>` resource under `preburn_address` does not contain a preburn request with a value matching `amount`. |
    /// | `Errors::NOT_PUBLISHED`       | `Diem::EPREBURN_QUEUE`                           | The account at `preburn_address` does not have a `Diem::PreburnQueue<Token>` resource published under it.                           |
    /// | `Errors::NOT_PUBLISHED`       | `Diem::ECURRENCY_INFO`                           | The specified `Token` is not a registered currency on-chain.                                                                        |
    /// | `Errors::INVALID_ARGUMENT`    | `DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE`  | The account at `preburn_address` doesn't have a balance resource for `Token`.                                                       |
    /// | `Errors::LIMIT_EXCEEDED`      | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`           | The depositing of the funds held in the prebun area would exceed the `account`'s account limits.                                    |
    /// | `Errors::INVALID_STATE`       | `DualAttestation::EPAYEE_COMPLIANCE_KEY_NOT_SET` | The `account` does not have a compliance key set on it but dual attestion checking was performed.                                   |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::burn_txn_fees`
    /// * `TreasuryComplianceScripts::burn_with_amount`
    /// * `TreasuryComplianceScripts::preburn`
    CancelBurnWithAmount {
        token: TypeTag,
        preburn_address: AccountAddress,
        amount: u64,
    },

    CreateAccUser {
        challenge: Bytes,
        solution: Bytes,
    },

    CreateAccVal {
        challenge: Bytes,
        solution: Bytes,
        ow_human_name: Bytes,
        op_address: AccountAddress,
        op_auth_key_prefix: Bytes,
        op_consensus_pubkey: Bytes,
        op_validator_network_addresses: Bytes,
        op_fullnode_network_addresses: Bytes,
        op_human_name: Bytes,
    },

    /// # Summary
    /// Creates a Child VASP account with its parent being the sending account of the transaction.
    /// The sender of the transaction must be a Parent VASP account.
    ///
    /// # Technical Description
    /// Creates a `ChildVASP` account for the sender `parent_vasp` at `child_address` with a balance of
    /// `child_initial_balance` in `CoinType` and an initial authentication key of
    /// `auth_key_prefix | child_address`. Authentication key prefixes, and how to construct them from an ed25519 public key is described
    /// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
    ///
    /// If `add_all_currencies` is true, the child address will have a zero balance in all available
    /// currencies in the system.
    ///
    /// The new account will be a child account of the transaction sender, which must be a
    /// Parent VASP account. The child account will be recorded against the limit of
    /// child accounts of the creating Parent VASP account.
    ///
    /// # Events
    /// Successful execution will emit:
    /// * A `DiemAccount::CreateAccountEvent` with the `created` field being `child_address`,
    /// and the `rold_id` field being `Roles::CHILD_VASP_ROLE_ID`. This is emitted on the
    /// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
    ///
    /// Successful execution with a `child_initial_balance` greater than zero will additionaly emit:
    /// * A `DiemAccount::SentPaymentEvent` with the `payee` field being `child_address`.
    /// This is emitted on the Parent VASP's `DiemAccount::DiemAccount` `sent_events` handle.
    /// * A `DiemAccount::ReceivedPaymentEvent` with the  `payer` field being the Parent VASP's address.
    /// This is emitted on the new Child VASPS's `DiemAccount::DiemAccount` `received_events` handle.
    ///
    /// # Parameters
    /// | Name                    | Type         | Description                                                                                                                                 |
    /// | ------                  | ------       | -------------                                                                                                                               |
    /// | `CoinType`              | Type         | The Move type for the `CoinType` that the child account should be created with. `CoinType` must be an already-registered currency on-chain. |
    /// | `parent_vasp`           | `signer`     | The reference of the sending account. Must be a Parent VASP account.                                                                        |
    /// | `child_address`         | `address`    | Address of the to-be-created Child VASP account.                                                                                            |
    /// | `auth_key_prefix`       | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                    |
    /// | `add_all_currencies`    | `bool`       | Whether to publish balance resources for all known currencies when the account is created.                                                  |
    /// | `child_initial_balance` | `u64`        | The initial balance in `CoinType` to give the child account when it's created.                                                              |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                                             | Description                                                                              |
    /// | ----------------            | --------------                                           | -------------                                                                            |
    /// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`            | The `auth_key_prefix` was not of length 32.                                              |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::EPARENT_VASP`                                    | The sending account wasn't a Parent VASP account.                                        |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                                        | The `child_address` address is already taken.                                            |
    /// | `Errors::LIMIT_EXCEEDED`    | `VASP::ETOO_MANY_CHILDREN`                               | The sending account has reached the maximum number of allowed child accounts.            |
    /// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                                  | The `CoinType` is not a registered currency on-chain.                                    |
    /// | `Errors::INVALID_STATE`     | `DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED` | The withdrawal capability for the sending account has already been extracted.            |
    /// | `Errors::NOT_PUBLISHED`     | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`              | The sending account doesn't have a balance in `CoinType`.                                |
    /// | `Errors::LIMIT_EXCEEDED`    | `DiemAccount::EINSUFFICIENT_BALANCE`                    | The sending account doesn't have at least `child_initial_balance` of `CoinType` balance. |
    /// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::ECANNOT_CREATE_AT_VM_RESERVED`            | The `child_address` is the reserved address 0x0.                                         |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_parent_vasp_account`
    /// * `AccountAdministrationScripts::add_currency_to_account`
    /// * `AccountAdministrationScripts::rotate_authentication_key`
    /// * `AccountAdministrationScripts::add_recovery_rotation_capability`
    /// * `AccountAdministrationScripts::create_recovery_address`
    CreateChildVaspAccount {
        coin_type: TypeTag,
        child_address: AccountAddress,
        auth_key_prefix: Bytes,
        add_all_currencies: bool,
        child_initial_balance: u64,
    },

    /// # Summary
    /// Creates a Designated Dealer account with the provided information, and initializes it with
    /// default mint tiers. The transaction can only be sent by the Treasury Compliance account.
    ///
    /// # Technical Description
    /// Creates an account with the Designated Dealer role at `addr` with authentication key
    /// `auth_key_prefix` | `addr` and a 0 balance of type `Currency`. If `add_all_currencies` is true,
    /// 0 balances for all available currencies in the system will also be added. This can only be
    /// invoked by an account with the TreasuryCompliance role.
    /// Authentication keys, prefixes, and how to construct them from an ed25519 public key are described
    /// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
    ///
    /// At the time of creation the account is also initialized with default mint tiers of (500_000,
    /// 5000_000, 50_000_000, 500_000_000), and preburn areas for each currency that is added to the
    /// account.
    ///
    /// # Events
    /// Successful execution will emit:
    /// * A `DiemAccount::CreateAccountEvent` with the `created` field being `addr`,
    /// and the `rold_id` field being `Roles::DESIGNATED_DEALER_ROLE_ID`. This is emitted on the
    /// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
    ///
    /// # Parameters
    /// | Name                 | Type         | Description                                                                                                                                         |
    /// | ------               | ------       | -------------                                                                                                                                       |
    /// | `Currency`           | Type         | The Move type for the `Currency` that the Designated Dealer should be initialized with. `Currency` must be an already-registered currency on-chain. |
    /// | `tc_account`         | `signer`     | The signer of the sending account of this transaction. Must be the Treasury Compliance account.                                                     |
    /// | `sliding_nonce`      | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                                          |
    /// | `addr`               | `address`    | Address of the to-be-created Designated Dealer account.                                                                                             |
    /// | `auth_key_prefix`    | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                            |
    /// | `human_name`         | `vector<u8>` | ASCII-encoded human name for the Designated Dealer.                                                                                                 |
    /// | `add_all_currencies` | `bool`       | Whether to publish preburn, balance, and tier info resources for all known (SCS) currencies or just `Currency` when the account is created.         |
    ///

    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                            | Description                                                                                |
    /// | ----------------            | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::ETREASURY_COMPLIANCE`           | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                 | The `Currency` is not a registered currency on-chain.                                      |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `addr` address is already taken.                                                       |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::tiered_mint`
    /// * `PaymentScripts::peer_to_peer_with_metadata`
    /// * `AccountAdministrationScripts::rotate_dual_attestation_info`
    CreateDesignatedDealer {
        currency: TypeTag,
        sliding_nonce: u64,
        addr: AccountAddress,
        auth_key_prefix: Bytes,
        human_name: Bytes,
        add_all_currencies: bool,
    },

    /// # Summary
    /// Publishes a `DiemId::DiemIdDomains` resource under a parent VASP account.
    /// The sending account must be a parent VASP account.
    ///
    /// # Technical Description
    /// Publishes a `DiemId::DiemIdDomains` resource under `account`.
    /// The The `DiemId::DiemIdDomains` resource's `domains` field is a vector
    /// of DiemIdDomain, and will be empty on at the end of processing this transaction.
    ///
    /// # Parameters
    /// | Name      | Type     | Description                                           |
    /// | ------    | ------   | -------------                                         |
    /// | `account` | `signer` | The signer of the sending account of the transaction. |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason              | Description                                                                    |
    /// | ----------------            | --------------            | -------------                                                                  |
    /// | `Errors::ALREADY_PUBLISHED` | `DiemId::EDIEM_ID_DOMAIN` | A `DiemId::DiemIdDomains` resource has already been published under `account`. |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::EPARENT_VASP`     | The sending `account` was not a parent VASP account.                           |
    CreateDiemIdDomains {},

    /// # Summary
    /// Creates a Parent VASP account with the specified human name. Must be called by the Treasury Compliance account.
    ///
    /// # Technical Description
    /// Creates an account with the Parent VASP role at `address` with authentication key
    /// `auth_key_prefix` | `new_account_address` and a 0 balance of type `CoinType`. If
    /// `add_all_currencies` is true, 0 balances for all available currencies in the system will
    /// also be added. This can only be invoked by an TreasuryCompliance account.
    /// `sliding_nonce` is a unique nonce for operation, see `SlidingNonce` for details.
    /// Authentication keys, prefixes, and how to construct them from an ed25519 public key are described
    /// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
    ///
    /// # Events
    /// Successful execution will emit:
    /// * A `DiemAccount::CreateAccountEvent` with the `created` field being `new_account_address`,
    /// and the `rold_id` field being `Roles::PARENT_VASP_ROLE_ID`. This is emitted on the
    /// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
    ///
    /// # Parameters
    /// | Name                  | Type         | Description                                                                                                                                                    |
    /// | ------                | ------       | -------------                                                                                                                                                  |
    /// | `CoinType`            | Type         | The Move type for the `CoinType` currency that the Parent VASP account should be initialized with. `CoinType` must be an already-registered currency on-chain. |
    /// | `tc_account`          | `signer`     | The signer of the sending account of this transaction. Must be the Treasury Compliance account.                                                                |
    /// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                                                     |
    /// | `new_account_address` | `address`    | Address of the to-be-created Parent VASP account.                                                                                                              |
    /// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                                       |
    /// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the Parent VASP.                                                                                                                  |
    /// | `add_all_currencies`  | `bool`       | Whether to publish balance resources for all known currencies when the account is created.                                                                     |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                            | Description                                                                                |
    /// | ----------------            | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::ETREASURY_COMPLIANCE`           | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                 | The `CoinType` is not a registered currency on-chain.                                      |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_child_vasp_account`
    /// * `AccountAdministrationScripts::add_currency_to_account`
    /// * `AccountAdministrationScripts::rotate_authentication_key`
    /// * `AccountAdministrationScripts::add_recovery_rotation_capability`
    /// * `AccountAdministrationScripts::create_recovery_address`
    /// * `AccountAdministrationScripts::rotate_dual_attestation_info`
    CreateParentVaspAccount {
        coin_type: TypeTag,
        sliding_nonce: u64,
        new_account_address: AccountAddress,
        auth_key_prefix: Bytes,
        human_name: Bytes,
        add_all_currencies: bool,
    },

    /// # Summary
    /// Initializes the sending account as a recovery address that may be used by
    /// other accounts belonging to the same VASP as `account`.
    /// The sending account must be a VASP account, and can be either a child or parent VASP account.
    /// Multiple recovery addresses can exist for a single VASP, but accounts in
    /// each must be disjoint.
    ///
    /// # Technical Description
    /// Publishes a `RecoveryAddress::RecoveryAddress` resource under `account`. It then
    /// extracts the `DiemAccount::KeyRotationCapability` for `account` and adds
    /// it to the resource. After the successful execution of this transaction
    /// other accounts may add their key rotation to this resource so that `account`
    /// may be used as a recovery account for those accounts.
    ///
    /// # Parameters
    /// | Name      | Type     | Description                                           |
    /// | ------    | ------   | -------------                                         |
    /// | `account` | `signer` | The signer of the sending account of the transaction. |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                                               | Description                                                                                   |
    /// | ----------------            | --------------                                             | -------------                                                                                 |
    /// | `Errors::INVALID_STATE`     | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.          |
    /// | `Errors::INVALID_ARGUMENT`  | `RecoveryAddress::ENOT_A_VASP`                             | `account` is not a VASP account.                                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `RecoveryAddress::EKEY_ROTATION_DEPENDENCY_CYCLE`          | A key rotation recovery cycle would be created by adding `account`'s key rotation capability. |
    /// | `Errors::ALREADY_PUBLISHED` | `RecoveryAddress::ERECOVERY_ADDRESS`                       | A `RecoveryAddress::RecoveryAddress` resource has already been published under `account`.     |
    ///
    /// # Related Scripts
    /// * `Script::add_recovery_rotation_capability`
    /// * `Script::rotate_authentication_key_with_recovery_address`
    CreateRecoveryAddress {},

    /// # Summary
    /// Creates a Validator account. This transaction can only be sent by the Diem
    /// Root account.
    ///
    /// # Technical Description
    /// Creates an account with a Validator role at `new_account_address`, with authentication key
    /// `auth_key_prefix` | `new_account_address`. It publishes a
    /// `ValidatorConfig::ValidatorConfig` resource with empty `config`, and
    /// `operator_account` fields. The `human_name` field of the
    /// `ValidatorConfig::ValidatorConfig` is set to the passed in `human_name`.
    /// This script does not add the validator to the validator set or the system,
    /// but only creates the account.
    /// Authentication keys, prefixes, and how to construct them from an ed25519 public key are described
    /// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
    ///
    /// # Events
    /// Successful execution will emit:
    /// * A `DiemAccount::CreateAccountEvent` with the `created` field being `new_account_address`,
    /// and the `rold_id` field being `Roles::VALIDATOR_ROLE_ID`. This is emitted on the
    /// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
    ///
    /// # Parameters
    /// | Name                  | Type         | Description                                                                              |
    /// | ------                | ------       | -------------                                                                            |
    /// | `dr_account`          | `signer`     | The signer of the sending account of this transaction. Must be the Diem Root signer.     |
    /// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.               |
    /// | `new_account_address` | `address`    | Address of the to-be-created Validator account.                                          |
    /// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account. |
    /// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the validator.                                              |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                            | Description                                                                                |
    /// | ----------------            | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                             |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                         |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                         |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_validator_operator_account`
    /// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::register_validator_config`
    /// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::set_validator_operator`
    /// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
    /// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
    CreateValidatorAccount {
        sliding_nonce: u64,
        new_account_address: AccountAddress,
        auth_key_prefix: Bytes,
        human_name: Bytes,
    },

    /// # Summary
    /// Creates a Validator Operator account. This transaction can only be sent by the Diem
    /// Root account.
    ///
    /// # Technical Description
    /// Creates an account with a Validator Operator role at `new_account_address`, with authentication key
    /// `auth_key_prefix` | `new_account_address`. It publishes a
    /// `ValidatorOperatorConfig::ValidatorOperatorConfig` resource with the specified `human_name`.
    /// This script does not assign the validator operator to any validator accounts but only creates the account.
    /// Authentication key prefixes, and how to construct them from an ed25519 public key are described
    /// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
    ///
    /// # Events
    /// Successful execution will emit:
    /// * A `DiemAccount::CreateAccountEvent` with the `created` field being `new_account_address`,
    /// and the `rold_id` field being `Roles::VALIDATOR_OPERATOR_ROLE_ID`. This is emitted on the
    /// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
    ///
    /// # Parameters
    /// | Name                  | Type         | Description                                                                              |
    /// | ------                | ------       | -------------                                                                            |
    /// | `dr_account`          | `signer`     | The signer of the sending account of this transaction. Must be the Diem Root signer.     |
    /// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.               |
    /// | `new_account_address` | `address`    | Address of the to-be-created Validator account.                                          |
    /// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account. |
    /// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the validator.                                              |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                            | Description                                                                                |
    /// | ----------------            | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                             |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                         |
    /// | `Errors::REQUIRES_ROLE`     | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                         |
    /// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_validator_account`
    /// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::register_validator_config`
    /// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::set_validator_operator`
    /// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
    /// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
    CreateValidatorOperatorAccount {
        sliding_nonce: u64,
        new_account_address: AccountAddress,
        auth_key_prefix: Bytes,
        human_name: Bytes,
    },

    DemoE2e {
        world: u64,
    },

    /// # Summary
    /// Freezes the account at `address`. The sending account of this transaction
    /// must be the Treasury Compliance account. The account being frozen cannot be
    /// the Diem Root or Treasury Compliance account. After the successful
    /// execution of this transaction no transactions may be sent from the frozen
    /// account, and the frozen account may not send or receive coins.
    ///
    /// # Technical Description
    /// Sets the `AccountFreezing::FreezingBit` to `true` and emits a
    /// `AccountFreezing::FreezeAccountEvent`. The transaction sender must be the
    /// Treasury Compliance account, but the account at `to_freeze_account` must
    /// not be either `0xA550C18` (the Diem Root address), or `0xB1E55ED` (the
    /// Treasury Compliance address). Note that this is a per-account property
    /// e.g., freezing a Parent VASP will not effect the status any of its child
    /// accounts and vice versa.
    ///

    /// # Events
    /// Successful execution of this transaction will emit a `AccountFreezing::FreezeAccountEvent` on
    /// the `freeze_event_handle` held in the `AccountFreezing::FreezeEventsHolder` resource published
    /// under `0xA550C18` with the `frozen_address` being the `to_freeze_account`.
    ///
    /// # Parameters
    /// | Name                | Type      | Description                                                                                     |
    /// | ------              | ------    | -------------                                                                                   |
    /// | `tc_account`        | `signer`  | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
    /// | `sliding_nonce`     | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
    /// | `to_freeze_account` | `address` | The account address to be frozen.                                                               |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                 | Description                                                                                |
    /// | ----------------           | --------------                               | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`        | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`                | The sending account is not the Treasury Compliance account.                                |
    /// | `Errors::INVALID_ARGUMENT` | `AccountFreezing::ECANNOT_FREEZE_TC`         | `to_freeze_account` was the Treasury Compliance account (`0xB1E55ED`).                     |
    /// | `Errors::INVALID_ARGUMENT` | `AccountFreezing::ECANNOT_FREEZE_DIEM_ROOT` | `to_freeze_account` was the Diem Root account (`0xA550C18`).                              |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::unfreeze_account`
    FreezeAccount {
        sliding_nonce: u64,
        to_freeze_account: AccountAddress,
    },

    /// # Summary
    /// Initializes the Diem consensus config that is stored on-chain.  This
    /// transaction can only be sent from the Diem Root account.
    ///
    /// # Technical Description
    /// Initializes the `DiemConsensusConfig` on-chain config to empty and allows future updates from DiemRoot via
    /// `update_diem_consensus_config`. This doesn't emit a `DiemConfig::NewEpochEvent`.
    ///
    /// # Parameters
    /// | Name            | Type      | Description                                                                |
    /// | ------          | ------    | -------------                                                              |
    /// | `account`       | `signer` | Signer of the sending account. Must be the Diem Root account.               |
    /// | `sliding_nonce` | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                  | Description                                                                                |
    /// | ----------------           | --------------                                | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                   | `account` is not the Diem Root account.                                                    |
    InitializeDiemConsensusConfig {
        sliding_nonce: u64,
    },

    Join {},

    Leave {},

    MinerstateCommit {
        challenge: Bytes,
        solution: Bytes,
    },

    MinerstateCommitByOperator {
        owner_address: AccountAddress,
        challenge: Bytes,
        solution: Bytes,
    },

    MinerstateHelper {},

    OlOracleTx {
        id: u64,
        data: Bytes,
    },

    OlReconfigBulkUpdateSetup {
        alice: AccountAddress,
        bob: AccountAddress,
        carol: AccountAddress,
        sha: AccountAddress,
        ram: AccountAddress,
    },

    /// # Summary
    /// Transfers a given number of coins in a specified currency from one account to another.
    /// Transfers over a specified amount defined on-chain that are between two different VASPs, or
    /// other accounts that have opted-in will be subject to on-chain checks to ensure the receiver has
    /// agreed to receive the coins.  This transaction can be sent by any account that can hold a
    /// balance, and to any account that can hold a balance. Both accounts must hold balances in the
    /// currency being transacted.
    ///
    /// # Technical Description
    ///
    /// Transfers `amount` coins of type `Currency` from `payer` to `payee` with (optional) associated
    /// `metadata` and an (optional) `metadata_signature` on the message of the form
    /// `metadata` | `Signer::address_of(payer)` | `amount` | `DualAttestation::DOMAIN_SEPARATOR`, that
    /// has been signed by the `payee`'s private key associated with the `compliance_public_key` held in
    /// the `payee`'s `DualAttestation::Credential`. Both the `Signer::address_of(payer)` and `amount` fields
    /// in the `metadata_signature` must be BCS-encoded bytes, and `|` denotes concatenation.
    /// The `metadata` and `metadata_signature` parameters are only required if `amount` >=
    /// `DualAttestation::get_cur_microdiem_limit` XDX and `payer` and `payee` are distinct VASPs.
    /// However, a transaction sender can opt in to dual attestation even when it is not required
    /// (e.g., a DesignatedDealer -> VASP payment) by providing a non-empty `metadata_signature`.
    /// Standardized `metadata` BCS format can be found in `diem_types::transaction::metadata::Metadata`.
    ///
    /// # Events
    /// Successful execution of this script emits two events:
    /// * A `DiemAccount::SentPaymentEvent` on `payer`'s `DiemAccount::DiemAccount` `sent_events` handle; and
    /// * A `DiemAccount::ReceivedPaymentEvent` on `payee`'s `DiemAccount::DiemAccount` `received_events` handle.
    ///
    /// # Parameters
    /// | Name                 | Type         | Description                                                                                                                  |
    /// | ------               | ------       | -------------                                                                                                                |
    /// | `Currency`           | Type         | The Move type for the `Currency` being sent in this transaction. `Currency` must be an already-registered currency on-chain. |
    /// | `payer`              | `signer`     | The signer of the sending account that coins are being transferred from.                                                     |
    /// | `payee`              | `address`    | The address of the account the coins are being transferred to.                                                               |
    /// | `metadata`           | `vector<u8>` | Optional metadata about this payment.                                                                                        |
    /// | `metadata_signature` | `vector<u8>` | Optional signature over `metadata` and payment information. See                                                              |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                     | Description                                                                                                                         |
    /// | ----------------           | --------------                                   | -------------                                                                                                                       |
    /// | `Errors::NOT_PUBLISHED`    | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`       | `payer` doesn't hold a balance in `Currency`.                                                                                       |
    /// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EINSUFFICIENT_BALANCE`             | `amount` is greater than `payer`'s balance in `Currency`.                                                                           |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::ECOIN_DEPOSIT_IS_ZERO`             | `amount` is zero.                                                                                                                   |
    /// | `Errors::NOT_PUBLISHED`    | `DiemAccount::EPAYEE_DOES_NOT_EXIST`             | No account exists at the `payee` address.                                                                                           |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE`  | An account exists at `payee`, but it does not accept payments in `Currency`.                                                        |
    /// | `Errors::INVALID_STATE`    | `AccountFreezing::EACCOUNT_FROZEN`               | The `payee` account is frozen.                                                                                                      |
    /// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EMALFORMED_METADATA_SIGNATURE` | `metadata_signature` is not 64 bytes.                                                                                               |
    /// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EINVALID_METADATA_SIGNATURE`   | `metadata_signature` does not verify on the against the `payee'`s `DualAttestation::Credential` `compliance_public_key` public key. |
    /// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EWITHDRAWAL_EXCEEDS_LIMITS`        | `payer` has exceeded its daily withdrawal limits for the backing coins of XDX.                                                      |
    /// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`           | `payee` has exceeded its daily deposit limits for XDX.                                                                              |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_child_vasp_account`
    /// * `AccountCreationScripts::create_parent_vasp_account`
    /// * `AccountAdministrationScripts::add_currency_to_account`
    PeerToPeerWithMetadata {
        currency: TypeTag,
        payee: AccountAddress,
        amount: u64,
        metadata: Bytes,
        metadata_signature: Bytes,
    },

    /// # Summary
    /// Moves a specified number of coins in a given currency from the account's
    /// balance to its preburn area after which the coins may be burned. This
    /// transaction may be sent by any account that holds a balance and preburn area
    /// in the specified currency.
    ///
    /// # Technical Description
    /// Moves the specified `amount` of coins in `Token` currency from the sending `account`'s
    /// `DiemAccount::Balance<Token>` to the `Diem::Preburn<Token>` published under the same
    /// `account`. `account` must have both of these resources published under it at the start of this
    /// transaction in order for it to execute successfully.
    ///
    /// # Events
    /// Successful execution of this script emits two events:
    /// * `DiemAccount::SentPaymentEvent ` on `account`'s `DiemAccount::DiemAccount` `sent_events`
    /// handle with the `payee` and `payer` fields being `account`'s address; and
    /// * A `Diem::PreburnEvent` with `Token`'s currency code on the
    /// `Diem::CurrencyInfo<Token`'s `preburn_events` handle for `Token` and with
    /// `preburn_address` set to `account`'s address.
    ///
    /// # Parameters
    /// | Name      | Type     | Description                                                                                                                      |
    /// | ------    | ------   | -------------                                                                                                                    |
    /// | `Token`   | Type     | The Move type for the `Token` currency being moved to the preburn area. `Token` must be an already-registered currency on-chain. |
    /// | `account` | `signer` | The signer of the sending account.                                                                                               |
    /// | `amount`  | `u64`    | The amount in `Token` to be moved to the preburn area.                                                                           |
    ///
    /// # Common Abort Conditions
    /// | Error Category           | Error Reason                                             | Description                                                                             |
    /// | ----------------         | --------------                                           | -------------                                                                           |
    /// | `Errors::NOT_PUBLISHED`  | `Diem::ECURRENCY_INFO`                                  | The `Token` is not a registered currency on-chain.                                      |
    /// | `Errors::INVALID_STATE`  | `DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED` | The withdrawal capability for `account` has already been extracted.                     |
    /// | `Errors::LIMIT_EXCEEDED` | `DiemAccount::EINSUFFICIENT_BALANCE`                    | `amount` is greater than `payer`'s balance in `Token`.                                  |
    /// | `Errors::NOT_PUBLISHED`  | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`              | `account` doesn't hold a balance in `Token`.                                            |
    /// | `Errors::NOT_PUBLISHED`  | `Diem::EPREBURN`                                        | `account` doesn't have a `Diem::Preburn<Token>` resource published under it.           |
    /// | `Errors::INVALID_STATE`  | `Diem::EPREBURN_OCCUPIED`                               | The `value` field in the `Diem::Preburn<Token>` resource under the sender is non-zero. |
    /// | `Errors::NOT_PUBLISHED`  | `Roles::EROLE_ID`                                        | The `account` did not have a role assigned to it.                                       |
    /// | `Errors::REQUIRES_ROLE`  | `Roles::EDESIGNATED_DEALER`                              | The `account` did not have the role of DesignatedDealer.                                |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::cancel_burn_with_amount`
    /// * `TreasuryComplianceScripts::burn_with_amount`
    /// * `TreasuryComplianceScripts::burn_txn_fees`
    Preburn {
        token: TypeTag,
        amount: u64,
    },

    /// # Summary
    /// Rotates the authentication key of the sending account to the newly-specified ed25519 public key and
    /// publishes a new shared authentication key derived from that public key under the sender's account.
    /// Any account can send this transaction.
    ///
    /// # Technical Description
    /// Rotates the authentication key of the sending account to the
    /// [authentication key derived from `public_key`](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys)
    /// and publishes a `SharedEd25519PublicKey::SharedEd25519PublicKey` resource
    /// containing the 32-byte ed25519 `public_key` and the `DiemAccount::KeyRotationCapability` for
    /// `account` under `account`.
    ///
    /// # Parameters
    /// | Name         | Type         | Description                                                                                        |
    /// | ------       | ------       | -------------                                                                                      |
    /// | `account`    | `signer`     | The signer of the sending account of the transaction.                                              |
    /// | `public_key` | `vector<u8>` | A valid 32-byte Ed25519 public key for `account`'s authentication key to be rotated to and stored. |
    ///
    /// # Common Abort Conditions
    /// | Error Category              | Error Reason                                               | Description                                                                                         |
    /// | ----------------            | --------------                                             | -------------                                                                                       |
    /// | `Errors::INVALID_STATE`     | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability` resource.       |
    /// | `Errors::ALREADY_PUBLISHED` | `SharedEd25519PublicKey::ESHARED_KEY`                      | The `SharedEd25519PublicKey::SharedEd25519PublicKey` resource is already published under `account`. |
    /// | `Errors::INVALID_ARGUMENT`  | `SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY`            | `public_key` is an invalid ed25519 public key.                                                      |
    ///
    /// # Related Scripts
    /// * `AccountAdministrationScripts::rotate_shared_ed25519_public_key`
    PublishSharedEd25519PublicKey {
        public_key: Bytes,
    },

    /// # Summary
    /// Updates a validator's configuration. This does not reconfigure the system and will not update
    /// the configuration in the validator set that is seen by other validators in the network. Can
    /// only be successfully sent by a Validator Operator account that is already registered with a
    /// validator.
    ///
    /// # Technical Description
    /// This updates the fields with corresponding names held in the `ValidatorConfig::ValidatorConfig`
    /// config resource held under `validator_account`. It does not emit a `DiemConfig::NewEpochEvent`
    /// so the copy of this config held in the validator set will not be updated, and the changes are
    /// only "locally" under the `validator_account` account address.
    ///
    /// # Parameters
    /// | Name                          | Type         | Description                                                                                                        |
    /// | ------                        | ------       | -------------                                                                                                      |
    /// | `validator_operator_account`  | `signer`     | Signer of the sending account. Must be the registered validator operator for the validator at `validator_address`. |
    /// | `validator_account`           | `address`    | The address of the validator's `ValidatorConfig::ValidatorConfig` resource being updated.                          |
    /// | `consensus_pubkey`            | `vector<u8>` | New Ed25519 public key to be used in the updated `ValidatorConfig::ValidatorConfig`.                               |
    /// | `validator_network_addresses` | `vector<u8>` | New set of `validator_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.             |
    /// | `fullnode_network_addresses`  | `vector<u8>` | New set of `fullnode_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.              |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                   | Description                                                                                           |
    /// | ----------------           | --------------                                 | -------------                                                                                         |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`           | `validator_address` does not have a `ValidatorConfig::ValidatorConfig` resource published under it.   |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_TRANSACTION_SENDER` | `validator_operator_account` is not the registered operator for the validator at `validator_address`. |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_CONSENSUS_KEY`      | `consensus_pubkey` is not a valid ed25519 public key.                                                 |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_validator_account`
    /// * `AccountCreationScripts::create_validator_operator_account`
    /// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::set_validator_operator`
    /// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
    /// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
    RegisterValidatorConfig {
        validator_account: AccountAddress,
        consensus_pubkey: Bytes,
        validator_network_addresses: Bytes,
        fullnode_network_addresses: Bytes,
    },

    /// # Summary
    /// Remove a DiemID domain from parent VASP account. The transaction can only be sent by
    /// the Treasury Compliance account.
    ///
    /// # Technical Description
    /// Removes a `DiemId::DiemIdDomain` from the `domains` field of the `DiemId::DiemIdDomains` resource published under
    /// account with `address`.
    ///
    /// # Parameters
    /// | Name         | Type         | Description                                                                                     |
    /// | ------       | ------       | -------------                                                                                   |
    /// | `tc_account` | `signer`     | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
    /// | `address`    | `address`    | The `address` of parent VASP account that will update its domains.                              |
    /// | `domain`     | `vector<u8>` | The domain name.                                                                                |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                             | Description                                                                                                                            |
    /// | ----------------           | --------------                           | -------------                                                                                                                          |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`            | The sending account is not the Treasury Compliance account.                                                                            |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`    | `tc_account` is not the Treasury Compliance account.                                                                                   |
    /// | `Errors::NOT_PUBLISHED`    | `DiemId::EDIEM_ID_DOMAIN_MANAGER`        | The `DiemId::DiemIdDomainManager` resource is not yet published under the Treasury Compliance account.                                 |
    /// | `Errors::NOT_PUBLISHED`    | `DiemId::EDIEM_ID_DOMAINS_NOT_PUBLISHED` | `address` does not have a `DiemId::DiemIdDomains` resource published under it.                                                         |
    /// | `Errors::INVALID_ARGUMENT` | `DiemId::EINVALID_DIEM_ID_DOMAIN`        | The `domain` is greater in length than `DiemId::DOMAIN_LENGTH`.                                                                        |
    /// | `Errors::INVALID_ARGUMENT` | `DiemId::EDOMAIN_NOT_FOUND`              | The `domain` does not exist in the list of `DiemId::DiemIdDomain`s  in the `DiemId::DiemIdDomains` resource published under `address`. |
    RemoveDiemIdDomain {
        address: AccountAddress,
        domain: Bytes,
    },

    /// # Summary
    /// This script removes a validator account from the validator set, and triggers a reconfiguration
    /// of the system to remove the validator from the system. This transaction can only be
    /// successfully called by the Diem Root account.
    ///
    /// # Technical Description
    /// This script removes the account at `validator_address` from the validator set. This transaction
    /// emits a `DiemConfig::NewEpochEvent` event. Once the reconfiguration triggered by this event
    /// has been performed, the account at `validator_address` is no longer considered to be a
    /// validator in the network. This transaction will fail if the validator at `validator_address`
    /// is not in the validator set.
    ///
    /// # Parameters
    /// | Name                | Type         | Description                                                                                                                        |
    /// | ------              | ------       | -------------                                                                                                                      |
    /// | `dr_account`        | `signer`     | The signer of the sending account of this transaction. Must be the Diem Root signer.                                               |
    /// | `sliding_nonce`     | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                         |
    /// | `validator_name`    | `vector<u8>` | ASCII-encoded human name for the validator. Must match the human name in the `ValidatorConfig::ValidatorConfig` for the validator. |
    /// | `validator_address` | `address`    | The validator account address to be removed from the validator set.                                                                |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                            | Description                                                                                     |
    /// | ----------------           | --------------                          | -------------                                                                                   |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                                  |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.      |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                                   |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                               |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | The sending account is not the Diem Root account or Treasury Compliance account                |
    /// | 0                          | 0                                       | The provided `validator_name` does not match the already-recorded human name for the validator. |
    /// | `Errors::INVALID_ARGUMENT` | `DiemSystem::ENOT_AN_ACTIVE_VALIDATOR` | The validator to be removed is not in the validator set.                                        |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                              |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                              |
    /// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`      | An invalid time value was encountered in reconfiguration. Unlikely to occur.                    |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_validator_account`
    /// * `AccountCreationScripts::create_validator_operator_account`
    /// * `ValidatorAdministrationScripts::register_validator_config`
    /// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::set_validator_operator`
    /// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
    /// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
    RemoveValidatorAndReconfigure {
        sliding_nonce: u64,
        validator_name: Bytes,
        validator_address: AccountAddress,
    },

    /// # Summary
    /// Rotates the `account`'s authentication key to the supplied new authentication key. May be sent by any account.
    ///
    /// # Technical Description
    /// Rotate the `account`'s `DiemAccount::DiemAccount` `authentication_key`
    /// field to `new_key`. `new_key` must be a valid authentication key that
    /// corresponds to an ed25519 public key as described [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys),
    /// and `account` must not have previously delegated its `DiemAccount::KeyRotationCapability`.
    ///
    /// # Parameters
    /// | Name      | Type         | Description                                       |
    /// | ------    | ------       | -------------                                     |
    /// | `account` | `signer`     | Signer of the sending account of the transaction. |
    /// | `new_key` | `vector<u8>` | New authentication key to be used for `account`.  |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                              | Description                                                                         |
    /// | ----------------           | --------------                                            | -------------                                                                       |
    /// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`. |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                    |
    ///
    /// # Related Scripts
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce_admin`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_recovery_address`
    RotateAuthenticationKey {
        new_key: Bytes,
    },

    /// # Summary
    /// Rotates the sender's authentication key to the supplied new authentication key. May be sent by
    /// any account that has a sliding nonce resource published under it (usually this is Treasury
    /// Compliance or Diem Root accounts).
    ///
    /// # Technical Description
    /// Rotates the `account`'s `DiemAccount::DiemAccount` `authentication_key`
    /// field to `new_key`. `new_key` must be a valid authentication key that
    /// corresponds to an ed25519 public key as described [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys),
    /// and `account` must not have previously delegated its `DiemAccount::KeyRotationCapability`.
    ///
    /// # Parameters
    /// | Name            | Type         | Description                                                                |
    /// | ------          | ------       | -------------                                                              |
    /// | `account`       | `signer`     | Signer of the sending account of the transaction.                          |
    /// | `sliding_nonce` | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
    /// | `new_key`       | `vector<u8>` | New authentication key to be used for `account`.                           |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                               | Description                                                                                |
    /// | ----------------           | --------------                                             | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                             | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                             | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                             | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`                    | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.       |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                           |
    ///
    /// # Related Scripts
    /// * `AccountAdministrationScripts::rotate_authentication_key`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce_admin`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_recovery_address`
    RotateAuthenticationKeyWithNonce {
        sliding_nonce: u64,
        new_key: Bytes,
    },

    /// # Summary
    /// Rotates the specified account's authentication key to the supplied new authentication key. May
    /// only be sent by the Diem Root account as a write set transaction.
    ///
    /// # Technical Description
    /// Rotate the `account`'s `DiemAccount::DiemAccount` `authentication_key` field to `new_key`.
    /// `new_key` must be a valid authentication key that corresponds to an ed25519
    /// public key as described [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys),
    /// and `account` must not have previously delegated its `DiemAccount::KeyRotationCapability`.
    ///
    /// # Parameters
    /// | Name            | Type         | Description                                                                                       |
    /// | ------          | ------       | -------------                                                                                     |
    /// | `dr_account`    | `signer`     | The signer of the sending account of the write set transaction. May only be the Diem Root signer. |
    /// | `account`       | `signer`     | Signer of account specified in the `execute_as` field of the write set transaction.               |
    /// | `sliding_nonce` | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction for Diem Root.          |
    /// | `new_key`       | `vector<u8>` | New authentication key to be used for `account`.                                                  |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                              | Description                                                                                                |
    /// | ----------------           | --------------                                            | -------------                                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                            | A `SlidingNonce` resource is not published under `dr_account`.                                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                            | The `sliding_nonce` in `dr_account` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                            | The `sliding_nonce` in `dr_account` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`                   | The `sliding_nonce` in` dr_account` has been previously recorded.                                          |
    /// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.                        |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                                           |
    ///
    /// # Related Scripts
    /// * `AccountAdministrationScripts::rotate_authentication_key`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_recovery_address`
    RotateAuthenticationKeyWithNonceAdmin {
        sliding_nonce: u64,
        new_key: Bytes,
    },

    /// # Summary
    /// Rotates the authentication key of a specified account that is part of a recovery address to a
    /// new authentication key. Only used for accounts that are part of a recovery address (see
    /// `AccountAdministrationScripts::add_recovery_rotation_capability` for account restrictions).
    ///
    /// # Technical Description
    /// Rotates the authentication key of the `to_recover` account to `new_key` using the
    /// `DiemAccount::KeyRotationCapability` stored in the `RecoveryAddress::RecoveryAddress` resource
    /// published under `recovery_address`. `new_key` must be a valide authentication key as described
    /// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
    /// This transaction can be sent either by the `to_recover` account, or by the account where the
    /// `RecoveryAddress::RecoveryAddress` resource is published that contains `to_recover`'s `DiemAccount::KeyRotationCapability`.
    ///
    /// # Parameters
    /// | Name               | Type         | Description                                                                                                                   |
    /// | ------             | ------       | -------------                                                                                                                 |
    /// | `account`          | `signer`     | Signer of the sending account of the transaction.                                                                             |
    /// | `recovery_address` | `address`    | Address where `RecoveryAddress::RecoveryAddress` that holds `to_recover`'s `DiemAccount::KeyRotationCapability` is published. |
    /// | `to_recover`       | `address`    | The address of the account whose authentication key will be updated.                                                          |
    /// | `new_key`          | `vector<u8>` | New authentication key to be used for the account at the `to_recover` address.                                                |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                 | Description                                                                                                                                         |
    /// | ----------------           | --------------                               | -------------                                                                                                                                       |
    /// | `Errors::NOT_PUBLISHED`    | `RecoveryAddress::ERECOVERY_ADDRESS`         | `recovery_address` does not have a `RecoveryAddress::RecoveryAddress` resource published under it.                                                  |
    /// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::ECANNOT_ROTATE_KEY`        | The address of `account` is not `recovery_address` or `to_recover`.                                                                                 |
    /// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::EACCOUNT_NOT_RECOVERABLE`  | `to_recover`'s `DiemAccount::KeyRotationCapability`  is not in the `RecoveryAddress::RecoveryAddress`  resource published under `recovery_address`. |
    /// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY` | `new_key` was an invalid length.                                                                                                                    |
    ///
    /// # Related Scripts
    /// * `AccountAdministrationScripts::rotate_authentication_key`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce`
    /// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce_admin`
    RotateAuthenticationKeyWithRecoveryAddress {
        recovery_address: AccountAddress,
        to_recover: AccountAddress,
        new_key: Bytes,
    },

    /// # Summary
    /// Updates the url used for off-chain communication, and the public key used to verify dual
    /// attestation on-chain. Transaction can be sent by any account that has dual attestation
    /// information published under it. In practice the only such accounts are Designated Dealers and
    /// Parent VASPs.
    ///
    /// # Technical Description
    /// Updates the `base_url` and `compliance_public_key` fields of the `DualAttestation::Credential`
    /// resource published under `account`. The `new_key` must be a valid ed25519 public key.
    ///
    /// # Events
    /// Successful execution of this transaction emits two events:
    /// * A `DualAttestation::ComplianceKeyRotationEvent` containing the new compliance public key, and
    /// the blockchain time at which the key was updated emitted on the `DualAttestation::Credential`
    /// `compliance_key_rotation_events` handle published under `account`; and
    /// * A `DualAttestation::BaseUrlRotationEvent` containing the new base url to be used for
    /// off-chain communication, and the blockchain time at which the url was updated emitted on the
    /// `DualAttestation::Credential` `base_url_rotation_events` handle published under `account`.
    ///
    /// # Parameters
    /// | Name      | Type         | Description                                                               |
    /// | ------    | ------       | -------------                                                             |
    /// | `account` | `signer`     | Signer of the sending account of the transaction.                         |
    /// | `new_url` | `vector<u8>` | ASCII-encoded url to be used for off-chain communication with `account`.  |
    /// | `new_key` | `vector<u8>` | New ed25519 public key to be used for on-chain dual attestation checking. |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                           | Description                                                                |
    /// | ----------------           | --------------                         | -------------                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `DualAttestation::ECREDENTIAL`         | A `DualAttestation::Credential` resource is not published under `account`. |
    /// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EINVALID_PUBLIC_KEY` | `new_key` is not a valid ed25519 public key.                               |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_parent_vasp_account`
    /// * `AccountCreationScripts::create_designated_dealer`
    /// * `AccountAdministrationScripts::rotate_dual_attestation_info`
    RotateDualAttestationInfo {
        new_url: Bytes,
        new_key: Bytes,
    },

    /// # Summary
    /// Rotates the authentication key in a `SharedEd25519PublicKey`. This transaction can be sent by
    /// any account that has previously published a shared ed25519 public key using
    /// `AccountAdministrationScripts::publish_shared_ed25519_public_key`.
    ///
    /// # Technical Description
    /// `public_key` must be a valid ed25519 public key.  This transaction first rotates the public key stored in `account`'s
    /// `SharedEd25519PublicKey::SharedEd25519PublicKey` resource to `public_key`, after which it
    /// rotates the `account`'s authentication key to the new authentication key derived from `public_key` as defined
    /// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys)
    /// using the `DiemAccount::KeyRotationCapability` stored in `account`'s `SharedEd25519PublicKey::SharedEd25519PublicKey`.
    ///
    /// # Parameters
    /// | Name         | Type         | Description                                           |
    /// | ------       | ------       | -------------                                         |
    /// | `account`    | `signer`     | The signer of the sending account of the transaction. |
    /// | `public_key` | `vector<u8>` | 32-byte Ed25519 public key.                           |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                    | Description                                                                                   |
    /// | ----------------           | --------------                                  | -------------                                                                                 |
    /// | `Errors::NOT_PUBLISHED`    | `SharedEd25519PublicKey::ESHARED_KEY`           | A `SharedEd25519PublicKey::SharedEd25519PublicKey` resource is not published under `account`. |
    /// | `Errors::INVALID_ARGUMENT` | `SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY` | `public_key` is an invalid ed25519 public key.                                                |
    ///
    /// # Related Scripts
    /// * `AccountAdministrationScripts::publish_shared_ed25519_public_key`
    RotateSharedEd25519PublicKey {
        public_key: Bytes,
    },

    /// # Summary
    /// Updates the gas constants stored on chain and used by the VM for gas
    /// metering. This transaction can only be sent from the Diem Root account.
    ///
    /// # Technical Description
    /// Updates the on-chain config holding the `DiemVMConfig` and emits a
    /// `DiemConfig::NewEpochEvent` to trigger a reconfiguration of the system.
    ///
    /// # Parameters
    /// | Name                                | Type     | Description                                                                                            |
    /// | ------                              | ------   | -------------                                                                                          |
    /// | `account`                           | `signer` | Signer of the sending account. Must be the Diem Root account.                                          |
    /// | `sliding_nonce`                     | `u64`    | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                             |
    /// | `global_memory_per_byte_cost`       | `u64`    | The new cost to read global memory per-byte to be used for gas metering.                               |
    /// | `global_memory_per_byte_write_cost` | `u64`    | The new cost to write global memory per-byte to be used for gas metering.                              |
    /// | `min_transaction_gas_units`         | `u64`    | The new flat minimum amount of gas required for any transaction.                                       |
    /// | `large_transaction_cutoff`          | `u64`    | The new size over which an additional charge will be assessed for each additional byte.                |
    /// | `intrinsic_gas_per_byte`            | `u64`    | The new number of units of gas that to be charged per-byte over the new `large_transaction_cutoff`.    |
    /// | `maximum_number_of_gas_units`       | `u64`    | The new maximum number of gas units that can be set in a transaction.                                  |
    /// | `min_price_per_gas_unit`            | `u64`    | The new minimum gas price that can be set for a transaction.                                           |
    /// | `max_price_per_gas_unit`            | `u64`    | The new maximum gas price that can be set for a transaction.                                           |
    /// | `max_transaction_size_in_bytes`     | `u64`    | The new maximum size of a transaction that can be processed.                                           |
    /// | `gas_unit_scaling_factor`           | `u64`    | The new scaling factor to use when scaling between external and internal gas units.                    |
    /// | `default_account_size`              | `u64`    | The new default account size to use when assessing final costs for reads and writes to global storage. |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                | Description                                                                                |
    /// | ----------------           | --------------                              | -------------                                                                              |
    /// | `Errors::INVALID_ARGUMENT` | `DiemVMConfig::EGAS_CONSTANT_INCONSISTENCY` | The provided gas constants are inconsistent.                                               |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`              | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`              | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`              | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`     | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                 | `account` is not the Diem Root account.                                                    |
    SetGasConstants {
        sliding_nonce: u64,
        global_memory_per_byte_cost: u64,
        global_memory_per_byte_write_cost: u64,
        min_transaction_gas_units: u64,
        large_transaction_cutoff: u64,
        intrinsic_gas_per_byte: u64,
        maximum_number_of_gas_units: u64,
        min_price_per_gas_unit: u64,
        max_price_per_gas_unit: u64,
        max_transaction_size_in_bytes: u64,
        gas_unit_scaling_factor: u64,
        default_account_size: u64,
    },

    /// # Summary
    /// Updates a validator's configuration, and triggers a reconfiguration of the system to update the
    /// validator set with this new validator configuration.  Can only be successfully sent by a
    /// Validator Operator account that is already registered with a validator.
    ///
    /// # Technical Description
    /// This updates the fields with corresponding names held in the `ValidatorConfig::ValidatorConfig`
    /// config resource held under `validator_account`. It then emits a `DiemConfig::NewEpochEvent` to
    /// trigger a reconfiguration of the system.  This reconfiguration will update the validator set
    /// on-chain with the updated `ValidatorConfig::ValidatorConfig`.
    ///
    /// # Parameters
    /// | Name                          | Type         | Description                                                                                                        |
    /// | ------                        | ------       | -------------                                                                                                      |
    /// | `validator_operator_account`  | `signer`     | Signer of the sending account. Must be the registered validator operator for the validator at `validator_address`. |
    /// | `validator_account`           | `address`    | The address of the validator's `ValidatorConfig::ValidatorConfig` resource being updated.                          |
    /// | `consensus_pubkey`            | `vector<u8>` | New Ed25519 public key to be used in the updated `ValidatorConfig::ValidatorConfig`.                               |
    /// | `validator_network_addresses` | `vector<u8>` | New set of `validator_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.             |
    /// | `fullnode_network_addresses`  | `vector<u8>` | New set of `fullnode_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.              |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                   | Description                                                                                           |
    /// | ----------------           | --------------                                 | -------------                                                                                         |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`           | `validator_address` does not have a `ValidatorConfig::ValidatorConfig` resource published under it.   |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR_OPERATOR`                   | `validator_operator_account` does not have a Validator Operator role.                                 |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_TRANSACTION_SENDER` | `validator_operator_account` is not the registered operator for the validator at `validator_address`. |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_CONSENSUS_KEY`      | `consensus_pubkey` is not a valid ed25519 public key.                                                 |
    /// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`             | An invalid time value was encountered in reconfiguration. Unlikely to occur.                          |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_validator_account`
    /// * `AccountCreationScripts::create_validator_operator_account`
    /// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::set_validator_operator`
    /// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
    /// * `ValidatorAdministrationScripts::register_validator_config`
    SetValidatorConfigAndReconfigure {
        validator_account: AccountAddress,
        consensus_pubkey: Bytes,
        validator_network_addresses: Bytes,
        fullnode_network_addresses: Bytes,
    },

    /// # Summary
    /// Sets the validator operator for a validator in the validator's configuration resource "locally"
    /// and does not reconfigure the system. Changes from this transaction will not picked up by the
    /// system until a reconfiguration of the system is triggered. May only be sent by an account with
    /// Validator role.
    ///
    /// # Technical Description
    /// Sets the account at `operator_account` address and with the specified `human_name` as an
    /// operator for the sending validator account. The account at `operator_account` address must have
    /// a Validator Operator role and have a `ValidatorOperatorConfig::ValidatorOperatorConfig`
    /// resource published under it. The sending `account` must be a Validator and have a
    /// `ValidatorConfig::ValidatorConfig` resource published under it. This script does not emit a
    /// `DiemConfig::NewEpochEvent` and no reconfiguration of the system is initiated by this script.
    ///
    /// # Parameters
    /// | Name               | Type         | Description                                                                                  |
    /// | ------             | ------       | -------------                                                                                |
    /// | `account`          | `signer`     | The signer of the sending account of the transaction.                                        |
    /// | `operator_name`    | `vector<u8>` | Validator operator's human name.                                                             |
    /// | `operator_account` | `address`    | Address of the validator operator account to be added as the `account` validator's operator. |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                          | Description                                                                                                                                                  |
    /// | ----------------           | --------------                                        | -------------                                                                                                                                                |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG` | The `ValidatorOperatorConfig::ValidatorOperatorConfig` resource is not published under `operator_account`.                                                   |
    /// | 0                          | 0                                                     | The `human_name` field of the `ValidatorOperatorConfig::ValidatorOperatorConfig` resource under `operator_account` does not match the provided `human_name`. |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR`                                   | `account` does not have a Validator account role.                                                                                                            |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR`          | The account at `operator_account` does not have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource.                                               |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`                  | A `ValidatorConfig::ValidatorConfig` is not published under `account`.                                                                                       |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_validator_account`
    /// * `AccountCreationScripts::create_validator_operator_account`
    /// * `ValidatorAdministrationScripts::register_validator_config`
    /// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
    /// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
    SetValidatorOperator {
        operator_name: Bytes,
        operator_account: AccountAddress,
    },

    /// # Summary
    /// Sets the validator operator for a validator in the validator's configuration resource "locally"
    /// and does not reconfigure the system. Changes from this transaction will not picked up by the
    /// system until a reconfiguration of the system is triggered. May only be sent by the Diem Root
    /// account as a write set transaction.
    ///
    /// # Technical Description
    /// Sets the account at `operator_account` address and with the specified `human_name` as an
    /// operator for the validator `account`. The account at `operator_account` address must have a
    /// Validator Operator role and have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource
    /// published under it. The account represented by the `account` signer must be a Validator and
    /// have a `ValidatorConfig::ValidatorConfig` resource published under it. No reconfiguration of
    /// the system is initiated by this script.
    ///
    /// # Parameters
    /// | Name               | Type         | Description                                                                                   |
    /// | ------             | ------       | -------------                                                                                 |
    /// | `dr_account`       | `signer`     | Signer of the sending account of the write set transaction. May only be the Diem Root signer. |
    /// | `account`          | `signer`     | Signer of account specified in the `execute_as` field of the write set transaction.           |
    /// | `sliding_nonce`    | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction for Diem Root.      |
    /// | `operator_name`    | `vector<u8>` | Validator operator's human name.                                                              |
    /// | `operator_account` | `address`    | Address of the validator operator account to be added as the `account` validator's operator.  |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                          | Description                                                                                                                                                  |
    /// | ----------------           | --------------                                        | -------------                                                                                                                                                |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                        | A `SlidingNonce` resource is not published under `dr_account`.                                                                                               |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                        | The `sliding_nonce` in `dr_account` is too old and it's impossible to determine if it's duplicated or not.                                                   |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                        | The `sliding_nonce` in `dr_account` is too far in the future.                                                                                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`               | The `sliding_nonce` in` dr_account` has been previously recorded.                                                                                            |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                        | The sending account is not the Diem Root account or Treasury Compliance account                                                                             |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG` | The `ValidatorOperatorConfig::ValidatorOperatorConfig` resource is not published under `operator_account`.                                                   |
    /// | 0                          | 0                                                     | The `human_name` field of the `ValidatorOperatorConfig::ValidatorOperatorConfig` resource under `operator_account` does not match the provided `human_name`. |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR`                                   | `account` does not have a Validator account role.                                                                                                            |
    /// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR`          | The account at `operator_account` does not have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource.                                               |
    /// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`                  | A `ValidatorConfig::ValidatorConfig` is not published under `account`.                                                                                       |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_validator_account`
    /// * `AccountCreationScripts::create_validator_operator_account`
    /// * `ValidatorAdministrationScripts::register_validator_config`
    /// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
    /// * `ValidatorAdministrationScripts::set_validator_operator`
    /// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
    SetValidatorOperatorWithNonceAdmin {
        sliding_nonce: u64,
        operator_name: Bytes,
        operator_account: AccountAddress,
    },

    SetWalletType {
        type_of: u8,
    },

    /// # Summary
    /// Mints a specified number of coins in a currency to a Designated Dealer. The sending account
    /// must be the Treasury Compliance account, and coins can only be minted to a Designated Dealer
    /// account.
    ///
    /// # Technical Description
    /// Mints `mint_amount` of coins in the `CoinType` currency to Designated Dealer account at
    /// `designated_dealer_address`. The `tier_index` parameter specifies which tier should be used to
    /// check verify the off-chain approval policy, and is based in part on the on-chain tier values
    /// for the specific Designated Dealer, and the number of `CoinType` coins that have been minted to
    /// the dealer over the past 24 hours. Every Designated Dealer has 4 tiers for each currency that
    /// they support. The sending `tc_account` must be the Treasury Compliance account, and the
    /// receiver an authorized Designated Dealer account.
    ///
    /// # Events
    /// Successful execution of the transaction will emit two events:
    /// * A `Diem::MintEvent` with the amount and currency code minted is emitted on the
    /// `mint_event_handle` in the stored `Diem::CurrencyInfo<CoinType>` resource stored under
    /// `0xA550C18`; and
    /// * A `DesignatedDealer::ReceivedMintEvent` with the amount, currency code, and Designated
    /// Dealer's address is emitted on the `mint_event_handle` in the stored `DesignatedDealer::Dealer`
    /// resource published under the `designated_dealer_address`.
    ///
    /// # Parameters
    /// | Name                        | Type      | Description                                                                                                |
    /// | ------                      | ------    | -------------                                                                                              |
    /// | `CoinType`                  | Type      | The Move type for the `CoinType` being minted. `CoinType` must be an already-registered currency on-chain. |
    /// | `tc_account`                | `signer`  | The signer of the sending account of this transaction. Must be the Treasury Compliance account.            |
    /// | `sliding_nonce`             | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                 |
    /// | `designated_dealer_address` | `address` | The address of the Designated Dealer account being minted to.                                              |
    /// | `mint_amount`               | `u64`     | The number of coins to be minted.                                                                          |
    /// | `tier_index`                | `u64`     | [Deprecated] The mint tier index to use for the Designated Dealer account. Will be ignored                 |
    ///
    /// # Common Abort Conditions
    /// | Error Category                | Error Reason                                 | Description                                                                                                                  |
    /// | ----------------              | --------------                               | -------------                                                                                                                |
    /// | `Errors::NOT_PUBLISHED`       | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `tc_account`.                                                               |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                   |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                                                                |
    /// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                                                            |
    /// | `Errors::REQUIRES_ADDRESS`    | `CoreAddresses::ETREASURY_COMPLIANCE`        | `tc_account` is not the Treasury Compliance account.                                                                         |
    /// | `Errors::REQUIRES_ROLE`       | `Roles::ETREASURY_COMPLIANCE`                | `tc_account` is not the Treasury Compliance account.                                                                         |
    /// | `Errors::INVALID_ARGUMENT`    | `DesignatedDealer::EINVALID_MINT_AMOUNT`     | `mint_amount` is zero.                                                                                                       |
    /// | `Errors::NOT_PUBLISHED`       | `DesignatedDealer::EDEALER`                  | `DesignatedDealer::Dealer` or `DesignatedDealer::TierInfo<CoinType>` resource does not exist at `designated_dealer_address`. |
    /// | `Errors::REQUIRES_CAPABILITY` | `Diem::EMINT_CAPABILITY`                    | `tc_account` does not have a `Diem::MintCapability<CoinType>` resource published under it.                                  |
    /// | `Errors::INVALID_STATE`       | `Diem::EMINTING_NOT_ALLOWED`                | Minting is not currently allowed for `CoinType` coins.                                                                       |
    /// | `Errors::LIMIT_EXCEEDED`      | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`      | The depositing of the funds would exceed the `account`'s account limits.                                                     |
    ///
    /// # Related Scripts
    /// * `AccountCreationScripts::create_designated_dealer`
    /// * `PaymentScripts::peer_to_peer_with_metadata`
    /// * `AccountAdministrationScripts::rotate_dual_attestation_info`
    TieredMint {
        coin_type: TypeTag,
        sliding_nonce: u64,
        designated_dealer_address: AccountAddress,
        mint_amount: u64,
        tier_index: u64,
    },

    /// # Summary
    /// Unfreezes the account at `address`. The sending account of this transaction must be the
    /// Treasury Compliance account. After the successful execution of this transaction transactions
    /// may be sent from the previously frozen account, and coins may be sent and received.
    ///
    /// # Technical Description
    /// Sets the `AccountFreezing::FreezingBit` to `false` and emits a
    /// `AccountFreezing::UnFreezeAccountEvent`. The transaction sender must be the Treasury Compliance
    /// account. Note that this is a per-account property so unfreezing a Parent VASP will not effect
    /// the status any of its child accounts and vice versa.
    ///
    /// # Events
    /// Successful execution of this script will emit a `AccountFreezing::UnFreezeAccountEvent` with
    /// the `unfrozen_address` set the `to_unfreeze_account`'s address.
    ///
    /// # Parameters
    /// | Name                  | Type      | Description                                                                                     |
    /// | ------                | ------    | -------------                                                                                   |
    /// | `tc_account`          | `signer`  | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
    /// | `sliding_nonce`       | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
    /// | `to_unfreeze_account` | `address` | The account address to be frozen.                                                               |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                            | Description                                                                                |
    /// | ----------------           | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::freeze_account`
    UnfreezeAccount {
        sliding_nonce: u64,
        to_unfreeze_account: AccountAddress,
    },

    /// # Summary
    /// Updates the Diem consensus config that is stored on-chain and is used by the Consensus.  This
    /// transaction can only be sent from the Diem Root account.
    ///
    /// # Technical Description
    /// Updates the `DiemConsensusConfig` on-chain config and emits a `DiemConfig::NewEpochEvent` to trigger
    /// a reconfiguration of the system.
    ///
    /// # Parameters
    /// | Name            | Type          | Description                                                                |
    /// | ------          | ------        | -------------                                                              |
    /// | `account`       | `signer`      | Signer of the sending account. Must be the Diem Root account.              |
    /// | `sliding_nonce` | `u64`         | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
    /// | `config`        | `vector<u8>`  | The serialized bytes of consensus config.                                  |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                  | Description                                                                                |
    /// | ----------------           | --------------                                | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                   | `account` is not the Diem Root account.                                                    |
    UpdateDiemConsensusConfig {
        sliding_nonce: u64,
        config: Bytes,
    },

    /// # Summary
    /// Updates the Diem major version that is stored on-chain and is used by the VM.  This
    /// transaction can only be sent from the Diem Root account.
    ///
    /// # Technical Description
    /// Updates the `DiemVersion` on-chain config and emits a `DiemConfig::NewEpochEvent` to trigger
    /// a reconfiguration of the system. The `major` version that is passed in must be strictly greater
    /// than the current major version held on-chain. The VM reads this information and can use it to
    /// preserve backwards compatibility with previous major versions of the VM.
    ///
    /// # Parameters
    /// | Name            | Type     | Description                                                                |
    /// | ------          | ------   | -------------                                                              |
    /// | `account`       | `signer` | Signer of the sending account. Must be the Diem Root account.              |
    /// | `sliding_nonce` | `u64`    | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
    /// | `major`         | `u64`    | The `major` version of the VM to be used from this transaction on.         |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                                  | Description                                                                                |
    /// | ----------------           | --------------                                | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `account`.                                |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                   | `account` is not the Diem Root account.                                                    |
    /// | `Errors::INVALID_ARGUMENT` | `DiemVersion::EINVALID_MAJOR_VERSION_NUMBER`  | `major` is less-than or equal to the current major version stored on-chain.                |
    UpdateDiemVersion {
        sliding_nonce: u64,
        major: u64,
    },

    /// # Summary
    /// Update the dual attestation limit on-chain. Defined in terms of micro-XDX.  The transaction can
    /// only be sent by the Treasury Compliance account.  After this transaction all inter-VASP
    /// payments over this limit must be checked for dual attestation.
    ///
    /// # Technical Description
    /// Updates the `micro_xdx_limit` field of the `DualAttestation::Limit` resource published under
    /// `0xA550C18`. The amount is set in micro-XDX.
    ///
    /// # Parameters
    /// | Name                  | Type     | Description                                                                                     |
    /// | ------                | ------   | -------------                                                                                   |
    /// | `tc_account`          | `signer` | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
    /// | `sliding_nonce`       | `u64`    | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
    /// | `new_micro_xdx_limit` | `u64`    | The new dual attestation limit to be used on-chain.                                             |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                            | Description                                                                                |
    /// | ----------------           | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | `tc_account` is not the Treasury Compliance account.                                       |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::update_exchange_rate`
    /// * `TreasuryComplianceScripts::update_minting_ability`
    UpdateDualAttestationLimit {
        sliding_nonce: u64,
        new_micro_xdx_limit: u64,
    },

    /// # Summary
    /// Update the rough on-chain exchange rate between a specified currency and XDX (as a conversion
    /// to micro-XDX). The transaction can only be sent by the Treasury Compliance account. After this
    /// transaction the updated exchange rate will be used for normalization of gas prices, and for
    /// dual attestation checking.
    ///
    /// # Technical Description
    /// Updates the on-chain exchange rate from the given `Currency` to micro-XDX.  The exchange rate
    /// is given by `new_exchange_rate_numerator/new_exchange_rate_denominator`.
    ///
    /// # Parameters
    /// | Name                            | Type     | Description                                                                                                                        |
    /// | ------                          | ------   | -------------                                                                                                                      |
    /// | `Currency`                      | Type     | The Move type for the `Currency` whose exchange rate is being updated. `Currency` must be an already-registered currency on-chain. |
    /// | `dm_account`                    | `signer` | The signer of the sending account of this transaction. Must be the Treasury Compliance account.                                    |
    /// | `sliding_nonce`                 | `u64`    | The `sliding_nonce` (see: `SlidingNonce`) to be used for the transaction.                                                          |
    /// | `new_exchange_rate_numerator`   | `u64`    | The numerator for the new to micro-XDX exchange rate for `Currency`.                                                               |
    /// | `new_exchange_rate_denominator` | `u64`    | The denominator for the new to micro-XDX exchange rate for `Currency`.                                                             |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                            | Description                                                                                |
    /// | ----------------           | --------------                          | -------------                                                                              |
    /// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dm_account`.                             |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
    /// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | `dm_account` is not the Treasury Compliance account.                                       |
    /// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`           | `dm_account` is not the Treasury Compliance account.                                       |
    /// | `Errors::INVALID_ARGUMENT` | `FixedPoint32::EDENOMINATOR`            | `new_exchange_rate_denominator` is zero.                                                   |
    /// | `Errors::INVALID_ARGUMENT` | `FixedPoint32::ERATIO_OUT_OF_RANGE`     | The quotient is unrepresentable as a `FixedPoint32`.                                       |
    /// | `Errors::LIMIT_EXCEEDED`   | `FixedPoint32::ERATIO_OUT_OF_RANGE`     | The quotient is unrepresentable as a `FixedPoint32`.                                       |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::update_dual_attestation_limit`
    /// * `TreasuryComplianceScripts::update_minting_ability`
    UpdateExchangeRate {
        currency: TypeTag,
        sliding_nonce: u64,
        new_exchange_rate_numerator: u64,
        new_exchange_rate_denominator: u64,
    },

    /// # Summary
    /// Script to allow or disallow minting of new coins in a specified currency.  This transaction can
    /// only be sent by the Treasury Compliance account.  Turning minting off for a currency will have
    /// no effect on coins already in circulation, and coins may still be removed from the system.
    ///
    /// # Technical Description
    /// This transaction sets the `can_mint` field of the `Diem::CurrencyInfo<Currency>` resource
    /// published under `0xA550C18` to the value of `allow_minting`. Minting of coins if allowed if
    /// this field is set to `true` and minting of new coins in `Currency` is disallowed otherwise.
    /// This transaction needs to be sent by the Treasury Compliance account.
    ///
    /// # Parameters
    /// | Name            | Type     | Description                                                                                                                          |
    /// | ------          | ------   | -------------                                                                                                                        |
    /// | `Currency`      | Type     | The Move type for the `Currency` whose minting ability is being updated. `Currency` must be an already-registered currency on-chain. |
    /// | `account`       | `signer` | Signer of the sending account. Must be the Diem Root account.                                                                        |
    /// | `allow_minting` | `bool`   | Whether to allow minting of new coins in `Currency`.                                                                                 |
    ///
    /// # Common Abort Conditions
    /// | Error Category             | Error Reason                          | Description                                          |
    /// | ----------------           | --------------                        | -------------                                        |
    /// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE` | `tc_account` is not the Treasury Compliance account. |
    /// | `Errors::NOT_PUBLISHED`    | `Diem::ECURRENCY_INFO`               | `Currency` is not a registered currency on-chain.    |
    ///
    /// # Related Scripts
    /// * `TreasuryComplianceScripts::update_dual_attestation_limit`
    /// * `TreasuryComplianceScripts::update_exchange_rate`
    UpdateMintingAbility {
        currency: TypeTag,
        allow_minting: bool,
    },

    ValAddSelf {},
}

impl ScriptCall {
    /// Build a Diem `Script` from a structured object `ScriptCall`.
    pub fn encode(self) -> Script {
        use ScriptCall::*;
        match self {
            AddCurrencyToAccount { currency } => encode_add_currency_to_account_script(currency),
            AddRecoveryRotationCapability { recovery_address } => {
                encode_add_recovery_rotation_capability_script(recovery_address)
            }
            AddValidatorAndReconfigure {
                sliding_nonce,
                validator_name,
                validator_address,
            } => encode_add_validator_and_reconfigure_script(
                sliding_nonce,
                validator_name,
                validator_address,
            ),
            Burn {
                token,
                sliding_nonce,
                preburn_address,
            } => encode_burn_script(token, sliding_nonce, preburn_address),
            BurnTxnFees { coin_type } => encode_burn_txn_fees_script(coin_type),
            CancelBurn {
                token,
                preburn_address,
            } => encode_cancel_burn_script(token, preburn_address),
            CreateChildVaspAccount {
                coin_type,
                child_address,
                auth_key_prefix,
                add_all_currencies,
                child_initial_balance,
            } => encode_create_child_vasp_account_script(
                coin_type,
                child_address,
                auth_key_prefix,
                add_all_currencies,
                child_initial_balance,
            ),
            CreateDesignatedDealer {
                currency,
                sliding_nonce,
                addr,
                auth_key_prefix,
                human_name,
                add_all_currencies,
            } => encode_create_designated_dealer_script(
                currency,
                sliding_nonce,
                addr,
                auth_key_prefix,
                human_name,
                add_all_currencies,
            ),
            CreateParentVaspAccount {
                coin_type,
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
                add_all_currencies,
            } => encode_create_parent_vasp_account_script(
                coin_type,
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
                add_all_currencies,
            ),
            CreateRecoveryAddress {} => encode_create_recovery_address_script(),
            CreateValidatorAccount {
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
            } => encode_create_validator_account_script(
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
            ),
            CreateValidatorOperatorAccount {
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
            } => encode_create_validator_operator_account_script(
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
            ),
            FreezeAccount {
                sliding_nonce,
                to_freeze_account,
            } => encode_freeze_account_script(sliding_nonce, to_freeze_account),
            PeerToPeerWithMetadata {
                currency,
                payee,
                amount,
                metadata,
                metadata_signature,
            } => encode_peer_to_peer_with_metadata_script(
                currency,
                payee,
                amount,
                metadata,
                metadata_signature,
            ),
            Preburn { token, amount } => encode_preburn_script(token, amount),
            PublishSharedEd25519PublicKey { public_key } => {
                encode_publish_shared_ed25519_public_key_script(public_key)
            }
            RegisterValidatorConfig {
                validator_account,
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
            } => encode_register_validator_config_script(
                validator_account,
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
            ),
            RemoveValidatorAndReconfigure {
                sliding_nonce,
                validator_name,
                validator_address,
            } => encode_remove_validator_and_reconfigure_script(
                sliding_nonce,
                validator_name,
                validator_address,
            ),
            RotateAuthenticationKey { new_key } => encode_rotate_authentication_key_script(new_key),
            RotateAuthenticationKeyWithNonce {
                sliding_nonce,
                new_key,
            } => encode_rotate_authentication_key_with_nonce_script(sliding_nonce, new_key),
            RotateAuthenticationKeyWithNonceAdmin {
                sliding_nonce,
                new_key,
            } => encode_rotate_authentication_key_with_nonce_admin_script(sliding_nonce, new_key),
            RotateAuthenticationKeyWithRecoveryAddress {
                recovery_address,
                to_recover,
                new_key,
            } => encode_rotate_authentication_key_with_recovery_address_script(
                recovery_address,
                to_recover,
                new_key,
            ),
            RotateDualAttestationInfo { new_url, new_key } => {
                encode_rotate_dual_attestation_info_script(new_url, new_key)
            }
            RotateSharedEd25519PublicKey { public_key } => {
                encode_rotate_shared_ed25519_public_key_script(public_key)
            }
            SetValidatorConfigAndReconfigure {
                validator_account,
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
            } => encode_set_validator_config_and_reconfigure_script(
                validator_account,
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
            ),
            SetValidatorOperator {
                operator_name,
                operator_account,
            } => encode_set_validator_operator_script(operator_name, operator_account),
            SetValidatorOperatorWithNonceAdmin {
                sliding_nonce,
                operator_name,
                operator_account,
            } => encode_set_validator_operator_with_nonce_admin_script(
                sliding_nonce,
                operator_name,
                operator_account,
            ),
            TieredMint {
                coin_type,
                sliding_nonce,
                designated_dealer_address,
                mint_amount,
                tier_index,
            } => encode_tiered_mint_script(
                coin_type,
                sliding_nonce,
                designated_dealer_address,
                mint_amount,
                tier_index,
            ),
            UnfreezeAccount {
                sliding_nonce,
                to_unfreeze_account,
            } => encode_unfreeze_account_script(sliding_nonce, to_unfreeze_account),
            UpdateDiemVersion {
                sliding_nonce,
                major,
            } => encode_update_diem_version_script(sliding_nonce, major),
            UpdateDualAttestationLimit {
                sliding_nonce,
                new_micro_xdx_limit,
            } => encode_update_dual_attestation_limit_script(sliding_nonce, new_micro_xdx_limit),
            UpdateExchangeRate {
                currency,
                sliding_nonce,
                new_exchange_rate_numerator,
                new_exchange_rate_denominator,
            } => encode_update_exchange_rate_script(
                currency,
                sliding_nonce,
                new_exchange_rate_numerator,
                new_exchange_rate_denominator,
            ),
            UpdateMintingAbility {
                currency,
                allow_minting,
            } => encode_update_minting_ability_script(currency, allow_minting),
        }
    }

    /// Try to recognize a Diem `Script` and convert it into a structured object `ScriptCall`.
    pub fn decode(script: &Script) -> Option<ScriptCall> {
        match TRANSACTION_SCRIPT_DECODER_MAP.get(script.code()) {
            Some(decoder) => decoder(script),
            None => None,
        }
    }

    /// Return the name of a Diem `Script` from a structured object `ScriptCall`.
    pub fn name(&self) -> &'static str {
        use ScriptCall::*;
        match self {
            AddCurrencyToAccount { .. } => "add_currency_to_account",
            AddRecoveryRotationCapability { .. } => "add_recovery_rotation_capability",
            AddValidatorAndReconfigure { .. } => "add_validator_and_reconfigure",
            Burn { .. } => "burn",
            BurnTxnFees { .. } => "burn_txn_fees",
            CancelBurn { .. } => "cancel_burn",
            CreateChildVaspAccount { .. } => "create_child_vasp_account",
            CreateDesignatedDealer { .. } => "create_designated_dealer",
            CreateParentVaspAccount { .. } => "create_parent_vasp_account",
            CreateRecoveryAddress { .. } => "create_recovery_address",
            CreateValidatorAccount { .. } => "create_validator_account",
            CreateValidatorOperatorAccount { .. } => "create_validator_operator_account",
            FreezeAccount { .. } => "freeze_account",
            PeerToPeerWithMetadata { .. } => "peer_to_peer_with_metadata",
            Preburn { .. } => "preburn",
            PublishSharedEd25519PublicKey { .. } => "publish_shared_ed25519_public_key",
            RegisterValidatorConfig { .. } => "register_validator_config",
            RemoveValidatorAndReconfigure { .. } => "remove_validator_and_reconfigure",
            RotateAuthenticationKey { .. } => "rotate_authentication_key",
            RotateAuthenticationKeyWithNonce { .. } => "rotate_authentication_key_with_nonce",
            RotateAuthenticationKeyWithNonceAdmin { .. } => {
                "rotate_authentication_key_with_nonce_admin"
            }
            RotateAuthenticationKeyWithRecoveryAddress { .. } => {
                "rotate_authentication_key_with_recovery_address"
            }
            RotateDualAttestationInfo { .. } => "rotate_dual_attestation_info",
            RotateSharedEd25519PublicKey { .. } => "rotate_shared_ed25519_public_key",
            SetValidatorConfigAndReconfigure { .. } => "set_validator_config_and_reconfigure",
            SetValidatorOperator { .. } => "set_validator_operator",
            SetValidatorOperatorWithNonceAdmin { .. } => "set_validator_operator_with_nonce_admin",
            TieredMint { .. } => "tiered_mint",
            UnfreezeAccount { .. } => "unfreeze_account",
            UpdateDiemVersion { .. } => "update_diem_version",
            UpdateDualAttestationLimit { .. } => "update_dual_attestation_limit",
            UpdateExchangeRate { .. } => "update_exchange_rate",
            UpdateMintingAbility { .. } => "update_minting_ability",
        }
    }
}

impl ScriptFunctionCall {
    /// Build a Diem `TransactionPayload` from a structured object `ScriptFunctionCall`.
    pub fn encode(self) -> TransactionPayload {
        use ScriptFunctionCall::*;
        match self {
            AddCurrencyToAccount { currency } => {
                encode_add_currency_to_account_script_function(currency)
            }
            AddDiemIdDomain { address, domain } => {
                encode_add_diem_id_domain_script_function(address, domain)
            }
            AddRecoveryRotationCapability { recovery_address } => {
                encode_add_recovery_rotation_capability_script_function(recovery_address)
            }
            AddValidatorAndReconfigure {
                sliding_nonce,
                validator_name,
                validator_address,
            } => encode_add_validator_and_reconfigure_script_function(
                sliding_nonce,
                validator_name,
                validator_address,
            ),
            AutopayCreateInstruction {
                uid,
                in_type,
                payee,
                end_epoch,
                value,
            } => encode_autopay_create_instruction_script_function(
                uid, in_type, payee, end_epoch, value,
            ),
            AutopayDisable {} => encode_autopay_disable_script_function(),
            AutopayEnable {} => encode_autopay_enable_script_function(),
            BurnTxnFees { coin_type } => encode_burn_txn_fees_script_function(coin_type),
            BurnWithAmount {
                token,
                sliding_nonce,
                preburn_address,
                amount,
            } => encode_burn_with_amount_script_function(
                token,
                sliding_nonce,
                preburn_address,
                amount,
            ),
            CancelBurnWithAmount {
                token,
                preburn_address,
                amount,
            } => encode_cancel_burn_with_amount_script_function(token, preburn_address, amount),
            CreateAccUser {
                challenge,
                solution,
            } => encode_create_acc_user_script_function(challenge, solution),
            CreateAccVal {
                challenge,
                solution,
                ow_human_name,
                op_address,
                op_auth_key_prefix,
                op_consensus_pubkey,
                op_validator_network_addresses,
                op_fullnode_network_addresses,
                op_human_name,
            } => encode_create_acc_val_script_function(
                challenge,
                solution,
                ow_human_name,
                op_address,
                op_auth_key_prefix,
                op_consensus_pubkey,
                op_validator_network_addresses,
                op_fullnode_network_addresses,
                op_human_name,
            ),
            CreateChildVaspAccount {
                coin_type,
                child_address,
                auth_key_prefix,
                add_all_currencies,
                child_initial_balance,
            } => encode_create_child_vasp_account_script_function(
                coin_type,
                child_address,
                auth_key_prefix,
                add_all_currencies,
                child_initial_balance,
            ),
            CreateDesignatedDealer {
                currency,
                sliding_nonce,
                addr,
                auth_key_prefix,
                human_name,
                add_all_currencies,
            } => encode_create_designated_dealer_script_function(
                currency,
                sliding_nonce,
                addr,
                auth_key_prefix,
                human_name,
                add_all_currencies,
            ),
            CreateDiemIdDomains {} => encode_create_diem_id_domains_script_function(),
            CreateParentVaspAccount {
                coin_type,
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
                add_all_currencies,
            } => encode_create_parent_vasp_account_script_function(
                coin_type,
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
                add_all_currencies,
            ),
            CreateRecoveryAddress {} => encode_create_recovery_address_script_function(),
            CreateValidatorAccount {
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
            } => encode_create_validator_account_script_function(
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
            ),
            CreateValidatorOperatorAccount {
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
            } => encode_create_validator_operator_account_script_function(
                sliding_nonce,
                new_account_address,
                auth_key_prefix,
                human_name,
            ),
            DemoE2e { world } => encode_demo_e2e_script_function(world),
            FreezeAccount {
                sliding_nonce,
                to_freeze_account,
            } => encode_freeze_account_script_function(sliding_nonce, to_freeze_account),
            InitializeDiemConsensusConfig { sliding_nonce } => {
                encode_initialize_diem_consensus_config_script_function(sliding_nonce)
            }
            Join {} => encode_join_script_function(),
            Leave {} => encode_leave_script_function(),
            MinerstateCommit {
                challenge,
                solution,
            } => encode_minerstate_commit_script_function(challenge, solution),
            MinerstateCommitByOperator {
                owner_address,
                challenge,
                solution,
            } => encode_minerstate_commit_by_operator_script_function(
                owner_address,
                challenge,
                solution,
            ),
            MinerstateHelper {} => encode_minerstate_helper_script_function(),
            OlOracleTx { id, data } => encode_ol_oracle_tx_script_function(id, data),
            OlReconfigBulkUpdateSetup {
                alice,
                bob,
                carol,
                sha,
                ram,
            } => encode_ol_reconfig_bulk_update_setup_script_function(alice, bob, carol, sha, ram),
            PeerToPeerWithMetadata {
                currency,
                payee,
                amount,
                metadata,
                metadata_signature,
            } => encode_peer_to_peer_with_metadata_script_function(
                currency,
                payee,
                amount,
                metadata,
                metadata_signature,
            ),
            Preburn { token, amount } => encode_preburn_script_function(token, amount),
            PublishSharedEd25519PublicKey { public_key } => {
                encode_publish_shared_ed25519_public_key_script_function(public_key)
            }
            RegisterValidatorConfig {
                validator_account,
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
            } => encode_register_validator_config_script_function(
                validator_account,
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
            ),
            RemoveDiemIdDomain { address, domain } => {
                encode_remove_diem_id_domain_script_function(address, domain)
            }
            RemoveValidatorAndReconfigure {
                sliding_nonce,
                validator_name,
                validator_address,
            } => encode_remove_validator_and_reconfigure_script_function(
                sliding_nonce,
                validator_name,
                validator_address,
            ),
            RotateAuthenticationKey { new_key } => {
                encode_rotate_authentication_key_script_function(new_key)
            }
            RotateAuthenticationKeyWithNonce {
                sliding_nonce,
                new_key,
            } => {
                encode_rotate_authentication_key_with_nonce_script_function(sliding_nonce, new_key)
            }
            RotateAuthenticationKeyWithNonceAdmin {
                sliding_nonce,
                new_key,
            } => encode_rotate_authentication_key_with_nonce_admin_script_function(
                sliding_nonce,
                new_key,
            ),
            RotateAuthenticationKeyWithRecoveryAddress {
                recovery_address,
                to_recover,
                new_key,
            } => encode_rotate_authentication_key_with_recovery_address_script_function(
                recovery_address,
                to_recover,
                new_key,
            ),
            RotateDualAttestationInfo { new_url, new_key } => {
                encode_rotate_dual_attestation_info_script_function(new_url, new_key)
            }
            RotateSharedEd25519PublicKey { public_key } => {
                encode_rotate_shared_ed25519_public_key_script_function(public_key)
            }
            SetGasConstants {
                sliding_nonce,
                global_memory_per_byte_cost,
                global_memory_per_byte_write_cost,
                min_transaction_gas_units,
                large_transaction_cutoff,
                intrinsic_gas_per_byte,
                maximum_number_of_gas_units,
                min_price_per_gas_unit,
                max_price_per_gas_unit,
                max_transaction_size_in_bytes,
                gas_unit_scaling_factor,
                default_account_size,
            } => encode_set_gas_constants_script_function(
                sliding_nonce,
                global_memory_per_byte_cost,
                global_memory_per_byte_write_cost,
                min_transaction_gas_units,
                large_transaction_cutoff,
                intrinsic_gas_per_byte,
                maximum_number_of_gas_units,
                min_price_per_gas_unit,
                max_price_per_gas_unit,
                max_transaction_size_in_bytes,
                gas_unit_scaling_factor,
                default_account_size,
            ),
            SetValidatorConfigAndReconfigure {
                validator_account,
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
            } => encode_set_validator_config_and_reconfigure_script_function(
                validator_account,
                consensus_pubkey,
                validator_network_addresses,
                fullnode_network_addresses,
            ),
            SetValidatorOperator {
                operator_name,
                operator_account,
            } => encode_set_validator_operator_script_function(operator_name, operator_account),
            SetValidatorOperatorWithNonceAdmin {
                sliding_nonce,
                operator_name,
                operator_account,
            } => encode_set_validator_operator_with_nonce_admin_script_function(
                sliding_nonce,
                operator_name,
                operator_account,
            ),
            SetWalletType { type_of } => encode_set_wallet_type_script_function(type_of),
            TieredMint {
                coin_type,
                sliding_nonce,
                designated_dealer_address,
                mint_amount,
                tier_index,
            } => encode_tiered_mint_script_function(
                coin_type,
                sliding_nonce,
                designated_dealer_address,
                mint_amount,
                tier_index,
            ),
            UnfreezeAccount {
                sliding_nonce,
                to_unfreeze_account,
            } => encode_unfreeze_account_script_function(sliding_nonce, to_unfreeze_account),
            UpdateDiemConsensusConfig {
                sliding_nonce,
                config,
            } => encode_update_diem_consensus_config_script_function(sliding_nonce, config),
            UpdateDiemVersion {
                sliding_nonce,
                major,
            } => encode_update_diem_version_script_function(sliding_nonce, major),
            UpdateDualAttestationLimit {
                sliding_nonce,
                new_micro_xdx_limit,
            } => encode_update_dual_attestation_limit_script_function(
                sliding_nonce,
                new_micro_xdx_limit,
            ),
            UpdateExchangeRate {
                currency,
                sliding_nonce,
                new_exchange_rate_numerator,
                new_exchange_rate_denominator,
            } => encode_update_exchange_rate_script_function(
                currency,
                sliding_nonce,
                new_exchange_rate_numerator,
                new_exchange_rate_denominator,
            ),
            UpdateMintingAbility {
                currency,
                allow_minting,
            } => encode_update_minting_ability_script_function(currency, allow_minting),
            ValAddSelf {} => encode_val_add_self_script_function(),
        }
    }

    /// Try to recognize a Diem `TransactionPayload` and convert it into a structured object `ScriptFunctionCall`.
    pub fn decode(payload: &TransactionPayload) -> Option<ScriptFunctionCall> {
        if let TransactionPayload::ScriptFunction(script) = payload {
            match SCRIPT_FUNCTION_DECODER_MAP.get(&format!(
                "{}{}",
                script.module().name(),
                script.function()
            )) {
                Some(decoder) => decoder(payload),
                None => None,
            }
        } else {
            None
        }
    }
}

/// # Summary
/// Adds a zero `Currency` balance to the sending `account`. This will enable `account` to
/// send, receive, and hold `Diem::Diem<Currency>` coins. This transaction can be
/// successfully sent by any account that is allowed to hold balances
/// (e.g., VASP, Designated Dealer).
///
/// # Technical Description
/// After the successful execution of this transaction the sending account will have a
/// `DiemAccount::Balance<Currency>` resource with zero balance published under it. Only
/// accounts that can hold balances can send this transaction, the sending account cannot
/// already have a `DiemAccount::Balance<Currency>` published under it.
///
/// # Parameters
/// | Name       | Type     | Description                                                                                                                                         |
/// | ------     | ------   | -------------                                                                                                                                       |
/// | `Currency` | Type     | The Move type for the `Currency` being added to the sending account of the transaction. `Currency` must be an already-registered currency on-chain. |
/// | `account`  | `signer` | The signer of the sending account of the transaction.                                                                                               |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                             | Description                                                                |
/// | ----------------            | --------------                           | -------------                                                              |
/// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                  | The `Currency` is not a registered currency on-chain.                      |
/// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::EROLE_CANT_STORE_BALANCE` | The sending `account`'s role does not permit balances.                     |
/// | `Errors::ALREADY_PUBLISHED` | `DiemAccount::EADD_EXISTING_CURRENCY`   | A balance for `Currency` is already published under the sending `account`. |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_child_vasp_account`
/// * `AccountCreationScripts::create_parent_vasp_account`
/// * `PaymentScripts::peer_to_peer_with_metadata`
pub fn encode_add_currency_to_account_script_function(currency: TypeTag) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("add_currency_to_account").to_owned(),
        vec![currency],
        vec![],
    ))
}

/// # Summary
/// Add a DiemID domain to parent VASP account. The transaction can only be sent by
/// the Treasury Compliance account.
///
/// # Technical Description
/// Adds a `DiemId::DiemIdDomain` to the `domains` field of the `DiemId::DiemIdDomains` resource published under
/// the account at `address`.
///
/// # Parameters
/// | Name         | Type         | Description                                                                                     |
/// | ------       | ------       | -------------                                                                                   |
/// | `tc_account` | `signer`     | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
/// | `address`    | `address`    | The `address` of the parent VASP account that will have have `domain` added to its domains.     |
/// | `domain`     | `vector<u8>` | The domain to be added.                                                                         |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                             | Description                                                                                                                            |
/// | ----------------           | --------------                           | -------------                                                                                                                          |
/// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`            | The sending account is not the Treasury Compliance account.                                                                            |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`    | `tc_account` is not the Treasury Compliance account.                                                                                   |
/// | `Errors::NOT_PUBLISHED`    | `DiemId::EDIEM_ID_DOMAIN_MANAGER`        | The `DiemId::DiemIdDomainManager` resource is not yet published under the Treasury Compliance account.                                 |
/// | `Errors::NOT_PUBLISHED`    | `DiemId::EDIEM_ID_DOMAINS_NOT_PUBLISHED` | `address` does not have a `DiemId::DiemIdDomains` resource published under it.                                                         |
/// | `Errors::INVALID_ARGUMENT` | `DiemId::EDOMAIN_ALREADY_EXISTS`         | The `domain` already exists in the list of `DiemId::DiemIdDomain`s  in the `DiemId::DiemIdDomains` resource published under `address`. |
/// | `Errors::INVALID_ARGUMENT` | `DiemId::EINVALID_DIEM_ID_DOMAIN`        | The `domain` is greater in length than `DiemId::DOMAIN_LENGTH`.                                                                        |
pub fn encode_add_diem_id_domain_script_function(
    address: AccountAddress,
    domain: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("add_diem_id_domain").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&address).unwrap(),
            bcs::to_bytes(&domain).unwrap(),
        ],
    ))
}

/// # Summary
/// Stores the sending accounts ability to rotate its authentication key with a designated recovery
/// account. Both the sending and recovery accounts need to belong to the same VASP and
/// both be VASP accounts. After this transaction both the sending account and the
/// specified recovery account can rotate the sender account's authentication key.
///
/// # Technical Description
/// Adds the `DiemAccount::KeyRotationCapability` for the sending account
/// (`to_recover_account`) to the `RecoveryAddress::RecoveryAddress` resource under
/// `recovery_address`. After this transaction has been executed successfully the account at
/// `recovery_address` and the `to_recover_account` may rotate the authentication key of
/// `to_recover_account` (the sender of this transaction).
///
/// The sending account of this transaction (`to_recover_account`) must not have previously given away its unique key
/// rotation capability, and must be a VASP account. The account at `recovery_address`
/// must also be a VASP account belonging to the same VASP as the `to_recover_account`.
/// Additionally the account at `recovery_address` must have already initialized itself as
/// a recovery account address using the `AccountAdministrationScripts::create_recovery_address` transaction script.
///
/// The sending account's (`to_recover_account`) key rotation capability is
/// removed in this transaction and stored in the `RecoveryAddress::RecoveryAddress`
/// resource stored under the account at `recovery_address`.
///
/// # Parameters
/// | Name                 | Type      | Description                                                                                               |
/// | ------               | ------    | -------------                                                                                             |
/// | `to_recover_account` | `signer`  | The signer of the sending account of this transaction.                                                    |
/// | `recovery_address`   | `address` | The account address where the `to_recover_account`'s `DiemAccount::KeyRotationCapability` will be stored. |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                              | Description                                                                                       |
/// | ----------------           | --------------                                            | -------------                                                                                     |
/// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `to_recover_account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.    |
/// | `Errors::NOT_PUBLISHED`    | `RecoveryAddress::ERECOVERY_ADDRESS`                      | `recovery_address` does not have a `RecoveryAddress` resource published under it.                 |
/// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::EINVALID_KEY_ROTATION_DELEGATION`       | `to_recover_account` and `recovery_address` do not belong to the same VASP.                       |
/// | `Errors::LIMIT_EXCEEDED`   | ` RecoveryAddress::EMAX_KEYS_REGISTERED`                  | `RecoveryAddress::MAX_REGISTERED_KEYS` have already been registered with this `recovery_address`. |
///
/// # Related Scripts
/// * `AccountAdministrationScripts::create_recovery_address`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_recovery_address`
pub fn encode_add_recovery_rotation_capability_script_function(
    recovery_address: AccountAddress,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("add_recovery_rotation_capability").to_owned(),
        vec![],
        vec![bcs::to_bytes(&recovery_address).unwrap()],
    ))
}

/// # Summary
/// Adds a validator account to the validator set, and triggers a
/// reconfiguration of the system to admit the account to the validator set for the system. This
/// transaction can only be successfully called by the Diem Root account.
///
/// # Technical Description
/// This script adds the account at `validator_address` to the validator set.
/// This transaction emits a `DiemConfig::NewEpochEvent` event and triggers a
/// reconfiguration. Once the reconfiguration triggered by this script's
/// execution has been performed, the account at the `validator_address` is
/// considered to be a validator in the network.
///
/// This transaction script will fail if the `validator_address` address is already in the validator set
/// or does not have a `ValidatorConfig::ValidatorConfig` resource already published under it.
///
/// # Parameters
/// | Name                | Type         | Description                                                                                                                        |
/// | ------              | ------       | -------------                                                                                                                      |
/// | `dr_account`        | `signer`     | The signer of the sending account of this transaction. Must be the Diem Root signer.                                               |
/// | `sliding_nonce`     | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                         |
/// | `validator_name`    | `vector<u8>` | ASCII-encoded human name for the validator. Must match the human name in the `ValidatorConfig::ValidatorConfig` for the validator. |
/// | `validator_address` | `address`    | The validator account address to be added to the validator set.                                                                    |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                 | Description                                                                                                                               |
/// | ----------------           | --------------                               | -------------                                                                                                                             |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `dr_account`.                                                                            |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                                                                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                                                                         |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                  | The sending account is not the Diem Root account.                                                                                         |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EDIEM_ROOT`                          | The sending account is not the Diem Root account.                                                                                         |
/// | 0                          | 0                                            | The provided `validator_name` does not match the already-recorded human name for the validator.                                           |
/// | `Errors::INVALID_ARGUMENT` | `DiemSystem::EINVALID_PROSPECTIVE_VALIDATOR` | The validator to be added does not have a `ValidatorConfig::ValidatorConfig` resource published under it, or its `config` field is empty. |
/// | `Errors::INVALID_ARGUMENT` | `DiemSystem::EALREADY_A_VALIDATOR`           | The `validator_address` account is already a registered validator.                                                                        |
/// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`            | An invalid time value was encountered in reconfiguration. Unlikely to occur.                                                              |
/// | `Errors::LIMIT_EXCEEDED`   | `DiemSystem::EMAX_VALIDATORS`                | The validator set is already at its maximum size. The validator could not be added.                                                       |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_validator_account`
/// * `AccountCreationScripts::create_validator_operator_account`
/// * `ValidatorAdministrationScripts::register_validator_config`
/// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::set_validator_operator`
/// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
/// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
pub fn encode_add_validator_and_reconfigure_script_function(
    sliding_nonce: u64,
    validator_name: Vec<u8>,
    validator_address: AccountAddress,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorAdministrationScripts").to_owned(),
        ),
        ident_str!("add_validator_and_reconfigure").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&validator_name).unwrap(),
            bcs::to_bytes(&validator_address).unwrap(),
        ],
    ))
}

pub fn encode_autopay_create_instruction_script_function(
    uid: u64,
    in_type: u8,
    payee: AccountAddress,
    end_epoch: u64,
    value: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AutoPayScripts").to_owned(),
        ),
        ident_str!("autopay_create_instruction").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&uid).unwrap(),
            bcs::to_bytes(&in_type).unwrap(),
            bcs::to_bytes(&payee).unwrap(),
            bcs::to_bytes(&end_epoch).unwrap(),
            bcs::to_bytes(&value).unwrap(),
        ],
    ))
}

pub fn encode_autopay_disable_script_function() -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AutoPayScripts").to_owned(),
        ),
        ident_str!("autopay_disable").to_owned(),
        vec![],
        vec![],
    ))
}

pub fn encode_autopay_enable_script_function() -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AutoPayScripts").to_owned(),
        ),
        ident_str!("autopay_enable").to_owned(),
        vec![],
        vec![],
    ))
}

/// # Summary
/// Burns the transaction fees collected in the `CoinType` currency so that the
/// Diem association may reclaim the backing coins off-chain. May only be sent
/// by the Treasury Compliance account.
///
/// # Technical Description
/// Burns the transaction fees collected in `CoinType` so that the
/// association may reclaim the backing coins. Once this transaction has executed
/// successfully all transaction fees that will have been collected in
/// `CoinType` since the last time this script was called with that specific
/// currency. Both `balance` and `preburn` fields in the
/// `TransactionFee::TransactionFee<CoinType>` resource published under the `0xB1E55ED`
/// account address will have a value of 0 after the successful execution of this script.
///
/// # Events
/// The successful execution of this transaction will emit a `Diem::BurnEvent` on the event handle
/// held in the `Diem::CurrencyInfo<CoinType>` resource's `burn_events` published under
/// `0xA550C18`.
///
/// # Parameters
/// | Name         | Type     | Description                                                                                                                                         |
/// | ------       | ------   | -------------                                                                                                                                       |
/// | `CoinType`   | Type     | The Move type for the `CoinType` being added to the sending account of the transaction. `CoinType` must be an already-registered currency on-chain. |
/// | `tc_account` | `signer` | The signer of the sending account of this transaction. Must be the Treasury Compliance account.                                                     |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                          | Description                                                 |
/// | ----------------           | --------------                        | -------------                                               |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE` | The sending account is not the Treasury Compliance account. |
/// | `Errors::NOT_PUBLISHED`    | `TransactionFee::ETRANSACTION_FEE`    | `CoinType` is not an accepted transaction fee currency.     |
/// | `Errors::INVALID_ARGUMENT` | `Diem::ECOIN`                        | The collected fees in `CoinType` are zero.                  |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::burn_with_amount`
/// * `TreasuryComplianceScripts::cancel_burn_with_amount`
pub fn encode_burn_txn_fees_script_function(coin_type: TypeTag) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("burn_txn_fees").to_owned(),
        vec![coin_type],
        vec![],
    ))
}

/// # Summary
/// Burns the coins held in a preburn resource in the preburn queue at the
/// specified preburn address, which are equal to the `amount` specified in the
/// transaction. Finds the first relevant outstanding preburn request with
/// matching amount and removes the contained coins from the system. The sending
/// account must be the Treasury Compliance account.
/// The account that holds the preburn queue resource will normally be a Designated
/// Dealer, but there are no enforced requirements that it be one.
///
/// # Technical Description
/// This transaction permanently destroys all the coins of `Token` type
/// stored in the `Diem::Preburn<Token>` resource published under the
/// `preburn_address` account address.
///
/// This transaction will only succeed if the sending `account` has a
/// `Diem::BurnCapability<Token>`, and a `Diem::Preburn<Token>` resource
/// exists under `preburn_address`, with a non-zero `to_burn` field. After the successful execution
/// of this transaction the `total_value` field in the
/// `Diem::CurrencyInfo<Token>` resource published under `0xA550C18` will be
/// decremented by the value of the `to_burn` field of the preburn resource
/// under `preburn_address` immediately before this transaction, and the
/// `to_burn` field of the preburn resource will have a zero value.
///
/// # Events
/// The successful execution of this transaction will emit a `Diem::BurnEvent` on the event handle
/// held in the `Diem::CurrencyInfo<Token>` resource's `burn_events` published under
/// `0xA550C18`.
///
/// # Parameters
/// | Name              | Type      | Description                                                                                                        |
/// | ------            | ------    | -------------                                                                                                      |
/// | `Token`           | Type      | The Move type for the `Token` currency being burned. `Token` must be an already-registered currency on-chain.      |
/// | `tc_account`      | `signer`  | The signer of the sending account of this transaction, must have a burn capability for `Token` published under it. |
/// | `sliding_nonce`   | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                         |
/// | `preburn_address` | `address` | The address where the coins to-be-burned are currently held.                                                       |
/// | `amount`          | `u64`     | The amount to be burned.                                                                                           |
///
/// # Common Abort Conditions
/// | Error Category                | Error Reason                            | Description                                                                                                                         |
/// | ----------------              | --------------                          | -------------                                                                                                                       |
/// | `Errors::NOT_PUBLISHED`       | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `account`.                                                                         |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                          |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                                                                       |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                                                                   |
/// | `Errors::REQUIRES_CAPABILITY` | `Diem::EBURN_CAPABILITY`                | The sending `account` does not have a `Diem::BurnCapability<Token>` published under it.                                             |
/// | `Errors::INVALID_STATE`       | `Diem::EPREBURN_NOT_FOUND`              | The `Diem::PreburnQueue<Token>` resource under `preburn_address` does not contain a preburn request with a value matching `amount`. |
/// | `Errors::NOT_PUBLISHED`       | `Diem::EPREBURN_QUEUE`                  | The account at `preburn_address` does not have a `Diem::PreburnQueue<Token>` resource published under it.                           |
/// | `Errors::NOT_PUBLISHED`       | `Diem::ECURRENCY_INFO`                  | The specified `Token` is not a registered currency on-chain.                                                                        |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::burn_txn_fees`
/// * `TreasuryComplianceScripts::cancel_burn_with_amount`
/// * `TreasuryComplianceScripts::preburn`
pub fn encode_burn_with_amount_script_function(
    token: TypeTag,
    sliding_nonce: u64,
    preburn_address: AccountAddress,
    amount: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("burn_with_amount").to_owned(),
        vec![token],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&preburn_address).unwrap(),
            bcs::to_bytes(&amount).unwrap(),
        ],
    ))
}

/// # Summary
/// Cancels and returns the coins held in the preburn area under
/// `preburn_address`, which are equal to the `amount` specified in the transaction. Finds the first preburn
/// resource with the matching amount and returns the funds to the `preburn_address`'s balance.
/// Can only be successfully sent by an account with Treasury Compliance role.
///
/// # Technical Description
/// Cancels and returns all coins held in the `Diem::Preburn<Token>` resource under the `preburn_address` and
/// return the funds to the `preburn_address` account's `DiemAccount::Balance<Token>`.
/// The transaction must be sent by an `account` with a `Diem::BurnCapability<Token>`
/// resource published under it. The account at `preburn_address` must have a
/// `Diem::Preburn<Token>` resource published under it, and its value must be nonzero. The transaction removes
/// the entire balance held in the `Diem::Preburn<Token>` resource, and returns it back to the account's
/// `DiemAccount::Balance<Token>` under `preburn_address`. Due to this, the account at
/// `preburn_address` must already have a balance in the `Token` currency published
/// before this script is called otherwise the transaction will fail.
///
/// # Events
/// The successful execution of this transaction will emit:
/// * A `Diem::CancelBurnEvent` on the event handle held in the `Diem::CurrencyInfo<Token>`
/// resource's `burn_events` published under `0xA550C18`.
/// * A `DiemAccount::ReceivedPaymentEvent` on the `preburn_address`'s
/// `DiemAccount::DiemAccount` `received_events` event handle with both the `payer` and `payee`
/// being `preburn_address`.
///
/// # Parameters
/// | Name              | Type      | Description                                                                                                                          |
/// | ------            | ------    | -------------                                                                                                                        |
/// | `Token`           | Type      | The Move type for the `Token` currenty that burning is being cancelled for. `Token` must be an already-registered currency on-chain. |
/// | `account`         | `signer`  | The signer of the sending account of this transaction, must have a burn capability for `Token` published under it.                   |
/// | `preburn_address` | `address` | The address where the coins to-be-burned are currently held.                                                                         |
/// | `amount`          | `u64`     | The amount to be cancelled.                                                                                                          |
///
/// # Common Abort Conditions
/// | Error Category                | Error Reason                                     | Description                                                                                                                         |
/// | ----------------              | --------------                                   | -------------                                                                                                                       |
/// | `Errors::REQUIRES_CAPABILITY` | `Diem::EBURN_CAPABILITY`                         | The sending `account` does not have a `Diem::BurnCapability<Token>` published under it.                                             |
/// | `Errors::INVALID_STATE`       | `Diem::EPREBURN_NOT_FOUND`                       | The `Diem::PreburnQueue<Token>` resource under `preburn_address` does not contain a preburn request with a value matching `amount`. |
/// | `Errors::NOT_PUBLISHED`       | `Diem::EPREBURN_QUEUE`                           | The account at `preburn_address` does not have a `Diem::PreburnQueue<Token>` resource published under it.                           |
/// | `Errors::NOT_PUBLISHED`       | `Diem::ECURRENCY_INFO`                           | The specified `Token` is not a registered currency on-chain.                                                                        |
/// | `Errors::INVALID_ARGUMENT`    | `DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE`  | The account at `preburn_address` doesn't have a balance resource for `Token`.                                                       |
/// | `Errors::LIMIT_EXCEEDED`      | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`           | The depositing of the funds held in the prebun area would exceed the `account`'s account limits.                                    |
/// | `Errors::INVALID_STATE`       | `DualAttestation::EPAYEE_COMPLIANCE_KEY_NOT_SET` | The `account` does not have a compliance key set on it but dual attestion checking was performed.                                   |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::burn_txn_fees`
/// * `TreasuryComplianceScripts::burn_with_amount`
/// * `TreasuryComplianceScripts::preburn`
pub fn encode_cancel_burn_with_amount_script_function(
    token: TypeTag,
    preburn_address: AccountAddress,
    amount: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("cancel_burn_with_amount").to_owned(),
        vec![token],
        vec![
            bcs::to_bytes(&preburn_address).unwrap(),
            bcs::to_bytes(&amount).unwrap(),
        ],
    ))
}

pub fn encode_create_acc_user_script_function(
    challenge: Vec<u8>,
    solution: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountScripts").to_owned(),
        ),
        ident_str!("create_acc_user").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&challenge).unwrap(),
            bcs::to_bytes(&solution).unwrap(),
        ],
    ))
}

pub fn encode_create_acc_val_script_function(
    challenge: Vec<u8>,
    solution: Vec<u8>,
    ow_human_name: Vec<u8>,
    op_address: AccountAddress,
    op_auth_key_prefix: Vec<u8>,
    op_consensus_pubkey: Vec<u8>,
    op_validator_network_addresses: Vec<u8>,
    op_fullnode_network_addresses: Vec<u8>,
    op_human_name: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountScripts").to_owned(),
        ),
        ident_str!("create_acc_val").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&challenge).unwrap(),
            bcs::to_bytes(&solution).unwrap(),
            bcs::to_bytes(&ow_human_name).unwrap(),
            bcs::to_bytes(&op_address).unwrap(),
            bcs::to_bytes(&op_auth_key_prefix).unwrap(),
            bcs::to_bytes(&op_consensus_pubkey).unwrap(),
            bcs::to_bytes(&op_validator_network_addresses).unwrap(),
            bcs::to_bytes(&op_fullnode_network_addresses).unwrap(),
            bcs::to_bytes(&op_human_name).unwrap(),
        ],
    ))
}

/// # Summary
/// Creates a Child VASP account with its parent being the sending account of the transaction.
/// The sender of the transaction must be a Parent VASP account.
///
/// # Technical Description
/// Creates a `ChildVASP` account for the sender `parent_vasp` at `child_address` with a balance of
/// `child_initial_balance` in `CoinType` and an initial authentication key of
/// `auth_key_prefix | child_address`. Authentication key prefixes, and how to construct them from an ed25519 public key is described
/// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
///
/// If `add_all_currencies` is true, the child address will have a zero balance in all available
/// currencies in the system.
///
/// The new account will be a child account of the transaction sender, which must be a
/// Parent VASP account. The child account will be recorded against the limit of
/// child accounts of the creating Parent VASP account.
///
/// # Events
/// Successful execution will emit:
/// * A `DiemAccount::CreateAccountEvent` with the `created` field being `child_address`,
/// and the `rold_id` field being `Roles::CHILD_VASP_ROLE_ID`. This is emitted on the
/// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
///
/// Successful execution with a `child_initial_balance` greater than zero will additionaly emit:
/// * A `DiemAccount::SentPaymentEvent` with the `payee` field being `child_address`.
/// This is emitted on the Parent VASP's `DiemAccount::DiemAccount` `sent_events` handle.
/// * A `DiemAccount::ReceivedPaymentEvent` with the  `payer` field being the Parent VASP's address.
/// This is emitted on the new Child VASPS's `DiemAccount::DiemAccount` `received_events` handle.
///
/// # Parameters
/// | Name                    | Type         | Description                                                                                                                                 |
/// | ------                  | ------       | -------------                                                                                                                               |
/// | `CoinType`              | Type         | The Move type for the `CoinType` that the child account should be created with. `CoinType` must be an already-registered currency on-chain. |
/// | `parent_vasp`           | `signer`     | The reference of the sending account. Must be a Parent VASP account.                                                                        |
/// | `child_address`         | `address`    | Address of the to-be-created Child VASP account.                                                                                            |
/// | `auth_key_prefix`       | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                    |
/// | `add_all_currencies`    | `bool`       | Whether to publish balance resources for all known currencies when the account is created.                                                  |
/// | `child_initial_balance` | `u64`        | The initial balance in `CoinType` to give the child account when it's created.                                                              |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                                             | Description                                                                              |
/// | ----------------            | --------------                                           | -------------                                                                            |
/// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`            | The `auth_key_prefix` was not of length 32.                                              |
/// | `Errors::REQUIRES_ROLE`     | `Roles::EPARENT_VASP`                                    | The sending account wasn't a Parent VASP account.                                        |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                                        | The `child_address` address is already taken.                                            |
/// | `Errors::LIMIT_EXCEEDED`    | `VASP::ETOO_MANY_CHILDREN`                               | The sending account has reached the maximum number of allowed child accounts.            |
/// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                                  | The `CoinType` is not a registered currency on-chain.                                    |
/// | `Errors::INVALID_STATE`     | `DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED` | The withdrawal capability for the sending account has already been extracted.            |
/// | `Errors::NOT_PUBLISHED`     | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`              | The sending account doesn't have a balance in `CoinType`.                                |
/// | `Errors::LIMIT_EXCEEDED`    | `DiemAccount::EINSUFFICIENT_BALANCE`                    | The sending account doesn't have at least `child_initial_balance` of `CoinType` balance. |
/// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::ECANNOT_CREATE_AT_VM_RESERVED`            | The `child_address` is the reserved address 0x0.                                         |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_parent_vasp_account`
/// * `AccountAdministrationScripts::add_currency_to_account`
/// * `AccountAdministrationScripts::rotate_authentication_key`
/// * `AccountAdministrationScripts::add_recovery_rotation_capability`
/// * `AccountAdministrationScripts::create_recovery_address`
pub fn encode_create_child_vasp_account_script_function(
    coin_type: TypeTag,
    child_address: AccountAddress,
    auth_key_prefix: Vec<u8>,
    add_all_currencies: bool,
    child_initial_balance: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountCreationScripts").to_owned(),
        ),
        ident_str!("create_child_vasp_account").to_owned(),
        vec![coin_type],
        vec![
            bcs::to_bytes(&child_address).unwrap(),
            bcs::to_bytes(&auth_key_prefix).unwrap(),
            bcs::to_bytes(&add_all_currencies).unwrap(),
            bcs::to_bytes(&child_initial_balance).unwrap(),
        ],
    ))
}

/// # Summary
/// Creates a Designated Dealer account with the provided information, and initializes it with
/// default mint tiers. The transaction can only be sent by the Treasury Compliance account.
///
/// # Technical Description
/// Creates an account with the Designated Dealer role at `addr` with authentication key
/// `auth_key_prefix` | `addr` and a 0 balance of type `Currency`. If `add_all_currencies` is true,
/// 0 balances for all available currencies in the system will also be added. This can only be
/// invoked by an account with the TreasuryCompliance role.
/// Authentication keys, prefixes, and how to construct them from an ed25519 public key are described
/// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
///
/// At the time of creation the account is also initialized with default mint tiers of (500_000,
/// 5000_000, 50_000_000, 500_000_000), and preburn areas for each currency that is added to the
/// account.
///
/// # Events
/// Successful execution will emit:
/// * A `DiemAccount::CreateAccountEvent` with the `created` field being `addr`,
/// and the `rold_id` field being `Roles::DESIGNATED_DEALER_ROLE_ID`. This is emitted on the
/// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
///
/// # Parameters
/// | Name                 | Type         | Description                                                                                                                                         |
/// | ------               | ------       | -------------                                                                                                                                       |
/// | `Currency`           | Type         | The Move type for the `Currency` that the Designated Dealer should be initialized with. `Currency` must be an already-registered currency on-chain. |
/// | `tc_account`         | `signer`     | The signer of the sending account of this transaction. Must be the Treasury Compliance account.                                                     |
/// | `sliding_nonce`      | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                                          |
/// | `addr`               | `address`    | Address of the to-be-created Designated Dealer account.                                                                                             |
/// | `auth_key_prefix`    | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                            |
/// | `human_name`         | `vector<u8>` | ASCII-encoded human name for the Designated Dealer.                                                                                                 |
/// | `add_all_currencies` | `bool`       | Whether to publish preburn, balance, and tier info resources for all known (SCS) currencies or just `Currency` when the account is created.         |
///

/// # Common Abort Conditions
/// | Error Category              | Error Reason                            | Description                                                                                |
/// | ----------------            | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::REQUIRES_ROLE`     | `Roles::ETREASURY_COMPLIANCE`           | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                 | The `Currency` is not a registered currency on-chain.                                      |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `addr` address is already taken.                                                       |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::tiered_mint`
/// * `PaymentScripts::peer_to_peer_with_metadata`
/// * `AccountAdministrationScripts::rotate_dual_attestation_info`
pub fn encode_create_designated_dealer_script_function(
    currency: TypeTag,
    sliding_nonce: u64,
    addr: AccountAddress,
    auth_key_prefix: Vec<u8>,
    human_name: Vec<u8>,
    add_all_currencies: bool,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountCreationScripts").to_owned(),
        ),
        ident_str!("create_designated_dealer").to_owned(),
        vec![currency],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&addr).unwrap(),
            bcs::to_bytes(&auth_key_prefix).unwrap(),
            bcs::to_bytes(&human_name).unwrap(),
            bcs::to_bytes(&add_all_currencies).unwrap(),
        ],
    ))
}

/// # Summary
/// Publishes a `DiemId::DiemIdDomains` resource under a parent VASP account.
/// The sending account must be a parent VASP account.
///
/// # Technical Description
/// Publishes a `DiemId::DiemIdDomains` resource under `account`.
/// The The `DiemId::DiemIdDomains` resource's `domains` field is a vector
/// of DiemIdDomain, and will be empty on at the end of processing this transaction.
///
/// # Parameters
/// | Name      | Type     | Description                                           |
/// | ------    | ------   | -------------                                         |
/// | `account` | `signer` | The signer of the sending account of the transaction. |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason              | Description                                                                    |
/// | ----------------            | --------------            | -------------                                                                  |
/// | `Errors::ALREADY_PUBLISHED` | `DiemId::EDIEM_ID_DOMAIN` | A `DiemId::DiemIdDomains` resource has already been published under `account`. |
/// | `Errors::REQUIRES_ROLE`     | `Roles::EPARENT_VASP`     | The sending `account` was not a parent VASP account.                           |
pub fn encode_create_diem_id_domains_script_function() -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("create_diem_id_domains").to_owned(),
        vec![],
        vec![],
    ))
}

/// # Summary
/// Creates a Parent VASP account with the specified human name. Must be called by the Treasury Compliance account.
///
/// # Technical Description
/// Creates an account with the Parent VASP role at `address` with authentication key
/// `auth_key_prefix` | `new_account_address` and a 0 balance of type `CoinType`. If
/// `add_all_currencies` is true, 0 balances for all available currencies in the system will
/// also be added. This can only be invoked by an TreasuryCompliance account.
/// `sliding_nonce` is a unique nonce for operation, see `SlidingNonce` for details.
/// Authentication keys, prefixes, and how to construct them from an ed25519 public key are described
/// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
///
/// # Events
/// Successful execution will emit:
/// * A `DiemAccount::CreateAccountEvent` with the `created` field being `new_account_address`,
/// and the `rold_id` field being `Roles::PARENT_VASP_ROLE_ID`. This is emitted on the
/// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
///
/// # Parameters
/// | Name                  | Type         | Description                                                                                                                                                    |
/// | ------                | ------       | -------------                                                                                                                                                  |
/// | `CoinType`            | Type         | The Move type for the `CoinType` currency that the Parent VASP account should be initialized with. `CoinType` must be an already-registered currency on-chain. |
/// | `tc_account`          | `signer`     | The signer of the sending account of this transaction. Must be the Treasury Compliance account.                                                                |
/// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                                                     |
/// | `new_account_address` | `address`    | Address of the to-be-created Parent VASP account.                                                                                                              |
/// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                                       |
/// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the Parent VASP.                                                                                                                  |
/// | `add_all_currencies`  | `bool`       | Whether to publish balance resources for all known currencies when the account is created.                                                                     |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                            | Description                                                                                |
/// | ----------------            | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::REQUIRES_ROLE`     | `Roles::ETREASURY_COMPLIANCE`           | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                 | The `CoinType` is not a registered currency on-chain.                                      |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_child_vasp_account`
/// * `AccountAdministrationScripts::add_currency_to_account`
/// * `AccountAdministrationScripts::rotate_authentication_key`
/// * `AccountAdministrationScripts::add_recovery_rotation_capability`
/// * `AccountAdministrationScripts::create_recovery_address`
/// * `AccountAdministrationScripts::rotate_dual_attestation_info`
pub fn encode_create_parent_vasp_account_script_function(
    coin_type: TypeTag,
    sliding_nonce: u64,
    new_account_address: AccountAddress,
    auth_key_prefix: Vec<u8>,
    human_name: Vec<u8>,
    add_all_currencies: bool,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountCreationScripts").to_owned(),
        ),
        ident_str!("create_parent_vasp_account").to_owned(),
        vec![coin_type],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&new_account_address).unwrap(),
            bcs::to_bytes(&auth_key_prefix).unwrap(),
            bcs::to_bytes(&human_name).unwrap(),
            bcs::to_bytes(&add_all_currencies).unwrap(),
        ],
    ))
}

/// # Summary
/// Initializes the sending account as a recovery address that may be used by
/// other accounts belonging to the same VASP as `account`.
/// The sending account must be a VASP account, and can be either a child or parent VASP account.
/// Multiple recovery addresses can exist for a single VASP, but accounts in
/// each must be disjoint.
///
/// # Technical Description
/// Publishes a `RecoveryAddress::RecoveryAddress` resource under `account`. It then
/// extracts the `DiemAccount::KeyRotationCapability` for `account` and adds
/// it to the resource. After the successful execution of this transaction
/// other accounts may add their key rotation to this resource so that `account`
/// may be used as a recovery account for those accounts.
///
/// # Parameters
/// | Name      | Type     | Description                                           |
/// | ------    | ------   | -------------                                         |
/// | `account` | `signer` | The signer of the sending account of the transaction. |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                                               | Description                                                                                   |
/// | ----------------            | --------------                                             | -------------                                                                                 |
/// | `Errors::INVALID_STATE`     | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.          |
/// | `Errors::INVALID_ARGUMENT`  | `RecoveryAddress::ENOT_A_VASP`                             | `account` is not a VASP account.                                                              |
/// | `Errors::INVALID_ARGUMENT`  | `RecoveryAddress::EKEY_ROTATION_DEPENDENCY_CYCLE`          | A key rotation recovery cycle would be created by adding `account`'s key rotation capability. |
/// | `Errors::ALREADY_PUBLISHED` | `RecoveryAddress::ERECOVERY_ADDRESS`                       | A `RecoveryAddress::RecoveryAddress` resource has already been published under `account`.     |
///
/// # Related Scripts
/// * `Script::add_recovery_rotation_capability`
/// * `Script::rotate_authentication_key_with_recovery_address`
pub fn encode_create_recovery_address_script_function() -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("create_recovery_address").to_owned(),
        vec![],
        vec![],
    ))
}

/// # Summary
/// Creates a Validator account. This transaction can only be sent by the Diem
/// Root account.
///
/// # Technical Description
/// Creates an account with a Validator role at `new_account_address`, with authentication key
/// `auth_key_prefix` | `new_account_address`. It publishes a
/// `ValidatorConfig::ValidatorConfig` resource with empty `config`, and
/// `operator_account` fields. The `human_name` field of the
/// `ValidatorConfig::ValidatorConfig` is set to the passed in `human_name`.
/// This script does not add the validator to the validator set or the system,
/// but only creates the account.
/// Authentication keys, prefixes, and how to construct them from an ed25519 public key are described
/// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
///
/// # Events
/// Successful execution will emit:
/// * A `DiemAccount::CreateAccountEvent` with the `created` field being `new_account_address`,
/// and the `rold_id` field being `Roles::VALIDATOR_ROLE_ID`. This is emitted on the
/// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
///
/// # Parameters
/// | Name                  | Type         | Description                                                                              |
/// | ------                | ------       | -------------                                                                            |
/// | `dr_account`          | `signer`     | The signer of the sending account of this transaction. Must be the Diem Root signer.     |
/// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.               |
/// | `new_account_address` | `address`    | Address of the to-be-created Validator account.                                          |
/// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account. |
/// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the validator.                                              |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                            | Description                                                                                |
/// | ----------------            | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                             |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                         |
/// | `Errors::REQUIRES_ROLE`     | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                         |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_validator_operator_account`
/// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::register_validator_config`
/// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::set_validator_operator`
/// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
/// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
pub fn encode_create_validator_account_script_function(
    sliding_nonce: u64,
    new_account_address: AccountAddress,
    auth_key_prefix: Vec<u8>,
    human_name: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountCreationScripts").to_owned(),
        ),
        ident_str!("create_validator_account").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&new_account_address).unwrap(),
            bcs::to_bytes(&auth_key_prefix).unwrap(),
            bcs::to_bytes(&human_name).unwrap(),
        ],
    ))
}

/// # Summary
/// Creates a Validator Operator account. This transaction can only be sent by the Diem
/// Root account.
///
/// # Technical Description
/// Creates an account with a Validator Operator role at `new_account_address`, with authentication key
/// `auth_key_prefix` | `new_account_address`. It publishes a
/// `ValidatorOperatorConfig::ValidatorOperatorConfig` resource with the specified `human_name`.
/// This script does not assign the validator operator to any validator accounts but only creates the account.
/// Authentication key prefixes, and how to construct them from an ed25519 public key are described
/// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
///
/// # Events
/// Successful execution will emit:
/// * A `DiemAccount::CreateAccountEvent` with the `created` field being `new_account_address`,
/// and the `rold_id` field being `Roles::VALIDATOR_OPERATOR_ROLE_ID`. This is emitted on the
/// `DiemAccount::AccountOperationsCapability` `creation_events` handle.
///
/// # Parameters
/// | Name                  | Type         | Description                                                                              |
/// | ------                | ------       | -------------                                                                            |
/// | `dr_account`          | `signer`     | The signer of the sending account of this transaction. Must be the Diem Root signer.     |
/// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.               |
/// | `new_account_address` | `address`    | Address of the to-be-created Validator account.                                          |
/// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account. |
/// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the validator.                                              |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                            | Description                                                                                |
/// | ----------------            | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                             |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                         |
/// | `Errors::REQUIRES_ROLE`     | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                         |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_validator_account`
/// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::register_validator_config`
/// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::set_validator_operator`
/// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
/// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
pub fn encode_create_validator_operator_account_script_function(
    sliding_nonce: u64,
    new_account_address: AccountAddress,
    auth_key_prefix: Vec<u8>,
    human_name: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountCreationScripts").to_owned(),
        ),
        ident_str!("create_validator_operator_account").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&new_account_address).unwrap(),
            bcs::to_bytes(&auth_key_prefix).unwrap(),
            bcs::to_bytes(&human_name).unwrap(),
        ],
    ))
}

pub fn encode_demo_e2e_script_function(world: u64) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("DemoScripts").to_owned(),
        ),
        ident_str!("demo_e2e").to_owned(),
        vec![],
        vec![bcs::to_bytes(&world).unwrap()],
    ))
}

/// # Summary
/// Freezes the account at `address`. The sending account of this transaction
/// must be the Treasury Compliance account. The account being frozen cannot be
/// the Diem Root or Treasury Compliance account. After the successful
/// execution of this transaction no transactions may be sent from the frozen
/// account, and the frozen account may not send or receive coins.
///
/// # Technical Description
/// Sets the `AccountFreezing::FreezingBit` to `true` and emits a
/// `AccountFreezing::FreezeAccountEvent`. The transaction sender must be the
/// Treasury Compliance account, but the account at `to_freeze_account` must
/// not be either `0xA550C18` (the Diem Root address), or `0xB1E55ED` (the
/// Treasury Compliance address). Note that this is a per-account property
/// e.g., freezing a Parent VASP will not effect the status any of its child
/// accounts and vice versa.
///

/// # Events
/// Successful execution of this transaction will emit a `AccountFreezing::FreezeAccountEvent` on
/// the `freeze_event_handle` held in the `AccountFreezing::FreezeEventsHolder` resource published
/// under `0xA550C18` with the `frozen_address` being the `to_freeze_account`.
///
/// # Parameters
/// | Name                | Type      | Description                                                                                     |
/// | ------              | ------    | -------------                                                                                   |
/// | `tc_account`        | `signer`  | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
/// | `sliding_nonce`     | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
/// | `to_freeze_account` | `address` | The account address to be frozen.                                                               |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                 | Description                                                                                |
/// | ----------------           | --------------                               | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`        | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`                | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::INVALID_ARGUMENT` | `AccountFreezing::ECANNOT_FREEZE_TC`         | `to_freeze_account` was the Treasury Compliance account (`0xB1E55ED`).                     |
/// | `Errors::INVALID_ARGUMENT` | `AccountFreezing::ECANNOT_FREEZE_DIEM_ROOT` | `to_freeze_account` was the Diem Root account (`0xA550C18`).                              |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::unfreeze_account`
pub fn encode_freeze_account_script_function(
    sliding_nonce: u64,
    to_freeze_account: AccountAddress,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("freeze_account").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&to_freeze_account).unwrap(),
        ],
    ))
}

/// # Summary
/// Initializes the Diem consensus config that is stored on-chain.  This
/// transaction can only be sent from the Diem Root account.
///
/// # Technical Description
/// Initializes the `DiemConsensusConfig` on-chain config to empty and allows future updates from DiemRoot via
/// `update_diem_consensus_config`. This doesn't emit a `DiemConfig::NewEpochEvent`.
///
/// # Parameters
/// | Name            | Type      | Description                                                                |
/// | ------          | ------    | -------------                                                              |
/// | `account`       | `signer` | Signer of the sending account. Must be the Diem Root account.               |
/// | `sliding_nonce` | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                  | Description                                                                                |
/// | ----------------           | --------------                                | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                   | `account` is not the Diem Root account.                                                    |
pub fn encode_initialize_diem_consensus_config_script_function(
    sliding_nonce: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("SystemAdministrationScripts").to_owned(),
        ),
        ident_str!("initialize_diem_consensus_config").to_owned(),
        vec![],
        vec![bcs::to_bytes(&sliding_nonce).unwrap()],
    ))
}

pub fn encode_join_script_function() -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorScripts").to_owned(),
        ),
        ident_str!("join").to_owned(),
        vec![],
        vec![],
    ))
}

pub fn encode_leave_script_function() -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorScripts").to_owned(),
        ),
        ident_str!("leave").to_owned(),
        vec![],
        vec![],
    ))
}

pub fn encode_minerstate_commit_script_function(
    challenge: Vec<u8>,
    solution: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("MinerStateScripts").to_owned(),
        ),
        ident_str!("minerstate_commit").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&challenge).unwrap(),
            bcs::to_bytes(&solution).unwrap(),
        ],
    ))
}

pub fn encode_minerstate_commit_by_operator_script_function(
    owner_address: AccountAddress,
    challenge: Vec<u8>,
    solution: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("MinerStateScripts").to_owned(),
        ),
        ident_str!("minerstate_commit_by_operator").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&owner_address).unwrap(),
            bcs::to_bytes(&challenge).unwrap(),
            bcs::to_bytes(&solution).unwrap(),
        ],
    ))
}

pub fn encode_minerstate_helper_script_function() -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("MinerStateScripts").to_owned(),
        ),
        ident_str!("minerstate_helper").to_owned(),
        vec![],
        vec![],
    ))
}

pub fn encode_ol_oracle_tx_script_function(id: u64, data: Vec<u8>) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("OracleScripts").to_owned(),
        ),
        ident_str!("ol_oracle_tx").to_owned(),
        vec![],
        vec![bcs::to_bytes(&id).unwrap(), bcs::to_bytes(&data).unwrap()],
    ))
}

pub fn encode_ol_reconfig_bulk_update_setup_script_function(
    alice: AccountAddress,
    bob: AccountAddress,
    carol: AccountAddress,
    sha: AccountAddress,
    ram: AccountAddress,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorScripts").to_owned(),
        ),
        ident_str!("ol_reconfig_bulk_update_setup").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&alice).unwrap(),
            bcs::to_bytes(&bob).unwrap(),
            bcs::to_bytes(&carol).unwrap(),
            bcs::to_bytes(&sha).unwrap(),
            bcs::to_bytes(&ram).unwrap(),
        ],
    ))
}

/// # Summary
/// Transfers a given number of coins in a specified currency from one account to another.
/// Transfers over a specified amount defined on-chain that are between two different VASPs, or
/// other accounts that have opted-in will be subject to on-chain checks to ensure the receiver has
/// agreed to receive the coins.  This transaction can be sent by any account that can hold a
/// balance, and to any account that can hold a balance. Both accounts must hold balances in the
/// currency being transacted.
///
/// # Technical Description
///
/// Transfers `amount` coins of type `Currency` from `payer` to `payee` with (optional) associated
/// `metadata` and an (optional) `metadata_signature` on the message of the form
/// `metadata` | `Signer::address_of(payer)` | `amount` | `DualAttestation::DOMAIN_SEPARATOR`, that
/// has been signed by the `payee`'s private key associated with the `compliance_public_key` held in
/// the `payee`'s `DualAttestation::Credential`. Both the `Signer::address_of(payer)` and `amount` fields
/// in the `metadata_signature` must be BCS-encoded bytes, and `|` denotes concatenation.
/// The `metadata` and `metadata_signature` parameters are only required if `amount` >=
/// `DualAttestation::get_cur_microdiem_limit` XDX and `payer` and `payee` are distinct VASPs.
/// However, a transaction sender can opt in to dual attestation even when it is not required
/// (e.g., a DesignatedDealer -> VASP payment) by providing a non-empty `metadata_signature`.
/// Standardized `metadata` BCS format can be found in `diem_types::transaction::metadata::Metadata`.
///
/// # Events
/// Successful execution of this script emits two events:
/// * A `DiemAccount::SentPaymentEvent` on `payer`'s `DiemAccount::DiemAccount` `sent_events` handle; and
/// * A `DiemAccount::ReceivedPaymentEvent` on `payee`'s `DiemAccount::DiemAccount` `received_events` handle.
///
/// # Parameters
/// | Name                 | Type         | Description                                                                                                                  |
/// | ------               | ------       | -------------                                                                                                                |
/// | `Currency`           | Type         | The Move type for the `Currency` being sent in this transaction. `Currency` must be an already-registered currency on-chain. |
/// | `payer`              | `signer`     | The signer of the sending account that coins are being transferred from.                                                     |
/// | `payee`              | `address`    | The address of the account the coins are being transferred to.                                                               |
/// | `metadata`           | `vector<u8>` | Optional metadata about this payment.                                                                                        |
/// | `metadata_signature` | `vector<u8>` | Optional signature over `metadata` and payment information. See                                                              |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                     | Description                                                                                                                         |
/// | ----------------           | --------------                                   | -------------                                                                                                                       |
/// | `Errors::NOT_PUBLISHED`    | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`       | `payer` doesn't hold a balance in `Currency`.                                                                                       |
/// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EINSUFFICIENT_BALANCE`             | `amount` is greater than `payer`'s balance in `Currency`.                                                                           |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::ECOIN_DEPOSIT_IS_ZERO`             | `amount` is zero.                                                                                                                   |
/// | `Errors::NOT_PUBLISHED`    | `DiemAccount::EPAYEE_DOES_NOT_EXIST`             | No account exists at the `payee` address.                                                                                           |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE`  | An account exists at `payee`, but it does not accept payments in `Currency`.                                                        |
/// | `Errors::INVALID_STATE`    | `AccountFreezing::EACCOUNT_FROZEN`               | The `payee` account is frozen.                                                                                                      |
/// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EMALFORMED_METADATA_SIGNATURE` | `metadata_signature` is not 64 bytes.                                                                                               |
/// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EINVALID_METADATA_SIGNATURE`   | `metadata_signature` does not verify on the against the `payee'`s `DualAttestation::Credential` `compliance_public_key` public key. |
/// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EWITHDRAWAL_EXCEEDS_LIMITS`        | `payer` has exceeded its daily withdrawal limits for the backing coins of XDX.                                                      |
/// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`           | `payee` has exceeded its daily deposit limits for XDX.                                                                              |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_child_vasp_account`
/// * `AccountCreationScripts::create_parent_vasp_account`
/// * `AccountAdministrationScripts::add_currency_to_account`
pub fn encode_peer_to_peer_with_metadata_script_function(
    currency: TypeTag,
    payee: AccountAddress,
    amount: u64,
    metadata: Vec<u8>,
    metadata_signature: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("PaymentScripts").to_owned(),
        ),
        ident_str!("peer_to_peer_with_metadata").to_owned(),
        vec![currency],
        vec![
            bcs::to_bytes(&payee).unwrap(),
            bcs::to_bytes(&amount).unwrap(),
            bcs::to_bytes(&metadata).unwrap(),
            bcs::to_bytes(&metadata_signature).unwrap(),
        ],
    ))
}

/// # Summary
/// Moves a specified number of coins in a given currency from the account's
/// balance to its preburn area after which the coins may be burned. This
/// transaction may be sent by any account that holds a balance and preburn area
/// in the specified currency.
///
/// # Technical Description
/// Moves the specified `amount` of coins in `Token` currency from the sending `account`'s
/// `DiemAccount::Balance<Token>` to the `Diem::Preburn<Token>` published under the same
/// `account`. `account` must have both of these resources published under it at the start of this
/// transaction in order for it to execute successfully.
///
/// # Events
/// Successful execution of this script emits two events:
/// * `DiemAccount::SentPaymentEvent ` on `account`'s `DiemAccount::DiemAccount` `sent_events`
/// handle with the `payee` and `payer` fields being `account`'s address; and
/// * A `Diem::PreburnEvent` with `Token`'s currency code on the
/// `Diem::CurrencyInfo<Token`'s `preburn_events` handle for `Token` and with
/// `preburn_address` set to `account`'s address.
///
/// # Parameters
/// | Name      | Type     | Description                                                                                                                      |
/// | ------    | ------   | -------------                                                                                                                    |
/// | `Token`   | Type     | The Move type for the `Token` currency being moved to the preburn area. `Token` must be an already-registered currency on-chain. |
/// | `account` | `signer` | The signer of the sending account.                                                                                               |
/// | `amount`  | `u64`    | The amount in `Token` to be moved to the preburn area.                                                                           |
///
/// # Common Abort Conditions
/// | Error Category           | Error Reason                                             | Description                                                                             |
/// | ----------------         | --------------                                           | -------------                                                                           |
/// | `Errors::NOT_PUBLISHED`  | `Diem::ECURRENCY_INFO`                                  | The `Token` is not a registered currency on-chain.                                      |
/// | `Errors::INVALID_STATE`  | `DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED` | The withdrawal capability for `account` has already been extracted.                     |
/// | `Errors::LIMIT_EXCEEDED` | `DiemAccount::EINSUFFICIENT_BALANCE`                    | `amount` is greater than `payer`'s balance in `Token`.                                  |
/// | `Errors::NOT_PUBLISHED`  | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`              | `account` doesn't hold a balance in `Token`.                                            |
/// | `Errors::NOT_PUBLISHED`  | `Diem::EPREBURN`                                        | `account` doesn't have a `Diem::Preburn<Token>` resource published under it.           |
/// | `Errors::INVALID_STATE`  | `Diem::EPREBURN_OCCUPIED`                               | The `value` field in the `Diem::Preburn<Token>` resource under the sender is non-zero. |
/// | `Errors::NOT_PUBLISHED`  | `Roles::EROLE_ID`                                        | The `account` did not have a role assigned to it.                                       |
/// | `Errors::REQUIRES_ROLE`  | `Roles::EDESIGNATED_DEALER`                              | The `account` did not have the role of DesignatedDealer.                                |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::cancel_burn_with_amount`
/// * `TreasuryComplianceScripts::burn_with_amount`
/// * `TreasuryComplianceScripts::burn_txn_fees`
pub fn encode_preburn_script_function(token: TypeTag, amount: u64) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("preburn").to_owned(),
        vec![token],
        vec![bcs::to_bytes(&amount).unwrap()],
    ))
}

/// # Summary
/// Rotates the authentication key of the sending account to the newly-specified ed25519 public key and
/// publishes a new shared authentication key derived from that public key under the sender's account.
/// Any account can send this transaction.
///
/// # Technical Description
/// Rotates the authentication key of the sending account to the
/// [authentication key derived from `public_key`](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys)
/// and publishes a `SharedEd25519PublicKey::SharedEd25519PublicKey` resource
/// containing the 32-byte ed25519 `public_key` and the `DiemAccount::KeyRotationCapability` for
/// `account` under `account`.
///
/// # Parameters
/// | Name         | Type         | Description                                                                                        |
/// | ------       | ------       | -------------                                                                                      |
/// | `account`    | `signer`     | The signer of the sending account of the transaction.                                              |
/// | `public_key` | `vector<u8>` | A valid 32-byte Ed25519 public key for `account`'s authentication key to be rotated to and stored. |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                                               | Description                                                                                         |
/// | ----------------            | --------------                                             | -------------                                                                                       |
/// | `Errors::INVALID_STATE`     | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability` resource.       |
/// | `Errors::ALREADY_PUBLISHED` | `SharedEd25519PublicKey::ESHARED_KEY`                      | The `SharedEd25519PublicKey::SharedEd25519PublicKey` resource is already published under `account`. |
/// | `Errors::INVALID_ARGUMENT`  | `SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY`            | `public_key` is an invalid ed25519 public key.                                                      |
///
/// # Related Scripts
/// * `AccountAdministrationScripts::rotate_shared_ed25519_public_key`
pub fn encode_publish_shared_ed25519_public_key_script_function(
    public_key: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("publish_shared_ed25519_public_key").to_owned(),
        vec![],
        vec![bcs::to_bytes(&public_key).unwrap()],
    ))
}

/// # Summary
/// Updates a validator's configuration. This does not reconfigure the system and will not update
/// the configuration in the validator set that is seen by other validators in the network. Can
/// only be successfully sent by a Validator Operator account that is already registered with a
/// validator.
///
/// # Technical Description
/// This updates the fields with corresponding names held in the `ValidatorConfig::ValidatorConfig`
/// config resource held under `validator_account`. It does not emit a `DiemConfig::NewEpochEvent`
/// so the copy of this config held in the validator set will not be updated, and the changes are
/// only "locally" under the `validator_account` account address.
///
/// # Parameters
/// | Name                          | Type         | Description                                                                                                        |
/// | ------                        | ------       | -------------                                                                                                      |
/// | `validator_operator_account`  | `signer`     | Signer of the sending account. Must be the registered validator operator for the validator at `validator_address`. |
/// | `validator_account`           | `address`    | The address of the validator's `ValidatorConfig::ValidatorConfig` resource being updated.                          |
/// | `consensus_pubkey`            | `vector<u8>` | New Ed25519 public key to be used in the updated `ValidatorConfig::ValidatorConfig`.                               |
/// | `validator_network_addresses` | `vector<u8>` | New set of `validator_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.             |
/// | `fullnode_network_addresses`  | `vector<u8>` | New set of `fullnode_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.              |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                   | Description                                                                                           |
/// | ----------------           | --------------                                 | -------------                                                                                         |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`           | `validator_address` does not have a `ValidatorConfig::ValidatorConfig` resource published under it.   |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_TRANSACTION_SENDER` | `validator_operator_account` is not the registered operator for the validator at `validator_address`. |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_CONSENSUS_KEY`      | `consensus_pubkey` is not a valid ed25519 public key.                                                 |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_validator_account`
/// * `AccountCreationScripts::create_validator_operator_account`
/// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::set_validator_operator`
/// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
/// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
pub fn encode_register_validator_config_script_function(
    validator_account: AccountAddress,
    consensus_pubkey: Vec<u8>,
    validator_network_addresses: Vec<u8>,
    fullnode_network_addresses: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorAdministrationScripts").to_owned(),
        ),
        ident_str!("register_validator_config").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&validator_account).unwrap(),
            bcs::to_bytes(&consensus_pubkey).unwrap(),
            bcs::to_bytes(&validator_network_addresses).unwrap(),
            bcs::to_bytes(&fullnode_network_addresses).unwrap(),
        ],
    ))
}

/// # Summary
/// Remove a DiemID domain from parent VASP account. The transaction can only be sent by
/// the Treasury Compliance account.
///
/// # Technical Description
/// Removes a `DiemId::DiemIdDomain` from the `domains` field of the `DiemId::DiemIdDomains` resource published under
/// account with `address`.
///
/// # Parameters
/// | Name         | Type         | Description                                                                                     |
/// | ------       | ------       | -------------                                                                                   |
/// | `tc_account` | `signer`     | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
/// | `address`    | `address`    | The `address` of parent VASP account that will update its domains.                              |
/// | `domain`     | `vector<u8>` | The domain name.                                                                                |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                             | Description                                                                                                                            |
/// | ----------------           | --------------                           | -------------                                                                                                                          |
/// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`            | The sending account is not the Treasury Compliance account.                                                                            |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`    | `tc_account` is not the Treasury Compliance account.                                                                                   |
/// | `Errors::NOT_PUBLISHED`    | `DiemId::EDIEM_ID_DOMAIN_MANAGER`        | The `DiemId::DiemIdDomainManager` resource is not yet published under the Treasury Compliance account.                                 |
/// | `Errors::NOT_PUBLISHED`    | `DiemId::EDIEM_ID_DOMAINS_NOT_PUBLISHED` | `address` does not have a `DiemId::DiemIdDomains` resource published under it.                                                         |
/// | `Errors::INVALID_ARGUMENT` | `DiemId::EINVALID_DIEM_ID_DOMAIN`        | The `domain` is greater in length than `DiemId::DOMAIN_LENGTH`.                                                                        |
/// | `Errors::INVALID_ARGUMENT` | `DiemId::EDOMAIN_NOT_FOUND`              | The `domain` does not exist in the list of `DiemId::DiemIdDomain`s  in the `DiemId::DiemIdDomains` resource published under `address`. |
pub fn encode_remove_diem_id_domain_script_function(
    address: AccountAddress,
    domain: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("remove_diem_id_domain").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&address).unwrap(),
            bcs::to_bytes(&domain).unwrap(),
        ],
    ))
}

/// # Summary
/// This script removes a validator account from the validator set, and triggers a reconfiguration
/// of the system to remove the validator from the system. This transaction can only be
/// successfully called by the Diem Root account.
///
/// # Technical Description
/// This script removes the account at `validator_address` from the validator set. This transaction
/// emits a `DiemConfig::NewEpochEvent` event. Once the reconfiguration triggered by this event
/// has been performed, the account at `validator_address` is no longer considered to be a
/// validator in the network. This transaction will fail if the validator at `validator_address`
/// is not in the validator set.
///
/// # Parameters
/// | Name                | Type         | Description                                                                                                                        |
/// | ------              | ------       | -------------                                                                                                                      |
/// | `dr_account`        | `signer`     | The signer of the sending account of this transaction. Must be the Diem Root signer.                                               |
/// | `sliding_nonce`     | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                         |
/// | `validator_name`    | `vector<u8>` | ASCII-encoded human name for the validator. Must match the human name in the `ValidatorConfig::ValidatorConfig` for the validator. |
/// | `validator_address` | `address`    | The validator account address to be removed from the validator set.                                                                |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                            | Description                                                                                     |
/// | ----------------           | --------------                          | -------------                                                                                   |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                                  |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.      |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                                   |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                               |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | The sending account is not the Diem Root account or Treasury Compliance account                |
/// | 0                          | 0                                       | The provided `validator_name` does not match the already-recorded human name for the validator. |
/// | `Errors::INVALID_ARGUMENT` | `DiemSystem::ENOT_AN_ACTIVE_VALIDATOR` | The validator to be removed is not in the validator set.                                        |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                              |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                              |
/// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`      | An invalid time value was encountered in reconfiguration. Unlikely to occur.                    |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_validator_account`
/// * `AccountCreationScripts::create_validator_operator_account`
/// * `ValidatorAdministrationScripts::register_validator_config`
/// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::set_validator_operator`
/// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
/// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
pub fn encode_remove_validator_and_reconfigure_script_function(
    sliding_nonce: u64,
    validator_name: Vec<u8>,
    validator_address: AccountAddress,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorAdministrationScripts").to_owned(),
        ),
        ident_str!("remove_validator_and_reconfigure").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&validator_name).unwrap(),
            bcs::to_bytes(&validator_address).unwrap(),
        ],
    ))
}

/// # Summary
/// Rotates the `account`'s authentication key to the supplied new authentication key. May be sent by any account.
///
/// # Technical Description
/// Rotate the `account`'s `DiemAccount::DiemAccount` `authentication_key`
/// field to `new_key`. `new_key` must be a valid authentication key that
/// corresponds to an ed25519 public key as described [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys),
/// and `account` must not have previously delegated its `DiemAccount::KeyRotationCapability`.
///
/// # Parameters
/// | Name      | Type         | Description                                       |
/// | ------    | ------       | -------------                                     |
/// | `account` | `signer`     | Signer of the sending account of the transaction. |
/// | `new_key` | `vector<u8>` | New authentication key to be used for `account`.  |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                              | Description                                                                         |
/// | ----------------           | --------------                                            | -------------                                                                       |
/// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`. |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                    |
///
/// # Related Scripts
/// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce_admin`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_recovery_address`
pub fn encode_rotate_authentication_key_script_function(new_key: Vec<u8>) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("rotate_authentication_key").to_owned(),
        vec![],
        vec![bcs::to_bytes(&new_key).unwrap()],
    ))
}

/// # Summary
/// Rotates the sender's authentication key to the supplied new authentication key. May be sent by
/// any account that has a sliding nonce resource published under it (usually this is Treasury
/// Compliance or Diem Root accounts).
///
/// # Technical Description
/// Rotates the `account`'s `DiemAccount::DiemAccount` `authentication_key`
/// field to `new_key`. `new_key` must be a valid authentication key that
/// corresponds to an ed25519 public key as described [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys),
/// and `account` must not have previously delegated its `DiemAccount::KeyRotationCapability`.
///
/// # Parameters
/// | Name            | Type         | Description                                                                |
/// | ------          | ------       | -------------                                                              |
/// | `account`       | `signer`     | Signer of the sending account of the transaction.                          |
/// | `sliding_nonce` | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
/// | `new_key`       | `vector<u8>` | New authentication key to be used for `account`.                           |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                               | Description                                                                                |
/// | ----------------           | --------------                                             | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                             | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                             | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                             | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`                    | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.       |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                           |
///
/// # Related Scripts
/// * `AccountAdministrationScripts::rotate_authentication_key`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce_admin`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_recovery_address`
pub fn encode_rotate_authentication_key_with_nonce_script_function(
    sliding_nonce: u64,
    new_key: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("rotate_authentication_key_with_nonce").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&new_key).unwrap(),
        ],
    ))
}

/// # Summary
/// Rotates the specified account's authentication key to the supplied new authentication key. May
/// only be sent by the Diem Root account as a write set transaction.
///
/// # Technical Description
/// Rotate the `account`'s `DiemAccount::DiemAccount` `authentication_key` field to `new_key`.
/// `new_key` must be a valid authentication key that corresponds to an ed25519
/// public key as described [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys),
/// and `account` must not have previously delegated its `DiemAccount::KeyRotationCapability`.
///
/// # Parameters
/// | Name            | Type         | Description                                                                                       |
/// | ------          | ------       | -------------                                                                                     |
/// | `dr_account`    | `signer`     | The signer of the sending account of the write set transaction. May only be the Diem Root signer. |
/// | `account`       | `signer`     | Signer of account specified in the `execute_as` field of the write set transaction.               |
/// | `sliding_nonce` | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction for Diem Root.          |
/// | `new_key`       | `vector<u8>` | New authentication key to be used for `account`.                                                  |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                              | Description                                                                                                |
/// | ----------------           | --------------                                            | -------------                                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                            | A `SlidingNonce` resource is not published under `dr_account`.                                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                            | The `sliding_nonce` in `dr_account` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                            | The `sliding_nonce` in `dr_account` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`                   | The `sliding_nonce` in` dr_account` has been previously recorded.                                          |
/// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.                        |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                                           |
///
/// # Related Scripts
/// * `AccountAdministrationScripts::rotate_authentication_key`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_recovery_address`
pub fn encode_rotate_authentication_key_with_nonce_admin_script_function(
    sliding_nonce: u64,
    new_key: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("rotate_authentication_key_with_nonce_admin").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&new_key).unwrap(),
        ],
    ))
}

/// # Summary
/// Rotates the authentication key of a specified account that is part of a recovery address to a
/// new authentication key. Only used for accounts that are part of a recovery address (see
/// `AccountAdministrationScripts::add_recovery_rotation_capability` for account restrictions).
///
/// # Technical Description
/// Rotates the authentication key of the `to_recover` account to `new_key` using the
/// `DiemAccount::KeyRotationCapability` stored in the `RecoveryAddress::RecoveryAddress` resource
/// published under `recovery_address`. `new_key` must be a valide authentication key as described
/// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys).
/// This transaction can be sent either by the `to_recover` account, or by the account where the
/// `RecoveryAddress::RecoveryAddress` resource is published that contains `to_recover`'s `DiemAccount::KeyRotationCapability`.
///
/// # Parameters
/// | Name               | Type         | Description                                                                                                                   |
/// | ------             | ------       | -------------                                                                                                                 |
/// | `account`          | `signer`     | Signer of the sending account of the transaction.                                                                             |
/// | `recovery_address` | `address`    | Address where `RecoveryAddress::RecoveryAddress` that holds `to_recover`'s `DiemAccount::KeyRotationCapability` is published. |
/// | `to_recover`       | `address`    | The address of the account whose authentication key will be updated.                                                          |
/// | `new_key`          | `vector<u8>` | New authentication key to be used for the account at the `to_recover` address.                                                |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                 | Description                                                                                                                                         |
/// | ----------------           | --------------                               | -------------                                                                                                                                       |
/// | `Errors::NOT_PUBLISHED`    | `RecoveryAddress::ERECOVERY_ADDRESS`         | `recovery_address` does not have a `RecoveryAddress::RecoveryAddress` resource published under it.                                                  |
/// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::ECANNOT_ROTATE_KEY`        | The address of `account` is not `recovery_address` or `to_recover`.                                                                                 |
/// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::EACCOUNT_NOT_RECOVERABLE`  | `to_recover`'s `DiemAccount::KeyRotationCapability`  is not in the `RecoveryAddress::RecoveryAddress`  resource published under `recovery_address`. |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY` | `new_key` was an invalid length.                                                                                                                    |
///
/// # Related Scripts
/// * `AccountAdministrationScripts::rotate_authentication_key`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce`
/// * `AccountAdministrationScripts::rotate_authentication_key_with_nonce_admin`
pub fn encode_rotate_authentication_key_with_recovery_address_script_function(
    recovery_address: AccountAddress,
    to_recover: AccountAddress,
    new_key: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("rotate_authentication_key_with_recovery_address").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&recovery_address).unwrap(),
            bcs::to_bytes(&to_recover).unwrap(),
            bcs::to_bytes(&new_key).unwrap(),
        ],
    ))
}

/// # Summary
/// Updates the url used for off-chain communication, and the public key used to verify dual
/// attestation on-chain. Transaction can be sent by any account that has dual attestation
/// information published under it. In practice the only such accounts are Designated Dealers and
/// Parent VASPs.
///
/// # Technical Description
/// Updates the `base_url` and `compliance_public_key` fields of the `DualAttestation::Credential`
/// resource published under `account`. The `new_key` must be a valid ed25519 public key.
///
/// # Events
/// Successful execution of this transaction emits two events:
/// * A `DualAttestation::ComplianceKeyRotationEvent` containing the new compliance public key, and
/// the blockchain time at which the key was updated emitted on the `DualAttestation::Credential`
/// `compliance_key_rotation_events` handle published under `account`; and
/// * A `DualAttestation::BaseUrlRotationEvent` containing the new base url to be used for
/// off-chain communication, and the blockchain time at which the url was updated emitted on the
/// `DualAttestation::Credential` `base_url_rotation_events` handle published under `account`.
///
/// # Parameters
/// | Name      | Type         | Description                                                               |
/// | ------    | ------       | -------------                                                             |
/// | `account` | `signer`     | Signer of the sending account of the transaction.                         |
/// | `new_url` | `vector<u8>` | ASCII-encoded url to be used for off-chain communication with `account`.  |
/// | `new_key` | `vector<u8>` | New ed25519 public key to be used for on-chain dual attestation checking. |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                           | Description                                                                |
/// | ----------------           | --------------                         | -------------                                                              |
/// | `Errors::NOT_PUBLISHED`    | `DualAttestation::ECREDENTIAL`         | A `DualAttestation::Credential` resource is not published under `account`. |
/// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EINVALID_PUBLIC_KEY` | `new_key` is not a valid ed25519 public key.                               |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_parent_vasp_account`
/// * `AccountCreationScripts::create_designated_dealer`
/// * `AccountAdministrationScripts::rotate_dual_attestation_info`
pub fn encode_rotate_dual_attestation_info_script_function(
    new_url: Vec<u8>,
    new_key: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("rotate_dual_attestation_info").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&new_url).unwrap(),
            bcs::to_bytes(&new_key).unwrap(),
        ],
    ))
}

/// # Summary
/// Rotates the authentication key in a `SharedEd25519PublicKey`. This transaction can be sent by
/// any account that has previously published a shared ed25519 public key using
/// `AccountAdministrationScripts::publish_shared_ed25519_public_key`.
///
/// # Technical Description
/// `public_key` must be a valid ed25519 public key.  This transaction first rotates the public key stored in `account`'s
/// `SharedEd25519PublicKey::SharedEd25519PublicKey` resource to `public_key`, after which it
/// rotates the `account`'s authentication key to the new authentication key derived from `public_key` as defined
/// [here](https://developers.diem.com/docs/core/accounts/#addresses-authentication-keys-and-cryptographic-keys)
/// using the `DiemAccount::KeyRotationCapability` stored in `account`'s `SharedEd25519PublicKey::SharedEd25519PublicKey`.
///
/// # Parameters
/// | Name         | Type         | Description                                           |
/// | ------       | ------       | -------------                                         |
/// | `account`    | `signer`     | The signer of the sending account of the transaction. |
/// | `public_key` | `vector<u8>` | 32-byte Ed25519 public key.                           |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                    | Description                                                                                   |
/// | ----------------           | --------------                                  | -------------                                                                                 |
/// | `Errors::NOT_PUBLISHED`    | `SharedEd25519PublicKey::ESHARED_KEY`           | A `SharedEd25519PublicKey::SharedEd25519PublicKey` resource is not published under `account`. |
/// | `Errors::INVALID_ARGUMENT` | `SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY` | `public_key` is an invalid ed25519 public key.                                                |
///
/// # Related Scripts
/// * `AccountAdministrationScripts::publish_shared_ed25519_public_key`
pub fn encode_rotate_shared_ed25519_public_key_script_function(
    public_key: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("AccountAdministrationScripts").to_owned(),
        ),
        ident_str!("rotate_shared_ed25519_public_key").to_owned(),
        vec![],
        vec![bcs::to_bytes(&public_key).unwrap()],
    ))
}

/// # Summary
/// Updates the gas constants stored on chain and used by the VM for gas
/// metering. This transaction can only be sent from the Diem Root account.
///
/// # Technical Description
/// Updates the on-chain config holding the `DiemVMConfig` and emits a
/// `DiemConfig::NewEpochEvent` to trigger a reconfiguration of the system.
///
/// # Parameters
/// | Name                                | Type     | Description                                                                                            |
/// | ------                              | ------   | -------------                                                                                          |
/// | `account`                           | `signer` | Signer of the sending account. Must be the Diem Root account.                                          |
/// | `sliding_nonce`                     | `u64`    | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                             |
/// | `global_memory_per_byte_cost`       | `u64`    | The new cost to read global memory per-byte to be used for gas metering.                               |
/// | `global_memory_per_byte_write_cost` | `u64`    | The new cost to write global memory per-byte to be used for gas metering.                              |
/// | `min_transaction_gas_units`         | `u64`    | The new flat minimum amount of gas required for any transaction.                                       |
/// | `large_transaction_cutoff`          | `u64`    | The new size over which an additional charge will be assessed for each additional byte.                |
/// | `intrinsic_gas_per_byte`            | `u64`    | The new number of units of gas that to be charged per-byte over the new `large_transaction_cutoff`.    |
/// | `maximum_number_of_gas_units`       | `u64`    | The new maximum number of gas units that can be set in a transaction.                                  |
/// | `min_price_per_gas_unit`            | `u64`    | The new minimum gas price that can be set for a transaction.                                           |
/// | `max_price_per_gas_unit`            | `u64`    | The new maximum gas price that can be set for a transaction.                                           |
/// | `max_transaction_size_in_bytes`     | `u64`    | The new maximum size of a transaction that can be processed.                                           |
/// | `gas_unit_scaling_factor`           | `u64`    | The new scaling factor to use when scaling between external and internal gas units.                    |
/// | `default_account_size`              | `u64`    | The new default account size to use when assessing final costs for reads and writes to global storage. |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                | Description                                                                                |
/// | ----------------           | --------------                              | -------------                                                                              |
/// | `Errors::INVALID_ARGUMENT` | `DiemVMConfig::EGAS_CONSTANT_INCONSISTENCY` | The provided gas constants are inconsistent.                                               |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`              | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`              | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`              | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`     | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                 | `account` is not the Diem Root account.                                                    |
pub fn encode_set_gas_constants_script_function(
    sliding_nonce: u64,
    global_memory_per_byte_cost: u64,
    global_memory_per_byte_write_cost: u64,
    min_transaction_gas_units: u64,
    large_transaction_cutoff: u64,
    intrinsic_gas_per_byte: u64,
    maximum_number_of_gas_units: u64,
    min_price_per_gas_unit: u64,
    max_price_per_gas_unit: u64,
    max_transaction_size_in_bytes: u64,
    gas_unit_scaling_factor: u64,
    default_account_size: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("SystemAdministrationScripts").to_owned(),
        ),
        ident_str!("set_gas_constants").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&global_memory_per_byte_cost).unwrap(),
            bcs::to_bytes(&global_memory_per_byte_write_cost).unwrap(),
            bcs::to_bytes(&min_transaction_gas_units).unwrap(),
            bcs::to_bytes(&large_transaction_cutoff).unwrap(),
            bcs::to_bytes(&intrinsic_gas_per_byte).unwrap(),
            bcs::to_bytes(&maximum_number_of_gas_units).unwrap(),
            bcs::to_bytes(&min_price_per_gas_unit).unwrap(),
            bcs::to_bytes(&max_price_per_gas_unit).unwrap(),
            bcs::to_bytes(&max_transaction_size_in_bytes).unwrap(),
            bcs::to_bytes(&gas_unit_scaling_factor).unwrap(),
            bcs::to_bytes(&default_account_size).unwrap(),
        ],
    ))
}

/// # Summary
/// Updates a validator's configuration, and triggers a reconfiguration of the system to update the
/// validator set with this new validator configuration.  Can only be successfully sent by a
/// Validator Operator account that is already registered with a validator.
///
/// # Technical Description
/// This updates the fields with corresponding names held in the `ValidatorConfig::ValidatorConfig`
/// config resource held under `validator_account`. It then emits a `DiemConfig::NewEpochEvent` to
/// trigger a reconfiguration of the system.  This reconfiguration will update the validator set
/// on-chain with the updated `ValidatorConfig::ValidatorConfig`.
///
/// # Parameters
/// | Name                          | Type         | Description                                                                                                        |
/// | ------                        | ------       | -------------                                                                                                      |
/// | `validator_operator_account`  | `signer`     | Signer of the sending account. Must be the registered validator operator for the validator at `validator_address`. |
/// | `validator_account`           | `address`    | The address of the validator's `ValidatorConfig::ValidatorConfig` resource being updated.                          |
/// | `consensus_pubkey`            | `vector<u8>` | New Ed25519 public key to be used in the updated `ValidatorConfig::ValidatorConfig`.                               |
/// | `validator_network_addresses` | `vector<u8>` | New set of `validator_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.             |
/// | `fullnode_network_addresses`  | `vector<u8>` | New set of `fullnode_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.              |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                   | Description                                                                                           |
/// | ----------------           | --------------                                 | -------------                                                                                         |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`           | `validator_address` does not have a `ValidatorConfig::ValidatorConfig` resource published under it.   |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR_OPERATOR`                   | `validator_operator_account` does not have a Validator Operator role.                                 |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_TRANSACTION_SENDER` | `validator_operator_account` is not the registered operator for the validator at `validator_address`. |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_CONSENSUS_KEY`      | `consensus_pubkey` is not a valid ed25519 public key.                                                 |
/// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`             | An invalid time value was encountered in reconfiguration. Unlikely to occur.                          |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_validator_account`
/// * `AccountCreationScripts::create_validator_operator_account`
/// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::set_validator_operator`
/// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
/// * `ValidatorAdministrationScripts::register_validator_config`
pub fn encode_set_validator_config_and_reconfigure_script_function(
    validator_account: AccountAddress,
    consensus_pubkey: Vec<u8>,
    validator_network_addresses: Vec<u8>,
    fullnode_network_addresses: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorAdministrationScripts").to_owned(),
        ),
        ident_str!("set_validator_config_and_reconfigure").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&validator_account).unwrap(),
            bcs::to_bytes(&consensus_pubkey).unwrap(),
            bcs::to_bytes(&validator_network_addresses).unwrap(),
            bcs::to_bytes(&fullnode_network_addresses).unwrap(),
        ],
    ))
}

/// # Summary
/// Sets the validator operator for a validator in the validator's configuration resource "locally"
/// and does not reconfigure the system. Changes from this transaction will not picked up by the
/// system until a reconfiguration of the system is triggered. May only be sent by an account with
/// Validator role.
///
/// # Technical Description
/// Sets the account at `operator_account` address and with the specified `human_name` as an
/// operator for the sending validator account. The account at `operator_account` address must have
/// a Validator Operator role and have a `ValidatorOperatorConfig::ValidatorOperatorConfig`
/// resource published under it. The sending `account` must be a Validator and have a
/// `ValidatorConfig::ValidatorConfig` resource published under it. This script does not emit a
/// `DiemConfig::NewEpochEvent` and no reconfiguration of the system is initiated by this script.
///
/// # Parameters
/// | Name               | Type         | Description                                                                                  |
/// | ------             | ------       | -------------                                                                                |
/// | `account`          | `signer`     | The signer of the sending account of the transaction.                                        |
/// | `operator_name`    | `vector<u8>` | Validator operator's human name.                                                             |
/// | `operator_account` | `address`    | Address of the validator operator account to be added as the `account` validator's operator. |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                          | Description                                                                                                                                                  |
/// | ----------------           | --------------                                        | -------------                                                                                                                                                |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG` | The `ValidatorOperatorConfig::ValidatorOperatorConfig` resource is not published under `operator_account`.                                                   |
/// | 0                          | 0                                                     | The `human_name` field of the `ValidatorOperatorConfig::ValidatorOperatorConfig` resource under `operator_account` does not match the provided `human_name`. |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR`                                   | `account` does not have a Validator account role.                                                                                                            |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR`          | The account at `operator_account` does not have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource.                                               |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`                  | A `ValidatorConfig::ValidatorConfig` is not published under `account`.                                                                                       |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_validator_account`
/// * `AccountCreationScripts::create_validator_operator_account`
/// * `ValidatorAdministrationScripts::register_validator_config`
/// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::set_validator_operator_with_nonce_admin`
/// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
pub fn encode_set_validator_operator_script_function(
    operator_name: Vec<u8>,
    operator_account: AccountAddress,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorAdministrationScripts").to_owned(),
        ),
        ident_str!("set_validator_operator").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&operator_name).unwrap(),
            bcs::to_bytes(&operator_account).unwrap(),
        ],
    ))
}

/// # Summary
/// Sets the validator operator for a validator in the validator's configuration resource "locally"
/// and does not reconfigure the system. Changes from this transaction will not picked up by the
/// system until a reconfiguration of the system is triggered. May only be sent by the Diem Root
/// account as a write set transaction.
///
/// # Technical Description
/// Sets the account at `operator_account` address and with the specified `human_name` as an
/// operator for the validator `account`. The account at `operator_account` address must have a
/// Validator Operator role and have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource
/// published under it. The account represented by the `account` signer must be a Validator and
/// have a `ValidatorConfig::ValidatorConfig` resource published under it. No reconfiguration of
/// the system is initiated by this script.
///
/// # Parameters
/// | Name               | Type         | Description                                                                                   |
/// | ------             | ------       | -------------                                                                                 |
/// | `dr_account`       | `signer`     | Signer of the sending account of the write set transaction. May only be the Diem Root signer. |
/// | `account`          | `signer`     | Signer of account specified in the `execute_as` field of the write set transaction.           |
/// | `sliding_nonce`    | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction for Diem Root.      |
/// | `operator_name`    | `vector<u8>` | Validator operator's human name.                                                              |
/// | `operator_account` | `address`    | Address of the validator operator account to be added as the `account` validator's operator.  |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                          | Description                                                                                                                                                  |
/// | ----------------           | --------------                                        | -------------                                                                                                                                                |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                        | A `SlidingNonce` resource is not published under `dr_account`.                                                                                               |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                        | The `sliding_nonce` in `dr_account` is too old and it's impossible to determine if it's duplicated or not.                                                   |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                        | The `sliding_nonce` in `dr_account` is too far in the future.                                                                                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`               | The `sliding_nonce` in` dr_account` has been previously recorded.                                                                                            |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                        | The sending account is not the Diem Root account or Treasury Compliance account                                                                             |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG` | The `ValidatorOperatorConfig::ValidatorOperatorConfig` resource is not published under `operator_account`.                                                   |
/// | 0                          | 0                                                     | The `human_name` field of the `ValidatorOperatorConfig::ValidatorOperatorConfig` resource under `operator_account` does not match the provided `human_name`. |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR`                                   | `account` does not have a Validator account role.                                                                                                            |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR`          | The account at `operator_account` does not have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource.                                               |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`                  | A `ValidatorConfig::ValidatorConfig` is not published under `account`.                                                                                       |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_validator_account`
/// * `AccountCreationScripts::create_validator_operator_account`
/// * `ValidatorAdministrationScripts::register_validator_config`
/// * `ValidatorAdministrationScripts::remove_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::add_validator_and_reconfigure`
/// * `ValidatorAdministrationScripts::set_validator_operator`
/// * `ValidatorAdministrationScripts::set_validator_config_and_reconfigure`
pub fn encode_set_validator_operator_with_nonce_admin_script_function(
    sliding_nonce: u64,
    operator_name: Vec<u8>,
    operator_account: AccountAddress,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorAdministrationScripts").to_owned(),
        ),
        ident_str!("set_validator_operator_with_nonce_admin").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&operator_name).unwrap(),
            bcs::to_bytes(&operator_account).unwrap(),
        ],
    ))
}

pub fn encode_set_wallet_type_script_function(type_of: u8) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("WalletScripts").to_owned(),
        ),
        ident_str!("set_wallet_type").to_owned(),
        vec![],
        vec![bcs::to_bytes(&type_of).unwrap()],
    ))
}

/// # Summary
/// Mints a specified number of coins in a currency to a Designated Dealer. The sending account
/// must be the Treasury Compliance account, and coins can only be minted to a Designated Dealer
/// account.
///
/// # Technical Description
/// Mints `mint_amount` of coins in the `CoinType` currency to Designated Dealer account at
/// `designated_dealer_address`. The `tier_index` parameter specifies which tier should be used to
/// check verify the off-chain approval policy, and is based in part on the on-chain tier values
/// for the specific Designated Dealer, and the number of `CoinType` coins that have been minted to
/// the dealer over the past 24 hours. Every Designated Dealer has 4 tiers for each currency that
/// they support. The sending `tc_account` must be the Treasury Compliance account, and the
/// receiver an authorized Designated Dealer account.
///
/// # Events
/// Successful execution of the transaction will emit two events:
/// * A `Diem::MintEvent` with the amount and currency code minted is emitted on the
/// `mint_event_handle` in the stored `Diem::CurrencyInfo<CoinType>` resource stored under
/// `0xA550C18`; and
/// * A `DesignatedDealer::ReceivedMintEvent` with the amount, currency code, and Designated
/// Dealer's address is emitted on the `mint_event_handle` in the stored `DesignatedDealer::Dealer`
/// resource published under the `designated_dealer_address`.
///
/// # Parameters
/// | Name                        | Type      | Description                                                                                                |
/// | ------                      | ------    | -------------                                                                                              |
/// | `CoinType`                  | Type      | The Move type for the `CoinType` being minted. `CoinType` must be an already-registered currency on-chain. |
/// | `tc_account`                | `signer`  | The signer of the sending account of this transaction. Must be the Treasury Compliance account.            |
/// | `sliding_nonce`             | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                 |
/// | `designated_dealer_address` | `address` | The address of the Designated Dealer account being minted to.                                              |
/// | `mint_amount`               | `u64`     | The number of coins to be minted.                                                                          |
/// | `tier_index`                | `u64`     | [Deprecated] The mint tier index to use for the Designated Dealer account. Will be ignored                 |
///
/// # Common Abort Conditions
/// | Error Category                | Error Reason                                 | Description                                                                                                                  |
/// | ----------------              | --------------                               | -------------                                                                                                                |
/// | `Errors::NOT_PUBLISHED`       | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `tc_account`.                                                               |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                   |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                                                                |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                                                            |
/// | `Errors::REQUIRES_ADDRESS`    | `CoreAddresses::ETREASURY_COMPLIANCE`        | `tc_account` is not the Treasury Compliance account.                                                                         |
/// | `Errors::REQUIRES_ROLE`       | `Roles::ETREASURY_COMPLIANCE`                | `tc_account` is not the Treasury Compliance account.                                                                         |
/// | `Errors::INVALID_ARGUMENT`    | `DesignatedDealer::EINVALID_MINT_AMOUNT`     | `mint_amount` is zero.                                                                                                       |
/// | `Errors::NOT_PUBLISHED`       | `DesignatedDealer::EDEALER`                  | `DesignatedDealer::Dealer` or `DesignatedDealer::TierInfo<CoinType>` resource does not exist at `designated_dealer_address`. |
/// | `Errors::REQUIRES_CAPABILITY` | `Diem::EMINT_CAPABILITY`                    | `tc_account` does not have a `Diem::MintCapability<CoinType>` resource published under it.                                  |
/// | `Errors::INVALID_STATE`       | `Diem::EMINTING_NOT_ALLOWED`                | Minting is not currently allowed for `CoinType` coins.                                                                       |
/// | `Errors::LIMIT_EXCEEDED`      | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`      | The depositing of the funds would exceed the `account`'s account limits.                                                     |
///
/// # Related Scripts
/// * `AccountCreationScripts::create_designated_dealer`
/// * `PaymentScripts::peer_to_peer_with_metadata`
/// * `AccountAdministrationScripts::rotate_dual_attestation_info`
pub fn encode_tiered_mint_script_function(
    coin_type: TypeTag,
    sliding_nonce: u64,
    designated_dealer_address: AccountAddress,
    mint_amount: u64,
    tier_index: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("tiered_mint").to_owned(),
        vec![coin_type],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&designated_dealer_address).unwrap(),
            bcs::to_bytes(&mint_amount).unwrap(),
            bcs::to_bytes(&tier_index).unwrap(),
        ],
    ))
}

/// # Summary
/// Unfreezes the account at `address`. The sending account of this transaction must be the
/// Treasury Compliance account. After the successful execution of this transaction transactions
/// may be sent from the previously frozen account, and coins may be sent and received.
///
/// # Technical Description
/// Sets the `AccountFreezing::FreezingBit` to `false` and emits a
/// `AccountFreezing::UnFreezeAccountEvent`. The transaction sender must be the Treasury Compliance
/// account. Note that this is a per-account property so unfreezing a Parent VASP will not effect
/// the status any of its child accounts and vice versa.
///
/// # Events
/// Successful execution of this script will emit a `AccountFreezing::UnFreezeAccountEvent` with
/// the `unfrozen_address` set the `to_unfreeze_account`'s address.
///
/// # Parameters
/// | Name                  | Type      | Description                                                                                     |
/// | ------                | ------    | -------------                                                                                   |
/// | `tc_account`          | `signer`  | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
/// | `sliding_nonce`       | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
/// | `to_unfreeze_account` | `address` | The account address to be frozen.                                                               |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                            | Description                                                                                |
/// | ----------------           | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::freeze_account`
pub fn encode_unfreeze_account_script_function(
    sliding_nonce: u64,
    to_unfreeze_account: AccountAddress,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("unfreeze_account").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&to_unfreeze_account).unwrap(),
        ],
    ))
}

/// # Summary
/// Updates the Diem consensus config that is stored on-chain and is used by the Consensus.  This
/// transaction can only be sent from the Diem Root account.
///
/// # Technical Description
/// Updates the `DiemConsensusConfig` on-chain config and emits a `DiemConfig::NewEpochEvent` to trigger
/// a reconfiguration of the system.
///
/// # Parameters
/// | Name            | Type          | Description                                                                |
/// | ------          | ------        | -------------                                                              |
/// | `account`       | `signer`      | Signer of the sending account. Must be the Diem Root account.              |
/// | `sliding_nonce` | `u64`         | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
/// | `config`        | `vector<u8>`  | The serialized bytes of consensus config.                                  |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                  | Description                                                                                |
/// | ----------------           | --------------                                | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                   | `account` is not the Diem Root account.                                                    |
pub fn encode_update_diem_consensus_config_script_function(
    sliding_nonce: u64,
    config: Vec<u8>,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("SystemAdministrationScripts").to_owned(),
        ),
        ident_str!("update_diem_consensus_config").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&config).unwrap(),
        ],
    ))
}

/// # Summary
/// Updates the Diem major version that is stored on-chain and is used by the VM.  This
/// transaction can only be sent from the Diem Root account.
///
/// # Technical Description
/// Updates the `DiemVersion` on-chain config and emits a `DiemConfig::NewEpochEvent` to trigger
/// a reconfiguration of the system. The `major` version that is passed in must be strictly greater
/// than the current major version held on-chain. The VM reads this information and can use it to
/// preserve backwards compatibility with previous major versions of the VM.
///
/// # Parameters
/// | Name            | Type     | Description                                                                |
/// | ------          | ------   | -------------                                                              |
/// | `account`       | `signer` | Signer of the sending account. Must be the Diem Root account.              |
/// | `sliding_nonce` | `u64`    | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
/// | `major`         | `u64`    | The `major` version of the VM to be used from this transaction on.         |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                  | Description                                                                                |
/// | ----------------           | --------------                                | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                   | `account` is not the Diem Root account.                                                    |
/// | `Errors::INVALID_ARGUMENT` | `DiemVersion::EINVALID_MAJOR_VERSION_NUMBER`  | `major` is less-than or equal to the current major version stored on-chain.                |
pub fn encode_update_diem_version_script_function(
    sliding_nonce: u64,
    major: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("SystemAdministrationScripts").to_owned(),
        ),
        ident_str!("update_diem_version").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&major).unwrap(),
        ],
    ))
}

/// # Summary
/// Update the dual attestation limit on-chain. Defined in terms of micro-XDX.  The transaction can
/// only be sent by the Treasury Compliance account.  After this transaction all inter-VASP
/// payments over this limit must be checked for dual attestation.
///
/// # Technical Description
/// Updates the `micro_xdx_limit` field of the `DualAttestation::Limit` resource published under
/// `0xA550C18`. The amount is set in micro-XDX.
///
/// # Parameters
/// | Name                  | Type     | Description                                                                                     |
/// | ------                | ------   | -------------                                                                                   |
/// | `tc_account`          | `signer` | The signer of the sending account of this transaction. Must be the Treasury Compliance account. |
/// | `sliding_nonce`       | `u64`    | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
/// | `new_micro_xdx_limit` | `u64`    | The new dual attestation limit to be used on-chain.                                             |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                            | Description                                                                                |
/// | ----------------           | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | `tc_account` is not the Treasury Compliance account.                                       |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::update_exchange_rate`
/// * `TreasuryComplianceScripts::update_minting_ability`
pub fn encode_update_dual_attestation_limit_script_function(
    sliding_nonce: u64,
    new_micro_xdx_limit: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("update_dual_attestation_limit").to_owned(),
        vec![],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&new_micro_xdx_limit).unwrap(),
        ],
    ))
}

/// # Summary
/// Update the rough on-chain exchange rate between a specified currency and XDX (as a conversion
/// to micro-XDX). The transaction can only be sent by the Treasury Compliance account. After this
/// transaction the updated exchange rate will be used for normalization of gas prices, and for
/// dual attestation checking.
///
/// # Technical Description
/// Updates the on-chain exchange rate from the given `Currency` to micro-XDX.  The exchange rate
/// is given by `new_exchange_rate_numerator/new_exchange_rate_denominator`.
///
/// # Parameters
/// | Name                            | Type     | Description                                                                                                                        |
/// | ------                          | ------   | -------------                                                                                                                      |
/// | `Currency`                      | Type     | The Move type for the `Currency` whose exchange rate is being updated. `Currency` must be an already-registered currency on-chain. |
/// | `dm_account`                    | `signer` | The signer of the sending account of this transaction. Must be the Treasury Compliance account.                                    |
/// | `sliding_nonce`                 | `u64`    | The `sliding_nonce` (see: `SlidingNonce`) to be used for the transaction.                                                          |
/// | `new_exchange_rate_numerator`   | `u64`    | The numerator for the new to micro-XDX exchange rate for `Currency`.                                                               |
/// | `new_exchange_rate_denominator` | `u64`    | The denominator for the new to micro-XDX exchange rate for `Currency`.                                                             |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                            | Description                                                                                |
/// | ----------------           | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dm_account`.                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | `dm_account` is not the Treasury Compliance account.                                       |
/// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`           | `dm_account` is not the Treasury Compliance account.                                       |
/// | `Errors::INVALID_ARGUMENT` | `FixedPoint32::EDENOMINATOR`            | `new_exchange_rate_denominator` is zero.                                                   |
/// | `Errors::INVALID_ARGUMENT` | `FixedPoint32::ERATIO_OUT_OF_RANGE`     | The quotient is unrepresentable as a `FixedPoint32`.                                       |
/// | `Errors::LIMIT_EXCEEDED`   | `FixedPoint32::ERATIO_OUT_OF_RANGE`     | The quotient is unrepresentable as a `FixedPoint32`.                                       |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::update_dual_attestation_limit`
/// * `TreasuryComplianceScripts::update_minting_ability`
pub fn encode_update_exchange_rate_script_function(
    currency: TypeTag,
    sliding_nonce: u64,
    new_exchange_rate_numerator: u64,
    new_exchange_rate_denominator: u64,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("update_exchange_rate").to_owned(),
        vec![currency],
        vec![
            bcs::to_bytes(&sliding_nonce).unwrap(),
            bcs::to_bytes(&new_exchange_rate_numerator).unwrap(),
            bcs::to_bytes(&new_exchange_rate_denominator).unwrap(),
        ],
    ))
}

/// # Summary
/// Script to allow or disallow minting of new coins in a specified currency.  This transaction can
/// only be sent by the Treasury Compliance account.  Turning minting off for a currency will have
/// no effect on coins already in circulation, and coins may still be removed from the system.
///
/// # Technical Description
/// This transaction sets the `can_mint` field of the `Diem::CurrencyInfo<Currency>` resource
/// published under `0xA550C18` to the value of `allow_minting`. Minting of coins if allowed if
/// this field is set to `true` and minting of new coins in `Currency` is disallowed otherwise.
/// This transaction needs to be sent by the Treasury Compliance account.
///
/// # Parameters
/// | Name            | Type     | Description                                                                                                                          |
/// | ------          | ------   | -------------                                                                                                                        |
/// | `Currency`      | Type     | The Move type for the `Currency` whose minting ability is being updated. `Currency` must be an already-registered currency on-chain. |
/// | `account`       | `signer` | Signer of the sending account. Must be the Diem Root account.                                                                        |
/// | `allow_minting` | `bool`   | Whether to allow minting of new coins in `Currency`.                                                                                 |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                          | Description                                          |
/// | ----------------           | --------------                        | -------------                                        |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE` | `tc_account` is not the Treasury Compliance account. |
/// | `Errors::NOT_PUBLISHED`    | `Diem::ECURRENCY_INFO`               | `Currency` is not a registered currency on-chain.    |
///
/// # Related Scripts
/// * `TreasuryComplianceScripts::update_dual_attestation_limit`
/// * `TreasuryComplianceScripts::update_exchange_rate`
pub fn encode_update_minting_ability_script_function(
    currency: TypeTag,
    allow_minting: bool,
) -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("TreasuryComplianceScripts").to_owned(),
        ),
        ident_str!("update_minting_ability").to_owned(),
        vec![currency],
        vec![bcs::to_bytes(&allow_minting).unwrap()],
    ))
}

pub fn encode_val_add_self_script_function() -> TransactionPayload {
    TransactionPayload::ScriptFunction(ScriptFunction::new(
        ModuleId::new(
            AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
            ident_str!("ValidatorScripts").to_owned(),
        ),
        ident_str!("val_add_self").to_owned(),
        vec![],
        vec![],
    ))
}

/// # Summary
/// Adds a zero `Currency` balance to the sending `account`. This will enable `account` to
/// send, receive, and hold `Diem::Diem<Currency>` coins. This transaction can be
/// successfully sent by any account that is allowed to hold balances
/// (e.g., VASP, Designated Dealer).
///
/// # Technical Description
/// After the successful execution of this transaction the sending account will have a
/// `DiemAccount::Balance<Currency>` resource with zero balance published under it. Only
/// accounts that can hold balances can send this transaction, the sending account cannot
/// already have a `DiemAccount::Balance<Currency>` published under it.
///
/// # Parameters
/// | Name       | Type      | Description                                                                                                                                         |
/// | ------     | ------    | -------------                                                                                                                                       |
/// | `Currency` | Type      | The Move type for the `Currency` being added to the sending account of the transaction. `Currency` must be an already-registered currency on-chain. |
/// | `account`  | `&signer` | The signer of the sending account of the transaction.                                                                                               |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                             | Description                                                                |
/// | ----------------            | --------------                           | -------------                                                              |
/// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                  | The `Currency` is not a registered currency on-chain.                      |
/// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::EROLE_CANT_STORE_BALANCE` | The sending `account`'s role does not permit balances.                     |
/// | `Errors::ALREADY_PUBLISHED` | `DiemAccount::EADD_EXISTING_CURRENCY`   | A balance for `Currency` is already published under the sending `account`. |
///
/// # Related Scripts
/// * `Script::create_child_vasp_account`
/// * `Script::create_parent_vasp_account`
/// * `Script::peer_to_peer_with_metadata`
pub fn encode_add_currency_to_account_script(currency: TypeTag) -> Script {
    Script::new(
        ADD_CURRENCY_TO_ACCOUNT_CODE.to_vec(),
        vec![currency],
        vec![],
    )
}

/// # Summary
/// Stores the sending accounts ability to rotate its authentication key with a designated recovery
/// account. Both the sending and recovery accounts need to belong to the same VASP and
/// both be VASP accounts. After this transaction both the sending account and the
/// specified recovery account can rotate the sender account's authentication key.
///
/// # Technical Description
/// Adds the `DiemAccount::KeyRotationCapability` for the sending account
/// (`to_recover_account`) to the `RecoveryAddress::RecoveryAddress` resource under
/// `recovery_address`. After this transaction has been executed successfully the account at
/// `recovery_address` and the `to_recover_account` may rotate the authentication key of
/// `to_recover_account` (the sender of this transaction).
///
/// The sending account of this transaction (`to_recover_account`) must not have previously given away its unique key
/// rotation capability, and must be a VASP account. The account at `recovery_address`
/// must also be a VASP account belonging to the same VASP as the `to_recover_account`.
/// Additionally the account at `recovery_address` must have already initialized itself as
/// a recovery account address using the `Script::create_recovery_address` transaction script.
///
/// The sending account's (`to_recover_account`) key rotation capability is
/// removed in this transaction and stored in the `RecoveryAddress::RecoveryAddress`
/// resource stored under the account at `recovery_address`.
///
/// # Parameters
/// | Name                 | Type      | Description                                                                                                |
/// | ------               | ------    | -------------                                                                                              |
/// | `to_recover_account` | `&signer` | The signer reference of the sending account of this transaction.                                           |
/// | `recovery_address`   | `address` | The account address where the `to_recover_account`'s `DiemAccount::KeyRotationCapability` will be stored. |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                              | Description                                                                                       |
/// | ----------------           | --------------                                            | -------------                                                                                     |
/// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `to_recover_account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.    |
/// | `Errors::NOT_PUBLISHED`    | `RecoveryAddress::ERECOVERY_ADDRESS`                      | `recovery_address` does not have a `RecoveryAddress` resource published under it.                 |
/// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::EINVALID_KEY_ROTATION_DELEGATION`       | `to_recover_account` and `recovery_address` do not belong to the same VASP.                       |
/// | `Errors::LIMIT_EXCEEDED`   | ` RecoveryAddress::EMAX_KEYS_REGISTERED`                  | `RecoveryAddress::MAX_REGISTERED_KEYS` have already been registered with this `recovery_address`. |
///
/// # Related Scripts
/// * `Script::create_recovery_address`
/// * `Script::rotate_authentication_key_with_recovery_address`
pub fn encode_add_recovery_rotation_capability_script(recovery_address: AccountAddress) -> Script {
    Script::new(
        ADD_RECOVERY_ROTATION_CAPABILITY_CODE.to_vec(),
        vec![],
        vec![TransactionArgument::Address(recovery_address)],
    )
}

/// # Summary
/// Adds a validator account to the validator set, and triggers a
/// reconfiguration of the system to admit the account to the validator set for the system. This
/// transaction can only be successfully called by the Diem Root account.
///
/// # Technical Description
/// This script adds the account at `validator_address` to the validator set.
/// This transaction emits a `DiemConfig::NewEpochEvent` event and triggers a
/// reconfiguration. Once the reconfiguration triggered by this script's
/// execution has been performed, the account at the `validator_address` is
/// considered to be a validator in the network.
///
/// This transaction script will fail if the `validator_address` address is already in the validator set
/// or does not have a `ValidatorConfig::ValidatorConfig` resource already published under it.
///
/// # Parameters
/// | Name                | Type         | Description                                                                                                                        |
/// | ------              | ------       | -------------                                                                                                                      |
/// | `dr_account`        | `&signer`    | The signer reference of the sending account of this transaction. Must be the Diem Root signer.                                    |
/// | `sliding_nonce`     | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                         |
/// | `validator_name`    | `vector<u8>` | ASCII-encoded human name for the validator. Must match the human name in the `ValidatorConfig::ValidatorConfig` for the validator. |
/// | `validator_address` | `address`    | The validator account address to be added to the validator set.                                                                    |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                  | Description                                                                                                                               |
/// | ----------------           | --------------                                | -------------                                                                                                                             |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `dr_account`.                                                                            |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                                                                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                                                                         |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                  | The sending account is not the Diem Root account.                                                                                        |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EDIEM_ROOT`                          | The sending account is not the Diem Root account.                                                                                        |
/// | 0                          | 0                                             | The provided `validator_name` does not match the already-recorded human name for the validator.                                           |
/// | `Errors::INVALID_ARGUMENT` | `DiemSystem::EINVALID_PROSPECTIVE_VALIDATOR` | The validator to be added does not have a `ValidatorConfig::ValidatorConfig` resource published under it, or its `config` field is empty. |
/// | `Errors::INVALID_ARGUMENT` | `DiemSystem::EALREADY_A_VALIDATOR`           | The `validator_address` account is already a registered validator.                                                                        |
/// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`            | An invalid time value was encountered in reconfiguration. Unlikely to occur.                                                              |
///
/// # Related Scripts
/// * `Script::create_validator_account`
/// * `Script::create_validator_operator_account`
/// * `Script::register_validator_config`
/// * `Script::remove_validator_and_reconfigure`
/// * `Script::set_validator_operator`
/// * `Script::set_validator_operator_with_nonce_admin`
/// * `Script::set_validator_config_and_reconfigure`
pub fn encode_add_validator_and_reconfigure_script(
    sliding_nonce: u64,
    validator_name: Vec<u8>,
    validator_address: AccountAddress,
) -> Script {
    Script::new(
        ADD_VALIDATOR_AND_RECONFIGURE_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::U8Vector(validator_name),
            TransactionArgument::Address(validator_address),
        ],
    )
}

/// # Summary
/// Burns all coins held in the preburn resource at the specified
/// preburn address and removes them from the system. The sending account must
/// be the Treasury Compliance account.
/// The account that holds the preburn resource will normally be a Designated
/// Dealer, but there are no enforced requirements that it be one.
///
/// # Technical Description
/// This transaction permanently destroys all the coins of `Token` type
/// stored in the `Diem::Preburn<Token>` resource published under the
/// `preburn_address` account address.
///
/// This transaction will only succeed if the sending `account` has a
/// `Diem::BurnCapability<Token>`, and a `Diem::Preburn<Token>` resource
/// exists under `preburn_address`, with a non-zero `to_burn` field. After the successful execution
/// of this transaction the `total_value` field in the
/// `Diem::CurrencyInfo<Token>` resource published under `0xA550C18` will be
/// decremented by the value of the `to_burn` field of the preburn resource
/// under `preburn_address` immediately before this transaction, and the
/// `to_burn` field of the preburn resource will have a zero value.
///
/// ## Events
/// The successful execution of this transaction will emit a `Diem::BurnEvent` on the event handle
/// held in the `Diem::CurrencyInfo<Token>` resource's `burn_events` published under
/// `0xA550C18`.
///
/// # Parameters
/// | Name              | Type      | Description                                                                                                                  |
/// | ------            | ------    | -------------                                                                                                                |
/// | `Token`           | Type      | The Move type for the `Token` currency being burned. `Token` must be an already-registered currency on-chain.                |
/// | `tc_account`      | `&signer` | The signer reference of the sending account of this transaction, must have a burn capability for `Token` published under it. |
/// | `sliding_nonce`   | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                   |
/// | `preburn_address` | `address` | The address where the coins to-be-burned are currently held.                                                                 |
///
/// # Common Abort Conditions
/// | Error Category                | Error Reason                            | Description                                                                                           |
/// | ----------------              | --------------                          | -------------                                                                                         |
/// | `Errors::NOT_PUBLISHED`       | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `account`.                                           |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.            |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                                         |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                                     |
/// | `Errors::REQUIRES_CAPABILITY` | `Diem::EBURN_CAPABILITY`               | The sending `account` does not have a `Diem::BurnCapability<Token>` published under it.              |
/// | `Errors::NOT_PUBLISHED`       | `Diem::EPREBURN`                       | The account at `preburn_address` does not have a `Diem::Preburn<Token>` resource published under it. |
/// | `Errors::INVALID_STATE`       | `Diem::EPREBURN_EMPTY`                 | The `Diem::Preburn<Token>` resource is empty (has a value of 0).                                     |
/// | `Errors::NOT_PUBLISHED`       | `Diem::ECURRENCY_INFO`                 | The specified `Token` is not a registered currency on-chain.                                          |
///
/// # Related Scripts
/// * `Script::burn_txn_fees`
/// * `Script::cancel_burn`
/// * `Script::preburn`
pub fn encode_burn_script(
    token: TypeTag,
    sliding_nonce: u64,
    preburn_address: AccountAddress,
) -> Script {
    Script::new(
        BURN_CODE.to_vec(),
        vec![token],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::Address(preburn_address),
        ],
    )
}

/// # Summary
/// Burns the transaction fees collected in the `CoinType` currency so that the
/// Diem association may reclaim the backing coins off-chain. May only be sent
/// by the Treasury Compliance account.
///
/// # Technical Description
/// Burns the transaction fees collected in `CoinType` so that the
/// association may reclaim the backing coins. Once this transaction has executed
/// successfully all transaction fees that will have been collected in
/// `CoinType` since the last time this script was called with that specific
/// currency. Both `balance` and `preburn` fields in the
/// `TransactionFee::TransactionFee<CoinType>` resource published under the `0xB1E55ED`
/// account address will have a value of 0 after the successful execution of this script.
///
/// ## Events
/// The successful execution of this transaction will emit a `Diem::BurnEvent` on the event handle
/// held in the `Diem::CurrencyInfo<CoinType>` resource's `burn_events` published under
/// `0xA550C18`.
///
/// # Parameters
/// | Name         | Type      | Description                                                                                                                                         |
/// | ------       | ------    | -------------                                                                                                                                       |
/// | `CoinType`   | Type      | The Move type for the `CoinType` being added to the sending account of the transaction. `CoinType` must be an already-registered currency on-chain. |
/// | `tc_account` | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.                                           |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                          | Description                                                 |
/// | ----------------           | --------------                        | -------------                                               |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE` | The sending account is not the Treasury Compliance account. |
/// | `Errors::NOT_PUBLISHED`    | `TransactionFee::ETRANSACTION_FEE`    | `CoinType` is not an accepted transaction fee currency.     |
/// | `Errors::INVALID_ARGUMENT` | `Diem::ECOIN`                        | The collected fees in `CoinType` are zero.                  |
///
/// # Related Scripts
/// * `Script::burn`
/// * `Script::cancel_burn`
pub fn encode_burn_txn_fees_script(coin_type: TypeTag) -> Script {
    Script::new(BURN_TXN_FEES_CODE.to_vec(), vec![coin_type], vec![])
}

/// # Summary
/// Cancels and returns all coins held in the preburn area under
/// `preburn_address` and returns the funds to the `preburn_address`'s balance.
/// Can only be successfully sent by an account with Treasury Compliance role.
///
/// # Technical Description
/// Cancels and returns all coins held in the `Diem::Preburn<Token>` resource under the `preburn_address` and
/// return the funds to the `preburn_address` account's `DiemAccount::Balance<Token>`.
/// The transaction must be sent by an `account` with a `Diem::BurnCapability<Token>`
/// resource published under it. The account at `preburn_address` must have a
/// `Diem::Preburn<Token>` resource published under it, and its value must be nonzero. The transaction removes
/// the entire balance held in the `Diem::Preburn<Token>` resource, and returns it back to the account's
/// `DiemAccount::Balance<Token>` under `preburn_address`. Due to this, the account at
/// `preburn_address` must already have a balance in the `Token` currency published
/// before this script is called otherwise the transaction will fail.
///
/// ## Events
/// The successful execution of this transaction will emit:
/// * A `Diem::CancelBurnEvent` on the event handle held in the `Diem::CurrencyInfo<Token>`
/// resource's `burn_events` published under `0xA550C18`.
/// * A `DiemAccount::ReceivedPaymentEvent` on the `preburn_address`'s
/// `DiemAccount::DiemAccount` `received_events` event handle with both the `payer` and `payee`
/// being `preburn_address`.
///
/// # Parameters
/// | Name              | Type      | Description                                                                                                                          |
/// | ------            | ------    | -------------                                                                                                                        |
/// | `Token`           | Type      | The Move type for the `Token` currenty that burning is being cancelled for. `Token` must be an already-registered currency on-chain. |
/// | `account`         | `&signer` | The signer reference of the sending account of this transaction, must have a burn capability for `Token` published under it.         |
/// | `preburn_address` | `address` | The address where the coins to-be-burned are currently held.                                                                         |
///
/// # Common Abort Conditions
/// | Error Category                | Error Reason                                     | Description                                                                                           |
/// | ----------------              | --------------                                   | -------------                                                                                         |
/// | `Errors::REQUIRES_CAPABILITY` | `Diem::EBURN_CAPABILITY`                        | The sending `account` does not have a `Diem::BurnCapability<Token>` published under it.              |
/// | `Errors::NOT_PUBLISHED`       | `Diem::EPREBURN`                                | The account at `preburn_address` does not have a `Diem::Preburn<Token>` resource published under it. |
/// | `Errors::NOT_PUBLISHED`       | `Diem::ECURRENCY_INFO`                          | The specified `Token` is not a registered currency on-chain.                                          |
/// | `Errors::INVALID_ARGUMENT`    | `DiemAccount::ECOIN_DEPOSIT_IS_ZERO`            | The value held in the preburn resource was zero.                                                      |
/// | `Errors::INVALID_ARGUMENT`    | `DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE` | The account at `preburn_address` doesn't have a balance resource for `Token`.                         |
/// | `Errors::LIMIT_EXCEEDED`      | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`          | The depositing of the funds held in the prebun area would exceed the `account`'s account limits.      |
/// | `Errors::INVALID_STATE`       | `DualAttestation::EPAYEE_COMPLIANCE_KEY_NOT_SET` | The `account` does not have a compliance key set on it but dual attestion checking was performed.     |
///
/// # Related Scripts
/// * `Script::burn_txn_fees`
/// * `Script::burn`
/// * `Script::preburn`
pub fn encode_cancel_burn_script(token: TypeTag, preburn_address: AccountAddress) -> Script {
    Script::new(
        CANCEL_BURN_CODE.to_vec(),
        vec![token],
        vec![TransactionArgument::Address(preburn_address)],
    )
}

/// # Summary
/// Creates a Child VASP account with its parent being the sending account of the transaction.
/// The sender of the transaction must be a Parent VASP account.
///
/// # Technical Description
/// Creates a `ChildVASP` account for the sender `parent_vasp` at `child_address` with a balance of
/// `child_initial_balance` in `CoinType` and an initial authentication key of
/// `auth_key_prefix | child_address`.
///
/// If `add_all_currencies` is true, the child address will have a zero balance in all available
/// currencies in the system.
///
/// The new account will be a child account of the transaction sender, which must be a
/// Parent VASP account. The child account will be recorded against the limit of
/// child accounts of the creating Parent VASP account.
///
/// ## Events
/// Successful execution with a `child_initial_balance` greater than zero will emit:
/// * A `DiemAccount::SentPaymentEvent` with the `payer` field being the Parent VASP's address,
/// and payee field being `child_address`. This is emitted on the Parent VASP's
/// `DiemAccount::DiemAccount` `sent_events` handle.
/// * A `DiemAccount::ReceivedPaymentEvent` with the  `payer` field being the Parent VASP's address,
/// and payee field being `child_address`. This is emitted on the new Child VASPS's
/// `DiemAccount::DiemAccount` `received_events` handle.
///
/// # Parameters
/// | Name                    | Type         | Description                                                                                                                                 |
/// | ------                  | ------       | -------------                                                                                                                               |
/// | `CoinType`              | Type         | The Move type for the `CoinType` that the child account should be created with. `CoinType` must be an already-registered currency on-chain. |
/// | `parent_vasp`           | `&signer`    | The signer reference of the sending account. Must be a Parent VASP account.                                                                 |
/// | `child_address`         | `address`    | Address of the to-be-created Child VASP account.                                                                                            |
/// | `auth_key_prefix`       | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                    |
/// | `add_all_currencies`    | `bool`       | Whether to publish balance resources for all known currencies when the account is created.                                                  |
/// | `child_initial_balance` | `u64`        | The initial balance in `CoinType` to give the child account when it's created.                                                              |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                                             | Description                                                                              |
/// | ----------------            | --------------                                           | -------------                                                                            |
/// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`            | The `auth_key_prefix` was not of length 32.                                              |
/// | `Errors::REQUIRES_ROLE`     | `Roles::EPARENT_VASP`                                    | The sending account wasn't a Parent VASP account.                                        |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                                        | The `child_address` address is already taken.                                            |
/// | `Errors::LIMIT_EXCEEDED`    | `VASP::ETOO_MANY_CHILDREN`                               | The sending account has reached the maximum number of allowed child accounts.            |
/// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                                  | The `CoinType` is not a registered currency on-chain.                                    |
/// | `Errors::INVALID_STATE`     | `DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED` | The withdrawal capability for the sending account has already been extracted.            |
/// | `Errors::NOT_PUBLISHED`     | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`              | The sending account doesn't have a balance in `CoinType`.                                |
/// | `Errors::LIMIT_EXCEEDED`    | `DiemAccount::EINSUFFICIENT_BALANCE`                    | The sending account doesn't have at least `child_initial_balance` of `CoinType` balance. |
/// | `Errors::INVALID_ARGUMENT`  | `DiemAccount::ECANNOT_CREATE_AT_VM_RESERVED`            | The `child_address` is the reserved address 0x0.                                         |
///
/// # Related Scripts
/// * `Script::create_parent_vasp_account`
/// * `Script::add_currency_to_account`
/// * `Script::rotate_authentication_key`
/// * `Script::add_recovery_rotation_capability`
/// * `Script::create_recovery_address`
pub fn encode_create_child_vasp_account_script(
    coin_type: TypeTag,
    child_address: AccountAddress,
    auth_key_prefix: Vec<u8>,
    add_all_currencies: bool,
    child_initial_balance: u64,
) -> Script {
    Script::new(
        CREATE_CHILD_VASP_ACCOUNT_CODE.to_vec(),
        vec![coin_type],
        vec![
            TransactionArgument::Address(child_address),
            TransactionArgument::U8Vector(auth_key_prefix),
            TransactionArgument::Bool(add_all_currencies),
            TransactionArgument::U64(child_initial_balance),
        ],
    )
}

/// # Summary
/// Creates a Designated Dealer account with the provided information, and initializes it with
/// default mint tiers. The transaction can only be sent by the Treasury Compliance account.
///
/// # Technical Description
/// Creates an account with the Designated Dealer role at `addr` with authentication key
/// `auth_key_prefix` | `addr` and a 0 balance of type `Currency`. If `add_all_currencies` is true,
/// 0 balances for all available currencies in the system will also be added. This can only be
/// invoked by an account with the TreasuryCompliance role.
///
/// At the time of creation the account is also initialized with default mint tiers of (500_000,
/// 5000_000, 50_000_000, 500_000_000), and preburn areas for each currency that is added to the
/// account.
///
/// # Parameters
/// | Name                 | Type         | Description                                                                                                                                         |
/// | ------               | ------       | -------------                                                                                                                                       |
/// | `Currency`           | Type         | The Move type for the `Currency` that the Designated Dealer should be initialized with. `Currency` must be an already-registered currency on-chain. |
/// | `tc_account`         | `&signer`    | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.                                           |
/// | `sliding_nonce`      | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                                          |
/// | `addr`               | `address`    | Address of the to-be-created Designated Dealer account.                                                                                             |
/// | `auth_key_prefix`    | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                            |
/// | `human_name`         | `vector<u8>` | ASCII-encoded human name for the Designated Dealer.                                                                                                 |
/// | `add_all_currencies` | `bool`       | Whether to publish preburn, balance, and tier info resources for all known (SCS) currencies or just `Currency` when the account is created.         |
///

/// # Common Abort Conditions
/// | Error Category              | Error Reason                            | Description                                                                                |
/// | ----------------            | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::REQUIRES_ROLE`     | `Roles::ETREASURY_COMPLIANCE`           | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                 | The `Currency` is not a registered currency on-chain.                                      |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `addr` address is already taken.                                                       |
///
/// # Related Scripts
/// * `Script::tiered_mint`
/// * `Script::peer_to_peer_with_metadata`
/// * `Script::rotate_dual_attestation_info`
pub fn encode_create_designated_dealer_script(
    currency: TypeTag,
    sliding_nonce: u64,
    addr: AccountAddress,
    auth_key_prefix: Vec<u8>,
    human_name: Vec<u8>,
    add_all_currencies: bool,
) -> Script {
    Script::new(
        CREATE_DESIGNATED_DEALER_CODE.to_vec(),
        vec![currency],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::Address(addr),
            TransactionArgument::U8Vector(auth_key_prefix),
            TransactionArgument::U8Vector(human_name),
            TransactionArgument::Bool(add_all_currencies),
        ],
    )
}

/// # Summary
/// Creates a Parent VASP account with the specified human name. Must be called by the Treasury Compliance account.
///
/// # Technical Description
/// Creates an account with the Parent VASP role at `address` with authentication key
/// `auth_key_prefix` | `new_account_address` and a 0 balance of type `CoinType`. If
/// `add_all_currencies` is true, 0 balances for all available currencies in the system will
/// also be added. This can only be invoked by an TreasuryCompliance account.
/// `sliding_nonce` is a unique nonce for operation, see `SlidingNonce` for details.
///
/// # Parameters
/// | Name                  | Type         | Description                                                                                                                                                    |
/// | ------                | ------       | -------------                                                                                                                                                  |
/// | `CoinType`            | Type         | The Move type for the `CoinType` currency that the Parent VASP account should be initialized with. `CoinType` must be an already-registered currency on-chain. |
/// | `tc_account`          | `&signer`    | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.                                                      |
/// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                                                     |
/// | `new_account_address` | `address`    | Address of the to-be-created Parent VASP account.                                                                                                              |
/// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.                                                                       |
/// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the Parent VASP.                                                                                                                  |
/// | `add_all_currencies`  | `bool`       | Whether to publish balance resources for all known currencies when the account is created.                                                                     |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                            | Description                                                                                |
/// | ----------------            | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::REQUIRES_ROLE`     | `Roles::ETREASURY_COMPLIANCE`           | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::NOT_PUBLISHED`     | `Diem::ECURRENCY_INFO`                 | The `CoinType` is not a registered currency on-chain.                                      |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
///
/// # Related Scripts
/// * `Script::create_child_vasp_account`
/// * `Script::add_currency_to_account`
/// * `Script::rotate_authentication_key`
/// * `Script::add_recovery_rotation_capability`
/// * `Script::create_recovery_address`
/// * `Script::rotate_dual_attestation_info`
pub fn encode_create_parent_vasp_account_script(
    coin_type: TypeTag,
    sliding_nonce: u64,
    new_account_address: AccountAddress,
    auth_key_prefix: Vec<u8>,
    human_name: Vec<u8>,
    add_all_currencies: bool,
) -> Script {
    Script::new(
        CREATE_PARENT_VASP_ACCOUNT_CODE.to_vec(),
        vec![coin_type],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::Address(new_account_address),
            TransactionArgument::U8Vector(auth_key_prefix),
            TransactionArgument::U8Vector(human_name),
            TransactionArgument::Bool(add_all_currencies),
        ],
    )
}

/// # Summary
/// Initializes the sending account as a recovery address that may be used by
/// the VASP that it belongs to. The sending account must be a VASP account.
/// Multiple recovery addresses can exist for a single VASP, but accounts in
/// each must be disjoint.
///
/// # Technical Description
/// Publishes a `RecoveryAddress::RecoveryAddress` resource under `account`. It then
/// extracts the `DiemAccount::KeyRotationCapability` for `account` and adds
/// it to the resource. After the successful execution of this transaction
/// other accounts may add their key rotation to this resource so that `account`
/// may be used as a recovery account for those accounts.
///
/// # Parameters
/// | Name      | Type      | Description                                           |
/// | ------    | ------    | -------------                                         |
/// | `account` | `&signer` | The signer of the sending account of the transaction. |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                                               | Description                                                                                   |
/// | ----------------            | --------------                                             | -------------                                                                                 |
/// | `Errors::INVALID_STATE`     | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.          |
/// | `Errors::INVALID_ARGUMENT`  | `RecoveryAddress::ENOT_A_VASP`                             | `account` is not a VASP account.                                                              |
/// | `Errors::INVALID_ARGUMENT`  | `RecoveryAddress::EKEY_ROTATION_DEPENDENCY_CYCLE`          | A key rotation recovery cycle would be created by adding `account`'s key rotation capability. |
/// | `Errors::ALREADY_PUBLISHED` | `RecoveryAddress::ERECOVERY_ADDRESS`                       | A `RecoveryAddress::RecoveryAddress` resource has already been published under `account`.     |
///
/// # Related Scripts
/// * `Script::add_recovery_rotation_capability`
/// * `Script::rotate_authentication_key_with_recovery_address`
pub fn encode_create_recovery_address_script() -> Script {
    Script::new(CREATE_RECOVERY_ADDRESS_CODE.to_vec(), vec![], vec![])
}

/// # Summary
/// Creates a Validator account. This transaction can only be sent by the Diem
/// Root account.
///
/// # Technical Description
/// Creates an account with a Validator role at `new_account_address`, with authentication key
/// `auth_key_prefix` | `new_account_address`. It publishes a
/// `ValidatorConfig::ValidatorConfig` resource with empty `config`, and
/// `operator_account` fields. The `human_name` field of the
/// `ValidatorConfig::ValidatorConfig` is set to the passed in `human_name`.
/// This script does not add the validator to the validator set or the system,
/// but only creates the account.
///
/// # Parameters
/// | Name                  | Type         | Description                                                                                     |
/// | ------                | ------       | -------------                                                                                   |
/// | `dr_account`          | `&signer`    | The signer reference of the sending account of this transaction. Must be the Diem Root signer. |
/// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
/// | `new_account_address` | `address`    | Address of the to-be-created Validator account.                                                 |
/// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.        |
/// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the validator.                                                     |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                            | Description                                                                                |
/// | ----------------            | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                             |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                         |
/// | `Errors::REQUIRES_ROLE`     | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                         |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
///
/// # Related Scripts
/// * `Script::add_validator_and_reconfigure`
/// * `Script::create_validator_operator_account`
/// * `Script::register_validator_config`
/// * `Script::remove_validator_and_reconfigure`
/// * `Script::set_validator_operator`
/// * `Script::set_validator_operator_with_nonce_admin`
/// * `Script::set_validator_config_and_reconfigure`
pub fn encode_create_validator_account_script(
    sliding_nonce: u64,
    new_account_address: AccountAddress,
    auth_key_prefix: Vec<u8>,
    human_name: Vec<u8>,
) -> Script {
    Script::new(
        CREATE_VALIDATOR_ACCOUNT_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::Address(new_account_address),
            TransactionArgument::U8Vector(auth_key_prefix),
            TransactionArgument::U8Vector(human_name),
        ],
    )
}

/// # Summary
/// Creates a Validator Operator account. This transaction can only be sent by the Diem
/// Root account.
///
/// # Technical Description
/// Creates an account with a Validator Operator role at `new_account_address`, with authentication key
/// `auth_key_prefix` | `new_account_address`. It publishes a
/// `ValidatorOperatorConfig::ValidatorOperatorConfig` resource with the specified `human_name`.
/// This script does not assign the validator operator to any validator accounts but only creates the account.
///
/// # Parameters
/// | Name                  | Type         | Description                                                                                     |
/// | ------                | ------       | -------------                                                                                   |
/// | `dr_account`          | `&signer`    | The signer reference of the sending account of this transaction. Must be the Diem Root signer. |
/// | `sliding_nonce`       | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                      |
/// | `new_account_address` | `address`    | Address of the to-be-created Validator account.                                                 |
/// | `auth_key_prefix`     | `vector<u8>` | The authentication key prefix that will be used initially for the newly created account.        |
/// | `human_name`          | `vector<u8>` | ASCII-encoded human name for the validator.                                                     |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                            | Description                                                                                |
/// | ----------------            | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`     | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                             |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT`  | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS`  | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                         |
/// | `Errors::REQUIRES_ROLE`     | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                         |
/// | `Errors::ALREADY_PUBLISHED` | `Roles::EROLE_ID`                       | The `new_account_address` address is already taken.                                        |
///
/// # Related Scripts
/// * `Script::create_validator_account`
/// * `Script::add_validator_and_reconfigure`
/// * `Script::register_validator_config`
/// * `Script::remove_validator_and_reconfigure`
/// * `Script::set_validator_operator`
/// * `Script::set_validator_operator_with_nonce_admin`
/// * `Script::set_validator_config_and_reconfigure`
pub fn encode_create_validator_operator_account_script(
    sliding_nonce: u64,
    new_account_address: AccountAddress,
    auth_key_prefix: Vec<u8>,
    human_name: Vec<u8>,
) -> Script {
    Script::new(
        CREATE_VALIDATOR_OPERATOR_ACCOUNT_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::Address(new_account_address),
            TransactionArgument::U8Vector(auth_key_prefix),
            TransactionArgument::U8Vector(human_name),
        ],
    )
}

/// # Summary
/// Freezes the account at `address`. The sending account of this transaction
/// must be the Treasury Compliance account. The account being frozen cannot be
/// the Diem Root or Treasury Compliance account. After the successful
/// execution of this transaction no transactions may be sent from the frozen
/// account, and the frozen account may not send or receive coins.
///
/// # Technical Description
/// Sets the `AccountFreezing::FreezingBit` to `true` and emits a
/// `AccountFreezing::FreezeAccountEvent`. The transaction sender must be the
/// Treasury Compliance account, but the account at `to_freeze_account` must
/// not be either `0xA550C18` (the Diem Root address), or `0xB1E55ED` (the
/// Treasury Compliance address). Note that this is a per-account property
/// e.g., freezing a Parent VASP will not effect the status any of its child
/// accounts and vice versa.
///

/// ## Events
/// Successful execution of this transaction will emit a `AccountFreezing::FreezeAccountEvent` on
/// the `freeze_event_handle` held in the `AccountFreezing::FreezeEventsHolder` resource published
/// under `0xA550C18` with the `frozen_address` being the `to_freeze_account`.
///
/// # Parameters
/// | Name                | Type      | Description                                                                                               |
/// | ------              | ------    | -------------                                                                                             |
/// | `tc_account`        | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account. |
/// | `sliding_nonce`     | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                |
/// | `to_freeze_account` | `address` | The account address to be frozen.                                                                         |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                 | Description                                                                                |
/// | ----------------           | --------------                               | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`        | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`                | The sending account is not the Treasury Compliance account.                                |
/// | `Errors::INVALID_ARGUMENT` | `AccountFreezing::ECANNOT_FREEZE_TC`         | `to_freeze_account` was the Treasury Compliance account (`0xB1E55ED`).                     |
/// | `Errors::INVALID_ARGUMENT` | `AccountFreezing::ECANNOT_FREEZE_DIEM_ROOT` | `to_freeze_account` was the Diem Root account (`0xA550C18`).                              |
///
/// # Related Scripts
/// * `Script::unfreeze_account`
pub fn encode_freeze_account_script(
    sliding_nonce: u64,
    to_freeze_account: AccountAddress,
) -> Script {
    Script::new(
        FREEZE_ACCOUNT_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::Address(to_freeze_account),
        ],
    )
}

/// # Summary
/// Transfers a given number of coins in a specified currency from one account to another.
/// Transfers over a specified amount defined on-chain that are between two different VASPs, or
/// other accounts that have opted-in will be subject to on-chain checks to ensure the receiver has
/// agreed to receive the coins.  This transaction can be sent by any account that can hold a
/// balance, and to any account that can hold a balance. Both accounts must hold balances in the
/// currency being transacted.
///
/// # Technical Description
///
/// Transfers `amount` coins of type `Currency` from `payer` to `payee` with (optional) associated
/// `metadata` and an (optional) `metadata_signature` on the message
/// `metadata` | `Signer::address_of(payer)` | `amount` | `DualAttestation::DOMAIN_SEPARATOR`.
/// The `metadata` and `metadata_signature` parameters are only required if `amount` >=
/// `DualAttestation::get_cur_microdiem_limit` XDX and `payer` and `payee` are distinct VASPs.
/// However, a transaction sender can opt in to dual attestation even when it is not required
/// (e.g., a DesignatedDealer -> VASP payment) by providing a non-empty `metadata_signature`.
/// Standardized `metadata` BCS format can be found in `diem_types::transaction::metadata::Metadata`.
///
/// ## Events
/// Successful execution of this script emits two events:
/// * A `DiemAccount::SentPaymentEvent` on `payer`'s `DiemAccount::DiemAccount` `sent_events` handle; and
/// * A `DiemAccount::ReceivedPaymentEvent` on `payee`'s `DiemAccount::DiemAccount` `received_events` handle.
///
/// # Parameters
/// | Name                 | Type         | Description                                                                                                                  |
/// | ------               | ------       | -------------                                                                                                                |
/// | `Currency`           | Type         | The Move type for the `Currency` being sent in this transaction. `Currency` must be an already-registered currency on-chain. |
/// | `payer`              | `&signer`    | The signer reference of the sending account that coins are being transferred from.                                           |
/// | `payee`              | `address`    | The address of the account the coins are being transferred to.                                                               |
/// | `metadata`           | `vector<u8>` | Optional metadata about this payment.                                                                                        |
/// | `metadata_signature` | `vector<u8>` | Optional signature over `metadata` and payment information. See                                                              |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                     | Description                                                                                                                         |
/// | ----------------           | --------------                                   | -------------                                                                                                                       |
/// | `Errors::NOT_PUBLISHED`    | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`      | `payer` doesn't hold a balance in `Currency`.                                                                                       |
/// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EINSUFFICIENT_BALANCE`            | `amount` is greater than `payer`'s balance in `Currency`.                                                                           |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::ECOIN_DEPOSIT_IS_ZERO`            | `amount` is zero.                                                                                                                   |
/// | `Errors::NOT_PUBLISHED`    | `DiemAccount::EPAYEE_DOES_NOT_EXIST`            | No account exists at the `payee` address.                                                                                           |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EPAYEE_CANT_ACCEPT_CURRENCY_TYPE` | An account exists at `payee`, but it does not accept payments in `Currency`.                                                        |
/// | `Errors::INVALID_STATE`    | `AccountFreezing::EACCOUNT_FROZEN`               | The `payee` account is frozen.                                                                                                      |
/// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EMALFORMED_METADATA_SIGNATURE` | `metadata_signature` is not 64 bytes.                                                                                               |
/// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EINVALID_METADATA_SIGNATURE`   | `metadata_signature` does not verify on the against the `payee'`s `DualAttestation::Credential` `compliance_public_key` public key. |
/// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EWITHDRAWAL_EXCEEDS_LIMITS`       | `payer` has exceeded its daily withdrawal limits for the backing coins of XDX.                                                      |
/// | `Errors::LIMIT_EXCEEDED`   | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`          | `payee` has exceeded its daily deposit limits for XDX.                                                                              |
///
/// # Related Scripts
/// * `Script::create_child_vasp_account`
/// * `Script::create_parent_vasp_account`
/// * `Script::add_currency_to_account`
pub fn encode_peer_to_peer_with_metadata_script(
    currency: TypeTag,
    payee: AccountAddress,
    amount: u64,
    metadata: Vec<u8>,
    metadata_signature: Vec<u8>,
) -> Script {
    Script::new(
        PEER_TO_PEER_WITH_METADATA_CODE.to_vec(),
        vec![currency],
        vec![
            TransactionArgument::Address(payee),
            TransactionArgument::U64(amount),
            TransactionArgument::U8Vector(metadata),
            TransactionArgument::U8Vector(metadata_signature),
        ],
    )
}

/// # Summary
/// Moves a specified number of coins in a given currency from the account's
/// balance to its preburn area after which the coins may be burned. This
/// transaction may be sent by any account that holds a balance and preburn area
/// in the specified currency.
///
/// # Technical Description
/// Moves the specified `amount` of coins in `Token` currency from the sending `account`'s
/// `DiemAccount::Balance<Token>` to the `Diem::Preburn<Token>` published under the same
/// `account`. `account` must have both of these resources published under it at the start of this
/// transaction in order for it to execute successfully.
///
/// ## Events
/// Successful execution of this script emits two events:
/// * `DiemAccount::SentPaymentEvent ` on `account`'s `DiemAccount::DiemAccount` `sent_events`
/// handle with the `payee` and `payer` fields being `account`'s address; and
/// * A `Diem::PreburnEvent` with `Token`'s currency code on the
/// `Diem::CurrencyInfo<Token`'s `preburn_events` handle for `Token` and with
/// `preburn_address` set to `account`'s address.
///
/// # Parameters
/// | Name      | Type      | Description                                                                                                                      |
/// | ------    | ------    | -------------                                                                                                                    |
/// | `Token`   | Type      | The Move type for the `Token` currency being moved to the preburn area. `Token` must be an already-registered currency on-chain. |
/// | `account` | `&signer` | The signer reference of the sending account.                                                                                     |
/// | `amount`  | `u64`     | The amount in `Token` to be moved to the preburn area.                                                                           |
///
/// # Common Abort Conditions
/// | Error Category           | Error Reason                                             | Description                                                                             |
/// | ----------------         | --------------                                           | -------------                                                                           |
/// | `Errors::NOT_PUBLISHED`  | `Diem::ECURRENCY_INFO`                                  | The `Token` is not a registered currency on-chain.                                      |
/// | `Errors::INVALID_STATE`  | `DiemAccount::EWITHDRAWAL_CAPABILITY_ALREADY_EXTRACTED` | The withdrawal capability for `account` has already been extracted.                     |
/// | `Errors::LIMIT_EXCEEDED` | `DiemAccount::EINSUFFICIENT_BALANCE`                    | `amount` is greater than `payer`'s balance in `Token`.                                  |
/// | `Errors::NOT_PUBLISHED`  | `DiemAccount::EPAYER_DOESNT_HOLD_CURRENCY`              | `account` doesn't hold a balance in `Token`.                                            |
/// | `Errors::NOT_PUBLISHED`  | `Diem::EPREBURN`                                        | `account` doesn't have a `Diem::Preburn<Token>` resource published under it.           |
/// | `Errors::INVALID_STATE`  | `Diem::EPREBURN_OCCUPIED`                               | The `value` field in the `Diem::Preburn<Token>` resource under the sender is non-zero. |
/// | `Errors::NOT_PUBLISHED`  | `Roles::EROLE_ID`                                        | The `account` did not have a role assigned to it.                                       |
/// | `Errors::REQUIRES_ROLE`  | `Roles::EDESIGNATED_DEALER`                              | The `account` did not have the role of DesignatedDealer.                                |
///
/// # Related Scripts
/// * `Script::cancel_burn`
/// * `Script::burn`
/// * `Script::burn_txn_fees`
pub fn encode_preburn_script(token: TypeTag, amount: u64) -> Script {
    Script::new(
        PREBURN_CODE.to_vec(),
        vec![token],
        vec![TransactionArgument::U64(amount)],
    )
}

/// # Summary
/// Rotates the authentication key of the sending account to the
/// newly-specified public key and publishes a new shared authentication key
/// under the sender's account. Any account can send this transaction.
///
/// # Technical Description
/// Rotates the authentication key of the sending account to `public_key`,
/// and publishes a `SharedEd25519PublicKey::SharedEd25519PublicKey` resource
/// containing the 32-byte ed25519 `public_key` and the `DiemAccount::KeyRotationCapability` for
/// `account` under `account`.
///
/// # Parameters
/// | Name         | Type         | Description                                                                               |
/// | ------       | ------       | -------------                                                                             |
/// | `account`    | `&signer`    | The signer reference of the sending account of the transaction.                           |
/// | `public_key` | `vector<u8>` | 32-byte Ed25519 public key for `account`' authentication key to be rotated to and stored. |
///
/// # Common Abort Conditions
/// | Error Category              | Error Reason                                               | Description                                                                                         |
/// | ----------------            | --------------                                             | -------------                                                                                       |
/// | `Errors::INVALID_STATE`     | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability` resource.       |
/// | `Errors::ALREADY_PUBLISHED` | `SharedEd25519PublicKey::ESHARED_KEY`                      | The `SharedEd25519PublicKey::SharedEd25519PublicKey` resource is already published under `account`. |
/// | `Errors::INVALID_ARGUMENT`  | `SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY`            | `public_key` is an invalid ed25519 public key.                                                      |
///
/// # Related Scripts
/// * `Script::rotate_shared_ed25519_public_key`
pub fn encode_publish_shared_ed25519_public_key_script(public_key: Vec<u8>) -> Script {
    Script::new(
        PUBLISH_SHARED_ED25519_PUBLIC_KEY_CODE.to_vec(),
        vec![],
        vec![TransactionArgument::U8Vector(public_key)],
    )
}

/// # Summary
/// Updates a validator's configuration. This does not reconfigure the system and will not update
/// the configuration in the validator set that is seen by other validators in the network. Can
/// only be successfully sent by a Validator Operator account that is already registered with a
/// validator.
///
/// # Technical Description
/// This updates the fields with corresponding names held in the `ValidatorConfig::ValidatorConfig`
/// config resource held under `validator_account`. It does not emit a `DiemConfig::NewEpochEvent`
/// so the copy of this config held in the validator set will not be updated, and the changes are
/// only "locally" under the `validator_account` account address.
///
/// # Parameters
/// | Name                          | Type         | Description                                                                                                                  |
/// | ------                        | ------       | -------------                                                                                                                |
/// | `validator_operator_account`  | `&signer`    | Signer reference of the sending account. Must be the registered validator operator for the validator at `validator_address`. |
/// | `validator_account`           | `address`    | The address of the validator's `ValidatorConfig::ValidatorConfig` resource being updated.                                    |
/// | `consensus_pubkey`            | `vector<u8>` | New Ed25519 public key to be used in the updated `ValidatorConfig::ValidatorConfig`.                                         |
/// | `validator_network_addresses` | `vector<u8>` | New set of `validator_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.                       |
/// | `fullnode_network_addresses`  | `vector<u8>` | New set of `fullnode_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.                        |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                   | Description                                                                                           |
/// | ----------------           | --------------                                 | -------------                                                                                         |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`           | `validator_address` does not have a `ValidatorConfig::ValidatorConfig` resource published under it.   |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_TRANSACTION_SENDER` | `validator_operator_account` is not the registered operator for the validator at `validator_address`. |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_CONSENSUS_KEY`      | `consensus_pubkey` is not a valid ed25519 public key.                                                 |
///
/// # Related Scripts
/// * `Script::create_validator_account`
/// * `Script::create_validator_operator_account`
/// * `Script::add_validator_and_reconfigure`
/// * `Script::remove_validator_and_reconfigure`
/// * `Script::set_validator_operator`
/// * `Script::set_validator_operator_with_nonce_admin`
/// * `Script::set_validator_config_and_reconfigure`
pub fn encode_register_validator_config_script(
    validator_account: AccountAddress,
    consensus_pubkey: Vec<u8>,
    validator_network_addresses: Vec<u8>,
    fullnode_network_addresses: Vec<u8>,
) -> Script {
    Script::new(
        REGISTER_VALIDATOR_CONFIG_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::Address(validator_account),
            TransactionArgument::U8Vector(consensus_pubkey),
            TransactionArgument::U8Vector(validator_network_addresses),
            TransactionArgument::U8Vector(fullnode_network_addresses),
        ],
    )
}

/// # Summary
/// This script removes a validator account from the validator set, and triggers a reconfiguration
/// of the system to remove the validator from the system. This transaction can only be
/// successfully called by the Diem Root account.
///
/// # Technical Description
/// This script removes the account at `validator_address` from the validator set. This transaction
/// emits a `DiemConfig::NewEpochEvent` event. Once the reconfiguration triggered by this event
/// has been performed, the account at `validator_address` is no longer considered to be a
/// validator in the network. This transaction will fail if the validator at `validator_address`
/// is not in the validator set.
///
/// # Parameters
/// | Name                | Type         | Description                                                                                                                        |
/// | ------              | ------       | -------------                                                                                                                      |
/// | `dr_account`        | `&signer`    | The signer reference of the sending account of this transaction. Must be the Diem Root signer.                                    |
/// | `sliding_nonce`     | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                                         |
/// | `validator_name`    | `vector<u8>` | ASCII-encoded human name for the validator. Must match the human name in the `ValidatorConfig::ValidatorConfig` for the validator. |
/// | `validator_address` | `address`    | The validator account address to be removed from the validator set.                                                                |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                            | Description                                                                                     |
/// | ----------------           | --------------                          | -------------                                                                                   |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `dr_account`.                                  |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.      |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                                   |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                               |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | The sending account is not the Diem Root account or Treasury Compliance account                |
/// | 0                          | 0                                       | The provided `validator_name` does not match the already-recorded human name for the validator. |
/// | `Errors::INVALID_ARGUMENT` | `DiemSystem::ENOT_AN_ACTIVE_VALIDATOR` | The validator to be removed is not in the validator set.                                        |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`            | The sending account is not the Diem Root account.                                              |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EDIEM_ROOT`                    | The sending account is not the Diem Root account.                                              |
/// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`      | An invalid time value was encountered in reconfiguration. Unlikely to occur.                    |
///
/// # Related Scripts
/// * `Script::create_validator_account`
/// * `Script::create_validator_operator_account`
/// * `Script::register_validator_config`
/// * `Script::add_validator_and_reconfigure`
/// * `Script::set_validator_operator`
/// * `Script::set_validator_operator_with_nonce_admin`
/// * `Script::set_validator_config_and_reconfigure`
pub fn encode_remove_validator_and_reconfigure_script(
    sliding_nonce: u64,
    validator_name: Vec<u8>,
    validator_address: AccountAddress,
) -> Script {
    Script::new(
        REMOVE_VALIDATOR_AND_RECONFIGURE_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::U8Vector(validator_name),
            TransactionArgument::Address(validator_address),
        ],
    )
}

/// # Summary
/// Rotates the transaction sender's authentication key to the supplied new authentication key. May
/// be sent by any account.
///
/// # Technical Description
/// Rotate the `account`'s `DiemAccount::DiemAccount` `authentication_key` field to `new_key`.
/// `new_key` must be a valid ed25519 public key, and `account` must not have previously delegated
/// its `DiemAccount::KeyRotationCapability`.
///
/// # Parameters
/// | Name      | Type         | Description                                                 |
/// | ------    | ------       | -------------                                               |
/// | `account` | `&signer`    | Signer reference of the sending account of the transaction. |
/// | `new_key` | `vector<u8>` | New ed25519 public key to be used for `account`.            |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                               | Description                                                                              |
/// | ----------------           | --------------                                             | -------------                                                                            |
/// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.     |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                         |
///
/// # Related Scripts
/// * `Script::rotate_authentication_key_with_nonce`
/// * `Script::rotate_authentication_key_with_nonce_admin`
/// * `Script::rotate_authentication_key_with_recovery_address`
pub fn encode_rotate_authentication_key_script(new_key: Vec<u8>) -> Script {
    Script::new(
        ROTATE_AUTHENTICATION_KEY_CODE.to_vec(),
        vec![],
        vec![TransactionArgument::U8Vector(new_key)],
    )
}

/// # Summary
/// Rotates the sender's authentication key to the supplied new authentication key. May be sent by
/// any account that has a sliding nonce resource published under it (usually this is Treasury
/// Compliance or Diem Root accounts).
///
/// # Technical Description
/// Rotates the `account`'s `DiemAccount::DiemAccount` `authentication_key` field to `new_key`.
/// `new_key` must be a valid ed25519 public key, and `account` must not have previously delegated
/// its `DiemAccount::KeyRotationCapability`.
///
/// # Parameters
/// | Name            | Type         | Description                                                                |
/// | ------          | ------       | -------------                                                              |
/// | `account`       | `&signer`    | Signer reference of the sending account of the transaction.                |
/// | `sliding_nonce` | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
/// | `new_key`       | `vector<u8>` | New ed25519 public key to be used for `account`.                           |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                               | Description                                                                                |
/// | ----------------           | --------------                                             | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                             | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                             | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                             | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`                    | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.       |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                           |
///
/// # Related Scripts
/// * `Script::rotate_authentication_key`
/// * `Script::rotate_authentication_key_with_nonce_admin`
/// * `Script::rotate_authentication_key_with_recovery_address`
pub fn encode_rotate_authentication_key_with_nonce_script(
    sliding_nonce: u64,
    new_key: Vec<u8>,
) -> Script {
    Script::new(
        ROTATE_AUTHENTICATION_KEY_WITH_NONCE_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::U8Vector(new_key),
        ],
    )
}

/// # Summary
/// Rotates the specified account's authentication key to the supplied new authentication key. May
/// only be sent by the Diem Root account as a write set transaction.
///
/// # Technical Description
/// Rotate the `account`'s `DiemAccount::DiemAccount` `authentication_key` field to `new_key`.
/// `new_key` must be a valid ed25519 public key, and `account` must not have previously delegated
/// its `DiemAccount::KeyRotationCapability`.
///
/// # Parameters
/// | Name            | Type         | Description                                                                                                  |
/// | ------          | ------       | -------------                                                                                                |
/// | `dr_account`    | `&signer`    | The signer reference of the sending account of the write set transaction. May only be the Diem Root signer. |
/// | `account`       | `&signer`    | Signer reference of account specified in the `execute_as` field of the write set transaction.                |
/// | `sliding_nonce` | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction for Diem Root.                    |
/// | `new_key`       | `vector<u8>` | New ed25519 public key to be used for `account`.                                                             |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                               | Description                                                                                                |
/// | ----------------           | --------------                                             | -------------                                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                             | A `SlidingNonce` resource is not published under `dr_account`.                                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                             | The `sliding_nonce` in `dr_account` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                             | The `sliding_nonce` in `dr_account` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`                    | The `sliding_nonce` in` dr_account` has been previously recorded.                                          |
/// | `Errors::INVALID_STATE`    | `DiemAccount::EKEY_ROTATION_CAPABILITY_ALREADY_EXTRACTED` | `account` has already delegated/extracted its `DiemAccount::KeyRotationCapability`.                       |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY`              | `new_key` was an invalid length.                                                                           |
///
/// # Related Scripts
/// * `Script::rotate_authentication_key`
/// * `Script::rotate_authentication_key_with_nonce`
/// * `Script::rotate_authentication_key_with_recovery_address`
pub fn encode_rotate_authentication_key_with_nonce_admin_script(
    sliding_nonce: u64,
    new_key: Vec<u8>,
) -> Script {
    Script::new(
        ROTATE_AUTHENTICATION_KEY_WITH_NONCE_ADMIN_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::U8Vector(new_key),
        ],
    )
}

/// # Summary
/// Rotates the authentication key of a specified account that is part of a recovery address to a
/// new authentication key. Only used for accounts that are part of a recovery address (see
/// `Script::add_recovery_rotation_capability` for account restrictions).
///
/// # Technical Description
/// Rotates the authentication key of the `to_recover` account to `new_key` using the
/// `DiemAccount::KeyRotationCapability` stored in the `RecoveryAddress::RecoveryAddress` resource
/// published under `recovery_address`. This transaction can be sent either by the `to_recover`
/// account, or by the account where the `RecoveryAddress::RecoveryAddress` resource is published
/// that contains `to_recover`'s `DiemAccount::KeyRotationCapability`.
///
/// # Parameters
/// | Name               | Type         | Description                                                                                                                    |
/// | ------             | ------       | -------------                                                                                                                  |
/// | `account`          | `&signer`    | Signer reference of the sending account of the transaction.                                                                    |
/// | `recovery_address` | `address`    | Address where `RecoveryAddress::RecoveryAddress` that holds `to_recover`'s `DiemAccount::KeyRotationCapability` is published. |
/// | `to_recover`       | `address`    | The address of the account whose authentication key will be updated.                                                           |
/// | `new_key`          | `vector<u8>` | New ed25519 public key to be used for the account at the `to_recover` address.                                                 |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                  | Description                                                                                                                                          |
/// | ----------------           | --------------                                | -------------                                                                                                                                        |
/// | `Errors::NOT_PUBLISHED`    | `RecoveryAddress::ERECOVERY_ADDRESS`          | `recovery_address` does not have a `RecoveryAddress::RecoveryAddress` resource published under it.                                                   |
/// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::ECANNOT_ROTATE_KEY`         | The address of `account` is not `recovery_address` or `to_recover`.                                                                                  |
/// | `Errors::INVALID_ARGUMENT` | `RecoveryAddress::EACCOUNT_NOT_RECOVERABLE`   | `to_recover`'s `DiemAccount::KeyRotationCapability`  is not in the `RecoveryAddress::RecoveryAddress`  resource published under `recovery_address`. |
/// | `Errors::INVALID_ARGUMENT` | `DiemAccount::EMALFORMED_AUTHENTICATION_KEY` | `new_key` was an invalid length.                                                                                                                     |
///
/// # Related Scripts
/// * `Script::rotate_authentication_key`
/// * `Script::rotate_authentication_key_with_nonce`
/// * `Script::rotate_authentication_key_with_nonce_admin`
pub fn encode_rotate_authentication_key_with_recovery_address_script(
    recovery_address: AccountAddress,
    to_recover: AccountAddress,
    new_key: Vec<u8>,
) -> Script {
    Script::new(
        ROTATE_AUTHENTICATION_KEY_WITH_RECOVERY_ADDRESS_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::Address(recovery_address),
            TransactionArgument::Address(to_recover),
            TransactionArgument::U8Vector(new_key),
        ],
    )
}

/// # Summary
/// Updates the url used for off-chain communication, and the public key used to verify dual
/// attestation on-chain. Transaction can be sent by any account that has dual attestation
/// information published under it. In practice the only such accounts are Designated Dealers and
/// Parent VASPs.
///
/// # Technical Description
/// Updates the `base_url` and `compliance_public_key` fields of the `DualAttestation::Credential`
/// resource published under `account`. The `new_key` must be a valid ed25519 public key.
///
/// ## Events
/// Successful execution of this transaction emits two events:
/// * A `DualAttestation::ComplianceKeyRotationEvent` containing the new compliance public key, and
/// the blockchain time at which the key was updated emitted on the `DualAttestation::Credential`
/// `compliance_key_rotation_events` handle published under `account`; and
/// * A `DualAttestation::BaseUrlRotationEvent` containing the new base url to be used for
/// off-chain communication, and the blockchain time at which the url was updated emitted on the
/// `DualAttestation::Credential` `base_url_rotation_events` handle published under `account`.
///
/// # Parameters
/// | Name      | Type         | Description                                                               |
/// | ------    | ------       | -------------                                                             |
/// | `account` | `&signer`    | Signer reference of the sending account of the transaction.               |
/// | `new_url` | `vector<u8>` | ASCII-encoded url to be used for off-chain communication with `account`.  |
/// | `new_key` | `vector<u8>` | New ed25519 public key to be used for on-chain dual attestation checking. |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                           | Description                                                                |
/// | ----------------           | --------------                         | -------------                                                              |
/// | `Errors::NOT_PUBLISHED`    | `DualAttestation::ECREDENTIAL`         | A `DualAttestation::Credential` resource is not published under `account`. |
/// | `Errors::INVALID_ARGUMENT` | `DualAttestation::EINVALID_PUBLIC_KEY` | `new_key` is not a valid ed25519 public key.                               |
///
/// # Related Scripts
/// * `Script::create_parent_vasp_account`
/// * `Script::create_designated_dealer`
/// * `Script::rotate_dual_attestation_info`
pub fn encode_rotate_dual_attestation_info_script(new_url: Vec<u8>, new_key: Vec<u8>) -> Script {
    Script::new(
        ROTATE_DUAL_ATTESTATION_INFO_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U8Vector(new_url),
            TransactionArgument::U8Vector(new_key),
        ],
    )
}

/// # Summary
/// Rotates the authentication key in a `SharedEd25519PublicKey`. This transaction can be sent by
/// any account that has previously published a shared ed25519 public key using
/// `Script::publish_shared_ed25519_public_key`.
///
/// # Technical Description
/// This first rotates the public key stored in `account`'s
/// `SharedEd25519PublicKey::SharedEd25519PublicKey` resource to `public_key`, after which it
/// rotates the authentication key using the capability stored in `account`'s
/// `SharedEd25519PublicKey::SharedEd25519PublicKey` to a new value derived from `public_key`
///
/// # Parameters
/// | Name         | Type         | Description                                                     |
/// | ------       | ------       | -------------                                                   |
/// | `account`    | `&signer`    | The signer reference of the sending account of the transaction. |
/// | `public_key` | `vector<u8>` | 32-byte Ed25519 public key.                                     |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                    | Description                                                                                   |
/// | ----------------           | --------------                                  | -------------                                                                                 |
/// | `Errors::NOT_PUBLISHED`    | `SharedEd25519PublicKey::ESHARED_KEY`           | A `SharedEd25519PublicKey::SharedEd25519PublicKey` resource is not published under `account`. |
/// | `Errors::INVALID_ARGUMENT` | `SharedEd25519PublicKey::EMALFORMED_PUBLIC_KEY` | `public_key` is an invalid ed25519 public key.                                                |
///
/// # Related Scripts
/// * `Script::publish_shared_ed25519_public_key`
pub fn encode_rotate_shared_ed25519_public_key_script(public_key: Vec<u8>) -> Script {
    Script::new(
        ROTATE_SHARED_ED25519_PUBLIC_KEY_CODE.to_vec(),
        vec![],
        vec![TransactionArgument::U8Vector(public_key)],
    )
}

/// # Summary
/// Updates a validator's configuration, and triggers a reconfiguration of the system to update the
/// validator set with this new validator configuration.  Can only be successfully sent by a
/// Validator Operator account that is already registered with a validator.
///
/// # Technical Description
/// This updates the fields with corresponding names held in the `ValidatorConfig::ValidatorConfig`
/// config resource held under `validator_account`. It then emits a `DiemConfig::NewEpochEvent` to
/// trigger a reconfiguration of the system.  This reconfiguration will update the validator set
/// on-chain with the updated `ValidatorConfig::ValidatorConfig`.
///
/// # Parameters
/// | Name                          | Type         | Description                                                                                                                  |
/// | ------                        | ------       | -------------                                                                                                                |
/// | `validator_operator_account`  | `&signer`    | Signer reference of the sending account. Must be the registered validator operator for the validator at `validator_address`. |
/// | `validator_account`           | `address`    | The address of the validator's `ValidatorConfig::ValidatorConfig` resource being updated.                                    |
/// | `consensus_pubkey`            | `vector<u8>` | New Ed25519 public key to be used in the updated `ValidatorConfig::ValidatorConfig`.                                         |
/// | `validator_network_addresses` | `vector<u8>` | New set of `validator_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.                       |
/// | `fullnode_network_addresses`  | `vector<u8>` | New set of `fullnode_network_addresses` to be used in the updated `ValidatorConfig::ValidatorConfig`.                        |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                   | Description                                                                                           |
/// | ----------------           | --------------                                 | -------------                                                                                         |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`           | `validator_address` does not have a `ValidatorConfig::ValidatorConfig` resource published under it.   |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR_OPERATOR`                   | `validator_operator_account` does not have a Validator Operator role.                                 |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_TRANSACTION_SENDER` | `validator_operator_account` is not the registered operator for the validator at `validator_address`. |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::EINVALID_CONSENSUS_KEY`      | `consensus_pubkey` is not a valid ed25519 public key.                                                 |
/// | `Errors::INVALID_STATE`    | `DiemConfig::EINVALID_BLOCK_TIME`             | An invalid time value was encountered in reconfiguration. Unlikely to occur.                          |
///
/// # Related Scripts
/// * `Script::create_validator_account`
/// * `Script::create_validator_operator_account`
/// * `Script::add_validator_and_reconfigure`
/// * `Script::remove_validator_and_reconfigure`
/// * `Script::set_validator_operator`
/// * `Script::set_validator_operator_with_nonce_admin`
/// * `Script::register_validator_config`
pub fn encode_set_validator_config_and_reconfigure_script(
    validator_account: AccountAddress,
    consensus_pubkey: Vec<u8>,
    validator_network_addresses: Vec<u8>,
    fullnode_network_addresses: Vec<u8>,
) -> Script {
    Script::new(
        SET_VALIDATOR_CONFIG_AND_RECONFIGURE_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::Address(validator_account),
            TransactionArgument::U8Vector(consensus_pubkey),
            TransactionArgument::U8Vector(validator_network_addresses),
            TransactionArgument::U8Vector(fullnode_network_addresses),
        ],
    )
}

/// # Summary
/// Sets the validator operator for a validator in the validator's configuration resource "locally"
/// and does not reconfigure the system. Changes from this transaction will not picked up by the
/// system until a reconfiguration of the system is triggered. May only be sent by an account with
/// Validator role.
///
/// # Technical Description
/// Sets the account at `operator_account` address and with the specified `human_name` as an
/// operator for the sending validator account. The account at `operator_account` address must have
/// a Validator Operator role and have a `ValidatorOperatorConfig::ValidatorOperatorConfig`
/// resource published under it. The sending `account` must be a Validator and have a
/// `ValidatorConfig::ValidatorConfig` resource published under it. This script does not emit a
/// `DiemConfig::NewEpochEvent` and no reconfiguration of the system is initiated by this script.
///
/// # Parameters
/// | Name               | Type         | Description                                                                                  |
/// | ------             | ------       | -------------                                                                                |
/// | `account`          | `&signer`    | The signer reference of the sending account of the transaction.                              |
/// | `operator_name`    | `vector<u8>` | Validator operator's human name.                                                             |
/// | `operator_account` | `address`    | Address of the validator operator account to be added as the `account` validator's operator. |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                          | Description                                                                                                                                                  |
/// | ----------------           | --------------                                        | -------------                                                                                                                                                |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG` | The `ValidatorOperatorConfig::ValidatorOperatorConfig` resource is not published under `operator_account`.                                                   |
/// | 0                          | 0                                                     | The `human_name` field of the `ValidatorOperatorConfig::ValidatorOperatorConfig` resource under `operator_account` does not match the provided `human_name`. |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR`                                   | `account` does not have a Validator account role.                                                                                                            |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR`          | The account at `operator_account` does not have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource.                                               |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`                  | A `ValidatorConfig::ValidatorConfig` is not published under `account`.                                                                                       |
///
/// # Related Scripts
/// * `Script::create_validator_account`
/// * `Script::create_validator_operator_account`
/// * `Script::register_validator_config`
/// * `Script::remove_validator_and_reconfigure`
/// * `Script::add_validator_and_reconfigure`
/// * `Script::set_validator_operator_with_nonce_admin`
/// * `Script::set_validator_config_and_reconfigure`
pub fn encode_set_validator_operator_script(
    operator_name: Vec<u8>,
    operator_account: AccountAddress,
) -> Script {
    Script::new(
        SET_VALIDATOR_OPERATOR_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U8Vector(operator_name),
            TransactionArgument::Address(operator_account),
        ],
    )
}

/// # Summary
/// Sets the validator operator for a validator in the validator's configuration resource "locally"
/// and does not reconfigure the system. Changes from this transaction will not picked up by the
/// system until a reconfiguration of the system is triggered. May only be sent by the Diem Root
/// account as a write set transaction.
///
/// # Technical Description
/// Sets the account at `operator_account` address and with the specified `human_name` as an
/// operator for the validator `account`. The account at `operator_account` address must have a
/// Validator Operator role and have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource
/// published under it. The account represented by the `account` signer must be a Validator and
/// have a `ValidatorConfig::ValidatorConfig` resource published under it. No reconfiguration of
/// the system is initiated by this script.
///
/// # Parameters
/// | Name               | Type         | Description                                                                                                  |
/// | ------             | ------       | -------------                                                                                                |
/// | `dr_account`       | `&signer`    | The signer reference of the sending account of the write set transaction. May only be the Diem Root signer. |
/// | `account`          | `&signer`    | Signer reference of account specified in the `execute_as` field of the write set transaction.                |
/// | `sliding_nonce`    | `u64`        | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction for Diem Root.                    |
/// | `operator_name`    | `vector<u8>` | Validator operator's human name.                                                                             |
/// | `operator_account` | `address`    | Address of the validator operator account to be added as the `account` validator's operator.                 |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                          | Description                                                                                                                                                  |
/// | ----------------           | --------------                                        | -------------                                                                                                                                                |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                        | A `SlidingNonce` resource is not published under `dr_account`.                                                                                               |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                        | The `sliding_nonce` in `dr_account` is too old and it's impossible to determine if it's duplicated or not.                                                   |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                        | The `sliding_nonce` in `dr_account` is too far in the future.                                                                                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`               | The `sliding_nonce` in` dr_account` has been previously recorded.                                                                                            |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                        | The sending account is not the Diem Root account or Treasury Compliance account                                                                             |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorOperatorConfig::EVALIDATOR_OPERATOR_CONFIG` | The `ValidatorOperatorConfig::ValidatorOperatorConfig` resource is not published under `operator_account`.                                                   |
/// | 0                          | 0                                                     | The `human_name` field of the `ValidatorOperatorConfig::ValidatorOperatorConfig` resource under `operator_account` does not match the provided `human_name`. |
/// | `Errors::REQUIRES_ROLE`    | `Roles::EVALIDATOR`                                   | `account` does not have a Validator account role.                                                                                                            |
/// | `Errors::INVALID_ARGUMENT` | `ValidatorConfig::ENOT_A_VALIDATOR_OPERATOR`          | The account at `operator_account` does not have a `ValidatorOperatorConfig::ValidatorOperatorConfig` resource.                                               |
/// | `Errors::NOT_PUBLISHED`    | `ValidatorConfig::EVALIDATOR_CONFIG`                  | A `ValidatorConfig::ValidatorConfig` is not published under `account`.                                                                                       |
///
/// # Related Scripts
/// * `Script::create_validator_account`
/// * `Script::create_validator_operator_account`
/// * `Script::register_validator_config`
/// * `Script::remove_validator_and_reconfigure`
/// * `Script::add_validator_and_reconfigure`
/// * `Script::set_validator_operator`
/// * `Script::set_validator_config_and_reconfigure`
pub fn encode_set_validator_operator_with_nonce_admin_script(
    sliding_nonce: u64,
    operator_name: Vec<u8>,
    operator_account: AccountAddress,
) -> Script {
    Script::new(
        SET_VALIDATOR_OPERATOR_WITH_NONCE_ADMIN_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::U8Vector(operator_name),
            TransactionArgument::Address(operator_account),
        ],
    )
}

/// # Summary
/// Mints a specified number of coins in a currency to a Designated Dealer. The sending account
/// must be the Treasury Compliance account, and coins can only be minted to a Designated Dealer
/// account.
///
/// # Technical Description
/// Mints `mint_amount` of coins in the `CoinType` currency to Designated Dealer account at
/// `designated_dealer_address`. The `tier_index` parameter specifies which tier should be used to
/// check verify the off-chain approval policy, and is based in part on the on-chain tier values
/// for the specific Designated Dealer, and the number of `CoinType` coins that have been minted to
/// the dealer over the past 24 hours. Every Designated Dealer has 4 tiers for each currency that
/// they support. The sending `tc_account` must be the Treasury Compliance account, and the
/// receiver an authorized Designated Dealer account.
///
/// ## Events
/// Successful execution of the transaction will emit two events:
/// * A `Diem::MintEvent` with the amount and currency code minted is emitted on the
/// `mint_event_handle` in the stored `Diem::CurrencyInfo<CoinType>` resource stored under
/// `0xA550C18`; and
/// * A `DesignatedDealer::ReceivedMintEvent` with the amount, currency code, and Designated
/// Dealer's address is emitted on the `mint_event_handle` in the stored `DesignatedDealer::Dealer`
/// resource published under the `designated_dealer_address`.
///
/// # Parameters
/// | Name                        | Type      | Description                                                                                                |
/// | ------                      | ------    | -------------                                                                                              |
/// | `CoinType`                  | Type      | The Move type for the `CoinType` being minted. `CoinType` must be an already-registered currency on-chain. |
/// | `tc_account`                | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.  |
/// | `sliding_nonce`             | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                 |
/// | `designated_dealer_address` | `address` | The address of the Designated Dealer account being minted to.                                              |
/// | `mint_amount`               | `u64`     | The number of coins to be minted.                                                                          |
/// | `tier_index`                | `u64`     | The mint tier index to use for the Designated Dealer account.                                              |
///
/// # Common Abort Conditions
/// | Error Category                | Error Reason                                 | Description                                                                                                                  |
/// | ----------------              | --------------                               | -------------                                                                                                                |
/// | `Errors::NOT_PUBLISHED`       | `SlidingNonce::ESLIDING_NONCE`               | A `SlidingNonce` resource is not published under `tc_account`.                                                               |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_OLD`               | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not.                                   |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_TOO_NEW`               | The `sliding_nonce` is too far in the future.                                                                                |
/// | `Errors::INVALID_ARGUMENT`    | `SlidingNonce::ENONCE_ALREADY_RECORDED`      | The `sliding_nonce` has been previously recorded.                                                                            |
/// | `Errors::REQUIRES_ADDRESS`    | `CoreAddresses::ETREASURY_COMPLIANCE`        | `tc_account` is not the Treasury Compliance account.                                                                         |
/// | `Errors::REQUIRES_ROLE`       | `Roles::ETREASURY_COMPLIANCE`                | `tc_account` is not the Treasury Compliance account.                                                                         |
/// | `Errors::INVALID_ARGUMENT`    | `DesignatedDealer::EINVALID_MINT_AMOUNT`     | `mint_amount` is zero.                                                                                                       |
/// | `Errors::NOT_PUBLISHED`       | `DesignatedDealer::EDEALER`                  | `DesignatedDealer::Dealer` or `DesignatedDealer::TierInfo<CoinType>` resource does not exist at `designated_dealer_address`. |
/// | `Errors::INVALID_ARGUMENT`    | `DesignatedDealer::EINVALID_TIER_INDEX`      | The `tier_index` is out of bounds.                                                                                           |
/// | `Errors::INVALID_ARGUMENT`    | `DesignatedDealer::EINVALID_AMOUNT_FOR_TIER` | `mint_amount` exceeds the maximum allowed amount for `tier_index`.                                                           |
/// | `Errors::REQUIRES_CAPABILITY` | `Diem::EMINT_CAPABILITY`                    | `tc_account` does not have a `Diem::MintCapability<CoinType>` resource published under it.                                  |
/// | `Errors::INVALID_STATE`       | `Diem::EMINTING_NOT_ALLOWED`                | Minting is not currently allowed for `CoinType` coins.                                                                       |
/// | `Errors::LIMIT_EXCEEDED`      | `DiemAccount::EDEPOSIT_EXCEEDS_LIMITS`      | The depositing of the funds would exceed the `account`'s account limits.                                                     |
///
/// # Related Scripts
/// * `Script::create_designated_dealer`
/// * `Script::peer_to_peer_with_metadata`
/// * `Script::rotate_dual_attestation_info`
pub fn encode_tiered_mint_script(
    coin_type: TypeTag,
    sliding_nonce: u64,
    designated_dealer_address: AccountAddress,
    mint_amount: u64,
    tier_index: u64,
) -> Script {
    Script::new(
        TIERED_MINT_CODE.to_vec(),
        vec![coin_type],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::Address(designated_dealer_address),
            TransactionArgument::U64(mint_amount),
            TransactionArgument::U64(tier_index),
        ],
    )
}

/// # Summary
/// Unfreezes the account at `address`. The sending account of this transaction must be the
/// Treasury Compliance account. After the successful execution of this transaction transactions
/// may be sent from the previously frozen account, and coins may be sent and received.
///
/// # Technical Description
/// Sets the `AccountFreezing::FreezingBit` to `false` and emits a
/// `AccountFreezing::UnFreezeAccountEvent`. The transaction sender must be the Treasury Compliance
/// account. Note that this is a per-account property so unfreezing a Parent VASP will not effect
/// the status any of its child accounts and vice versa.
///
/// ## Events
/// Successful execution of this script will emit a `AccountFreezing::UnFreezeAccountEvent` with
/// the `unfrozen_address` set the `to_unfreeze_account`'s address.
///
/// # Parameters
/// | Name                  | Type      | Description                                                                                               |
/// | ------                | ------    | -------------                                                                                             |
/// | `tc_account`          | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account. |
/// | `sliding_nonce`       | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                |
/// | `to_unfreeze_account` | `address` | The account address to be frozen.                                                                         |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                            | Description                                                                                |
/// | ----------------           | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | The sending account is not the Treasury Compliance account.                                |
///
/// # Related Scripts
/// * `Script::freeze_account`
pub fn encode_unfreeze_account_script(
    sliding_nonce: u64,
    to_unfreeze_account: AccountAddress,
) -> Script {
    Script::new(
        UNFREEZE_ACCOUNT_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::Address(to_unfreeze_account),
        ],
    )
}

/// # Summary
/// Updates the Diem major version that is stored on-chain and is used by the VM.  This
/// transaction can only be sent from the Diem Root account.
///
/// # Technical Description
/// Updates the `DiemVersion` on-chain config and emits a `DiemConfig::NewEpochEvent` to trigger
/// a reconfiguration of the system. The `major` version that is passed in must be strictly greater
/// than the current major version held on-chain. The VM reads this information and can use it to
/// preserve backwards compatibility with previous major versions of the VM.
///
/// # Parameters
/// | Name            | Type      | Description                                                                |
/// | ------          | ------    | -------------                                                              |
/// | `account`       | `&signer` | Signer reference of the sending account. Must be the Diem Root account.   |
/// | `sliding_nonce` | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction. |
/// | `major`         | `u64`     | The `major` version of the VM to be used from this transaction on.         |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                                  | Description                                                                                |
/// | ----------------           | --------------                                | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`                | A `SlidingNonce` resource is not published under `account`.                                |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`                | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`                | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED`       | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::EDIEM_ROOT`                  | `account` is not the Diem Root account.                                                   |
/// | `Errors::INVALID_ARGUMENT` | `DiemVersion::EINVALID_MAJOR_VERSION_NUMBER` | `major` is less-than or equal to the current major version stored on-chain.                |
pub fn encode_update_diem_version_script(sliding_nonce: u64, major: u64) -> Script {
    Script::new(
        UPDATE_DIEM_VERSION_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::U64(major),
        ],
    )
}

/// # Summary
/// Update the dual attestation limit on-chain. Defined in terms of micro-XDX.  The transaction can
/// only be sent by the Treasury Compliance account.  After this transaction all inter-VASP
/// payments over this limit must be checked for dual attestation.
///
/// # Technical Description
/// Updates the `micro_xdx_limit` field of the `DualAttestation::Limit` resource published under
/// `0xA550C18`. The amount is set in micro-XDX.
///
/// # Parameters
/// | Name                  | Type      | Description                                                                                               |
/// | ------                | ------    | -------------                                                                                             |
/// | `tc_account`          | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account. |
/// | `sliding_nonce`       | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for this transaction.                                |
/// | `new_micro_xdx_limit` | `u64`     | The new dual attestation limit to be used on-chain.                                                       |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                            | Description                                                                                |
/// | ----------------           | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | `tc_account` is not the Treasury Compliance account.                                       |
///
/// # Related Scripts
/// * `Script::update_exchange_rate`
/// * `Script::update_minting_ability`
pub fn encode_update_dual_attestation_limit_script(
    sliding_nonce: u64,
    new_micro_xdx_limit: u64,
) -> Script {
    Script::new(
        UPDATE_DUAL_ATTESTATION_LIMIT_CODE.to_vec(),
        vec![],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::U64(new_micro_xdx_limit),
        ],
    )
}

/// # Summary
/// Update the rough on-chain exchange rate between a specified currency and XDX (as a conversion
/// to micro-XDX). The transaction can only be sent by the Treasury Compliance account. After this
/// transaction the updated exchange rate will be used for normalization of gas prices, and for
/// dual attestation checking.
///
/// # Technical Description
/// Updates the on-chain exchange rate from the given `Currency` to micro-XDX.  The exchange rate
/// is given by `new_exchange_rate_numerator/new_exchange_rate_denominator`.
///
/// # Parameters
/// | Name                            | Type      | Description                                                                                                                        |
/// | ------                          | ------    | -------------                                                                                                                      |
/// | `Currency`                      | Type      | The Move type for the `Currency` whose exchange rate is being updated. `Currency` must be an already-registered currency on-chain. |
/// | `tc_account`                    | `&signer` | The signer reference of the sending account of this transaction. Must be the Treasury Compliance account.                          |
/// | `sliding_nonce`                 | `u64`     | The `sliding_nonce` (see: `SlidingNonce`) to be used for the transaction.                                                          |
/// | `new_exchange_rate_numerator`   | `u64`     | The numerator for the new to micro-XDX exchange rate for `Currency`.                                                               |
/// | `new_exchange_rate_denominator` | `u64`     | The denominator for the new to micro-XDX exchange rate for `Currency`.                                                             |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                            | Description                                                                                |
/// | ----------------           | --------------                          | -------------                                                                              |
/// | `Errors::NOT_PUBLISHED`    | `SlidingNonce::ESLIDING_NONCE`          | A `SlidingNonce` resource is not published under `tc_account`.                             |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_OLD`          | The `sliding_nonce` is too old and it's impossible to determine if it's duplicated or not. |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_TOO_NEW`          | The `sliding_nonce` is too far in the future.                                              |
/// | `Errors::INVALID_ARGUMENT` | `SlidingNonce::ENONCE_ALREADY_RECORDED` | The `sliding_nonce` has been previously recorded.                                          |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE`   | `tc_account` is not the Treasury Compliance account.                                       |
/// | `Errors::REQUIRES_ROLE`    | `Roles::ETREASURY_COMPLIANCE`           | `tc_account` is not the Treasury Compliance account.                                       |
/// | `Errors::INVALID_ARGUMENT` | `FixedPoint32::EDENOMINATOR`            | `new_exchange_rate_denominator` is zero.                                                   |
/// | `Errors::INVALID_ARGUMENT` | `FixedPoint32::ERATIO_OUT_OF_RANGE`     | The quotient is unrepresentable as a `FixedPoint32`.                                       |
/// | `Errors::LIMIT_EXCEEDED`   | `FixedPoint32::ERATIO_OUT_OF_RANGE`     | The quotient is unrepresentable as a `FixedPoint32`.                                       |
///
/// # Related Scripts
/// * `Script::update_dual_attestation_limit`
/// * `Script::update_minting_ability`
pub fn encode_update_exchange_rate_script(
    currency: TypeTag,
    sliding_nonce: u64,
    new_exchange_rate_numerator: u64,
    new_exchange_rate_denominator: u64,
) -> Script {
    Script::new(
        UPDATE_EXCHANGE_RATE_CODE.to_vec(),
        vec![currency],
        vec![
            TransactionArgument::U64(sliding_nonce),
            TransactionArgument::U64(new_exchange_rate_numerator),
            TransactionArgument::U64(new_exchange_rate_denominator),
        ],
    )
}

/// # Summary
/// Script to allow or disallow minting of new coins in a specified currency.  This transaction can
/// only be sent by the Treasury Compliance account.  Turning minting off for a currency will have
/// no effect on coins already in circulation, and coins may still be removed from the system.
///
/// # Technical Description
/// This transaction sets the `can_mint` field of the `Diem::CurrencyInfo<Currency>` resource
/// published under `0xA550C18` to the value of `allow_minting`. Minting of coins if allowed if
/// this field is set to `true` and minting of new coins in `Currency` is disallowed otherwise.
/// This transaction needs to be sent by the Treasury Compliance account.
///
/// # Parameters
/// | Name            | Type      | Description                                                                                                                          |
/// | ------          | ------    | -------------                                                                                                                        |
/// | `Currency`      | Type      | The Move type for the `Currency` whose minting ability is being updated. `Currency` must be an already-registered currency on-chain. |
/// | `account`       | `&signer` | Signer reference of the sending account. Must be the Diem Root account.                                                             |
/// | `allow_minting` | `bool`    | Whether to allow minting of new coins in `Currency`.                                                                                 |
///
/// # Common Abort Conditions
/// | Error Category             | Error Reason                          | Description                                          |
/// | ----------------           | --------------                        | -------------                                        |
/// | `Errors::REQUIRES_ADDRESS` | `CoreAddresses::ETREASURY_COMPLIANCE` | `tc_account` is not the Treasury Compliance account. |
/// | `Errors::NOT_PUBLISHED`    | `Diem::ECURRENCY_INFO`               | `Currency` is not a registered currency on-chain.    |
///
/// # Related Scripts
/// * `Script::update_dual_attestation_limit`
/// * `Script::update_exchange_rate`
pub fn encode_update_minting_ability_script(currency: TypeTag, allow_minting: bool) -> Script {
    Script::new(
        UPDATE_MINTING_ABILITY_CODE.to_vec(),
        vec![currency],
        vec![TransactionArgument::Bool(allow_minting)],
    )
}

fn decode_add_currency_to_account_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::AddCurrencyToAccount {
            currency: script.ty_args().get(0)?.clone(),
        })
    } else {
        None
    }
}

fn decode_add_diem_id_domain_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::AddDiemIdDomain {
            address: bcs::from_bytes(script.args().get(0)?).ok()?,
            domain: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_add_recovery_rotation_capability_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::AddRecoveryRotationCapability {
            recovery_address: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_add_validator_and_reconfigure_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::AddValidatorAndReconfigure {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            validator_name: bcs::from_bytes(script.args().get(1)?).ok()?,
            validator_address: bcs::from_bytes(script.args().get(2)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_autopay_create_instruction_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::AutopayCreateInstruction {
            uid: bcs::from_bytes(script.args().get(0)?).ok()?,
            in_type: bcs::from_bytes(script.args().get(1)?).ok()?,
            payee: bcs::from_bytes(script.args().get(2)?).ok()?,
            end_epoch: bcs::from_bytes(script.args().get(3)?).ok()?,
            value: bcs::from_bytes(script.args().get(4)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_autopay_disable_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(_script) = payload {
        Some(ScriptFunctionCall::AutopayDisable {})
    } else {
        None
    }
}

fn decode_autopay_enable_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(_script) = payload {
        Some(ScriptFunctionCall::AutopayEnable {})
    } else {
        None
    }
}

fn decode_burn_txn_fees_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::BurnTxnFees {
            coin_type: script.ty_args().get(0)?.clone(),
        })
    } else {
        None
    }
}

fn decode_burn_with_amount_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::BurnWithAmount {
            token: script.ty_args().get(0)?.clone(),
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            preburn_address: bcs::from_bytes(script.args().get(1)?).ok()?,
            amount: bcs::from_bytes(script.args().get(2)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_cancel_burn_with_amount_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::CancelBurnWithAmount {
            token: script.ty_args().get(0)?.clone(),
            preburn_address: bcs::from_bytes(script.args().get(0)?).ok()?,
            amount: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_create_acc_user_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::CreateAccUser {
            challenge: bcs::from_bytes(script.args().get(0)?).ok()?,
            solution: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_create_acc_val_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::CreateAccVal {
            challenge: bcs::from_bytes(script.args().get(0)?).ok()?,
            solution: bcs::from_bytes(script.args().get(1)?).ok()?,
            ow_human_name: bcs::from_bytes(script.args().get(2)?).ok()?,
            op_address: bcs::from_bytes(script.args().get(3)?).ok()?,
            op_auth_key_prefix: bcs::from_bytes(script.args().get(4)?).ok()?,
            op_consensus_pubkey: bcs::from_bytes(script.args().get(5)?).ok()?,
            op_validator_network_addresses: bcs::from_bytes(script.args().get(6)?).ok()?,
            op_fullnode_network_addresses: bcs::from_bytes(script.args().get(7)?).ok()?,
            op_human_name: bcs::from_bytes(script.args().get(8)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_create_child_vasp_account_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::CreateChildVaspAccount {
            coin_type: script.ty_args().get(0)?.clone(),
            child_address: bcs::from_bytes(script.args().get(0)?).ok()?,
            auth_key_prefix: bcs::from_bytes(script.args().get(1)?).ok()?,
            add_all_currencies: bcs::from_bytes(script.args().get(2)?).ok()?,
            child_initial_balance: bcs::from_bytes(script.args().get(3)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_create_designated_dealer_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::CreateDesignatedDealer {
            currency: script.ty_args().get(0)?.clone(),
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            addr: bcs::from_bytes(script.args().get(1)?).ok()?,
            auth_key_prefix: bcs::from_bytes(script.args().get(2)?).ok()?,
            human_name: bcs::from_bytes(script.args().get(3)?).ok()?,
            add_all_currencies: bcs::from_bytes(script.args().get(4)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_create_diem_id_domains_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(_script) = payload {
        Some(ScriptFunctionCall::CreateDiemIdDomains {})
    } else {
        None
    }
}

fn decode_create_parent_vasp_account_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::CreateParentVaspAccount {
            coin_type: script.ty_args().get(0)?.clone(),
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            new_account_address: bcs::from_bytes(script.args().get(1)?).ok()?,
            auth_key_prefix: bcs::from_bytes(script.args().get(2)?).ok()?,
            human_name: bcs::from_bytes(script.args().get(3)?).ok()?,
            add_all_currencies: bcs::from_bytes(script.args().get(4)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_create_recovery_address_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(_script) = payload {
        Some(ScriptFunctionCall::CreateRecoveryAddress {})
    } else {
        None
    }
}

fn decode_create_validator_account_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::CreateValidatorAccount {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            new_account_address: bcs::from_bytes(script.args().get(1)?).ok()?,
            auth_key_prefix: bcs::from_bytes(script.args().get(2)?).ok()?,
            human_name: bcs::from_bytes(script.args().get(3)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_create_validator_operator_account_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::CreateValidatorOperatorAccount {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            new_account_address: bcs::from_bytes(script.args().get(1)?).ok()?,
            auth_key_prefix: bcs::from_bytes(script.args().get(2)?).ok()?,
            human_name: bcs::from_bytes(script.args().get(3)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_demo_e2e_script_function(payload: &TransactionPayload) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::DemoE2e {
            world: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_freeze_account_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::FreezeAccount {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            to_freeze_account: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_initialize_diem_consensus_config_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::InitializeDiemConsensusConfig {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_join_script_function(payload: &TransactionPayload) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(_script) = payload {
        Some(ScriptFunctionCall::Join {})
    } else {
        None
    }
}

fn decode_leave_script_function(payload: &TransactionPayload) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(_script) = payload {
        Some(ScriptFunctionCall::Leave {})
    } else {
        None
    }
}

fn decode_minerstate_commit_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::MinerstateCommit {
            challenge: bcs::from_bytes(script.args().get(0)?).ok()?,
            solution: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_minerstate_commit_by_operator_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::MinerstateCommitByOperator {
            owner_address: bcs::from_bytes(script.args().get(0)?).ok()?,
            challenge: bcs::from_bytes(script.args().get(1)?).ok()?,
            solution: bcs::from_bytes(script.args().get(2)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_minerstate_helper_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(_script) = payload {
        Some(ScriptFunctionCall::MinerstateHelper {})
    } else {
        None
    }
}

fn decode_ol_oracle_tx_script_function(payload: &TransactionPayload) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::OlOracleTx {
            id: bcs::from_bytes(script.args().get(0)?).ok()?,
            data: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_ol_reconfig_bulk_update_setup_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::OlReconfigBulkUpdateSetup {
            alice: bcs::from_bytes(script.args().get(0)?).ok()?,
            bob: bcs::from_bytes(script.args().get(1)?).ok()?,
            carol: bcs::from_bytes(script.args().get(2)?).ok()?,
            sha: bcs::from_bytes(script.args().get(3)?).ok()?,
            ram: bcs::from_bytes(script.args().get(4)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_peer_to_peer_with_metadata_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::PeerToPeerWithMetadata {
            currency: script.ty_args().get(0)?.clone(),
            payee: bcs::from_bytes(script.args().get(0)?).ok()?,
            amount: bcs::from_bytes(script.args().get(1)?).ok()?,
            metadata: bcs::from_bytes(script.args().get(2)?).ok()?,
            metadata_signature: bcs::from_bytes(script.args().get(3)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_preburn_script_function(payload: &TransactionPayload) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::Preburn {
            token: script.ty_args().get(0)?.clone(),
            amount: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_publish_shared_ed25519_public_key_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::PublishSharedEd25519PublicKey {
            public_key: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_register_validator_config_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::RegisterValidatorConfig {
            validator_account: bcs::from_bytes(script.args().get(0)?).ok()?,
            consensus_pubkey: bcs::from_bytes(script.args().get(1)?).ok()?,
            validator_network_addresses: bcs::from_bytes(script.args().get(2)?).ok()?,
            fullnode_network_addresses: bcs::from_bytes(script.args().get(3)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_remove_diem_id_domain_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::RemoveDiemIdDomain {
            address: bcs::from_bytes(script.args().get(0)?).ok()?,
            domain: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_remove_validator_and_reconfigure_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::RemoveValidatorAndReconfigure {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            validator_name: bcs::from_bytes(script.args().get(1)?).ok()?,
            validator_address: bcs::from_bytes(script.args().get(2)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_rotate_authentication_key_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::RotateAuthenticationKey {
            new_key: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_rotate_authentication_key_with_nonce_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::RotateAuthenticationKeyWithNonce {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            new_key: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_rotate_authentication_key_with_nonce_admin_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::RotateAuthenticationKeyWithNonceAdmin {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            new_key: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_rotate_authentication_key_with_recovery_address_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(
            ScriptFunctionCall::RotateAuthenticationKeyWithRecoveryAddress {
                recovery_address: bcs::from_bytes(script.args().get(0)?).ok()?,
                to_recover: bcs::from_bytes(script.args().get(1)?).ok()?,
                new_key: bcs::from_bytes(script.args().get(2)?).ok()?,
            },
        )
    } else {
        None
    }
}

fn decode_rotate_dual_attestation_info_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::RotateDualAttestationInfo {
            new_url: bcs::from_bytes(script.args().get(0)?).ok()?,
            new_key: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_rotate_shared_ed25519_public_key_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::RotateSharedEd25519PublicKey {
            public_key: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_set_gas_constants_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::SetGasConstants {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            global_memory_per_byte_cost: bcs::from_bytes(script.args().get(1)?).ok()?,
            global_memory_per_byte_write_cost: bcs::from_bytes(script.args().get(2)?).ok()?,
            min_transaction_gas_units: bcs::from_bytes(script.args().get(3)?).ok()?,
            large_transaction_cutoff: bcs::from_bytes(script.args().get(4)?).ok()?,
            intrinsic_gas_per_byte: bcs::from_bytes(script.args().get(5)?).ok()?,
            maximum_number_of_gas_units: bcs::from_bytes(script.args().get(6)?).ok()?,
            min_price_per_gas_unit: bcs::from_bytes(script.args().get(7)?).ok()?,
            max_price_per_gas_unit: bcs::from_bytes(script.args().get(8)?).ok()?,
            max_transaction_size_in_bytes: bcs::from_bytes(script.args().get(9)?).ok()?,
            gas_unit_scaling_factor: bcs::from_bytes(script.args().get(10)?).ok()?,
            default_account_size: bcs::from_bytes(script.args().get(11)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_set_validator_config_and_reconfigure_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::SetValidatorConfigAndReconfigure {
            validator_account: bcs::from_bytes(script.args().get(0)?).ok()?,
            consensus_pubkey: bcs::from_bytes(script.args().get(1)?).ok()?,
            validator_network_addresses: bcs::from_bytes(script.args().get(2)?).ok()?,
            fullnode_network_addresses: bcs::from_bytes(script.args().get(3)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_set_validator_operator_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::SetValidatorOperator {
            operator_name: bcs::from_bytes(script.args().get(0)?).ok()?,
            operator_account: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_set_validator_operator_with_nonce_admin_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::SetValidatorOperatorWithNonceAdmin {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            operator_name: bcs::from_bytes(script.args().get(1)?).ok()?,
            operator_account: bcs::from_bytes(script.args().get(2)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_set_wallet_type_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::SetWalletType {
            type_of: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_tiered_mint_script_function(payload: &TransactionPayload) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::TieredMint {
            coin_type: script.ty_args().get(0)?.clone(),
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            designated_dealer_address: bcs::from_bytes(script.args().get(1)?).ok()?,
            mint_amount: bcs::from_bytes(script.args().get(2)?).ok()?,
            tier_index: bcs::from_bytes(script.args().get(3)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_unfreeze_account_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::UnfreezeAccount {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            to_unfreeze_account: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_update_diem_consensus_config_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::UpdateDiemConsensusConfig {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            config: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_update_diem_version_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::UpdateDiemVersion {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            major: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_update_dual_attestation_limit_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::UpdateDualAttestationLimit {
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            new_micro_xdx_limit: bcs::from_bytes(script.args().get(1)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_update_exchange_rate_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::UpdateExchangeRate {
            currency: script.ty_args().get(0)?.clone(),
            sliding_nonce: bcs::from_bytes(script.args().get(0)?).ok()?,
            new_exchange_rate_numerator: bcs::from_bytes(script.args().get(1)?).ok()?,
            new_exchange_rate_denominator: bcs::from_bytes(script.args().get(2)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_update_minting_ability_script_function(
    payload: &TransactionPayload,
) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(script) = payload {
        Some(ScriptFunctionCall::UpdateMintingAbility {
            currency: script.ty_args().get(0)?.clone(),
            allow_minting: bcs::from_bytes(script.args().get(0)?).ok()?,
        })
    } else {
        None
    }
}

fn decode_val_add_self_script_function(payload: &TransactionPayload) -> Option<ScriptFunctionCall> {
    if let TransactionPayload::ScriptFunction(_script) = payload {
        Some(ScriptFunctionCall::ValAddSelf {})
    } else {
        None
    }
}

fn decode_add_currency_to_account_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::AddCurrencyToAccount {
        currency: script.ty_args().get(0)?.clone(),
    })
}

fn decode_add_recovery_rotation_capability_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::AddRecoveryRotationCapability {
        recovery_address: decode_address_argument(script.args().get(0)?.clone())?,
    })
}

fn decode_add_validator_and_reconfigure_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::AddValidatorAndReconfigure {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        validator_name: decode_u8vector_argument(script.args().get(1)?.clone())?,
        validator_address: decode_address_argument(script.args().get(2)?.clone())?,
    })
}

fn decode_burn_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::Burn {
        token: script.ty_args().get(0)?.clone(),
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        preburn_address: decode_address_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_burn_txn_fees_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::BurnTxnFees {
        coin_type: script.ty_args().get(0)?.clone(),
    })
}

fn decode_cancel_burn_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::CancelBurn {
        token: script.ty_args().get(0)?.clone(),
        preburn_address: decode_address_argument(script.args().get(0)?.clone())?,
    })
}

fn decode_create_child_vasp_account_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::CreateChildVaspAccount {
        coin_type: script.ty_args().get(0)?.clone(),
        child_address: decode_address_argument(script.args().get(0)?.clone())?,
        auth_key_prefix: decode_u8vector_argument(script.args().get(1)?.clone())?,
        add_all_currencies: decode_bool_argument(script.args().get(2)?.clone())?,
        child_initial_balance: decode_u64_argument(script.args().get(3)?.clone())?,
    })
}

fn decode_create_designated_dealer_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::CreateDesignatedDealer {
        currency: script.ty_args().get(0)?.clone(),
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        addr: decode_address_argument(script.args().get(1)?.clone())?,
        auth_key_prefix: decode_u8vector_argument(script.args().get(2)?.clone())?,
        human_name: decode_u8vector_argument(script.args().get(3)?.clone())?,
        add_all_currencies: decode_bool_argument(script.args().get(4)?.clone())?,
    })
}

fn decode_create_parent_vasp_account_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::CreateParentVaspAccount {
        coin_type: script.ty_args().get(0)?.clone(),
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        new_account_address: decode_address_argument(script.args().get(1)?.clone())?,
        auth_key_prefix: decode_u8vector_argument(script.args().get(2)?.clone())?,
        human_name: decode_u8vector_argument(script.args().get(3)?.clone())?,
        add_all_currencies: decode_bool_argument(script.args().get(4)?.clone())?,
    })
}

fn decode_create_recovery_address_script(_script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::CreateRecoveryAddress {})
}

fn decode_create_validator_account_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::CreateValidatorAccount {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        new_account_address: decode_address_argument(script.args().get(1)?.clone())?,
        auth_key_prefix: decode_u8vector_argument(script.args().get(2)?.clone())?,
        human_name: decode_u8vector_argument(script.args().get(3)?.clone())?,
    })
}

fn decode_create_validator_operator_account_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::CreateValidatorOperatorAccount {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        new_account_address: decode_address_argument(script.args().get(1)?.clone())?,
        auth_key_prefix: decode_u8vector_argument(script.args().get(2)?.clone())?,
        human_name: decode_u8vector_argument(script.args().get(3)?.clone())?,
    })
}

fn decode_freeze_account_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::FreezeAccount {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        to_freeze_account: decode_address_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_peer_to_peer_with_metadata_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::PeerToPeerWithMetadata {
        currency: script.ty_args().get(0)?.clone(),
        payee: decode_address_argument(script.args().get(0)?.clone())?,
        amount: decode_u64_argument(script.args().get(1)?.clone())?,
        metadata: decode_u8vector_argument(script.args().get(2)?.clone())?,
        metadata_signature: decode_u8vector_argument(script.args().get(3)?.clone())?,
    })
}

fn decode_preburn_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::Preburn {
        token: script.ty_args().get(0)?.clone(),
        amount: decode_u64_argument(script.args().get(0)?.clone())?,
    })
}

fn decode_publish_shared_ed25519_public_key_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::PublishSharedEd25519PublicKey {
        public_key: decode_u8vector_argument(script.args().get(0)?.clone())?,
    })
}

fn decode_register_validator_config_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::RegisterValidatorConfig {
        validator_account: decode_address_argument(script.args().get(0)?.clone())?,
        consensus_pubkey: decode_u8vector_argument(script.args().get(1)?.clone())?,
        validator_network_addresses: decode_u8vector_argument(script.args().get(2)?.clone())?,
        fullnode_network_addresses: decode_u8vector_argument(script.args().get(3)?.clone())?,
    })
}

fn decode_remove_validator_and_reconfigure_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::RemoveValidatorAndReconfigure {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        validator_name: decode_u8vector_argument(script.args().get(1)?.clone())?,
        validator_address: decode_address_argument(script.args().get(2)?.clone())?,
    })
}

fn decode_rotate_authentication_key_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::RotateAuthenticationKey {
        new_key: decode_u8vector_argument(script.args().get(0)?.clone())?,
    })
}

fn decode_rotate_authentication_key_with_nonce_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::RotateAuthenticationKeyWithNonce {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        new_key: decode_u8vector_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_rotate_authentication_key_with_nonce_admin_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::RotateAuthenticationKeyWithNonceAdmin {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        new_key: decode_u8vector_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_rotate_authentication_key_with_recovery_address_script(
    script: &Script,
) -> Option<ScriptCall> {
    Some(ScriptCall::RotateAuthenticationKeyWithRecoveryAddress {
        recovery_address: decode_address_argument(script.args().get(0)?.clone())?,
        to_recover: decode_address_argument(script.args().get(1)?.clone())?,
        new_key: decode_u8vector_argument(script.args().get(2)?.clone())?,
    })
}

fn decode_rotate_dual_attestation_info_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::RotateDualAttestationInfo {
        new_url: decode_u8vector_argument(script.args().get(0)?.clone())?,
        new_key: decode_u8vector_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_rotate_shared_ed25519_public_key_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::RotateSharedEd25519PublicKey {
        public_key: decode_u8vector_argument(script.args().get(0)?.clone())?,
    })
}

fn decode_set_validator_config_and_reconfigure_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::SetValidatorConfigAndReconfigure {
        validator_account: decode_address_argument(script.args().get(0)?.clone())?,
        consensus_pubkey: decode_u8vector_argument(script.args().get(1)?.clone())?,
        validator_network_addresses: decode_u8vector_argument(script.args().get(2)?.clone())?,
        fullnode_network_addresses: decode_u8vector_argument(script.args().get(3)?.clone())?,
    })
}

fn decode_set_validator_operator_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::SetValidatorOperator {
        operator_name: decode_u8vector_argument(script.args().get(0)?.clone())?,
        operator_account: decode_address_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_set_validator_operator_with_nonce_admin_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::SetValidatorOperatorWithNonceAdmin {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        operator_name: decode_u8vector_argument(script.args().get(1)?.clone())?,
        operator_account: decode_address_argument(script.args().get(2)?.clone())?,
    })
}

fn decode_tiered_mint_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::TieredMint {
        coin_type: script.ty_args().get(0)?.clone(),
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        designated_dealer_address: decode_address_argument(script.args().get(1)?.clone())?,
        mint_amount: decode_u64_argument(script.args().get(2)?.clone())?,
        tier_index: decode_u64_argument(script.args().get(3)?.clone())?,
    })
}

fn decode_unfreeze_account_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::UnfreezeAccount {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        to_unfreeze_account: decode_address_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_update_diem_version_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::UpdateDiemVersion {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        major: decode_u64_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_update_dual_attestation_limit_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::UpdateDualAttestationLimit {
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        new_micro_xdx_limit: decode_u64_argument(script.args().get(1)?.clone())?,
    })
}

fn decode_update_exchange_rate_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::UpdateExchangeRate {
        currency: script.ty_args().get(0)?.clone(),
        sliding_nonce: decode_u64_argument(script.args().get(0)?.clone())?,
        new_exchange_rate_numerator: decode_u64_argument(script.args().get(1)?.clone())?,
        new_exchange_rate_denominator: decode_u64_argument(script.args().get(2)?.clone())?,
    })
}

fn decode_update_minting_ability_script(script: &Script) -> Option<ScriptCall> {
    Some(ScriptCall::UpdateMintingAbility {
        currency: script.ty_args().get(0)?.clone(),
        allow_minting: decode_bool_argument(script.args().get(0)?.clone())?,
    })
}

type TransactionScriptDecoderMap = std::collections::HashMap<
    Vec<u8>,
    Box<dyn Fn(&Script) -> Option<ScriptCall> + std::marker::Sync + std::marker::Send>,
>;

static TRANSACTION_SCRIPT_DECODER_MAP: once_cell::sync::Lazy<TransactionScriptDecoderMap> =
    once_cell::sync::Lazy::new(|| {
        let mut map: TransactionScriptDecoderMap = std::collections::HashMap::new();
        map.insert(
            ADD_CURRENCY_TO_ACCOUNT_CODE.to_vec(),
            Box::new(decode_add_currency_to_account_script),
        );
        map.insert(
            ADD_RECOVERY_ROTATION_CAPABILITY_CODE.to_vec(),
            Box::new(decode_add_recovery_rotation_capability_script),
        );
        map.insert(
            ADD_VALIDATOR_AND_RECONFIGURE_CODE.to_vec(),
            Box::new(decode_add_validator_and_reconfigure_script),
        );
        map.insert(BURN_CODE.to_vec(), Box::new(decode_burn_script));
        map.insert(
            BURN_TXN_FEES_CODE.to_vec(),
            Box::new(decode_burn_txn_fees_script),
        );
        map.insert(
            CANCEL_BURN_CODE.to_vec(),
            Box::new(decode_cancel_burn_script),
        );
        map.insert(
            CREATE_CHILD_VASP_ACCOUNT_CODE.to_vec(),
            Box::new(decode_create_child_vasp_account_script),
        );
        map.insert(
            CREATE_DESIGNATED_DEALER_CODE.to_vec(),
            Box::new(decode_create_designated_dealer_script),
        );
        map.insert(
            CREATE_PARENT_VASP_ACCOUNT_CODE.to_vec(),
            Box::new(decode_create_parent_vasp_account_script),
        );
        map.insert(
            CREATE_RECOVERY_ADDRESS_CODE.to_vec(),
            Box::new(decode_create_recovery_address_script),
        );
        map.insert(
            CREATE_VALIDATOR_ACCOUNT_CODE.to_vec(),
            Box::new(decode_create_validator_account_script),
        );
        map.insert(
            CREATE_VALIDATOR_OPERATOR_ACCOUNT_CODE.to_vec(),
            Box::new(decode_create_validator_operator_account_script),
        );
        map.insert(
            FREEZE_ACCOUNT_CODE.to_vec(),
            Box::new(decode_freeze_account_script),
        );
        map.insert(
            PEER_TO_PEER_WITH_METADATA_CODE.to_vec(),
            Box::new(decode_peer_to_peer_with_metadata_script),
        );
        map.insert(PREBURN_CODE.to_vec(), Box::new(decode_preburn_script));
        map.insert(
            PUBLISH_SHARED_ED25519_PUBLIC_KEY_CODE.to_vec(),
            Box::new(decode_publish_shared_ed25519_public_key_script),
        );
        map.insert(
            REGISTER_VALIDATOR_CONFIG_CODE.to_vec(),
            Box::new(decode_register_validator_config_script),
        );
        map.insert(
            REMOVE_VALIDATOR_AND_RECONFIGURE_CODE.to_vec(),
            Box::new(decode_remove_validator_and_reconfigure_script),
        );
        map.insert(
            ROTATE_AUTHENTICATION_KEY_CODE.to_vec(),
            Box::new(decode_rotate_authentication_key_script),
        );
        map.insert(
            ROTATE_AUTHENTICATION_KEY_WITH_NONCE_CODE.to_vec(),
            Box::new(decode_rotate_authentication_key_with_nonce_script),
        );
        map.insert(
            ROTATE_AUTHENTICATION_KEY_WITH_NONCE_ADMIN_CODE.to_vec(),
            Box::new(decode_rotate_authentication_key_with_nonce_admin_script),
        );
        map.insert(
            ROTATE_AUTHENTICATION_KEY_WITH_RECOVERY_ADDRESS_CODE.to_vec(),
            Box::new(decode_rotate_authentication_key_with_recovery_address_script),
        );
        map.insert(
            ROTATE_DUAL_ATTESTATION_INFO_CODE.to_vec(),
            Box::new(decode_rotate_dual_attestation_info_script),
        );
        map.insert(
            ROTATE_SHARED_ED25519_PUBLIC_KEY_CODE.to_vec(),
            Box::new(decode_rotate_shared_ed25519_public_key_script),
        );
        map.insert(
            SET_VALIDATOR_CONFIG_AND_RECONFIGURE_CODE.to_vec(),
            Box::new(decode_set_validator_config_and_reconfigure_script),
        );
        map.insert(
            SET_VALIDATOR_OPERATOR_CODE.to_vec(),
            Box::new(decode_set_validator_operator_script),
        );
        map.insert(
            SET_VALIDATOR_OPERATOR_WITH_NONCE_ADMIN_CODE.to_vec(),
            Box::new(decode_set_validator_operator_with_nonce_admin_script),
        );
        map.insert(
            TIERED_MINT_CODE.to_vec(),
            Box::new(decode_tiered_mint_script),
        );
        map.insert(
            UNFREEZE_ACCOUNT_CODE.to_vec(),
            Box::new(decode_unfreeze_account_script),
        );
        map.insert(
            UPDATE_DIEM_VERSION_CODE.to_vec(),
            Box::new(decode_update_diem_version_script),
        );
        map.insert(
            UPDATE_DUAL_ATTESTATION_LIMIT_CODE.to_vec(),
            Box::new(decode_update_dual_attestation_limit_script),
        );
        map.insert(
            UPDATE_EXCHANGE_RATE_CODE.to_vec(),
            Box::new(decode_update_exchange_rate_script),
        );
        map.insert(
            UPDATE_MINTING_ABILITY_CODE.to_vec(),
            Box::new(decode_update_minting_ability_script),
        );
        map
    });

type ScriptFunctionDecoderMap = std::collections::HashMap<
    String,
    Box<
        dyn Fn(&TransactionPayload) -> Option<ScriptFunctionCall>
            + std::marker::Sync
            + std::marker::Send,
    >,
>;

static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy<ScriptFunctionDecoderMap> =
    once_cell::sync::Lazy::new(|| {
        let mut map: ScriptFunctionDecoderMap = std::collections::HashMap::new();
        map.insert(
            "AccountAdministrationScriptsadd_currency_to_account".to_string(),
            Box::new(decode_add_currency_to_account_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsadd_diem_id_domain".to_string(),
            Box::new(decode_add_diem_id_domain_script_function),
        );
        map.insert(
            "AccountAdministrationScriptsadd_recovery_rotation_capability".to_string(),
            Box::new(decode_add_recovery_rotation_capability_script_function),
        );
        map.insert(
            "ValidatorAdministrationScriptsadd_validator_and_reconfigure".to_string(),
            Box::new(decode_add_validator_and_reconfigure_script_function),
        );
        map.insert(
            "AutoPayScriptsautopay_create_instruction".to_string(),
            Box::new(decode_autopay_create_instruction_script_function),
        );
        map.insert(
            "AutoPayScriptsautopay_disable".to_string(),
            Box::new(decode_autopay_disable_script_function),
        );
        map.insert(
            "AutoPayScriptsautopay_enable".to_string(),
            Box::new(decode_autopay_enable_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsburn_txn_fees".to_string(),
            Box::new(decode_burn_txn_fees_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsburn_with_amount".to_string(),
            Box::new(decode_burn_with_amount_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptscancel_burn_with_amount".to_string(),
            Box::new(decode_cancel_burn_with_amount_script_function),
        );
        map.insert(
            "AccountScriptscreate_acc_user".to_string(),
            Box::new(decode_create_acc_user_script_function),
        );
        map.insert(
            "AccountScriptscreate_acc_val".to_string(),
            Box::new(decode_create_acc_val_script_function),
        );
        map.insert(
            "AccountCreationScriptscreate_child_vasp_account".to_string(),
            Box::new(decode_create_child_vasp_account_script_function),
        );
        map.insert(
            "AccountCreationScriptscreate_designated_dealer".to_string(),
            Box::new(decode_create_designated_dealer_script_function),
        );
        map.insert(
            "AccountAdministrationScriptscreate_diem_id_domains".to_string(),
            Box::new(decode_create_diem_id_domains_script_function),
        );
        map.insert(
            "AccountCreationScriptscreate_parent_vasp_account".to_string(),
            Box::new(decode_create_parent_vasp_account_script_function),
        );
        map.insert(
            "AccountAdministrationScriptscreate_recovery_address".to_string(),
            Box::new(decode_create_recovery_address_script_function),
        );
        map.insert(
            "AccountCreationScriptscreate_validator_account".to_string(),
            Box::new(decode_create_validator_account_script_function),
        );
        map.insert(
            "AccountCreationScriptscreate_validator_operator_account".to_string(),
            Box::new(decode_create_validator_operator_account_script_function),
        );
        map.insert(
            "DemoScriptsdemo_e2e".to_string(),
            Box::new(decode_demo_e2e_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsfreeze_account".to_string(),
            Box::new(decode_freeze_account_script_function),
        );
        map.insert(
            "SystemAdministrationScriptsinitialize_diem_consensus_config".to_string(),
            Box::new(decode_initialize_diem_consensus_config_script_function),
        );
        map.insert(
            "ValidatorScriptsjoin".to_string(),
            Box::new(decode_join_script_function),
        );
        map.insert(
            "ValidatorScriptsleave".to_string(),
            Box::new(decode_leave_script_function),
        );
        map.insert(
            "MinerStateScriptsminerstate_commit".to_string(),
            Box::new(decode_minerstate_commit_script_function),
        );
        map.insert(
            "MinerStateScriptsminerstate_commit_by_operator".to_string(),
            Box::new(decode_minerstate_commit_by_operator_script_function),
        );
        map.insert(
            "MinerStateScriptsminerstate_helper".to_string(),
            Box::new(decode_minerstate_helper_script_function),
        );
        map.insert(
            "OracleScriptsol_oracle_tx".to_string(),
            Box::new(decode_ol_oracle_tx_script_function),
        );
        map.insert(
            "ValidatorScriptsol_reconfig_bulk_update_setup".to_string(),
            Box::new(decode_ol_reconfig_bulk_update_setup_script_function),
        );
        map.insert(
            "PaymentScriptspeer_to_peer_with_metadata".to_string(),
            Box::new(decode_peer_to_peer_with_metadata_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptspreburn".to_string(),
            Box::new(decode_preburn_script_function),
        );
        map.insert(
            "AccountAdministrationScriptspublish_shared_ed25519_public_key".to_string(),
            Box::new(decode_publish_shared_ed25519_public_key_script_function),
        );
        map.insert(
            "ValidatorAdministrationScriptsregister_validator_config".to_string(),
            Box::new(decode_register_validator_config_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsremove_diem_id_domain".to_string(),
            Box::new(decode_remove_diem_id_domain_script_function),
        );
        map.insert(
            "ValidatorAdministrationScriptsremove_validator_and_reconfigure".to_string(),
            Box::new(decode_remove_validator_and_reconfigure_script_function),
        );
        map.insert(
            "AccountAdministrationScriptsrotate_authentication_key".to_string(),
            Box::new(decode_rotate_authentication_key_script_function),
        );
        map.insert(
            "AccountAdministrationScriptsrotate_authentication_key_with_nonce".to_string(),
            Box::new(decode_rotate_authentication_key_with_nonce_script_function),
        );
        map.insert(
            "AccountAdministrationScriptsrotate_authentication_key_with_nonce_admin".to_string(),
            Box::new(decode_rotate_authentication_key_with_nonce_admin_script_function),
        );
        map.insert(
            "AccountAdministrationScriptsrotate_authentication_key_with_recovery_address"
                .to_string(),
            Box::new(decode_rotate_authentication_key_with_recovery_address_script_function),
        );
        map.insert(
            "AccountAdministrationScriptsrotate_dual_attestation_info".to_string(),
            Box::new(decode_rotate_dual_attestation_info_script_function),
        );
        map.insert(
            "AccountAdministrationScriptsrotate_shared_ed25519_public_key".to_string(),
            Box::new(decode_rotate_shared_ed25519_public_key_script_function),
        );
        map.insert(
            "SystemAdministrationScriptsset_gas_constants".to_string(),
            Box::new(decode_set_gas_constants_script_function),
        );
        map.insert(
            "ValidatorAdministrationScriptsset_validator_config_and_reconfigure".to_string(),
            Box::new(decode_set_validator_config_and_reconfigure_script_function),
        );
        map.insert(
            "ValidatorAdministrationScriptsset_validator_operator".to_string(),
            Box::new(decode_set_validator_operator_script_function),
        );
        map.insert(
            "ValidatorAdministrationScriptsset_validator_operator_with_nonce_admin".to_string(),
            Box::new(decode_set_validator_operator_with_nonce_admin_script_function),
        );
        map.insert(
            "WalletScriptsset_wallet_type".to_string(),
            Box::new(decode_set_wallet_type_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptstiered_mint".to_string(),
            Box::new(decode_tiered_mint_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsunfreeze_account".to_string(),
            Box::new(decode_unfreeze_account_script_function),
        );
        map.insert(
            "SystemAdministrationScriptsupdate_diem_consensus_config".to_string(),
            Box::new(decode_update_diem_consensus_config_script_function),
        );
        map.insert(
            "SystemAdministrationScriptsupdate_diem_version".to_string(),
            Box::new(decode_update_diem_version_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsupdate_dual_attestation_limit".to_string(),
            Box::new(decode_update_dual_attestation_limit_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsupdate_exchange_rate".to_string(),
            Box::new(decode_update_exchange_rate_script_function),
        );
        map.insert(
            "TreasuryComplianceScriptsupdate_minting_ability".to_string(),
            Box::new(decode_update_minting_ability_script_function),
        );
        map.insert(
            "ValidatorScriptsval_add_self".to_string(),
            Box::new(decode_val_add_self_script_function),
        );
        map
    });

fn decode_bool_argument(arg: TransactionArgument) -> Option<bool> {
    match arg {
        TransactionArgument::Bool(value) => Some(value),
        _ => None,
    }
}

fn decode_u8_argument(arg: TransactionArgument) -> Option<u8> {
    match arg {
        TransactionArgument::U8(value) => Some(value),
        _ => None,
    }
}

fn decode_u64_argument(arg: TransactionArgument) -> Option<u64> {
    match arg {
        TransactionArgument::U64(value) => Some(value),
        _ => None,
    }
}

fn decode_address_argument(arg: TransactionArgument) -> Option<AccountAddress> {
    match arg {
        TransactionArgument::Address(value) => Some(value),
        _ => None,
    }
}

fn decode_u8vector_argument(arg: TransactionArgument) -> Option<Vec<u8>> {
    match arg {
        TransactionArgument::U8Vector(value) => Some(value),
        _ => None,
    }
}

const ADD_CURRENCY_TO_ACCOUNT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 2, 3, 2, 6, 4, 8, 2, 5, 10, 7, 7, 17, 25, 8, 42, 16, 0,
    0, 0, 1, 0, 1, 1, 1, 0, 2, 1, 6, 12, 0, 1, 9, 0, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117,
    110, 116, 12, 97, 100, 100, 95, 99, 117, 114, 114, 101, 110, 99, 121, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 3, 11, 0, 56, 0, 2,
];

const ADD_RECOVERY_ROTATION_CAPABILITY_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 4, 2, 4, 4, 3, 8, 10, 5, 18, 15, 7, 33, 106, 8, 139, 1,
    16, 0, 0, 0, 1, 0, 2, 1, 0, 0, 3, 0, 1, 0, 1, 4, 2, 3, 0, 1, 6, 12, 1, 8, 0, 2, 8, 0, 5, 0, 2,
    6, 12, 5, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117, 110, 116, 15, 82, 101, 99, 111, 118,
    101, 114, 121, 65, 100, 100, 114, 101, 115, 115, 21, 75, 101, 121, 82, 111, 116, 97, 116, 105,
    111, 110, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121, 31, 101, 120, 116, 114, 97, 99, 116,
    95, 107, 101, 121, 95, 114, 111, 116, 97, 116, 105, 111, 110, 95, 99, 97, 112, 97, 98, 105,
    108, 105, 116, 121, 23, 97, 100, 100, 95, 114, 111, 116, 97, 116, 105, 111, 110, 95, 99, 97,
    112, 97, 98, 105, 108, 105, 116, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 3,
    5, 11, 0, 17, 0, 10, 1, 17, 1, 2,
];

const ADD_VALIDATOR_AND_RECONFIGURE_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 6, 3, 6, 15, 5, 21, 24, 7, 45, 91, 8, 136, 1, 16, 0, 0,
    0, 1, 0, 2, 1, 3, 0, 1, 0, 2, 4, 2, 3, 0, 0, 5, 4, 1, 0, 2, 6, 12, 3, 0, 1, 5, 1, 10, 2, 2, 6,
    12, 5, 4, 6, 12, 3, 10, 2, 5, 2, 1, 3, 10, 68, 105, 101, 109, 83, 121, 115, 116, 101, 109, 12,
    83, 108, 105, 100, 105, 110, 103, 78, 111, 110, 99, 101, 15, 86, 97, 108, 105, 100, 97, 116,
    111, 114, 67, 111, 110, 102, 105, 103, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99,
    101, 95, 111, 114, 95, 97, 98, 111, 114, 116, 14, 103, 101, 116, 95, 104, 117, 109, 97, 110,
    95, 110, 97, 109, 101, 13, 97, 100, 100, 95, 118, 97, 108, 105, 100, 97, 116, 111, 114, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 6, 18, 10, 0, 10, 1, 17, 0, 10, 3, 17, 1, 11,
    2, 33, 12, 4, 11, 4, 3, 14, 11, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 39, 11, 0, 10, 3, 17, 2, 2,
];

const BURN_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 4, 3, 4, 11, 4, 15, 2, 5, 17, 17, 7, 34, 45, 8, 79, 16,
    0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 3, 2, 1, 1, 1, 1, 4, 2, 6, 12, 3, 0, 2, 6, 12, 5, 3, 6, 12, 3, 5,
    1, 9, 0, 4, 68, 105, 101, 109, 12, 83, 108, 105, 100, 105, 110, 103, 78, 111, 110, 99, 101, 21,
    114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95, 97, 98, 111, 114,
    116, 4, 98, 117, 114, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 1, 7, 10,
    0, 10, 1, 17, 0, 11, 0, 10, 2, 56, 0, 2,
];

const BURN_TXN_FEES_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 2, 3, 2, 6, 4, 8, 2, 5, 10, 7, 7, 17, 25, 8, 42, 16, 0,
    0, 0, 1, 0, 1, 1, 1, 0, 2, 1, 6, 12, 0, 1, 9, 0, 14, 84, 114, 97, 110, 115, 97, 99, 116, 105,
    111, 110, 70, 101, 101, 9, 98, 117, 114, 110, 95, 102, 101, 101, 115, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 3, 11, 0, 56, 0, 2,
];

const CANCEL_BURN_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 2, 3, 2, 6, 4, 8, 2, 5, 10, 8, 7, 18, 24, 8, 42, 16, 0,
    0, 0, 1, 0, 1, 1, 1, 0, 2, 2, 6, 12, 5, 0, 1, 9, 0, 11, 68, 105, 101, 109, 65, 99, 99, 111,
    117, 110, 116, 11, 99, 97, 110, 99, 101, 108, 95, 98, 117, 114, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 4, 11, 0, 10, 1, 56, 0, 2,
];

const CREATE_CHILD_VASP_ACCOUNT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 8, 1, 0, 2, 2, 2, 4, 3, 6, 22, 4, 28, 4, 5, 32, 35, 7, 67, 122,
    8, 189, 1, 16, 6, 205, 1, 4, 0, 0, 0, 1, 1, 0, 0, 2, 0, 1, 1, 1, 0, 3, 2, 3, 0, 0, 4, 4, 1, 1,
    1, 0, 5, 3, 1, 0, 0, 6, 2, 6, 4, 6, 12, 5, 10, 2, 1, 0, 1, 6, 12, 1, 8, 0, 5, 6, 8, 0, 5, 3,
    10, 2, 10, 2, 5, 6, 12, 5, 10, 2, 1, 3, 1, 9, 0, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117,
    110, 116, 18, 87, 105, 116, 104, 100, 114, 97, 119, 67, 97, 112, 97, 98, 105, 108, 105, 116,
    121, 25, 99, 114, 101, 97, 116, 101, 95, 99, 104, 105, 108, 100, 95, 118, 97, 115, 112, 95, 97,
    99, 99, 111, 117, 110, 116, 27, 101, 120, 116, 114, 97, 99, 116, 95, 119, 105, 116, 104, 100,
    114, 97, 119, 95, 99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 8, 112, 97, 121, 95, 102, 114,
    111, 109, 27, 114, 101, 115, 116, 111, 114, 101, 95, 119, 105, 116, 104, 100, 114, 97, 119, 95,
    99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    10, 2, 1, 0, 1, 1, 5, 3, 25, 10, 0, 10, 1, 11, 2, 10, 3, 56, 0, 10, 4, 6, 0, 0, 0, 0, 0, 0, 0,
    0, 36, 3, 10, 5, 22, 11, 0, 17, 1, 12, 5, 14, 5, 10, 1, 10, 4, 7, 0, 7, 0, 56, 1, 11, 5, 17, 3,
    5, 24, 11, 0, 1, 2,
];

const CREATE_DESIGNATED_DEALER_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 4, 3, 4, 11, 4, 15, 2, 5, 17, 27, 7, 44, 72, 8, 116, 16,
    0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 3, 2, 1, 1, 1, 1, 4, 2, 6, 12, 3, 0, 5, 6, 12, 5, 10, 2, 10, 2,
    1, 6, 6, 12, 3, 5, 10, 2, 10, 2, 1, 1, 9, 0, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117, 110,
    116, 12, 83, 108, 105, 100, 105, 110, 103, 78, 111, 110, 99, 101, 21, 114, 101, 99, 111, 114,
    100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95, 97, 98, 111, 114, 116, 24, 99, 114, 101, 97,
    116, 101, 95, 100, 101, 115, 105, 103, 110, 97, 116, 101, 100, 95, 100, 101, 97, 108, 101, 114,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 1, 10, 10, 0, 10, 1, 17, 0, 11, 0, 10,
    2, 11, 3, 11, 4, 10, 5, 56, 0, 2,
];

const CREATE_PARENT_VASP_ACCOUNT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 4, 3, 4, 11, 4, 15, 2, 5, 17, 27, 7, 44, 74, 8, 118, 16,
    0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 3, 2, 1, 1, 1, 1, 4, 2, 6, 12, 3, 0, 5, 6, 12, 5, 10, 2, 10, 2,
    1, 6, 6, 12, 3, 5, 10, 2, 10, 2, 1, 1, 9, 0, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117, 110,
    116, 12, 83, 108, 105, 100, 105, 110, 103, 78, 111, 110, 99, 101, 21, 114, 101, 99, 111, 114,
    100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95, 97, 98, 111, 114, 116, 26, 99, 114, 101, 97,
    116, 101, 95, 112, 97, 114, 101, 110, 116, 95, 118, 97, 115, 112, 95, 97, 99, 99, 111, 117,
    110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 1, 10, 10, 0, 10, 1, 17, 0,
    11, 0, 10, 2, 11, 3, 11, 4, 10, 5, 56, 0, 2,
];

const CREATE_RECOVERY_ADDRESS_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 4, 2, 4, 4, 3, 8, 10, 5, 18, 12, 7, 30, 90, 8, 120, 16,
    0, 0, 0, 1, 0, 2, 1, 0, 0, 3, 0, 1, 0, 1, 4, 2, 3, 0, 1, 6, 12, 1, 8, 0, 2, 6, 12, 8, 0, 0, 11,
    68, 105, 101, 109, 65, 99, 99, 111, 117, 110, 116, 15, 82, 101, 99, 111, 118, 101, 114, 121,
    65, 100, 100, 114, 101, 115, 115, 21, 75, 101, 121, 82, 111, 116, 97, 116, 105, 111, 110, 67,
    97, 112, 97, 98, 105, 108, 105, 116, 121, 31, 101, 120, 116, 114, 97, 99, 116, 95, 107, 101,
    121, 95, 114, 111, 116, 97, 116, 105, 111, 110, 95, 99, 97, 112, 97, 98, 105, 108, 105, 116,
    121, 7, 112, 117, 98, 108, 105, 115, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
    3, 5, 10, 0, 11, 0, 17, 0, 17, 1, 2,
];

const CREATE_VALIDATOR_ACCOUNT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 4, 3, 4, 10, 5, 14, 22, 7, 36, 72, 8, 108, 16, 0, 0, 0,
    1, 1, 2, 0, 1, 0, 0, 3, 2, 1, 0, 2, 6, 12, 3, 0, 4, 6, 12, 5, 10, 2, 10, 2, 5, 6, 12, 3, 5, 10,
    2, 10, 2, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117, 110, 116, 12, 83, 108, 105, 100, 105,
    110, 103, 78, 111, 110, 99, 101, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101,
    95, 111, 114, 95, 97, 98, 111, 114, 116, 24, 99, 114, 101, 97, 116, 101, 95, 118, 97, 108, 105,
    100, 97, 116, 111, 114, 95, 97, 99, 99, 111, 117, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 1, 0, 3, 1, 9, 10, 0, 10, 1, 17, 0, 11, 0, 10, 2, 11, 3, 11, 4, 17, 1, 2,
];

const CREATE_VALIDATOR_OPERATOR_ACCOUNT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 4, 3, 4, 10, 5, 14, 22, 7, 36, 81, 8, 117, 16, 0, 0, 0,
    1, 1, 2, 0, 1, 0, 0, 3, 2, 1, 0, 2, 6, 12, 3, 0, 4, 6, 12, 5, 10, 2, 10, 2, 5, 6, 12, 3, 5, 10,
    2, 10, 2, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117, 110, 116, 12, 83, 108, 105, 100, 105,
    110, 103, 78, 111, 110, 99, 101, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101,
    95, 111, 114, 95, 97, 98, 111, 114, 116, 33, 99, 114, 101, 97, 116, 101, 95, 118, 97, 108, 105,
    100, 97, 116, 111, 114, 95, 111, 112, 101, 114, 97, 116, 111, 114, 95, 97, 99, 99, 111, 117,
    110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 1, 9, 10, 0, 10, 1, 17, 0, 11,
    0, 10, 2, 11, 3, 11, 4, 17, 1, 2,
];

const FREEZE_ACCOUNT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 4, 3, 4, 10, 5, 14, 14, 7, 28, 66, 8, 94, 16, 0, 0, 0,
    1, 0, 2, 0, 1, 0, 1, 3, 2, 1, 0, 2, 6, 12, 5, 0, 2, 6, 12, 3, 3, 6, 12, 3, 5, 15, 65, 99, 99,
    111, 117, 110, 116, 70, 114, 101, 101, 122, 105, 110, 103, 12, 83, 108, 105, 100, 105, 110,
    103, 78, 111, 110, 99, 101, 14, 102, 114, 101, 101, 122, 101, 95, 97, 99, 99, 111, 117, 110,
    116, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95, 97, 98,
    111, 114, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 1, 7, 10, 0, 10, 1, 17, 1,
    11, 0, 10, 2, 17, 0, 2,
];

const PEER_TO_PEER_WITH_METADATA_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 7, 1, 0, 2, 2, 2, 4, 3, 6, 16, 4, 22, 2, 5, 24, 29, 7, 53, 96, 8,
    149, 1, 16, 0, 0, 0, 1, 1, 0, 0, 2, 0, 1, 0, 0, 3, 2, 3, 1, 1, 0, 4, 1, 3, 0, 1, 5, 1, 6, 12,
    1, 8, 0, 5, 6, 8, 0, 5, 3, 10, 2, 10, 2, 0, 5, 6, 12, 5, 3, 10, 2, 10, 2, 1, 9, 0, 11, 68, 105,
    101, 109, 65, 99, 99, 111, 117, 110, 116, 18, 87, 105, 116, 104, 100, 114, 97, 119, 67, 97,
    112, 97, 98, 105, 108, 105, 116, 121, 27, 101, 120, 116, 114, 97, 99, 116, 95, 119, 105, 116,
    104, 100, 114, 97, 119, 95, 99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 8, 112, 97, 121, 95,
    102, 114, 111, 109, 27, 114, 101, 115, 116, 111, 114, 101, 95, 119, 105, 116, 104, 100, 114,
    97, 119, 95, 99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 1, 1, 1, 4, 1, 12, 11, 0, 17, 0, 12, 5, 14, 5, 10, 1, 10, 2, 11, 3, 11, 4, 56, 0, 11,
    5, 17, 2, 2,
];

const PREBURN_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 7, 1, 0, 2, 2, 2, 4, 3, 6, 16, 4, 22, 2, 5, 24, 21, 7, 45, 95, 8,
    140, 1, 16, 0, 0, 0, 1, 1, 0, 0, 2, 0, 1, 0, 0, 3, 2, 3, 1, 1, 0, 4, 1, 3, 0, 1, 5, 1, 6, 12,
    1, 8, 0, 3, 6, 12, 6, 8, 0, 3, 0, 2, 6, 12, 3, 1, 9, 0, 11, 68, 105, 101, 109, 65, 99, 99, 111,
    117, 110, 116, 18, 87, 105, 116, 104, 100, 114, 97, 119, 67, 97, 112, 97, 98, 105, 108, 105,
    116, 121, 27, 101, 120, 116, 114, 97, 99, 116, 95, 119, 105, 116, 104, 100, 114, 97, 119, 95,
    99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 7, 112, 114, 101, 98, 117, 114, 110, 27, 114,
    101, 115, 116, 111, 114, 101, 95, 119, 105, 116, 104, 100, 114, 97, 119, 95, 99, 97, 112, 97,
    98, 105, 108, 105, 116, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 4, 1, 10,
    10, 0, 17, 0, 12, 2, 11, 0, 14, 2, 10, 1, 56, 0, 11, 2, 17, 2, 2,
];

const PUBLISH_SHARED_ED25519_PUBLIC_KEY_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 2, 3, 2, 5, 5, 7, 6, 7, 13, 31, 8, 44, 16, 0, 0, 0, 1,
    0, 1, 0, 2, 6, 12, 10, 2, 0, 22, 83, 104, 97, 114, 101, 100, 69, 100, 50, 53, 53, 49, 57, 80,
    117, 98, 108, 105, 99, 75, 101, 121, 7, 112, 117, 98, 108, 105, 115, 104, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 4, 11, 0, 11, 1, 17, 0, 2,
];

const REGISTER_VALIDATOR_CONFIG_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 2, 3, 2, 5, 5, 7, 11, 7, 18, 27, 8, 45, 16, 0, 0, 0, 1,
    0, 1, 0, 5, 6, 12, 5, 10, 2, 10, 2, 10, 2, 0, 15, 86, 97, 108, 105, 100, 97, 116, 111, 114, 67,
    111, 110, 102, 105, 103, 10, 115, 101, 116, 95, 99, 111, 110, 102, 105, 103, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 7, 11, 0, 10, 1, 11, 2, 11, 3, 11, 4, 17, 0, 2,
];

const REMOVE_VALIDATOR_AND_RECONFIGURE_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 6, 3, 6, 15, 5, 21, 24, 7, 45, 94, 8, 139, 1, 16, 0, 0,
    0, 1, 0, 2, 1, 3, 0, 1, 0, 2, 4, 2, 3, 0, 0, 5, 4, 1, 0, 2, 6, 12, 3, 0, 1, 5, 1, 10, 2, 2, 6,
    12, 5, 4, 6, 12, 3, 10, 2, 5, 2, 1, 3, 10, 68, 105, 101, 109, 83, 121, 115, 116, 101, 109, 12,
    83, 108, 105, 100, 105, 110, 103, 78, 111, 110, 99, 101, 15, 86, 97, 108, 105, 100, 97, 116,
    111, 114, 67, 111, 110, 102, 105, 103, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99,
    101, 95, 111, 114, 95, 97, 98, 111, 114, 116, 14, 103, 101, 116, 95, 104, 117, 109, 97, 110,
    95, 110, 97, 109, 101, 16, 114, 101, 109, 111, 118, 101, 95, 118, 97, 108, 105, 100, 97, 116,
    111, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 6, 18, 10, 0, 10, 1, 17, 0, 10,
    3, 17, 1, 11, 2, 33, 12, 4, 11, 4, 3, 14, 11, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 39, 11, 0, 10,
    3, 17, 2, 2,
];

const ROTATE_AUTHENTICATION_KEY_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 2, 2, 2, 4, 3, 6, 15, 5, 21, 18, 7, 39, 124, 8, 163, 1,
    16, 0, 0, 0, 1, 1, 0, 0, 2, 0, 1, 0, 0, 3, 1, 2, 0, 0, 4, 3, 2, 0, 1, 6, 12, 1, 8, 0, 0, 2, 6,
    8, 0, 10, 2, 2, 6, 12, 10, 2, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117, 110, 116, 21, 75,
    101, 121, 82, 111, 116, 97, 116, 105, 111, 110, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121,
    31, 101, 120, 116, 114, 97, 99, 116, 95, 107, 101, 121, 95, 114, 111, 116, 97, 116, 105, 111,
    110, 95, 99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 31, 114, 101, 115, 116, 111, 114, 101,
    95, 107, 101, 121, 95, 114, 111, 116, 97, 116, 105, 111, 110, 95, 99, 97, 112, 97, 98, 105,
    108, 105, 116, 121, 25, 114, 111, 116, 97, 116, 101, 95, 97, 117, 116, 104, 101, 110, 116, 105,
    99, 97, 116, 105, 111, 110, 95, 107, 101, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    0, 4, 1, 9, 11, 0, 17, 0, 12, 2, 14, 2, 11, 1, 17, 2, 11, 2, 17, 1, 2,
];

const ROTATE_AUTHENTICATION_KEY_WITH_NONCE_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 4, 2, 4, 4, 3, 8, 20, 5, 28, 23, 7, 51, 159, 1, 8, 210,
    1, 16, 0, 0, 0, 1, 0, 3, 1, 0, 1, 2, 0, 1, 0, 0, 4, 2, 3, 0, 0, 5, 3, 1, 0, 0, 6, 4, 1, 0, 2,
    6, 12, 3, 0, 1, 6, 12, 1, 8, 0, 2, 6, 8, 0, 10, 2, 3, 6, 12, 3, 10, 2, 11, 68, 105, 101, 109,
    65, 99, 99, 111, 117, 110, 116, 12, 83, 108, 105, 100, 105, 110, 103, 78, 111, 110, 99, 101,
    21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95, 97, 98, 111,
    114, 116, 21, 75, 101, 121, 82, 111, 116, 97, 116, 105, 111, 110, 67, 97, 112, 97, 98, 105,
    108, 105, 116, 121, 31, 101, 120, 116, 114, 97, 99, 116, 95, 107, 101, 121, 95, 114, 111, 116,
    97, 116, 105, 111, 110, 95, 99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 31, 114, 101, 115,
    116, 111, 114, 101, 95, 107, 101, 121, 95, 114, 111, 116, 97, 116, 105, 111, 110, 95, 99, 97,
    112, 97, 98, 105, 108, 105, 116, 121, 25, 114, 111, 116, 97, 116, 101, 95, 97, 117, 116, 104,
    101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 95, 107, 101, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 1, 0, 5, 3, 12, 10, 0, 10, 1, 17, 0, 11, 0, 17, 1, 12, 3, 14, 3, 11, 2, 17,
    3, 11, 3, 17, 2, 2,
];

const ROTATE_AUTHENTICATION_KEY_WITH_NONCE_ADMIN_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 4, 2, 4, 4, 3, 8, 20, 5, 28, 25, 7, 53, 159, 1, 8, 212,
    1, 16, 0, 0, 0, 1, 0, 3, 1, 0, 1, 2, 0, 1, 0, 0, 4, 2, 3, 0, 0, 5, 3, 1, 0, 0, 6, 4, 1, 0, 2,
    6, 12, 3, 0, 1, 6, 12, 1, 8, 0, 2, 6, 8, 0, 10, 2, 4, 6, 12, 6, 12, 3, 10, 2, 11, 68, 105, 101,
    109, 65, 99, 99, 111, 117, 110, 116, 12, 83, 108, 105, 100, 105, 110, 103, 78, 111, 110, 99,
    101, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95, 97, 98,
    111, 114, 116, 21, 75, 101, 121, 82, 111, 116, 97, 116, 105, 111, 110, 67, 97, 112, 97, 98,
    105, 108, 105, 116, 121, 31, 101, 120, 116, 114, 97, 99, 116, 95, 107, 101, 121, 95, 114, 111,
    116, 97, 116, 105, 111, 110, 95, 99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 31, 114, 101,
    115, 116, 111, 114, 101, 95, 107, 101, 121, 95, 114, 111, 116, 97, 116, 105, 111, 110, 95, 99,
    97, 112, 97, 98, 105, 108, 105, 116, 121, 25, 114, 111, 116, 97, 116, 101, 95, 97, 117, 116,
    104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 95, 107, 101, 121, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 3, 12, 11, 0, 10, 2, 17, 0, 11, 1, 17, 1, 12, 4, 14, 4, 11, 3,
    17, 3, 11, 4, 17, 2, 2,
];

const ROTATE_AUTHENTICATION_KEY_WITH_RECOVERY_ADDRESS_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 2, 3, 2, 5, 5, 7, 8, 7, 15, 42, 8, 57, 16, 0, 0, 0, 1,
    0, 1, 0, 4, 6, 12, 5, 5, 10, 2, 0, 15, 82, 101, 99, 111, 118, 101, 114, 121, 65, 100, 100, 114,
    101, 115, 115, 25, 114, 111, 116, 97, 116, 101, 95, 97, 117, 116, 104, 101, 110, 116, 105, 99,
    97, 116, 105, 111, 110, 95, 107, 101, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
    0, 1, 6, 11, 0, 10, 1, 10, 2, 11, 3, 17, 0, 2,
];

const ROTATE_DUAL_ATTESTATION_INFO_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 2, 3, 2, 10, 5, 12, 13, 7, 25, 61, 8, 86, 16, 0, 0, 0,
    1, 0, 1, 0, 0, 2, 0, 1, 0, 2, 6, 12, 10, 2, 0, 3, 6, 12, 10, 2, 10, 2, 15, 68, 117, 97, 108,
    65, 116, 116, 101, 115, 116, 97, 116, 105, 111, 110, 15, 114, 111, 116, 97, 116, 101, 95, 98,
    97, 115, 101, 95, 117, 114, 108, 28, 114, 111, 116, 97, 116, 101, 95, 99, 111, 109, 112, 108,
    105, 97, 110, 99, 101, 95, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1, 7, 10, 0, 11, 1, 17, 0, 11, 0, 11, 2, 17, 1, 2,
];

const ROTATE_SHARED_ED25519_PUBLIC_KEY_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 2, 3, 2, 5, 5, 7, 6, 7, 13, 34, 8, 47, 16, 0, 0, 0, 1,
    0, 1, 0, 2, 6, 12, 10, 2, 0, 22, 83, 104, 97, 114, 101, 100, 69, 100, 50, 53, 53, 49, 57, 80,
    117, 98, 108, 105, 99, 75, 101, 121, 10, 114, 111, 116, 97, 116, 101, 95, 107, 101, 121, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 4, 11, 0, 11, 1, 17, 0, 2,
];

const SET_VALIDATOR_CONFIG_AND_RECONFIGURE_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 4, 3, 4, 10, 5, 14, 15, 7, 29, 68, 8, 97, 16, 0, 0, 0,
    1, 1, 2, 0, 1, 0, 0, 3, 2, 1, 0, 5, 6, 12, 5, 10, 2, 10, 2, 10, 2, 0, 2, 6, 12, 5, 10, 68, 105,
    101, 109, 83, 121, 115, 116, 101, 109, 15, 86, 97, 108, 105, 100, 97, 116, 111, 114, 67, 111,
    110, 102, 105, 103, 10, 115, 101, 116, 95, 99, 111, 110, 102, 105, 103, 29, 117, 112, 100, 97,
    116, 101, 95, 99, 111, 110, 102, 105, 103, 95, 97, 110, 100, 95, 114, 101, 99, 111, 110, 102,
    105, 103, 117, 114, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 10, 10, 0,
    10, 1, 11, 2, 11, 3, 11, 4, 17, 0, 11, 0, 10, 1, 17, 1, 2,
];

const SET_VALIDATOR_OPERATOR_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 4, 3, 4, 10, 5, 14, 19, 7, 33, 68, 8, 101, 16, 0, 0, 0,
    1, 1, 2, 0, 1, 0, 0, 3, 2, 3, 0, 1, 5, 1, 10, 2, 2, 6, 12, 5, 0, 3, 6, 12, 10, 2, 5, 2, 1, 3,
    15, 86, 97, 108, 105, 100, 97, 116, 111, 114, 67, 111, 110, 102, 105, 103, 23, 86, 97, 108,
    105, 100, 97, 116, 111, 114, 79, 112, 101, 114, 97, 116, 111, 114, 67, 111, 110, 102, 105, 103,
    14, 103, 101, 116, 95, 104, 117, 109, 97, 110, 95, 110, 97, 109, 101, 12, 115, 101, 116, 95,
    111, 112, 101, 114, 97, 116, 111, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 5,
    15, 10, 2, 17, 0, 11, 1, 33, 12, 3, 11, 3, 3, 11, 11, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 39, 11,
    0, 10, 2, 17, 1, 2,
];

const SET_VALIDATOR_OPERATOR_WITH_NONCE_ADMIN_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 6, 3, 6, 15, 5, 21, 26, 7, 47, 103, 8, 150, 1, 16, 0, 0,
    0, 1, 0, 2, 0, 3, 0, 1, 0, 2, 4, 2, 3, 0, 1, 5, 4, 1, 0, 2, 6, 12, 3, 0, 1, 5, 1, 10, 2, 2, 6,
    12, 5, 5, 6, 12, 6, 12, 3, 10, 2, 5, 2, 1, 3, 12, 83, 108, 105, 100, 105, 110, 103, 78, 111,
    110, 99, 101, 15, 86, 97, 108, 105, 100, 97, 116, 111, 114, 67, 111, 110, 102, 105, 103, 23,
    86, 97, 108, 105, 100, 97, 116, 111, 114, 79, 112, 101, 114, 97, 116, 111, 114, 67, 111, 110,
    102, 105, 103, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95,
    97, 98, 111, 114, 116, 14, 103, 101, 116, 95, 104, 117, 109, 97, 110, 95, 110, 97, 109, 101,
    12, 115, 101, 116, 95, 111, 112, 101, 114, 97, 116, 111, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 1, 0, 5, 6, 18, 11, 0, 10, 2, 17, 0, 10, 4, 17, 1, 11, 3, 33, 12, 5, 11, 5, 3, 14,
    11, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 39, 11, 1, 10, 4, 17, 2, 2,
];

const TIERED_MINT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 4, 3, 4, 11, 4, 15, 2, 5, 17, 21, 7, 38, 59, 8, 97, 16,
    0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 3, 2, 1, 1, 1, 1, 4, 2, 6, 12, 3, 0, 4, 6, 12, 5, 3, 3, 5, 6, 12,
    3, 5, 3, 3, 1, 9, 0, 11, 68, 105, 101, 109, 65, 99, 99, 111, 117, 110, 116, 12, 83, 108, 105,
    100, 105, 110, 103, 78, 111, 110, 99, 101, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110,
    99, 101, 95, 111, 114, 95, 97, 98, 111, 114, 116, 11, 116, 105, 101, 114, 101, 100, 95, 109,
    105, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 1, 9, 10, 0, 10, 1, 17,
    0, 11, 0, 10, 2, 10, 3, 10, 4, 56, 0, 2,
];

const UNFREEZE_ACCOUNT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 4, 3, 4, 10, 5, 14, 14, 7, 28, 68, 8, 96, 16, 0, 0, 0,
    1, 0, 2, 0, 1, 0, 1, 3, 2, 1, 0, 2, 6, 12, 5, 0, 2, 6, 12, 3, 3, 6, 12, 3, 5, 15, 65, 99, 99,
    111, 117, 110, 116, 70, 114, 101, 101, 122, 105, 110, 103, 12, 83, 108, 105, 100, 105, 110,
    103, 78, 111, 110, 99, 101, 16, 117, 110, 102, 114, 101, 101, 122, 101, 95, 97, 99, 99, 111,
    117, 110, 116, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95,
    97, 98, 111, 114, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 1, 7, 10, 0, 10,
    1, 17, 1, 11, 0, 10, 2, 17, 0, 2,
];

const UPDATE_DIEM_VERSION_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 4, 3, 4, 10, 5, 14, 10, 7, 24, 51, 8, 75, 16, 0, 0, 0,
    1, 0, 2, 0, 1, 0, 1, 3, 0, 1, 0, 2, 6, 12, 3, 0, 3, 6, 12, 3, 3, 11, 68, 105, 101, 109, 86,
    101, 114, 115, 105, 111, 110, 12, 83, 108, 105, 100, 105, 110, 103, 78, 111, 110, 99, 101, 3,
    115, 101, 116, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95,
    97, 98, 111, 114, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1, 7, 10, 0, 10,
    1, 17, 1, 11, 0, 10, 2, 17, 0, 2,
];

const UPDATE_DUAL_ATTESTATION_LIMIT_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 5, 1, 0, 4, 3, 4, 10, 5, 14, 10, 7, 24, 71, 8, 95, 16, 0, 0, 0,
    1, 0, 2, 0, 1, 0, 1, 3, 0, 1, 0, 2, 6, 12, 3, 0, 3, 6, 12, 3, 3, 15, 68, 117, 97, 108, 65, 116,
    116, 101, 115, 116, 97, 116, 105, 111, 110, 12, 83, 108, 105, 100, 105, 110, 103, 78, 111, 110,
    99, 101, 19, 115, 101, 116, 95, 109, 105, 99, 114, 111, 100, 105, 101, 109, 95, 108, 105, 109,
    105, 116, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110, 99, 101, 95, 111, 114, 95, 97,
    98, 111, 114, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1, 7, 10, 0, 10, 1,
    17, 1, 11, 0, 10, 2, 17, 0, 2,
];

const UPDATE_EXCHANGE_RATE_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 7, 1, 0, 6, 2, 6, 4, 3, 10, 16, 4, 26, 2, 5, 28, 25, 7, 53, 99,
    8, 152, 1, 16, 0, 0, 0, 1, 0, 2, 1, 1, 2, 0, 1, 3, 0, 1, 0, 2, 4, 2, 3, 0, 0, 5, 4, 3, 1, 1, 2,
    6, 2, 3, 3, 1, 8, 0, 2, 6, 12, 3, 0, 2, 6, 12, 8, 0, 4, 6, 12, 3, 3, 3, 1, 9, 0, 4, 68, 105,
    101, 109, 12, 70, 105, 120, 101, 100, 80, 111, 105, 110, 116, 51, 50, 12, 83, 108, 105, 100,
    105, 110, 103, 78, 111, 110, 99, 101, 20, 99, 114, 101, 97, 116, 101, 95, 102, 114, 111, 109,
    95, 114, 97, 116, 105, 111, 110, 97, 108, 21, 114, 101, 99, 111, 114, 100, 95, 110, 111, 110,
    99, 101, 95, 111, 114, 95, 97, 98, 111, 114, 116, 24, 117, 112, 100, 97, 116, 101, 95, 120,
    100, 120, 95, 101, 120, 99, 104, 97, 110, 103, 101, 95, 114, 97, 116, 101, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 5, 1, 11, 10, 0, 10, 1, 17, 1, 10, 2, 10, 3, 17, 0, 12, 4, 11,
    0, 11, 4, 56, 0, 2,
];

const UPDATE_MINTING_ABILITY_CODE: &[u8] = &[
    161, 28, 235, 11, 1, 0, 0, 0, 6, 1, 0, 2, 3, 2, 6, 4, 8, 2, 5, 10, 8, 7, 18, 28, 8, 46, 16, 0,
    0, 0, 1, 0, 1, 1, 1, 0, 2, 2, 6, 12, 1, 0, 1, 9, 0, 4, 68, 105, 101, 109, 22, 117, 112, 100,
    97, 116, 101, 95, 109, 105, 110, 116, 105, 110, 103, 95, 97, 98, 105, 108, 105, 116, 121, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 4, 11, 0, 10, 1, 56, 0, 2,
];
