/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

syntax = "proto3";

option go_package = "github.com/hyperledger/fabric/protos/token";
option java_package = "org.hyperledger.fabric.protos.token";

package protos;

import "google/protobuf/timestamp.proto";
import "token/expectations.proto";
import "token/transaction.proto";

// TokenToIssue describes a token to be issued in the system
message TokenToIssue {
    // Recipient refers to the owner of the token to be issued
    bytes recipient = 1;

    // Type refers to the token type
    string type = 2;

    // Quantity refers to the number of token units to be issued
    uint64 quantity = 3;
}

// RecipientTransferShare describes how much a recipient will receive in a token transfer
message RecipientTransferShare {
    // Recipient refers to the prospective owner of a transferred token
    bytes recipient = 1;

    // Quantity refers to the number of token units to be transferred to the recipient
    uint64 quantity = 2;
}

// TokenOutput is used to specify a token returned by ListRequest
message TokenOutput {
    // ID is used to uniquely identify the token
    bytes id = 1;

    // Type is the type of the token
    string type = 2;

    // Quantity represents the number for this type of token
    uint64 quantity = 3;
}

// UnspentTokens is used to hold the output of listRequest
message UnspentTokens {
    repeated TokenOutput tokens = 1;
}

// ListRequest is used to request a list of unspent tokens
message ListRequest {
    bytes credential = 1;
}

// ImportRequest is used to request creation of imports
message ImportRequest {
    // Credential contains information about the party who is requesting the operation
    // the content of this field depends on the charateristic of the token manager system used.
    bytes credential = 1;

    // TokenToIssue contains the information about the tokens to be issued
    repeated TokenToIssue tokens_to_issue = 2;
}

// RequestTransfer is used to request creation of transfers
message TransferRequest {
    bytes credential = 1;

    repeated bytes token_ids = 2;

    repeated RecipientTransferShare shares = 3;
}

// RedeemRequest is used to request token redemption
message RedeemRequest {
    // Credential contains information for the party who is requesting the operation
    // The content of this field depends on the characteristic of token manager system
    bytes credential = 1;

    // token_ids specifies the ids for the tokens that will be redeemed
    repeated bytes token_ids = 2;

    // quantity refers to the number of units of a given token needs to be redeemed.
    uint64 quantity_to_redeem = 3;
}

// ALlowance defines how many and what tokens a recipient can transfer on behalf of their actual owner
message AllowanceRecipientShare {
    // Recipient refers to the entity allowed to spend the specified quantity from the tokens identified by token IDs
    bytes recipient = 1;

    // Quantity is how many tokens are delegated to the recipient
    uint64 quantity = 2;
}

// ApproveRequest is used to request the creation of allowance from one owner to another
message ApproveRequest{
    // Credential refers to the public credential of the request creator
    bytes credential = 1;

    // Allowance describes the tokens the creator of the request is willing to delegate
    repeated AllowanceRecipientShare allowance_shares = 2;

    // TokenIds are the token identifiers used to create the allowance
    repeated bytes token_ids = 3;
}

// ExpectationRequest is used to request indirect token import or transfer based on the token expectation
message ExpectationRequest {
    // credential contains information for the party who is requesting the operation
    // The content of this field depends on the characteristic of token manager system
    bytes credential = 1;

    // expectation contains the expected outputs for token import or transfer
    TokenExpectation expectation = 2;

    // TokenIds are the token identifiers used to fulfill the expectation
    repeated bytes token_ids = 3;
}

// Header is a generic replay prevention and identity message to include in a signed command
message Header {
    // Timestamp is the local time when the message was created
    // by the sender
    google.protobuf.Timestamp timestamp = 1;

    // ChannelId identifies the channel this message is bound for
    string channel_id = 2;

    // Nonce is a sufficientley long random value
    // used to ensure the request has enough entropy.
    bytes nonce = 3;

    // Creator of the message.
    // Typically, a marshaled msp.SerializedIdentity
    bytes creator = 4;
}


// Command describes the type of operation that a client is requesting.
message Command {
    // Header is the header of this command
    Header header = 1;

    // Payload is the payload of this command. It can assume one of the following value
    oneof payload {
        ImportRequest import_request = 2;
        TransferRequest transfer_request = 3;
        ListRequest list_request = 4;
        RedeemRequest redeem_request = 5;
        ApproveRequest approve_request = 6;
        TransferRequest transfer_from_request = 7;
        ExpectationRequest expectation_request = 8;
    }
}

// SignedCommand is a command that carries the signature of the command's creator.
message SignedCommand {
    // Command is the serialised version of a Command message
    bytes command = 1;

    // Signature is the signature over command
    bytes signature = 2;
}

message CommandResponseHeader {
    // Timestamp is the time that the message
    // was created as  defined by the sender
    google.protobuf.Timestamp timestamp = 1;

    // CommandHash is the hash computed on the concatenation of the SignedCommand's command and signature fields.
    // If not specified differently, SHA256 is used
    // The hash is used to link a response with its request, both for bookeeping purposes on an
    // asynchronous system and for security reasons (accountability, non-repudiation)
    bytes command_hash = 2;

    // Creator is the identity of the party creating this message
    bytes creator = 3;
}

// Error reports an application error
message Error {
    // Message associated with this response.
    string message = 1;

    // Payload that can be used to include metadata with this response.
    bytes payload = 2;
}

// A CommnandResponse is returned from a prover to the command submitter.
message CommandResponse {
    // Header of the response.
    CommandResponseHeader header = 1;

    // Payload of the response.
    oneof payload {
        Error err = 2;
        TokenTransaction token_transaction = 3;
        UnspentTokens unspent_tokens = 4;
    }
}

// SignedCommandResponse is a signed command response
message SignedCommandResponse {
    // Response is the serialised version of a CommandResponse message
    bytes response = 1;

    // Signature is the signature over command
    bytes signature = 2;
}

// Prover provides support to clients for the creation of FabToken transactions,
// and to query the ledger.
service Prover {
    // ProcessCommand processes the passed command ensuring proper access control.
    // The returned response allows the client to understand if the
    // operation was succeffully executed and if not, the response
    // reports the reason of the failure.
    rpc ProcessCommand(SignedCommand) returns (SignedCommandResponse) {}
}
