diff --git a/templates/NftSaleContract/.template.config/template.json b/templates/NftSaleContract/.template.config/template.json new file mode 100644 index 0000000..2dea2b2 --- /dev/null +++ b/templates/NftSaleContract/.template.config/template.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "AElf", + "classifications": [ + "AElf/SmartContract" + ], + "identity": "AElf.Contract.NftSale.Template", + "name": "AElf Contract NftSale Template", + "shortName": "aelf-nft-sale", + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "NftSale", + "symbols": { + "NamespacePath": { + "type": "parameter", + "replaces": "AElf.Contracts.NftSale" + } + } +} \ No newline at end of file diff --git a/templates/NftSaleContract/src/ContractReferences.cs b/templates/NftSaleContract/src/ContractReferences.cs new file mode 100644 index 0000000..e037d81 --- /dev/null +++ b/templates/NftSaleContract/src/ContractReferences.cs @@ -0,0 +1,11 @@ +using AElf.Contracts.Consensus.AEDPoS; +using AElf.Contracts.MultiToken; + +namespace AElf.Contracts.NftSale +{ + public partial class NftSaleState + { + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal AEDPoSContractContainer.AEDPoSContractReferenceState ConsensusContract { get; set; } + } +} \ No newline at end of file diff --git a/templates/NftSaleContract/src/NftSale.cs b/templates/NftSaleContract/src/NftSale.cs new file mode 100644 index 0000000..1c12ed0 --- /dev/null +++ b/templates/NftSaleContract/src/NftSale.cs @@ -0,0 +1,159 @@ +using AElf.Contracts.MultiToken; +using AElf.Sdk.CSharp; +using AElf.Types; +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Contracts.NftSale +{ + // Contract class must inherit the base class generated from the proto file + public class NftSale : NftSaleContainer.NftSaleBase + { + // Initializes the contract + public override Empty Initialize(NftPrice input) + { + // Check if the contract is already initialized + Assert(State.Initialized.Value == false, "Already initialized."); + // Set the contract state + State.Initialized.Value = true; + // Set the owner address + State.Owner.Value = Context.Sender; + State.NftPrice.Value = input.Price; + + // Initialize the token contract + State.TokenContract.Value = Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + // The below code can be used to replace the above line. The below is a showcase of how you can reference to any contracts. + State.ConsensusContract.Value = Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); + + return new Empty(); + } + + // transfer nft + public override Empty Purchase(PurchaseInput input) + { + var price = State.NftPrice.Value; + // transfer token + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = Context.Sender, + To = Context.Self, + Symbol = price.Symbol, + Amount = price.Amount * input.Amount + }); + // transfer nft + State.TokenContract.Transfer.Send(new TransferInput + { + To = Context.Sender, + Symbol = input.Symbol, + Amount = input.Amount + }); + + Context.Fire(new SaleNft + { + To = Context.Self, + Symbol = input.Symbol, + Amount = input.Amount, + }); + + return new Empty(); + } + + // + public override Empty SetPriceAndSymbol(NftPrice input) + { + AssertIsOwner(); + State.NftPrice.Value = input.Price; + return new Empty(); + } + + public override Price GetPrice(Empty input) + { + return State.NftPrice.Value; + } + + + // Withdraws a specified amount of tokens from the contract. + // This method can only be called by the owner of the contract. + // After the tokens are transferred, a WithdrawEvent is fired to notify any listeners about the withdrawal. + public override Empty Withdraw(Int64Value input) + { + AssertIsOwner(); + + // Transfer the token from the contract to the sender + State.TokenContract.Transfer.Send(new TransferInput + { + To = Context.Sender, + Symbol = State.NftPrice.Value.Symbol, + Amount = input.Value + }); + + // Emit an event to notify listeners about the withdrawal + Context.Fire(new WithdrawEvent + { + Amount = input.Value, + From = Context.Self, + To = Context.Sender + }); + + return new Empty(); + } + + // Deposits a specified amount of tokens into the contract. + // This method can only be called by the owner of the contract. + // After the tokens are transferred, a DepositEvent is fired to notify any listeners about the deposit. + public override Empty Deposit(DepositeInput input) + { + AssertIsOwner(); + + // Transfer the token from the sender to the contract + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = Context.Sender, + To = Context.Self, + Symbol = input.Symbol, + Amount = input.Amount + }); + + // Emit an event to notify listeners about the deposit + Context.Fire(new DepositEvent + { + Amount = input.Amount, + From = Context.Sender, + To = Context.Self + }); + + return new Empty(); + } + + + // A method that read the contract's current balance + public override Int64Value GetContractBalance(GetContractBalanceInput input) + { + // Get the balance of the contract + var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Owner = input.Address, + Symbol = State.NftPrice.Value.Symbol + }).Balance; + + // Wrap the value in the return type + return new Int64Value + { + Value = balance + }; + } + + // This method is used to ensure that only the owner of the contract can perform certain actions. + // If the context sender is not the owner, an exception is thrown with the message "Unauthorized to perform the action." + private void AssertIsOwner() + { + Assert(Context.Sender == State.Owner.Value, "Unauthorized to perform the action."); + } + + // A method that read the contract's owner + public override StringValue GetOwner(Empty input) + { + return State.Owner.Value == null ? new StringValue() : new StringValue {Value = State.Owner.Value.ToBase58()}; + } + } + +} \ No newline at end of file diff --git a/templates/NftSaleContract/src/NftSale.csproj b/templates/NftSaleContract/src/NftSale.csproj new file mode 100644 index 0000000..072233a --- /dev/null +++ b/templates/NftSaleContract/src/NftSale.csproj @@ -0,0 +1,28 @@ + + + net6.0 + AElf.Contracts.NftSale + true + true + 1.0.0.0 + + + $(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/ + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + \ No newline at end of file diff --git a/templates/NftSaleContract/src/NftSaleState.cs b/templates/NftSaleContract/src/NftSaleState.cs new file mode 100644 index 0000000..ed77d7a --- /dev/null +++ b/templates/NftSaleContract/src/NftSaleState.cs @@ -0,0 +1,15 @@ +using AElf.Sdk.CSharp.State; +using AElf.Types; + +namespace AElf.Contracts.NftSale +{ + // The state class is access the blockchain state + public partial class NftSaleState : ContractState + { + // A state to check if contract is initialized + public BoolState Initialized { get; set; } + // A state to store the owner address + public SingletonState
Owner { get; set; } + public SingletonState NftPrice { get; set; } + } +} \ No newline at end of file diff --git a/templates/NftSaleContract/src/Protobuf/contract/nft_sale_contract.proto b/templates/NftSaleContract/src/Protobuf/contract/nft_sale_contract.proto new file mode 100644 index 0000000..373588e --- /dev/null +++ b/templates/NftSaleContract/src/Protobuf/contract/nft_sale_contract.proto @@ -0,0 +1,114 @@ +syntax = "proto3"; + +import "aelf/core.proto"; +import "aelf/options.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; +import "Protobuf/reference/acs12.proto"; +// The namespace of this class +option csharp_namespace = "AElf.Contracts.NftSale"; + +service NftSale { + // The name of the state class the smart contract is going to use to access blockchain state + option (aelf.csharp_state) = "AElf.Contracts.NftSale.NftSaleState"; + option (aelf.base) = "Protobuf/reference/acs12.proto"; + + rpc Initialize (NftPrice) returns (google.protobuf.Empty) { + } + + rpc Purchase (PurchaseInput) returns (google.protobuf.Empty) { + } + + rpc SetPriceAndSymbol (NftPrice) returns (google.protobuf.Empty) { + } + + rpc GetPrice (google.protobuf.Empty) returns (Price) { + option (aelf.is_view) = true; + } + + rpc GetSymbol (google.protobuf.Empty) returns (NftSymbol) { + option (aelf.is_view) = true; + } + + rpc Withdraw (google.protobuf.Int64Value) returns (google.protobuf.Empty) { + } + + rpc Deposit (DepositeInput) returns (google.protobuf.Empty) { + } + + rpc TransferOwnership (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc GetContractBalance (GetContractBalanceInput) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + rpc GetOwner (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } +} + +message DepositeInput{ + string symbol = 1; // nft + int64 amount = 2; // token amount +} + +message Price { + string symbol = 1; // token type + int64 amount = 2; // token price +} + +message NftSymbol { + string symbol = 1; +} + +message NftPrice{ + // // The token symbol price + Price price = 1; + // The token symbol + string symbol = 2; +} + +message PurchaseInput { + // The token symbol to transfer. + string symbol = 2; + // The amount to to transfer. + int64 amount = 3; + // The memo. + string memo = 4; + // Transaction information + Price price = 5; +} + +message SaleNft { + option (aelf.is_event) = true; + // The destination address of the transferred token. + aelf.Address to = 2 [(aelf.is_indexed) = true]; + // The symbol of the transferred token. + string symbol = 3 [(aelf.is_indexed) = true]; + // The amount of the transferred token. + int64 amount = 4; + // The memo. + string memo = 5; +} + +message GetContractBalanceInput{ + aelf.Address address = 1; +} + +// An event that will be emitted from contract method call when Withdraw is called. +message WithdrawEvent { + option (aelf.is_event) = true; + int64 amount = 1; + aelf.Address from = 2; + aelf.Address to = 3; +} + +// An event that will be emitted from contract method call when Deposit is called. +message DepositEvent { + option (aelf.is_event) = true; + int64 amount = 1; + string symbol = 2; + aelf.Address from = 3; + aelf.Address to = 4; +} diff --git a/templates/NftSaleContract/src/Protobuf/message/authority_info.proto b/templates/NftSaleContract/src/Protobuf/message/authority_info.proto new file mode 100644 index 0000000..eee3496 --- /dev/null +++ b/templates/NftSaleContract/src/Protobuf/message/authority_info.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +import "aelf/core.proto"; + +option csharp_namespace = "AElf.Contracts.NftSale"; + +message AuthorityInfo { + aelf.Address contract_address = 1; + aelf.Address owner_address = 2; +} \ No newline at end of file diff --git a/templates/NftSaleContract/src/Protobuf/reference/acs12.proto b/templates/NftSaleContract/src/Protobuf/reference/acs12.proto new file mode 100644 index 0000000..e6ead4b --- /dev/null +++ b/templates/NftSaleContract/src/Protobuf/reference/acs12.proto @@ -0,0 +1,35 @@ +/** + * AElf Standards ACS12(User Contract Standard) + * + * Used to manage user contract. + */ +syntax = "proto3"; + +package acs12; + +import public "aelf/options.proto"; +import public "google/protobuf/empty.proto"; +import public "google/protobuf/wrappers.proto"; +import "aelf/core.proto"; + +option (aelf.identity) = "acs12"; +option csharp_namespace = "AElf.Standards.ACS12"; + +service UserContract{ + +} + +//Specified method fee for user contract. +message UserContractMethodFees { + // List of fees to be charged. + repeated UserContractMethodFee fees = 2; + // Optional based on the implementation of SetConfiguration method. + bool is_size_fee_free = 3; +} + +message UserContractMethodFee { + // The token symbol of the method fee. + string symbol = 1; + // The amount of fees to be charged. + int64 basic_fee = 2; +} \ No newline at end of file diff --git a/templates/NftSaleContract/src/Protobuf/reference/aedpos_contract.proto b/templates/NftSaleContract/src/Protobuf/reference/aedpos_contract.proto new file mode 100644 index 0000000..37965d8 --- /dev/null +++ b/templates/NftSaleContract/src/Protobuf/reference/aedpos_contract.proto @@ -0,0 +1,507 @@ +/** + * AEDPoS contract. + */ +syntax = "proto3"; + +package AEDPoS; + +import "aelf/options.proto"; +import "aelf/core.proto"; +import "Protobuf/message/authority_info.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +option csharp_namespace = "AElf.Contracts.Consensus.AEDPoS"; + +service AEDPoSContract { + + option (aelf.csharp_state) = "AElf.Contracts.Consensus.AEDPoS.AEDPoSContractState"; + + // Initialize the consensus contract. + rpc InitialAElfConsensusContract (InitialAElfConsensusContractInput) returns (google.protobuf.Empty) { + } + + // Initializes the consensus information in the first round. + rpc FirstRound (Round) returns (google.protobuf.Empty) { + } + + // Update consensus information. + rpc UpdateValue (UpdateValueInput) returns (google.protobuf.Empty) { + } + + // Update consensus information, create a new round. + rpc NextRound (NextRoundInput) returns (google.protobuf.Empty) { + } + + // Update consensus information, create a new term. + rpc NextTerm (NextTermInput) returns (google.protobuf.Empty) { + } + + // Update consensus tiny block information. + rpc UpdateTinyBlockInformation (TinyBlockInput) returns (google.protobuf.Empty) { + } + + // Set the maximum count of miners, by default, is unlimited. + // If you want to control the count of miners, you need to set it through parliament. + rpc SetMaximumMinersCount (google.protobuf.Int32Value) returns (google.protobuf.Empty) { + } + + // The authority information for SetMaximumMinersCount, by default, is governed by parliament. + rpc ChangeMaximumMinersCountController (AuthorityInfo) returns (google.protobuf.Empty) { + } + + // Set miner increase interval + rpc SetMinerIncreaseInterval (google.protobuf.Int64Value) returns (google.protobuf.Empty){ + } + + // Election Contract can notify AEDPoS Contract to aware candidate replacement happened. + rpc RecordCandidateReplacement (RecordCandidateReplacementInput) returns (google.protobuf.Empty) { + } + + // Get the list of current miners. + rpc GetCurrentMinerList (google.protobuf.Empty) returns (MinerList) { + option (aelf.is_view) = true; + } + + // Get the list of current miners (hexadecimal format). + rpc GetCurrentMinerPubkeyList (google.protobuf.Empty) returns (PubkeyList) { + option (aelf.is_view) = true; + } + + // Get the list of current miners and current round number. + rpc GetCurrentMinerListWithRoundNumber (google.protobuf.Empty) returns (MinerListWithRoundNumber) { + option (aelf.is_view) = true; + } + + // Get information of the round according to round number. + rpc GetRoundInformation (google.protobuf.Int64Value) returns (Round) { + option (aelf.is_view) = true; + } + + // Get the current round number. + rpc GetCurrentRoundNumber (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get the current round information. + rpc GetCurrentRoundInformation (google.protobuf.Empty) returns (Round) { + option (aelf.is_view) = true; + } + + // Get the previous round information. + rpc GetPreviousRoundInformation (google.protobuf.Empty) returns (Round) { + option (aelf.is_view) = true; + } + + // Get the current term number. + rpc GetCurrentTermNumber (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get the welfare reward the current term. + rpc GetCurrentTermMiningReward (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get the list of miners according to term number. + rpc GetMinerList (GetMinerListInput) returns (MinerList) { + option (aelf.is_view) = true; + } + + // Get the list of miner in previous term. + rpc GetPreviousMinerList (google.protobuf.Empty) returns (MinerList) { + option (aelf.is_view) = true; + } + + // Get the amount of mined blocks in previous term. + rpc GetMinedBlocksOfPreviousTerm (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get the miner that produces the next block. + rpc GetNextMinerPubkey (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + // Check to see if the account address is on the miner list for the current round. + rpc IsCurrentMiner (aelf.Address) returns (google.protobuf.BoolValue) { + option (aelf.is_view) = true; + } + + // Query the left time before the next election takes effects (seconds). + rpc GetNextElectCountDown (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get term information according term number. + rpc GetPreviousTermInformation (google.protobuf.Int64Value) returns (Round) { + option (aelf.is_view) = true; + } + + // Get random hash (Keep this for compatibility). + rpc GetRandomHash (google.protobuf.Int64Value) returns (aelf.Hash) { + option (aelf.is_view) = true; + } + + // Get the maximum of tiny blocks produced by a miner each round. + rpc GetMaximumBlocksCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) { + option (aelf.is_view) = true; + } + + // Get the maximum count of miners. + rpc GetMaximumMinersCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) { + option (aelf.is_view) = true; + } + + // Get the authority information for SetMaximumMinersCount. + rpc GetMaximumMinersCountController (google.protobuf.Empty) returns (AuthorityInfo) { + option (aelf.is_view) = true; + } + + // Get miner increase interval + rpc GetMinerIncreaseInterval (google.protobuf.Empty) returns (google.protobuf.Int64Value){ + option (aelf.is_view) = true; + } + + // Gets the list of miners in the main chain. + rpc GetMainChainCurrentMinerList (google.protobuf.Empty) returns (MinerList) { + option (aelf.is_view) = true; + } + + // Get the list of miners in the previous term. + rpc GetPreviousTermMinerPubkeyList (google.protobuf.Empty) returns (PubkeyList) { + option (aelf.is_view) = true; + } + + // Query the current mining reward for each block. + rpc GetCurrentMiningRewardPerBlock (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } +} + +message InitialAElfConsensusContractInput { + // Whether not to change the term. + bool is_term_stay_one = 1; + // Is a side chain. + bool is_side_chain = 2; + // The number of seconds per term. + int64 period_seconds = 3; + // The interval second that increases the number of miners. + int64 miner_increase_interval = 4; +} + +message UpdateValueInput { + // Calculated from current in value. + aelf.Hash out_value = 1; + // Calculated from current in value and signatures of previous round. + aelf.Hash signature = 2; + // To ensure the values to update will be apply to correct round by comparing round id. + int64 round_id = 3; + // Publish previous in value for validation previous signature and previous out value. + aelf.Hash previous_in_value = 4; + // The actual mining time, miners must fill actual mining time when they do the mining. + google.protobuf.Timestamp actual_mining_time = 5; + // The supposed order of mining for the next round. + int32 supposed_order_of_next_round = 6; + // The tuning order of mining for the next round, miner public key -> order. + map tune_order_information = 7; + // The encrypted pieces of InValue. + map encrypted_pieces = 8; + // The decrypted pieces of InValue. + map decrypted_pieces = 9; + // The amount of produced blocks. + int64 produced_blocks = 10; + // The InValue in the previous round, miner public key -> InValue. + map miners_previous_in_values = 11; + // The irreversible block height that miner recorded. + int64 implied_irreversible_block_height = 12; + // The random number. + bytes random_number = 13; +} + +message MinerList { + // The miners public key list. + repeated bytes pubkeys = 1; +} + +message PubkeyList { + // The miners public key list. + repeated string pubkeys = 1; +} + +message TermNumberLookUp { + // Term number -> Round number. + map map = 1; +} + +message Candidates { + // The candidate public keys. + repeated bytes pubkeys = 1; +} + +message Round { + // The round number. + int64 round_number = 1; + // Current miner information, miner public key -> miner information. + map real_time_miners_information = 2; + // The round number on the main chain + int64 main_chain_miners_round_number = 3; + // The time from chain start to current round (seconds). + int64 blockchain_age = 4; + // The miner public key that produced the extra block in the previous round. + string extra_block_producer_of_previous_round = 5; + // The current term number. + int64 term_number = 6; + // The height of the confirmed irreversible block. + int64 confirmed_irreversible_block_height = 7; + // The round number of the confirmed irreversible block. + int64 confirmed_irreversible_block_round_number = 8; + // Is miner list different from the the miner list in the previous round. + bool is_miner_list_just_changed = 9; + // The round id, calculated by summing block producers’ expecting time (second). + int64 round_id_for_validation = 10; +} + +message MinerInRound { + // The order of the miner producing block. + int32 order = 1; + // Is extra block producer in the current round. + bool is_extra_block_producer = 2; + // Generated by secret sharing and used for validation between miner. + aelf.Hash in_value = 3; + // Calculated from current in value. + aelf.Hash out_value = 4; + // Calculated from current in value and signatures of previous round. + aelf.Hash signature = 5; + // The expected mining time. + google.protobuf.Timestamp expected_mining_time = 6; + // The amount of produced blocks. + int64 produced_blocks = 7; + // The amount of missed time slots. + int64 missed_time_slots = 8; + // The public key of this miner. + string pubkey = 9; + // The InValue of the previous round. + aelf.Hash previous_in_value = 10; + // The supposed order of mining for the next round. + int32 supposed_order_of_next_round = 11; + // The final order of mining for the next round. + int32 final_order_of_next_round = 12; + // The actual mining time, miners must fill actual mining time when they do the mining. + repeated google.protobuf.Timestamp actual_mining_times = 13; + // The encrypted pieces of InValue. + map encrypted_pieces = 14; + // The decrypted pieces of InValue. + map decrypted_pieces = 15; + // The amount of produced tiny blocks. + int64 produced_tiny_blocks = 16; + // The irreversible block height that current miner recorded. + int64 implied_irreversible_block_height = 17; +} + +message AElfConsensusHeaderInformation { + // The sender public key. + bytes sender_pubkey = 1; + // The round information. + Round round = 2; + // The behaviour of consensus. + AElfConsensusBehaviour behaviour = 3; +} + +message AElfConsensusHint { + // The behaviour of consensus. + AElfConsensusBehaviour behaviour = 1; + // The round id. + int64 round_id = 2; + // The previous round id. + int64 previous_round_id = 3; +} + +enum AElfConsensusBehaviour { + UPDATE_VALUE = 0; + NEXT_ROUND = 1; + NEXT_TERM = 2; + NOTHING = 3; + TINY_BLOCK = 4; +} + +message AElfConsensusTriggerInformation { + // The miner public key. + bytes pubkey = 1; + // The InValue for current round. + aelf.Hash in_value = 2; + // The InValue for previous round. + aelf.Hash previous_in_value = 3; + // The behaviour of consensus. + AElfConsensusBehaviour behaviour = 4; + // The encrypted pieces of InValue. + map encrypted_pieces = 5; + // The decrypted pieces of InValue. + map decrypted_pieces = 6; + // The revealed InValues. + map revealed_in_values = 7; + // The random number. + bytes random_number = 8; +} + +message TermInfo { + int64 term_number = 1; + int64 round_number = 2; +} + +message MinerListWithRoundNumber { + // The list of miners. + MinerList miner_list = 1; + // The round number. + int64 round_number = 2; +} + +message TinyBlockInput { + // The round id. + int64 round_id = 1; + // The actual mining time. + google.protobuf.Timestamp actual_mining_time = 2; + // Count of blocks currently produced + int64 produced_blocks = 3; + // The random number. + bytes random_number = 4; +} + +message VoteMinersCountInput { + int32 miners_count = 1; + int64 amount = 2; +} + +message ConsensusInformation { + bytes value = 1; +} + +message GetMinerListInput { + // The term number. + int64 term_number = 1; +} + +message RandomNumberRequestInformation { + int64 target_round_number = 1;// The random hash is likely generated during this round. + int64 order = 2; + int64 expected_block_height = 3; +} + +message HashList { + repeated aelf.Hash values = 1; +} + +message LatestPubkeyToTinyBlocksCount { + // The miner public key. + string pubkey = 1; + // The count of blocks the miner produced. + int64 blocks_count = 2; +} + +message IrreversibleBlockFound { + option (aelf.is_event) = true; + // The irreversible block height found. + int64 irreversible_block_height = 1 [(aelf.is_indexed) = true]; +} + +message IrreversibleBlockHeightUnacceptable { + option (aelf.is_event) = true; + // Distance to the height of the last irreversible block. + int64 distance_to_irreversible_block_height = 1; +} + +message MiningInformationUpdated { + option (aelf.is_event) = true; + // The miner public key. + string pubkey = 1 [(aelf.is_indexed) = true]; + // The current block time. + google.protobuf.Timestamp mining_time = 2 [(aelf.is_indexed) = true]; + // The behaviour of consensus. + string behaviour = 3 [(aelf.is_indexed) = true]; + // The current block height. + int64 block_height = 4 [(aelf.is_indexed) = true]; + // The previous block hash. + aelf.Hash previous_block_hash = 5 [(aelf.is_indexed) = true]; +} + +message SecretSharingInformation { + option (aelf.is_event) = true; + // The previous round information. + Round previous_round = 1 [(aelf.is_indexed) = true]; + // The current round id. + int64 current_round_id = 2; + // The previous round id. + int64 previous_round_id = 3; +} + +message MiningRewardGenerated { + option (aelf.is_event) = true; + // The number of term the mining reward is generated. + int64 term_number = 1 [(aelf.is_indexed) = true]; + // The amount of mining reward. + int64 amount = 2; +} + +message MinerReplaced { + option (aelf.is_event) = true; + // The new miner public key. + string new_miner_pubkey = 1; +} + +message RecordCandidateReplacementInput { + string old_pubkey = 1; + string new_pubkey = 2; +} + +// For compatibility, it is the same as the Round with the addition of the random_number property. +message NextRoundInput { + // The round number. + int64 round_number = 1; + // Current miner information, miner public key -> miner information. + map real_time_miners_information = 2; + // The round number on the main chain + int64 main_chain_miners_round_number = 3; + // The time from chain start to current round (seconds). + int64 blockchain_age = 4; + // The miner public key that produced the extra block in the previous round. + string extra_block_producer_of_previous_round = 5; + // The current term number. + int64 term_number = 6; + // The height of the confirmed irreversible block. + int64 confirmed_irreversible_block_height = 7; + // The round number of the confirmed irreversible block. + int64 confirmed_irreversible_block_round_number = 8; + // Is miner list different from the the miner list in the previous round. + bool is_miner_list_just_changed = 9; + // The round id, calculated by summing block producers’ expecting time (second). + int64 round_id_for_validation = 10; + // The random number. + bytes random_number = 11; +} + +// For compatibility, it is the same as the Round with the addition of the random_number property. +message NextTermInput { + // The round number. + int64 round_number = 1; + // Current miner information, miner public key -> miner information. + map real_time_miners_information = 2; + // The round number on the main chain + int64 main_chain_miners_round_number = 3; + // The time from chain start to current round (seconds). + int64 blockchain_age = 4; + // The miner public key that produced the extra block in the previous round. + string extra_block_producer_of_previous_round = 5; + // The current term number. + int64 term_number = 6; + // The height of the confirmed irreversible block. + int64 confirmed_irreversible_block_height = 7; + // The round number of the confirmed irreversible block. + int64 confirmed_irreversible_block_round_number = 8; + // Is miner list different from the the miner list in the previous round. + bool is_miner_list_just_changed = 9; + // The round id, calculated by summing block producers’ expecting time (second). + int64 round_id_for_validation = 10; + // The random number. + bytes random_number = 11; +} \ No newline at end of file diff --git a/templates/NftSaleContract/src/Protobuf/reference/token_contract.proto b/templates/NftSaleContract/src/Protobuf/reference/token_contract.proto new file mode 100644 index 0000000..d632247 --- /dev/null +++ b/templates/NftSaleContract/src/Protobuf/reference/token_contract.proto @@ -0,0 +1,894 @@ +/** + * MultiToken contract. + */ +syntax = "proto3"; + +package token; + +import "aelf/core.proto"; +import "aelf/options.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; + +option csharp_namespace = "AElf.Contracts.MultiToken"; + +service TokenContract { + // Create a new token. + rpc Create (CreateInput) returns (google.protobuf.Empty) { + } + + // Issuing some amount of tokens to an address is the action of increasing that addresses balance + // for the given token. The total amount of issued tokens must not exceed the total supply of the token + // and only the issuer (creator) of the token can issue tokens. + // Issuing tokens effectively increases the circulating supply. + rpc Issue (IssueInput) returns (google.protobuf.Empty) { + } + + // Transferring tokens simply is the action of transferring a given amount of tokens from one address to another. + // The origin or source address is the signer of the transaction. + // The balance of the sender must be higher than the amount that is transferred. + rpc Transfer (TransferInput) returns (google.protobuf.Empty) { + } + + // The TransferFrom action will transfer a specified amount of tokens from one address to another. + // For this operation to succeed the from address needs to have approved (see allowances) enough tokens + // to Sender of this transaction. If successful the amount will be removed from the allowance. + rpc TransferFrom (TransferFromInput) returns (google.protobuf.Empty) { + } + + // The approve action increases the allowance from the Sender to the Spender address, + // enabling the Spender to call TransferFrom. + rpc Approve (ApproveInput) returns (google.protobuf.Empty) { + } + + rpc BatchApprove (BatchApproveInput) returns (google.protobuf.Empty) { + } + + // This is the reverse operation for Approve, it will decrease the allowance. + rpc UnApprove (UnApproveInput) returns (google.protobuf.Empty) { + } + + // This method can be used to lock tokens. + rpc Lock (LockInput) returns (google.protobuf.Empty) { + } + + // This is the reverse operation of locking, it un-locks some previously locked tokens. + rpc Unlock (UnlockInput) returns (google.protobuf.Empty) { + } + + // This action will burn the specified amount of tokens, removing them from the token’s Supply. + rpc Burn (BurnInput) returns (google.protobuf.Empty) { + } + + // Set the primary token of side chain. + rpc SetPrimaryTokenSymbol (SetPrimaryTokenSymbolInput) returns (google.protobuf.Empty) { + } + + // This interface is used for cross-chain transfer. + rpc CrossChainTransfer (CrossChainTransferInput) returns (google.protobuf.Empty) { + } + + // This method is used to receive cross-chain transfers. + rpc CrossChainReceiveToken (CrossChainReceiveTokenInput) returns (google.protobuf.Empty) { + } + + // The side chain creates tokens. + rpc CrossChainCreateToken(CrossChainCreateTokenInput) returns (google.protobuf.Empty) { + } + + // When the side chain is started, the side chain is initialized with the parent chain information. + rpc InitializeFromParentChain (InitializeFromParentChainInput) returns (google.protobuf.Empty) { + } + + // Handle the transaction fees charged by ChargeTransactionFees. + rpc ClaimTransactionFees (TotalTransactionFeesMap) returns (google.protobuf.Empty) { + } + + // Used to collect transaction fees. + rpc ChargeTransactionFees (ChargeTransactionFeesInput) returns (ChargeTransactionFeesOutput) { + } + + rpc ChargeUserContractTransactionFees(ChargeTransactionFeesInput) returns(ChargeTransactionFeesOutput){ + + } + + // Check the token threshold. + rpc CheckThreshold (CheckThresholdInput) returns (google.protobuf.Empty) { + } + + // Initialize coefficients of every type of tokens supporting charging fee. + rpc InitialCoefficients (google.protobuf.Empty) returns (google.protobuf.Empty){ + } + + // Processing resource token received. + rpc DonateResourceToken (TotalResourceTokensMaps) returns (google.protobuf.Empty) { + } + + // A transaction resource fee is charged to implement the ACS8 standards. + rpc ChargeResourceToken (ChargeResourceTokenInput) returns (google.protobuf.Empty) { + } + + // Verify that the resource token are sufficient. + rpc CheckResourceToken (google.protobuf.Empty) returns (google.protobuf.Empty) { + } + + // Set the list of tokens to pay transaction fees. + rpc SetSymbolsToPayTxSizeFee (SymbolListToPayTxSizeFee) returns (google.protobuf.Empty){ + } + + // Update the coefficient of the transaction fee calculation formula. + rpc UpdateCoefficientsForSender (UpdateCoefficientsInput) returns (google.protobuf.Empty) { + } + + // Update the coefficient of the transaction fee calculation formula. + rpc UpdateCoefficientsForContract (UpdateCoefficientsInput) returns (google.protobuf.Empty) { + } + + // This method is used to initialize the governance organization for some functions, + // including: the coefficient of the user transaction fee calculation formula, + // the coefficient of the contract developer resource fee calculation formula, and the side chain rental fee. + rpc InitializeAuthorizedController (google.protobuf.Empty) returns (google.protobuf.Empty){ + } + + rpc AddAddressToCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) { + } + rpc RemoveAddressFromCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc SetTransactionFeeDelegations (SetTransactionFeeDelegationsInput) returns (SetTransactionFeeDelegationsOutput){ + } + + rpc RemoveTransactionFeeDelegator (RemoveTransactionFeeDelegatorInput) returns (google.protobuf.Empty){ + } + + rpc RemoveTransactionFeeDelegatee (RemoveTransactionFeeDelegateeInput) returns (google.protobuf.Empty){ + } + + rpc SetSymbolAlias (SetSymbolAliasInput) returns (google.protobuf.Empty){ + } + + // Get all delegatees' address of delegator from input + rpc GetTransactionFeeDelegatees (GetTransactionFeeDelegateesInput) returns (GetTransactionFeeDelegateesOutput) { + option (aelf.is_view) = true; + } + + // Query token information. + rpc GetTokenInfo (GetTokenInfoInput) returns (TokenInfo) { + option (aelf.is_view) = true; + } + + // Query native token information. + rpc GetNativeTokenInfo (google.protobuf.Empty) returns (TokenInfo) { + option (aelf.is_view) = true; + } + + // Query resource token information. + rpc GetResourceTokenInfo (google.protobuf.Empty) returns (TokenInfoList) { + option (aelf.is_view) = true; + } + + // Query the balance at the specified address. + rpc GetBalance (GetBalanceInput) returns (GetBalanceOutput) { + option (aelf.is_view) = true; + } + + // Query the account's allowance for other addresses + rpc GetAllowance (GetAllowanceInput) returns (GetAllowanceOutput) { + option (aelf.is_view) = true; + } + + // Query the account's available allowance for other addresses + rpc GetAvailableAllowance (GetAllowanceInput) returns (GetAllowanceOutput) { + option (aelf.is_view) = true; + } + + // Check whether the token is in the whitelist of an address, + // which can be called TransferFrom to transfer the token under the condition of not being credited. + rpc IsInWhiteList (IsInWhiteListInput) returns (google.protobuf.BoolValue) { + option (aelf.is_view) = true; + } + + // Query the information for a lock. + rpc GetLockedAmount (GetLockedAmountInput) returns (GetLockedAmountOutput) { + option (aelf.is_view) = true; + } + + // Query the address of receiving token in cross-chain transfer. + rpc GetCrossChainTransferTokenContractAddress (GetCrossChainTransferTokenContractAddressInput) returns (aelf.Address) { + option (aelf.is_view) = true; + } + + // Query the name of the primary Token. + rpc GetPrimaryTokenSymbol (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + // Query the coefficient of the transaction fee calculation formula. + rpc GetCalculateFeeCoefficientsForContract (google.protobuf.Int32Value) returns (CalculateFeeCoefficients) { + option (aelf.is_view) = true; + } + + // Query the coefficient of the transaction fee calculation formula. + rpc GetCalculateFeeCoefficientsForSender (google.protobuf.Empty) returns (CalculateFeeCoefficients) { + option (aelf.is_view) = true; + } + + // Query tokens that can pay transaction fees. + rpc GetSymbolsToPayTxSizeFee (google.protobuf.Empty) returns (SymbolListToPayTxSizeFee){ + option (aelf.is_view) = true; + } + + // Query the hash of the last input of ClaimTransactionFees. + rpc GetLatestTotalTransactionFeesMapHash (google.protobuf.Empty) returns (aelf.Hash){ + option (aelf.is_view) = true; + } + + // Query the hash of the last input of DonateResourceToken. + rpc GetLatestTotalResourceTokensMapsHash (google.protobuf.Empty) returns (aelf.Hash){ + option (aelf.is_view) = true; + } + rpc IsTokenAvailableForMethodFee (google.protobuf.StringValue) returns (google.protobuf.BoolValue) { + option (aelf.is_view) = true; + } + rpc GetReservedExternalInfoKeyList (google.protobuf.Empty) returns (StringList) { + option (aelf.is_view) = true; + } + + rpc GetTransactionFeeDelegationsOfADelegatee(GetTransactionFeeDelegationsOfADelegateeInput) returns(TransactionFeeDelegations){ + option (aelf.is_view) = true; + } + + rpc GetTokenAlias (google.protobuf.StringValue) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + rpc GetSymbolByAlias (google.protobuf.StringValue) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } +} + +message TokenInfo { + // The symbol of the token.f + string symbol = 1; + // The full name of the token. + string token_name = 2; + // The current supply of the token. + int64 supply = 3; + // The total supply of the token. + int64 total_supply = 4; + // The precision of the token. + int32 decimals = 5; + // The address that has permission to issue the token. + aelf.Address issuer = 6; + // A flag indicating if this token is burnable. + bool is_burnable = 7; + // The chain id of the token. + int32 issue_chain_id = 8; + // The amount of issued tokens. + int64 issued = 9; + // The external information of the token. + ExternalInfo external_info = 10; + // The address that owns the token. + aelf.Address owner = 11; +} + +message ExternalInfo { + map value = 1; +} + +message CreateInput { + // The symbol of the token. + string symbol = 1; + // The full name of the token. + string token_name = 2; + // The total supply of the token. + int64 total_supply = 3; + // The precision of the token + int32 decimals = 4; + // The address that has permission to issue the token. + aelf.Address issuer = 5; + // A flag indicating if this token is burnable. + bool is_burnable = 6; + // A whitelist address list used to lock tokens. + repeated aelf.Address lock_white_list = 7; + // The chain id of the token. + int32 issue_chain_id = 8; + // The external information of the token. + ExternalInfo external_info = 9; + // The address that owns the token. + aelf.Address owner = 10; +} + +message SetPrimaryTokenSymbolInput { + // The symbol of the token. + string symbol = 1; +} + +message IssueInput { + // The token symbol to issue. + string symbol = 1; + // The token amount to issue. + int64 amount = 2; + // The memo. + string memo = 3; + // The target address to issue. + aelf.Address to = 4; +} + +message TransferInput { + // The receiver of the token. + aelf.Address to = 1; + // The token symbol to transfer. + string symbol = 2; + // The amount to to transfer. + int64 amount = 3; + // The memo. + string memo = 4; +} + +message LockInput { + // The one want to lock his token. + aelf.Address address = 1; + // Id of the lock. + aelf.Hash lock_id = 2; + // The symbol of the token to lock. + string symbol = 3; + // a memo. + string usage = 4; + // The amount of tokens to lock. + int64 amount = 5; +} + +message UnlockInput { + // The one want to un-lock his token. + aelf.Address address = 1; + // Id of the lock. + aelf.Hash lock_id = 2; + // The symbol of the token to un-lock. + string symbol = 3; + // a memo. + string usage = 4; + // The amount of tokens to un-lock. + int64 amount = 5; +} + +message TransferFromInput { + // The source address of the token. + aelf.Address from = 1; + // The destination address of the token. + aelf.Address to = 2; + // The symbol of the token to transfer. + string symbol = 3; + // The amount to transfer. + int64 amount = 4; + // The memo. + string memo = 5; +} + +message ApproveInput { + // The address that allowance will be increased. + aelf.Address spender = 1; + // The symbol of token to approve. + string symbol = 2; + // The amount of token to approve. + int64 amount = 3; +} +message BatchApproveInput { + repeated ApproveInput value = 1; +} + +message UnApproveInput { + // The address that allowance will be decreased. + aelf.Address spender = 1; + // The symbol of token to un-approve. + string symbol = 2; + // The amount of token to un-approve. + int64 amount = 3; +} + +message BurnInput { + // The symbol of token to burn. + string symbol = 1; + // The amount of token to burn. + int64 amount = 2; +} + +message ChargeResourceTokenInput { + // Collection of charge resource token, Symbol->Amount. + map cost_dic = 1; + // The sender of the transaction. + aelf.Address caller = 2; +} + +message TransactionFeeBill { + // The transaction fee dictionary, Symbol->fee. + map fees_map = 1; +} + +message TransactionFreeFeeAllowanceBill { + // The transaction free fee allowance dictionary, Symbol->fee. + map free_fee_allowances_map = 1; +} + +message CheckThresholdInput { + // The sender of the transaction. + aelf.Address sender = 1; + // The threshold to set, Symbol->Threshold. + map symbol_to_threshold = 2; + // Whether to check the allowance. + bool is_check_allowance = 3; +} + +message GetTokenInfoInput { + // The symbol of token. + string symbol = 1; +} + +message GetBalanceInput { + // The symbol of token. + string symbol = 1; + // The target address of the query. + aelf.Address owner = 2; +} + +message GetBalanceOutput { + // The symbol of token. + string symbol = 1; + // The target address of the query. + aelf.Address owner = 2; + // The balance of the owner. + int64 balance = 3; +} + +message GetAllowanceInput { + // The symbol of token. + string symbol = 1; + // The address of the token owner. + aelf.Address owner = 2; + // The address of the spender. + aelf.Address spender = 3; +} + +message GetAllowanceOutput { + // The symbol of token. + string symbol = 1; + // The address of the token owner. + aelf.Address owner = 2; + // The address of the spender. + aelf.Address spender = 3; + // The amount of allowance. + int64 allowance = 4; +} + +message CrossChainTransferInput { + // The receiver of transfer. + aelf.Address to = 1; + // The symbol of token. + string symbol = 2; + // The amount of token to transfer. + int64 amount = 3; + // The memo. + string memo = 4; + // The destination chain id. + int32 to_chain_id = 5; + // The chain id of the token. + int32 issue_chain_id = 6; +} + +message CrossChainReceiveTokenInput { + // The source chain id. + int32 from_chain_id = 1; + // The height of the transfer transaction. + int64 parent_chain_height = 2; + // The raw bytes of the transfer transaction. + bytes transfer_transaction_bytes = 3; + // The merkle path created from the transfer transaction. + aelf.MerklePath merkle_path = 4; +} + +message IsInWhiteListInput { + // The symbol of token. + string symbol = 1; + // The address to check. + aelf.Address address = 2; +} + +message SymbolToPayTxSizeFee{ + // The symbol of token. + string token_symbol = 1; + // The charge weight of primary token. + int32 base_token_weight = 2; + // The new added token charge weight. For example, the charge weight of primary Token is set to 1. + // The newly added token charge weight is set to 10. If the transaction requires 1 unit of primary token, + // the user can also pay for 10 newly added tokens. + int32 added_token_weight = 3; +} + +message SymbolListToPayTxSizeFee{ + // Transaction fee token information. + repeated SymbolToPayTxSizeFee symbols_to_pay_tx_size_fee = 1; +} + +message ChargeTransactionFeesInput { + // The method name of transaction. + string method_name = 1; + // The contract address of transaction. + aelf.Address contract_address = 2; + // The amount of transaction size fee. + int64 transaction_size_fee = 3; + // Transaction fee token information. + repeated SymbolToPayTxSizeFee symbols_to_pay_tx_size_fee = 4; +} + +message ChargeTransactionFeesOutput { + // Whether the charge was successful. + bool success = 1; + // The charging information. + string charging_information = 2; +} + +message CallbackInfo { + aelf.Address contract_address = 1; + string method_name = 2; +} + +message ExtraTokenListModified { + option (aelf.is_event) = true; + // Transaction fee token information. + SymbolListToPayTxSizeFee symbol_list_to_pay_tx_size_fee = 1; +} + +message GetLockedAmountInput { + // The address of the lock. + aelf.Address address = 1; + // The token symbol. + string symbol = 2; + // The id of the lock. + aelf.Hash lock_id = 3; +} + +message GetLockedAmountOutput { + // The address of the lock. + aelf.Address address = 1; + // The token symbol. + string symbol = 2; + // The id of the lock. + aelf.Hash lock_id = 3; + // The locked amount. + int64 amount = 4; +} + +message TokenInfoList { + // List of token information. + repeated TokenInfo value = 1; +} + +message GetCrossChainTransferTokenContractAddressInput { + // The chain id. + int32 chainId = 1; +} + +message CrossChainCreateTokenInput { + // The chain id of the chain on which the token was created. + int32 from_chain_id = 1; + // The height of the transaction that created the token. + int64 parent_chain_height = 2; + // The transaction that created the token. + bytes transaction_bytes = 3; + // The merkle path created from the transaction that created the transaction. + aelf.MerklePath merkle_path = 4; +} + +message InitializeFromParentChainInput { + // The amount of resource. + map resource_amount = 1; + // The token contract addresses. + map registered_other_token_contract_addresses = 2; + // The creator the side chain. + aelf.Address creator = 3; +} + +message UpdateCoefficientsInput { + // The specify pieces gonna update. + repeated int32 piece_numbers = 1; + // Coefficients of one single type. + CalculateFeeCoefficients coefficients = 2; +} + +enum FeeTypeEnum { + READ = 0; + STORAGE = 1; + WRITE = 2; + TRAFFIC = 3; + TX = 4; +} + +message CalculateFeePieceCoefficients { + // Coefficients of one single piece. + // The first char is its type: liner / power. + // The second char is its piece upper bound. + repeated int32 value = 1; +} + +message CalculateFeeCoefficients { + // The resource fee type, like READ, WRITE, etc. + int32 fee_token_type = 1; + // Coefficients of one single piece. + repeated CalculateFeePieceCoefficients piece_coefficients_list = 2; +} + +message AllCalculateFeeCoefficients { + // The coefficients of fee Calculation. + repeated CalculateFeeCoefficients value = 1; +} + +message TotalTransactionFeesMap +{ + // Token dictionary that charge transaction fee, Symbol->Amount. + map value = 1; + // The hash of the block processing the transaction. + aelf.Hash block_hash = 2; + // The height of the block processing the transaction. + int64 block_height = 3; +} + +message TotalResourceTokensMaps { + // Resource tokens to charge. + repeated ContractTotalResourceTokens value = 1; + // The hash of the block processing the transaction. + aelf.Hash block_hash = 2; + // The height of the block processing the transaction. + int64 block_height = 3; +} + +message ContractTotalResourceTokens { + // The contract address. + aelf.Address contract_address = 1; + // Resource tokens to charge. + TotalResourceTokensMap tokens_map = 2; +} + +message TotalResourceTokensMap +{ + // Resource token dictionary, Symbol->Amount. + map value = 1; +} + +message StringList { + repeated string value = 1; +} + +message TransactionFeeDelegations{ + // delegation, symbols and its' amount + map delegations = 1; + // height when added + int64 block_height = 2; + //Whether to pay transaction fee continuously + bool isUnlimitedDelegate = 3; +} + +message TransactionFeeDelegatees{ + map delegatees = 1; +} + +message SetTransactionFeeDelegationsInput { + // the delegator address + aelf.Address delegator_address = 1; + // delegation, symbols and its' amount + map delegations = 2; +} + +message SetTransactionFeeDelegationsOutput { + bool success = 1; +} + +message RemoveTransactionFeeDelegatorInput{ + // the delegator address + aelf.Address delegator_address = 1; +} + +message RemoveTransactionFeeDelegateeInput { + // the delegatee address + aelf.Address delegatee_address = 1; +} + +message GetTransactionFeeDelegationsOfADelegateeInput { + aelf.Address delegatee_address = 1; + aelf.Address delegator_address = 2; +} + +message GetTransactionFeeDelegateesInput { + aelf.Address delegator_address = 1; +} + +message GetTransactionFeeDelegateesOutput { + repeated aelf.Address delegatee_addresses = 1; +} + +message SetSymbolAliasInput { + string symbol = 1; + string alias = 2; +} + +// Events + +message Transferred { + option (aelf.is_event) = true; + // The source address of the transferred token. + aelf.Address from = 1 [(aelf.is_indexed) = true]; + // The destination address of the transferred token. + aelf.Address to = 2 [(aelf.is_indexed) = true]; + // The symbol of the transferred token. + string symbol = 3 [(aelf.is_indexed) = true]; + // The amount of the transferred token. + int64 amount = 4; + // The memo. + string memo = 5; +} + +message Approved { + option (aelf.is_event) = true; + // The address of the token owner. + aelf.Address owner = 1 [(aelf.is_indexed) = true]; + // The address that allowance be increased. + aelf.Address spender = 2 [(aelf.is_indexed) = true]; + // The symbol of approved token. + string symbol = 3 [(aelf.is_indexed) = true]; + // The amount of approved token. + int64 amount = 4; +} + +message UnApproved { + option (aelf.is_event) = true; + // The address of the token owner. + aelf.Address owner = 1 [(aelf.is_indexed) = true]; + // The address that allowance be decreased. + aelf.Address spender = 2 [(aelf.is_indexed) = true]; + // The symbol of un-approved token. + string symbol = 3 [(aelf.is_indexed) = true]; + // The amount of un-approved token. + int64 amount = 4; +} + +message Burned +{ + option (aelf.is_event) = true; + // The address who wants to burn token. + aelf.Address burner = 1 [(aelf.is_indexed) = true]; + // The symbol of burned token. + string symbol = 2 [(aelf.is_indexed) = true]; + // The amount of burned token. + int64 amount = 3; +} + +message ChainPrimaryTokenSymbolSet { + option (aelf.is_event) = true; + // The symbol of token. + string token_symbol = 1; +} + +message CalculateFeeAlgorithmUpdated { + option (aelf.is_event) = true; + // All calculate fee coefficients after modification. + AllCalculateFeeCoefficients all_type_fee_coefficients = 1; +} + +message RentalCharged { + option (aelf.is_event) = true; + // The symbol of rental fee charged. + string symbol = 1; + // The amount of rental fee charged. + int64 amount = 2; + // The payer of rental fee. + aelf.Address payer = 3; + // The receiver of rental fee. + aelf.Address receiver = 4; +} + +message RentalAccountBalanceInsufficient { + option (aelf.is_event) = true; + // The symbol of insufficient rental account balance. + string symbol = 1; + // The balance of the account. + int64 amount = 2; +} + +message TokenCreated { + option (aelf.is_event) = true; + // The symbol of the token. + string symbol = 1; + // The full name of the token. + string token_name = 2; + // The total supply of the token. + int64 total_supply = 3; + // The precision of the token. + int32 decimals = 4; + // The address that has permission to issue the token. + aelf.Address issuer = 5; + // A flag indicating if this token is burnable. + bool is_burnable = 6; + // The chain id of the token. + int32 issue_chain_id = 7; + // The external information of the token. + ExternalInfo external_info = 8; + // The address that owns the token. + aelf.Address owner = 9; +} + +message Issued { + option (aelf.is_event) = true; + // The symbol of issued token. + string symbol = 1; + // The amount of issued token. + int64 amount = 2; + // The memo. + string memo = 3; + // The issued target address. + aelf.Address to = 4; +} + +message CrossChainTransferred { + option (aelf.is_event) = true; + // The source address of the transferred token. + aelf.Address from = 1; + // The destination address of the transferred token. + aelf.Address to = 2; + // The symbol of the transferred token. + string symbol = 3; + // The amount of the transferred token. + int64 amount = 4; + // The memo. + string memo = 5; + // The destination chain id. + int32 to_chain_id = 6; + // The chain id of the token. + int32 issue_chain_id = 7; +} + +message CrossChainReceived { + option (aelf.is_event) = true; + // The source address of the transferred token. + aelf.Address from = 1; + // The destination address of the transferred token. + aelf.Address to = 2; + // The symbol of the received token. + string symbol = 3; + // The amount of the received token. + int64 amount = 4; + // The memo. + string memo = 5; + // The destination chain id. + int32 from_chain_id = 6; + // The chain id of the token. + int32 issue_chain_id = 7; + // The parent chain height of the transfer transaction. + int64 parent_chain_height = 8; + // The id of transfer transaction. + aelf.Hash transfer_transaction_id =9; +} + +message TransactionFeeDelegationAdded { + option (aelf.is_event) = true; + aelf.Address delegator = 1 [(aelf.is_indexed) = true]; + aelf.Address delegatee = 2 [(aelf.is_indexed) = true]; + aelf.Address caller = 3 [(aelf.is_indexed) = true]; +} + +message TransactionFeeDelegationCancelled { + option (aelf.is_event) = true; + aelf.Address delegator = 1 [(aelf.is_indexed) = true]; + aelf.Address delegatee = 2 [(aelf.is_indexed) = true]; + aelf.Address caller = 3 [(aelf.is_indexed) = true]; +} + +message SymbolAliasAdded { + option (aelf.is_event) = true; + string symbol = 1 [(aelf.is_indexed) = true]; + string alias = 2 [(aelf.is_indexed) = true]; +} + +message SymbolAliasDeleted { + option (aelf.is_event) = true; + string symbol = 1 [(aelf.is_indexed) = true]; + string alias = 2 [(aelf.is_indexed) = true]; +} \ No newline at end of file diff --git a/templates/NftSaleContract/test/NftSale.Tests.csproj b/templates/NftSaleContract/test/NftSale.Tests.csproj new file mode 100644 index 0000000..f23534b --- /dev/null +++ b/templates/NftSaleContract/test/NftSale.Tests.csproj @@ -0,0 +1,51 @@ + + + net6.0 + AElf.Contracts.NftSale + + + + 0436;CS2002 + + + $(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/ + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + nocontract + + + nocontract + + + stub + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/NftSaleContract/test/NftSaleTests.cs b/templates/NftSaleContract/test/NftSaleTests.cs new file mode 100644 index 0000000..6755e7b --- /dev/null +++ b/templates/NftSaleContract/test/NftSaleTests.cs @@ -0,0 +1,294 @@ +using System; +using System.Threading.Tasks; +using AElf.Contracts.MultiToken; +using AElf.Contracts.Vote; +using AElf.Types; +using Google.Protobuf.WellKnownTypes; +using Shouldly; +using Xunit; + +namespace AElf.Contracts.NftSale +{ + // This class is unit test class, and it inherit TestBase. Write your unit test code inside it + public class NftSaleTests : TestBase + { + [Fact] + public async Task InitializeContract_Success() + { + var price = new Price + { + Amount = 4, + Symbol = "ELF" + }; + var nftPrice = new NftPrice + { + Symbol = "ELF", + Price = price + }; + // Act + var result = await NftSaleStub.Initialize.SendAsync(nftPrice); + + // Assert + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var owner = await NftSaleStub.GetOwner.CallAsync(new Empty()); + owner.Value.ShouldBe(DefaultAccount.Address.ToBase58()); + } + + [Fact] + public async Task InitializeContract_Fail_AlreadyInitialized() + { + var price = new Price + { + Amount = 4, + Symbol = "ELF" + }; + var nftPrice = new NftPrice + { + Symbol = "ELF", + Price = price + }; + // Arrange + await NftSaleStub.Initialize.SendAsync(nftPrice); + + // Act & Assert + Should.Throw(async () => await NftSaleStub.Initialize.SendAsync(nftPrice)); + } + + [Fact] + public async Task SetPrice_and_GetPrice() + { + var price = new Price + { + Amount = 2, + Symbol = "ELF" + }; + var nftPrice = new NftPrice + { + Symbol = "ELF", + Price = price + }; + // Arrange + await NftSaleStub.Initialize.SendAsync(nftPrice); + var priceNew = new Price + { + Amount = 4, + Symbol = "ELF" + }; + + await NftSaleStub.SetPriceAndSymbol.SendAsync(new NftPrice + { + Symbol = "ELF", + Price = priceNew + }); + + var symbolPrice = await NftSaleStub.GetPrice.CallAsync(new Empty{}); + + symbolPrice.Amount.ShouldBe(4); + } + + [Fact] + public async Task Purchase_Success() + { + var price = new Price + { + Amount = 2, + Symbol = "ELF" + }; + var nftPrice = new NftPrice + { + Symbol = "ELF", + Price = price + }; + await NftSaleStub.Initialize.SendAsync(nftPrice); + await ApproveSpendingAsync(10000_0000000); + await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Spender = Accounts[1].Address, + Symbol = "ELF", + Amount = 100_00000000 + }); + await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Spender = Accounts[0].Address, + Symbol = "ELF", + Amount = 100_00000000 + }); + //await SendTokenTo(Accounts[2].Address); + await SendTokenTo(ContractAddress); + //await SendTokenTo(Accounts[0].Address); + await SendTokenTo(Accounts[1].Address); + var initialContractBalance = await GetContractBalanceAsync(Accounts[0].Address); + + var initialContractBalance1 = await GetContractBalanceAsync(Accounts[1].Address); + var priceNew = new Price + { + Amount = 3, + Symbol = "ELF" + }; + await NftSaleStub.Purchase.SendAsync(new PurchaseInput + { + Amount = 1, + Symbol = "ELF", + Memo = "Test get resource", + Price = priceNew + }); + + var finalContractBalance = await GetContractBalanceAsync(Accounts[0].Address); + var finalContractBalance2 = await GetContractBalanceAsync(Accounts[1].Address); + finalContractBalance.ShouldBe(initialContractBalance - 1); + } + + private async Task ApproveSpendingAsync(long amount) + { + await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Spender = ContractAddress, + Symbol = "ELF", + Amount = amount + }); + } + + [Fact] + public async Task Deposit_Success() + { + var price = new Price + { + Amount = 2, + Symbol = "ELF" + }; + var nftPrice = new NftPrice + { + Symbol = "ELF", + Price = price + }; + // Arrange + await NftSaleStub.Initialize.SendAsync(nftPrice); + + // Approve spending on the lottery contract + await ApproveSpendingAsync(100_00000000); + + const long depositAmount = 10_000_000; // 0.1 ELF + // var depositInput = new Int64Value() { Value = depositAmount }; + var depositInput = new DepositeInput + { + Symbol = "ELF", + Amount = 10_000_000 + }; + + var initialContractBalance = await GetContractBalanceAsync(ContractAddress); + + // Act + var result = await NftSaleStub.Deposit.SendAsync(depositInput); + + // Assert + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // Check balance update + var finalContractBalance = await GetContractBalanceAsync(ContractAddress); + finalContractBalance.ShouldBe(initialContractBalance + depositAmount); + + // Check if the event is emitted + var events = result.TransactionResult.Logs; + events.ShouldContain(log => log.Name == nameof(DepositEvent)); + } + + [Fact] + public async Task Withdraw_Success() + { + var price = new Price + { + Amount = 2, + Symbol = "ELF" + }; + var nftPrice = new NftPrice + { + Symbol = "ELF", + Price = price + }; + // Arrange + await NftSaleStub.Initialize.SendAsync(nftPrice); + + // Approve spending on the lottery contract + await ApproveSpendingAsync(100_00000000); + + var depositInput = new DepositeInput + { + Symbol = "ELF", + Amount = 10_000_000 + }; + await NftSaleStub.Deposit.SendAsync(depositInput); + + const long withdrawAmount = 5_000_000; // 0.05 ELF + var withdrawInput = new Int64Value() { Value = withdrawAmount }; + + var initialSenderBalance = await GetTokenBalanceAsync(DefaultAccount.Address); + var initialContractBalance = await GetContractBalanceAsync(ContractAddress); + + // Act + var result = await NftSaleStub.Withdraw.SendAsync(withdrawInput); + + // Assert + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // Check balance update + var finalSenderBalance = await GetTokenBalanceAsync(DefaultAccount.Address); + var finalContractBalance = await GetContractBalanceAsync(ContractAddress); + + finalSenderBalance.ShouldBe(initialSenderBalance + withdrawAmount); + finalContractBalance.ShouldBe(initialContractBalance - withdrawAmount); + + // Check if the event is emitted + var events = result.TransactionResult.Logs; + events.ShouldContain(log => log.Name == nameof(WithdrawEvent)); + } + + [Fact] + public async Task Withdraw_InsufficientBalance_Fail() + { + var price = new Price + { + Amount = 2, + Symbol = "ELF" + }; + var nftPrice = new NftPrice + { + Symbol = "ELF", + Price = price + }; + // Arrange + await NftSaleStub.Initialize.SendAsync(nftPrice); + + long withdrawAmount = 5_000_000; // 0.05 ELF + var withdrawInput = new Int64Value() { Value = withdrawAmount }; + + // Act & Assert + Should.Throw(async () => await NftSaleStub.Withdraw.SendAsync(withdrawInput)); + } + + private async Task GetTokenBalanceAsync(Address owner) + { + return (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = owner, + Symbol = "ELF" + })).Balance; + } + + private async Task GetContractBalanceAsync(Address address) + { + var input = new GetContractBalanceInput {Address = address}; + return (await NftSaleStub.GetContractBalance.CallAsync(input)).Value; + } + + private async Task SendTokenTo(Address address) + { + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + To = address, + Symbol = "ELF", + Amount = 100 + }); + } + } +} \ No newline at end of file diff --git a/templates/NftSaleContract/test/Protobuf/message/authority_info.proto b/templates/NftSaleContract/test/Protobuf/message/authority_info.proto new file mode 100644 index 0000000..eee3496 --- /dev/null +++ b/templates/NftSaleContract/test/Protobuf/message/authority_info.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +import "aelf/core.proto"; + +option csharp_namespace = "AElf.Contracts.NftSale"; + +message AuthorityInfo { + aelf.Address contract_address = 1; + aelf.Address owner_address = 2; +} \ No newline at end of file diff --git a/templates/NftSaleContract/test/Protobuf/reference/acs12.proto b/templates/NftSaleContract/test/Protobuf/reference/acs12.proto new file mode 100644 index 0000000..e6ead4b --- /dev/null +++ b/templates/NftSaleContract/test/Protobuf/reference/acs12.proto @@ -0,0 +1,35 @@ +/** + * AElf Standards ACS12(User Contract Standard) + * + * Used to manage user contract. + */ +syntax = "proto3"; + +package acs12; + +import public "aelf/options.proto"; +import public "google/protobuf/empty.proto"; +import public "google/protobuf/wrappers.proto"; +import "aelf/core.proto"; + +option (aelf.identity) = "acs12"; +option csharp_namespace = "AElf.Standards.ACS12"; + +service UserContract{ + +} + +//Specified method fee for user contract. +message UserContractMethodFees { + // List of fees to be charged. + repeated UserContractMethodFee fees = 2; + // Optional based on the implementation of SetConfiguration method. + bool is_size_fee_free = 3; +} + +message UserContractMethodFee { + // The token symbol of the method fee. + string symbol = 1; + // The amount of fees to be charged. + int64 basic_fee = 2; +} \ No newline at end of file diff --git a/templates/NftSaleContract/test/Protobuf/reference/aedpos_contract.proto b/templates/NftSaleContract/test/Protobuf/reference/aedpos_contract.proto new file mode 100644 index 0000000..37965d8 --- /dev/null +++ b/templates/NftSaleContract/test/Protobuf/reference/aedpos_contract.proto @@ -0,0 +1,507 @@ +/** + * AEDPoS contract. + */ +syntax = "proto3"; + +package AEDPoS; + +import "aelf/options.proto"; +import "aelf/core.proto"; +import "Protobuf/message/authority_info.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +option csharp_namespace = "AElf.Contracts.Consensus.AEDPoS"; + +service AEDPoSContract { + + option (aelf.csharp_state) = "AElf.Contracts.Consensus.AEDPoS.AEDPoSContractState"; + + // Initialize the consensus contract. + rpc InitialAElfConsensusContract (InitialAElfConsensusContractInput) returns (google.protobuf.Empty) { + } + + // Initializes the consensus information in the first round. + rpc FirstRound (Round) returns (google.protobuf.Empty) { + } + + // Update consensus information. + rpc UpdateValue (UpdateValueInput) returns (google.protobuf.Empty) { + } + + // Update consensus information, create a new round. + rpc NextRound (NextRoundInput) returns (google.protobuf.Empty) { + } + + // Update consensus information, create a new term. + rpc NextTerm (NextTermInput) returns (google.protobuf.Empty) { + } + + // Update consensus tiny block information. + rpc UpdateTinyBlockInformation (TinyBlockInput) returns (google.protobuf.Empty) { + } + + // Set the maximum count of miners, by default, is unlimited. + // If you want to control the count of miners, you need to set it through parliament. + rpc SetMaximumMinersCount (google.protobuf.Int32Value) returns (google.protobuf.Empty) { + } + + // The authority information for SetMaximumMinersCount, by default, is governed by parliament. + rpc ChangeMaximumMinersCountController (AuthorityInfo) returns (google.protobuf.Empty) { + } + + // Set miner increase interval + rpc SetMinerIncreaseInterval (google.protobuf.Int64Value) returns (google.protobuf.Empty){ + } + + // Election Contract can notify AEDPoS Contract to aware candidate replacement happened. + rpc RecordCandidateReplacement (RecordCandidateReplacementInput) returns (google.protobuf.Empty) { + } + + // Get the list of current miners. + rpc GetCurrentMinerList (google.protobuf.Empty) returns (MinerList) { + option (aelf.is_view) = true; + } + + // Get the list of current miners (hexadecimal format). + rpc GetCurrentMinerPubkeyList (google.protobuf.Empty) returns (PubkeyList) { + option (aelf.is_view) = true; + } + + // Get the list of current miners and current round number. + rpc GetCurrentMinerListWithRoundNumber (google.protobuf.Empty) returns (MinerListWithRoundNumber) { + option (aelf.is_view) = true; + } + + // Get information of the round according to round number. + rpc GetRoundInformation (google.protobuf.Int64Value) returns (Round) { + option (aelf.is_view) = true; + } + + // Get the current round number. + rpc GetCurrentRoundNumber (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get the current round information. + rpc GetCurrentRoundInformation (google.protobuf.Empty) returns (Round) { + option (aelf.is_view) = true; + } + + // Get the previous round information. + rpc GetPreviousRoundInformation (google.protobuf.Empty) returns (Round) { + option (aelf.is_view) = true; + } + + // Get the current term number. + rpc GetCurrentTermNumber (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get the welfare reward the current term. + rpc GetCurrentTermMiningReward (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get the list of miners according to term number. + rpc GetMinerList (GetMinerListInput) returns (MinerList) { + option (aelf.is_view) = true; + } + + // Get the list of miner in previous term. + rpc GetPreviousMinerList (google.protobuf.Empty) returns (MinerList) { + option (aelf.is_view) = true; + } + + // Get the amount of mined blocks in previous term. + rpc GetMinedBlocksOfPreviousTerm (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get the miner that produces the next block. + rpc GetNextMinerPubkey (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + // Check to see if the account address is on the miner list for the current round. + rpc IsCurrentMiner (aelf.Address) returns (google.protobuf.BoolValue) { + option (aelf.is_view) = true; + } + + // Query the left time before the next election takes effects (seconds). + rpc GetNextElectCountDown (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + // Get term information according term number. + rpc GetPreviousTermInformation (google.protobuf.Int64Value) returns (Round) { + option (aelf.is_view) = true; + } + + // Get random hash (Keep this for compatibility). + rpc GetRandomHash (google.protobuf.Int64Value) returns (aelf.Hash) { + option (aelf.is_view) = true; + } + + // Get the maximum of tiny blocks produced by a miner each round. + rpc GetMaximumBlocksCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) { + option (aelf.is_view) = true; + } + + // Get the maximum count of miners. + rpc GetMaximumMinersCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) { + option (aelf.is_view) = true; + } + + // Get the authority information for SetMaximumMinersCount. + rpc GetMaximumMinersCountController (google.protobuf.Empty) returns (AuthorityInfo) { + option (aelf.is_view) = true; + } + + // Get miner increase interval + rpc GetMinerIncreaseInterval (google.protobuf.Empty) returns (google.protobuf.Int64Value){ + option (aelf.is_view) = true; + } + + // Gets the list of miners in the main chain. + rpc GetMainChainCurrentMinerList (google.protobuf.Empty) returns (MinerList) { + option (aelf.is_view) = true; + } + + // Get the list of miners in the previous term. + rpc GetPreviousTermMinerPubkeyList (google.protobuf.Empty) returns (PubkeyList) { + option (aelf.is_view) = true; + } + + // Query the current mining reward for each block. + rpc GetCurrentMiningRewardPerBlock (google.protobuf.Empty) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } +} + +message InitialAElfConsensusContractInput { + // Whether not to change the term. + bool is_term_stay_one = 1; + // Is a side chain. + bool is_side_chain = 2; + // The number of seconds per term. + int64 period_seconds = 3; + // The interval second that increases the number of miners. + int64 miner_increase_interval = 4; +} + +message UpdateValueInput { + // Calculated from current in value. + aelf.Hash out_value = 1; + // Calculated from current in value and signatures of previous round. + aelf.Hash signature = 2; + // To ensure the values to update will be apply to correct round by comparing round id. + int64 round_id = 3; + // Publish previous in value for validation previous signature and previous out value. + aelf.Hash previous_in_value = 4; + // The actual mining time, miners must fill actual mining time when they do the mining. + google.protobuf.Timestamp actual_mining_time = 5; + // The supposed order of mining for the next round. + int32 supposed_order_of_next_round = 6; + // The tuning order of mining for the next round, miner public key -> order. + map tune_order_information = 7; + // The encrypted pieces of InValue. + map encrypted_pieces = 8; + // The decrypted pieces of InValue. + map decrypted_pieces = 9; + // The amount of produced blocks. + int64 produced_blocks = 10; + // The InValue in the previous round, miner public key -> InValue. + map miners_previous_in_values = 11; + // The irreversible block height that miner recorded. + int64 implied_irreversible_block_height = 12; + // The random number. + bytes random_number = 13; +} + +message MinerList { + // The miners public key list. + repeated bytes pubkeys = 1; +} + +message PubkeyList { + // The miners public key list. + repeated string pubkeys = 1; +} + +message TermNumberLookUp { + // Term number -> Round number. + map map = 1; +} + +message Candidates { + // The candidate public keys. + repeated bytes pubkeys = 1; +} + +message Round { + // The round number. + int64 round_number = 1; + // Current miner information, miner public key -> miner information. + map real_time_miners_information = 2; + // The round number on the main chain + int64 main_chain_miners_round_number = 3; + // The time from chain start to current round (seconds). + int64 blockchain_age = 4; + // The miner public key that produced the extra block in the previous round. + string extra_block_producer_of_previous_round = 5; + // The current term number. + int64 term_number = 6; + // The height of the confirmed irreversible block. + int64 confirmed_irreversible_block_height = 7; + // The round number of the confirmed irreversible block. + int64 confirmed_irreversible_block_round_number = 8; + // Is miner list different from the the miner list in the previous round. + bool is_miner_list_just_changed = 9; + // The round id, calculated by summing block producers’ expecting time (second). + int64 round_id_for_validation = 10; +} + +message MinerInRound { + // The order of the miner producing block. + int32 order = 1; + // Is extra block producer in the current round. + bool is_extra_block_producer = 2; + // Generated by secret sharing and used for validation between miner. + aelf.Hash in_value = 3; + // Calculated from current in value. + aelf.Hash out_value = 4; + // Calculated from current in value and signatures of previous round. + aelf.Hash signature = 5; + // The expected mining time. + google.protobuf.Timestamp expected_mining_time = 6; + // The amount of produced blocks. + int64 produced_blocks = 7; + // The amount of missed time slots. + int64 missed_time_slots = 8; + // The public key of this miner. + string pubkey = 9; + // The InValue of the previous round. + aelf.Hash previous_in_value = 10; + // The supposed order of mining for the next round. + int32 supposed_order_of_next_round = 11; + // The final order of mining for the next round. + int32 final_order_of_next_round = 12; + // The actual mining time, miners must fill actual mining time when they do the mining. + repeated google.protobuf.Timestamp actual_mining_times = 13; + // The encrypted pieces of InValue. + map encrypted_pieces = 14; + // The decrypted pieces of InValue. + map decrypted_pieces = 15; + // The amount of produced tiny blocks. + int64 produced_tiny_blocks = 16; + // The irreversible block height that current miner recorded. + int64 implied_irreversible_block_height = 17; +} + +message AElfConsensusHeaderInformation { + // The sender public key. + bytes sender_pubkey = 1; + // The round information. + Round round = 2; + // The behaviour of consensus. + AElfConsensusBehaviour behaviour = 3; +} + +message AElfConsensusHint { + // The behaviour of consensus. + AElfConsensusBehaviour behaviour = 1; + // The round id. + int64 round_id = 2; + // The previous round id. + int64 previous_round_id = 3; +} + +enum AElfConsensusBehaviour { + UPDATE_VALUE = 0; + NEXT_ROUND = 1; + NEXT_TERM = 2; + NOTHING = 3; + TINY_BLOCK = 4; +} + +message AElfConsensusTriggerInformation { + // The miner public key. + bytes pubkey = 1; + // The InValue for current round. + aelf.Hash in_value = 2; + // The InValue for previous round. + aelf.Hash previous_in_value = 3; + // The behaviour of consensus. + AElfConsensusBehaviour behaviour = 4; + // The encrypted pieces of InValue. + map encrypted_pieces = 5; + // The decrypted pieces of InValue. + map decrypted_pieces = 6; + // The revealed InValues. + map revealed_in_values = 7; + // The random number. + bytes random_number = 8; +} + +message TermInfo { + int64 term_number = 1; + int64 round_number = 2; +} + +message MinerListWithRoundNumber { + // The list of miners. + MinerList miner_list = 1; + // The round number. + int64 round_number = 2; +} + +message TinyBlockInput { + // The round id. + int64 round_id = 1; + // The actual mining time. + google.protobuf.Timestamp actual_mining_time = 2; + // Count of blocks currently produced + int64 produced_blocks = 3; + // The random number. + bytes random_number = 4; +} + +message VoteMinersCountInput { + int32 miners_count = 1; + int64 amount = 2; +} + +message ConsensusInformation { + bytes value = 1; +} + +message GetMinerListInput { + // The term number. + int64 term_number = 1; +} + +message RandomNumberRequestInformation { + int64 target_round_number = 1;// The random hash is likely generated during this round. + int64 order = 2; + int64 expected_block_height = 3; +} + +message HashList { + repeated aelf.Hash values = 1; +} + +message LatestPubkeyToTinyBlocksCount { + // The miner public key. + string pubkey = 1; + // The count of blocks the miner produced. + int64 blocks_count = 2; +} + +message IrreversibleBlockFound { + option (aelf.is_event) = true; + // The irreversible block height found. + int64 irreversible_block_height = 1 [(aelf.is_indexed) = true]; +} + +message IrreversibleBlockHeightUnacceptable { + option (aelf.is_event) = true; + // Distance to the height of the last irreversible block. + int64 distance_to_irreversible_block_height = 1; +} + +message MiningInformationUpdated { + option (aelf.is_event) = true; + // The miner public key. + string pubkey = 1 [(aelf.is_indexed) = true]; + // The current block time. + google.protobuf.Timestamp mining_time = 2 [(aelf.is_indexed) = true]; + // The behaviour of consensus. + string behaviour = 3 [(aelf.is_indexed) = true]; + // The current block height. + int64 block_height = 4 [(aelf.is_indexed) = true]; + // The previous block hash. + aelf.Hash previous_block_hash = 5 [(aelf.is_indexed) = true]; +} + +message SecretSharingInformation { + option (aelf.is_event) = true; + // The previous round information. + Round previous_round = 1 [(aelf.is_indexed) = true]; + // The current round id. + int64 current_round_id = 2; + // The previous round id. + int64 previous_round_id = 3; +} + +message MiningRewardGenerated { + option (aelf.is_event) = true; + // The number of term the mining reward is generated. + int64 term_number = 1 [(aelf.is_indexed) = true]; + // The amount of mining reward. + int64 amount = 2; +} + +message MinerReplaced { + option (aelf.is_event) = true; + // The new miner public key. + string new_miner_pubkey = 1; +} + +message RecordCandidateReplacementInput { + string old_pubkey = 1; + string new_pubkey = 2; +} + +// For compatibility, it is the same as the Round with the addition of the random_number property. +message NextRoundInput { + // The round number. + int64 round_number = 1; + // Current miner information, miner public key -> miner information. + map real_time_miners_information = 2; + // The round number on the main chain + int64 main_chain_miners_round_number = 3; + // The time from chain start to current round (seconds). + int64 blockchain_age = 4; + // The miner public key that produced the extra block in the previous round. + string extra_block_producer_of_previous_round = 5; + // The current term number. + int64 term_number = 6; + // The height of the confirmed irreversible block. + int64 confirmed_irreversible_block_height = 7; + // The round number of the confirmed irreversible block. + int64 confirmed_irreversible_block_round_number = 8; + // Is miner list different from the the miner list in the previous round. + bool is_miner_list_just_changed = 9; + // The round id, calculated by summing block producers’ expecting time (second). + int64 round_id_for_validation = 10; + // The random number. + bytes random_number = 11; +} + +// For compatibility, it is the same as the Round with the addition of the random_number property. +message NextTermInput { + // The round number. + int64 round_number = 1; + // Current miner information, miner public key -> miner information. + map real_time_miners_information = 2; + // The round number on the main chain + int64 main_chain_miners_round_number = 3; + // The time from chain start to current round (seconds). + int64 blockchain_age = 4; + // The miner public key that produced the extra block in the previous round. + string extra_block_producer_of_previous_round = 5; + // The current term number. + int64 term_number = 6; + // The height of the confirmed irreversible block. + int64 confirmed_irreversible_block_height = 7; + // The round number of the confirmed irreversible block. + int64 confirmed_irreversible_block_round_number = 8; + // Is miner list different from the the miner list in the previous round. + bool is_miner_list_just_changed = 9; + // The round id, calculated by summing block producers’ expecting time (second). + int64 round_id_for_validation = 10; + // The random number. + bytes random_number = 11; +} \ No newline at end of file diff --git a/templates/NftSaleContract/test/Protobuf/stub/nft_sale_contract.proto b/templates/NftSaleContract/test/Protobuf/stub/nft_sale_contract.proto new file mode 100644 index 0000000..373588e --- /dev/null +++ b/templates/NftSaleContract/test/Protobuf/stub/nft_sale_contract.proto @@ -0,0 +1,114 @@ +syntax = "proto3"; + +import "aelf/core.proto"; +import "aelf/options.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; +import "Protobuf/reference/acs12.proto"; +// The namespace of this class +option csharp_namespace = "AElf.Contracts.NftSale"; + +service NftSale { + // The name of the state class the smart contract is going to use to access blockchain state + option (aelf.csharp_state) = "AElf.Contracts.NftSale.NftSaleState"; + option (aelf.base) = "Protobuf/reference/acs12.proto"; + + rpc Initialize (NftPrice) returns (google.protobuf.Empty) { + } + + rpc Purchase (PurchaseInput) returns (google.protobuf.Empty) { + } + + rpc SetPriceAndSymbol (NftPrice) returns (google.protobuf.Empty) { + } + + rpc GetPrice (google.protobuf.Empty) returns (Price) { + option (aelf.is_view) = true; + } + + rpc GetSymbol (google.protobuf.Empty) returns (NftSymbol) { + option (aelf.is_view) = true; + } + + rpc Withdraw (google.protobuf.Int64Value) returns (google.protobuf.Empty) { + } + + rpc Deposit (DepositeInput) returns (google.protobuf.Empty) { + } + + rpc TransferOwnership (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc GetContractBalance (GetContractBalanceInput) returns (google.protobuf.Int64Value) { + option (aelf.is_view) = true; + } + + rpc GetOwner (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } +} + +message DepositeInput{ + string symbol = 1; // nft + int64 amount = 2; // token amount +} + +message Price { + string symbol = 1; // token type + int64 amount = 2; // token price +} + +message NftSymbol { + string symbol = 1; +} + +message NftPrice{ + // // The token symbol price + Price price = 1; + // The token symbol + string symbol = 2; +} + +message PurchaseInput { + // The token symbol to transfer. + string symbol = 2; + // The amount to to transfer. + int64 amount = 3; + // The memo. + string memo = 4; + // Transaction information + Price price = 5; +} + +message SaleNft { + option (aelf.is_event) = true; + // The destination address of the transferred token. + aelf.Address to = 2 [(aelf.is_indexed) = true]; + // The symbol of the transferred token. + string symbol = 3 [(aelf.is_indexed) = true]; + // The amount of the transferred token. + int64 amount = 4; + // The memo. + string memo = 5; +} + +message GetContractBalanceInput{ + aelf.Address address = 1; +} + +// An event that will be emitted from contract method call when Withdraw is called. +message WithdrawEvent { + option (aelf.is_event) = true; + int64 amount = 1; + aelf.Address from = 2; + aelf.Address to = 3; +} + +// An event that will be emitted from contract method call when Deposit is called. +message DepositEvent { + option (aelf.is_event) = true; + int64 amount = 1; + string symbol = 2; + aelf.Address from = 3; + aelf.Address to = 4; +} diff --git a/templates/NftSaleContract/test/Protobuf/stub/token_contract.proto b/templates/NftSaleContract/test/Protobuf/stub/token_contract.proto new file mode 100644 index 0000000..d632247 --- /dev/null +++ b/templates/NftSaleContract/test/Protobuf/stub/token_contract.proto @@ -0,0 +1,894 @@ +/** + * MultiToken contract. + */ +syntax = "proto3"; + +package token; + +import "aelf/core.proto"; +import "aelf/options.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; + +option csharp_namespace = "AElf.Contracts.MultiToken"; + +service TokenContract { + // Create a new token. + rpc Create (CreateInput) returns (google.protobuf.Empty) { + } + + // Issuing some amount of tokens to an address is the action of increasing that addresses balance + // for the given token. The total amount of issued tokens must not exceed the total supply of the token + // and only the issuer (creator) of the token can issue tokens. + // Issuing tokens effectively increases the circulating supply. + rpc Issue (IssueInput) returns (google.protobuf.Empty) { + } + + // Transferring tokens simply is the action of transferring a given amount of tokens from one address to another. + // The origin or source address is the signer of the transaction. + // The balance of the sender must be higher than the amount that is transferred. + rpc Transfer (TransferInput) returns (google.protobuf.Empty) { + } + + // The TransferFrom action will transfer a specified amount of tokens from one address to another. + // For this operation to succeed the from address needs to have approved (see allowances) enough tokens + // to Sender of this transaction. If successful the amount will be removed from the allowance. + rpc TransferFrom (TransferFromInput) returns (google.protobuf.Empty) { + } + + // The approve action increases the allowance from the Sender to the Spender address, + // enabling the Spender to call TransferFrom. + rpc Approve (ApproveInput) returns (google.protobuf.Empty) { + } + + rpc BatchApprove (BatchApproveInput) returns (google.protobuf.Empty) { + } + + // This is the reverse operation for Approve, it will decrease the allowance. + rpc UnApprove (UnApproveInput) returns (google.protobuf.Empty) { + } + + // This method can be used to lock tokens. + rpc Lock (LockInput) returns (google.protobuf.Empty) { + } + + // This is the reverse operation of locking, it un-locks some previously locked tokens. + rpc Unlock (UnlockInput) returns (google.protobuf.Empty) { + } + + // This action will burn the specified amount of tokens, removing them from the token’s Supply. + rpc Burn (BurnInput) returns (google.protobuf.Empty) { + } + + // Set the primary token of side chain. + rpc SetPrimaryTokenSymbol (SetPrimaryTokenSymbolInput) returns (google.protobuf.Empty) { + } + + // This interface is used for cross-chain transfer. + rpc CrossChainTransfer (CrossChainTransferInput) returns (google.protobuf.Empty) { + } + + // This method is used to receive cross-chain transfers. + rpc CrossChainReceiveToken (CrossChainReceiveTokenInput) returns (google.protobuf.Empty) { + } + + // The side chain creates tokens. + rpc CrossChainCreateToken(CrossChainCreateTokenInput) returns (google.protobuf.Empty) { + } + + // When the side chain is started, the side chain is initialized with the parent chain information. + rpc InitializeFromParentChain (InitializeFromParentChainInput) returns (google.protobuf.Empty) { + } + + // Handle the transaction fees charged by ChargeTransactionFees. + rpc ClaimTransactionFees (TotalTransactionFeesMap) returns (google.protobuf.Empty) { + } + + // Used to collect transaction fees. + rpc ChargeTransactionFees (ChargeTransactionFeesInput) returns (ChargeTransactionFeesOutput) { + } + + rpc ChargeUserContractTransactionFees(ChargeTransactionFeesInput) returns(ChargeTransactionFeesOutput){ + + } + + // Check the token threshold. + rpc CheckThreshold (CheckThresholdInput) returns (google.protobuf.Empty) { + } + + // Initialize coefficients of every type of tokens supporting charging fee. + rpc InitialCoefficients (google.protobuf.Empty) returns (google.protobuf.Empty){ + } + + // Processing resource token received. + rpc DonateResourceToken (TotalResourceTokensMaps) returns (google.protobuf.Empty) { + } + + // A transaction resource fee is charged to implement the ACS8 standards. + rpc ChargeResourceToken (ChargeResourceTokenInput) returns (google.protobuf.Empty) { + } + + // Verify that the resource token are sufficient. + rpc CheckResourceToken (google.protobuf.Empty) returns (google.protobuf.Empty) { + } + + // Set the list of tokens to pay transaction fees. + rpc SetSymbolsToPayTxSizeFee (SymbolListToPayTxSizeFee) returns (google.protobuf.Empty){ + } + + // Update the coefficient of the transaction fee calculation formula. + rpc UpdateCoefficientsForSender (UpdateCoefficientsInput) returns (google.protobuf.Empty) { + } + + // Update the coefficient of the transaction fee calculation formula. + rpc UpdateCoefficientsForContract (UpdateCoefficientsInput) returns (google.protobuf.Empty) { + } + + // This method is used to initialize the governance organization for some functions, + // including: the coefficient of the user transaction fee calculation formula, + // the coefficient of the contract developer resource fee calculation formula, and the side chain rental fee. + rpc InitializeAuthorizedController (google.protobuf.Empty) returns (google.protobuf.Empty){ + } + + rpc AddAddressToCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) { + } + rpc RemoveAddressFromCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) { + } + + rpc SetTransactionFeeDelegations (SetTransactionFeeDelegationsInput) returns (SetTransactionFeeDelegationsOutput){ + } + + rpc RemoveTransactionFeeDelegator (RemoveTransactionFeeDelegatorInput) returns (google.protobuf.Empty){ + } + + rpc RemoveTransactionFeeDelegatee (RemoveTransactionFeeDelegateeInput) returns (google.protobuf.Empty){ + } + + rpc SetSymbolAlias (SetSymbolAliasInput) returns (google.protobuf.Empty){ + } + + // Get all delegatees' address of delegator from input + rpc GetTransactionFeeDelegatees (GetTransactionFeeDelegateesInput) returns (GetTransactionFeeDelegateesOutput) { + option (aelf.is_view) = true; + } + + // Query token information. + rpc GetTokenInfo (GetTokenInfoInput) returns (TokenInfo) { + option (aelf.is_view) = true; + } + + // Query native token information. + rpc GetNativeTokenInfo (google.protobuf.Empty) returns (TokenInfo) { + option (aelf.is_view) = true; + } + + // Query resource token information. + rpc GetResourceTokenInfo (google.protobuf.Empty) returns (TokenInfoList) { + option (aelf.is_view) = true; + } + + // Query the balance at the specified address. + rpc GetBalance (GetBalanceInput) returns (GetBalanceOutput) { + option (aelf.is_view) = true; + } + + // Query the account's allowance for other addresses + rpc GetAllowance (GetAllowanceInput) returns (GetAllowanceOutput) { + option (aelf.is_view) = true; + } + + // Query the account's available allowance for other addresses + rpc GetAvailableAllowance (GetAllowanceInput) returns (GetAllowanceOutput) { + option (aelf.is_view) = true; + } + + // Check whether the token is in the whitelist of an address, + // which can be called TransferFrom to transfer the token under the condition of not being credited. + rpc IsInWhiteList (IsInWhiteListInput) returns (google.protobuf.BoolValue) { + option (aelf.is_view) = true; + } + + // Query the information for a lock. + rpc GetLockedAmount (GetLockedAmountInput) returns (GetLockedAmountOutput) { + option (aelf.is_view) = true; + } + + // Query the address of receiving token in cross-chain transfer. + rpc GetCrossChainTransferTokenContractAddress (GetCrossChainTransferTokenContractAddressInput) returns (aelf.Address) { + option (aelf.is_view) = true; + } + + // Query the name of the primary Token. + rpc GetPrimaryTokenSymbol (google.protobuf.Empty) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + // Query the coefficient of the transaction fee calculation formula. + rpc GetCalculateFeeCoefficientsForContract (google.protobuf.Int32Value) returns (CalculateFeeCoefficients) { + option (aelf.is_view) = true; + } + + // Query the coefficient of the transaction fee calculation formula. + rpc GetCalculateFeeCoefficientsForSender (google.protobuf.Empty) returns (CalculateFeeCoefficients) { + option (aelf.is_view) = true; + } + + // Query tokens that can pay transaction fees. + rpc GetSymbolsToPayTxSizeFee (google.protobuf.Empty) returns (SymbolListToPayTxSizeFee){ + option (aelf.is_view) = true; + } + + // Query the hash of the last input of ClaimTransactionFees. + rpc GetLatestTotalTransactionFeesMapHash (google.protobuf.Empty) returns (aelf.Hash){ + option (aelf.is_view) = true; + } + + // Query the hash of the last input of DonateResourceToken. + rpc GetLatestTotalResourceTokensMapsHash (google.protobuf.Empty) returns (aelf.Hash){ + option (aelf.is_view) = true; + } + rpc IsTokenAvailableForMethodFee (google.protobuf.StringValue) returns (google.protobuf.BoolValue) { + option (aelf.is_view) = true; + } + rpc GetReservedExternalInfoKeyList (google.protobuf.Empty) returns (StringList) { + option (aelf.is_view) = true; + } + + rpc GetTransactionFeeDelegationsOfADelegatee(GetTransactionFeeDelegationsOfADelegateeInput) returns(TransactionFeeDelegations){ + option (aelf.is_view) = true; + } + + rpc GetTokenAlias (google.protobuf.StringValue) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } + + rpc GetSymbolByAlias (google.protobuf.StringValue) returns (google.protobuf.StringValue) { + option (aelf.is_view) = true; + } +} + +message TokenInfo { + // The symbol of the token.f + string symbol = 1; + // The full name of the token. + string token_name = 2; + // The current supply of the token. + int64 supply = 3; + // The total supply of the token. + int64 total_supply = 4; + // The precision of the token. + int32 decimals = 5; + // The address that has permission to issue the token. + aelf.Address issuer = 6; + // A flag indicating if this token is burnable. + bool is_burnable = 7; + // The chain id of the token. + int32 issue_chain_id = 8; + // The amount of issued tokens. + int64 issued = 9; + // The external information of the token. + ExternalInfo external_info = 10; + // The address that owns the token. + aelf.Address owner = 11; +} + +message ExternalInfo { + map value = 1; +} + +message CreateInput { + // The symbol of the token. + string symbol = 1; + // The full name of the token. + string token_name = 2; + // The total supply of the token. + int64 total_supply = 3; + // The precision of the token + int32 decimals = 4; + // The address that has permission to issue the token. + aelf.Address issuer = 5; + // A flag indicating if this token is burnable. + bool is_burnable = 6; + // A whitelist address list used to lock tokens. + repeated aelf.Address lock_white_list = 7; + // The chain id of the token. + int32 issue_chain_id = 8; + // The external information of the token. + ExternalInfo external_info = 9; + // The address that owns the token. + aelf.Address owner = 10; +} + +message SetPrimaryTokenSymbolInput { + // The symbol of the token. + string symbol = 1; +} + +message IssueInput { + // The token symbol to issue. + string symbol = 1; + // The token amount to issue. + int64 amount = 2; + // The memo. + string memo = 3; + // The target address to issue. + aelf.Address to = 4; +} + +message TransferInput { + // The receiver of the token. + aelf.Address to = 1; + // The token symbol to transfer. + string symbol = 2; + // The amount to to transfer. + int64 amount = 3; + // The memo. + string memo = 4; +} + +message LockInput { + // The one want to lock his token. + aelf.Address address = 1; + // Id of the lock. + aelf.Hash lock_id = 2; + // The symbol of the token to lock. + string symbol = 3; + // a memo. + string usage = 4; + // The amount of tokens to lock. + int64 amount = 5; +} + +message UnlockInput { + // The one want to un-lock his token. + aelf.Address address = 1; + // Id of the lock. + aelf.Hash lock_id = 2; + // The symbol of the token to un-lock. + string symbol = 3; + // a memo. + string usage = 4; + // The amount of tokens to un-lock. + int64 amount = 5; +} + +message TransferFromInput { + // The source address of the token. + aelf.Address from = 1; + // The destination address of the token. + aelf.Address to = 2; + // The symbol of the token to transfer. + string symbol = 3; + // The amount to transfer. + int64 amount = 4; + // The memo. + string memo = 5; +} + +message ApproveInput { + // The address that allowance will be increased. + aelf.Address spender = 1; + // The symbol of token to approve. + string symbol = 2; + // The amount of token to approve. + int64 amount = 3; +} +message BatchApproveInput { + repeated ApproveInput value = 1; +} + +message UnApproveInput { + // The address that allowance will be decreased. + aelf.Address spender = 1; + // The symbol of token to un-approve. + string symbol = 2; + // The amount of token to un-approve. + int64 amount = 3; +} + +message BurnInput { + // The symbol of token to burn. + string symbol = 1; + // The amount of token to burn. + int64 amount = 2; +} + +message ChargeResourceTokenInput { + // Collection of charge resource token, Symbol->Amount. + map cost_dic = 1; + // The sender of the transaction. + aelf.Address caller = 2; +} + +message TransactionFeeBill { + // The transaction fee dictionary, Symbol->fee. + map fees_map = 1; +} + +message TransactionFreeFeeAllowanceBill { + // The transaction free fee allowance dictionary, Symbol->fee. + map free_fee_allowances_map = 1; +} + +message CheckThresholdInput { + // The sender of the transaction. + aelf.Address sender = 1; + // The threshold to set, Symbol->Threshold. + map symbol_to_threshold = 2; + // Whether to check the allowance. + bool is_check_allowance = 3; +} + +message GetTokenInfoInput { + // The symbol of token. + string symbol = 1; +} + +message GetBalanceInput { + // The symbol of token. + string symbol = 1; + // The target address of the query. + aelf.Address owner = 2; +} + +message GetBalanceOutput { + // The symbol of token. + string symbol = 1; + // The target address of the query. + aelf.Address owner = 2; + // The balance of the owner. + int64 balance = 3; +} + +message GetAllowanceInput { + // The symbol of token. + string symbol = 1; + // The address of the token owner. + aelf.Address owner = 2; + // The address of the spender. + aelf.Address spender = 3; +} + +message GetAllowanceOutput { + // The symbol of token. + string symbol = 1; + // The address of the token owner. + aelf.Address owner = 2; + // The address of the spender. + aelf.Address spender = 3; + // The amount of allowance. + int64 allowance = 4; +} + +message CrossChainTransferInput { + // The receiver of transfer. + aelf.Address to = 1; + // The symbol of token. + string symbol = 2; + // The amount of token to transfer. + int64 amount = 3; + // The memo. + string memo = 4; + // The destination chain id. + int32 to_chain_id = 5; + // The chain id of the token. + int32 issue_chain_id = 6; +} + +message CrossChainReceiveTokenInput { + // The source chain id. + int32 from_chain_id = 1; + // The height of the transfer transaction. + int64 parent_chain_height = 2; + // The raw bytes of the transfer transaction. + bytes transfer_transaction_bytes = 3; + // The merkle path created from the transfer transaction. + aelf.MerklePath merkle_path = 4; +} + +message IsInWhiteListInput { + // The symbol of token. + string symbol = 1; + // The address to check. + aelf.Address address = 2; +} + +message SymbolToPayTxSizeFee{ + // The symbol of token. + string token_symbol = 1; + // The charge weight of primary token. + int32 base_token_weight = 2; + // The new added token charge weight. For example, the charge weight of primary Token is set to 1. + // The newly added token charge weight is set to 10. If the transaction requires 1 unit of primary token, + // the user can also pay for 10 newly added tokens. + int32 added_token_weight = 3; +} + +message SymbolListToPayTxSizeFee{ + // Transaction fee token information. + repeated SymbolToPayTxSizeFee symbols_to_pay_tx_size_fee = 1; +} + +message ChargeTransactionFeesInput { + // The method name of transaction. + string method_name = 1; + // The contract address of transaction. + aelf.Address contract_address = 2; + // The amount of transaction size fee. + int64 transaction_size_fee = 3; + // Transaction fee token information. + repeated SymbolToPayTxSizeFee symbols_to_pay_tx_size_fee = 4; +} + +message ChargeTransactionFeesOutput { + // Whether the charge was successful. + bool success = 1; + // The charging information. + string charging_information = 2; +} + +message CallbackInfo { + aelf.Address contract_address = 1; + string method_name = 2; +} + +message ExtraTokenListModified { + option (aelf.is_event) = true; + // Transaction fee token information. + SymbolListToPayTxSizeFee symbol_list_to_pay_tx_size_fee = 1; +} + +message GetLockedAmountInput { + // The address of the lock. + aelf.Address address = 1; + // The token symbol. + string symbol = 2; + // The id of the lock. + aelf.Hash lock_id = 3; +} + +message GetLockedAmountOutput { + // The address of the lock. + aelf.Address address = 1; + // The token symbol. + string symbol = 2; + // The id of the lock. + aelf.Hash lock_id = 3; + // The locked amount. + int64 amount = 4; +} + +message TokenInfoList { + // List of token information. + repeated TokenInfo value = 1; +} + +message GetCrossChainTransferTokenContractAddressInput { + // The chain id. + int32 chainId = 1; +} + +message CrossChainCreateTokenInput { + // The chain id of the chain on which the token was created. + int32 from_chain_id = 1; + // The height of the transaction that created the token. + int64 parent_chain_height = 2; + // The transaction that created the token. + bytes transaction_bytes = 3; + // The merkle path created from the transaction that created the transaction. + aelf.MerklePath merkle_path = 4; +} + +message InitializeFromParentChainInput { + // The amount of resource. + map resource_amount = 1; + // The token contract addresses. + map registered_other_token_contract_addresses = 2; + // The creator the side chain. + aelf.Address creator = 3; +} + +message UpdateCoefficientsInput { + // The specify pieces gonna update. + repeated int32 piece_numbers = 1; + // Coefficients of one single type. + CalculateFeeCoefficients coefficients = 2; +} + +enum FeeTypeEnum { + READ = 0; + STORAGE = 1; + WRITE = 2; + TRAFFIC = 3; + TX = 4; +} + +message CalculateFeePieceCoefficients { + // Coefficients of one single piece. + // The first char is its type: liner / power. + // The second char is its piece upper bound. + repeated int32 value = 1; +} + +message CalculateFeeCoefficients { + // The resource fee type, like READ, WRITE, etc. + int32 fee_token_type = 1; + // Coefficients of one single piece. + repeated CalculateFeePieceCoefficients piece_coefficients_list = 2; +} + +message AllCalculateFeeCoefficients { + // The coefficients of fee Calculation. + repeated CalculateFeeCoefficients value = 1; +} + +message TotalTransactionFeesMap +{ + // Token dictionary that charge transaction fee, Symbol->Amount. + map value = 1; + // The hash of the block processing the transaction. + aelf.Hash block_hash = 2; + // The height of the block processing the transaction. + int64 block_height = 3; +} + +message TotalResourceTokensMaps { + // Resource tokens to charge. + repeated ContractTotalResourceTokens value = 1; + // The hash of the block processing the transaction. + aelf.Hash block_hash = 2; + // The height of the block processing the transaction. + int64 block_height = 3; +} + +message ContractTotalResourceTokens { + // The contract address. + aelf.Address contract_address = 1; + // Resource tokens to charge. + TotalResourceTokensMap tokens_map = 2; +} + +message TotalResourceTokensMap +{ + // Resource token dictionary, Symbol->Amount. + map value = 1; +} + +message StringList { + repeated string value = 1; +} + +message TransactionFeeDelegations{ + // delegation, symbols and its' amount + map delegations = 1; + // height when added + int64 block_height = 2; + //Whether to pay transaction fee continuously + bool isUnlimitedDelegate = 3; +} + +message TransactionFeeDelegatees{ + map delegatees = 1; +} + +message SetTransactionFeeDelegationsInput { + // the delegator address + aelf.Address delegator_address = 1; + // delegation, symbols and its' amount + map delegations = 2; +} + +message SetTransactionFeeDelegationsOutput { + bool success = 1; +} + +message RemoveTransactionFeeDelegatorInput{ + // the delegator address + aelf.Address delegator_address = 1; +} + +message RemoveTransactionFeeDelegateeInput { + // the delegatee address + aelf.Address delegatee_address = 1; +} + +message GetTransactionFeeDelegationsOfADelegateeInput { + aelf.Address delegatee_address = 1; + aelf.Address delegator_address = 2; +} + +message GetTransactionFeeDelegateesInput { + aelf.Address delegator_address = 1; +} + +message GetTransactionFeeDelegateesOutput { + repeated aelf.Address delegatee_addresses = 1; +} + +message SetSymbolAliasInput { + string symbol = 1; + string alias = 2; +} + +// Events + +message Transferred { + option (aelf.is_event) = true; + // The source address of the transferred token. + aelf.Address from = 1 [(aelf.is_indexed) = true]; + // The destination address of the transferred token. + aelf.Address to = 2 [(aelf.is_indexed) = true]; + // The symbol of the transferred token. + string symbol = 3 [(aelf.is_indexed) = true]; + // The amount of the transferred token. + int64 amount = 4; + // The memo. + string memo = 5; +} + +message Approved { + option (aelf.is_event) = true; + // The address of the token owner. + aelf.Address owner = 1 [(aelf.is_indexed) = true]; + // The address that allowance be increased. + aelf.Address spender = 2 [(aelf.is_indexed) = true]; + // The symbol of approved token. + string symbol = 3 [(aelf.is_indexed) = true]; + // The amount of approved token. + int64 amount = 4; +} + +message UnApproved { + option (aelf.is_event) = true; + // The address of the token owner. + aelf.Address owner = 1 [(aelf.is_indexed) = true]; + // The address that allowance be decreased. + aelf.Address spender = 2 [(aelf.is_indexed) = true]; + // The symbol of un-approved token. + string symbol = 3 [(aelf.is_indexed) = true]; + // The amount of un-approved token. + int64 amount = 4; +} + +message Burned +{ + option (aelf.is_event) = true; + // The address who wants to burn token. + aelf.Address burner = 1 [(aelf.is_indexed) = true]; + // The symbol of burned token. + string symbol = 2 [(aelf.is_indexed) = true]; + // The amount of burned token. + int64 amount = 3; +} + +message ChainPrimaryTokenSymbolSet { + option (aelf.is_event) = true; + // The symbol of token. + string token_symbol = 1; +} + +message CalculateFeeAlgorithmUpdated { + option (aelf.is_event) = true; + // All calculate fee coefficients after modification. + AllCalculateFeeCoefficients all_type_fee_coefficients = 1; +} + +message RentalCharged { + option (aelf.is_event) = true; + // The symbol of rental fee charged. + string symbol = 1; + // The amount of rental fee charged. + int64 amount = 2; + // The payer of rental fee. + aelf.Address payer = 3; + // The receiver of rental fee. + aelf.Address receiver = 4; +} + +message RentalAccountBalanceInsufficient { + option (aelf.is_event) = true; + // The symbol of insufficient rental account balance. + string symbol = 1; + // The balance of the account. + int64 amount = 2; +} + +message TokenCreated { + option (aelf.is_event) = true; + // The symbol of the token. + string symbol = 1; + // The full name of the token. + string token_name = 2; + // The total supply of the token. + int64 total_supply = 3; + // The precision of the token. + int32 decimals = 4; + // The address that has permission to issue the token. + aelf.Address issuer = 5; + // A flag indicating if this token is burnable. + bool is_burnable = 6; + // The chain id of the token. + int32 issue_chain_id = 7; + // The external information of the token. + ExternalInfo external_info = 8; + // The address that owns the token. + aelf.Address owner = 9; +} + +message Issued { + option (aelf.is_event) = true; + // The symbol of issued token. + string symbol = 1; + // The amount of issued token. + int64 amount = 2; + // The memo. + string memo = 3; + // The issued target address. + aelf.Address to = 4; +} + +message CrossChainTransferred { + option (aelf.is_event) = true; + // The source address of the transferred token. + aelf.Address from = 1; + // The destination address of the transferred token. + aelf.Address to = 2; + // The symbol of the transferred token. + string symbol = 3; + // The amount of the transferred token. + int64 amount = 4; + // The memo. + string memo = 5; + // The destination chain id. + int32 to_chain_id = 6; + // The chain id of the token. + int32 issue_chain_id = 7; +} + +message CrossChainReceived { + option (aelf.is_event) = true; + // The source address of the transferred token. + aelf.Address from = 1; + // The destination address of the transferred token. + aelf.Address to = 2; + // The symbol of the received token. + string symbol = 3; + // The amount of the received token. + int64 amount = 4; + // The memo. + string memo = 5; + // The destination chain id. + int32 from_chain_id = 6; + // The chain id of the token. + int32 issue_chain_id = 7; + // The parent chain height of the transfer transaction. + int64 parent_chain_height = 8; + // The id of transfer transaction. + aelf.Hash transfer_transaction_id =9; +} + +message TransactionFeeDelegationAdded { + option (aelf.is_event) = true; + aelf.Address delegator = 1 [(aelf.is_indexed) = true]; + aelf.Address delegatee = 2 [(aelf.is_indexed) = true]; + aelf.Address caller = 3 [(aelf.is_indexed) = true]; +} + +message TransactionFeeDelegationCancelled { + option (aelf.is_event) = true; + aelf.Address delegator = 1 [(aelf.is_indexed) = true]; + aelf.Address delegatee = 2 [(aelf.is_indexed) = true]; + aelf.Address caller = 3 [(aelf.is_indexed) = true]; +} + +message SymbolAliasAdded { + option (aelf.is_event) = true; + string symbol = 1 [(aelf.is_indexed) = true]; + string alias = 2 [(aelf.is_indexed) = true]; +} + +message SymbolAliasDeleted { + option (aelf.is_event) = true; + string symbol = 1 [(aelf.is_indexed) = true]; + string alias = 2 [(aelf.is_indexed) = true]; +} \ No newline at end of file diff --git a/templates/NftSaleContract/test/_Setup.cs b/templates/NftSaleContract/test/_Setup.cs new file mode 100644 index 0000000..7be808c --- /dev/null +++ b/templates/NftSaleContract/test/_Setup.cs @@ -0,0 +1,34 @@ +using AElf.Contracts.MultiToken; +using AElf.Cryptography.ECDSA; +using AElf.Testing.TestBase; + +namespace AElf.Contracts.NftSale +{ + // The Module class load the context required for unit testing + public class Module : ContractTestModule + { + + } + + // The TestBase class inherit ContractTestBase class, it defines Stub classes and gets instances required for unit testing + public class TestBase : ContractTestBase + { + // The Stub class for unit testing + internal readonly NftSaleContainer.NftSaleStub NftSaleStub; + internal readonly TokenContractContainer.TokenContractStub TokenContractStub; + // A key pair that can be used to interact with the contract instance + private ECKeyPair DefaultKeyPair => Accounts[0].KeyPair; + + public TestBase() + { + NftSaleStub = GetNftSaleContractStub(DefaultKeyPair); + TokenContractStub = GetTester(TokenContractAddress, DefaultKeyPair); + } + + private NftSaleContainer.NftSaleStub GetNftSaleContractStub(ECKeyPair senderKeyPair) + { + return GetTester(ContractAddress, senderKeyPair); + } + } + +} \ No newline at end of file