{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Operation",
  "description": "One of various types of actions that be put in a multi-operation transaction\nPayload structs are different from the top-level [ClaimType] where we\nneed to support multiple operations with different receivers",
  "oneOf": [
    {
      "description": "Transfer or burn tokens (that is, transfer tokens to the burn address)",
      "type": "object",
      "properties": {
        "TokenTransfer": {
          "$ref": "#/$defs/TokenTransferOperation"
        }
      },
      "required": [
        "TokenTransfer"
      ],
      "additionalProperties": false
    },
    {
      "description": "Create custom token",
      "type": "object",
      "properties": {
        "TokenCreation": {
          "$ref": "#/$defs/TokenCreation"
        }
      },
      "required": [
        "TokenCreation"
      ],
      "additionalProperties": false
    },
    {
      "description": "Modify custom token",
      "type": "object",
      "properties": {
        "TokenManagement": {
          "$ref": "#/$defs/TokenManagement"
        }
      },
      "required": [
        "TokenManagement"
      ],
      "additionalProperties": false
    },
    {
      "description": "Mint funds in a custom token",
      "type": "object",
      "properties": {
        "Mint": {
          "$ref": "#/$defs/MintOperation"
        }
      },
      "required": [
        "Mint"
      ],
      "additionalProperties": false
    },
    {
      "description": "Initialize the state of an Ethereum blockchain mirroring account",
      "type": "object",
      "properties": {
        "StateInitialization": {
          "$ref": "#/$defs/StateInitialization"
        }
      },
      "required": [
        "StateInitialization"
      ],
      "additionalProperties": false
    },
    {
      "description": "Update the state of an Ethereum blockchain mirroring account",
      "type": "object",
      "properties": {
        "StateUpdate": {
          "$ref": "#/$defs/StateUpdate"
        }
      },
      "required": [
        "StateUpdate"
      ],
      "additionalProperties": false
    },
    {
      "description": "Submit arbitrary data to be settled on the network",
      "type": "object",
      "properties": {
        "ExternalClaim": {
          "$ref": "#/$defs/ExternalClaim"
        }
      },
      "required": [
        "ExternalClaim"
      ],
      "additionalProperties": false
    },
    {
      "description": "Reset the state of an Ethereum blockchain mirroring account",
      "type": "object",
      "properties": {
        "StateReset": {
          "$ref": "#/$defs/StateReset"
        }
      },
      "required": [
        "StateReset"
      ],
      "additionalProperties": false
    }
  ],
  "$defs": {
    "TokenTransferOperation": {
      "description": "Transfer tokens to another address.\nThis is a variant of [TokenTransfer] that adds a recipient field.",
      "type": "object",
      "properties": {
        "token_id": {
          "description": "Token ID to transfer",
          "type": "array",
          "items": {
            "type": "integer",
            "format": "uint8",
            "minimum": 0,
            "maximum": 255
          },
          "minItems": 32,
          "maxItems": 32
        },
        "recipient": {
          "description": "Recipient",
          "$ref": "#/$defs/PublicKeyBytes"
        },
        "amount": {
          "description": "Amount to transfer",
          "$ref": "#/$defs/Amount"
        },
        "user_data": {
          "description": "Extra data field to associate with this transfer",
          "$ref": "#/$defs/UserData"
        }
      },
      "required": [
        "token_id",
        "recipient",
        "amount",
        "user_data"
      ]
    },
    "PublicKeyBytes": {
      "description": "A byte sequence that names an entity on or off the FastSet network,\ndepending on the name of type which stores this value;\ntypically encoded as an Ed25519 public key,\nbut may have other formats including but not limited to:\n(a) Burn Address - a 32-byte string composed of all 0x00 bytes.\nNote: any funds sent to the burn address will be permenantly lost!",
      "type": "array",
      "items": {
        "type": "integer",
        "format": "uint8",
        "minimum": 0,
        "maximum": 255
      },
      "minItems": 32,
      "maxItems": 32
    },
    "Amount": {
      "description": "256-bit unsigned integer encoded as a hex string",
      "type": "string"
    },
    "UserData": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "type": "integer",
        "format": "uint8",
        "minimum": 0,
        "maximum": 255
      },
      "minItems": 32,
      "maxItems": 32
    },
    "TokenCreation": {
      "description": "Create a new token.\nThe token id is derived from the [Transaction]\nso it depends also on the creator and the [Nonce].",
      "type": "object",
      "properties": {
        "token_name": {
          "description": "Human-readable name",
          "type": "string"
        },
        "decimals": {
          "description": "Power of 10 that should be considered a full unit of this token.\nAn [Amount] is still always in least units.",
          "type": "integer",
          "format": "uint8",
          "minimum": 0,
          "maximum": 255
        },
        "initial_amount": {
          "description": "Initial balance, which will be held by the creator of the token.",
          "$ref": "#/$defs/Amount"
        },
        "mints": {
          "description": "Addresses which will be able to create more of this token",
          "type": "array",
          "items": {
            "$ref": "#/$defs/PublicKeyBytes"
          }
        },
        "user_data": {
          "description": "Arbitrary userdata attached to this transaction",
          "$ref": "#/$defs/UserData"
        }
      },
      "required": [
        "token_name",
        "decimals",
        "initial_amount",
        "mints",
        "user_data"
      ]
    },
    "TokenManagement": {
      "description": "Manage an existing token.",
      "type": "object",
      "properties": {
        "token_id": {
          "description": "The id of the token to be managed",
          "type": "array",
          "items": {
            "type": "integer",
            "format": "uint8",
            "minimum": 0,
            "maximum": 255
          },
          "minItems": 32,
          "maxItems": 32
        },
        "update_id": {
          "description": "The update id for this token (used for sequencing)\nEach update id must be one greater than the last",
          "$ref": "#/$defs/Nonce"
        },
        "new_admin": {
          "description": "The new admin address; preserve existing admin if None",
          "anyOf": [
            {
              "$ref": "#/$defs/PublicKeyBytes"
            },
            {
              "type": "null"
            }
          ]
        },
        "mints": {
          "description": "The minter addresses to be added/removed",
          "type": "array",
          "items": {
            "type": "array",
            "prefixItems": [
              {
                "$ref": "#/$defs/AddressChange"
              },
              {
                "$ref": "#/$defs/PublicKeyBytes"
              }
            ],
            "minItems": 2,
            "maxItems": 2
          }
        },
        "user_data": {
          "description": "Arbitrary userdata attached to this transaction",
          "$ref": "#/$defs/UserData"
        }
      },
      "required": [
        "token_id",
        "update_id",
        "mints",
        "user_data"
      ]
    },
    "Nonce": {
      "type": "integer",
      "format": "uint64",
      "minimum": 0
    },
    "AddressChange": {
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "Add": {
              "type": "array",
              "maxItems": 0
            }
          },
          "required": [
            "Add"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "Remove": {
              "type": "array",
              "maxItems": 0
            }
          },
          "required": [
            "Remove"
          ],
          "additionalProperties": false
        }
      ]
    },
    "MintOperation": {
      "description": "Create more funds of a token.\nThe sender of the [Transaction] must be a current mint of the token.\nWarning: This is not independent of a token management operation that\nremoves the sender of this transaction from the list of mints.\nThis is a variant of [Mint] that adds a recipient field.",
      "type": "object",
      "properties": {
        "token_id": {
          "description": "Token ID. This is the hash of the TokenCreation transaction that created the token.\nThis is calculated using the keccak256 hash over the data encoded in the same way as\nfor signing.",
          "type": "array",
          "items": {
            "type": "integer",
            "format": "uint8",
            "minimum": 0,
            "maximum": 255
          },
          "minItems": 32,
          "maxItems": 32
        },
        "recipient": {
          "description": "Recipient of the new funds",
          "$ref": "#/$defs/PublicKeyBytes"
        },
        "amount": {
          "description": "Amount to mint",
          "$ref": "#/$defs/Amount"
        }
      },
      "required": [
        "token_id",
        "recipient",
        "amount"
      ]
    },
    "StateInitialization": {
      "description": "Initialize one state cell of a blockchain mirroring account",
      "type": "object",
      "properties": {
        "key": {
          "description": "Key to initialize",
          "$ref": "#/$defs/StateKey"
        },
        "initial_state": {
          "description": "Initial state",
          "$ref": "#/$defs/State"
        }
      },
      "required": [
        "key",
        "initial_state"
      ]
    },
    "StateKey": {
      "type": "array",
      "items": {
        "type": "integer",
        "format": "uint8",
        "minimum": 0,
        "maximum": 255
      },
      "minItems": 32,
      "maxItems": 32
    },
    "State": {
      "type": "array",
      "items": {
        "type": "integer",
        "format": "uint8",
        "minimum": 0,
        "maximum": 255
      },
      "minItems": 32,
      "maxItems": 32
    },
    "StateUpdate": {
      "description": "Update the state of a blockchain mirroring account",
      "type": "object",
      "properties": {
        "key": {
          "description": "Key to update",
          "$ref": "#/$defs/StateKey"
        },
        "previous_state": {
          "description": "Previous state",
          "$ref": "#/$defs/State"
        },
        "next_state": {
          "description": "Next state",
          "$ref": "#/$defs/State"
        },
        "compute_claim_tx_hash": {
          "type": "array",
          "items": {
            "type": "integer",
            "format": "uint8",
            "minimum": 0,
            "maximum": 255
          },
          "minItems": 32,
          "maxItems": 32
        },
        "compute_claim_tx_timestamp": {
          "type": "integer",
          "format": "uint128",
          "minimum": 0
        }
      },
      "required": [
        "key",
        "previous_state",
        "next_state",
        "compute_claim_tx_hash",
        "compute_claim_tx_timestamp"
      ]
    },
    "ExternalClaim": {
      "description": "Submit arbitrary data along with a quorum of signatures from external verifiers",
      "type": "object",
      "properties": {
        "claim": {
          "description": "The claim itself plus the required verifier quorum",
          "$ref": "#/$defs/ExternalClaimBody"
        },
        "signatures": {
          "description": "At least `claim.verifier_quorum` signatures over the enclosing `Transaction` (with this field set to the empty list) by members of `claim.verifier_committee`",
          "type": "array",
          "items": {
            "$ref": "#/$defs/VerifierSig"
          }
        }
      },
      "required": [
        "claim",
        "signatures"
      ]
    },
    "ExternalClaimBody": {
      "type": "object",
      "properties": {
        "verifier_committee": {
          "description": "Set of verifiers (regular  FastSet addresses) that can sign for this ExternalClaim",
          "type": "array",
          "items": {
            "$ref": "#/$defs/PublicKeyBytes"
          }
        },
        "verifier_quorum": {
          "description": "Minimum number of verifiers in `verifier_committee` for which fastset validators will sign\nthis transaction",
          "$ref": "#/$defs/Quorum"
        },
        "claim_data": {
          "description": "Arbitrary data that the verifiers are signing.",
          "$ref": "#/$defs/ClaimData"
        }
      },
      "required": [
        "verifier_committee",
        "verifier_quorum",
        "claim_data"
      ]
    },
    "Quorum": {
      "type": "integer",
      "format": "uint64",
      "minimum": 0
    },
    "ClaimData": {
      "type": "array",
      "items": {
        "type": "integer",
        "format": "uint8",
        "minimum": 0,
        "maximum": 255
      }
    },
    "VerifierSig": {
      "type": "object",
      "properties": {
        "verifier_addr": {
          "$ref": "#/$defs/PublicKeyBytes"
        },
        "sig": {
          "$ref": "#/$defs/Signature"
        }
      },
      "required": [
        "verifier_addr",
        "sig"
      ]
    },
    "Signature": {
      "description": "An Ed25519 signature",
      "type": "array",
      "items": {
        "type": "integer",
        "format": "uint8"
      },
      "minItems": 64,
      "maxItems": 64
    },
    "StateReset": {
      "description": "Reset the state of a blockchain mirroring account\nThis claim type is a temporary work-around that allows a left behind account to\nbe easily caught up with the target blockchain's tip. In the future this claim type\nwill be dropped and a left-behind mirroring account will need to settle all\nmissed state updates in order to be caught up.",
      "type": "object",
      "properties": {
        "key": {
          "description": "Key to reset",
          "$ref": "#/$defs/StateKey"
        },
        "reset_state": {
          "description": "Reset state",
          "$ref": "#/$defs/State"
        }
      },
      "required": [
        "key",
        "reset_state"
      ]
    }
  }
}