syntax = "proto3";
package forge_abi;

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

// Used on deploy_protocol
message CodeInfo {
  // checksum of the module
  bytes checksum = 1;
  // gzipped binary
  bytes binary = 2;
}

message TypeUrls {
  string url = 1;
  string module = 2;
}

message DeployProtocolTx {
  // address of the tx protocol
  string address = 1;
  // human readable name of the transaction, shall only contains alphabat and
  // underscore. For CoreTx, it shall be compatible with existing definition in
  // type_url.ex..
  string name = 2;
  // version of the tx protocol. If version is 0, this is a genesis
  // installation.
  uint32 version = 3;
  // namespace of the tx protocol. If namespace is CoreTx, it will use
  // "fg:t:#{name}" as type_url, this is for backward compatibility.
  string namespace = 4;
  // human readable description on what the tx is about, limited to 256 chars.
  string description = 5;
  // new type urls used by this tx protocol. Will be registered in ForgeAbi
  repeated TypeUrls type_urls = 6;
  // the protobuf definition for the tx protocol.
  string proto = 7;
  // the pipeline of the tx protocol, in yaml format.
  string pipeline = 8;
  // the source code for the tx protocol, in elixir.
  repeated string sources = 9;
  // the compressed code of the protocol
  repeated CodeInfo code = 10;
  // categories or tags this protocol belongs to
  repeated string tags = 11;

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

// account
message AccountMigrateTx {
  bytes pk = 1;                              // new public key
  WalletType type = 2 [ deprecated = true ]; // new wallet type
  string address = 3;                        // new wallet address

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

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 DelegateTx {
  string address = 1; // address of the delegation between sender and receiver
  string to = 2;      // delegatee's address
  repeated DelegateOp ops = 3; // a list of operations permitted

  google.protobuf.Any data = 15;
}

// if rules are empty, signature for this type_url is entirely delegated
// otherwise rules are checked one by one, relationship between rules is AND.
// a rule is an expression defined in rule_parser
// (github.com/arcblock/rule-parser) one can setup
message DelegateOp {
  string type_url = 1;
  repeated string rules = 2;
}

message RevokeDelegateTx {
  string address = 1; // address of the delegation between sender and receiver
  string to = 2;      // delegatee's address
  repeated string type_urls = 3;

  google.protobuf.Any data = 15;
}

// asset
message AssetSpec {
  // the address of the generated asset. The sender shall apply the spec to the
  // template to generate a structure of the asset, and then generate the
  // CreateAssetTx, and then calculate the address. SDK could help to alleviate
  // the process.
  string address = 1;
  // json string that contains args for the asset factory template
  string data = 2;
}

message AcquireAssetTx {
  // the address of the asset factory
  string to = 1;
  // asset spec
  repeated AssetSpec specs = 2;

  // 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 asset, 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;
  // asset address
  string address = 7;
}

message AssetAttributes {
  bool transferrable = 1;
  uint32 ttl = 2;
}

message AssetFactory {
  // description of the asset factory
  string description = 1;
  // total assets it can create
  uint32 limit = 2;
  // the price for the asset, in unit
  BigUint price = 3;
  // the template that asset factory will use to generate the asset, template is
  // string that could be processed by EEx with the given args, and its output
  // is json. Then the json will be parsed and converted against the asset_name.
  // e.g. If your asset name is `Ticket`,e.g. the the generated json data will
  // be converted with `ForgeAbi.Ticket.new(json)`.
  string template = 4;
  // allowed args for the template. In transfer tx, user can transfer tokens to
  // this AssetFactory address with a json string containing necessary args,
  // once the json is parsed, it will be checked against this, if any
  // field not in the list, the transfer tx will fail.
  repeated string allowed_spec_args = 5;
  // the protobuf message name for the asset. Note that this shall be registered
  // to forge.
  string asset_name = 6;

  // asset attributes will be copied to generated asset. Note assets generated
  // from asset factory is read only.
  AssetAttributes attributes = 7;

  // extra content that user can inject into the factory
  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;
}

// governance
message UpdateConsensusParamsTx {
  // new delegate config
  DelegateConfig delegate_config = 1;
  // new declare config
  DeclareConfig declare_config = 2;
  // new token swap config
  TokenSwapConfig token_swap_config = 3;
  // new moderator address
  AccountConfig moderator_config = 4;
}

message UpdateValidatorTx {
  repeated forge_abi.Validator candidates = 1;

  google.protobuf.Any data = 15;
}

message UpgradeNodeTx {
  // the height node will be stopped at.
  uint64 height = 1;
  // the version next release is expected
  string version = 2;
  // override the existing upgrade settings if there's already one. Use it with
  // cautious.
  bool override = 3;
}

// misc
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;
}

message RefuelTx {
  string date = 1;

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

// atomic swap
message RetrieveSwapTx {
  // The address of the swap state.
  string address = 1;
  // The origin value of the random number.
  bytes hashkey = 2;

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

message RevokeSwapTx {
  // The address of the swap state.
  string address = 1;

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

message SetupSwapTx {
  // The amount of token to swap.
  BigUint value = 1;
  // The addresses of assets to swap.
  repeated string assets = 2;
  // The address of the receiver who is the only one allowed to get the token
  // and assets locktime.
  string receiver = 3;
  // The sha3 value of the random number.
  bytes hashlock = 4;
  // The height of the block before which the swap is locked.
  uint32 locktime = 5;

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

// token swap
message ApproveWithdrawTx {
  string withdraw_tx_hash = 1; // the hash of withdraw tx
  Evidence evidence = 2;       // the evidence of the original transaction that
                               // transferred the token back
}

message DepositTokenTx {
  BigUint value = 1;     // how many units to issue
  string address = 2;    // address of the controlled account on Forge
  Evidence evidence = 3; // the evidence of the original transaction
}

message RevokeWithdrawTx {
  string withdraw_tx_hash = 1; // the hash of withdraw tx
}

message WithdrawTokenTx {
  BigUint value = 1;     // how many units to revokes
  string to = 2;         // foreign address to withdraw token to.
  string chain_type = 3; // type of the chain currently only "eth"
  string chain_id = 4;   // chain id of the chain. Could be testnet or mainnet.
}

// trade

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;
}

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;
}
