syntax = "proto3";
package forge_abi;

import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";
import "type.proto";

// Transaction definition

message AccountMigrateTx {
  bytes pk = 1;        // new public key
  WalletType type = 2; // new wallet type

  // forge won't touch this field. Only forge app shall handle it.
  google.protobuf.Any data = 15;
}

message ConsensusUpgradeTx {
  repeated Validator validators = 1;
  uint64 max_bytes = 2;
  sint64 max_gas = 3;
  uint32 max_validators = 4;
  uint32 max_candidates = 5;

  // forge won't touch this field. Only forge app shall handle it.
  google.protobuf.Any data = 15;
}

message ConsumeAssetTx {
  // `issuer` could be the same as `from`, or different, depending on use case.
  // when this tx is being mutisigned by the asset holder, the wallet could
  // check if the issuer is the issuer of the ticket, otherwise wallet shall
  // refuse signing it. when it goes into the chain, at verify state stage, we
  // shall check `from` of this tx:
  //  a. the same as the issuer
  //  b. `from.issuer == issuer`
  // For example, a museum issued a ticket and Alice bought it. At the
  // door (doorman) of the meseum, Alice need to consume the asset, which she
  // scan a QR code with a prepolulated ConsumeAssetTx. Most of the time, this
  // prepopulated tx shall be signed by the account of the door (doorman) so
  // that we can trace where and how Alice consumed this asset, however we don't
  // want anyone to be able to create this tx to allure Alice to consume the
  // asset, thus the door (doorman) shall be an account that issued by the
  // museum. The chain will make sure only accounts that has this issuer would
  // be able to successfully sign this tx.
  string issuer = 1;
  // an asset might belong to another asset, for example a ticket belongs to a
  // specific concert or movie asset. If this is provided, besides issuer we
  // will verify if the parent address of the asset equals to this address.
  string address = 2;

  // forge won't update data into state if app is interested in this tx.
  google.protobuf.Any data = 15;
}

message CreateAssetTx {
  string moniker = 1;
  // forge won't update data into state if app is interested in this tx.
  google.protobuf.Any data = 2;
  bool readonly = 3;
  bool transferrable = 4;
  // ttl for the asset after first consumption. 0 means unlimited.
  uint32 ttl = 5;
  string parent = 6;
}

message DeclareTx {
  string moniker = 1;
  string issuer = 2;

  // forge won't update data into state if app is interested in this tx.
  google.protobuf.Any data = 15;
}

message DeclareFileTx { string hash = 1; }

message ExchangeInfo {
  BigUint value = 1;
  repeated string assets = 2;
}

// we could support these cases (and vise versa):
// 1. sender fungible token <-> receiver one or more assets
// 2. sender fungible token + asset <-> receiver one or more assets
// 3. sender one or more assets <-> receiver one or more assets
message ExchangeTx {
  string to = 1;
  ExchangeInfo sender = 2;
  ExchangeInfo receiver = 3;
  google.protobuf.Timestamp expired_at = 4;

  // forge won't touch this field. Only forge app shall handle it.
  google.protobuf.Any data = 15;
}

// type url: fg:x:stake_asset. Stake for Tx is the same as stake for asset.
message stakeForAsset {}

// type url: fg:x:stake_chain. So far we haven't figured out how this could be
// done.
message stakeForChain {}

// type url: fg:x:stake_node
message StakeForNode {}

// type url: fg:x:stake_user
message stakeForUser {}

// Here we will reuse DeclareTx to declare a node.
// DeclareTx could only be carried out by node admin. We will have an RPC
// to ask forge to use the private key of the node and declare its identity.
// Then an account state will be created for that node and later on people can
// stake to that account. The top N staked nodes will be validators in the
// chain.
// Once a node is declared, people can use StakeTx to stake its tokens to it
// minimun staked token is 1. stake could be very flexible, that one can stake
// for a node, a user, an asset, a chain or a tx hash (normally a vote tx)
message StakeTx {
  string to = 1;
  BigSint value = 2;
  string message = 3;

  // forge won't touch this field. Only forge app shall handle it.
  // forge app can extend the stake if the given data cannot meet its
  // requirement.
  google.protobuf.Any data = 15;
}

message SysUpgradeTx {
  UpgradeTask task = 1;
  uint64 grace_period = 2; // wait for how many blocks to take the operation

  // forge won't touch this field. Only forge app shall handle it.
  google.protobuf.Any data = 15;
}

message TransferTx {
  string to = 1;
  BigUint value = 2;
  repeated string assets = 3;

  // forge won't touch this field. Only forge app shall handle it.
  google.protobuf.Any data = 15;
}

message UpdateAssetTx {
  string address = 1;
  string moniker = 2;

  // forge won't update data into state if app is interested in this tx.
  google.protobuf.Any data = 15;
}

message PokeTx {
  // type url: fg:x:poke
  string date = 1;
  string address = 2;

  // forge won't touch this field. Only forge app shall handle it.
  google.protobuf.Any data = 15;
}
