diff --git a/.gitignore b/.gitignore
index 86181d1c..cee95826 100644
--- a/.gitignore
+++ b/.gitignore
@@ -296,4 +296,6 @@ aelf.js
Contracts.manifest
# Contract patcher dlls
-chain/scripts/patcher/*
+scripts/patcher/*
+src/AElf.Boilerplate.Launcher/contracts/*
+test/patched/*
\ No newline at end of file
diff --git a/AElf.Contracts.PortAll.sln b/AElf.Contracts.PortAll.sln
index 76b7320a..e06f8585 100644
--- a/AElf.Contracts.PortAll.sln
+++ b/AElf.Contracts.PortAll.sln
@@ -16,8 +16,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Boilerplate.TestBase",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Oracle", "contract\AElf.Contracts.Oracle\AElf.Contracts.Oracle.csproj", "{AC06E580-EFC8-4D3F-BA4A-B2D2D1F65B9F}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AElf.Contracts.Oracle.Tests", "test\AElf.Contracts.Oracle.Tests\AElf.Contracts.Oracle.Tests.csproj", "{3631B538-C617-4FCE-9C9B-1D1B5F290A7F}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Boilerplate.ContractPatcher", "src\AElf.Boilerplate.ContractPatcher\AElf.Boilerplate.ContractPatcher.csproj", "{DCC207EA-842A-4B54-858B-295CAA8947D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.OracleUser", "contract\AElf.Contracts.OracleUser\AElf.Contracts.OracleUser.csproj", "{1A8F790C-4172-426C-83E3-2B49589782AB}"
@@ -46,11 +44,38 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenLockRec
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Lottery", "contract\AElf.Contracts.Lottery\AElf.Contracts.Lottery.csproj", "{BDB841AC-3230-4EBF-A735-EEF30CDE20ED}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Lottery.Tests", "test\AElf.Contracts.Lottery.Tests\AElf.Contracts.Lottery.Tests.csproj", "{073D711D-9F38-472D-ACE2-9830A222768C}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.TokenSwap", "src\AElf.TokenSwap\AElf.TokenSwap.csproj", "{AFFFAFFC-992F-4A88-95A8-C395D04B36D3}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Bridge.Tests", "test\AElf.Contracts.Bridge.Tests\AElf.Contracts.Bridge.Tests.csproj", "{463F5276-2D88-4A66-AA45-688F1920E1D7}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}"
+ ProjectSection(SolutionItems) = preProject
+ modules\AElf.Nethereum.Core\obj\Debug\net6.0\.NETCoreApp,Version = v6.0.AssemblyAttributes.cs = modules\AElf.Nethereum.Core\obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client", "modules\AElf.Client\AElf.Client.csproj", "{45B743E6-3B58-4AFA-9782-EA67015C9CD3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client.Core", "modules\AElf.Client.Core\AElf.Client.Core.csproj", "{8E6296BA-D3A6-4C23-837C-8A40A6BE3822}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client.Oracle", "modules\AElf.Client.Oracle\AElf.Client.Oracle.csproj", "{EA90104B-835D-4700-B0CD-93045173C033}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client.Protobuf", "modules\AElf.Client.Protobuf\AElf.Client.Protobuf.csproj", "{60CE45CF-3CF2-47DD-BE40-DB5585A5B0DE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client.Report", "modules\AElf.Client.Report\AElf.Client.Report.csproj", "{E4400680-1754-48A9-BEE9-8A6BC79302C2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client.MerkleTree", "modules\AElf.Client.MerkleTree\AElf.Client.MerkleTree.csproj", "{538194EF-9329-4C90-8BD9-0E6EFDFEF691}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Nethereum.Core", "modules\AElf.Nethereum.Core\AElf.Nethereum.Core.csproj", "{4175F31E-5ED6-4B67-973C-51B0C44BE74B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client.Bridge", "modules\AElf.Client.Bridge\AElf.Client.Bridge.csproj", "{ADD0EBAC-F957-4D59-AF43-C10D31DFB2DA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Nethereum.Bridge", "modules\AElf.Nethereum.Bridge\AElf.Nethereum.Bridge.csproj", "{1AC48421-CF85-44B9-B79A-6D41F8C09FF8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.BlockchainTransactionFee", "modules\AElf.BlockchainTransactionFee\AElf.BlockchainTransactionFee.csproj", "{0D9CCDEA-1E0B-4428-8DA7-F040CD971816}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.TokenPrice.Abstractions", "modules\AElf.TokenPrice.Abstractions\AElf.TokenPrice.Abstractions.csproj", "{F51259FD-7510-4166-8E96-C0C13DFA811F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.TokenPrice.CoinGecko", "modules\AElf.TokenPrice.CoinGecko\AElf.TokenPrice.CoinGecko.csproj", "{94EB8357-3CE0-4750-A167-8BCF7740BFB2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.PriceWorker", "src\AElf.PriceWorker\AElf.PriceWorker.csproj", "{63E22799-0213-42B3-A751-1592349180B9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -58,10 +83,6 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {3631B538-C617-4FCE-9C9B-1D1B5F290A7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3631B538-C617-4FCE-9C9B-1D1B5F290A7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3631B538-C617-4FCE-9C9B-1D1B5F290A7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3631B538-C617-4FCE-9C9B-1D1B5F290A7F}.Release|Any CPU.Build.0 = Release|Any CPU
{9484A7A9-CA57-4FF4-9FD8-27BFEF92EDBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9484A7A9-CA57-4FF4-9FD8-27BFEF92EDBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9484A7A9-CA57-4FF4-9FD8-27BFEF92EDBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -126,24 +147,67 @@ Global
{BDB841AC-3230-4EBF-A735-EEF30CDE20ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BDB841AC-3230-4EBF-A735-EEF30CDE20ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BDB841AC-3230-4EBF-A735-EEF30CDE20ED}.Release|Any CPU.Build.0 = Release|Any CPU
- {073D711D-9F38-472D-ACE2-9830A222768C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {073D711D-9F38-472D-ACE2-9830A222768C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {073D711D-9F38-472D-ACE2-9830A222768C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {073D711D-9F38-472D-ACE2-9830A222768C}.Release|Any CPU.Build.0 = Release|Any CPU
{AFFFAFFC-992F-4A88-95A8-C395D04B36D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFFFAFFC-992F-4A88-95A8-C395D04B36D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFFFAFFC-992F-4A88-95A8-C395D04B36D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AFFFAFFC-992F-4A88-95A8-C395D04B36D3}.Release|Any CPU.Build.0 = Release|Any CPU
- {463F5276-2D88-4A66-AA45-688F1920E1D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {463F5276-2D88-4A66-AA45-688F1920E1D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {463F5276-2D88-4A66-AA45-688F1920E1D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {463F5276-2D88-4A66-AA45-688F1920E1D7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {45B743E6-3B58-4AFA-9782-EA67015C9CD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {45B743E6-3B58-4AFA-9782-EA67015C9CD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {45B743E6-3B58-4AFA-9782-EA67015C9CD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {45B743E6-3B58-4AFA-9782-EA67015C9CD3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8E6296BA-D3A6-4C23-837C-8A40A6BE3822}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8E6296BA-D3A6-4C23-837C-8A40A6BE3822}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8E6296BA-D3A6-4C23-837C-8A40A6BE3822}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8E6296BA-D3A6-4C23-837C-8A40A6BE3822}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EA90104B-835D-4700-B0CD-93045173C033}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EA90104B-835D-4700-B0CD-93045173C033}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EA90104B-835D-4700-B0CD-93045173C033}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EA90104B-835D-4700-B0CD-93045173C033}.Release|Any CPU.Build.0 = Release|Any CPU
+ {60CE45CF-3CF2-47DD-BE40-DB5585A5B0DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {60CE45CF-3CF2-47DD-BE40-DB5585A5B0DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {60CE45CF-3CF2-47DD-BE40-DB5585A5B0DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {60CE45CF-3CF2-47DD-BE40-DB5585A5B0DE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E4400680-1754-48A9-BEE9-8A6BC79302C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E4400680-1754-48A9-BEE9-8A6BC79302C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E4400680-1754-48A9-BEE9-8A6BC79302C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E4400680-1754-48A9-BEE9-8A6BC79302C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {538194EF-9329-4C90-8BD9-0E6EFDFEF691}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {538194EF-9329-4C90-8BD9-0E6EFDFEF691}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {538194EF-9329-4C90-8BD9-0E6EFDFEF691}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {538194EF-9329-4C90-8BD9-0E6EFDFEF691}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4175F31E-5ED6-4B67-973C-51B0C44BE74B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4175F31E-5ED6-4B67-973C-51B0C44BE74B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4175F31E-5ED6-4B67-973C-51B0C44BE74B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4175F31E-5ED6-4B67-973C-51B0C44BE74B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ADD0EBAC-F957-4D59-AF43-C10D31DFB2DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ADD0EBAC-F957-4D59-AF43-C10D31DFB2DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ADD0EBAC-F957-4D59-AF43-C10D31DFB2DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ADD0EBAC-F957-4D59-AF43-C10D31DFB2DA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1AC48421-CF85-44B9-B79A-6D41F8C09FF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1AC48421-CF85-44B9-B79A-6D41F8C09FF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1AC48421-CF85-44B9-B79A-6D41F8C09FF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1AC48421-CF85-44B9-B79A-6D41F8C09FF8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0D9CCDEA-1E0B-4428-8DA7-F040CD971816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0D9CCDEA-1E0B-4428-8DA7-F040CD971816}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0D9CCDEA-1E0B-4428-8DA7-F040CD971816}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0D9CCDEA-1E0B-4428-8DA7-F040CD971816}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F51259FD-7510-4166-8E96-C0C13DFA811F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F51259FD-7510-4166-8E96-C0C13DFA811F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F51259FD-7510-4166-8E96-C0C13DFA811F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F51259FD-7510-4166-8E96-C0C13DFA811F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {94EB8357-3CE0-4750-A167-8BCF7740BFB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {94EB8357-3CE0-4750-A167-8BCF7740BFB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {94EB8357-3CE0-4750-A167-8BCF7740BFB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {94EB8357-3CE0-4750-A167-8BCF7740BFB2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {63E22799-0213-42B3-A751-1592349180B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {63E22799-0213-42B3-A751-1592349180B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {63E22799-0213-42B3-A751-1592349180B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {63E22799-0213-42B3-A751-1592349180B9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {3631B538-C617-4FCE-9C9B-1D1B5F290A7F} = {DBC47323-E6A2-42A2-A624-CE2EE6139567}
{AC06E580-EFC8-4D3F-BA4A-B2D2D1F65B9F} = {5C980166-C987-470D-AEE0-3858A170A903}
{F72731A8-5803-4362-834F-0C066E64D4CD} = {21D85A91-5BB8-4912-8107-49435A461AAC}
{DCC207EA-842A-4B54-858B-295CAA8947D5} = {21D85A91-5BB8-4912-8107-49435A461AAC}
@@ -160,9 +224,20 @@ Global
{4F30B2D8-432C-4686-81B5-9ADFE905B2B9} = {5C980166-C987-470D-AEE0-3858A170A903}
{B0145883-39B3-440E-9BA1-D80F13701E5C} = {5C980166-C987-470D-AEE0-3858A170A903}
{BDB841AC-3230-4EBF-A735-EEF30CDE20ED} = {5C980166-C987-470D-AEE0-3858A170A903}
- {073D711D-9F38-472D-ACE2-9830A222768C} = {DBC47323-E6A2-42A2-A624-CE2EE6139567}
{AFFFAFFC-992F-4A88-95A8-C395D04B36D3} = {21D85A91-5BB8-4912-8107-49435A461AAC}
- {463F5276-2D88-4A66-AA45-688F1920E1D7} = {DBC47323-E6A2-42A2-A624-CE2EE6139567}
+ {45B743E6-3B58-4AFA-9782-EA67015C9CD3} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {8E6296BA-D3A6-4C23-837C-8A40A6BE3822} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {EA90104B-835D-4700-B0CD-93045173C033} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {60CE45CF-3CF2-47DD-BE40-DB5585A5B0DE} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {E4400680-1754-48A9-BEE9-8A6BC79302C2} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {538194EF-9329-4C90-8BD9-0E6EFDFEF691} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {4175F31E-5ED6-4B67-973C-51B0C44BE74B} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {ADD0EBAC-F957-4D59-AF43-C10D31DFB2DA} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {1AC48421-CF85-44B9-B79A-6D41F8C09FF8} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {0D9CCDEA-1E0B-4428-8DA7-F040CD971816} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {F51259FD-7510-4166-8E96-C0C13DFA811F} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {94EB8357-3CE0-4750-A167-8BCF7740BFB2} = {FDE8EA32-0CD6-464B-A974-B6C3A3FB7039}
+ {63E22799-0213-42B3-A751-1592349180B9} = {21D85A91-5BB8-4912-8107-49435A461AAC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D7426B41-E959-40E4-9ED8-ED8D9C50F133}
diff --git a/CodeCoverage.runsettings b/CodeCoverage.runsettings
new file mode 100644
index 00000000..fca024f1
--- /dev/null
+++ b/CodeCoverage.runsettings
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ cobertura
+ [xunit.*]*,[*Tests]*
+ **/test/**/*.cs,**/AElf.ContractTestBase/**/*.cs,**/src/**/*.cs
+ Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute
+ false
+
+
+
+
+
diff --git a/README.md b/README.md
index 465b802c..b050fb4d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,11 @@
# PortAll
该repo中主要为与aelf预言机机制(或者port-all平台)或多或少相关的合约。
+BRANCH | AZURE PIPELINES | TESTS | CODE COVERAGE
+-------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------
+MAIN | [](https://dev.azure.com/portall-finance/port-all-contracts/_build/latest?definitionId=1&branchName=main) | [](https://dev.azure.com/portall-finance/port-all-contracts/_build/latest?definitionId=1&branchName=main) | [](https://codecov.io/gh/portall-finance/port-all-contracts)
+DEV | [](https://dev.azure.com/portall-finance/port-all-contracts/_build/latest?definitionId=1&branchName=dev) | [](https://dev.azure.com/portall-finance/port-all-contracts/_build/latest?definitionId=1&branchName=dev) | [](https://codecov.io/gh/portall-finance/port-all-contracts)
+
## 预言机合约
### [Regiment合约](https://github.com/PortAllProject/port-all-contracts/tree/dev/contract/AElf.Contracts.Regiment)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
new file mode 100644
index 00000000..e8e83974
--- /dev/null
+++ b/azure-pipelines.yml
@@ -0,0 +1,102 @@
+jobs:
+# All tasks on Windows....
+- job: build_all_windows
+ displayName: Build all tasks (Windows)
+ timeoutInMinutes: 120
+ pool:
+ vmImage: windows-latest
+ variables:
+ CI_TEST: true
+ steps:
+ - task: UseDotNet@2
+ displayName: 'Install .NET Core SDK'
+ inputs:
+ version: 6.0.x
+ - script: choco install protoc --version=3.19.4 -y
+ displayName: 'Install protobuf'
+ - script: choco install unzip
+ displayName: 'Install unzip'
+ - task: BatchScript@1
+ displayName: 'Download AElf build tools'
+ inputs:
+ filename: 'scripts/download_binary.bat'
+ - script: PowerShell.exe -file build.ps1 -target=Build
+ displayName: 'Build and Test'
+ - task: PublishTestResults@2
+ condition: always()
+ inputs:
+ testRunner: VSTest
+ testResultsFiles: '**/*.trx'
+
+# - task: reportgenerator@5
+# displayName: ReportGenerator
+# inputs:
+# reports: '$(Build.SourcesDirectory)/test/*/TestResults/*/coverage.cobertura.xml'
+# targetdir: '$(Build.SourcesDirectory)/CodeCoverage'
+# reporttypes: 'Cobertura'
+# assemblyfilters: '-xunit*'
+# - script: PowerShell.exe -file build.ps1 -target=Upload-Coverage-Azure
+# displayName: 'Upload data to Codecov'
+# All tasks on Linux
+- job: build_all_linux
+ displayName: Build all tasks (Linux)
+ timeoutInMinutes: 120
+ pool:
+ vmImage: ubuntu-latest
+ steps:
+ - task: UseDotNet@2
+ displayName: 'Install .NET Core SDK'
+ inputs:
+ version: 6.0.x
+ - script: bash scripts/install_protobuf.sh
+ - script: bash scripts/download_binary.sh
+ - script: bash build.sh -target=Build
+ displayName: 'Build and Test'
+ - task: PublishTestResults@2
+ condition: always()
+ inputs:
+ testRunner: VSTest
+ testResultsFiles: '**/*.trx'
+
+# - task: reportgenerator@5
+# displayName: ReportGenerator
+# inputs:
+# reports: '$(Build.SourcesDirectory)/test/*/TestResults/*/coverage.cobertura.xml'
+# targetdir: '$(Build.SourcesDirectory)/CodeCoverage'
+# reporttypes: 'Cobertura'
+# assemblyfilters: '-xunit*'
+# - script: bash build.sh -target=Upload-Coverage-Azure
+# displayName: 'Upload data to Codecov'
+
+# All tasks on macOS
+- job: build_all_darwin
+ displayName: Build all tasks (macOS)
+ timeoutInMinutes: 120
+ pool:
+ vmImage: macos-latest
+ variables:
+ CI_TEST: true
+ steps:
+ - task: UseDotNet@2
+ displayName: 'Install .NET Core SDK'
+ inputs:
+ version: 6.0.x
+ - script: bash scripts/install_protobuf.sh
+ - script: bash scripts/download_binary.sh
+ - script: bash build.sh -target=Build
+ displayName: 'Build and Test'
+ - task: PublishTestResults@2
+ condition: always()
+ inputs:
+ testRunner: VSTest
+ testResultsFiles: '**/*.trx'
+
+# - task: reportgenerator@5
+# displayName: ReportGenerator
+# inputs:
+# reports: '$(Build.SourcesDirectory)/test/*/TestResults/*/coverage.cobertura.xml'
+# targetdir: '$(Build.SourcesDirectory)/CodeCoverage'
+# reporttypes: 'Cobertura'
+# assemblyfilters: '-xunit*'
+# - script: bash build.sh -target=Upload-Coverage-Azure
+# displayName: 'Upload data to Codecov'
diff --git a/build.cake b/build.cake
new file mode 100755
index 00000000..109f173d
--- /dev/null
+++ b/build.cake
@@ -0,0 +1,225 @@
+#tool nuget:?package=Codecov
+#addin nuget:?package=Cake.Codecov&version=0.8.0
+var target = Argument("target", "Default");
+var configuration = Argument("configuration", "Debug");
+var rootPath = "./";
+var srcPath = rootPath + "src/";
+var contractPath = rootPath + "contract/";
+var testPath = rootPath + "test/";
+var distPath = rootPath + "aelf-node/";
+var solution = rootPath + "AElf.Contracts.PortAll.sln";
+var srcProjects = GetFiles(srcPath + "**/*.csproj");
+var contractProjects = GetFiles(contractPath + "**/*.csproj");
+
+
+Task("Clean")
+ .Description("clean up project cache")
+ .Does(() =>
+{
+ DeleteFiles(distPath + "*.nupkg");
+ CleanDirectories(srcPath + "**/bin");
+ CleanDirectories(srcPath + "**/obj");
+ CleanDirectories(contractPath + "**/bin");
+ CleanDirectories(contractPath + "**/obj");
+ CleanDirectories(testPath + "**/bin");
+ CleanDirectories(testPath + "**/obj");
+});
+
+Task("Restore")
+ .Description("restore project dependencies")
+ .Does(() =>
+{
+ var restoreSettings = new DotNetCoreRestoreSettings{
+ ArgumentCustomization = args => {
+ return args.Append("-v quiet");}
+};
+ DotNetCoreRestore(solution,restoreSettings);
+});
+Task("Build")
+ .Description("Compilation project")
+ .IsDependentOn("Clean")
+ .IsDependentOn("Restore")
+ .Does(() =>
+{
+ var buildSetting = new DotNetCoreBuildSettings{
+ Configuration = configuration,
+ NoRestore = true,
+ ArgumentCustomization = args => {
+ return args.Append("/clp:ErrorsOnly")
+ .Append("/p:GeneratePackageOnBuild=false")
+ .Append("-v quiet");}
+ };
+
+ DotNetCoreBuild(solution, buildSetting);
+});
+Task("Build-Release")
+ .Description("Compilation project")
+ .IsDependentOn("Clean")
+ .IsDependentOn("Restore")
+ .Does(() =>
+{ var versionPrefix = EnvironmentVariable("MYGET_VERSION_PREFIX");
+ var buildVersion = (DateTime.UtcNow.Ticks - 621355968000000000) / 10000000 / 86400;
+ var buildSetting = new DotNetCoreBuildSettings{
+ NoRestore = true,
+ Configuration = "Release",
+ ArgumentCustomization = args => {
+ return args.Append("/clp:ErrorsOnly")
+ .Append("-v quiet")
+ .Append($"-P:Version={versionPrefix}-{buildVersion}")
+ .Append("-P:Authors=AElf")
+ .Append("-o ./nuget")
+;}
+ };
+
+ DotNetCoreBuild(solution, buildSetting);
+});
+
+Task("Test-with-Codecov")
+ .Description("operation test_with_codecov")
+ .IsDependentOn("Build")
+ .Does(() =>
+{
+ var testSetting = new DotNetCoreTestSettings{
+ Configuration = configuration,
+ NoRestore = true,
+ NoBuild = true,
+ ArgumentCustomization = args => {
+ return args
+ .Append("--logger trx")
+ .Append("--settings CodeCoverage.runsettings")
+ .Append("--collect:\"XPlat Code Coverage\"");
+ }
+ };
+ var codecovToken = "$CODECOV_TOKEN";
+ var actions = new List();
+ var testProjects = GetFiles("./test/*.Tests/*.csproj");
+
+ foreach(var testProject in testProjects)
+ {
+ var action=new Action(()=>{
+ DotNetCoreTest(testProject.FullPath, testSetting);
+
+ // if(codecovToken!=""){
+ // var dir=testProject.GetDirectory().FullPath;
+ // var reports = GetFiles(dir + "/TestResults/*/coverage.cobertura.xml");
+
+ // foreach(var report in reports)
+ // {
+ // Codecov(report.FullPath,"$CODECOV_TOKEN");
+ // }
+ // }
+ });
+ actions.Add(action);
+ }
+
+
+ var options = new ParallelOptions {
+ MaxDegreeOfParallelism = 1,
+ //CancellationToken = cancellationToken
+ };
+
+ Parallel.Invoke(options, actions.ToArray());
+});
+
+Task("Test-with-Codecov-N")
+ .Description("operation test_with_codecov")
+ .IsDependentOn("Build")
+ .Does(() =>
+{
+ var testSetting = new DotNetCoreTestSettings{
+ Configuration = configuration,
+ NoRestore = true,
+ NoBuild = true,
+ ArgumentCustomization = args => {
+ return args
+ .Append("--logger trx")
+ .Append("--settings CodeCoverage.runsettings")
+ .Append("--collect:\"XPlat Code Coverage\"");
+ }
+ };
+ var testSetting_nocoverage = new DotNetCoreTestSettings{
+ NoRestore = true,
+ NoBuild = true,
+ ArgumentCustomization = args => {
+ return args
+ .Append("--logger trx");
+ }
+ };
+ var codecovToken = "$CODECOV_TOKEN";
+ var actions = new List();
+ var testProjects = GetFiles("./test/*.Tests/*.csproj");
+ var testProjectList = testProjects.OrderBy(p=>p.FullPath).ToList();
+ var n = Argument("n",1);
+ var parts = Argument("parts",1);
+
+ Information($"n:{n}, parts:{parts}");
+ int i=0;
+ foreach(var testProject in testProjectList)
+ {
+ if(i++ % parts == n - 1){
+ DotNetCoreTest(testProject.FullPath, testSetting);
+ }else{
+ DotNetCoreTest(testProject.FullPath, testSetting_nocoverage);
+ }
+ }
+});
+
+Task("Run-Unit-Tests")
+ .Description("operation test")
+ .IsDependentOn("Build")
+ .Does(() =>
+{
+ var testSetting = new DotNetCoreTestSettings{
+ Configuration = configuration,
+ NoRestore = true,
+ NoBuild = true,
+ ArgumentCustomization = args => {
+ return args.Append("--logger trx");
+ }
+};
+ var testProjects = GetFiles("./test/*.Tests/*.csproj");
+
+
+ foreach(var testProject in testProjects)
+ {
+ DotNetCoreTest(testProject.FullPath, testSetting);
+ }
+});
+Task("Upload-Coverage")
+ .Does(() =>
+{
+ var reports = GetFiles("./test/*.Tests/TestResults/*/coverage.cobertura.xml");
+
+ foreach(var report in reports)
+ {
+ Codecov(report.FullPath,"$CODECOV_TOKEN");
+ }
+});
+Task("Upload-Coverage-Azure")
+ .Does(() =>
+{
+ Codecov("./CodeCoverage/Cobertura.xml","$CODECOV_TOKEN");
+});
+Task("Publish-MyGet")
+ .IsDependentOn("Build-Release")
+ .Does(() => {
+ var apiKey = EnvironmentVariable("MYGET_API_KEY");
+ var pushSettings = new DotNetCoreNuGetPushSettings
+ {
+ Source = "https://www.myget.org/F/aelf-project-dev/api/v3/index.json",
+ ApiKey = apiKey
+
+ };
+
+ var pkgs = GetFiles("./nuget/*.nupkg");
+ foreach(var pkg in pkgs)
+ {
+ Information($"Publishing \"{pkg}\".");
+ DotNetCoreNuGetPush(pkg.FullPath, pushSettings);
+ }
+ });
+Task("Default")
+ .IsDependentOn("Run-Unit-Tests");
+
+RunTarget(target);
+
diff --git a/build.config b/build.config
new file mode 100644
index 00000000..015ef8ec
--- /dev/null
+++ b/build.config
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+CAKE_VERSION=0.37.0
+DOTNET_VERSION=6.0.300
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 00000000..e48d09a0
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,154 @@
+#!/usr/bin/env pwsh
+$DotNetInstallerUri = 'https://dot.net/v1/dotnet-install.ps1';
+$DotNetUnixInstallerUri = 'https://dot.net/v1/dotnet-install.sh'
+$DotNetChannel = 'LTS'
+$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
+
+[string] $CakeVersion = ''
+[string] $DotNetVersion= ''
+foreach($line in Get-Content (Join-Path $PSScriptRoot 'build.config'))
+{
+ if ($line -like 'CAKE_VERSION=*') {
+ $CakeVersion = $line.SubString(13)
+ }
+ elseif ($line -like 'DOTNET_VERSION=*') {
+ $DotNetVersion =$line.SubString(15)
+ }
+}
+
+
+if ([string]::IsNullOrEmpty($CakeVersion) -or [string]::IsNullOrEmpty($DotNetVersion)) {
+ 'Failed to parse Cake / .NET Core SDK Version'
+ exit 1
+}
+
+# Make sure tools folder exists
+$ToolPath = Join-Path $PSScriptRoot "tools"
+if (!(Test-Path $ToolPath)) {
+ Write-Verbose "Creating tools directory..."
+ New-Item -Path $ToolPath -Type Directory -Force | out-null
+}
+
+
+if ($PSVersionTable.PSEdition -ne 'Core') {
+ # Attempt to set highest encryption available for SecurityProtocol.
+ # PowerShell will not set this by default (until maybe .NET 4.6.x). This
+ # will typically produce a message for PowerShell v2 (just an info
+ # message though)
+ try {
+ # Set TLS 1.2 (3072), then TLS 1.1 (768), then TLS 1.0 (192), finally SSL 3.0 (48)
+ # Use integers because the enumeration values for TLS 1.2 and TLS 1.1 won't
+ # exist in .NET 4.0, even though they are addressable if .NET 4.5+ is
+ # installed (.NET 4.5 is an in-place upgrade).
+ [System.Net.ServicePointManager]::SecurityProtocol = 3072 -bor 768 -bor 192 -bor 48
+ } catch {
+ Write-Output 'Unable to set PowerShell to use TLS 1.2 and TLS 1.1 due to old .NET Framework installed. If you see underlying connection closed or trust errors, you may need to upgrade to .NET Framework 4.5+ and PowerShell v3'
+ }
+}
+
+###########################################################################
+# INSTALL .NET CORE CLI
+###########################################################################
+
+$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+$env:DOTNET_CLI_TELEMETRY_OPTOUT=1
+$env:DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=2
+
+
+Function Remove-PathVariable([string]$VariableToRemove)
+{
+ $SplitChar = ';'
+ if ($IsMacOS -or $IsLinux) {
+ $SplitChar = ':'
+ }
+
+ $path = [Environment]::GetEnvironmentVariable("PATH", "User")
+ if ($path -ne $null)
+ {
+ $newItems = $path.Split($SplitChar, [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove }
+ [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join($SplitChar, $newItems), "User")
+ }
+
+ $path = [Environment]::GetEnvironmentVariable("PATH", "Process")
+ if ($path -ne $null)
+ {
+ $newItems = $path.Split($SplitChar, [StringSplitOptions]::RemoveEmptyEntries) | Where-Object { "$($_)" -inotlike $VariableToRemove }
+ [Environment]::SetEnvironmentVariable("PATH", [System.String]::Join($SplitChar, $newItems), "Process")
+ }
+}
+
+# Get .NET Core CLI path if installed.
+$FoundDotNetCliVersion = $null;
+if (Get-Command dotnet -ErrorAction SilentlyContinue) {
+ $FoundDotNetCliVersion = dotnet --version;
+}
+
+if($FoundDotNetCliVersion -ne $DotNetVersion) {
+ $InstallPath = Join-Path $PSScriptRoot ".dotnet"
+ if (!(Test-Path $InstallPath)) {
+ New-Item -Path $InstallPath -ItemType Directory -Force | Out-Null;
+ }
+
+ if ($IsMacOS -or $IsLinux) {
+ $ScriptPath = Join-Path $InstallPath 'dotnet-install.sh'
+ (New-Object System.Net.WebClient).DownloadFile($DotNetUnixInstallerUri, $ScriptPath);
+ & bash $ScriptPath --version "$DotNetVersion" --install-dir "$InstallPath" --channel "$DotNetChannel" --no-path
+
+ Remove-PathVariable "$InstallPath"
+ $env:PATH = "$($InstallPath):$env:PATH"
+ }
+ else {
+ $ScriptPath = Join-Path $InstallPath 'dotnet-install.ps1'
+ (New-Object System.Net.WebClient).DownloadFile($DotNetInstallerUri, $ScriptPath);
+ & $ScriptPath -Channel $DotNetChannel -Version $DotNetVersion -InstallDir $InstallPath;
+
+ Remove-PathVariable "$InstallPath"
+ $env:PATH = "$InstallPath;$env:PATH"
+ }
+ $env:DOTNET_ROOT=$InstallPath
+}
+
+###########################################################################
+# INSTALL CAKE
+###########################################################################
+
+# Make sure Cake has been installed.
+[string] $CakeExePath = ''
+[string] $CakeInstalledVersion = Get-Command dotnet-cake -ErrorAction SilentlyContinue | % {&$_.Source --version}
+
+if ($CakeInstalledVersion -eq $CakeVersion) {
+ # Cake found locally
+ $CakeExePath = (Get-Command dotnet-cake).Source
+}
+else {
+ $CakePath = [System.IO.Path]::Combine($ToolPath,'.store', 'cake.tool', $CakeVersion) # Old PowerShell versions Join-Path only supports one child path
+
+ $CakeExePath = (Get-ChildItem -Path $ToolPath -Filter "dotnet-cake*" -File| ForEach-Object FullName | Select-Object -First 1)
+
+
+ if ((!(Test-Path -Path $CakePath -PathType Container)) -or (!(Test-Path $CakeExePath -PathType Leaf))) {
+
+ if ((![string]::IsNullOrEmpty($CakeExePath)) -and (Test-Path $CakeExePath -PathType Leaf))
+ {
+ & dotnet tool uninstall --tool-path $ToolPath Cake.Tool
+ }
+
+ & dotnet tool install --tool-path $ToolPath --version $CakeVersion Cake.Tool
+ if ($LASTEXITCODE -ne 0)
+ {
+ 'Failed to install cake'
+ exit 1
+ }
+ $CakeExePath = (Get-ChildItem -Path $ToolPath -Filter "dotnet-cake*" -File| ForEach-Object FullName | Select-Object -First 1)
+ }
+}
+
+###########################################################################
+# RUN BUILD SCRIPT
+###########################################################################
+& "$CakeExePath" ./build.cake --bootstrap
+if ($LASTEXITCODE -eq 0)
+{
+ & "$CakeExePath" ./build.cake $args
+}
+exit $LASTEXITCODE
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100755
index 00000000..06bcee80
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,75 @@
+#!/usr/bin/env bash
+# Define varibles
+SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+source $SCRIPT_DIR/build.config
+TOOLS_DIR=$SCRIPT_DIR/tools
+CAKE_EXE=$TOOLS_DIR/dotnet-cake
+CAKE_PATH=$TOOLS_DIR/.store/cake.tool/$CAKE_VERSION
+
+if [ "$CAKE_VERSION" = "" ] || [ "$DOTNET_VERSION" = "" ]; then
+ echo "An error occured while parsing Cake / .NET Core SDK version."
+ exit 1
+fi
+
+# Make sure the tools folder exist.
+if [ ! -d "$TOOLS_DIR" ]; then
+ mkdir "$TOOLS_DIR"
+fi
+
+###########################################################################
+# INSTALL .NET CORE CLI
+###########################################################################
+
+export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+export DOTNET_CLI_TELEMETRY_OPTOUT=1
+export DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0
+export DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=2
+
+DOTNET_INSTALLED_VERSION=$(dotnet --version 2>&1)
+
+if [ "$DOTNET_VERSION" != "$DOTNET_INSTALLED_VERSION" ]; then
+ echo "Installing .NET CLI..."
+ if [ ! -d "$SCRIPT_DIR/.dotnet" ]; then
+ mkdir "$SCRIPT_DIR/.dotnet"
+ fi
+ curl -Lsfo "$SCRIPT_DIR/.dotnet/dotnet-install.sh" https://dot.net/v1/dotnet-install.sh
+ bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --version $DOTNET_VERSION --install-dir .dotnet --no-path
+ export PATH="$SCRIPT_DIR/.dotnet":$PATH
+ export DOTNET_ROOT="$SCRIPT_DIR/.dotnet"
+fi
+
+###########################################################################
+# INSTALL CAKE
+###########################################################################
+
+CAKE_INSTALLED_VERSION=$(dotnet-cake --version 2>&1)
+
+if [ "$CAKE_VERSION" != "$CAKE_INSTALLED_VERSION" ]; then
+ if [ ! -f "$CAKE_EXE" ] || [ ! -d "$CAKE_PATH" ]; then
+ if [ -f "$CAKE_EXE" ]; then
+ dotnet tool uninstall --tool-path $TOOLS_DIR Cake.Tool
+ fi
+
+ echo "Installing Cake $CAKE_VERSION..."
+ dotnet tool install --tool-path $TOOLS_DIR --version $CAKE_VERSION Cake.Tool
+ if [ $? -ne 0 ]; then
+ echo "An error occured while installing Cake."
+ exit 1
+ fi
+ fi
+
+ # Make sure that Cake has been installed.
+ if [ ! -f "$CAKE_EXE" ]; then
+ echo "Could not find Cake.exe at '$CAKE_EXE'."
+ exit 1
+ fi
+else
+ CAKE_EXE="dotnet-cake"
+fi
+
+###########################################################################
+# RUN BUILD SCRIPT
+###########################################################################
+
+# Start Cake
+(exec "$CAKE_EXE" build.cake --bootstrap) && (exec "$CAKE_EXE" build.cake "$@")
\ No newline at end of file
diff --git a/codecov.sh b/codecov.sh
new file mode 100755
index 00000000..6b97c5b6
--- /dev/null
+++ b/codecov.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+TOKEN=$1
+rm -r ./test/*.Tests/TestResults
+rm -r CodeCoverage
+for name in `ls ./test/*.Tests/*.csproj | awk '{print $NF}'`;
+do
+ echo ${name}
+ dotnet test ${name} --logger trx --settings CodeCoverage.runsettings --collect:"XPlat Code Coverage"
+done
+reportgenerator /test/*/TestResults/*/coverage.cobertura.xml -reports:./test/*/TestResults/*/coverage.cobertura.xml -targetdir:./CodeCoverage -reporttypes:Cobertura -assemblyfilters:-xunit*
+codecov -f ./CodeCoverage/Cobertura.xml -t ${TOKEN}
\ No newline at end of file
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 00000000..13395c9c
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,3 @@
+codecov:
+ notify:
+ after_n_builds: 1
\ No newline at end of file
diff --git a/modules/AElf.BlockchainTransactionFee/AElf.BlockchainTransactionFee.csproj b/modules/AElf.BlockchainTransactionFee/AElf.BlockchainTransactionFee.csproj
new file mode 100644
index 00000000..a3adf259
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/AElf.BlockchainTransactionFee.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/modules/AElf.BlockchainTransactionFee/AElfBlockchainTransactionFeeModule.cs b/modules/AElf.BlockchainTransactionFee/AElfBlockchainTransactionFeeModule.cs
new file mode 100644
index 00000000..456511a2
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/AElfBlockchainTransactionFeeModule.cs
@@ -0,0 +1,19 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Caching;
+using Volo.Abp.Modularity;
+
+namespace AElf.BlockchainTransactionFee
+{
+ [DependsOn(typeof(AbpCachingModule))]
+ public class AElfBlockchainTransactionFeeModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+ Configure(configuration.GetSection("ChainExplorerApi"));
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.BlockchainTransactionFee/ApiClient.cs b/modules/AElf.BlockchainTransactionFee/ApiClient.cs
new file mode 100644
index 00000000..875964e5
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/ApiClient.cs
@@ -0,0 +1,32 @@
+using System.Net;
+using System.Text.Json;
+using Newtonsoft.Json;
+
+namespace AElf.BlockchainTransactionFee;
+
+public class ApiClient
+{
+ private readonly HttpClient _httpClient;
+
+ public ApiClient()
+ {
+ _httpClient = new HttpClient();
+ }
+
+ public async Task GetAsync(string uri)
+ {
+ var response = await _httpClient.GetAsync(uri)
+ .ConfigureAwait(false);
+ response.EnsureSuccessStatusCode();
+
+ var responseContent = await response.Content.ReadAsStringAsync();
+ try
+ {
+ return JsonConvert.DeserializeObject(responseContent);
+ }
+ catch (Exception e)
+ {
+ throw new HttpRequestException(e.Message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.BlockchainTransactionFee/BSCTransactionFeeProvider.cs b/modules/AElf.BlockchainTransactionFee/BSCTransactionFeeProvider.cs
new file mode 100644
index 00000000..81d30935
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/BSCTransactionFeeProvider.cs
@@ -0,0 +1,52 @@
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.BlockchainTransactionFee;
+
+public class BSCTransactionFeeProvider : IBlockchainTransactionFeeProvider
+{
+ public string BlockChain { get; } = "BSC";
+
+ private readonly ApiClient _apiClient;
+
+ private readonly ChainExplorerApiOptions _chainExplorerApiOptions;
+
+ public BSCTransactionFeeProvider(ApiClient apiClient,
+ IOptionsSnapshot blockchainExplorerApiOptions)
+ {
+ _apiClient = apiClient;
+ _chainExplorerApiOptions = blockchainExplorerApiOptions.Value;
+ }
+
+ public async Task GetTransactionFee()
+ {
+ var result = await _apiClient.GetAsync>(
+ $"https://api.bscscan.com/api?module=gastracker&action=gasoracle&apikey={_chainExplorerApiOptions.ApiKeys[BlockChain]}");
+ if (result.Message != "OK")
+ {
+ throw new HttpRequestException($"BSC api failed: {result.Message}");
+ }
+
+ return new TransactionFeeDto
+ {
+ Symbol = "BNB",
+ Fee = decimal.Parse(result.Result.SafeGasPrice)
+ };
+ }
+}
+
+public class BSCApiResult
+{
+ public string Message { get; set; }
+
+ public T Result { get; set; }
+}
+
+public class BSCGasTracker
+{
+ public string FastGasPrice { get; set; }
+ public string LastBlock { get; set; }
+ public string ProposeGasPrice { get; set; }
+ public string SafeGasPrice { get; set; }
+ public string UsdPrice { get; set; }
+}
\ No newline at end of file
diff --git a/modules/AElf.BlockchainTransactionFee/ChainExplorerApiOptions.cs b/modules/AElf.BlockchainTransactionFee/ChainExplorerApiOptions.cs
new file mode 100644
index 00000000..a49af71b
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/ChainExplorerApiOptions.cs
@@ -0,0 +1,6 @@
+namespace AElf.BlockchainTransactionFee;
+
+public class ChainExplorerApiOptions
+{
+ public Dictionary ApiKeys { get; set; } = new();
+}
\ No newline at end of file
diff --git a/modules/AElf.BlockchainTransactionFee/EthereumTransactionFeeProvider.cs b/modules/AElf.BlockchainTransactionFee/EthereumTransactionFeeProvider.cs
new file mode 100644
index 00000000..b7043e0d
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/EthereumTransactionFeeProvider.cs
@@ -0,0 +1,51 @@
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.BlockchainTransactionFee;
+
+public class EthereumTransactionFeeProvider : IBlockchainTransactionFeeProvider
+{
+ public string BlockChain { get; } = "Ethereum";
+
+ private readonly ApiClient _apiClient;
+
+ private readonly ChainExplorerApiOptions _chainExplorerApiOptions;
+
+ public EthereumTransactionFeeProvider(ApiClient apiClient,
+ IOptionsSnapshot blockchainExplorerApiOptions)
+ {
+ _apiClient = apiClient;
+ _chainExplorerApiOptions = blockchainExplorerApiOptions.Value;
+ }
+
+ public async Task GetTransactionFee()
+ {
+ var result = await _apiClient.GetAsync>(
+ $"https://api.etherscan.io/api?module=gastracker&action=gasoracle&apikey={_chainExplorerApiOptions.ApiKeys[BlockChain]}");
+ if (result.Message != "OK")
+ {
+ throw new HttpRequestException($"Ethereum api failed: {result.Message}");
+ }
+
+ return new TransactionFeeDto
+ {
+ Symbol = "ETH",
+ Fee = decimal.Parse(result.Result.SafeGasPrice)
+ };
+ }
+}
+
+public class EthereumApiResult
+{
+ public string Message { get; set; }
+
+ public T Result { get; set; }
+}
+
+public class EthereumGasTracker
+{
+ public string FastGasPrice { get; set; }
+ public string LastBlock { get; set; }
+ public string ProposeGasPrice { get; set; }
+ public string SafeGasPrice { get; set; }
+}
\ No newline at end of file
diff --git a/modules/AElf.BlockchainTransactionFee/IBlockchainTransactionFeeProvider.cs b/modules/AElf.BlockchainTransactionFee/IBlockchainTransactionFeeProvider.cs
new file mode 100644
index 00000000..718177af
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/IBlockchainTransactionFeeProvider.cs
@@ -0,0 +1,7 @@
+namespace AElf.BlockchainTransactionFee;
+
+public interface IBlockchainTransactionFeeProvider
+{
+ string BlockChain { get; }
+ Task GetTransactionFee();
+}
\ No newline at end of file
diff --git a/modules/AElf.BlockchainTransactionFee/IBlockchainTransactionFeeService.cs b/modules/AElf.BlockchainTransactionFee/IBlockchainTransactionFeeService.cs
new file mode 100644
index 00000000..efd9eaaa
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/IBlockchainTransactionFeeService.cs
@@ -0,0 +1,30 @@
+using Microsoft.Extensions.Caching.Distributed;
+using Volo.Abp.Caching;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.BlockchainTransactionFee;
+
+public interface IBlockchainTransactionFeeService
+{
+ Task GetTransactionFeeAsync(string chainName);
+}
+
+public class BlockchainTransactionFeeService : IBlockchainTransactionFeeService, ITransientDependency
+{
+ private readonly IEnumerable _blockchainTransactionFeeProviders;
+
+ public BlockchainTransactionFeeService(
+ IEnumerable blockchainTransactionFeeProviders)
+ {
+ _blockchainTransactionFeeProviders = blockchainTransactionFeeProviders;
+ }
+
+ public async Task GetTransactionFeeAsync(string chainName)
+ {
+ var provider = _blockchainTransactionFeeProviders.First(o => o.BlockChain == chainName);
+ var fee = await provider.GetTransactionFee();
+ return fee;
+ }
+}
+
+
diff --git a/modules/AElf.BlockchainTransactionFee/TransactionFeeDto.cs b/modules/AElf.BlockchainTransactionFee/TransactionFeeDto.cs
new file mode 100644
index 00000000..81c5fa61
--- /dev/null
+++ b/modules/AElf.BlockchainTransactionFee/TransactionFeeDto.cs
@@ -0,0 +1,7 @@
+namespace AElf.BlockchainTransactionFee;
+
+public class TransactionFeeDto
+{
+ public string Symbol { get; set; }
+ public decimal Fee { get; set; }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Bridge/AElf.Client.Bridge.csproj b/modules/AElf.Client.Bridge/AElf.Client.Bridge.csproj
new file mode 100644
index 00000000..3100d67f
--- /dev/null
+++ b/modules/AElf.Client.Bridge/AElf.Client.Bridge.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/AElf.Client.Bridge/AElfClientBridgeModule.cs b/modules/AElf.Client.Bridge/AElfClientBridgeModule.cs
new file mode 100644
index 00000000..6540b08e
--- /dev/null
+++ b/modules/AElf.Client.Bridge/AElfClientBridgeModule.cs
@@ -0,0 +1,18 @@
+using AElf.Client.Core;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+
+namespace AElf.Client.Bridge;
+
+[DependsOn(
+ typeof(AElfClientModule),
+ typeof(CoreAElfModule)
+)]
+public class AElfClientBridgeModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+ Configure(configuration.GetSection("Bridge"));
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Bridge/BridgeOptions.cs b/modules/AElf.Client.Bridge/BridgeOptions.cs
new file mode 100644
index 00000000..9269f006
--- /dev/null
+++ b/modules/AElf.Client.Bridge/BridgeOptions.cs
@@ -0,0 +1,6 @@
+namespace AElf.Client.Bridge;
+
+public class BridgeOptions
+{
+
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Bridge/BridgeService.cs b/modules/AElf.Client.Bridge/BridgeService.cs
new file mode 100644
index 00000000..beec29fb
--- /dev/null
+++ b/modules/AElf.Client.Bridge/BridgeService.cs
@@ -0,0 +1,91 @@
+using AElf.Client.Core;
+using AElf.Client.Core.Options;
+using AElf.Contracts.Bridge;
+using AElf.Contracts.Report;
+using AElf.Types;
+using Google.Protobuf;
+using Google.Protobuf.WellKnownTypes;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.Client.Bridge;
+
+public interface IBridgeService
+{
+ Task GetSpaceIdBySwapIdAsync(string chainId, Hash swapId);
+ Task SetGasPriceAsync(string chainId, SetGasPriceInput input);
+ Task SetPriceRatioAsync(string chainId, SetPriceRatioInput input);
+ Task GetGasPriceAsync(string chainId, StringValue input);
+ Task GetPriceRatioAsync(string chainId, StringValue input);
+ Task GetReceiptIdInfoAsync(string chainId, Hash receiptIdHash);
+}
+
+public class BridgeService : ContractServiceBase, IBridgeService, ITransientDependency
+{
+ private readonly IAElfClientService _clientService;
+ private readonly AElfContractOptions _contractOptions;
+
+ protected override string SmartContractName { get; }= "BridgeContract";
+
+ public BridgeService(IAElfClientService clientService,
+ IOptionsSnapshot contractOptions)
+ {
+ _clientService = clientService;
+ _contractOptions = contractOptions.Value;
+ }
+
+ public async Task GetSpaceIdBySwapIdAsync(string chainId, Hash swapId)
+ {
+ var result = await _clientService.ViewAsync(GetContractAddress(chainId), "GetSpaceIdBySwapId",
+ swapId, AElfChainAliasOptions.Value.Mapping[chainId]);
+
+ return Hash.Parser.ParseFrom(result);
+ }
+
+ public async Task SetGasPriceAsync(string chainId, SetGasPriceInput input)
+ {
+ var tx = await PerformSendTransactionAsync("SetGasPrice", input, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task SetPriceRatioAsync(string chainId, SetPriceRatioInput input)
+ {
+ var tx = await PerformSendTransactionAsync("SetPriceRatio", input, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task GetGasPriceAsync(string chainId, StringValue input)
+ {
+ var result = await _clientService.ViewAsync(GetContractAddress(chainId), "GetGasPrice",
+ input, AElfChainAliasOptions.Value.Mapping[chainId]);
+ var actualResult = new Int64Value();
+ actualResult.MergeFrom(result);
+ return actualResult;
+ }
+
+ public async Task GetPriceRatioAsync(string chainId, StringValue input)
+ {
+ var result = await _clientService.ViewAsync(GetContractAddress(chainId), "GetPriceRatio",
+ input, AElfChainAliasOptions.Value.Mapping[chainId]);
+ var actualResult = new Int64Value();
+ actualResult.MergeFrom(result);
+ return actualResult;
+ }
+
+ public async Task GetReceiptIdInfoAsync(string chainId, Hash receiptIdHash)
+ {
+ var result = await _clientService.ViewAsync(GetContractAddress(chainId), "GetReceiptIdInfo",
+ receiptIdHash, AElfChainAliasOptions.Value.Mapping[chainId]);
+ var actualResult = new ReceiptIdInfo();
+ actualResult.MergeFrom(result);
+ return actualResult;
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/AElf.Client.Core.csproj b/modules/AElf.Client.Core/AElf.Client.Core.csproj
new file mode 100644
index 00000000..1399c1a6
--- /dev/null
+++ b/modules/AElf.Client.Core/AElf.Client.Core.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net6.0
+ enable
+ enable
+ AElf.Client.Core
+ AElf C# sdk with abp module.
+ AElf
+ true
+ AElf.Client.Core
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/AElf.Client.Core/AElfClientAbpConstants.cs b/modules/AElf.Client.Core/AElfClientAbpConstants.cs
new file mode 100644
index 00000000..2db31b01
--- /dev/null
+++ b/modules/AElf.Client.Core/AElfClientAbpConstants.cs
@@ -0,0 +1,6 @@
+namespace AElf.Client.Core;
+
+public class AElfClientAbpConstants
+{
+ public const int DefaultWaitMilliseconds = 100;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/AElfClientModule.cs b/modules/AElf.Client.Core/AElfClientModule.cs
new file mode 100644
index 00000000..a68382cc
--- /dev/null
+++ b/modules/AElf.Client.Core/AElfClientModule.cs
@@ -0,0 +1,35 @@
+using AElf.Client.Core.Options;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Autofac;
+using Volo.Abp.AutoMapper;
+using Volo.Abp.Modularity;
+
+namespace AElf.Client.Core;
+
+[DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(AbpAutoMapperModule)
+ )]
+public class AElfClientModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+ Configure(options => { configuration.GetSection("AElfClient").Bind(options); });
+ Configure(options => { configuration.GetSection("AElfAccount").Bind(options); });
+ Configure(options => { configuration.GetSection("AElfClientConfig").Bind(options); });
+ Configure(options => { configuration.GetSection("AElfMinerAccount").Bind(options); });
+ Configure(options => { configuration.GetSection("AElfContract").Bind(options); });
+ Configure(options => { configuration.GetSection("AElfChainAlias").Bind(options); });
+
+ context.Services.AddSingleton();
+
+ context.Services.AddAutoMapperObjectMapper();
+
+ Configure(options =>
+ {
+ options.AddMaps();
+ });
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/AElfClientService.Blockchain.cs b/modules/AElf.Client.Core/AElfClientService.Blockchain.cs
new file mode 100644
index 00000000..19730c6c
--- /dev/null
+++ b/modules/AElf.Client.Core/AElfClientService.Blockchain.cs
@@ -0,0 +1,57 @@
+using AElf.Client.Dto;
+using Microsoft.Extensions.Logging;
+
+namespace AElf.Client.Core;
+
+public partial class AElfClientService
+{
+ public async Task GetTransactionResultAsync(string transactionId, string clientAlias)
+ {
+ var aelfClient = _aelfClientProvider.GetClient(alias: clientAlias);
+ var result = await aelfClient.GetTransactionResultAsync(transactionId);
+ var i = 0;
+ while (i < 10)
+ {
+ if (result!.Status == TransactionResultStatus.Mined.ToString().ToUpper())
+ {
+ break;
+ }
+
+ if (result.Status == TransactionResultStatus.Failed.ToString().ToUpper() ||
+ result.Status == TransactionResultStatus.NodeValidationFailed.ToString().ToUpper())
+ {
+ break;
+ }
+
+ await Task.Delay(AElfClientAbpConstants.DefaultWaitMilliseconds);
+ result = await aelfClient.GetTransactionResultAsync(transactionId);
+ i++;
+ }
+
+ return _objectMapper.Map(result!);
+ }
+
+ public async Task GetChainStatusAsync(string clientAlias)
+ {
+ var aelfClient = _aelfClientProvider.GetClient(alias: clientAlias);
+ return await aelfClient.GetChainStatusAsync();
+ }
+
+ public async Task GetBlockByHeightAsync(string clientAlias, long height)
+ {
+ var aelfClient = _aelfClientProvider.GetClient(alias: clientAlias);
+ return await aelfClient.GetBlockByHeightAsync(height);
+ }
+
+ public async Task GetMerklePathByTransactionIdAsync(string transactionId, string clientAlias)
+ {
+ var aelfClient = _aelfClientProvider.GetClient(alias: clientAlias);
+ var merklePathDto = await aelfClient.GetMerklePathByTransactionIdAsync(transactionId);
+ if (merklePathDto == null)
+ {
+ Logger.LogError("Cannot get merkle path of transaction {TransactionId}", transactionId);
+ }
+
+ return _objectMapper.Map(merklePathDto);
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/AElfClientService.Send.cs b/modules/AElf.Client.Core/AElfClientService.Send.cs
new file mode 100644
index 00000000..bed5e988
--- /dev/null
+++ b/modules/AElf.Client.Core/AElfClientService.Send.cs
@@ -0,0 +1,64 @@
+using AElf.Client.Dto;
+using Castle.Core.Logging;
+using Google.Protobuf;
+
+namespace AElf.Client.Core;
+
+public partial class AElfClientService
+{
+ public async Task SendAsync(string contractAddress, string methodName, IMessage parameter,
+ string clientAlias, string? alias = null, string? address = null)
+ {
+ var aelfClient = _aelfClientProvider.GetClient(alias: clientAlias);
+ var aelfAccount = SetAccount(alias, address);
+ var tx = new TransactionBuilder(aelfClient)
+ .UsePrivateKey(aelfAccount)
+ .UseContract(contractAddress)
+ .UseMethod(methodName)
+ .UseParameter(parameter)
+ .Build();
+ await PerformSendAsync(aelfClient, tx);
+ return tx;
+ }
+
+ public async Task SendSystemAsync(string systemContractName, string methodName, IMessage parameter,
+ string clientAlias, string? alias = null, string? address = null)
+ {
+ var aelfClient = _aelfClientProvider.GetClient(alias: clientAlias);
+ var aelfAccount = SetAccount(alias, address);
+ var tx = new TransactionBuilder(aelfClient)
+ .UsePrivateKey(aelfAccount)
+ .UseSystemContract(systemContractName)
+ .UseMethod(methodName)
+ .UseParameter(parameter)
+ .Build();
+ await PerformSendAsync(aelfClient, tx);
+ return tx;
+ }
+
+ private static async Task PerformSendAsync(AElfClient aelfClient, Transaction tx)
+ {
+ var result = await aelfClient.SendTransactionAsync(new SendTransactionInput
+ {
+ RawTransaction = tx.ToByteArray().ToHex()
+ });
+ }
+
+ private byte[] SetAccount(string? alias, string? address)
+ {
+ byte[] aelfAccount;
+ if (!string.IsNullOrWhiteSpace(address))
+ {
+ _aelfAccountProvider.SetPrivateKey(address, _aelfAccountProvider.GetDefaultPassword());
+ aelfAccount = _aelfAccountProvider.GetPrivateKey(null, address);
+ }
+ else
+ {
+ if (string.IsNullOrWhiteSpace(alias))
+ alias = _clientConfigOptions.AccountAlias;
+ aelfAccount = _aelfAccountProvider.GetPrivateKey(alias);
+ }
+
+ return aelfAccount;
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/AElfClientService.View.cs b/modules/AElf.Client.Core/AElfClientService.View.cs
new file mode 100644
index 00000000..35f4e232
--- /dev/null
+++ b/modules/AElf.Client.Core/AElfClientService.View.cs
@@ -0,0 +1,68 @@
+using AElf.Client.Dto;
+using AElf.Client.Core.Options;
+using Google.Protobuf;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.ObjectMapping;
+
+namespace AElf.Client.Core;
+
+public partial class AElfClientService : IAElfClientService, ITransientDependency
+{
+ private readonly IAElfClientProvider _aelfClientProvider;
+ private readonly IAElfAccountProvider _aelfAccountProvider;
+ private readonly IObjectMapper _objectMapper;
+ private readonly AElfClientConfigOptions _clientConfigOptions;
+
+ public ILogger Logger { get; set; }
+
+ public AElfClientService(IAElfClientProvider aelfClientProvider, IAElfAccountProvider aelfAccountProvider,
+ IObjectMapper objectMapper, IOptionsSnapshot clientConfigOptions)
+ {
+ _aelfClientProvider = aelfClientProvider;
+ _aelfAccountProvider = aelfAccountProvider;
+ _objectMapper = objectMapper;
+ _clientConfigOptions = clientConfigOptions.Value;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public async Task ViewAsync(string contractAddress, string methodName, IMessage parameter,
+ string clientAlias, string accountAlias = "Default")
+ {
+ var aelfClient = _aelfClientProvider.GetClient(alias: clientAlias);
+ var aelfAccount = _aelfAccountProvider.GetPrivateKey(alias: accountAlias);
+ var tx = new TransactionBuilder(aelfClient)
+ .UsePrivateKey(aelfAccount)
+ .UseContract(contractAddress)
+ .UseMethod(methodName)
+ .UseParameter(parameter)
+ .Build();
+ return await PerformViewAsync(aelfClient, tx);
+ }
+
+ public async Task ViewSystemAsync(string systemContractName, string methodName, IMessage parameter,
+ string clientAlias, string accountAlias = "Default")
+ {
+ var aelfClient = _aelfClientProvider.GetClient(alias: clientAlias);
+ var privateKey = _aelfAccountProvider.GetPrivateKey(alias: accountAlias);
+ var tx = new TransactionBuilder(aelfClient)
+ .UsePrivateKey(privateKey)
+ .UseSystemContract(systemContractName)
+ .UseMethod(methodName)
+ .UseParameter(parameter)
+ .Build();
+ return await PerformViewAsync(aelfClient, tx);
+ }
+
+ private async Task PerformViewAsync(AElfClient aelfClient, Transaction tx)
+ {
+ var result = await aelfClient.ExecuteTransactionAsync(new ExecuteTransactionDto
+ {
+ RawTransaction = tx.ToByteArray().ToHex()
+ });
+ return ByteArrayHelper.HexStringToByteArray(result);
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/ContractService.ttinclude b/modules/AElf.Client.Core/ContractService.ttinclude
new file mode 100644
index 00000000..37fdd911
--- /dev/null
+++ b/modules/AElf.Client.Core/ContractService.ttinclude
@@ -0,0 +1,59 @@
+<#@ template language="C#"#>
+<#@ output extension=".g.cs"#>
+<#@ import namespace="System.Collections.Generic" #>
+<#+
+ public string ContractName = "";
+
+ public List ContractMethodInfoList = new()
+ {
+ // new ContractMethodInfo("Query"),
+ // new ContractMethodInfo("Commit"),
+ // new ContractMethodInfo("Reveal"),
+ // new ContractMethodInfo("CancelQuery", "Hash")
+ };
+
+ public class ContractMethodInfo
+ {
+ public ContractMethodInfo(string methodName)
+ {
+ MethodName = methodName;
+ }
+
+ public ContractMethodInfo(string methodName, string parameterTypeName)
+ {
+ MethodName = methodName;
+ _parameterTypeName = parameterTypeName;
+ }
+
+ public string MethodName { get; set; }
+ private string _parameterTypeName;
+
+ public string ParameterTypeName
+ {
+ get => _parameterTypeName ?? $"{MethodName}Input";
+ set => _parameterTypeName = value;
+ }
+
+ public string InputName => ConvertMethodNameToInputName(MethodName);
+ }
+
+ ///
+ /// Generates text for a given sequence of items, automatically adding the necessary spacing
+ ///
+ public void GenerateTextForItems(IReadOnlyList items, Action factory)
+ {
+ for (int i = 0; i < items.Count; i++)
+ {
+ // Insert a blank line after the first item
+ if (i > 0) WriteLine("");
+
+ // Invoke the factory with the current item
+ factory(items [i]);
+ }
+ }
+
+ public static string ConvertMethodNameToInputName(string methodName)
+ {
+ return $"{char.ToLowerInvariant(methodName[0])}{methodName.Substring(1)}Input";
+ }
+#>
diff --git a/modules/AElf.Client.Core/ContractServiceBase.cs b/modules/AElf.Client.Core/ContractServiceBase.cs
new file mode 100644
index 00000000..80a2995d
--- /dev/null
+++ b/modules/AElf.Client.Core/ContractServiceBase.cs
@@ -0,0 +1,43 @@
+using AElf.Client.Core.Options;
+using Google.Protobuf;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Volo.Abp.Threading;
+
+namespace AElf.Client.Core;
+
+public abstract class ContractServiceBase
+{
+ public IAElfClientService ClientService { get; set; }
+ public IOptionsSnapshot ContractOptions { get; set; }
+ protected abstract string SmartContractName { get; }
+ public ILogger Logger { get; set; }
+ public IOptionsSnapshot AElfChainAliasOptions { get; set; }
+
+ protected async Task PerformSendTransactionAsync(string methodName, IMessage parameter,
+ string chainId)
+ {
+ var contractAddress = GetContractAddress(chainId);
+ var clientAlias = AElfChainAliasOptions.Value.Mapping[chainId];
+ return await ClientService.SendAsync(contractAddress, methodName, parameter, clientAlias);
+ }
+
+ protected async Task PerformGetTransactionResultAsync(string transactionId,
+ string chainId)
+ {
+ TransactionResult txResult;
+ var clientAlias = AElfChainAliasOptions.Value.Mapping[chainId];
+ do
+ {
+ txResult = await ClientService.GetTransactionResultAsync(transactionId, clientAlias);
+ } while (txResult.Status == TransactionResultStatus.Pending);
+
+ Logger.LogInformation("{TxResult}", txResult);
+ return txResult;
+ }
+
+ protected string GetContractAddress(string chainId)
+ {
+ return ContractOptions.Value.ContractAddressList[chainId][SmartContractName];
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Extensions/EventExtensions.cs b/modules/AElf.Client.Core/Extensions/EventExtensions.cs
new file mode 100644
index 00000000..768f27e4
--- /dev/null
+++ b/modules/AElf.Client.Core/Extensions/EventExtensions.cs
@@ -0,0 +1,12 @@
+using Google.Protobuf;
+
+namespace AElf.Client.Core.Extensions;
+
+public static class EventExtensions
+{
+ public static void MergeFrom(this T eventData, LogEvent log) where T : IMessage
+ {
+ foreach (var bs in log.Indexed) eventData.MergeFrom(bs);
+ eventData.MergeFrom(log.NonIndexed);
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/GlobalUsings.cs b/modules/AElf.Client.Core/GlobalUsings.cs
new file mode 100644
index 00000000..e2e7f5ce
--- /dev/null
+++ b/modules/AElf.Client.Core/GlobalUsings.cs
@@ -0,0 +1 @@
+global using AElf.Types;
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/IAElfAccountProvider.cs b/modules/AElf.Client.Core/IAElfAccountProvider.cs
new file mode 100644
index 00000000..ba8781a1
--- /dev/null
+++ b/modules/AElf.Client.Core/IAElfAccountProvider.cs
@@ -0,0 +1,134 @@
+using AElf.Client.Core.Infrastructure;
+using AElf.Client.Core.Options;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
+using Nethereum.KeyStore;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Threading;
+
+namespace AElf.Client.Core;
+
+public interface IAElfAccountProvider
+{
+ byte[] GetPrivateKey(string? alias = null, string? address = null);
+ void SetPrivateKey(byte[] privateKey, string? alias = null, string? address = null);
+ void SetPrivateKey(string address, string password, string? alias = null);
+ string GetDefaultPassword();
+}
+
+public class AElfAccountProvider : Dictionary, IAElfAccountProvider, ISingletonDependency
+{
+ private readonly IKeyDirectoryProvider _keyDirectoryProvider;
+ private readonly AElfAccountOptions _aelfAccountOptions;
+ private readonly string _aelfMinerAccountPassword;
+
+ private readonly KeyStoreService _keyStoreService;
+
+ public ILogger Logger { get; set; }
+
+ public AElfAccountProvider(IKeyDirectoryProvider keyDirectoryProvider,
+ IOptionsSnapshot aelfAccountOptions,
+ IOptionsSnapshot aelfMinerAccountOptions)
+ {
+ Logger = NullLogger.Instance;
+ _keyDirectoryProvider = keyDirectoryProvider;
+ _aelfAccountOptions = aelfAccountOptions.Value;
+ _aelfMinerAccountPassword = aelfMinerAccountOptions.Value.DefaultPassword;
+ var defaultPrivateKey = ByteArrayHelper.HexStringToByteArray(AElfClientConstants.DefaultPrivateKey);
+ SetPrivateKey(defaultPrivateKey, "Default", Address.FromPublicKey(defaultPrivateKey).ToBase58());
+ _keyStoreService = new KeyStoreService();
+
+ foreach (var accountConfig in aelfAccountOptions.Value.AccountConfigList)
+ {
+ if (string.IsNullOrWhiteSpace(accountConfig.PrivateKey))
+ {
+ var keyFilePath = GetKeyFileFullPath(accountConfig.Address, aelfAccountOptions.Value.KeyDirectory);
+ var privateKey = AsyncHelper.RunSync(() => Task.Run(() =>
+ {
+ using var textReader = File.OpenText(keyFilePath);
+ var json = textReader.ReadToEnd();
+ return _keyStoreService.DecryptKeyStoreFromJson(accountConfig.Password, json);
+ }));
+ SetPrivateKey(privateKey, accountConfig.Alias, accountConfig.Address);
+ }
+ else
+ {
+ var privateKey = ByteArrayHelper.HexStringToByteArray(accountConfig.PrivateKey);
+ SetPrivateKey(privateKey, accountConfig.Alias, Address.FromPublicKey(privateKey).ToBase58());
+ }
+ }
+ }
+
+ public string GetDefaultPassword()
+ {
+ return _aelfMinerAccountPassword;
+ }
+
+ public byte[] GetPrivateKey(string? alias = null, string? address = null)
+ {
+ var keys = Keys
+ .WhereIf(!alias.IsNullOrWhiteSpace(), a => a.Alias == alias)
+ .WhereIf(!address.IsNullOrWhiteSpace(), a => a.Address == address)
+ .ToList();
+ if (keys.Count != 1)
+ {
+ throw new AElfClientException($"Failed to get private key of {alias} - {address}.");
+ }
+
+ return this[keys.Single()];
+ }
+
+ public void SetPrivateKey(byte[] privateKey, string? alias = null, string? address = null)
+ {
+ TryAdd(new AElfAccountInfo
+ {
+ Alias = alias,
+ Address = address
+ }, privateKey);
+ }
+
+ public void SetPrivateKey(string address, string password, string? alias = null)
+ {
+ var keyFilePath = GetKeyFileFullPath(address, _aelfAccountOptions.KeyDirectory);
+ var privateKey = AsyncHelper.RunSync(() => Task.Run(() =>
+ {
+ using var textReader = File.OpenText(keyFilePath);
+ var json = textReader.ReadToEnd();
+ return _keyStoreService.DecryptKeyStoreFromJson(password, json);
+ }));
+
+ var keys = Keys
+ .WhereIf(!alias.IsNullOrWhiteSpace(), a => a.Alias == alias)
+ .WhereIf(!address.IsNullOrWhiteSpace(), a => a.Address == address)
+ .ToList();
+
+ if (keys.Count == 1) return;
+ TryAdd(new AElfAccountInfo
+ {
+ Alias = alias,
+ Address = address
+ }, privateKey);
+ }
+
+ private string GetKeyFileFullPath(string address, string configuredKeyDirectory)
+ {
+ var dirPath = GetKeystoreDirectoryPath(configuredKeyDirectory);
+ var filePath = Path.Combine(dirPath, address);
+ var filePathWithExtension = Path.ChangeExtension(filePath, ".json");
+ return filePathWithExtension;
+ }
+
+ private string GetKeystoreDirectoryPath(string? configuredKeyDirectory)
+ {
+ return string.IsNullOrWhiteSpace(configuredKeyDirectory)
+ ? Path.Combine(_keyDirectoryProvider.GetAppDataPath(), "keys")
+ : configuredKeyDirectory;
+ }
+}
+
+public class AElfAccountInfo
+{
+ public string? Alias { get; set; }
+ public string? Address { get; set; }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/IAElfClientProvider.cs b/modules/AElf.Client.Core/IAElfClientProvider.cs
new file mode 100644
index 00000000..a0f1794c
--- /dev/null
+++ b/modules/AElf.Client.Core/IAElfClientProvider.cs
@@ -0,0 +1,81 @@
+using AElf.Client.Core.Options;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.Client.Core;
+
+public interface IAElfClientProvider
+{
+ AElfClient GetClient(string? alias = null, string? environment = null, int? chainId = null, string? chainType = null);
+
+ void SetClient(AElfClient client, string? environment = null, int? chainId = null, string? chainType = null,
+ string? alias = null);
+}
+
+public class AElfClientProvider : Dictionary, IAElfClientProvider, ISingletonDependency
+{
+ public AElfClientProvider(IOptionsSnapshot aelfClientOptions,
+ IOptionsSnapshot aelfClientConfigOptions)
+ {
+ var useCamelCase = aelfClientConfigOptions.Value.CamelCase;
+ var clientBuilder = new AElfClientBuilder();
+ SetClient(clientBuilder.UsePublicEndpoint(EndpointType.MainNetMainChain).UseCamelCase(useCamelCase).Build(),
+ "MainNet", AElfClientConstants.MainChainId, "MainChain", EndpointType.MainNetMainChain.ToString());
+ SetClient(clientBuilder.UsePublicEndpoint(EndpointType.MainNetSideChain1).UseCamelCase(useCamelCase).Build(),
+ "MainNet", AElfClientConstants.SideChainId2, "SideChain", EndpointType.MainNetSideChain1.ToString());
+ SetClient(clientBuilder.UsePublicEndpoint(EndpointType.TestNetMainChain).UseCamelCase(useCamelCase).Build(),
+ "TestNet", AElfClientConstants.MainChainId, "MainChain", EndpointType.TestNetMainChain.ToString());
+ SetClient(clientBuilder.UsePublicEndpoint(EndpointType.TestNetSideChain2).UseCamelCase(useCamelCase).Build(),
+ "MainNet", AElfClientConstants.SideChainId2, "SideChain", EndpointType.TestNetSideChain2.ToString());
+ SetClient(clientBuilder.UsePublicEndpoint(EndpointType.Local).UseCamelCase(useCamelCase).Build(), "Local",
+ AElfClientConstants.MainChainId, "MainChain", EndpointType.Local.ToString());
+
+ foreach (var clientConfig in aelfClientOptions.Value.ClientConfigList)
+ {
+ var client = clientBuilder
+ .UseEndpoint(clientConfig.Endpoint)
+ .ManagePeerInfo(clientConfig.UserName, clientConfig.Password)
+ .SetHttpTimeout(clientConfig.Timeout)
+ .Build();
+ SetClient(client, alias: clientConfig.Alias);
+ }
+ }
+
+ public AElfClient GetClient(string? alias = null, string? environment = null, int? chainId = null,
+ string? chainType = null)
+ {
+ var keys = Keys
+ .WhereIf(!alias.IsNullOrWhiteSpace(), c => c.Alias == alias)
+ .WhereIf(!environment.IsNullOrWhiteSpace(), c => c.Environment == environment)
+ .WhereIf(chainId.HasValue, c => c.ChainId == chainId)
+ .WhereIf(!chainType.IsNullOrWhiteSpace(), c => c.ChainType == chainType)
+ .ToList();
+ if (keys.Count != 1)
+ {
+ throw new AElfClientException(
+ $"Failed to get client of {alias} - {environment} - {chainId} - {chainType}.");
+ }
+
+ return this[keys.Single()];
+ }
+
+ public void SetClient(AElfClient client, string? environment = null, int? chainId = null, string? chainType = null,
+ string? alias = null)
+ {
+ TryAdd(new AElfClientInfo
+ {
+ Environment = environment,
+ ChainId = chainId,
+ ChainType = chainType,
+ Alias = alias
+ }, client);
+ }
+}
+
+public class AElfClientInfo
+{
+ public string? Environment { get; set; }
+ public int? ChainId { get; set; }
+ public string? ChainType { get; set; }
+ public string? Alias { get; set; }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/IAElfClientService.cs b/modules/AElf.Client.Core/IAElfClientService.cs
new file mode 100644
index 00000000..63b847cb
--- /dev/null
+++ b/modules/AElf.Client.Core/IAElfClientService.cs
@@ -0,0 +1,27 @@
+using AElf.Client.Dto;
+using Google.Protobuf;
+
+namespace AElf.Client.Core;
+
+public interface IAElfClientService
+{
+ Task ViewAsync(string contractAddress, string methodName, IMessage parameter, string clientAlias,
+ string accountAlias = "Default");
+
+ Task ViewSystemAsync(string systemContractName, string methodName, IMessage parameter,
+ string clientAlias, string accountAlias = "Default");
+
+ Task SendAsync(string contractAddress, string methodName, IMessage parameter,
+ string clientAlias, string? accountAlias = null, string? accountAddress = null);
+
+ Task SendSystemAsync(string systemContractName, string methodName, IMessage parameter,
+ string clientAlias, string? accountAlias = null, string? accountAddress = null);
+
+ Task GetTransactionResultAsync(string transactionId, string clientAlias);
+
+ Task GetChainStatusAsync(string clientAlias);
+
+ Task GetBlockByHeightAsync(string clientAlias, long height);
+
+ Task GetMerklePathByTransactionIdAsync(string transactionId, string clientAlias);
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Infrastructure/IKeyDirectoryProvider.cs b/modules/AElf.Client.Core/Infrastructure/IKeyDirectoryProvider.cs
new file mode 100644
index 00000000..77ef3415
--- /dev/null
+++ b/modules/AElf.Client.Core/Infrastructure/IKeyDirectoryProvider.cs
@@ -0,0 +1,6 @@
+namespace AElf.Client.Core.Infrastructure;
+
+public interface IKeyDirectoryProvider
+{
+ string GetAppDataPath();
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Infrastructure/KeyDirectoryProvider.cs b/modules/AElf.Client.Core/Infrastructure/KeyDirectoryProvider.cs
new file mode 100644
index 00000000..789672b6
--- /dev/null
+++ b/modules/AElf.Client.Core/Infrastructure/KeyDirectoryProvider.cs
@@ -0,0 +1,24 @@
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.Client.Core.Infrastructure;
+
+public class KeyDirectoryProvider : IKeyDirectoryProvider, ISingletonDependency
+{
+ private const string ApplicationFolderName = "aelf";
+ private string _appDataPath;
+
+ public string GetAppDataPath()
+ {
+ if (string.IsNullOrWhiteSpace(_appDataPath))
+ {
+ _appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ApplicationFolderName);
+
+ if (!Directory.Exists(_appDataPath))
+ {
+ Directory.CreateDirectory(_appDataPath);
+ }
+ }
+
+ return _appDataPath;
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Options/AElfAccountOptions.cs b/modules/AElf.Client.Core/Options/AElfAccountOptions.cs
new file mode 100644
index 00000000..a49e606b
--- /dev/null
+++ b/modules/AElf.Client.Core/Options/AElfAccountOptions.cs
@@ -0,0 +1,15 @@
+namespace AElf.Client.Core.Options;
+
+public class AElfAccountOptions
+{
+ public string KeyDirectory { get; set; }
+ public List AccountConfigList { get; set; } = new();
+}
+
+public class AccountConfig
+{
+ public string Alias { get; set; }
+ public string Address { get; set; }
+ public string Password { get; set; }
+ public string PrivateKey { get; set; }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Options/AElfChainAliasOptions.cs b/modules/AElf.Client.Core/Options/AElfChainAliasOptions.cs
new file mode 100644
index 00000000..0a53aa58
--- /dev/null
+++ b/modules/AElf.Client.Core/Options/AElfChainAliasOptions.cs
@@ -0,0 +1,6 @@
+namespace AElf.Client.Core.Options;
+
+public class AElfChainAliasOptions
+{
+ public Dictionary Mapping { get; set; } = new();
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Options/AElfClientConfigOptions.cs b/modules/AElf.Client.Core/Options/AElfClientConfigOptions.cs
new file mode 100644
index 00000000..816a4ef8
--- /dev/null
+++ b/modules/AElf.Client.Core/Options/AElfClientConfigOptions.cs
@@ -0,0 +1,10 @@
+namespace AElf.Client.Core.Options;
+
+public class AElfClientConfigOptions
+{
+ public string ClientAlias { get; set; } = "TestNetSideChain2";
+ public string MainChainClientAlias { get; set; } = "TestNetMainChain";
+ public string SideChainClientAlias { get; set; } = "TestNetSideChain2";
+ public string AccountAlias { get; set; } = "Default";
+ public bool CamelCase { get; set; } = false;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Options/AElfClientOptions.cs b/modules/AElf.Client.Core/Options/AElfClientOptions.cs
new file mode 100644
index 00000000..ae612ddb
--- /dev/null
+++ b/modules/AElf.Client.Core/Options/AElfClientOptions.cs
@@ -0,0 +1,15 @@
+namespace AElf.Client.Core.Options;
+
+public class AElfClientOptions
+{
+ public List ClientConfigList { get; set; } = new();
+}
+
+public class ClientConfig
+{
+ public string Alias { get; set; }
+ public string Endpoint { get; set; }
+ public string? UserName { get; set; }
+ public string? Password { get; set; }
+ public int Timeout { get; set; } = 60;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Options/AElfContractOptions.cs b/modules/AElf.Client.Core/Options/AElfContractOptions.cs
new file mode 100644
index 00000000..fe2161c2
--- /dev/null
+++ b/modules/AElf.Client.Core/Options/AElfContractOptions.cs
@@ -0,0 +1,7 @@
+namespace AElf.Client.Core.Options;
+
+public class AElfContractOptions
+{
+ public string ContractDirectory { get; set; }
+ public Dictionary> ContractAddressList { get; set; } = new();
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Options/AElfMinerAccountOptions.cs b/modules/AElf.Client.Core/Options/AElfMinerAccountOptions.cs
new file mode 100644
index 00000000..3be3b5d6
--- /dev/null
+++ b/modules/AElf.Client.Core/Options/AElfMinerAccountOptions.cs
@@ -0,0 +1,6 @@
+namespace AElf.Client.Core.Options;
+
+public class AElfMinerAccountOptions
+{
+ public string DefaultPassword { get; set; }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Profile/CommonProfile.cs b/modules/AElf.Client.Core/Profile/CommonProfile.cs
new file mode 100644
index 00000000..3bacaa97
--- /dev/null
+++ b/modules/AElf.Client.Core/Profile/CommonProfile.cs
@@ -0,0 +1,27 @@
+using Google.Protobuf;
+
+namespace AElf.Client.Core;
+
+public class CommonProfile : AutoMapper.Profile
+{
+ public CommonProfile()
+ {
+ CreateMap()
+ .ConvertUsing(s => s == null ? null : s.ToHex());
+
+ CreateMap()
+ .ConvertUsing(s => Hash.LoadFromHex(s));
+
+ CreateMap()
+ .ConvertUsing(s => s.ToBase58());
+
+ CreateMap()
+ .ConvertUsing(s => Address.FromBase58(s));
+
+ CreateMap()
+ .ConvertUsing(s => s.ToBase64());
+
+ CreateMap()
+ .ConvertUsing(s => ByteString.CopyFromUtf8(s));
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Profile/MerklePathProfile.cs b/modules/AElf.Client.Core/Profile/MerklePathProfile.cs
new file mode 100644
index 00000000..8a9bf65a
--- /dev/null
+++ b/modules/AElf.Client.Core/Profile/MerklePathProfile.cs
@@ -0,0 +1,16 @@
+using AElf.Client.Dto;
+using AutoMapper;
+
+namespace AElf.Client.Core;
+
+public class MerklePathProfile : Profile
+{
+ public MerklePathProfile()
+ {
+ CreateMap();
+ CreateMap();
+
+ CreateMap();
+ CreateMap();
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/Profile/TransactionProfile.cs b/modules/AElf.Client.Core/Profile/TransactionProfile.cs
new file mode 100644
index 00000000..f7766233
--- /dev/null
+++ b/modules/AElf.Client.Core/Profile/TransactionProfile.cs
@@ -0,0 +1,78 @@
+using AElf.Client.Dto;
+using AutoMapper;
+using Google.Protobuf;
+using Volo.Abp.AutoMapper;
+
+namespace AElf.Client.Core;
+
+public class TransactionProfile : Profile
+{
+ public const string ErrorTrace = "WithMetrics";
+
+ public TransactionProfile()
+ {
+ CreateMap();
+ CreateMap();
+
+ CreateMap()
+ .ForMember(d => d.ReturnValue, opt => opt.MapFrom(s => s.ReturnValue.ToHex(false)))
+ .ForMember(d => d.Bloom,
+ opt => opt.MapFrom(s =>
+ s.Status == TransactionResultStatus.NotExisted
+ ? null
+ : s.Bloom.Length == 0
+ ? ByteString.CopyFrom(new byte[256]).ToBase64()
+ : s.Bloom.ToBase64()))
+ .ForMember(d => d.Status, opt => opt.MapFrom(s => s.Status.ToString().ToUpper()))
+ .ForMember(d => d.Error, opt => opt.MapFrom())
+ .Ignore(d => d.Transaction)
+ .Ignore(d => d.TransactionSize);
+
+ TransactionResultStatus status;
+ CreateMap()
+ .ForMember(d => d.ReturnValue,
+ opt => opt.MapFrom(s => ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(s.ReturnValue))))
+ .ForMember(d => d.BlockHash, opt => opt.MapFrom(s => Hash.LoadFromHex(s.BlockHash)))
+ .ForMember(d => d.Bloom, opt => opt.MapFrom(s =>
+ s.Status.ToUpper() == TransactionResultStatus.NotExisted.ToString().ToUpper()
+ ? null
+ : string.IsNullOrEmpty(s.Bloom)
+ ? ByteString.Empty
+ : ByteString.FromBase64(s.Bloom)))
+ .ForMember(d => d.Status,
+ opt => opt.MapFrom(s =>
+ Enum.TryParse($"{s.Status[0]}{s.Status.Substring(1).ToLower()}", out status)
+ ? status
+ : TransactionResultStatus.NotExisted))
+ .ForMember(d => d.Logs, opt => opt.MapFrom(s => s.Logs))
+ .Ignore(d => d.Error)
+ .Ignore(d => d.Bloom);
+
+ CreateMap()
+ .ForMember(d => d.Indexed, opt => opt.MapFrom(s => s.Indexed.Select(ByteString.FromBase64)))
+ .ForMember(d => d.NonIndexed, opt => opt.MapFrom(s => ByteString.FromBase64(s.NonIndexed)));
+ CreateMap();
+ }
+}
+
+public class TransactionErrorResolver : IValueResolver
+{
+ public string Resolve(TransactionResult source, TransactionResultDto destination, string destMember,
+ ResolutionContext context)
+ {
+ var errorTraceNeeded = (bool)context.Items[TransactionProfile.ErrorTrace];
+ return TakeErrorMessage(source.Error, errorTraceNeeded);
+ }
+
+ public static string TakeErrorMessage(string transactionResultError, bool errorTraceNeeded)
+ {
+ if (string.IsNullOrWhiteSpace(transactionResultError))
+ return null;
+
+ if (errorTraceNeeded)
+ return transactionResultError;
+
+ using var stringReader = new StringReader(transactionResultError);
+ return stringReader.ReadLine();
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Core/SendTransactionResult.cs b/modules/AElf.Client.Core/SendTransactionResult.cs
new file mode 100644
index 00000000..057d94ea
--- /dev/null
+++ b/modules/AElf.Client.Core/SendTransactionResult.cs
@@ -0,0 +1,7 @@
+namespace AElf.Client.Core;
+
+public class SendTransactionResult
+{
+ public TransactionResult TransactionResult { get; set; }
+ public Transaction Transaction { get; set; }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.MerkleTree/AElf.Client.MerkleTree.csproj b/modules/AElf.Client.MerkleTree/AElf.Client.MerkleTree.csproj
new file mode 100644
index 00000000..e13af04b
--- /dev/null
+++ b/modules/AElf.Client.MerkleTree/AElf.Client.MerkleTree.csproj
@@ -0,0 +1,33 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TextTemplatingFileGenerator
+ MerkleTreeContract.g.cs
+
+
+
+
+
+ True
+ True
+ MerkleTreeService.tt
+
+
+
+
diff --git a/modules/AElf.Client.MerkleTree/AElfClientMerkleTreeModule.cs b/modules/AElf.Client.MerkleTree/AElfClientMerkleTreeModule.cs
new file mode 100644
index 00000000..81c8f8ac
--- /dev/null
+++ b/modules/AElf.Client.MerkleTree/AElfClientMerkleTreeModule.cs
@@ -0,0 +1,16 @@
+using AElf.Client.Core;
+using Volo.Abp.Modularity;
+
+namespace AElf.Client.MerkleTree;
+
+[DependsOn(
+ typeof(AElfClientModule),
+ typeof(CoreAElfModule)
+)]
+public class AElfClientMerkleTreeModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ base.ConfigureServices(context);
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.MerkleTree/ContractService.ttinclude b/modules/AElf.Client.MerkleTree/ContractService.ttinclude
new file mode 100644
index 00000000..eeb31d7a
--- /dev/null
+++ b/modules/AElf.Client.MerkleTree/ContractService.ttinclude
@@ -0,0 +1,84 @@
+<#@ template language="C#"#>
+<#@ output extension=".g.cs"#>
+<#@ import namespace="System.Collections.Generic" #>
+<#+
+ public string ContractName = "MerkleTreeContract";
+
+ public List ContractActionMethodInfoList = new()
+ {
+ new ContractActionMethodInfo("CreateSpace"),
+
+ };
+
+ public List ContractViewMethodInfoList = new()
+ {
+ new ContractViewMethodInfo("GetLastLeafIndex", "Int64Value"),
+ };
+
+ public class ContractActionMethodInfo
+ {
+ public ContractActionMethodInfo(string methodName)
+ {
+ MethodName = methodName;
+ }
+
+ public ContractActionMethodInfo(string methodName, string parameterTypeName)
+ {
+ MethodName = methodName;
+ _parameterTypeName = parameterTypeName;
+ }
+
+ public string MethodName { get; set; }
+ private string _parameterTypeName;
+
+ public string ParameterTypeName
+ {
+ get => _parameterTypeName ?? $"{MethodName}Input";
+ set => _parameterTypeName = value;
+ }
+
+ public string InputName => ConvertMethodNameToInputName(MethodName);
+ }
+
+ public class ContractViewMethodInfo
+ {
+ public ContractViewMethodInfo(string methodName, string returnTypeName)
+ {
+ MethodName = methodName;
+ ReturnTypeName = returnTypeName;
+ }
+
+ public string MethodName { get; set; }
+ public string ReturnTypeName { get; set; }
+
+ private string _parameterTypeName;
+
+ public string ParameterTypeName
+ {
+ get => _parameterTypeName ?? $"{MethodName}Input";
+ set => _parameterTypeName = value;
+ }
+
+ public string InputName => ConvertMethodNameToInputName(MethodName);
+ }
+
+ ///
+ /// Generates text for a given sequence of items, automatically adding the necessary spacing
+ ///
+ public void GenerateTextForItems(IReadOnlyList items, Action factory)
+ {
+ for (int i = 0; i < items.Count; i++)
+ {
+ // Insert a blank line after the first item
+ if (i > 0) WriteLine("");
+
+ // Invoke the factory with the current item
+ factory(items [i]);
+ }
+ }
+
+ public static string ConvertMethodNameToInputName(string methodName)
+ {
+ return $"{char.ToLowerInvariant(methodName[0])}{methodName.Substring(1)}Input";
+ }
+#>
diff --git a/modules/AElf.Client.MerkleTree/MerkleTreeContract.cs b/modules/AElf.Client.MerkleTree/MerkleTreeContract.cs
new file mode 100644
index 00000000..64bffd5d
--- /dev/null
+++ b/modules/AElf.Client.MerkleTree/MerkleTreeContract.cs
@@ -0,0 +1,49 @@
+using AElf.Client.Core;
+using AElf.Client.Core.Options;
+using AElf.Contracts.MerkleTreeContract;
+using AElf.Types;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+using Google.Protobuf.WellKnownTypes;
+using Google.Protobuf;
+
+namespace AElf.Client.MerkleTreeContract;
+
+public interface IMerkleTreeContractService
+{
+ Task CreateSpaceAsync(string chainId, CreateSpaceInput createSpaceInput);
+
+ Task GetLastLeafIndexAsync(string chainId, GetLastLeafIndexInput getLastLeafIndexInput);
+}
+
+public class MerkleTreeContractService : ContractServiceBase, IMerkleTreeContractService, ITransientDependency
+{
+ private readonly IAElfClientService _clientService;
+
+ protected override string SmartContractName { get; } = "MerkleTreeContract";
+
+ public MerkleTreeContractService(IAElfClientService clientService)
+ {
+ _clientService = clientService;
+ }
+
+ public async Task CreateSpaceAsync(string chainId, CreateSpaceInput createSpaceInput)
+ {
+ var tx = await PerformSendTransactionAsync("CreateSpace", createSpaceInput, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task GetLastLeafIndexAsync(string chainId, GetLastLeafIndexInput getLastLeafIndexInput)
+ {
+ var clientAlias = AElfChainAliasOptions.Value.Mapping[chainId];
+ var result = await _clientService.ViewAsync(GetContractAddress(chainId), "GetLastLeafIndex",
+ getLastLeafIndexInput, clientAlias);
+ var actualResult = new Int64Value();
+ actualResult.MergeFrom(result);
+ return actualResult;
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.MerkleTree/MerkleTreeContract.tt b/modules/AElf.Client.MerkleTree/MerkleTreeContract.tt
new file mode 100644
index 00000000..506b6c64
--- /dev/null
+++ b/modules/AElf.Client.MerkleTree/MerkleTreeContract.tt
@@ -0,0 +1,84 @@
+<#@include file="ContractService.ttinclude" #><#@ import namespace="System.Diagnostics.Contracts" #>
+using AElf.Client.Core;
+using AElf.Client.Core.Options;
+using AElf.Contracts.<#=ContractName#>;
+using AElf.Types;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+using Google.Protobuf.WellKnownTypes;
+using Google.Protobuf;
+
+namespace AElf.Client.<#=ContractName#>;
+
+public interface I<#=ContractName#>Service
+{
+<#
+ GenerateTextForItems(ContractActionMethodInfoList, item =>
+ {
+#>
+ Task <#=item.MethodName#>Async(<#=item.ParameterTypeName#> <#=item.InputName#>);
+<#
+ });
+#>
+
+<#
+ GenerateTextForItems(ContractViewMethodInfoList, item =>
+ {
+#>
+ Task<<#=item.ReturnTypeName#>> <#=item.MethodName#>Async(<#=item.ParameterTypeName#> <#=item.InputName#>);
+<#
+ });
+#>
+}
+
+public class <#=ContractName#>Service : ContractServiceBase, I<#=ContractName#>Service, ITransientDependency
+{
+ private readonly IAElfClientService _clientService;
+ private readonly AElfClientConfigOptions _clientConfigOptions;
+ private readonly AElfContractOptions _contractOptions;
+
+ protected <#=ContractName#>Service(IAElfClientService clientService,
+ IOptionsSnapshot clientConfigOptions,
+ IOptionsSnapshot contractOptions) : base(clientService,
+ Address.FromBase58(contractOptions.Value.ContractAddressList["<#=ContractName#>ContractAddress"]))
+ {
+ _clientService = clientService;
+ _clientConfigOptions = clientConfigOptions.Value;
+ _contractOptions = contractOptions.Value;
+ }
+
+<#
+ GenerateTextForItems(ContractActionMethodInfoList, item =>
+ {
+#>
+ public async Task <#=item.MethodName#>Async(<#=item.ParameterTypeName#> <#=item.InputName#>)
+ {
+ var useClientAlias = _clientConfigOptions.ClientAlias;
+ var tx = await PerformSendTransactionAsync("<#=item.MethodName#>", <#=item.InputName#>, useClientAlias);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), useClientAlias)
+ };
+ }
+<#
+ });
+#>
+
+<#
+ GenerateTextForItems(ContractViewMethodInfoList, item =>
+ {
+#>
+ public async Task<<#=item.ReturnTypeName#>> <#=item.MethodName#>Async(<#=item.ParameterTypeName#> <#=item.InputName#>)
+ {
+ var useClientAlias = _clientConfigOptions.ClientAlias;
+ var result = await _clientService.ViewAsync(_contractOptions.ContractAddressList["<#=ContractName#>Address"], "<#=item.MethodName#>",
+ <#=item.InputName#>, useClientAlias);
+ var actualResult = new <#=item.ReturnTypeName#>();
+ actualResult.MergeFrom(result);
+ return actualResult;
+ }
+<#
+ });
+#>
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Oracle/AElf.Client.Oracle.csproj b/modules/AElf.Client.Oracle/AElf.Client.Oracle.csproj
new file mode 100644
index 00000000..a927f044
--- /dev/null
+++ b/modules/AElf.Client.Oracle/AElf.Client.Oracle.csproj
@@ -0,0 +1,33 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TextTemplatingFileGenerator
+ OracleService.g.cs
+
+
+
+
+
+ True
+ True
+ OracleService.tt
+
+
+
+
diff --git a/modules/AElf.Client.Oracle/AElfClientOracleModule.cs b/modules/AElf.Client.Oracle/AElfClientOracleModule.cs
new file mode 100644
index 00000000..d2982800
--- /dev/null
+++ b/modules/AElf.Client.Oracle/AElfClientOracleModule.cs
@@ -0,0 +1,18 @@
+using AElf.Client.Core;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+
+namespace AElf.Client.Oracle;
+
+[DependsOn(
+ typeof(AElfClientModule),
+ typeof(CoreAElfModule)
+)]
+public class AElfClientOracleModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+ Configure(configuration.GetSection("Oracle"));
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Oracle/ContractService.ttinclude b/modules/AElf.Client.Oracle/ContractService.ttinclude
new file mode 100644
index 00000000..6ef56bb8
--- /dev/null
+++ b/modules/AElf.Client.Oracle/ContractService.ttinclude
@@ -0,0 +1,59 @@
+<#@ template language="C#"#>
+<#@ output extension=".g.cs"#>
+<#@ import namespace="System.Collections.Generic" #>
+<#+
+ public string ContractName = "Oracle";
+
+ public List ContractMethodInfoList = new()
+ {
+ new ContractMethodInfo("Query"),
+ new ContractMethodInfo("Commit"),
+ new ContractMethodInfo("Reveal"),
+ new ContractMethodInfo("CancelQuery", "Hash")
+ };
+
+ public class ContractMethodInfo
+ {
+ public ContractMethodInfo(string methodName)
+ {
+ MethodName = methodName;
+ }
+
+ public ContractMethodInfo(string methodName, string parameterTypeName)
+ {
+ MethodName = methodName;
+ _parameterTypeName = parameterTypeName;
+ }
+
+ public string MethodName { get; set; }
+ private string _parameterTypeName;
+
+ public string ParameterTypeName
+ {
+ get => _parameterTypeName ?? $"{MethodName}Input";
+ set => _parameterTypeName = value;
+ }
+
+ public string InputName => ConvertMethodNameToInputName(MethodName);
+ }
+
+ ///
+ /// Generates text for a given sequence of items, automatically adding the necessary spacing
+ ///
+ public void GenerateTextForItems(IReadOnlyList items, Action factory)
+ {
+ for (int i = 0; i < items.Count; i++)
+ {
+ // Insert a blank line after the first item
+ if (i > 0) WriteLine("");
+
+ // Invoke the factory with the current item
+ factory(items [i]);
+ }
+ }
+
+ public static string ConvertMethodNameToInputName(string methodName)
+ {
+ return $"{char.ToLowerInvariant(methodName[0])}{methodName.Substring(1)}Input";
+ }
+#>
diff --git a/modules/AElf.Client.Oracle/OracleOptions.cs b/modules/AElf.Client.Oracle/OracleOptions.cs
new file mode 100644
index 00000000..d0f545b6
--- /dev/null
+++ b/modules/AElf.Client.Oracle/OracleOptions.cs
@@ -0,0 +1,6 @@
+namespace AElf.Client.Oracle;
+
+public class OracleOptions
+{
+
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Oracle/OracleService.cs b/modules/AElf.Client.Oracle/OracleService.cs
new file mode 100644
index 00000000..6f6f6b20
--- /dev/null
+++ b/modules/AElf.Client.Oracle/OracleService.cs
@@ -0,0 +1,65 @@
+using AElf.Client.Core;
+using AElf.Client.Core.Options;
+using AElf.Contracts.Oracle;
+using AElf.Types;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.Client.Oracle;
+
+public interface IOracleService
+{
+ Task QueryAsync(string chainId, QueryInput queryInput);
+
+ Task CommitAsync(string chainId, CommitInput commitInput);
+
+ Task RevealAsync(string chainId, RevealInput revealInput);
+
+ Task CancelQueryAsync(string chainId, Hash cancelQueryInput);
+}
+
+public class OracleService : ContractServiceBase, IOracleService, ITransientDependency
+{
+ protected override string SmartContractName { get; } = "OracleContract";
+
+ public async Task QueryAsync(string chainId, QueryInput queryInput)
+ {
+ var tx = await PerformSendTransactionAsync("Query", queryInput, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task CommitAsync(string chainId, CommitInput commitInput)
+ {
+ var tx = await PerformSendTransactionAsync("Commit", commitInput, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task RevealAsync(string chainId, RevealInput revealInput)
+ {
+ var tx = await PerformSendTransactionAsync("Reveal", revealInput, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task CancelQueryAsync(string chainId, Hash cancelQueryInput)
+ {
+ var tx = await PerformSendTransactionAsync("CancelQuery", cancelQueryInput, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Oracle/OracleService.tt b/modules/AElf.Client.Oracle/OracleService.tt
new file mode 100644
index 00000000..074d3a95
--- /dev/null
+++ b/modules/AElf.Client.Oracle/OracleService.tt
@@ -0,0 +1,54 @@
+<#@include file="ContractService.ttinclude" #><#@ import namespace="System.Diagnostics.Contracts" #>
+using AElf.Client.Core;
+using AElf.Client.Core.Options;
+using AElf.Contracts.<#=ContractName#>;
+using AElf.Types;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.Client.<#=ContractName#>;
+
+public interface I<#=ContractName#>Service
+{
+<#
+ GenerateTextForItems(ContractMethodInfoList, item =>
+ {
+#>
+ Task <#=item.MethodName#>Async(<#=item.ParameterTypeName#> <#=item.InputName#>);
+<#
+ });
+#>
+}
+
+public class <#=ContractName#>Service : ContractServiceBase, I<#=ContractName#>Service, ITransientDependency
+{
+ private readonly IAElfClientService _clientService;
+ private readonly AElfClientConfigOptions _clientConfigOptions;
+
+ protected <#=ContractName#>Service(IAElfClientService clientService,
+ IOptionsSnapshot clientConfigOptions,
+ IOptionsSnapshot contractOptions) : base(clientService,
+ Address.FromBase58(contractOptions.Value.ContractAddressList["<#=ContractName#>ContractAddress"]))
+ {
+ _clientService = clientService;
+ _clientConfigOptions = clientConfigOptions.Value;
+ }
+
+<#
+ GenerateTextForItems(ContractMethodInfoList, item =>
+ {
+#>
+ public async Task <#=item.MethodName#>Async(<#=item.ParameterTypeName#> <#=item.InputName#>)
+ {
+ var useClientAlias = _clientConfigOptions.ClientAlias;
+ var tx = await PerformSendTransactionAsync("<#=item.MethodName#>", <#=item.InputName#>, useClientAlias);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), useClientAlias)
+ };
+ }
+<#
+ });
+#>
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/AElf.Client.Protobuf.csproj b/modules/AElf.Client.Protobuf/AElf.Client.Protobuf.csproj
new file mode 100644
index 00000000..64669554
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/AElf.Client.Protobuf.csproj
@@ -0,0 +1,94 @@
+
+
+
+ net6.0
+ enable
+ enable
+ AElf.Client.Protobuf
+ Protobuf using by AElf C# sdk.
+ AElf
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+
+
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs0.proto b/modules/AElf.Client.Protobuf/Protobuf/acs0.proto
new file mode 100644
index 00000000..84606e7e
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs0.proto
@@ -0,0 +1,234 @@
+/**
+ * AElf Standards ACS0(Contract Deployment Standard)
+ *
+ * Used to manage the deployment and update of contracts.
+ */
+syntax = "proto3";
+
+package acs0;
+option csharp_namespace = "AElf.Standards.ACS0";
+
+import public "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+service ACS0 {
+ // Deploy a system smart contract on chain and return the address of the system contract deployed.
+ rpc DeploySystemSmartContract (SystemContractDeploymentInput) returns (aelf.Address) {
+ }
+
+ // Deploy a smart contract on chain and return the address of the contract deployed.
+ rpc DeploySmartContract (ContractDeploymentInput) returns (aelf.Address) {
+ }
+
+ // Update a smart contract on chain.
+ rpc UpdateSmartContract (ContractUpdateInput) returns (aelf.Address) {
+ }
+
+ // Create a proposal to deploy a new contract and returns the id of the proposed contract.
+ rpc ProposeNewContract (ContractDeploymentInput) returns (aelf.Hash) {
+ }
+
+ // Create a proposal to check the code of a contract and return the id of the proposed contract.
+ rpc ProposeContractCodeCheck (ContractCodeCheckInput) returns (aelf.Hash) {
+ }
+
+ // Create a proposal to update the specified contract
+ // and return the id of the proposed contract.
+ rpc ProposeUpdateContract (ContractUpdateInput) returns (aelf.Hash) {
+ }
+
+ // Release the contract proposal which has been approved.
+ rpc ReleaseApprovedContract (ReleaseContractInput) returns (google.protobuf.Empty) {
+ }
+
+ // Release the proposal which has passed the code check.
+ rpc ReleaseCodeCheckedContract (ReleaseContractInput) returns (google.protobuf.Empty) {
+ }
+
+ // Validate whether the input system contract exists.
+ rpc ValidateSystemContractAddress(ValidateSystemContractAddressInput) returns (google.protobuf.Empty){
+ }
+
+ // Set authority of contract deployment.
+ rpc SetContractProposerRequiredState (google.protobuf.BoolValue) returns (google.protobuf.Empty) {
+ }
+
+ // Get the current serial number of genesis contract
+ // (corresponds to the serial number that will be given to the next deployed contract).
+ rpc CurrentContractSerialNumber (google.protobuf.Empty) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get detailed information about the specified contract.
+ rpc GetContractInfo (aelf.Address) returns (ContractInfo) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get author of the specified contract.
+ rpc GetContractAuthor (aelf.Address) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the code hash of the contract about the specified address.
+ rpc GetContractHash (aelf.Address) returns (aelf.Hash) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the address of a system contract by its name.
+ rpc GetContractAddressByName (aelf.Hash) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the registration of a smart contract by its address.
+ rpc GetSmartContractRegistrationByAddress (aelf.Address) returns (aelf.SmartContractRegistration) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the registration of a smart contract by code hash.
+ rpc GetSmartContractRegistrationByCodeHash (aelf.Hash) returns (aelf.SmartContractRegistration) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetContractCodeHashListByDeployingBlockHeight (google.protobuf.Int64Value) returns (ContractCodeHashList) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message ContractInfo
+{
+ // The serial number of the contract.
+ int64 serial_number = 1;
+ // The author of the contract, this is the person who deployed the contract.
+ aelf.Address author = 2;
+ // The category of contract code(0: C#).
+ sint32 category = 3;
+ // The hash of the contract code.
+ aelf.Hash code_hash = 4;
+ // Whether it is a system contract.
+ bool is_system_contract = 5;
+ // The version of the current contract.
+ int32 version = 6;
+}
+
+message ContractDeploymentInput {
+ // The category of contract code(0: C#).
+ sint32 category = 1;
+ // The byte array of the contract code.
+ bytes code = 2;
+}
+
+message SystemContractDeploymentInput {
+ message SystemTransactionMethodCall {
+ // The method name of system transaction.
+ string method_name = 1;
+ // The params of system transaction method.
+ bytes params = 2;
+ }
+ message SystemTransactionMethodCallList {
+ // The list of system transactions.
+ repeated SystemTransactionMethodCall value = 1;
+ }
+ // The category of contract code(0: C#).
+ sint32 category = 1;
+ // The byte array of the contract code.
+ bytes code = 2;
+ // The name of the contract. It has to be unique.
+ aelf.Hash name = 3;
+ // An initial list of transactions for the system contract,
+ // which is executed in sequence when the contract is deployed.
+ SystemTransactionMethodCallList transaction_method_call_list = 4;
+}
+
+message ContractUpdateInput {
+ // The contract address that needs to be updated.
+ aelf.Address address = 1;
+ // The byte array of the new contract code.
+ bytes code = 2;
+}
+
+message ContractCodeCheckInput{
+ // The byte array of the contract code to be checked.
+ bytes contract_input = 1;
+ // Whether the input contract is to be deployed or updated.
+ bool is_contract_deployment = 2;
+ // Method to call after code check complete(DeploySmartContract or UpdateSmartContract).
+ string code_check_release_method = 3;
+ // The id of the proposed contract.
+ aelf.Hash proposed_contract_input_hash = 4;
+ // The category of contract code(0: C#).
+ sint32 category = 5;
+ // Indicates if the contract is the system contract.
+ bool is_system_contract = 6;
+}
+
+message ContractProposed
+{
+ option (aelf.is_event) = true;
+ // The id of the proposed contract.
+ aelf.Hash proposed_contract_input_hash = 1;
+}
+
+message ContractDeployed
+{
+ option (aelf.is_event) = true;
+ // The author of the contract, this is the person who deployed the contract.
+ aelf.Address author = 1 [(aelf.is_indexed) = true];
+ // The hash of the contract code.
+ aelf.Hash code_hash = 2 [(aelf.is_indexed) = true];
+ // The address of the contract.
+ aelf.Address address = 3;
+ // The version of the current contract.
+ int32 version = 4;
+ // The name of the contract. It has to be unique.
+ aelf.Hash Name = 5;
+}
+
+message CodeCheckRequired
+{
+ option (aelf.is_event) = true;
+ // The byte array of the contract code.
+ bytes code = 1;
+ // The id of the proposed contract.
+ aelf.Hash proposed_contract_input_hash = 2;
+ // The category of contract code(0: C#).
+ sint32 category = 3;
+ // Indicates if the contract is the system contract.
+ bool is_system_contract = 4;
+}
+
+message CodeUpdated
+{
+ option (aelf.is_event) = true;
+ // The address of the updated contract.
+ aelf.Address address = 1 [(aelf.is_indexed) = true];
+ // The byte array of the old contract code.
+ aelf.Hash old_code_hash = 2;
+ // The byte array of the new contract code.
+ aelf.Hash new_code_hash = 3;
+ // The version of the current contract.
+ int32 version = 4;
+}
+
+message ValidateSystemContractAddressInput {
+ // The name hash of the contract.
+ aelf.Hash system_contract_hash_name = 1;
+ // The address of the contract.
+ aelf.Address address = 2;
+}
+
+message ReleaseContractInput {
+ // The hash of the proposal.
+ aelf.Hash proposal_id = 1;
+ // The id of the proposed contract.
+ aelf.Hash proposed_contract_input_hash = 2;
+}
+
+message ContractCodeHashList {
+ repeated aelf.Hash value = 1;
+}
+
+message ContractCodeHashMap {
+ map value = 1;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs1.proto b/modules/AElf.Client.Protobuf/Protobuf/acs1.proto
new file mode 100644
index 00000000..4894a1bc
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs1.proto
@@ -0,0 +1,53 @@
+/**
+ * AElf Standards ACS1(Transaction Fee Standard)
+ *
+ * Used to manage the transaction fee.
+ */
+syntax = "proto3";
+
+package acs1;
+
+import public "aelf/options.proto";
+import public "google/protobuf/empty.proto";
+import public "google/protobuf/wrappers.proto";
+import "aelf/core.proto";
+import "authority_info.proto";
+
+option (aelf.identity) = "acs1";
+option csharp_namespace = "AElf.Standards.ACS1";
+
+service MethodFeeProviderContract {
+
+ // Set the method fees for the specified method. Note that this will override all fees of the method.
+ rpc SetMethodFee (MethodFees) returns (google.protobuf.Empty) {
+ }
+
+ // Change the method fee controller, the default is parliament and default organization.
+ rpc ChangeMethodFeeController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Query method fee information by method name.
+ rpc GetMethodFee (google.protobuf.StringValue) returns (MethodFees) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the method fee controller.
+ rpc GetMethodFeeController (google.protobuf.Empty) returns (AuthorityInfo) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message MethodFees {
+ // The name of the method to be charged.
+ string method_name = 1;
+ // List of fees to be charged.
+ repeated MethodFee fees = 2;
+ bool is_size_fee_free = 3;// Optional based on the implementation of SetMethodFee method.
+}
+
+message MethodFee {
+ // 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/modules/AElf.Client.Protobuf/Protobuf/acs10.proto b/modules/AElf.Client.Protobuf/Protobuf/acs10.proto
new file mode 100644
index 00000000..0b6f3240
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs10.proto
@@ -0,0 +1,80 @@
+/**
+ * AElf Standards ACS10(Dividend Pool Standard)
+ *
+ * Used to construct a dividend pool in the contract.
+ */
+syntax = "proto3";
+
+package acs10;
+
+import public "aelf/options.proto";
+import public "google/protobuf/empty.proto";
+import public "google/protobuf/wrappers.proto";
+import "aelf/core.proto";
+
+option (aelf.identity) = "acs10";
+option csharp_namespace = "AElf.Standards.ACS10";
+
+service DividendPoolContract {
+ // Donates tokens from the caller to the treasury. If the tokens are not native tokens in the current chain,
+ // they will be first converted to the native token.
+ rpc Donate (DonateInput) returns (google.protobuf.Empty) {
+ }
+
+ // Release dividend pool according the period number.
+ rpc Release (ReleaseInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set the token symbols dividend pool supports.
+ rpc SetSymbolList (SymbolList) returns (google.protobuf.Empty) {
+ }
+
+ // Query the token symbols dividend pool supports.
+ rpc GetSymbolList (google.protobuf.Empty) returns (SymbolList) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the balance of undistributed tokens whose symbols are included in the symbol list.
+ rpc GetUndistributedDividends (google.protobuf.Empty) returns (Dividends) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the dividend information according to the height.
+ rpc GetDividends (google.protobuf.Int64Value) returns (Dividends) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message DonateInput {
+ // The token symbol to donate.
+ string symbol = 1;
+ // The amount to donate.
+ int64 amount = 2;
+}
+
+message ReleaseInput {
+ // The period number to release.
+ int64 period_number = 1;
+}
+
+message SymbolList {
+ // The token symbol list.
+ repeated string value = 1;
+}
+
+message Dividends {
+ // The dividends, symbol -> amount.
+ map value = 1;
+}
+
+message DonationReceived {
+ option (aelf.is_event) = true;
+ // The address of donors.
+ aelf.Address from = 1;
+ // The address of dividend pool.
+ aelf.Address pool_contract = 2;
+ // The token symbol Donated.
+ string symbol = 3;
+ // The amount Donated.
+ int64 amount = 4;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs11.proto b/modules/AElf.Client.Protobuf/Protobuf/acs11.proto
new file mode 100644
index 00000000..d7708a78
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs11.proto
@@ -0,0 +1,31 @@
+/**
+ * AElf Standards ACS11(Consensus Standard)
+ *
+ * Used to customize consensus mechanisms for cross chain.
+ */
+syntax = "proto3";
+
+package acs11;
+import "aelf/options.proto";
+import "aelf/core.proto";
+import "google/protobuf/wrappers.proto";
+import "google/protobuf/empty.proto";
+
+option (aelf.identity) = "acs11";
+option csharp_namespace = "AElf.Standards.ACS11";
+
+service CrossChainInteractionContract {
+ // Update the consensus information of the side chain.
+ rpc UpdateInformationFromCrossChain (google.protobuf.BytesValue) returns (google.protobuf.Empty) {
+ }
+
+ // Get the current miner list and consensus round information.
+ rpc GetChainInitializationInformation (google.protobuf.BytesValue) returns (google.protobuf.BytesValue) {
+ option (aelf.is_view) = true;
+ }
+
+ // Verify that the input address is the current miner.
+ rpc CheckCrossChainIndexingPermission (aelf.Address) returns (google.protobuf.BoolValue) {
+ option (aelf.is_view) = true;
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs13.proto b/modules/AElf.Client.Protobuf/Protobuf/acs13.proto
new file mode 100644
index 00000000..2f80e12a
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs13.proto
@@ -0,0 +1,21 @@
+syntax = "proto3";
+
+package acs13;
+import "aelf/options.proto";
+import "aelf/core.proto";
+import "google/protobuf/wrappers.proto";
+
+option (aelf.identity) = "acs13";
+option csharp_namespace = "AElf.Standards.ACS13";
+
+service OracleAggregatorContract {
+ rpc Aggregate (AggregateInput) returns (google.protobuf.StringValue) {
+ }
+}
+
+
+message AggregateInput {
+ repeated string results = 1;
+ repeated int32 frequencies = 2;
+ int32 aggregate_option = 3;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs2.proto b/modules/AElf.Client.Protobuf/Protobuf/acs2.proto
new file mode 100644
index 00000000..637e66e1
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs2.proto
@@ -0,0 +1,30 @@
+/**
+ * AElf Standards ACS2(Parallel Execution Standard)
+ *
+ * Used to provide information for parallel execution of transactions.
+ */
+syntax = "proto3";
+
+package acs2;
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+
+option (aelf.identity) = "acs2";
+option csharp_namespace = "AElf.Standards.ACS2";
+
+service ACS2Base {
+ // Gets the resource information that the transaction execution depends on.
+ rpc GetResourceInfo (aelf.Transaction) returns (ResourceInfo) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message ResourceInfo {
+ // The state path that depends on when writing.
+ repeated aelf.ScopedStatePath write_paths = 1;
+ // The state path that depends on when reading.
+ repeated aelf.ScopedStatePath read_paths = 2;
+ // Whether the transaction is not executed in parallel.
+ bool non_parallelizable = 3;
+}
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs3.proto b/modules/AElf.Client.Protobuf/Protobuf/acs3.proto
new file mode 100644
index 00000000..65ee66e8
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs3.proto
@@ -0,0 +1,207 @@
+/**
+ * AElf Standards ACS3(Contract Proposal Standard)
+ *
+ * Used for governance through proposals.
+ */
+syntax = "proto3";
+
+package acs3;
+
+import public "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import public "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+
+option (aelf.identity) = "acs3";
+option csharp_namespace = "AElf.Standards.ACS3";
+
+service AuthorizationContract {
+ // Create a proposal for which organization members can vote.
+ // When the proposal is released, a transaction will be sent to the specified contract.
+ // Return id of the newly created proposal.
+ rpc CreateProposal (CreateProposalInput) returns (aelf.Hash) {
+ }
+
+ // Approve a proposal according to the proposal ID.
+ rpc Approve (aelf.Hash) returns (google.protobuf.Empty) {
+ }
+
+ // Reject a proposal according to the proposal ID.
+ rpc Reject(aelf.Hash) returns (google.protobuf.Empty) {
+ }
+
+ // Abstain a proposal according to the proposal ID.
+ rpc Abstain(aelf.Hash) returns (google.protobuf.Empty){
+ }
+
+ // Release a proposal according to the proposal ID and send a transaction to the specified contract.
+ rpc Release(aelf.Hash) returns (google.protobuf.Empty){
+ }
+
+ // Change the thresholds associated with proposals.
+ // All fields will be overwritten by the input value and this will affect all current proposals of the organization.
+ // Note: only the organization can execute this through a proposal.
+ rpc ChangeOrganizationThreshold(ProposalReleaseThreshold)returns(google.protobuf.Empty) {
+ }
+
+ // Change the white list of organization proposer.
+ // This method overrides the list of whitelisted proposers.
+ rpc ChangeOrganizationProposerWhiteList(ProposerWhiteList) returns (google.protobuf.Empty){
+ }
+
+ // Create a proposal by system contracts,
+ // and return id of the newly created proposal.
+ rpc CreateProposalBySystemContract(CreateProposalBySystemContractInput) returns (aelf.Hash){
+ }
+
+ // Remove the specified proposal. If the proposal is in effect, the cleanup fails.
+ rpc ClearProposal(aelf.Hash) returns (google.protobuf.Empty){
+ }
+
+ // Get the proposal according to the proposal ID.
+ rpc GetProposal(aelf.Hash) returns (ProposalOutput) {
+ option (aelf.is_view) = true;
+ }
+
+ // Check the existence of an organization.
+ rpc ValidateOrganizationExist(aelf.Address) returns (google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+
+ // Check if the proposer is whitelisted.
+ rpc ValidateProposerInWhiteList(ValidateProposerInWhiteListInput) returns (google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+}
+
+message CreateProposalInput {
+ // The name of the method to call after release.
+ string contract_method_name = 1;
+ // The address of the contract to call after release.
+ aelf.Address to_address = 2;
+ // The parameter of the method to be called after the release.
+ bytes params = 3;
+ // The timestamp at which this proposal will expire.
+ google.protobuf.Timestamp expired_time = 4;
+ // The address of the organization.
+ aelf.Address organization_address = 5;
+ // Url is used for proposal describing.
+ string proposal_description_url = 6;
+ // The token is for proposal id generation and with this token, proposal id can be calculated before proposing.
+ aelf.Hash token = 7;
+}
+
+message ProposalOutput {
+ // The id of the proposal.
+ aelf.Hash proposal_id = 1;
+ // The method that this proposal will call when being released.
+ string contract_method_name = 2;
+ // The address of the target contract.
+ aelf.Address to_address = 3;
+ // The parameters of the release transaction.
+ bytes params = 4;
+ // The date at which this proposal will expire.
+ google.protobuf.Timestamp expired_time = 5;
+ // The address of this proposals organization.
+ aelf.Address organization_address = 6;
+ // The address of the proposer of this proposal.
+ aelf.Address proposer = 7;
+ // Indicates if this proposal is releasable.
+ bool to_be_released = 8;
+ // Approval count for this proposal.
+ int64 approval_count = 9;
+ // Rejection count for this proposal.
+ int64 rejection_count = 10;
+ // Abstention count for this proposal.
+ int64 abstention_count = 11;
+}
+
+message ProposalReleaseThreshold {
+ // The value for the minimum approval threshold.
+ int64 minimal_approval_threshold = 1;
+ // The value for the maximal rejection threshold.
+ int64 maximal_rejection_threshold = 2;
+ // The value for the maximal abstention threshold.
+ int64 maximal_abstention_threshold = 3;
+ // The value for the minimal vote threshold.
+ int64 minimal_vote_threshold = 4;
+}
+
+message ProposerWhiteList{
+ // The address of the proposers
+ repeated aelf.Address proposers = 1;
+}
+
+message OrganizationHashAddressPair{
+ // The id of organization.
+ aelf.Hash organization_hash = 1;
+ // The address of organization.
+ aelf.Address organization_address = 2;
+}
+
+message CreateProposalBySystemContractInput {
+ // The parameters of creating proposal.
+ acs3.CreateProposalInput proposal_input =1;
+ // The actor that trigger the call.
+ aelf.Address origin_proposer = 2;
+}
+
+message ValidateProposerInWhiteListInput{
+ // The address to search/check.
+ aelf.Address proposer = 1;
+ // The address of the organization.
+ aelf.Address organization_address = 2;
+}
+
+message ProposalCreated{
+ option (aelf.is_event) = true;
+ // The id of the created proposal.
+ aelf.Hash proposal_id = 1;
+ // The organization address of the created proposal.
+ aelf.Address organization_address=2 [(aelf.is_indexed) = true];
+}
+
+message ProposalReleased{
+ option (aelf.is_event) = true;
+ // The id of the released proposal.
+ aelf.Hash proposal_id = 1;
+ // The organization address of the released proposal.
+ aelf.Address organization_address=2 [(aelf.is_indexed) = true];
+}
+
+message OrganizationCreated{
+ option (aelf.is_event) = true;
+ // The address of the created organization.
+ aelf.Address organization_address = 1;
+}
+
+message ReceiptCreated {
+ option (aelf.is_event) = true;
+ // The id of the proposal.
+ aelf.Hash proposal_id = 1;
+ // The sender address.
+ aelf.Address address = 2;
+ // The type of receipt(Approve, Reject or Abstain).
+ string receipt_type = 3;
+ // The timestamp of this method call.
+ google.protobuf.Timestamp time = 4;
+ // The address of the organization.
+ aelf.Address organization_address = 5 [(aelf.is_indexed) = true];
+}
+
+message OrganizationWhiteListChanged{
+ option (aelf.is_event) = true;
+ // The organization address.
+ aelf.Address organization_address = 1;
+ // The new proposer whitelist.
+ ProposerWhiteList proposer_white_list = 2;
+}
+
+message OrganizationThresholdChanged{
+ option (aelf.is_event) = true;
+ // The organization address
+ aelf.Address organization_address = 1;
+ // The new release threshold.
+ ProposalReleaseThreshold proposer_release_threshold = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs4.proto b/modules/AElf.Client.Protobuf/Protobuf/acs4.proto
new file mode 100644
index 00000000..0328f538
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs4.proto
@@ -0,0 +1,70 @@
+/**
+ * AElf Standards ACS4(Consensus Standard)
+ *
+ * Used to customize consensus mechanisms.
+ */
+syntax = "proto3";
+
+package acs4;
+
+import "aelf/options.proto";
+import "aelf/core.proto";
+import "google/protobuf/wrappers.proto";
+import "google/protobuf/timestamp.proto";
+
+option (aelf.identity) = "acs4";
+option csharp_namespace = "AElf.Standards.ACS4";
+
+service ConsensusContract {
+ // Generate a consensus command based on the consensus contract state and the input public key.
+ rpc GetConsensusCommand (google.protobuf.BytesValue) returns (ConsensusCommand) {
+ option (aelf.is_view) = true;
+ }
+
+ // Generate consensus extra data when a block is generated.
+ rpc GetConsensusExtraData (google.protobuf.BytesValue) returns (google.protobuf.BytesValue) {
+ option (aelf.is_view) = true;
+ }
+
+ // Generate consensus system transactions when a block is generated.
+ // Each block will contain only one consensus transaction, which is used to write the latest consensus information
+ // to the State database.
+ rpc GenerateConsensusTransactions (google.protobuf.BytesValue) returns (TransactionList) {
+ option (aelf.is_view) = true;
+ }
+
+ // Before executing the block, verify that the consensus information in the block header is correct.
+ rpc ValidateConsensusBeforeExecution (google.protobuf.BytesValue) returns (ValidationResult) {
+ option (aelf.is_view) = true;
+ }
+
+ // After executing the block, verify that the state information written to the consensus is correct.
+ rpc ValidateConsensusAfterExecution (google.protobuf.BytesValue) returns (ValidationResult) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message ConsensusCommand {
+ // Time limit of mining next block.
+ int32 limit_milliseconds_of_mining_block = 1;
+ // Context of Hint is diverse according to the consensus protocol we choose, so we use bytes.
+ bytes hint = 2;
+ // The time of arrange mining.
+ google.protobuf.Timestamp arranged_mining_time = 3;
+ // The expiration time of mining.
+ google.protobuf.Timestamp mining_due_time = 4;
+}
+
+message ValidationResult {
+ // Is successful.
+ bool success = 1;
+ // The error message.
+ string message = 2;
+ // Whether to trigger mining again.
+ bool is_re_trigger = 3;
+}
+
+message TransactionList {
+ // Consensus system transactions.
+ repeated aelf.Transaction transactions = 1;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs5.proto b/modules/AElf.Client.Protobuf/Protobuf/acs5.proto
new file mode 100644
index 00000000..f6de21ed
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs5.proto
@@ -0,0 +1,51 @@
+/**
+ * AElf Standards ACS5(Method Calling Threshold Contract Standard)
+ *
+ * To avoid DDOS attacks, all contracts should theoretically implement AElf Standards ACS5,
+ * setting a threshold for expensive methods. There are two types of call thresholds: check balance only,
+ * and check balance and allowance at the same time.
+ */
+syntax = "proto3";
+
+package acs5;
+
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option (aelf.identity) = "acs5";
+option csharp_namespace = "AElf.Standards.ACS5";
+
+service ThresholdSettingContract {
+ // Set the threshold for method calling.
+ rpc SetMethodCallingThreshold (SetMethodCallingThresholdInput) returns (google.protobuf.Empty) {
+ }
+
+ // Get the threshold for method calling.
+ rpc GetMethodCallingThreshold (google.protobuf.StringValue) returns (MethodCallingThreshold) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message MethodCallingThreshold {
+ // The threshold for method calling, token symbol -> amount.
+ map symbol_to_amount = 1;
+ // The type of threshold check.
+ ThresholdCheckType threshold_check_type = 2;
+}
+
+message SetMethodCallingThresholdInput {
+ // The method name to check.
+ string method = 1;
+ // The threshold for method calling, token symbol -> amount.
+ map symbol_to_amount = 2;
+ // The type of threshold check.
+ ThresholdCheckType threshold_check_type = 3;
+}
+
+enum ThresholdCheckType {
+ // Check balance only.
+ BALANCE = 0;
+ // Check balance and allowance at the same time.
+ ALLOWANCE = 1;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs6.proto b/modules/AElf.Client.Protobuf/Protobuf/acs6.proto
new file mode 100644
index 00000000..f95ba5ed
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs6.proto
@@ -0,0 +1,22 @@
+/**
+ * AElf Standards ACS6(Random Number Standard)
+ *
+ * Used to generate random number.
+ */
+syntax = "proto3";
+
+package acs6;
+
+import "aelf/options.proto";
+import "aelf/core.proto";
+import "google/protobuf/wrappers.proto";
+
+option (aelf.identity) = "acs6";
+option csharp_namespace = "AElf.Standards.ACS6";
+
+service RandomNumberProviderContract {
+ // Get random number according to block height.
+ rpc GetRandomBytes (google.protobuf.BytesValue) returns (google.protobuf.BytesValue) {
+ option (aelf.is_view) = true;
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs7.proto b/modules/AElf.Client.Protobuf/Protobuf/acs7.proto
new file mode 100644
index 00000000..2e9619d1
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs7.proto
@@ -0,0 +1,292 @@
+/**
+ * AElf Standards ACS7(Contract CrossChain Standard)
+ *
+ * ACS7 is for cross chain related contract implementation.
+ */
+syntax = "proto3";
+
+package acs7;
+
+import public "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+import public "google/protobuf/timestamp.proto";
+
+option (aelf.identity) = "acs7";
+option csharp_namespace = "AElf.Standards.ACS7";
+
+service ACS7 {
+
+ // Propose once cross chain indexing.
+ rpc ProposeCrossChainIndexing(CrossChainBlockData) returns (google.protobuf.Empty) {
+ }
+
+ // Release the proposed indexing if already approved.
+ rpc ReleaseCrossChainIndexingProposal(ReleaseCrossChainIndexingProposalInput) returns (google.protobuf.Empty) {
+ }
+
+ // Request side chain creation.
+ rpc RequestSideChainCreation(SideChainCreationRequest) returns (google.protobuf.Empty){
+ }
+
+ // Release the side chain creation request if already approved and it will call the method CreateSideChain.
+ rpc ReleaseSideChainCreation(ReleaseSideChainCreationInput) returns (google.protobuf.Empty){
+ }
+
+ // Create the side chain and returns the newly created side chain ID.
+ // Only SideChainLifetimeController is permitted to invoke this method.
+ rpc CreateSideChain (CreateSideChainInput) returns (google.protobuf.Int32Value) {
+ }
+
+ // Recharge for the specified side chain.
+ rpc Recharge (RechargeInput) returns (google.protobuf.Empty) {
+ }
+
+ // Dispose a side chain according to side chain id.
+ // Only SideChainLifetimeController is permitted to invoke this method.
+ rpc DisposeSideChain (google.protobuf.Int32Value) returns (google.protobuf.Int32Value) {
+ }
+
+ // Adjust side chain indexing fee. Only IndexingFeeController is permitted to invoke this method.
+ rpc AdjustIndexingFeePrice(AdjustIndexingFeeInput)returns(google.protobuf.Empty){
+ }
+
+ // Verify cross chain transaction.
+ rpc VerifyTransaction (VerifyTransactionInput) returns (google.protobuf.BoolValue) {
+ option (aelf.is_view) = true;
+ }
+
+ // Gets all the side chain id and height of the current chain.
+ rpc GetSideChainIdAndHeight (google.protobuf.Empty) returns (ChainIdAndHeightDict) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get indexing information of side chains.
+ rpc GetSideChainIndexingInformationList (google.protobuf.Empty) returns (SideChainIndexingInformationList) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get id and recorded height of all chains.
+ rpc GetAllChainsIdAndHeight (google.protobuf.Empty) returns (ChainIdAndHeightDict) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get block data of indexed side chain according to height.
+ rpc GetIndexedSideChainBlockDataByHeight (google.protobuf.Int64Value) returns (IndexedSideChainBlockData) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get merkle path bound up with side chain according to height.
+ rpc GetBoundParentChainHeightAndMerklePathByHeight (google.protobuf.Int64Value) returns (CrossChainMerkleProofContext) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get initialization data for specified side chain.
+ rpc GetChainInitializationData (google.protobuf.Int32Value) returns (ChainInitializationData) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message SideChainBlockData {
+ // The height of side chain block.
+ int64 height = 1;
+ // The hash of side chain block.
+ aelf.Hash block_header_hash = 2;
+ // The merkle tree root computing from transactions status in side chain block.
+ aelf.Hash transaction_status_merkle_tree_root = 3;
+ // The id of side chain.
+ int32 chain_id = 4;
+}
+
+message RechargeInput {
+ // The chain id to recharge.
+ int32 chain_id = 1;
+ // The amount to recharge.
+ int64 amount = 2;
+}
+
+message ParentChainBlockData {
+ // The height of parent chain.
+ int64 height = 1;
+ // The merkle tree root computing from side chain roots.
+ CrossChainExtraData cross_chain_extra_data = 2;
+ // The parent chain id.
+ int32 chain_id = 3;
+ // The merkle tree root computing from transactions status in parent chain block.
+ aelf.Hash transaction_status_merkle_tree_root = 4;
+ // Indexed block height from side chain and merkle path for this side chain block
+ map indexed_merkle_path = 5;
+ // Extra data map.
+ map extra_data = 6;
+}
+
+message CrossChainExtraData {
+ // Merkle tree root of side chain block transaction status root.
+ aelf.Hash transaction_status_merkle_tree_root = 1;
+}
+
+message ChainIdAndHeightDict {
+ // A collection of chain ids and heights, where the key is the chain id and the value is the height.
+ map id_height_dict = 1;
+}
+
+message SideChainIndexingInformationList {
+ // A list contains indexing information of side chains.
+ repeated SideChainIndexingInformation indexing_information_list = 1;
+}
+
+message SideChainIndexingInformation {
+ // The side chain id.
+ int32 chain_id = 1;
+ // The indexed height.
+ int64 indexed_height = 2;
+}
+
+message CrossChainBlockData {
+ // The side chain block data list to index.
+ repeated SideChainBlockData side_chain_block_data_list = 1;
+ // The parent chain block data list to index.
+ repeated ParentChainBlockData parent_chain_block_data_list = 2;
+}
+
+message CrossChainMerkleProofContext {
+ // The height of parent chain bound up with side chain.
+ int64 bound_parent_chain_height = 1;
+ // The merkle path generated from parent chain.
+ aelf.MerklePath merkle_path_from_parent_chain = 2;
+}
+
+message ChainInitializationData {
+ // The id of side chain.
+ int32 chain_id = 1;
+ // The side chain creator.
+ aelf.Address creator = 2;
+ // The timestamp for side chain creation.
+ google.protobuf.Timestamp creation_timestamp = 3;
+ // The height of side chain creation on parent chain.
+ int64 creation_height_on_parent_chain = 4;
+ // Creator privilege boolean flag: True if chain creator privilege preserved, otherwise false.
+ bool chain_creator_privilege_preserved = 5;
+ // Parent chain token contract address.
+ aelf.Address parent_chain_token_contract_address = 6;
+ // Initial consensus information.
+ ChainInitializationConsensusInfo chain_initialization_consensus_info = 7;
+ // The native token info.
+ bytes native_token_info_data = 8;
+ // The resource token information.
+ ResourceTokenInfo resource_token_info = 9;
+ // The chain primary token information.
+ ChainPrimaryTokenInfo chain_primary_token_info = 10;
+}
+
+message ResourceTokenInfo{
+ // The resource token information.
+ bytes resource_token_list_data = 1;
+ // The initial resource token amount.
+ map initial_resource_amount = 2;
+}
+
+message ChainPrimaryTokenInfo{
+ // The side chain primary token data.
+ bytes chain_primary_token_data = 1;
+ // The side chain primary token initial issue list.
+ repeated SideChainTokenInitialIssue side_chain_token_initial_issue_list = 2;
+}
+
+message ChainInitializationConsensusInfo{
+ // Initial consensus data.
+ bytes initial_consensus_data = 1;
+}
+
+message SideChainCreationRequest {
+ // The cross chain indexing price.
+ int64 indexing_price = 1;
+ // Initial locked balance for a new side chain.
+ int64 locked_token_amount = 2;
+ // Creator privilege boolean flag: True if chain creator privilege preserved, otherwise false.
+ bool is_privilege_preserved = 3;
+ // Side chain token information.
+ SideChainTokenCreationRequest side_chain_token_creation_request = 4;
+ // A list of accounts and amounts that will be issued when the chain starts.
+ repeated SideChainTokenInitialIssue side_chain_token_initial_issue_list = 5;
+ // The initial rent resources.
+ map initial_resource_amount = 6;
+}
+
+message SideChainTokenCreationRequest{
+ // Token symbol of the side chain to be created
+ string side_chain_token_symbol = 1;
+ // Token name of the side chain to be created
+ string side_chain_token_name = 2;
+ // Token total supply of the side chain to be created
+ int64 side_chain_token_total_supply = 3;
+ // Token decimals of the side chain to be created
+ int32 side_chain_token_decimals = 4;
+}
+
+message SideChainTokenInitialIssue{
+ // The account that will be issued.
+ aelf.Address address = 1;
+ // The amount that will be issued.
+ int64 amount = 2;
+}
+
+message IndexedParentChainBlockData {
+ // The height of the local chain when indexing the parent chain.
+ int64 local_chain_height = 1;
+ // Parent chain block data.
+ repeated acs7.ParentChainBlockData parent_chain_block_data_list = 2;
+}
+
+message IndexedSideChainBlockData{
+ // Side chain block data.
+ repeated acs7.SideChainBlockData side_chain_block_data_list = 1;
+}
+
+message ReleaseCrossChainIndexingProposalInput{
+ // List of chain ids to release.
+ repeated int32 chain_id_list = 1;
+}
+
+message CreateSideChainInput{
+ // The request information of the side chain creation.
+ SideChainCreationRequest side_chain_creation_request = 1;
+ // The proposer of the side chain creation.
+ aelf.Address proposer = 2;
+}
+
+message ReleaseSideChainCreationInput {
+ // The proposal id of side chain creation.
+ aelf.Hash proposal_id = 1;
+}
+
+message AdjustIndexingFeeInput{
+ // The side chain id to adjust.
+ int32 side_chain_id = 1;
+ // The new price of indexing fee.
+ int64 indexing_fee = 2;
+}
+
+message SideChainBlockDataIndexed{
+ option (aelf.is_event) = true;
+}
+
+message CrossChainIndexingDataProposedEvent{
+ option (aelf.is_event) = true;
+ // Proposed cross chain data to be indexed.
+ acs7.CrossChainBlockData proposed_cross_chain_data = 1;
+ // The proposal id.
+ aelf.Hash proposal_id = 2;
+}
+
+message VerifyTransactionInput {
+ // The cross chain transaction id to verify.
+ aelf.Hash transaction_id = 1;
+ // The merkle path of the transaction.
+ aelf.MerklePath path = 2;
+ // The height of parent chain that indexing this transaction.
+ int64 parent_chain_height = 3;
+ // The chain if to verify.
+ int32 verified_chain_id = 4;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs8.proto b/modules/AElf.Client.Protobuf/Protobuf/acs8.proto
new file mode 100644
index 00000000..a711fdf4
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs8.proto
@@ -0,0 +1,35 @@
+/**
+ * AElf Standards ACS8(Transaction Resource Token Fee Standard)
+ *
+ * ACS8 has some similarities to ACS1, both of them are charge transaction fee standard.
+ * The difference is that ACS1 charges the user a transaction fee, ACS8 charges the called contract,
+ * and the transaction fee charged by ACS8 is the specified four tokens: WRITE, READ, STORAGE, TRAFFIC.
+ * In another word, if a contract declares that it inherits from ACS8, each transaction in this contract will
+ * charge four kinds of resource token.
+ */
+syntax = "proto3";
+
+package acs8;
+
+import public "aelf/options.proto";
+import public "google/protobuf/empty.proto";
+
+option (aelf.identity) = "acs8";
+option csharp_namespace = "AElf.Standards.ACS8";
+
+service ResourceConsumptionContract {
+ // Buy one of the four resource coins, which consumes the ELF balance in the contract account
+ // (you can recharge it yourself, or you can collect the user’s ELF tokens as a profit to be self-sufficient).
+ rpc BuyResourceToken (BuyResourceTokenInput) returns (google.protobuf.Empty) {
+ }
+}
+
+message BuyResourceTokenInput {
+ // The symbol token you want to buy.
+ string symbol = 1;
+ // The amount you want to buy.
+ int64 amount = 2;
+ // Limit of cost. If the token required for buy exceeds this value, the buy will be abandoned.
+ // And 0 is no limit.
+ int64 pay_limit = 3;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/acs9.proto b/modules/AElf.Client.Protobuf/Protobuf/acs9.proto
new file mode 100644
index 00000000..dedf8e2b
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/acs9.proto
@@ -0,0 +1,52 @@
+/**
+ * AElf Standards ACS9 (Contract Profit Dividend Standard)
+ *
+ * Used for developers implement a profit divided mechanism on the AElf side chain.
+ */
+syntax = "proto3";
+
+package acs9;
+
+import public "aelf/options.proto";
+import public "google/protobuf/empty.proto";
+
+option (aelf.identity) = "acs9";
+option csharp_namespace = "AElf.Standards.ACS9";
+
+service ContractProfitsContract {
+ // Used for the developer to collect the profits from the contract,
+ // and the profits will be distributed in this method.
+ rpc TakeContractProfits (TakeContractProfitsInput) returns (google.protobuf.Empty) {
+ }
+
+ // Query the config of profit.
+ rpc GetProfitConfig (google.protobuf.Empty) returns (ProfitConfig) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the profits of the contract so far.
+ rpc GetProfitsAmount (google.protobuf.Empty) returns (ProfitsMap) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message TakeContractProfitsInput {
+ // The token symbol to take.
+ string symbol = 1;
+ // The amount to take.
+ int64 amount = 2;
+}
+
+message ProfitConfig {
+ // The portion of the profit that will be donated to the dividend pool each time the developer receives the profit.
+ int32 donation_parts_per_hundred = 1;
+ // The profit token symbol list.
+ repeated string profits_token_symbol_list = 2;
+ // The token symbol that the user can lock them to claim the profit.
+ string staking_token_symbol = 3;
+}
+
+message ProfitsMap {
+ // The profits, token symbol -> amount.
+ map value = 1;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/aedpos_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/aedpos_contract.proto
new file mode 100644
index 00000000..05546ab3
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/aedpos_contract.proto
@@ -0,0 +1,440 @@
+/**
+ * AEDPoS contract.
+ */
+syntax = "proto3";
+
+package AEDPoS;
+
+import "aelf/options.proto";
+import "aelf/core.proto";
+import "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 (Round) returns (google.protobuf.Empty) {
+ }
+
+ // Update consensus information, create a new term.
+ rpc NextTerm (Round) 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) {
+ }
+
+ // 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;
+ }
+
+ // 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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/aelf/core.proto b/modules/AElf.Client.Protobuf/Protobuf/aelf/core.proto
new file mode 100644
index 00000000..e4109962
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/aelf/core.proto
@@ -0,0 +1,147 @@
+syntax = "proto3";
+
+package aelf;
+
+option csharp_namespace = "AElf.Types";
+
+message Transaction {
+ // The address of the sender of the transaction.
+ Address from = 1;
+ // The address of the contract when calling a contract.
+ Address to = 2;
+ // The height of the referenced block hash.
+ int64 ref_block_number = 3;
+ // The first four bytes of the referenced block hash.
+ bytes ref_block_prefix = 4;
+ // The name of a method in the smart contract at the To address.
+ string method_name = 5;
+ // The parameters to pass to the smart contract method.
+ bytes params = 6;
+ // When signing a transaction it’s actually a subset of the fields: from/to and the target method as well as
+ // the parameter that were given. It also contains the reference block number and prefix.
+ bytes signature = 10000;
+}
+
+message StatePath {
+ // The partial path of the state path.
+ repeated string parts = 1;
+}
+
+message ScopedStatePath {
+ // The scope address, which will be the contract address.
+ Address address = 1;
+ // The path of contract state.
+ StatePath path = 2;
+}
+
+enum TransactionResultStatus {
+ // The execution result of the transaction does not exist.
+ NOT_EXISTED = 0;
+ // The transaction is in the transaction pool waiting to be packaged.
+ PENDING = 1;
+ // Transaction execution failed.
+ FAILED = 2;
+ // The transaction was successfully executed and successfully packaged into a block.
+ MINED = 3;
+ // When executed in parallel, there are conflicts with other transactions.
+ CONFLICT = 4;
+ // The transaction is waiting for validation.
+ PENDING_VALIDATION = 5;
+ // Transaction validation failed.
+ NODE_VALIDATION_FAILED = 6;
+}
+
+message TransactionResult {
+ // The transaction id.
+ Hash transaction_id = 1;
+ // The transaction result status.
+ TransactionResultStatus status = 2;
+ // The log events.
+ repeated LogEvent logs = 3;
+ // Bloom filter for transaction logs. A transaction log event can be defined in the contract and stored
+ // in the bloom filter after the transaction is executed. Through this filter, we can quickly search for
+ // and determine whether a log exists in the transaction result.
+ bytes bloom = 4;
+ // The return value of the transaction execution.
+ bytes return_value = 5;
+ // The height of the block hat packages the transaction.
+ int64 block_number = 6;
+ // The hash of the block hat packages the transaction.
+ Hash block_hash = 7;
+ // Failed execution error message.
+ string error = 10;
+}
+
+message LogEvent {
+ // The contract address.
+ Address address = 1;
+ // The name of the log event.
+ string name = 2;
+ // The indexed data, used to calculate bloom.
+ repeated bytes indexed = 3;
+ // The non indexed data.
+ bytes non_indexed = 4;
+}
+
+message SmartContractRegistration {
+ // The category of contract code(0: C#).
+ sint32 category = 1;
+ // The byte array of the contract code.
+ bytes code = 2;
+ // The hash of the contract code.
+ Hash code_hash = 3;
+ // Whether it is a system contract.
+ bool is_system_contract = 4;
+ // The version of the current contract.
+ int32 version = 5;
+}
+
+message TransactionExecutingStateSet {
+ // The changed states.
+ map writes = 1;
+ // The read states.
+ map reads = 2;
+ // The deleted states.
+ map deletes = 3;
+}
+
+message Address
+{
+ bytes value = 1;
+}
+
+message Hash
+{
+ bytes value = 1;
+}
+
+message SInt32Value
+{
+ sint32 value = 1;
+}
+
+message SInt64Value
+{
+ sint64 value = 1;
+}
+
+message MerklePath {
+ // The merkle path nodes.
+ repeated MerklePathNode merkle_path_nodes = 1;
+}
+
+message MerklePathNode{
+ // The node hash.
+ Hash hash = 1;
+ // Whether it is a left child node.
+ bool is_left_child_node = 2;
+}
+
+message BinaryMerkleTree {
+ // The leaf nodes.
+ repeated Hash nodes = 1;
+ // The root node hash.
+ Hash root = 2;
+ // The count of leaf node.
+ int32 leaf_count = 3;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/aelf/options.proto b/modules/AElf.Client.Protobuf/Protobuf/aelf/options.proto
new file mode 100644
index 00000000..34058baf
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/aelf/options.proto
@@ -0,0 +1,38 @@
+syntax = "proto3";
+
+package aelf;
+
+import "google/protobuf/descriptor.proto";
+
+option csharp_namespace = "AElf";
+
+// All aelf custom options field numbers are like 50yxxx
+// where y stands for the custom options type:
+// 0 - FileOptions
+// 1 - MessageOptions
+// 2 - FieldOptions
+// 3 - EnumOptions
+// 4 - EnumValueOptions
+// 5 - ServiceOptions
+// 6 - MethodOptions
+
+extend google.protobuf.FileOptions {
+ string identity = 500001;
+}
+
+extend google.protobuf.ServiceOptions {
+ repeated string base = 505001;
+ string csharp_state = 505030;
+}
+
+extend google.protobuf.MethodOptions {
+ bool is_view = 506001;
+}
+
+extend google.protobuf.MessageOptions {
+ bool is_event = 50100;
+}
+
+extend google.protobuf.FieldOptions {
+ bool is_indexed = 502001;
+}
diff --git a/modules/AElf.Client.Protobuf/Protobuf/association_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/association_contract.proto
new file mode 100644
index 00000000..2efb8210
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/association_contract.proto
@@ -0,0 +1,144 @@
+/**
+ * Association contract.
+ */
+syntax = "proto3";
+
+package Association;
+
+import "acs3.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.Association";
+
+service AssociationContract {
+
+ option (aelf.csharp_state) = "AElf.Contracts.Association.AssociationState";
+
+ // Create an organization and return its address.
+ rpc CreateOrganization (CreateOrganizationInput) returns (aelf.Address) {
+ }
+
+ // Creates an organization by system contract and return its address.
+ rpc CreateOrganizationBySystemContract(CreateOrganizationBySystemContractInput) returns (aelf.Address){
+ }
+
+ // Add organization members.
+ rpc AddMember(aelf.Address) returns (google.protobuf.Empty){
+ }
+
+ // Remove organization members.
+ rpc RemoveMember(aelf.Address) returns (google.protobuf.Empty){
+ }
+
+ // Replace organization member with a new member.
+ rpc ChangeMember(ChangeMemberInput) returns (google.protobuf.Empty){
+ }
+
+ // Get the organization according to the organization address.
+ rpc GetOrganization (aelf.Address) returns (Organization) {
+ option (aelf.is_view) = true;
+ }
+
+ // Calculate the input and return the organization address.
+ rpc CalculateOrganizationAddress(CreateOrganizationInput) returns (aelf.Address){
+ option (aelf.is_view) = true;
+ }
+}
+
+message CreateOrganizationInput{
+ // Initial organization members.
+ OrganizationMemberList organization_member_list = 1;
+ // The threshold for releasing the proposal.
+ acs3.ProposalReleaseThreshold proposal_release_threshold = 2;
+ // The proposer whitelist.
+ acs3.ProposerWhiteList proposer_white_list = 3;
+ // The creation token is for organization address generation.
+ aelf.Hash creation_token = 4;
+}
+
+message Organization{
+ // The organization members.
+ OrganizationMemberList organization_member_list = 1;
+ // The threshold for releasing the proposal.
+ acs3.ProposalReleaseThreshold proposal_release_threshold = 2;
+ // The proposer whitelist.
+ acs3.ProposerWhiteList proposer_white_list = 3;
+ // The address of organization.
+ aelf.Address organization_address = 4;
+ // The organizations id.
+ aelf.Hash organization_hash = 5;
+ // The creation token is for organization address generation.
+ aelf.Hash creation_token = 6;
+}
+
+message ProposalInfo {
+ // The proposal ID.
+ aelf.Hash proposal_id = 1;
+ // The method that this proposal will call when being released.
+ string contract_method_name = 2;
+ // The address of the target contract.
+ aelf.Address to_address = 3;
+ // The parameters of the release transaction.
+ bytes params = 4;
+ // The date at which this proposal will expire.
+ google.protobuf.Timestamp expired_time = 5;
+ // The address of the proposer of this proposal.
+ aelf.Address proposer = 6;
+ // The address of this proposals organization.
+ aelf.Address organization_address = 7;
+ // Address list of approved.
+ repeated aelf.Address approvals = 8;
+ // Address list of rejected.
+ repeated aelf.Address rejections = 9;
+ // Address list of abstained.
+ repeated aelf.Address abstentions = 10;
+ // Url is used for proposal describing.
+ string proposal_description_url = 11;
+}
+
+message OrganizationMemberList {
+ // The address of organization members.
+ repeated aelf.Address organization_members = 1;
+}
+
+message ChangeMemberInput{
+ // The old member address.
+ aelf.Address old_member = 1;
+ // The new member address.
+ aelf.Address new_member = 2;
+}
+
+message CreateOrganizationBySystemContractInput {
+ // The parameters of creating organization.
+ CreateOrganizationInput organization_creation_input = 1;
+ // The organization address callback method which replies the organization address to caller contract.
+ string organization_address_feedback_method = 2;
+}
+
+message MemberAdded{
+ option (aelf.is_event) = true;
+ // The added member address.
+ aelf.Address member = 1;
+ // The organization address.
+ aelf.Address organization_address = 2 [(aelf.is_indexed) = true];
+}
+
+message MemberRemoved{
+ option (aelf.is_event) = true;
+ // The removed member address.
+ aelf.Address member = 1;
+ // The organization address.
+ aelf.Address organization_address = 2 [(aelf.is_indexed) = true];
+}
+
+message MemberChanged{
+ option (aelf.is_event) = true;
+ // The old member address.
+ aelf.Address old_member = 1;
+ // The new member address.
+ aelf.Address new_member = 2;
+ // The organization address.
+ aelf.Address organization_address = 3 [(aelf.is_indexed) = true];
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/authority_info.proto b/modules/AElf.Client.Protobuf/Protobuf/authority_info.proto
new file mode 100644
index 00000000..65302e8b
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/authority_info.proto
@@ -0,0 +1,10 @@
+syntax = "proto3";
+
+import "aelf/core.proto";
+
+message AuthorityInfo {
+ // The contract address of the controller.
+ aelf.Address contract_address = 1;
+ // The address of the owner of the contract.
+ aelf.Address owner_address = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/basic_contract_zero.proto b/modules/AElf.Client.Protobuf/Protobuf/basic_contract_zero.proto
new file mode 100644
index 00000000..5c14ec09
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/basic_contract_zero.proto
@@ -0,0 +1,71 @@
+/**
+ * Genesis contract.
+ */
+syntax = "proto3";
+
+package Zero;
+
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "aelf/core.proto";
+import "google/protobuf/timestamp.proto";
+import "authority_info.proto";
+
+option csharp_namespace = "AElf.Contracts.Genesis";
+
+service BasicContractZero {
+ option (aelf.csharp_state) = "AElf.Contracts.Genesis.BasicContractZeroState";
+
+ // Initialize the genesis contract.
+ rpc Initialize (InitializeInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set initial controller address for CodeCheckController and ContractDeploymentController.
+ rpc SetInitialControllerAddress (aelf.Address) returns (google.protobuf.Empty) {
+ }
+
+ // Modify the contract deployment controller authority.
+ // Note: Only old controller has permission to do this.
+ rpc ChangeContractDeploymentController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Modify the contract code check controller authority.
+ // Note: Only old controller has permission to do this.
+ rpc ChangeCodeCheckController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Query the ContractDeploymentController authority info.
+ rpc GetContractDeploymentController (google.protobuf.Empty) returns (AuthorityInfo) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the CodeCheckController authority info.
+ rpc GetCodeCheckController(google.protobuf.Empty) returns (AuthorityInfo){
+ option (aelf.is_view) = true;
+ }
+}
+
+message InitializeInput{
+ // Whether contract deployment/update requires authority.
+ bool contract_deployment_authority_required = 1;
+}
+
+message ContractProposingInput{
+ // The address of proposer for contract deployment/update.
+ aelf.Address proposer = 1;
+ // The status of proposal.
+ ContractProposingInputStatus status = 2;
+ // The expiration time of proposal.
+ google.protobuf.Timestamp expired_time = 3;
+}
+
+enum ContractProposingInputStatus {
+ // Proposal is proposed.
+ PROPOSED = 0;
+ // Proposal is approved by parliament.
+ APPROVED = 1;
+ // Code check is proposed.
+ CODE_CHECK_PROPOSED = 2;
+ // Passed code checks.
+ CODE_CHECKED = 3;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/bridge_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/bridge_contract.proto
new file mode 100644
index 00000000..d90d70f3
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/bridge_contract.proto
@@ -0,0 +1,338 @@
+syntax = "proto3";
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+import "callback_input.proto";
+import "acs13.proto";
+import "receipt_maker.proto";
+
+option csharp_namespace = "AElf.Contracts.Bridge";
+
+service BridgeContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Bridge.BridgeContractState";
+ option (aelf.base) = "acs13.proto";
+ option (aelf.base) = "receipt_maker.proto";
+
+ rpc Initialize (InitializeInput) returns (google.protobuf.Empty) {}
+
+ //To AElf.
+ rpc CreateSwap (CreateSwapInput) returns (aelf.Hash) {
+ }
+ rpc SwapToken (SwapTokenInput) returns (google.protobuf.Empty) {
+ }
+ rpc ChangeSwapRatio (ChangeSwapRatioInput) returns (google.protobuf.Empty) {
+ }
+ rpc Deposit (DepositInput) returns (google.protobuf.Empty) {
+ }
+ rpc Withdraw (WithdrawInput) returns (google.protobuf.Empty) {
+ }
+ rpc RecordReceiptHash (CallbackInput) returns (google.protobuf.Empty) {
+ }
+
+ //AElf to others.
+ rpc AddToken(AddTokenInput) returns(google.protobuf.Empty){
+ }
+ rpc RemoveToken(RemoveTokenInput) returns (google.protobuf.Empty){
+ }
+ rpc CreateReceipt(CreateReceiptInput) returns (google.protobuf.Empty){
+ }
+
+ //Gas Fee
+ rpc SetGasFee(SetGasFeeInput) returns(google.protobuf.Empty){
+ }
+ rpc SetGasPrice(SetGasPriceInput) returns (google.protobuf.Empty){
+ }
+ rpc SetPriceRatio(SetPriceRatioInput) returns (google.protobuf.Empty){
+ }
+ rpc GetGasFee(google.protobuf.StringValue) returns (google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+ rpc GetGasPrice(google.protobuf.StringValue) returns(google.protobuf.StringValue){
+ option (aelf.is_view) = true;
+ }
+ rpc GetPriceRatio(google.protobuf.StringValue) returns (google.protobuf.StringValue){
+ option (aelf.is_view) = true;
+ }
+
+ rpc SetController(aelf.Address) returns(google.protobuf.Empty){
+ }
+
+ rpc GetReceiptIdInfo(aelf.Hash) returns (ReceiptIdInfo){
+ option (aelf.is_view) = true;
+ }
+ rpc GetOwnerLockReceipt(GetOwnerLockReceiptInput) returns (ReceiptIdList){
+ option (aelf.is_view) = true;
+ }
+ rpc GetLockTokens(GetLockTokensInput) returns(google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+ rpc GetReceiptInfo(GetReceiptInfoInput) returns (Receipt){
+ option (aelf.is_view) = true;
+ }
+
+ // view methods
+
+ rpc GetSwapInfo (aelf.Hash) returns (SwapInfo) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetSwapAmounts (GetSwapAmountsInput) returns (SwapAmounts) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetRegimentIdBySpaceId (aelf.Hash) returns (aelf.Hash) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetSwappedReceiptIdList (GetSwappedReceiptIdListInput) returns (ReceiptIdList) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetSwappedReceiptInfoList (GetSwappedReceiptInfoListInput) returns (ReceiptInfoList) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetSpaceIdBySwapId (aelf.Hash) returns (aelf.Hash){
+ option (aelf.is_view) = true;
+ }
+}
+
+message InitializeInput {
+ aelf.Address oracle_contract_address = 1;
+ aelf.Address merkle_tree_contract_address = 2;
+ aelf.Address regiment_contract_address = 3;
+ aelf.Address report_contract_address = 4;
+ aelf.Address admin = 5;
+}
+//To AElf message.
+message CreateSwapInput {
+ repeated SwapTargetToken swap_target_token_list = 1;
+ aelf.Hash regiment_id = 2;
+ int32 merkle_tree_leaf_limit = 3;
+}
+
+message SwapTargetToken {
+ string symbol = 1;
+ SwapRatio swap_ratio = 2;
+ string from_chain_id = 3;
+}
+
+message SwapInfo {
+ aelf.Hash swap_id = 1;
+ repeated SwapTargetToken swap_target_token_list = 2;
+ aelf.Hash regiment_id = 3;
+ aelf.Hash space_id = 4;
+}
+
+
+message SwapPairInfo {
+ int64 swapped_amount = 1;
+ int64 swapped_times = 2;
+ int64 deposit_amount = 3;
+}
+
+message SwapRatio {
+ int64 origin_share = 1;
+ int64 target_share = 2;
+}
+
+message SwapAmounts {
+ aelf.Address receiver = 1;
+ map received_amounts = 2;
+}
+
+message ReceiptInfo {
+ string receipt_id = 1;
+ aelf.Hash receiving_tx_id = 2;
+ google.protobuf.Timestamp receiving_time = 3;
+ map amount_map = 4;
+}
+
+message ReceiptInfoList {
+ repeated ReceiptInfo value = 1;
+}
+
+message ReceiptHashMap {
+ map value = 1;
+ string swap_id = 2;
+}
+
+message ReceiptIdList {
+ repeated string value = 1;
+}
+
+
+message ReceiptIdInfo{
+ string chain_id = 1;
+ string symbol = 2;
+}
+
+message SendingInfo {
+ int64 receipt_id = 1;
+ string sending_tx_id = 2;
+ string sending_time = 3;
+}
+
+message ChangeSwapRatioInput {
+ aelf.Hash swap_id = 1;
+ SwapRatio swap_ratio = 2;
+ string target_token_symbol = 3;
+}
+
+message SwapTokenInput {
+ aelf.Hash swap_id = 1;
+ string receipt_id = 2;
+ string origin_amount = 3;
+ aelf.Address receiver_address = 4;
+}
+
+message DepositInput {
+ aelf.Hash swap_id = 1;
+ string target_token_symbol = 2;
+ int64 amount = 3;
+}
+
+message GetSwapPairInput {
+ aelf.Hash swap_id = 1;
+ string symbol = 2;
+}
+
+message GetSwapAmountsInput {
+ aelf.Hash swap_id = 1;
+ string receipt_id = 2;
+}
+
+message WithdrawInput {
+ aelf.Hash swap_id = 1;
+ string target_token_symbol = 2;
+ int64 amount = 3;
+}
+
+message GetSwappedReceiptIdListInput {
+ aelf.Hash swap_id = 1;
+ aelf.Address receiver_address = 2;
+}
+
+message GetSwappedReceiptInfoListInput {
+ aelf.Hash swap_id = 1;
+ aelf.Address receiver_address = 2;
+}
+
+//AElf to others message.
+message Receipt{
+ string symbol = 1;
+ aelf.Address owner = 2;
+ string targetAddress = 3;
+ int64 amount = 4;
+}
+message ReceiptList{
+ repeated Receipt value = 1;
+}
+
+message AddTokenInput{
+ StringList symbol = 1;
+}
+
+message TokenSymbolList {
+ StringList symbol = 1;
+}
+
+message RemoveTokenInput{
+ StringList symbol = 1;
+}
+
+message CreateReceiptInput{
+ string symbol = 1;
+ aelf.Address owner = 2;
+ string targetAddress = 3;
+ int64 amount = 4;
+ string target_chain_id = 5;
+}
+
+message SetGasFeeInput{
+ repeated GasFee gas_fee_list = 1;
+}
+message SetGasPriceInput{
+ repeated GasPrice gas_price_list = 1;
+}
+
+message GasPrice{
+ string chain_id = 1;
+ int64 gas_price = 2;
+}
+
+message GasFee{
+ string chain_id = 1;
+ int64 gas_fee = 2;
+}
+
+message SetPriceRatioInput{
+ repeated PriceRatio value = 1;
+}
+message PriceRatio{
+ string target_chain_id = 1;
+ int64 price_ratio = 2;
+}
+
+
+message GetReceiptInfoInput{
+ string receipt_id = 1;
+}
+
+message GetOwnerLockReceiptInput{
+ aelf.Address owner = 1;
+}
+
+message GetLockTokensInput{
+ aelf.Address owner = 1;
+}
+
+message StringList{
+ repeated string value = 1;
+}
+
+
+
+
+// Events
+
+message SwapRatioChanged {
+ option (aelf.is_event) = true;
+ aelf.Hash swap_id = 1;
+ SwapRatio new_swap_ratio = 2;
+ string target_token_symbol = 3;
+}
+
+message TokenSwapped {
+ option (aelf.is_event) = true;
+ aelf.Address address = 1;
+ int64 amount = 2;
+ string symbol = 3;
+ string receipt_id = 4;
+ string from_chain_id = 5;
+}
+
+message SwapInfoAdded {
+ option (aelf.is_event) = true;
+ aelf.Hash swap_id = 1;
+ string from_chain_id = 2;
+ string symbol = 3;
+}
+
+message TokenWhitelistAdded{
+ option (aelf.is_event) = true;
+ StringList token_list = 1;
+}
+
+message TokenWhitelistRemoved{
+ option (aelf.is_event) = true;
+ StringList token_list = 1;
+}
+
+message ReceiptCreated{
+ option (aelf.is_event) = true;
+ string receipt_id = 1;
+ string symbol = 2;
+ aelf.Address owner = 3;
+ string targetAddress = 4;
+ int64 amount = 5;
+ string target_chain_id = 6;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/callback_input.proto b/modules/AElf.Client.Protobuf/Protobuf/callback_input.proto
new file mode 100644
index 00000000..c3898290
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/callback_input.proto
@@ -0,0 +1,9 @@
+syntax = "proto3";
+
+import "aelf/core.proto";
+
+message CallbackInput {
+ aelf.Hash query_id = 1;
+ bytes result = 2;
+ repeated aelf.Address oracle_nodes = 3;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/configuration_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/configuration_contract.proto
new file mode 100644
index 00000000..041e7266
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/configuration_contract.proto
@@ -0,0 +1,52 @@
+/**
+ * Configuration contract.
+ */
+syntax = "proto3";
+
+package Configuration;
+
+import "aelf/core.proto";
+import "google/protobuf/wrappers.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "authority_info.proto";
+
+option csharp_namespace = "AElf.Contracts.Configuration";
+
+service Configuration {
+ option (aelf.csharp_state) = "AElf.Contracts.Configuration.ConfigurationState";
+
+ // Add or update configuration.
+ rpc SetConfiguration (SetConfigurationInput) returns (google.protobuf.Empty) {
+ }
+
+ // Change the method fee controller, the default is Parliament.
+ rpc ChangeConfigurationController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Query the configuration by configuration’s key.
+ rpc GetConfiguration (google.protobuf.StringValue) returns (google.protobuf.BytesValue) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the controller information
+ rpc GetConfigurationController (google.protobuf.Empty) returns (AuthorityInfo) {
+ option (aelf.is_view) = true;
+ }
+
+}
+
+message SetConfigurationInput {
+ // The configuration’s key.
+ string key = 1;
+ // The configuration’s value(binary data).
+ bytes value = 2;
+}
+
+message ConfigurationSet {
+ option (aelf.is_event) = true;
+ // The configuration’s key.
+ string key = 1;
+ // The configuration’s value(binary data).
+ bytes value = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/cross_chain_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/cross_chain_contract.proto
new file mode 100644
index 00000000..5441a661
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/cross_chain_contract.proto
@@ -0,0 +1,266 @@
+/**
+ * Cross-Chain contract.
+ */
+syntax = "proto3";
+
+package CrossChain;
+
+import "acs7.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+import "authority_info.proto";
+
+option csharp_namespace = "AElf.Contracts.CrossChain";
+
+service CrossChainContract {
+
+ option (aelf.csharp_state) = "AElf.Contracts.CrossChain.CrossChainContractState";
+
+ // Propose once cross chain indexing.
+ rpc Initialize (InitializeInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set the initial SideChainLifetimeController address which should be parliament organization by default.
+ rpc SetInitialSideChainLifetimeControllerAddress(aelf.Address) returns (google.protobuf.Empty){
+ }
+
+ // Set the initial CrossChainIndexingController address which should be parliament organization by default.
+ rpc SetInitialIndexingControllerAddress(aelf.Address) returns (google.protobuf.Empty){
+ }
+
+ // Change the cross chain indexing controller.
+ rpc ChangeCrossChainIndexingController(AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Change the lifetime controller of the side chain.
+ rpc ChangeSideChainLifetimeController(AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Change indexing fee adjustment controller for specific side chain.
+ rpc ChangeSideChainIndexingFeeController(ChangeSideChainIndexingFeeControllerInput) returns (google.protobuf.Empty){
+ }
+
+ // When the indexing proposal is released, clean up the pending proposal.
+ rpc AcceptCrossChainIndexingProposal(AcceptCrossChainIndexingProposalInput) returns (google.protobuf.Empty){
+ }
+
+ // Get the side chain creator address according to side chain id.
+ rpc GetSideChainCreator (google.protobuf.Int32Value) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the current status of side chain according to side chain id.
+ rpc GetChainStatus (google.protobuf.Int32Value) returns (GetChainStatusOutput) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the side chain height according to side chain id.
+ rpc GetSideChainHeight (google.protobuf.Int32Value) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the height of parent chain.
+ rpc GetParentChainHeight (google.protobuf.Empty) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the chain id of parent chain.
+ rpc GetParentChainId (google.protobuf.Empty) returns (google.protobuf.Int32Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the balance of side chain indexing according to side chain id.
+ rpc GetSideChainBalance (google.protobuf.Int32Value) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the fee debt of side chain indexing according to side chain id.
+ rpc GetSideChainIndexingFeeDebt (google.protobuf.Int32Value) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the status of the current indexing proposal.
+ rpc GetIndexingProposalStatus (google.protobuf.Empty) returns (GetIndexingProposalStatusOutput) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the side chain indexing fee price according to side chain id.
+ rpc GetSideChainIndexingFeePrice(google.protobuf.Int32Value) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the lifetime controller of the side chain.
+ rpc GetSideChainLifetimeController(google.protobuf.Empty) returns (AuthorityInfo){
+ option (aelf.is_view) = true;
+ }
+
+ // Get the cross chain indexing controller.
+ rpc GetCrossChainIndexingController(google.protobuf.Empty) returns (AuthorityInfo){
+ option (aelf.is_view) = true;
+ }
+
+ // Get the indexing fee controller of side chain according to side chain id.
+ rpc GetSideChainIndexingFeeController(google.protobuf.Int32Value) returns (AuthorityInfo){
+ option (aelf.is_view) = true;
+ }
+}
+
+message InitializeInput {
+ // The id of parent chain.
+ int32 parent_chain_id = 1;
+ // The height of side chain created on parent chain.
+ int64 creation_height_on_parent_chain = 2;
+ // True if chain privilege needed, otherwise false.
+ bool is_privilege_preserved = 3;
+}
+
+message SideChainCreatedEvent {
+ option (aelf.is_event) = true;
+ // The proposer who propose to create the side chain.
+ aelf.Address creator = 1;
+ // The created side chain id.
+ int32 chainId = 2;
+}
+
+message Disposed {
+ option (aelf.is_event) = true;
+ // The disposed side chain id.
+ int32 chain_id = 1;
+}
+
+message ProposedCrossChainIndexing{
+ // The collection of chain indexing proposal, the key is chain id.
+ map chain_indexing_proposal_collections = 1;
+}
+
+message ChainIndexingProposal{
+ // The id of cross chain indexing proposal.
+ aelf.Hash proposal_id = 1;
+ // The proposer of cross chain indexing.
+ aelf.Address proposer = 2;
+ // The cross chain data proposed.
+ acs7.CrossChainBlockData proposed_cross_chain_block_data = 3;
+ // The status of of cross chain indexing proposal.
+ CrossChainIndexingProposalStatus status = 4;
+ // The chain id of the indexing.
+ int32 chain_id = 5;
+}
+
+message GetIndexingProposalStatusOutput{
+ // The collection of pending indexing proposal, the key is chain id.
+ map chain_indexing_proposal_status = 1;
+}
+
+message PendingChainIndexingProposalStatus{
+ // The id of cross chain indexing proposal.
+ aelf.Hash proposal_id = 1;
+ // The proposer of cross chain indexing.
+ aelf.Address proposer = 2;
+ // True if the proposal can be released, otherwise false.
+ bool to_be_released = 3;
+ // The cross chain data proposed.
+ acs7.CrossChainBlockData proposed_cross_chain_block_data = 4;
+ // The proposal expiration time.
+ google.protobuf.Timestamp expired_time = 5;
+}
+
+message GetPendingCrossChainIndexingProposalOutput{
+ // The proposal id of cross chain indexing.
+ aelf.Hash proposal_id = 1;
+ // The proposer of cross chain indexing proposal.
+ aelf.Address proposer = 2;
+ // True if the proposal can be released, otherwise false.
+ bool to_be_released = 3;
+ // The cross chain data proposed.
+ acs7.CrossChainBlockData proposed_cross_chain_block_data = 4;
+ // The proposal expiration time.
+ google.protobuf.Timestamp expired_time = 5;
+}
+
+enum CrossChainIndexingProposalStatus{
+ NON_PROPOSED = 0;
+ // The proposal is pending.
+ PENDING = 1;
+ // The proposal has been released.
+ ACCEPTED = 2;
+}
+
+enum SideChainStatus
+{
+ // Currently no meaning.
+ FATAL = 0;
+ // The side chain is being indexed.
+ ACTIVE = 1;
+ // The side chain is in debt for indexing fee.
+ INDEXING_FEE_DEBT = 2;
+ // The side chain is disposed.
+ TERMINATED = 3;
+}
+
+message SideChainInfo {
+ // The proposer who propose to create the side chain.
+ aelf.Address proposer = 1;
+ // The status of side chain.
+ SideChainStatus side_chain_status = 2;
+ // The side chain id.
+ int32 side_chain_id = 3;
+ // The time of side chain created.
+ google.protobuf.Timestamp creation_timestamp = 4;
+ // The height of side chain created on parent chain.
+ int64 creation_height_on_parent_chain = 5;
+ // The price of indexing fee.
+ int64 indexing_price = 6;
+ // True if chain privilege needed, otherwise false.
+ bool is_privilege_preserved = 7;
+ // creditor and amounts for the chain indexing fee debt
+ map arrears_info = 8;
+ // The controller of indexing fee.
+ AuthorityInfo indexing_fee_controller = 9;
+}
+
+message GetChainStatusOutput{
+ // The status of side chain.
+ SideChainStatus status = 1;
+}
+
+message SideChainCreationRequestState{
+ // The parameters of creating side chain.
+ acs7.SideChainCreationRequest side_chain_creation_request = 1;
+ // The expiration date of the proposal.
+ google.protobuf.Timestamp expired_time = 2;
+ // The proposer who proposed to create the side chain.
+ aelf.Address proposer = 3;
+}
+
+message ChangeSideChainIndexingFeeControllerInput{
+ // The side chain id.
+ int32 chain_id = 1;
+ // The changed controller of indexing fee.
+ AuthorityInfo authority_info = 2;
+}
+
+message SideChainLifetimeControllerChanged{
+ option (aelf.is_event) = true;
+ // The changed controller of side chain lifetime.
+ AuthorityInfo authority_info = 1;
+}
+
+message CrossChainIndexingControllerChanged{
+ option (aelf.is_event) = true;
+ // The changed controller of indexing.
+ AuthorityInfo authority_info = 1;
+}
+
+message SideChainIndexingFeeControllerChanged{
+ option (aelf.is_event) = true;
+ // The side chain id.
+ int32 chain_id = 1 [(aelf.is_indexed) = true];
+ // The changed controller of side chain indexing fee.
+ AuthorityInfo authority_info = 2;
+}
+
+message AcceptCrossChainIndexingProposalInput{
+ // The chain id of accepted indexing.
+ int32 chain_id = 1;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/economic_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/economic_contract.proto
new file mode 100644
index 00000000..943fe740
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/economic_contract.proto
@@ -0,0 +1,62 @@
+/**
+ * Economic contract.
+ */
+syntax = "proto3";
+
+package Economic;
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+
+option csharp_namespace = "AElf.Contracts.Economic";
+
+service EconomicContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Economic.EconomicContractState";
+
+ // Only ZeroContract is able to issue the native token.
+ rpc IssueNativeToken (IssueNativeTokenInput) returns (google.protobuf.Empty) {
+ }
+
+ // It will initialize other contracts related to economic activities (For instance, create the native token).
+ // This transaction only can be send once because after the first sending, its state will be set to initialized.
+ rpc InitialEconomicSystem (InitialEconomicSystemInput) returns (google.protobuf.Empty) {
+ }
+}
+
+message InitialEconomicSystemInput {
+ // The native token symbol.
+ string native_token_symbol = 1;
+ // The native token name.
+ string native_token_name = 2;
+ // The native token total supply.
+ int64 native_token_total_supply = 3;
+ // The accuracy of the native token.
+ int32 native_token_decimals = 4;
+ // It indicates if the token is burnable.
+ bool is_native_token_burnable = 5;
+ // It determines how much native token is used to reward the miners.
+ int64 mining_reward_total_amount = 6;
+ // todo : remove unused fields
+ int64 transaction_size_fee_unit_price = 7;
+}
+
+message IssueNativeTokenInput {
+ // The amount of token.
+ int64 amount = 1;
+ // The memo.
+ string memo = 2;
+ // The recipient of the token.
+ aelf.Address to = 3;
+}
+
+message IssueResourceTokenInput {
+ // The symbol of resource token.
+ string symbol = 1;
+ // The amount of resource token.
+ int64 amount = 2;
+ // The memo.
+ string memo = 3;
+ // The recipient of the token.
+ aelf.Address to = 4;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/election_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/election_contract.proto
new file mode 100644
index 00000000..0337e7c4
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/election_contract.proto
@@ -0,0 +1,522 @@
+/**
+ * Election contract.
+ */
+syntax = "proto3";
+
+package Election;
+
+import "aelf/core.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+import "google/protobuf/empty.proto";
+import "aelf/options.proto";
+import "authority_info.proto";
+
+option csharp_namespace = "AElf.Contracts.Election";
+
+service ElectionContract {
+
+ option (aelf.csharp_state) = "AElf.Contracts.Election.ElectionContractState";
+
+ // Initialize the election contract.
+ rpc InitialElectionContract (InitialElectionContractInput) returns (google.protobuf.Empty) {
+ }
+
+ // Register a new voting item through vote contract.
+ rpc RegisterElectionVotingEvent (google.protobuf.Empty) returns (google.protobuf.Empty) {
+ }
+
+ // Take snapshot according to term number, and distribute profits.
+ rpc TakeSnapshot (TakeElectionSnapshotInput) returns (google.protobuf.Empty) {
+ }
+
+ // To be a block producer, a user should first register to be a candidate and lock some token as a deposit.
+ // If the data center is not full, the user will be added in automatically and get one weight
+ // for sharing bonus in the future.
+ rpc AnnounceElection (aelf.Address) returns (google.protobuf.Empty) {
+ }
+
+ // A candidate is able to quit the election provided he is not currently elected. If you quit successfully,
+ // the candidate will get his locked tokens back and will not receive anymore bonus.
+ rpc QuitElection (google.protobuf.StringValue) returns (google.protobuf.Empty) {
+ }
+
+ // Used for voting for a candidate to be elected. The tokens you vote with will be locked until the end time.
+ // According to the number of token you voted and its lock time, you can get corresponding weight for
+ // sharing the bonus in the future. And return the vote id.
+ rpc Vote (VoteMinerInput) returns (aelf.Hash) {
+ }
+
+ // Before the end time, you are able to change your vote target to other candidates.
+ rpc ChangeVotingOption (ChangeVotingOptionInput) returns (google.protobuf.Empty) {
+ }
+
+ rpc FixWelfareProfit (FixWelfareProfitInput) returns (google.protobuf.Empty) {
+ }
+
+ rpc DisableWelfareFix (google.protobuf.Empty) returns (google.protobuf.Empty) {
+ }
+
+ // After the lock time, your locked tokens will be unlocked and you can withdraw them according to the vote id.
+ rpc Withdraw (aelf.Hash) returns (google.protobuf.Empty) {
+ }
+
+ // Update candidate information by consensus contract.
+ rpc UpdateCandidateInformation (UpdateCandidateInformationInput) returns (google.protobuf.Empty) {
+ }
+
+ // Batch update candidate information by consensus contract.
+ rpc UpdateMultipleCandidateInformation (UpdateMultipleCandidateInformationInput) returns (google.protobuf.Empty) {
+ }
+
+ // Update the count of miner by consensus contract.
+ rpc UpdateMinersCount (UpdateMinersCountInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set the treasury profit ids.
+ rpc SetTreasurySchemeIds (SetTreasurySchemeIdsInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set the weight of vote interest.
+ rpc SetVoteWeightInterest (VoteWeightInterestList) returns (google.protobuf.Empty) {
+ }
+
+ // Set the weight of lock time and votes in the calculation of voting weight.
+ rpc SetVoteWeightProportion (VoteWeightProportion) returns (google.protobuf.Empty) {
+ }
+
+ // Change the controller for the weight of vote interest.
+ rpc ChangeVoteWeightInterestController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Candidate admin can replace candidate pubkey with a new pubkey.
+ rpc ReplaceCandidatePubkey (ReplaceCandidatePubkeyInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set admin address of candidate (mostly supply)
+ rpc SetCandidateAdmin (SetCandidateAdminInput) returns (google.protobuf.Empty) {
+ }
+
+ rpc RemoveEvilNode (google.protobuf.StringValue) returns (google.protobuf.Empty) {
+ }
+
+ // Views
+
+ // Get all candidates’ public keys.
+ rpc GetCandidates (google.protobuf.Empty) returns (PubkeyList) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get all candidates whose number of votes is greater than 0.
+ rpc GetVotedCandidates (google.protobuf.Empty) returns (PubkeyList) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get a candidate’s information.
+ rpc GetCandidateInformation (google.protobuf.StringValue) returns (CandidateInformation) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the victories of the latest term.
+ rpc GetVictories (google.protobuf.Empty) returns (PubkeyList) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the snapshot of term according to term number.
+ rpc GetTermSnapshot (GetTermSnapshotInput) returns (TermSnapshot) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the count of miner.
+ rpc GetMinersCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the election result according to term id.
+ rpc GetElectionResult (GetElectionResultInput) returns (ElectionResult) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the voter information according to voter public key.
+ rpc GetElectorVote (google.protobuf.StringValue) returns (ElectorVote) {
+ option (aelf.is_view) = true;
+ }
+
+ // Gets the voter information including the active voting records (excluding withdrawn voting records.).
+ rpc GetElectorVoteWithRecords (google.protobuf.StringValue) returns (ElectorVote) {
+ option (aelf.is_view) = true;
+ }
+
+ // Gets the voter information including the active and withdrawn voting records.
+ rpc GetElectorVoteWithAllRecords (google.protobuf.StringValue) returns (ElectorVote) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get voting information for candidate according to the public key of the candidate.
+ rpc GetCandidateVote (google.protobuf.StringValue) returns (CandidateVote) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get voting information for candidate according to the public key of the candidate.
+ rpc GetCandidateVoteWithRecords (google.protobuf.StringValue) returns (CandidateVote) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get voting information for candidate according to the public key of the candidate
+ // (including the active and withdrawn voting records).
+ rpc GetCandidateVoteWithAllRecords (google.protobuf.StringValue) returns (CandidateVote) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the total number of voters.
+ rpc GetVotersCount (google.protobuf.Empty) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the total number of vote token.
+ rpc GetVotesAmount (google.protobuf.Empty) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get candidate information according to the index and length.
+ rpc GetPageableCandidateInformation (PageInformation) returns (GetPageableCandidateInformationOutput) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the voting item id of miner election.
+ rpc GetMinerElectionVotingItemId (google.protobuf.Empty) returns (aelf.Hash) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the data center ranking list.
+ rpc GetDataCenterRankingList (google.protobuf.Empty) returns (DataCenterRankingList) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the weight of vote interest.
+ rpc GetVoteWeightSetting (google.protobuf.Empty) returns (VoteWeightInterestList) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the weight of lock time and votes in the calculation of voting weight.
+ rpc GetVoteWeightProportion (google.protobuf.Empty) returns (VoteWeightProportion) {
+ option (aelf.is_view) = true;
+ }
+
+ // Used to calculate the bonus weights that users can get by voting.
+ rpc GetCalculateVoteWeight (VoteInformation) returns (google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+
+ // Query the controller for the weight of vote interest.
+ rpc GetVoteWeightInterestController (google.protobuf.Empty) returns (AuthorityInfo) {
+ option (aelf.is_view) = true;
+ }
+
+ // Inspect the evil nodes included in the specified miners and return to the replacement node.
+ rpc GetMinerReplacementInformation (GetMinerReplacementInformationInput) returns (MinerReplacementInformation) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query candidate admin.
+ rpc GetCandidateAdmin (google.protobuf.StringValue) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the newest pubkey of an old pubkey.
+ rpc GetNewestPubkey (google.protobuf.StringValue) returns (google.protobuf.StringValue) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the old pubkey.
+ rpc GetReplacedPubkey (google.protobuf.StringValue) returns (google.protobuf.StringValue) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message InitialElectionContractInput {
+ // Minimum number of seconds for locking.
+ int64 minimum_lock_time = 1;
+ // Maximum number of seconds for locking.
+ int64 maximum_lock_time = 2;
+ // The current miner list.
+ repeated string miner_list = 3;
+ // The number of seconds per term.
+ int64 time_each_term = 4;
+ // The interval second that increases the number of miners.
+ int64 miner_increase_interval = 5;
+}
+
+message GetTermSnapshotInput {
+ // The term number.
+ int64 term_number = 1;
+}
+
+message UpdateCandidateInformationInput {
+ // The candidate public key.
+ string pubkey = 1;
+ // The number of blocks recently produced.
+ int64 recently_produced_blocks = 2;
+ // The number of time slots recently missed.
+ int64 recently_missed_time_slots = 3;
+ // Is it a evil node. If true will remove the candidate.
+ bool is_evil_node = 4;
+}
+
+message UpdateMultipleCandidateInformationInput {
+ // The candidate information to update.
+ repeated UpdateCandidateInformationInput value = 1;
+}
+
+message TakeElectionSnapshotInput {
+ // The term number to take snapshot.
+ int64 term_number = 1;
+ // The number of mined blocks of this term.
+ int64 mined_blocks = 2;
+ // The end round number of this term.
+ int64 round_number = 3;
+}
+
+message VoteMinerInput {
+ // The candidate public key.
+ string candidate_pubkey = 1;
+ // The amount token to vote.
+ int64 amount = 2;
+ // The end timestamp of this vote.
+ google.protobuf.Timestamp end_timestamp = 3;
+ // Used to generate vote id.
+ aelf.Hash token = 4;
+}
+
+message ChangeVotingOptionInput {
+ // The vote id to change.
+ aelf.Hash vote_id = 1;
+ // The new candidate public key.
+ string candidate_pubkey = 2;
+ // Tokens will be locked another previous locking time if this is true.
+ bool is_reset_voting_time = 3;
+}
+
+message FixWelfareProfitInput {
+ repeated FixWelfareProfitInfo fix_info_list = 1;
+}
+
+message FixWelfareProfitInfo {
+ aelf.Hash vote_id = 1;
+ int64 start_period = 2;
+ int64 end_period = 3;
+}
+
+message UpdateTermNumberInput {
+ // The term number.
+ int64 term_number = 1;
+}
+
+message GetElectionResultInput {
+ // The term number.
+ int64 term_number = 1;
+}
+
+message ElectionResult {
+ // The term number
+ int64 term_number = 1;
+ // The election result, candidates’ public key -> number of votes.
+ map results = 2;
+ // Whether an election is currently being held.
+ bool is_active = 3;
+}
+
+message ElectorVote {
+ // The active voting record ids.
+ repeated aelf.Hash active_voting_record_ids = 1;
+ // The voting record ids that were withdrawn.
+ repeated aelf.Hash withdrawn_voting_record_ids = 2;
+ // The total number of active votes.
+ int64 active_voted_votes_amount = 3;
+ // The total number of votes (including the number of votes withdrawn).
+ int64 all_voted_votes_amount = 4;
+ // The active voting records.
+ repeated ElectionVotingRecord active_voting_records = 5;
+ // The voting records that were withdrawn.
+ repeated ElectionVotingRecord withdrawn_votes_records = 6;
+ // Public key for voter.
+ bytes pubkey = 7;
+}
+
+message CandidateVote {
+ // The active voting record ids obtained.
+ repeated aelf.Hash obtained_active_voting_record_ids = 1;
+ // The active voting record ids that were withdrawn.
+ repeated aelf.Hash obtained_withdrawn_voting_record_ids = 2;
+ // The total number of active votes obtained.
+ int64 obtained_active_voted_votes_amount = 3;
+ // The total number of votes obtained.
+ int64 all_obtained_voted_votes_amount = 4;
+ // The active voting records.
+ repeated ElectionVotingRecord obtained_active_voting_records = 5;
+ // The voting records that were withdrawn.
+ repeated ElectionVotingRecord obtained_withdrawn_votes_records = 6;
+ // Public key for candidate.
+ bytes pubkey = 7;
+}
+
+message CandidateInformation {
+ // Candidate’s public key.
+ string pubkey = 1;
+ // The number of terms that the candidate is elected.
+ repeated int64 terms = 2;
+ // The number of blocks the candidate has produced.
+ int64 produced_blocks = 3;
+ // The time slot for which the candidate failed to produce blocks.
+ int64 missed_time_slots = 4;
+ // The count of continual appointment.
+ int64 continual_appointment_count = 5;
+ // The transaction id when the candidate announced.
+ aelf.Hash announcement_transaction_id = 6;
+ // Indicate whether the candidate can be elected in the current term.
+ bool is_current_candidate = 7;
+}
+
+message CandidateDetail {
+ // The candidate information.
+ CandidateInformation candidate_information = 1;
+ // The number of votes a candidate has obtained.
+ int64 obtained_votes_amount = 2;
+}
+
+message ElectionVotingRecord {
+ // The address of voter.
+ aelf.Address voter = 1;
+ // The public key of candidate.
+ string candidate = 2;
+ // Amount of voting.
+ int64 amount = 3;
+ // The term number of voting.
+ int64 term_number = 4;
+ // The vote id.
+ aelf.Hash vote_id = 5;
+ // Vote lock time.
+ int64 lock_time = 6;
+ // The unlock timestamp.
+ google.protobuf.Timestamp unlock_timestamp = 7;
+ // The withdraw timestamp.
+ google.protobuf.Timestamp withdraw_timestamp = 8;
+ // The vote timestamp.
+ google.protobuf.Timestamp vote_timestamp = 9;
+ // Indicates if the vote has been withdrawn.
+ bool is_withdrawn = 10;
+ // Vote weight for sharing bonus.
+ int64 weight = 11;
+ // Whether vote others.
+ bool is_change_target = 12;
+}
+
+message PageInformation {
+ // The start index.
+ int32 start = 1;
+ // The number of records.
+ int32 length = 2;
+}
+
+message PubkeyList {
+ // Candidates’ public keys
+ repeated bytes value = 1;
+}
+
+message TermSnapshot {
+ // The end round number of this term.
+ int64 end_round_number = 1;
+ // The number of blocks mined in this term.
+ int64 mined_blocks = 2;
+ // The election result, candidates’ public key -> number of votes.
+ map election_result = 3;
+}
+
+message UpdateMinersCountInput {
+ // The count of miner.
+ int32 miners_count = 1;
+}
+
+message GetPageableCandidateInformationOutput {
+ // The details of the candidates.
+ repeated CandidateDetail value = 1;
+}
+
+message SetTreasurySchemeIdsInput {
+ // The scheme id of treasury reward.
+ aelf.Hash treasury_hash = 1;
+ // The scheme id of welfare reward.
+ aelf.Hash welfare_hash = 2;
+ // The scheme id of subsidy reward.
+ aelf.Hash subsidy_hash = 3;
+ // The scheme id of welcome reward.
+ aelf.Hash welcome_hash = 4;
+ // The scheme id of flexible reward.
+ aelf.Hash flexible_hash = 5;
+}
+
+message DataCenterRankingList {
+ // The top n * 5 candidates with vote amount, candidate public key -> vote amount.
+ map data_centers = 1;
+}
+
+message VoteWeightInterest{
+ // Number of days locked.
+ int32 day = 1;
+ // Locked interest.
+ int32 interest = 2;
+ int32 capital = 3;
+}
+
+message VoteWeightInterestList {
+ // The weight of vote interest.
+ repeated VoteWeightInterest vote_weight_interest_infos = 1;
+}
+
+message VoteWeightProportion {
+ // The weight of lock time.
+ int32 time_proportion = 1;
+ // The weight of the votes cast.
+ int32 amount_proportion = 2;
+}
+
+message VoteInformation{
+ // Amount of voting.
+ int64 amount = 1;
+ // Vote lock time.
+ int64 lock_time = 2;
+}
+
+message GetMinerReplacementInformationInput {
+ // The current miner list to inspect.
+ repeated string current_miner_list = 1;
+}
+
+message MinerReplacementInformation {
+ // The alternative candidate public keys.
+ repeated string alternative_candidate_pubkeys = 1;
+ // The evil miner public keys.
+ repeated string evil_miner_pubkeys = 2;
+}
+
+message ReplaceCandidatePubkeyInput {
+ string old_pubkey = 1;
+ string new_pubkey = 2;
+}
+
+message SetCandidateAdminInput {
+ string pubkey = 1;
+ aelf.Address admin = 2;
+}
+
+message EvilMinerDetected {
+ option (aelf.is_event) = true;
+ // The public key of evil miner.
+ string pubkey = 1;
+}
+
+message CandidatePubkeyReplaced {
+ option (aelf.is_event) = true;
+ string old_pubkey = 1;
+ string new_pubkey = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/kernel.proto b/modules/AElf.Client.Protobuf/Protobuf/kernel.proto
new file mode 100644
index 00000000..4a9c404c
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/kernel.proto
@@ -0,0 +1,183 @@
+syntax = "proto3";
+
+package aelf;
+
+import "google/protobuf/timestamp.proto";
+import "aelf/core.proto";
+
+option csharp_namespace = "AElf.Kernel";
+
+enum TransactionStatus {
+ UNKNOWN_TRANSACTION_STATUS = 0;
+ TRANSACTION_EXECUTING = 1;
+ TRANSACTION_EXECUTED = 2;
+}
+
+message StateValue {
+ bytes current_value = 1;
+ bytes original_value = 2;
+}
+
+message StateChange {
+ StatePath state_path = 1;
+ StateValue state_value = 2;
+}
+
+// For failed transactions, its status follows the Min of
+// its own status and its inline transactions'
+enum ExecutionStatus {
+ UNDEFINED = 0;
+ // Successful =>
+ EXECUTED = 1;
+
+ // Failed =>
+ // Infrastructure reasons
+ CANCELED = -1;
+ SYSTEM_ERROR = -2;
+
+ // Contract reasons
+ CONTRACT_ERROR = -10;
+ EXCEEDED_MAX_CALL_DEPTH = -11;
+
+ // Pre-failed
+ PREFAILED = -99;
+
+ // Post-failed
+ POSTFAILED = -199;
+}
+
+message TransactionTrace {
+ Hash transaction_id = 1;
+ bytes return_value = 2;
+ string error = 3;
+ repeated Transaction pre_transactions = 4;
+ repeated TransactionTrace pre_traces = 5;
+ repeated Transaction inline_transactions = 6;
+ repeated TransactionTrace inline_traces = 7;
+ repeated Transaction post_transactions = 8;
+ repeated TransactionTrace post_traces = 9;
+ repeated LogEvent logs = 10;
+ int64 elapsed = 11;
+ ExecutionStatus execution_status = 12;
+ TransactionExecutingStateSet state_set = 13;
+}
+
+message ExecutionReturnSet {
+ Hash transaction_id = 1;
+ TransactionResultStatus status = 2;
+ map state_changes = 3;
+ map state_accesses = 4;
+ bytes bloom = 5;
+ bytes return_value = 6;
+ map state_deletes = 7;
+ TransactionResult transaction_result = 8;
+}
+
+message BlockHeaderList {
+ repeated BlockHeader headers = 1;
+}
+
+message BlockHeader {
+ int32 version = 1;
+ int32 chain_id = 2;
+ Hash previous_block_hash = 3;
+ Hash merkle_tree_root_of_transactions = 4;
+ Hash merkle_tree_root_of_world_state = 5;
+ bytes bloom = 6;
+ int64 height = 7;
+ map extra_data = 8;
+ google.protobuf.Timestamp time = 9;
+ Hash merkle_tree_root_of_transaction_status = 10;
+ bytes signer_pubkey = 9999;
+ bytes signature = 10000;
+}
+
+message BlockBody {
+ repeated Hash transaction_ids = 1;
+}
+
+message Block {
+ BlockHeader header = 1;
+ BlockBody body = 2;
+}
+
+message VersionedState {
+ string key = 1;
+ bytes value = 2;
+ int64 block_height = 3;
+ Hash block_hash = 4;
+ Hash origin_block_hash = 5;
+}
+
+message BlockStateSet {
+ Hash block_hash = 1;
+ Hash previous_hash = 2;
+ int64 block_height = 3;
+ map changes = 4;
+ repeated string deletes = 5;
+ map block_executed_data = 6;
+}
+
+enum ChainStateMergingStatus {
+ COMMON = 0;
+ MERGING = 1;
+ MERGED = 2;
+}
+
+message ChainStateInfo {
+ int32 chain_id = 1;
+ Hash block_hash = 2;
+ int64 block_height = 3;
+ Hash merging_block_hash = 4;
+ ChainStateMergingStatus status = 5;
+}
+
+enum ChainBlockLinkExecutionStatus {
+ EXECUTION_NONE = 0;
+ EXECUTION_SUCCESS = 1;
+ EXECUTION_FAILED = 2;
+}
+
+message ChainBlockLink {
+ Hash block_hash = 1;
+ int64 height = 2;
+ Hash previous_block_hash = 3;
+ ChainBlockLinkExecutionStatus execution_status = 4;
+ bool is_irreversible_block = 5;
+ bool is_linked = 6;
+ bool is_light_block = 7; //no block body
+}
+
+message Chain {
+ int32 id = 1;
+ Hash genesis_block_hash = 2;
+ Hash longest_chain_hash = 3;
+ int64 longest_chain_height = 4;
+ map branches = 5;
+ map not_linked_blocks = 6;
+ Hash last_irreversible_block_hash = 7;
+ int64 last_irreversible_block_height = 8;
+ Hash best_chain_hash = 9;
+ int64 best_chain_height = 10;
+}
+
+message ChainBlockIndex {
+ Hash block_hash = 1;
+}
+
+message BlockIndex{
+ Hash block_hash = 1;
+ int64 block_height = 2;
+}
+
+message TransactionBlockIndex {
+ Hash block_hash = 1;
+ int64 block_height = 2;
+ repeated BlockIndex previous_execution_block_index_list = 3;
+}
+
+message SmartContractAddress{
+ Address address = 1;
+ Hash block_hash = 2;
+ int64 block_height = 3;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/merkle_tree_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/merkle_tree_contract.proto
new file mode 100644
index 00000000..1c89ead0
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/merkle_tree_contract.proto
@@ -0,0 +1,219 @@
+syntax = "proto3";
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+import "acs1.proto";
+import "receipt_maker.proto";
+
+option csharp_namespace = "AElf.Contracts.MerkleTreeContract";
+
+service MerkleTreeContract {
+ option (aelf.csharp_state) = "AElf.Contracts.MerkleTreeContract.MerkleTreeContractState";
+ option (aelf.base) = "acs1.proto";
+
+ rpc Initialize(InitializeInput) returns(google.protobuf.Empty){
+ }
+ rpc CreateSpace(CreateSpaceInput) returns(google.protobuf.Empty){
+ }
+ rpc RecordMerkleTree(RecordMerkleTreeInput) returns(google.protobuf.Empty){
+ }
+
+ // regiment related
+
+ rpc CreateRegiment (CreateRegimentInput) returns (google.protobuf.Empty) {
+ }
+ rpc JoinRegiment (JoinRegimentInput) returns (google.protobuf.Empty) {
+ }
+ rpc LeaveRegiment (LeaveRegimentInput) returns (google.protobuf.Empty) {
+ }
+ rpc AddRegimentMember (AddRegimentMemberInput) returns (google.protobuf.Empty) {
+ }
+ rpc DeleteRegimentMember (DeleteRegimentMemberInput) returns (google.protobuf.Empty) {
+ }
+ rpc TransferRegimentOwnership (TransferRegimentOwnershipInput) returns (google.protobuf.Empty) {
+ }
+ rpc AddAdmins (AddAdminsInput) returns (google.protobuf.Empty) {
+ }
+ rpc DeleteAdmins (DeleteAdminsInput) returns (google.protobuf.Empty) {
+ }
+
+ rpc ConstructMerkleTree(ConstructMerkleTreeInput) returns(MerkleTreeList){
+ option (aelf.is_view) = true;
+ }
+ rpc GetMerklePath(GetMerklePathInput) returns(aelf.MerklePath){
+ option (aelf.is_view) = true;
+ }
+ rpc MerkleProof(MerkleProofInput) returns(google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+ rpc GetRegimentSpaceCount(aelf.Hash) returns(google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+ rpc GetRegimentSpaceIdList(aelf.Hash) returns(HashList){
+ option (aelf.is_view) = true;
+ }
+ rpc GetSpaceInfo(aelf.Hash) returns(SpaceInfo){
+ option(aelf.is_view) = true;
+ }
+ rpc GetMerkleTreeByIndex(GetMerkleTreeByIndexInput) returns (MerkleTree){
+ option (aelf.is_view) = true;
+ }
+ rpc GetMerkleTreeCountBySpace(aelf.Hash) returns(google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+ rpc GetLastMerkleTreeIndex(aelf.Hash) returns (google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+ rpc GetLastLeafIndex(GetLastLeafIndexInput) returns (google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+ rpc GetFullTreeCount(aelf.Hash) returns(google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+ rpc GetLeafLocatedMerkleTree(GetLeafLocatedMerkleTreeInput) returns(GetLeafLocatedMerkleTreeOutput){
+ option (aelf.is_view) = true;
+ }
+ rpc GetRemainLeafCount(aelf.Hash) returns(google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+}
+
+
+message SpaceInfo{
+ int64 max_leaf_count = 1;
+ aelf.Hash operators = 2;
+}
+
+message MerkleTree{
+ aelf.Hash space_id = 1;
+ int64 merkle_tree_index = 2;
+ int64 first_leaf_index = 3;
+ int64 last_leaf_index = 4;
+ aelf.Hash merkle_tree_root = 5;
+ bool is_full_tree = 6;
+}
+
+message MerkleTreeList{
+ repeated MerkleTree value = 1;
+}
+
+message HashList{
+ repeated aelf.Hash value = 1;
+}
+
+message InitializeInput{
+ aelf.Address owner = 1;
+ aelf.Address regiment_contract_address = 2;
+}
+
+message CreateSpaceInput{
+ SpaceInfo value = 1;
+}
+
+message ConstructMerkleTreeInput{
+ aelf.Hash space_id = 1;
+ repeated aelf.Hash leaf_node_hash = 2;
+}
+
+message RecordMerkleTreeInput{
+ aelf.Hash space_id = 1;
+ repeated aelf.Hash leaf_node_hash = 2;
+}
+
+
+message GetMerkleTreeByIndexInput{
+ aelf.Hash space_id = 1;
+ int64 merkle_tree_index = 2;
+}
+
+message GetMerklePathInput{
+ aelf.Hash space_id = 1;
+ int64 leaf_node_index = 2;
+ aelf.Address receipt_maker = 3;
+}
+
+message MerkleProofInput{
+ aelf.Hash space_id = 1;
+ aelf.Hash leaf_node = 2;
+ aelf.MerklePath merkle_path = 3;
+ int64 last_leaf_index = 4;
+}
+
+message GetLastLeafIndexInput{
+ aelf.Hash space_id = 1;
+}
+
+message GetLeafLocatedMerkleTreeInput {
+ aelf.Hash space_id = 1;
+ int64 leaf_index = 2;
+}
+
+
+message GetLeafLocatedMerkleTreeOutput {
+ aelf.Hash space_id = 1;
+ int64 merkle_tree_index = 2;
+ int64 first_leaf_index = 3;
+ int64 last_leaf_index = 4;
+}
+
+//Regiment
+message CreateRegimentInput {
+ aelf.Address manager = 1;
+ repeated aelf.Address initial_member_list = 2;
+ bool is_approve_to_join = 3;
+}
+
+message JoinRegimentInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_member_address = 2;
+}
+
+message LeaveRegimentInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address leave_member_address = 2;
+}
+
+message AddRegimentMemberInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_member_address = 2;
+}
+
+message DeleteRegimentMemberInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address delete_member_address = 2;
+}
+
+message TransferRegimentOwnershipInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_manager_address = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message AddAdminsInput {
+ aelf.Address regiment_address = 1;
+ repeated aelf.Address new_admins = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message DeleteAdminsInput {
+ aelf.Address regiment_address = 1;
+ repeated aelf.Address delete_admins = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message SpaceCreated{
+ option (aelf.is_event) = true;
+ aelf.Hash regiment_id = 1;
+ aelf.Hash space_id = 2;
+ SpaceInfo space_info = 3;
+}
+
+message MerkleTreeRecorded{
+ option (aelf.is_event) = true;
+ aelf.Address regiment_member_address = 1;
+ aelf.Hash space_id = 2;
+ int64 merkle_tree_index = 3;
+ int64 last_leaf_index = 4;
+}
diff --git a/modules/AElf.Client.Protobuf/Protobuf/nft_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/nft_contract.proto
new file mode 100644
index 00000000..b3521f6f
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/nft_contract.proto
@@ -0,0 +1,505 @@
+/**
+ * NFT contract.
+ */
+syntax = "proto3";
+
+package nft;
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "acs1.proto";
+import "transaction_fee.proto";
+import "authority_info.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.NFT";
+
+service NFTContract {
+ option (aelf.csharp_state) = "AElf.Contracts.NFT.NFTContractState";
+ option (aelf.base) = "acs1.proto";
+
+ // Create a new nft protocol.
+ rpc Create (CreateInput) returns (google.protobuf.StringValue) {
+ }
+ rpc CrossChainCreate (CrossChainCreateInput) returns (google.protobuf.Empty) {
+ }
+ // Mint (Issue) an amount of nft.
+ rpc Mint (MintInput) returns (aelf.Hash) {
+ }
+ // Transfer nft to another address.
+ rpc Transfer (TransferInput) returns (google.protobuf.Empty) {
+ }
+ // Transfer nft from one address to another.
+ rpc TransferFrom (TransferFromInput) returns (google.protobuf.Empty) {
+ }
+ // Approve another address to transfer nft from own account.
+ rpc Approve (ApproveInput) returns (google.protobuf.Empty) {
+ }
+ // De-approve.
+ rpc UnApprove (UnApproveInput) returns (google.protobuf.Empty) {
+ }
+ // Approve or de-approve another address as the operator of all NFTs of a certain protocol.
+ rpc ApproveProtocol (ApproveProtocolInput) returns (google.protobuf.Empty) {
+ }
+ // Destroy nfts.
+ rpc Burn (BurnInput) returns (google.protobuf.Empty) {
+ }
+ // Lock several nfts and fts to mint one nft.
+ rpc Assemble (AssembleInput) returns (aelf.Hash) {
+ }
+ // Disassemble one assembled nft to get locked nfts and fts back.
+ rpc Disassemble (DisassembleInput) returns (google.protobuf.Empty) {
+ }
+ // Modify metadata of one nft.
+ rpc Recast (RecastInput) returns (google.protobuf.Empty) {
+ }
+
+ rpc AddMinters (AddMintersInput) returns (google.protobuf.Empty) {
+ }
+ rpc RemoveMinters (RemoveMintersInput) returns (google.protobuf.Empty) {
+ }
+
+ rpc AddNFTType (AddNFTTypeInput) returns (google.protobuf.Empty) {
+ }
+ rpc RemoveNFTType (google.protobuf.StringValue) returns (google.protobuf.Empty) {
+ }
+
+ rpc GetNFTProtocolInfo (google.protobuf.StringValue) returns (NFTProtocolInfo) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetNFTInfo (GetNFTInfoInput) returns (NFTInfo) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetNFTInfoByTokenHash (aelf.Hash) returns (NFTInfo) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetBalance (GetBalanceInput) returns (GetBalanceOutput) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetBalanceByTokenHash (GetBalanceByTokenHashInput) returns (GetBalanceOutput) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetAllowance (GetAllowanceInput) returns (GetAllowanceOutput) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetAllowanceByTokenHash (GetAllowanceByTokenHashInput) returns (GetAllowanceOutput) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetMinterList (google.protobuf.StringValue) returns (MinterList) {
+ option (aelf.is_view) = true;
+ }
+ rpc CalculateTokenHash (CalculateTokenHashInput) returns (aelf.Hash) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetNFTTypes (google.protobuf.Empty) returns (NFTTypes) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetOperatorList (GetOperatorListInput) returns (AddressList) {
+ option (aelf.is_view) = true;
+ }
+}
+
+// Structs
+message NFTTypes {
+ map value = 1;
+}
+
+// Inputs
+message CreateInput {
+ // The type of this nft protocol.
+ string nft_type = 1;
+ // The name of this nft protocol.
+ string protocol_name = 2;
+ // The total supply of the token.
+ int64 total_supply = 3;
+ // The address that created the token.
+ aelf.Address creator = 4;
+ // A flag indicating if this token is burnable.
+ bool is_burnable = 5;
+ // The chain id of the token.
+ int32 issue_chain_id = 6;
+ // The metadata of the token.
+ Metadata metadata = 7;
+ // Base Uri.
+ string base_uri = 8;
+ // Is token id can be reused.
+ bool is_token_id_reuse = 9;
+ // Initial minter list (creator will be added automatically)
+ MinterList minter_list = 10;
+}
+
+message CrossChainCreateInput {
+ string symbol = 1;
+}
+
+message TransferInput {
+ aelf.Address to = 1;
+ string symbol = 2;
+ int64 token_id = 3;
+ string memo = 4;
+ int64 amount = 5;
+}
+
+message TransferFromInput {
+ aelf.Address from = 1;
+ aelf.Address to = 2;
+ string symbol = 3;
+ int64 token_id = 4;
+ string memo = 5;
+ int64 amount = 6;
+}
+
+message ApproveInput {
+ aelf.Address spender = 1;
+ string symbol = 2;
+ int64 token_id = 3;
+ int64 amount = 4;
+}
+
+message UnApproveInput {
+ aelf.Address spender = 1;
+ string symbol = 2;
+ int64 token_id = 3;
+ int64 amount = 4;
+}
+
+message ApproveProtocolInput {
+ aelf.Address operator = 1;
+ string symbol = 2;
+ bool approved = 3;
+}
+
+message AddressList {
+ repeated aelf.Address value = 1;
+}
+
+message GetOperatorListInput {
+ string symbol = 1;
+ aelf.Address owner = 2;
+}
+
+message BurnInput {
+ string symbol = 1;
+ int64 token_id = 2;
+ int64 amount = 3;
+}
+
+message AssembleInput {
+ string symbol = 1;
+ aelf.Address owner = 2;
+ string uri = 3;
+ string alias = 4;
+ Metadata metadata = 5;
+ AssembledNfts assembled_nfts = 6;
+ AssembledFts assembled_fts = 7;
+ int64 token_id = 8;
+}
+
+message DisassembleInput {
+ string symbol = 1;
+ int64 token_id = 2;
+ aelf.Address owner = 3;
+}
+
+message MinterList {
+ repeated aelf.Address value = 1;
+}
+
+message MintInput {
+ string symbol = 1;
+ aelf.Address owner = 2;
+ string uri = 3;
+ string alias = 4;
+ Metadata metadata = 5;
+ int64 quantity = 6;
+ int64 token_id = 7;
+}
+
+message GetBalanceInput {
+ aelf.Address owner = 1;
+ string symbol = 2;
+ int64 token_id = 3;
+}
+
+message GetBalanceByTokenHashInput {
+ aelf.Address owner = 1;
+ aelf.Hash token_hash = 2;
+}
+
+message GetBalanceOutput {
+ aelf.Address owner = 1;
+ aelf.Hash token_hash = 2;
+ int64 balance = 3;
+}
+
+message GetAllowanceInput {
+ string symbol = 1;
+ int64 token_id = 2;
+ aelf.Address owner = 3;
+ aelf.Address spender = 4;
+}
+
+message GetAllowanceByTokenHashInput {
+ aelf.Hash token_hash = 1;
+ aelf.Address owner = 2;
+ aelf.Address spender = 3;
+}
+
+message GetAllowanceOutput {
+ aelf.Hash token_hash = 1;
+ int64 allowance = 2;
+ aelf.Address owner = 3;
+ aelf.Address spender = 4;
+}
+
+message CalculateTokenHashInput {
+ string symbol = 1;
+ int64 token_id = 2;
+}
+
+message NFTProtocolInfo {
+ // The symbol of the token.
+ string symbol = 1;
+ // The minted number of the token.
+ int64 supply = 2;
+ // The total number of the token.
+ int64 total_supply = 3;
+ // The address that creat the token.
+ aelf.Address creator = 4;
+ // Base Uri.
+ string base_uri = 5;
+ // A flag indicating if this token is burnable.
+ bool is_burnable = 6;
+ // The chain to mint this token.
+ int32 issue_chain_id = 7;
+ // The metadata of the token.
+ Metadata metadata = 8;
+ // NFT Type.
+ string nft_type = 9;
+ // Protocol name, aka token name in MultiToken Contract.
+ string protocol_name = 10;
+ // Is token id can be reused.
+ bool is_token_id_reuse = 11;
+ int64 issued = 12;
+}
+
+message NFTInfo {
+ // The symbol of the protocol this nft belongs to.
+ string symbol = 1;
+ // The name of the protocol this nft belongs to.
+ string protocol_name = 2;
+ // Actually is the order of this token.
+ int64 token_id = 3;
+ // The address that creat the base token.
+ aelf.Address creator = 4;
+ // The addresses that mint this token.
+ repeated aelf.Address minters = 5;
+ // The metadata of the token.
+ Metadata metadata = 6;
+ // Minted amount.
+ int64 quantity = 7;
+ // Token Uri.
+ string uri = 8;
+ // Base Uri.
+ string base_uri = 9;
+ // Alias
+ string alias = 10;
+ // Is burned.
+ bool is_burned = 11;
+ // NFT Type
+ string nft_type = 12;
+}
+
+enum NFTType {
+ ANY = 0;
+ ART = 1;
+ MUSIC = 2;
+ DOMAIN_NAMES = 3;
+ VIRTUAL_WORLDS = 4;
+ TRADING_CARDS = 5;
+ COLLECTABLES = 6;
+ SPORTS = 7;
+ UTILITY = 8;
+ BADGES = 9;
+}
+
+message Metadata {
+ map value = 1;
+}
+
+message AddMintersInput {
+ MinterList minter_list = 1;
+ string symbol = 2;
+}
+
+message RemoveMintersInput {
+ MinterList minter_list = 1;
+ string symbol = 2;
+}
+
+message GetNFTInfoInput {
+ string symbol = 1;
+ int64 token_id = 2;
+}
+
+message RecastInput {
+ string symbol = 1;
+ int64 token_id = 2;
+ string uri = 3;
+ string alias = 4;
+ Metadata metadata = 5;
+}
+
+message AssembledNfts {
+ map value = 1;
+}
+
+message AssembledFts {
+ map value = 1;
+}
+
+message AddNFTTypeInput {
+ string full_name = 1;
+ string short_name = 2;
+}
+
+// Events
+
+message NFTProtocolCreated {
+ option (aelf.is_event) = true;
+ // The symbol of this protocol.
+ string symbol = 1;
+ // The name of this protocol.
+ string protocol_name = 2;
+ // The total supply of the token.
+ int64 total_supply = 3;
+ // The address that created the token.
+ aelf.Address creator = 4;
+ // A flag indicating if this token is burnable.
+ bool is_burnable = 5;
+ // The chain id of the token.
+ int32 issue_chain_id = 6;
+ // The metadata of the token.
+ Metadata metadata = 7;
+ // Base Uri.
+ string base_uri = 8;
+ // Is token id can be reused.
+ bool is_token_id_reuse = 9;
+ string nft_type = 10;
+}
+
+message NFTMinted {
+ option (aelf.is_event) = true;
+ // The symbol of this protocol.
+ string symbol = 1;
+ // The name of this protocol.
+ string protocol_name = 2;
+ // Actually is the order of this token.
+ int64 token_id = 3;
+ // The address that creat the base token.
+ aelf.Address creator = 4;
+ // The address that mint this token.
+ aelf.Address minter = 5;
+ // The metadata of the token.
+ Metadata metadata = 6;
+ // The current owner of this nft.
+ aelf.Address owner = 7;
+ // Token Uri.
+ string uri = 8;
+ // Base Uri.
+ string base_uri = 9;
+ // Alias
+ string alias = 10;
+ // NFT Type
+ string nft_type = 11;
+ // Quantity
+ int64 quantity = 12;
+ int64 total_quantity = 13;
+ aelf.Hash token_hash = 14;
+}
+
+message Transferred {
+ option (aelf.is_event) = true;
+ aelf.Address from = 1 [(aelf.is_indexed) = true];
+ aelf.Address to = 2 [(aelf.is_indexed) = true];
+ string symbol = 3 [(aelf.is_indexed) = true];
+ int64 token_id = 4 [(aelf.is_indexed) = true];
+ int64 amount = 5;
+ string memo = 6;
+}
+
+message Approved {
+ option (aelf.is_event) = true;
+ aelf.Address owner = 1 [(aelf.is_indexed) = true];
+ aelf.Address spender = 2 [(aelf.is_indexed) = true];
+ string symbol = 3 [(aelf.is_indexed) = true];
+ int64 token_id = 4 [(aelf.is_indexed) = true];
+ int64 amount = 5;
+}
+
+message UnApproved {
+ option (aelf.is_event) = true;
+ aelf.Address owner = 1 [(aelf.is_indexed) = true];
+ aelf.Address spender = 2 [(aelf.is_indexed) = true];
+ string symbol = 3 [(aelf.is_indexed) = true];
+ int64 token_id = 4 [(aelf.is_indexed) = true];
+ int64 current_allowance = 5;
+}
+
+message Burned {
+ option (aelf.is_event) = true;
+ aelf.Address burner = 1 [(aelf.is_indexed) = true];
+ string symbol = 2 [(aelf.is_indexed) = true];
+ int64 token_id = 3 [(aelf.is_indexed) = true];
+ int64 amount = 4;
+}
+
+message Recasted {
+ option (aelf.is_event) = true;
+ string symbol = 1 [(aelf.is_indexed) = true];
+ int64 token_id = 2 [(aelf.is_indexed) = true];
+ Metadata old_metadata = 3 [(aelf.is_indexed) = true];
+ Metadata new_metadata = 4 [(aelf.is_indexed) = true];
+ string alias = 5 [(aelf.is_indexed) = true];
+ string uri = 6 [(aelf.is_indexed) = true];
+}
+
+message Assembled {
+ option (aelf.is_event) = true;
+ string symbol = 1 [(aelf.is_indexed) = true];
+ int64 token_id = 2 [(aelf.is_indexed) = true];
+ AssembledNfts assembled_nfts = 3 [(aelf.is_indexed) = true];
+ AssembledFts assembled_fts = 4 [(aelf.is_indexed) = true];
+}
+
+message Disassembled {
+ option (aelf.is_event) = true;
+ string symbol = 1 [(aelf.is_indexed) = true];
+ int64 token_id = 2 [(aelf.is_indexed) = true];
+ AssembledNfts disassembled_nfts = 3 [(aelf.is_indexed) = true];
+ AssembledFts disassembled_fts = 4 [(aelf.is_indexed) = true];
+}
+
+message NFTTypeAdded {
+ option (aelf.is_event) = true;
+ string full_name = 1;
+ string short_name = 2;
+}
+
+message NFTTypeRemoved {
+ option (aelf.is_event) = true;
+ string short_name = 1;
+}
+
+message MinterListAdded {
+ option (aelf.is_event) = true;
+ MinterList minter_list = 1;
+ string symbol = 2;
+}
+
+message MinterListRemoved {
+ option (aelf.is_event) = true;
+ MinterList minter_list = 1;
+ string symbol = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/oracle_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/oracle_contract.proto
new file mode 100644
index 00000000..44846122
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/oracle_contract.proto
@@ -0,0 +1,380 @@
+syntax = "proto3";
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.Oracle";
+
+service OracleContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Oracle.OracleContractState";
+
+ rpc Initialize (InitializeInput) returns (google.protobuf.Empty) {}
+ rpc InitializeAndCreateToken (InitializeInput) returns (google.protobuf.Empty) {}
+
+ // base function
+
+ rpc Query (QueryInput) returns (aelf.Hash) {}
+
+ rpc Commit (CommitInput) returns (google.protobuf.Empty) {}
+
+ rpc Reveal (RevealInput) returns (google.protobuf.Empty) {}
+
+ rpc CancelQuery (aelf.Hash) returns (google.protobuf.Empty) {}
+
+ rpc CreateQueryTask (CreateQueryTaskInput) returns (aelf.Hash) {}
+
+ rpc TaskQuery (TaskQueryInput) returns (aelf.Hash) {}
+
+ rpc CompleteQueryTask (CompleteQueryTaskInput) returns (google.protobuf.Empty) {}
+
+ // controller
+
+ rpc ChangeController (aelf.Address) returns (google.protobuf.Empty) {}
+
+ // regiment related
+
+ rpc CreateRegiment (CreateRegimentInput) returns (google.protobuf.Empty) {}
+ rpc JoinRegiment (JoinRegimentInput) returns (google.protobuf.Empty) {}
+ rpc LeaveRegiment (LeaveRegimentInput) returns (google.protobuf.Empty) {}
+ rpc AddRegimentMember (AddRegimentMemberInput) returns (google.protobuf.Empty) {}
+ rpc DeleteRegimentMember (DeleteRegimentMemberInput) returns (google.protobuf.Empty) {}
+ rpc TransferRegimentOwnership (TransferRegimentOwnershipInput) returns (google.protobuf.Empty) {}
+ rpc AddAdmins (AddAdminsInput) returns (google.protobuf.Empty) {}
+ rpc DeleteAdmins (DeleteAdminsInput) returns (google.protobuf.Empty) {}
+
+ rpc LockTokens (LockTokensInput) returns (google.protobuf.Empty) {}
+
+ rpc UnlockTokens (UnlockTokensInput) returns (google.protobuf.Empty) {}
+
+ // config setting
+
+ rpc SetThreshold (OracleNodeThreshold) returns (google.protobuf.Empty) {}
+
+ rpc ChangeDefaultExpirationSeconds (google.protobuf.Int32Value) returns (google.protobuf.Empty) {}
+
+ rpc EnableChargeFee (google.protobuf.Empty) returns (google.protobuf.Empty) {}
+
+ rpc AddPostPayAddress (aelf.Address) returns (google.protobuf.Empty) {}
+
+ rpc RemovePostPayAddress (aelf.Address) returns (google.protobuf.Empty) {}
+
+ // view methods
+
+ rpc GetController (google.protobuf.Empty) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetQueryRecord (aelf.Hash) returns (QueryRecord) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetCommitmentMap (aelf.Hash) returns (CommitmentMap) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetOracleTokenSymbol (google.protobuf.Empty) returns (google.protobuf.StringValue) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetLockedTokensAmount (aelf.Address) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetThreshold (google.protobuf.Empty) returns (OracleNodeThreshold) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetDefaultExpirationSeconds (google.protobuf.Empty) returns (google.protobuf.Int32Value) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetHelpfulNodeList (aelf.Hash) returns (AddressList) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetQueryTask (aelf.Hash) returns (QueryTask) {
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetRegimentMemberList (aelf.Address) returns (AddressList) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message InitializeInput {
+ int32 minimum_oracle_nodes_count = 1;
+ int32 default_reveal_threshold = 2;
+ int32 default_aggregate_threshold = 3;
+ int32 default_expiration_seconds = 4;
+ bool is_charge_fee = 5;
+ aelf.Address regiment_contract_address = 6;
+}
+
+message QueryInput {
+ int64 payment = 1;// Maximum for this query option.
+ CallbackInfo callback_info = 2;
+ aelf.Address aggregator_contract_address = 3;
+ AddressList designated_node_list = 4;// Will be regiment address if count is 1.
+ QueryInfo query_info = 5;
+ int32 aggregate_threshold = 6;
+ string token = 7;
+ int32 aggregate_option = 8;
+ aelf.Hash task_id = 9;
+}
+
+message CreateQueryTaskInput {
+ int64 each_payment = 1;
+ int32 supposed_query_times = 2;
+ QueryInfo query_info = 3;
+ google.protobuf.Timestamp end_time = 4;
+ CallbackInfo callback_info = 5;
+ aelf.Address aggregator_contract_address = 6;
+ int32 aggregate_option = 7;
+ int32 aggregate_threshold = 8;
+}
+
+message TaskQueryInput {
+ aelf.Hash task_id = 1;
+}
+
+message CompleteQueryTaskInput {
+ aelf.Hash task_id = 1;
+ AddressList designated_node_list = 2;
+ int32 aggregate_threshold = 3;
+}
+
+message CallbackInfo {
+ aelf.Address contract_address = 1;
+ string method_name = 2;
+}
+
+message AddressList {
+ repeated aelf.Address value = 1;
+}
+
+message QueryRecord {
+ AddressList designated_node_list = 1;
+ aelf.Address aggregator_contract_address = 2;
+ google.protobuf.Timestamp expiration_timestamp = 3;
+ bool is_sufficient_commitments_collected = 4;
+ bool is_sufficient_data_collected = 5;
+ string final_result = 6;
+ int64 payment = 7;
+ CallbackInfo callback_info = 8;
+ aelf.Hash query_id = 9;
+ int32 aggregate_threshold = 10;
+ aelf.Address query_sender = 11;
+ bool is_commit_stage_finished = 12;
+ int32 commitments_count = 13;
+ bool is_cancelled = 14;
+ QueryInfo query_info = 15;
+ string token = 16;
+ DataRecords data_records = 17;
+ int32 aggregate_option = 18;
+ aelf.Hash task_id = 19;
+ bool is_paid_to_oracle_contract = 20;
+}
+
+message CreateRegimentInput {
+ aelf.Address manager = 1;
+ repeated aelf.Address initial_member_list = 2;
+ bool is_approve_to_join = 3;
+}
+
+message JoinRegimentInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_member_address = 2;
+}
+
+message LeaveRegimentInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address leave_member_address = 2;
+}
+
+message AddRegimentMemberInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_member_address = 2;
+}
+
+message DeleteRegimentMemberInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address delete_member_address = 2;
+}
+
+message TransferRegimentOwnershipInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_manager_address = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message AddAdminsInput {
+ aelf.Address regiment_address = 1;
+ repeated aelf.Address new_admins = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message DeleteAdminsInput {
+ aelf.Address regiment_address = 1;
+ repeated aelf.Address delete_admins = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message QueryTask {
+ int64 each_payment = 1;
+ int32 supposed_query_times = 2;
+ QueryInfo query_info = 3;
+ google.protobuf.Timestamp end_time = 4;
+ AddressList designated_node_list = 5;
+ aelf.Address aggregator_contract_address = 6;
+ int32 actual_queried_times = 7;
+ CallbackInfo callback_info = 8;
+ aelf.Address creator = 9;
+ int32 aggregate_threshold = 10;
+ int32 aggregate_option = 11;
+ bool on_going = 12;
+}
+
+message CommitInput {
+ aelf.Hash query_id = 1;
+ aelf.Hash commitment = 2;
+}
+
+message RevealInput {
+ aelf.Hash query_id = 1;
+ string data = 2;
+ aelf.Hash salt = 3;
+}
+
+message CommitmentMap {
+ map value = 1;
+}
+
+message OracleNodeThreshold {
+ int32 minimum_oracle_nodes_count = 1;
+ int32 default_reveal_threshold = 2;
+ int32 default_aggregate_threshold = 3;
+}
+
+message ResultList {
+ repeated string results = 1;
+ repeated int32 frequencies = 2;
+}
+
+message DataRecord {
+ aelf.Address address = 1;
+ string data = 2;
+}
+
+message DataRecords {
+ repeated DataRecord value = 1;
+}
+
+message PlainResult {
+ DataRecords data_records = 1;
+ aelf.Address regiment_address = 2;
+ QueryInfo query_info = 3;
+ string token = 4;
+}
+
+message LockTokensInput {
+ aelf.Address oracle_node_address = 1;
+ int64 lock_amount = 2;
+}
+
+message UnlockTokensInput {
+ aelf.Address oracle_node_address = 1;
+ int64 withdraw_amount = 2;
+}
+
+message QueryInfo {
+ string title = 1;
+ repeated string options = 2;
+}
+
+// Events
+message QueryCreated {
+ option (aelf.is_event) = true;
+ int64 payment = 1;// Maximum for this query option.
+ CallbackInfo callback_info = 2;
+ aelf.Address aggregator_contract_address = 3;
+ AddressList designated_node_list = 4;// Will be regiment address if count is 1.
+ QueryInfo query_info = 5;
+ int32 aggregate_threshold = 6;
+ aelf.Address query_sender = 7;
+ aelf.Hash query_id = 8;
+ string token = 9;
+ int32 maximum_permissible_deviation = 10;
+ int32 aggregate_option = 11;
+ aelf.Hash task_id = 12;
+}
+
+message QueryTaskCreated {
+ option (aelf.is_event) = true;
+ int64 each_payment = 1;
+ int32 supposed_query_times = 2;
+ QueryInfo query_info = 3;
+ google.protobuf.Timestamp end_time = 4;
+ AddressList designated_node_list = 5;
+ aelf.Address aggregator_contract_address = 6;
+ CallbackInfo callback_info = 7;
+ aelf.Address creator = 8;
+ int32 aggregate_threshold = 9;
+ int32 aggregate_option = 10;
+}
+
+message QueryCancelled {
+ option (aelf.is_event) = true;
+ aelf.Hash query_id = 1;
+}
+
+message SufficientCommitmentsCollected {
+ option (aelf.is_event) = true;
+ aelf.Hash query_id = 1;
+}
+
+message Committed {
+ option (aelf.is_event) = true;
+ aelf.Hash query_id = 1;
+ aelf.Address oracle_node_address = 2;
+ aelf.Hash commitment = 3;
+}
+
+message CommitmentRevealed {
+ option (aelf.is_event) = true;
+ aelf.Hash query_id = 1;
+ aelf.Address oracle_node_address = 2;
+ aelf.Hash commitment = 3;
+ string reveal_data = 4;
+ aelf.Hash salt = 5;
+}
+
+message CommitmentRevealFailed {
+ option (aelf.is_event) = true;
+ aelf.Hash query_id = 1;
+ aelf.Address oracle_node_address = 2;
+ aelf.Hash commitment = 3;
+ string reveal_data = 4;
+ aelf.Hash salt = 5;
+}
+
+message QueryCompletedWithAggregation {
+ option (aelf.is_event) = true;
+ aelf.Hash query_id = 1;
+ string result = 2;
+}
+
+message QueryCompletedWithoutAggregation {
+ option (aelf.is_event) = true;
+ aelf.Hash query_id = 1;
+ PlainResult result = 2;
+}
+
+message TokenLocked {
+ option (aelf.is_event) = true;
+ aelf.Address oracle_node_address = 1;
+ aelf.Address from_address = 2;
+ int64 locked_amount = 3;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/parliament_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/parliament_contract.proto
new file mode 100644
index 00000000..c7a8936e
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/parliament_contract.proto
@@ -0,0 +1,148 @@
+/**
+ * Parliament contract.
+ */
+syntax = "proto3";
+
+package Parliament;
+
+import "acs3.proto";
+import public "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.Parliament";
+
+service ParliamentContract {
+
+ option (aelf.csharp_state) = "AElf.Contracts.Parliament.ParliamentState";
+
+ // Initialize parliament proposer whitelist and create the first parliament organization
+ // with specific proposer_authority_required.
+ rpc Initialize(InitializeInput) returns (google.protobuf.Empty) {
+ }
+
+ // Create an organization and return its address.
+ rpc CreateOrganization (CreateOrganizationInput) returns (aelf.Address) {
+ }
+
+ // Batch approval proposal.
+ rpc ApproveMultiProposals(ProposalIdList) returns (google.protobuf.Empty){
+ }
+
+ // Creates an organization by system contract and return its address.
+ rpc CreateOrganizationBySystemContract(CreateOrganizationBySystemContractInput) returns (aelf.Address){
+ }
+
+ // Creates an organization to handle emergency events.
+ rpc CreateEmergencyResponseOrganization (google.protobuf.Empty) returns (google.protobuf.Empty) {
+ }
+
+ // Get the organization according to the organization address.
+ rpc GetOrganization (aelf.Address) returns (Organization) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the default organization address.
+ rpc GetDefaultOrganizationAddress (google.protobuf.Empty) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ // Validates if the provided address is a parliament member.
+ rpc ValidateAddressIsParliamentMember(aelf.Address) returns (google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+
+ // Returns the list of whitelisted proposers.
+ rpc GetProposerWhiteList(google.protobuf.Empty) returns (acs3.ProposerWhiteList){
+ option (aelf.is_view) = true;
+ }
+
+ // Filter still pending ones not yet voted by the sender from provided proposals.
+ rpc GetNotVotedPendingProposals(ProposalIdList) returns (ProposalIdList){
+ option (aelf.is_view) = true;
+ }
+
+ // Filter not yet voted ones by the sender from provided proposals.
+ rpc GetNotVotedProposals(ProposalIdList) returns (ProposalIdList){
+ option (aelf.is_view) = true;
+ }
+
+ // Calculates with input and return the organization address.
+ rpc CalculateOrganizationAddress(CreateOrganizationInput) returns (aelf.Address){
+ option (aelf.is_view) = true;
+ }
+
+ rpc GetEmergencyResponseOrganizationAddress (google.protobuf.Empty) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message CreateOrganizationInput {
+ // The threshold for releasing the proposal.
+ acs3.ProposalReleaseThreshold proposal_release_threshold = 1;
+ // Setting this to false will allow anyone creating proposals.
+ bool proposer_authority_required = 2;
+ // Setting this to true can allow parliament member to create proposals.
+ bool parliament_member_proposing_allowed = 3;
+ // The creation token is for organization address generation.
+ aelf.Hash creation_token = 4;
+}
+
+message Organization {
+ // Indicates if proposals need authority to be created.
+ bool proposer_authority_required = 1;
+ // The organization address.
+ aelf.Address organization_address = 2;
+ // The organization id.
+ aelf.Hash organization_hash = 3;
+ // The threshold for releasing the proposal.
+ acs3.ProposalReleaseThreshold proposal_release_threshold = 4;
+ // Indicates if parliament member can propose to this organization.
+ bool parliament_member_proposing_allowed = 5;
+ // The creation token is for organization address generation.
+ aelf.Hash creation_token = 6;
+}
+
+message ProposalInfo {
+ // The proposal ID.
+ aelf.Hash proposal_id = 1;
+ // The method that this proposal will call when being released.
+ string contract_method_name = 2;
+ // The address of the target contract.
+ aelf.Address to_address = 3;
+ // The parameters of the release transaction.
+ bytes params = 4;
+ // The date at which this proposal will expire.
+ google.protobuf.Timestamp expired_time = 5;
+ // The address of the proposer of this proposal.
+ aelf.Address proposer = 6;
+ // The address of this proposals organization.
+ aelf.Address organization_address = 7;
+ // Address list of approved.
+ repeated aelf.Address approvals = 8;
+ // Address list of rejected.
+ repeated aelf.Address rejections = 9;
+ // Address list of abstained.
+ repeated aelf.Address abstentions = 10;
+ // Url is used for proposal describing.
+ string proposal_description_url = 11;
+}
+
+message InitializeInput{
+ // Privileged proposer would be the first address in parliament proposer whitelist.
+ aelf.Address privileged_proposer = 1;
+ // The setting indicates if proposals need authority to be created for first/default parliament organization.
+ bool proposer_authority_required = 2;
+}
+
+message ProposalIdList{
+ // The list of proposal ids.
+ repeated aelf.Hash proposal_ids = 1;
+}
+
+message CreateOrganizationBySystemContractInput {
+ // The parameters of creating organization.
+ CreateOrganizationInput organization_creation_input = 1;
+ // The organization address callback method which replies the organization address to caller contract.
+ string organization_address_feedback_method = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/profit_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/profit_contract.proto
new file mode 100644
index 00000000..745406dc
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/profit_contract.proto
@@ -0,0 +1,370 @@
+/**
+ * Profit contract.
+ */
+syntax = "proto3";
+
+package Profit;
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.Profit";
+
+service ProfitContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Profit.ProfitContractState";
+
+ // Create a scheme for profit distribution, and return the created scheme id.
+ rpc CreateScheme (CreateSchemeInput) returns (aelf.Hash) {
+ }
+
+ // Add beneficiary to scheme.
+ rpc AddBeneficiary (AddBeneficiaryInput) returns (google.protobuf.Empty) {
+ }
+
+ // Remove beneficiary from scheme.
+ rpc RemoveBeneficiary (RemoveBeneficiaryInput) returns (google.protobuf.Empty) {
+ }
+
+ // Batch add beneficiary to scheme.
+ rpc AddBeneficiaries (AddBeneficiariesInput) returns (google.protobuf.Empty) {
+ }
+
+ // Batch remove beneficiary from scheme.
+ rpc RemoveBeneficiaries (RemoveBeneficiariesInput) returns (google.protobuf.Empty) {
+ }
+
+ rpc FixProfitDetail (FixProfitDetailInput) returns (google.protobuf.Empty) {
+ }
+
+ // Contribute profit to a scheme.
+ rpc ContributeProfits (ContributeProfitsInput) returns (google.protobuf.Empty) {
+ }
+
+ // The beneficiary draws tokens from the scheme.
+ rpc ClaimProfits (ClaimProfitsInput) returns (google.protobuf.Empty) {
+ }
+
+ // Distribute profits to schemes, including its sub scheme according to period and token symbol,
+ // should be called by the manager.
+ rpc DistributeProfits (DistributeProfitsInput) returns (google.protobuf.Empty) {
+ }
+
+ // Add sub scheme to a scheme.
+ // This will effectively add the specified sub-scheme as a beneficiary of the parent scheme.
+ rpc AddSubScheme (AddSubSchemeInput) returns (google.protobuf.Empty) {
+ }
+
+ // Remove sub scheme from a scheme.
+ rpc RemoveSubScheme (RemoveSubSchemeInput) returns (google.protobuf.Empty) {
+ }
+
+ // Reset the manager of a scheme.
+ rpc ResetManager (ResetManagerInput) returns (google.protobuf.Empty) {
+ }
+
+ // Get all schemes managed by the specified manager.
+ rpc GetManagingSchemeIds (GetManagingSchemeIdsInput) returns (CreatedSchemeIds) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get scheme according to scheme id.
+ rpc GetScheme (aelf.Hash) returns (Scheme) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the virtual address of the number of period of the scheme.
+ rpc GetSchemeAddress (SchemePeriod) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the distributed profit information for the specified period.
+ rpc GetDistributedProfitsInfo (SchemePeriod) returns (DistributedProfitsInfo) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the beneficiary's profit information on the scheme.
+ rpc GetProfitDetails (GetProfitDetailsInput) returns (ProfitDetails) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the amount of profit according to token symbol. (up to 10 periods).
+ rpc GetProfitAmount (GetProfitAmountInput) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query all profit (up to 10 periods).
+ rpc GetProfitsMap (ClaimProfitsInput) returns (ReceivedProfitsMap) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message CreateSchemeInput {
+ // Period of profit distribution.
+ int64 profit_receiving_due_period_count = 1;
+ // Whether all the schemes balance will be distributed during distribution each period.
+ bool is_release_all_balance_every_time_by_default = 2;
+ // Delay distribute period.
+ int32 delay_distribute_period_count = 3;
+ // The manager of this scheme, the default is the creator.
+ aelf.Address manager = 4;
+ // Whether you can directly remove the beneficiary.
+ bool can_remove_beneficiary_directly = 5;
+ // Use to generate scheme id.
+ aelf.Hash token = 6;
+}
+
+message Scheme {
+ // The virtual address of the scheme.
+ aelf.Address virtual_address = 1;
+ // The total weight of the scheme.
+ int64 total_shares = 2;
+ // The manager of the scheme.
+ aelf.Address manager = 3;
+ // The current period.
+ int64 current_period = 4;
+ // Sub schemes information.
+ repeated SchemeBeneficiaryShare sub_schemes = 5;
+ // Whether you can directly remove the beneficiary.
+ bool can_remove_beneficiary_directly = 6;
+ // Period of profit distribution.
+ int64 profit_receiving_due_period_count = 7;
+ // Whether all the schemes balance will be distributed during distribution each period.
+ bool is_release_all_balance_every_time_by_default = 8;
+ // The is of the scheme.
+ aelf.Hash scheme_id = 9;
+ // Delay distribute period.
+ int32 delay_distribute_period_count = 10;
+ // Record the scheme's current total share for deferred distribution of benefits, period -> total shares.
+ map cached_delay_total_shares = 11;
+ // The received token symbols.
+ repeated string received_token_symbols = 12;
+}
+
+message SchemeBeneficiaryShare {
+ // The id of the sub scheme.
+ aelf.Hash scheme_id = 1;
+ // The weight of the sub scheme.
+ int64 shares = 2;
+}
+
+message AddBeneficiaryInput {
+ // The scheme id.
+ aelf.Hash scheme_id = 1;
+ // The beneficiary information.
+ BeneficiaryShare beneficiary_share = 2;
+ // The end period which the beneficiary receives the profit.
+ int64 start_period = 3;
+ int64 end_period = 4;
+ bool is_fix_profit_detail = 5;
+ aelf.Hash profit_detail_id = 6;
+}
+
+message FixProfitDetailInput {
+ aelf.Hash scheme_id = 1;
+ BeneficiaryShare beneficiary_share = 2;
+ int64 start_period = 3;
+ int64 end_period = 4;
+ aelf.Hash profit_detail_id = 5;
+}
+
+message RemoveBeneficiaryInput {
+ // The address of beneficiary.
+ aelf.Address beneficiary = 1;
+ // The scheme id.
+ aelf.Hash scheme_id = 2;
+ aelf.Hash profit_detail_id = 3;
+}
+
+message AddBeneficiariesInput {
+ // The scheme id.
+ aelf.Hash scheme_id = 1;
+ // The beneficiary information.
+ repeated BeneficiaryShare beneficiary_shares = 2;
+ // The end period which the beneficiary receives the profit.
+ int64 end_period = 3;
+}
+
+message RemoveBeneficiariesInput {
+ // The addresses of beneficiary.
+ repeated aelf.Address beneficiaries = 1;
+ // The scheme id.
+ aelf.Hash scheme_id = 2;
+}
+
+message BeneficiaryShare {
+ // The address of beneficiary.
+ aelf.Address beneficiary = 1;
+ // The profit weight of the beneficiary in the scheme.
+ int64 shares = 2;
+}
+
+message ClaimProfitsInput {
+ // The scheme id.
+ aelf.Hash scheme_id = 1;
+ // The address of beneficiary.
+ aelf.Address beneficiary = 2;
+}
+
+message DistributeProfitsInput {
+ // The scheme id to distribute.
+ aelf.Hash scheme_id = 1;
+ // The period number to distribute, should be the current period.
+ int64 period = 2;
+ // The amount to distribute, symbol -> amount.
+ map amounts_map = 3;
+}
+
+message ProfitDetails {
+ // The profit information.
+ repeated ProfitDetail details = 1;
+}
+
+message ProfitDetail {
+ // The start period number.
+ int64 start_period = 1;
+ // The end period number.
+ int64 end_period = 2;
+ // The weight of the proceeds on the current period of the scheme.
+ int64 shares = 3;
+ // The last period number that the beneficiary received the profit.
+ int64 last_profit_period = 4;
+ // Whether the weight has been removed.
+ bool is_weight_removed = 5;
+ aelf.Hash id = 6;
+}
+
+message ContributeProfitsInput {
+ // The scheme id to contribute.
+ aelf.Hash scheme_id = 1;
+ // The amount to contribute.
+ int64 amount = 2;
+ // The number of periods in which the income is used for dividends.
+ int64 period = 3;
+ // The token symbol to contribute.
+ string symbol = 4;
+}
+
+message AddSubSchemeInput {
+ // The parent scheme id.
+ aelf.Hash scheme_id = 1;
+ // The sub scheme id.
+ aelf.Hash sub_scheme_id = 2;
+ // The profit weight of sub scheme.
+ int64 sub_scheme_shares = 3;
+}
+
+message RemoveSubSchemeInput {
+ // The parent scheme id.
+ aelf.Hash scheme_id = 1;
+ // The sub scheme id.
+ aelf.Hash sub_scheme_id = 2;
+}
+
+message DistributedProfitsInfo {
+ // The total amount of shares in this scheme at the current period.
+ int64 total_shares = 1;
+ // The contributed amount in this scheme at the current period.
+ map amounts_map = 2;//Token symbol -> Amount
+ // Whether released.
+ bool is_released = 3;
+}
+
+message CreatedSchemeIds {
+ // The scheme ids.
+ repeated aelf.Hash scheme_ids = 1;
+}
+
+message GetManagingSchemeIdsInput {
+ // The manager address.
+ aelf.Address manager = 1;
+}
+
+message SchemePeriod {
+ // The scheme id.
+ aelf.Hash scheme_id = 1;
+ // The period number.
+ int64 period = 2;
+}
+
+message GetProfitDetailsInput {
+ // The scheme id.
+ aelf.Hash scheme_id = 1;
+ // The address of beneficiary.
+ aelf.Address beneficiary = 2;
+}
+
+message ResetManagerInput {
+ // The scheme id.
+ aelf.Hash scheme_id = 1;
+ // The address of new manager.
+ aelf.Address new_manager = 2;
+}
+
+message GetProfitAmountInput {
+ // The scheme id.
+ aelf.Hash scheme_id = 1;
+ // The token symbol.
+ string symbol = 2;
+ // The beneficiary's address.
+ aelf.Address beneficiary = 3;
+}
+
+message ReceivedProfitsMap {
+ // The collection of profits received, token symbol -> amount.
+ map value = 1;
+}
+
+message ReceivedProfitsMapList {
+ repeated ReceivedProfitsMap value = 1;
+}
+
+message SchemeCreated {
+ option (aelf.is_event) = true;
+ // The virtual address of the created scheme.
+ aelf.Address virtual_address = 1;
+ // The manager of the created scheme.
+ aelf.Address manager = 2;
+ // Period of profit distribution.
+ int64 profit_receiving_due_period_count = 3;
+ // Whether all the schemes balance will be distributed during distribution each period.
+ bool is_release_all_balance_every_time_by_default = 4;
+ // The id of the created scheme.
+ aelf.Hash scheme_id = 5;
+}
+
+message ProfitsClaimed {
+ option (aelf.is_event) = true;
+ // The beneficiary's address claimed.
+ aelf.Address beneficiary = 1;
+ // The token symbol claimed.
+ string symbol = 2;
+ // The amount claimed.
+ int64 amount = 3;
+ // The period number claimed.
+ int64 period = 4;
+ // The shares of the claimer.
+ int64 claimer_shares = 5;
+ // The total shares at the current period.
+ int64 total_shares = 6;
+}
+
+message ProfitDetailAdded {
+ option (aelf.is_event) = true;
+ int64 start_period = 1;
+ int64 end_period = 2;
+ int64 shares = 3;
+ bool is_weight_removed = 4;
+ aelf.Address beneficiary = 5;
+}
+
+message DistributedPeriodInfoChanged {
+ option (aelf.is_event) = true;
+ aelf.Hash scheme_id = 1;
+ int64 period = 2;
+ int64 total_shares = 3;
+ ReceivedProfitsMapList profits_map_list = 4;
+ bool is_released = 5;
+ aelf.Address virtual_address = 6;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/receipt_maker.proto b/modules/AElf.Client.Protobuf/Protobuf/receipt_maker.proto
new file mode 100644
index 00000000..3adefd56
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/receipt_maker.proto
@@ -0,0 +1,35 @@
+syntax = "proto3";
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.ReceiptMakerContract";
+
+service ReceiptMakerContract {
+ rpc GetReceiptCount(google.protobuf.Int64Value) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetReceiptHash(GetReceiptHashInput) returns (aelf.Hash) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetReceiptHashList(GetReceiptHashListInput) returns (GetReceiptHashListOutput) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message GetReceiptHashInput {
+ int64 recorder_id = 1;
+ int64 receipt_id = 2;
+}
+
+message GetReceiptHashListInput {
+ int64 first_leaf_index = 1;
+ int64 last_leaf_index = 2;
+ int64 recorder_id = 3;
+}
+
+message GetReceiptHashListOutput {
+ repeated aelf.Hash receipt_hash_list = 1;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/referendum_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/referendum_contract.proto
new file mode 100644
index 00000000..82af016f
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/referendum_contract.proto
@@ -0,0 +1,129 @@
+/**
+ * Referendum contract.
+ */
+syntax = "proto3";
+
+package Referendum;
+
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "aelf/core.proto";
+import "acs3.proto";
+
+option csharp_namespace = "AElf.Contracts.Referendum";
+
+service ReferendumContract {
+
+ option (aelf.csharp_state) = "AElf.Contracts.Referendum.ReferendumState";
+
+ // Unlock the token used for voting according to proposal id.
+ rpc ReclaimVoteToken (aelf.Hash) returns (google.protobuf.Empty) {
+ }
+
+ // Create an organization and return its address.
+ rpc CreateOrganization (CreateOrganizationInput) returns (aelf.Address) {
+ }
+
+ // Creates an organization by system contract and return its address.
+ rpc CreateOrganizationBySystemContract (CreateOrganizationBySystemContractInput) returns (aelf.Address) {
+ }
+
+ // Get the organization according to the organization address.
+ rpc GetOrganization (aelf.Address) returns (Organization) {
+ option (aelf.is_view) = true;
+ }
+
+ // Calculate the input and return the organization address.
+ rpc CalculateOrganizationAddress (CreateOrganizationInput) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the virtual address of a proposal based on the proposal id.
+ rpc GetProposalVirtualAddress (aelf.Hash) returns (aelf.Address) {
+ }
+}
+
+message CreateOrganizationInput {
+ // The token used during proposal operations.
+ string token_symbol = 1;
+ // The threshold for releasing the proposal.
+ acs3.ProposalReleaseThreshold proposal_release_threshold = 2;
+ // The proposer whitelist.
+ acs3.ProposerWhiteList proposer_white_list = 3;
+ // The creation token is for organization address generation.
+ aelf.Hash creation_token = 4;
+}
+
+message Organization {
+ // The threshold for releasing the proposal.
+ acs3.ProposalReleaseThreshold proposal_release_threshold = 1;
+ // The token used during proposal operations.
+ string token_symbol = 2;
+ // The address of organization.
+ aelf.Address organization_address = 3;
+ // The organizations id.
+ aelf.Hash organization_hash = 4;
+ // The proposer whitelist.
+ acs3.ProposerWhiteList proposer_white_list = 5;
+ // The creation token is for organization address generation.
+ aelf.Hash creation_token = 6;
+}
+
+message Receipt {
+ // The amount of token locked.
+ int64 amount = 1;
+ // The symbol of token locked.
+ string token_symbol = 2;
+ // The lock id.
+ aelf.Hash lock_id = 3;
+}
+
+message ProposalInfo {
+ // The proposal ID.
+ aelf.Hash proposal_id = 1;
+ // The method that this proposal will call when being released.
+ string contract_method_name = 2;
+ // The address of the target contract.
+ aelf.Address to_address = 3;
+ // The parameters of the release transaction.
+ bytes params = 4;
+ // The date at which this proposal will expire.
+ google.protobuf.Timestamp expired_time = 5;
+ // The address of the proposer of this proposal.
+ aelf.Address proposer = 6;
+ // The address of this proposals organization.
+ aelf.Address organization_address = 7;
+ // The count of approved.
+ int64 approval_count = 8;
+ // The count of rejected.
+ int64 rejection_count = 9;
+ // The count of abstained.
+ int64 abstention_count = 10;
+ // Url is used for proposal describing.
+ string proposal_description_url = 11;
+}
+
+message CreateOrganizationBySystemContractInput {
+ // The parameters of creating organization.
+ CreateOrganizationInput organization_creation_input = 1;
+ // The organization address callback method which replies the organization address to caller contract.
+ string organization_address_feedback_method = 2;
+}
+
+message ReferendumReceiptCreated {
+ option (aelf.is_event) = true;
+ // The id of the proposal.
+ aelf.Hash proposal_id = 1;
+ // The sender address.
+ aelf.Address address = 2;
+ // The symbol of token locked.
+ string symbol = 3;
+ // The amount of token locked.
+ int64 amount = 4;
+ // The type of receipt(Approve, Reject or Abstain).
+ string receipt_type = 5;
+ // The timestamp of this method call.
+ google.protobuf.Timestamp time = 6;
+ // The address of the organization.
+ aelf.Address organization_address = 7 [(aelf.is_indexed) = true];
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/regiment_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/regiment_contract.proto
new file mode 100644
index 00000000..3a8380c2
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/regiment_contract.proto
@@ -0,0 +1,158 @@
+syntax = "proto3";
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.Regiment";
+
+service RegimentContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Regiment.RegimentContractState";
+
+ // Actions (Can only performed by the Controller.)
+ rpc Initialize (InitializeInput) returns (google.protobuf.Empty) {}
+
+ rpc CreateRegiment (CreateRegimentInput) returns (google.protobuf.Empty) {}
+ rpc JoinRegiment (JoinRegimentInput) returns (google.protobuf.Empty) {}
+ rpc LeaveRegiment (LeaveRegimentInput) returns (google.protobuf.Empty) {}
+ rpc AddRegimentMember (AddRegimentMemberInput) returns (google.protobuf.Empty) {}
+ rpc DeleteRegimentMember (DeleteRegimentMemberInput) returns (google.protobuf.Empty) {}
+ rpc TransferRegimentOwnership (TransferRegimentOwnershipInput) returns (google.protobuf.Empty) {}
+ rpc AddAdmins (AddAdminsInput) returns (google.protobuf.Empty) {}
+ rpc DeleteAdmins (DeleteAdminsInput) returns (google.protobuf.Empty) {}
+
+ rpc ChangeController (aelf.Address) returns (google.protobuf.Empty) {}
+ rpc ResetConfig (RegimentContractConfig) returns (google.protobuf.Empty) {}
+
+ // Views
+ rpc GetController (google.protobuf.Empty) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetConfig (google.protobuf.Empty) returns (RegimentContractConfig) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetRegimentId(aelf.Address) returns(aelf.Hash){
+ option(aelf.is_view) = true;
+ }
+ rpc GetRegimentAddress(aelf.Hash) returns (aelf.Address){
+ option (aelf.is_view) = true;
+ }
+ rpc GetRegimentInfo (aelf.Address) returns (RegimentInfo) {
+ option (aelf.is_view) = true;
+ }
+ rpc IsRegimentMember (IsRegimentMemberInput) returns (google.protobuf.BoolValue) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetRegimentMemberList (aelf.Address) returns (RegimentMemberList) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message InitializeInput {
+ aelf.Address Controller = 1;// The only address can perform action in this contract.
+ int32 member_join_limit = 2;
+ int32 regiment_limit = 3;
+ int32 maximum_admins_count = 4;
+}
+
+message RegimentContractConfig {
+ int32 member_join_limit = 1;
+ int32 regiment_limit = 2;
+ int32 maximum_admins_count = 3;
+}
+
+message CreateRegimentInput {
+ aelf.Address manager = 1;
+ repeated aelf.Address initial_member_list = 2;
+ bool is_approve_to_join = 3;
+}
+
+message JoinRegimentInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_member_address = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message LeaveRegimentInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address leave_member_address = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message AddRegimentMemberInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_member_address = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message DeleteRegimentMemberInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address delete_member_address = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message RegimentInfo {
+ google.protobuf.Timestamp create_time = 1;
+ aelf.Address manager = 2;
+ repeated aelf.Address admins = 3;
+ bool is_approve_to_join = 4;
+}
+
+message IsRegimentMemberInput {
+ aelf.Address address = 1;
+ aelf.Address regiment_address = 2;
+}
+
+message RegimentMemberList {
+ repeated aelf.Address value = 1;
+}
+
+message TransferRegimentOwnershipInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address new_manager_address = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message AddAdminsInput {
+ aelf.Address regiment_address = 1;
+ repeated aelf.Address new_admins = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+message DeleteAdminsInput {
+ aelf.Address regiment_address = 1;
+ repeated aelf.Address delete_admins = 2;
+ aelf.Address origin_sender_address = 3;
+}
+
+// Events
+message RegimentCreated {
+ option (aelf.is_event) = true;
+ google.protobuf.Timestamp create_time = 1;
+ aelf.Address manager = 2;
+ RegimentMemberList initial_member_list = 3;
+ aelf.Address regiment_address = 4;
+ aelf.Hash regiment_id = 5;
+}
+
+message NewMemberApplied {
+ option (aelf.is_event) = true;
+ aelf.Address regiment_address = 1;
+ aelf.Address apply_member_address = 2;
+}
+
+message NewMemberAdded {
+ option (aelf.is_event) = true;
+ aelf.Address regiment_address = 1;
+ aelf.Address new_member_address = 2;
+ aelf.Address operator_address = 3;
+}
+
+message RegimentMemberLeft {
+ option (aelf.is_event) = true;
+ aelf.Address regiment_address = 1;
+ aelf.Address left_member_address = 2;
+ aelf.Address operator_address = 3;
+}
diff --git a/modules/AElf.Client.Protobuf/Protobuf/report_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/report_contract.proto
new file mode 100644
index 00000000..39c2f188
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/report_contract.proto
@@ -0,0 +1,353 @@
+syntax = "proto3";
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/wrappers.proto";
+import "callback_input.proto";
+
+option csharp_namespace = "AElf.Contracts.Report";
+
+// the contract definition: a gRPC service definition.
+service ReportContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Report.ReportContractState";
+
+ rpc Initialize (InitializeInput) returns (google.protobuf.Empty) {}
+
+ rpc QueryOracle (QueryOracleInput) returns (aelf.Hash) {}
+
+ rpc CancelQueryOracle (aelf.Hash) returns (google.protobuf.Empty) {}
+
+ rpc ConfirmReport (ConfirmReportInput) returns (google.protobuf.Empty) {}
+
+ rpc RejectReport (RejectReportInput) returns (google.protobuf.Empty) {}
+
+ rpc ProposeReport (CallbackInput) returns (Report) {}
+
+ rpc MortgageTokens (google.protobuf.Int64Value) returns (google.protobuf.Empty) {}
+
+ rpc WithdrawTokens (google.protobuf.Int64Value) returns (google.protobuf.Empty) {}
+
+ rpc SetSkipMemberList (SetSkipMemberListInput) returns (google.protobuf.Empty){}
+
+
+ // Observer management.
+ rpc ApplyObserver (ApplyObserverInput) returns (google.protobuf.Empty) {}
+
+ rpc QuitObserver (QuitObserverInput) returns (google.protobuf.Empty) {}
+
+ rpc AdjustApplyObserverFee (google.protobuf.Int64Value) returns (google.protobuf.Empty) {}
+
+ rpc AdjustReportFee (google.protobuf.Int64Value) returns (google.protobuf.Empty) {}
+
+ // Offchain Aggregator Contract management.
+
+ rpc RegisterOffChainAggregation (RegisterOffChainAggregationInput) returns (OffChainAggregationInfo) {}
+
+ rpc BindOffChainAggregation (BindOffChainAggregationInput) returns (OffChainAggregationInfo) {}
+
+ rpc AddOffChainQueryInfo (AddOffChainQueryInfoInput) returns (google.protobuf.Empty) {}
+
+ rpc RemoveOffChainQueryInfo (RemoveOffChainQueryInfoInput) returns (google.protobuf.Empty) {}
+
+ rpc ChangeOffChainQueryInfo (ChangeOffChainQueryInfoInput) returns (google.protobuf.Empty) {}
+
+ rpc AddRegisterWhiteList (aelf.Address) returns (google.protobuf.Empty) {}
+
+ rpc RemoveFromRegisterWhiteList (aelf.Address) returns (google.protobuf.Empty) {}
+
+ rpc ChangeOracleContractAddress (aelf.Address) returns (google.protobuf.Empty) {}
+
+ // Merkle tree style aggregator.
+
+ rpc GetMerklePath (GetMerklePathInput) returns (aelf.MerklePath) {
+ option (aelf.is_view) = true;
+ }
+
+ // View methods.
+
+ rpc GetReport (GetReportInput) returns (Report) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetSignature (GetSignatureInput) returns (google.protobuf.StringValue) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetOffChainAggregationInfo (GetOffChainAggregationInfoInput) returns (OffChainAggregationInfo) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetReportQueryRecord (aelf.Hash) returns (ReportQueryRecord) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetCurrentRoundId (GetCurrentRoundIdInput) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetRawReport (GetRawReportInput) returns (google.protobuf.StringValue) {
+ option (aelf.is_view) = true;
+ }
+ rpc GenerateRawReport (GenerateRawReportInput) returns (google.protobuf.StringValue) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetSignatureMap (GetSignatureMapInput) returns (SignatureMap) {
+ option (aelf.is_view) = true;
+ }
+ rpc IsInRegisterWhiteList (aelf.Address) returns (google.protobuf.BoolValue) {
+ option (aelf.is_view) = true;
+ }
+ rpc IsObserver (IsObserverInput) returns (google.protobuf.BoolValue) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetMortgagedTokenAmount (aelf.Address) returns (google.protobuf.Int64Value) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetObserverList (aelf.Address) returns (ObserverList) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetSkipMemberList(GetSkipMemberListInput) returns (MemberList){
+ option (aelf.is_view) = true;
+ }
+ rpc GetTokenByChainId(google.protobuf.StringValue) returns (google.protobuf.StringValue){
+ option (aelf.is_view) = true;
+ }
+}
+
+message InitializeInput {
+ aelf.Address oracle_contract_address = 1;
+ int64 report_fee = 2;
+ int64 apply_observer_fee = 3;
+ repeated aelf.Address initial_register_white_list = 4;
+ aelf.Address regiment_contract_address = 5;
+}
+
+message QueryOracleInput {
+ int64 payment = 1;
+ string token = 2;
+ int32 aggregate_threshold = 3;
+ int32 node_index = 4;
+ OffChainQueryInfo query_info = 5;
+ string chain_id = 6;
+}
+
+message ConfirmReportInput {
+ string token = 1;
+ int64 round_id = 2;
+ string signature = 3;
+ string chain_id = 4;
+}
+
+message RejectReportInput {
+ string token = 1;
+ int64 round_id = 2;
+ repeated aelf.Address accusing_nodes = 3;
+ string chain_id = 4;
+}
+
+message Report {
+ aelf.Hash query_id = 1;
+ int64 round_id = 2;
+ Observations observations = 3;
+ bytes aggregated_data = 4;
+}
+
+message ReportQueryRecord {
+ aelf.Address origin_query_sender = 1;
+ int64 paid_report_fee = 2;
+ bool is_rejected = 3;
+ bool is_all_node_confirmed = 4;
+ repeated aelf.Address confirmed_node_list = 5;
+ int64 payment = 6;
+}
+
+message ObserverList {
+ repeated aelf.Address value = 1;
+}
+
+message Observations {
+ repeated Observation value = 1;
+}
+
+message Observation {
+ string key = 1;
+ string data = 2;
+}
+
+message GetSignatureInput {
+ string token = 1;
+ int64 round_id = 2;
+ aelf.Address address = 3;
+ string chain_id = 4;
+}
+
+message GetSignatureMapInput {
+ string token = 1;
+ int64 round_id = 2;
+ string chain_id = 3;
+}
+
+message SignatureMap {
+ map value = 1;
+}
+
+message MemberList{
+ repeated aelf.Address value = 1;
+}
+
+message GetOffChainAggregationInfoInput{
+ string chain_id = 1;
+ string token = 2;
+}
+
+message OffChainAggregationInfo {
+ string token = 1;
+ OffChainQueryInfoList off_chain_query_info_list = 2;
+ aelf.Hash regiment_id = 3;
+ bytes config_digest = 4;
+ int32 aggregate_threshold = 5;
+ aelf.Address aggregator_contract_address = 6;
+ repeated int64 round_ids = 7;
+ string chain_id = 8;
+ aelf.Address register = 9;
+ int32 aggregate_option = 10;
+}
+
+message RegisterOffChainAggregationInput {
+ aelf.Hash regiment_id = 1;
+ OffChainQueryInfoList off_chain_query_info_list = 2;
+ string token = 3;
+ bytes config_digest = 4;
+ int32 aggregate_threshold = 5;
+ aelf.Address aggregator_contract_address = 6;
+ string chain_id = 7;
+ int32 aggregate_option = 8;
+}
+
+message BindOffChainAggregationInput {
+ repeated aelf.Hash task_id_list = 1;
+ string chain_name = 2;
+ string token = 3;
+ bytes config_digest = 4;
+}
+
+message OffChainQueryInfo {
+ string title = 1;
+ repeated string options = 2;
+}
+
+message GetReportInput {
+ string token = 1;
+ int64 round_id = 2;
+ string chain_id = 3;
+}
+
+message GetMerklePathInput {
+ string token = 1;
+ int64 round_id = 2;
+ int32 node_index = 3;
+ string chain_id = 4;
+}
+
+message GetRawReportInput{
+ string token = 1;
+ int64 round_id = 2;
+ string chain_id = 3;
+}
+
+message GetCurrentRoundIdInput{
+ string chain_id = 1;
+ string token = 2;
+}
+
+message GenerateRawReportInput{
+ Report report = 1;
+ bytes config_digest = 2;
+ aelf.Address organization = 3;
+}
+
+message OffChainQueryInfoList {
+ repeated OffChainQueryInfo value = 1;
+}
+
+message AddOffChainQueryInfoInput {
+ string token = 1;
+ string chain_id = 2;
+ OffChainQueryInfo off_chain_query_info = 3;
+}
+
+message RemoveOffChainQueryInfoInput {
+ string token = 1;
+ string chain_id = 2;
+ int32 remove_node_index = 3;
+}
+
+message ChangeOffChainQueryInfoInput {
+ string token = 1;
+ string chain_id = 2;
+ OffChainQueryInfo new_off_chain_query_info = 3;
+}
+
+message ApplyObserverInput {
+ repeated aelf.Address regiment_address_list = 1;
+}
+
+message QuitObserverInput {
+ repeated aelf.Address regiment_address_list = 1;
+}
+
+message IsObserverInput {
+ aelf.Address regiment_address = 1;
+ aelf.Address oracle_node_address = 2;
+}
+
+message SetSkipMemberListInput{
+ string token = 1;
+ MemberList value = 2;
+ string chain_id = 3;
+}
+
+message GetSkipMemberListInput{
+ string token = 1;
+ string chain_id = 2;
+}
+
+// Events
+
+message ReportProposed {
+ option (aelf.is_event) = true;
+ string raw_report = 1;
+ aelf.Hash regiment_id = 2;
+ string token = 3;
+ int64 round_id = 4;
+ OffChainQueryInfo query_info = 5;
+ string target_chain_id = 6;
+}
+
+message ReportConfirmed {
+ option (aelf.is_event) = true;
+ int64 round_id = 1;
+ string signature = 2;
+ aelf.Hash regiment_id = 3;
+ string token = 4;
+ bool is_all_node_confirmed = 5;
+ string target_chain_id = 6;
+}
+
+message OffChainAggregationRegistered {
+ option (aelf.is_event) = true;
+ string token = 1;
+ OffChainQueryInfoList off_chain_query_info_list = 2;
+ aelf.Hash regiment_id = 3;
+ bytes config_digest = 4;
+ int32 aggregate_threshold = 5;
+ aelf.Address aggregator_contract_address = 6;
+ string chain_id = 7;
+ aelf.Address register = 8;
+ int32 aggregate_option = 9;
+}
+
+message MerkleReportNodeAdded {
+ option (aelf.is_event) = true;
+ string token = 1;
+ int32 node_index = 2;
+ int64 node_round_id = 3;
+ string aggregated_data = 4;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/token_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/token_contract.proto
new file mode 100644
index 00000000..90c19450
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/token_contract.proto
@@ -0,0 +1,782 @@
+/**
+ * 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) {
+ }
+
+ // 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) {
+ }
+
+ // Change the issuer of the specified token. Only the original issuer can change it.
+ rpc ChangeTokenIssuer (ChangeTokenIssuerInput) 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) {
+ }
+
+ // 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 ResetExternalInfo (ResetExternalInfoInput) returns (google.protobuf.Empty){
+ }
+
+ rpc AddAddressToCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) {
+ }
+ rpc RemoveAddressFromCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) {
+ }
+
+ // 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;
+ }
+
+ // 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 IsInCreateTokenWhiteList (aelf.Address) returns (google.protobuf.BoolValue) {
+ option (aelf.is_view) = true;
+ }
+ rpc GetReservedExternalInfoKeyList (google.protobuf.Empty) returns (StringList) {
+ 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 created 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;
+}
+
+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 created 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;
+}
+
+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 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 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 ChangeTokenIssuerInput
+{
+ // The token symbol.
+ string symbol = 1;
+ // The new token issuer for change.
+ aelf.Address new_token_Issuer = 2;
+}
+
+message ResetExternalInfoInput {
+ string symbol = 1;
+ ExternalInfo external_info = 2;
+}
+
+message StringList {
+ repeated string value = 1;
+}
+
+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;
+}
+
+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 created 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;
+}
+
+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;
+}
+
+message ExternalInfoChanged {
+ option (aelf.is_event) = true;
+ string symbol = 1;
+ ExternalInfo external_info = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/token_contract_impl.proto b/modules/AElf.Client.Protobuf/Protobuf/token_contract_impl.proto
new file mode 100644
index 00000000..cfc91fcf
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/token_contract_impl.proto
@@ -0,0 +1,240 @@
+/**
+ * MultiToken contract.
+ *
+ * The MultiToken contract is mainly used to manage the user's account and transaction fees related Settings.
+ *
+ * Implement AElf Standards ACS1 and ACS2.
+ */
+syntax = "proto3";
+
+package tokenimpl;
+
+import "aelf/core.proto";
+import "acs1.proto";
+import "acs2.proto";
+import "token_contract.proto";
+// Because implementation uses this proto file.
+import "transaction_fee.proto";
+import "authority_info.proto";
+
+option csharp_namespace = "AElf.Contracts.MultiToken";
+
+service TokenContractImpl {
+ option (aelf.csharp_state) = "AElf.Contracts.MultiToken.TokenContractState";
+ option (aelf.base) = "acs1.proto";
+ option (aelf.base) = "acs2.proto";
+ option (aelf.base) = "token_contract.proto";
+
+ // Transfer resource tokens to designated contract address.
+ rpc AdvanceResourceToken (AdvanceResourceTokenInput) returns (google.protobuf.Empty) {
+ }
+
+ // Take token from contract address.
+ rpc TakeResourceTokenBack (TakeResourceTokenBackInput) returns (google.protobuf.Empty) {
+ }
+
+ // Register the token contract address for cross chain.
+ rpc RegisterCrossChainTokenContractAddress (RegisterCrossChainTokenContractAddressInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set the receiver address of the side chain transaction fee.
+ rpc SetFeeReceiver (aelf.Address) returns (google.protobuf.Empty) {
+ }
+
+ // Validates if the token exist.
+ rpc ValidateTokenInfoExists(ValidateTokenInfoExistsInput) returns (google.protobuf.Empty){
+ }
+
+ // Update the rental unit price of the side chain.
+ rpc UpdateRental (UpdateRentalInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set the amount of resources fee per minute for the side chain.
+ rpc UpdateRentedResources (UpdateRentedResourcesInput) returns (google.protobuf.Empty) {
+ }
+
+ // Transfer Token to the specified contract.
+ rpc TransferToContract (TransferToContractInput) returns (google.protobuf.Empty) {
+ }
+
+ // Change the governance organization of side chain rental.
+ rpc ChangeSideChainRentalController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Change the governance organization for tokens to pay transaction fees.
+ rpc ChangeSymbolsToPayTXSizeFeeController(AuthorityInfo) returns (google.protobuf.Empty){
+ }
+
+ // Change the governance organization for cross-chain token contract address registration.
+ rpc ChangeCrossChainTokenContractRegistrationController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Change the governance organization of the coefficient of the user transaction fee calculation formula.
+ rpc ChangeUserFeeController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Change the governance organization of the coefficient of the developer's transaction resource fee calculation formula.
+ rpc ChangeDeveloperController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Get the address of fee receiver.
+ rpc GetFeeReceiver (google.protobuf.Empty) returns (aelf.Address){
+ option (aelf.is_view) = true;
+ }
+
+ // Query the amount of resources usage currently.
+ rpc GetResourceUsage (google.protobuf.Empty) returns (ResourceUsage) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the governance organization for tokens to pay transaction fees.
+ rpc GetSymbolsToPayTXSizeFeeController(google.protobuf.Empty) returns (AuthorityInfo){
+ option (aelf.is_view) = true;
+ }
+
+ // Query the governance organization of the
+ rpc GetCrossChainTokenContractRegistrationController (google.protobuf.Empty) returns (AuthorityInfo) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the governance organization that calculates the formula coefficient
+ // for the transaction cost the user sends the contract.
+ rpc GetUserFeeController(google.protobuf.Empty) returns (UserFeeController){
+ option (aelf.is_view) = true;
+ }
+
+ // Query the governing organization of the formula coefficients for calculating developer contract transaction fee.
+ rpc GetDeveloperFeeController (google.protobuf.Empty) returns (DeveloperFeeController) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the organization that governs the side chain rental fee.
+ rpc GetSideChainRentalControllerCreateInfo (google.protobuf.Empty) returns (AuthorityInfo) {
+ option (aelf.is_view) = true;
+ }
+
+ // Compute the virtual address for locking.
+ rpc GetVirtualAddressForLocking (GetVirtualAddressForLockingInput) returns (aelf.Address) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query how much resource tokens should be paid currently.
+ rpc GetOwningRental (google.protobuf.Empty) returns (OwningRental) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the unit price of the side chain resource cost, resource cost = unit price * quantity,
+ // the quantity can be queried through GetResourceUsage.
+ rpc GetOwningRentalUnitValue (google.protobuf.Empty) returns (OwningRentalUnitValue) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message AdvanceResourceTokenInput {
+ // The contract address to transfer.
+ aelf.Address contract_address = 1;
+ // The resource token symbol to transfer.
+ string resource_token_symbol = 2;
+ // The amount of resource token to transfer.
+ int64 amount = 3;
+}
+
+message TakeResourceTokenBackInput {
+ // The contract address to take back.
+ aelf.Address contract_address = 1;
+ // The resource token symbol to take back.
+ string resource_token_symbol = 2;
+ // The amount of resource token to take back.
+ int64 amount = 3;
+}
+
+message RegisterCrossChainTokenContractAddressInput{
+ // The source chain id.
+ int32 from_chain_id = 1;
+ // The parent chain height of the transaction.
+ int64 parent_chain_height = 2;
+ // The raw bytes of the transfer transaction.
+ bytes transaction_bytes = 3;
+ // The merkle path created from the transaction.
+ aelf.MerklePath merkle_path = 4;
+ // The token contract address.
+ aelf.Address token_contract_address = 5;
+}
+
+message ValidateTokenInfoExistsInput{
+ // 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 created 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.
+ map external_info = 8;
+}
+
+message UpdateRentalInput {
+ // The unit price of resource tokens, symbol -> unit price.
+ map rental = 1;
+}
+
+message UpdateRentedResourcesInput {
+ // Amount of resource tokens consumed per minute, symbol -> resource consumption.
+ map resource_amount = 1;
+}
+
+message ResourceUsage {
+ // The amount of resource tokens usage, symbol -> amount.
+ map value = 1;
+}
+
+message GetVirtualAddressForLockingInput {
+ // The address of the lock.
+ aelf.Address address = 1;
+ // The id of the lock.
+ aelf.Hash lock_id = 2;
+}
+
+message OwningRental {
+ // The amount of resource tokens owed, symbol -> amount.
+ map resource_amount = 1;
+}
+
+message OwningRentalUnitValue {
+ // Resource unit price, symbol -> unit price.
+ map resource_unit_value = 1;
+}
+
+message TransferToContractInput {
+ // The symbol of token.
+ string symbol = 1;
+ // The amount of token.
+ int64 amount = 2;
+ // The memo.
+ string memo = 3;
+}
+
+message UserFeeController{
+ // The association that governs the organization.
+ AuthorityInfo root_controller = 1;
+ // The parliament organization of members.
+ AuthorityInfo parliament_controller = 2;
+ // The referendum organization of members.
+ AuthorityInfo referendum_controller = 3;
+}
+
+message DeveloperFeeController {
+ // The association that governs the organization.
+ AuthorityInfo root_controller = 1;
+ // The parliament organization of members.
+ AuthorityInfo parliament_controller = 2;
+ // The developer organization of members.
+ AuthorityInfo developer_controller = 3;
+}
diff --git a/modules/AElf.Client.Protobuf/Protobuf/token_converter_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/token_converter_contract.proto
new file mode 100644
index 00000000..af6e99c1
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/token_converter_contract.proto
@@ -0,0 +1,193 @@
+/**
+ * TokenConvert contract.
+ */
+syntax = "proto3";
+
+package TokenConverter;
+
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+import "aelf/core.proto";
+import "authority_info.proto";
+
+option csharp_namespace = "AElf.Contracts.TokenConverter";
+
+service TokenConverterContract {
+
+ option (aelf.csharp_state) = "AElf.Contracts.TokenConverter.TokenConverterContractState";
+
+ // Initialize TokenConvert contract.
+ rpc Initialize (InitializeInput) returns (google.protobuf.Empty) {
+ }
+
+ rpc SetConnector (Connector) returns (google.protobuf.Empty) {
+ }
+
+ // After establishing bancor model of token and base token, you can buy token through this method.
+ rpc Buy (BuyInput) returns (google.protobuf.Empty) {
+ }
+
+ // After establishing bancor model of token and base token, you can sell token through this method.
+ rpc Sell (SellInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set the fee rate for buy/sell (fee amount = cost * feeRate).
+ rpc SetFeeRate (google.protobuf.StringValue) returns (google.protobuf.Empty) {
+ }
+
+ // Before calling the EnableConnector, the connector controller can update the pair connector through this method.
+ rpc UpdateConnector(Connector) returns (google.protobuf.Empty){
+ }
+
+ // Add a pair connector for new token and the base token.
+ rpc AddPairConnector(PairConnectorParam) returns (google.protobuf.Empty){
+ }
+
+ // After adding a pair, you need to call this method to enable it before buy and sell token.
+ rpc EnableConnector (ToBeConnectedTokenInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Set the governance authority information for TokenConvert contract.
+ rpc ChangeConnectorController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // Query the pair connector according to token symbol.
+ rpc GetPairConnector (TokenSymbol) returns (PairConnector) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the fee rate for buy/sell.
+ rpc GetFeeRate (google.protobuf.Empty) returns (google.protobuf.StringValue) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the symbol of base token.
+ rpc GetBaseTokenSymbol (google.protobuf.Empty) returns (TokenSymbol) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query how much the base token need be deposited before enabling the connector.
+ rpc GetNeededDeposit(ToBeConnectedTokenInfo) returns (DepositInfo) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query how much the base token have been deposited.
+ rpc GetDepositConnectorBalance(google.protobuf.StringValue) returns (google.protobuf.Int64Value){
+ option (aelf.is_view) = true;
+ }
+
+ // Query the governance authority information for TokenConvert contract.
+ rpc GetControllerForManageConnector (google.protobuf.Empty) returns (AuthorityInfo) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query whether the token can be sold.
+ rpc IsSymbolAbleToSell (google.protobuf.StringValue) returns (google.protobuf.BoolValue) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message Connector {
+ // The token symbol.
+ string symbol = 1;
+ // The virtual balance for base token.
+ int64 virtual_balance = 2;
+ // The calculated weight value for this Connector.
+ string weight = 3;
+ // Whether to use Virtual Balance.
+ bool is_virtual_balance_enabled = 4;
+ // Whether the connector is enabled.
+ bool is_purchase_enabled = 5;
+ // Indicates its related connector, the pair connector includes a new created token connector and the base token connector.
+ string related_symbol = 6;
+ // Indicates if the connector is base token connector.
+ bool is_deposit_account = 7;
+}
+
+message TokenSymbol {
+ // The token symbol.
+ string symbol = 1;
+}
+
+message InitializeInput {
+ // Base token symbol, default is the native token symbol.
+ string base_token_symbol = 1;
+ // The fee rate for buy/sell.
+ string fee_rate = 2;
+ // The default added connectors.
+ repeated Connector connectors = 3;
+}
+
+message BuyInput {
+ // The token symbol you want to buy.
+ string symbol = 1;
+ // The amount you want to buy.
+ int64 amount = 2;
+ // Limit of cost. If the token required for buy exceeds this value, the buy will be abandoned.
+ // And 0 is no limit.
+ int64 pay_limit = 3;
+}
+
+message SellInput {
+ // The token symbol you want to sell.
+ string symbol = 1;
+ // The amount you want to sell.
+ int64 amount = 2;
+ // Limits on tokens obtained by selling. If the token obtained is less than this value, the sale will be abandoned.
+ // And 0 is no limit.
+ int64 receive_limit = 3;
+}
+
+message TokenBought {
+ option (aelf.is_event) = true;
+ // The token symbol bought.
+ string symbol = 1 [(aelf.is_indexed) = true];
+ // The amount bought.
+ int64 bought_amount = 2;
+ // The total cost of the base token.
+ int64 base_amount = 3;
+ // The fee amount.
+ int64 fee_amount =4;
+}
+
+message TokenSold {
+ option (aelf.is_event) = true;
+ // The token symbol sold.
+ string symbol = 1 [(aelf.is_indexed) = true];
+ // The amount sold.
+ int64 sold_amount = 2;
+ // The total received of the base token.
+ int64 base_amount = 3;
+ // The fee amount.
+ int64 fee_amount =4;
+}
+message PairConnectorParam {
+ // The token symbol.
+ string resource_connector_symbol = 1;
+ // The weight value of this token in the Bancor model.
+ string resource_weight = 2;
+ // This token corresponds to the value of base token.
+ int64 native_virtual_balance = 3;
+ // The weight value of base token in Bancor model.
+ string native_weight = 4;
+}
+
+message ToBeConnectedTokenInfo{
+ // The token symbol.
+ string token_symbol = 1;
+ // Specifies the number of tokens to convert to the TokenConvert contract.
+ int64 amount_to_token_convert = 2;
+}
+message DepositInfo{
+ // How much more base Token is needed as the deposit.
+ int64 need_amount = 1;
+ // How many tokens are not on the TokenConvert address.
+ int64 amount_out_of_token_convert = 2;
+}
+message PairConnector{
+ // The connector of the specified token.
+ Connector resource_connector = 1;
+ // The related connector.
+ Connector deposit_connector = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/token_holder_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/token_holder_contract.proto
new file mode 100644
index 00000000..53fd16c4
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/token_holder_contract.proto
@@ -0,0 +1,132 @@
+/**
+ * TokenHolder contract.
+ */
+syntax = "proto3";
+
+package TokenHolder;
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.TokenHolder";
+
+service TokenHolderContract {
+
+ option (aelf.csharp_state) = "AElf.Contracts.TokenHolder.TokenHolderContractState";
+
+ // Create a scheme for distributing bonus.
+ rpc CreateScheme (CreateTokenHolderProfitSchemeInput) returns (google.protobuf.Empty) {
+ }
+
+ // Add a beneficiary to a scheme.
+ rpc AddBeneficiary (AddTokenHolderBeneficiaryInput) returns (google.protobuf.Empty) {
+ }
+
+ // Removes a beneficiary from a scheme.
+ // Note: amount > 0: update the weight of the beneficiary, amount = 0: remove the beneficiary.
+ rpc RemoveBeneficiary (RemoveTokenHolderBeneficiaryInput) returns (google.protobuf.Empty) {
+ }
+
+ // Contribute profit to a scheme.
+ rpc ContributeProfits (ContributeProfitsInput) returns (google.protobuf.Empty) {
+ }
+
+ // To distribute the profits of the scheme, the stakeholders of the project may go to receive dividends.
+ rpc DistributeProfits (DistributeProfitsInput) returns (google.protobuf.Empty) {
+ }
+
+ // The user registers a bonus project.
+ rpc RegisterForProfits (RegisterForProfitsInput) returns (google.protobuf.Empty) {
+ }
+
+ // After the lockup time expires, the user can withdraw token.
+ rpc Withdraw (aelf.Address) returns (google.protobuf.Empty) {
+ }
+
+ // After DistributeProfits the holder can get his dividend.
+ rpc ClaimProfits (ClaimProfitsInput) returns (google.protobuf.Empty) {
+ }
+
+ // Query the details of the specified scheme.
+ rpc GetScheme (aelf.Address) returns (TokenHolderProfitScheme) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the dividends available to the holder.
+ rpc GetProfitsMap (ClaimProfitsInput) returns (ReceivedProfitsMap) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message CreateTokenHolderProfitSchemeInput {
+ // The token symbol.
+ string symbol = 1;
+ // Minimum lock time for holding token.
+ int64 minimum_lock_minutes = 2;
+ // Threshold setting for releasing dividends.
+ map auto_distribute_threshold = 3;
+}
+
+message AddTokenHolderBeneficiaryInput {
+ // Beneficiary's address.
+ aelf.Address beneficiary = 1;
+ // The weight of the beneficiary's dividends in the scheme.
+ int64 shares = 2;
+}
+
+message RemoveTokenHolderBeneficiaryInput {
+ // Beneficiary's address.
+ aelf.Address beneficiary = 1;
+ // The amount of weights to remove.
+ int64 amount = 2;
+}
+
+message ContributeProfitsInput {
+ // The manager of the scheme.
+ aelf.Address scheme_manager = 1;
+ // The amount of token to contribute.
+ int64 amount = 2;
+ // The symbol of token to contribute.
+ string symbol = 3;
+}
+
+message DistributeProfitsInput {
+ // The manager of the scheme.
+ aelf.Address scheme_manager = 1;
+ // The token to distribute, symbol -> amount.
+ map amounts_map = 2;
+}
+
+message RegisterForProfitsInput {
+ // The manager of the scheme.
+ aelf.Address scheme_manager = 1;
+ // The amount of token holding.
+ int64 amount = 2;
+}
+
+message ClaimProfitsInput {
+ // The manager of the scheme.
+ aelf.Address scheme_manager = 1;
+ // Beneficiary's address.
+ aelf.Address beneficiary = 2;
+}
+
+message TokenHolderProfitScheme {
+ // The token symbol.
+ string symbol = 1;
+ // The scheme id.
+ aelf.Hash scheme_id = 2;
+ // The current dividend period.
+ int64 period = 3;
+ // Minimum lock time for holding token.
+ int64 minimum_lock_minutes = 4;
+ // Threshold setting for releasing dividends.
+ map auto_distribute_threshold = 5;
+}
+
+message ReceivedProfitsMap {
+ // The amount of token the beneficiary can get, symbol -> amount.
+ map value = 1;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/transaction_fee.proto b/modules/AElf.Client.Protobuf/Protobuf/transaction_fee.proto
new file mode 100644
index 00000000..ed4ed8bf
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/transaction_fee.proto
@@ -0,0 +1,47 @@
+syntax = "proto3";
+
+package aelf;
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+
+option csharp_namespace = "AElf.Contracts.MultiToken";
+
+service TransactionFee {
+}
+
+// Messages
+
+message TransactionSizeFeeSymbols
+{
+ repeated TransactionSizeFeeSymbol transaction_size_fee_symbol_list = 1;
+}
+
+message TransactionSizeFeeSymbol
+{
+ string token_symbol = 1;
+ int32 base_token_weight = 2;
+ int32 added_token_weight = 3;
+}
+
+// Events
+
+message TransactionFeeCharged {
+ option (aelf.is_event) = true;
+ string symbol = 1;
+ int64 amount = 2;
+}
+
+message ResourceTokenCharged {
+ option (aelf.is_event) = true;
+ string symbol = 1;
+ int64 amount = 2;
+ aelf.Address contract_address = 3;
+}
+
+message ResourceTokenOwned {
+ option (aelf.is_event) = true;
+ string symbol = 1;
+ int64 amount = 2;
+ aelf.Address contract_address = 3;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/treasury_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/treasury_contract.proto
new file mode 100644
index 00000000..0ce87cfd
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/treasury_contract.proto
@@ -0,0 +1,149 @@
+/**
+ * Treasury contract.
+ */
+syntax = "proto3";
+
+package Treasury;
+
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+import "aelf/core.proto";
+import "authority_info.proto";
+
+option csharp_namespace = "AElf.Contracts.Treasury";
+
+service TreasuryContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Treasury.TreasuryContractState";
+
+ // Initialize treasury contract.
+ rpc InitialTreasuryContract (google.protobuf.Empty) returns (google.protobuf.Empty) {
+ }
+
+ // Initialize the sub-item of the bonus scheme.
+ rpc InitialMiningRewardProfitItem (google.protobuf.Empty) returns (google.protobuf.Empty) {
+ }
+
+ // Donate all tokens owned by the sender.
+ rpc DonateAll (DonateAllInput) returns (google.protobuf.Empty) {
+ }
+
+ // Set the dividend weight of the sub-item of the dividend item.
+ rpc SetDividendPoolWeightSetting (DividendPoolWeightSetting) returns (google.protobuf.Empty){
+ }
+
+ // Set the miner reward weight.
+ rpc SetMinerRewardWeightSetting (MinerRewardWeightSetting) returns (google.protobuf.Empty){
+ }
+
+ // Set the reward for mining.
+ rpc UpdateMiningReward (google.protobuf.Int64Value) returns (google.protobuf.Empty){
+ }
+
+ // Change the governance authority information for treasury contract.
+ rpc ChangeTreasuryController (AuthorityInfo) returns (google.protobuf.Empty) {
+ }
+
+ // AEDPoS Contract can notify Treasury Contract to aware miner replacement happened.
+ rpc RecordMinerReplacement (RecordMinerReplacementInput) returns (google.protobuf.Empty) {
+ }
+
+ // Used to estimate the revenue weight of 10000 tokens voted by users.
+ rpc GetWelfareRewardAmountSample (GetWelfareRewardAmountSampleInput) returns (GetWelfareRewardAmountSampleOutput) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the scheme id of treasury.
+ rpc GetTreasurySchemeId (google.protobuf.Empty) returns (aelf.Hash) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the weight percentage of dividend pool items.
+ rpc GetDividendPoolWeightProportion (google.protobuf.Empty) returns (DividendPoolWeightProportion) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the weight percentage of the dividend item for miner.
+ rpc GetMinerRewardWeightProportion (google.protobuf.Empty) returns (MinerRewardWeightProportion) {
+ option (aelf.is_view) = true;
+ }
+
+ // Query the governance authority information.
+ rpc GetTreasuryController (google.protobuf.Empty) returns (AuthorityInfo) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message GetWelfareRewardAmountSampleInput {
+ // Token lock time.
+ repeated int64 value = 1;
+}
+
+message GetWelfareRewardAmountSampleOutput {
+ // The weight calculated.
+ repeated int64 value = 1;
+}
+
+message DonateAllInput {
+ // The token symbol to donate.
+ string symbol = 1;
+}
+
+message MinerReElectionInformation {
+ // The reappointment information for miner.
+ map continual_appointment_times = 1;
+}
+
+message DividendPoolWeightSetting {
+ // The dividend weight for citizen.
+ int32 citizen_welfare_weight = 1;
+ // The dividend weight for backup nodes.
+ int32 backup_subsidy_weight = 2;
+ // The dividend weight for miners.
+ int32 miner_reward_weight = 3;
+}
+
+message MinerRewardWeightSetting {
+ // The dividend weight for all current miners.
+ int32 basic_miner_reward_weight = 1;
+ // The dividend weight for new miners.
+ int32 welcome_reward_weight = 2;
+ // The dividend weight for the flexible scheme.
+ int32 flexible_reward_weight = 3;
+}
+
+message SchemeProportionInfo {
+ // The scheme id.
+ aelf.Hash scheme_id = 1;
+ // Dividend weight percentage.
+ int32 proportion = 2;
+}
+
+message DividendPoolWeightProportion {
+ // The proportion of citizen welfare.
+ SchemeProportionInfo citizen_welfare_proportion_info = 1;
+ // The proportion of candidate nodes.
+ SchemeProportionInfo backup_subsidy_proportion_info = 2;
+ // The proportion of miner
+ SchemeProportionInfo miner_reward_proportion_info = 3;
+}
+
+message MinerRewardWeightProportion {
+ // The proportion of the basic income of the miner.
+ SchemeProportionInfo basic_miner_reward_proportion_info = 1;
+ // The proportion of the vote of the miner.
+ SchemeProportionInfo welcome_reward_proportion_info = 2;
+ // The proportion of the reappointment of the miner.
+ SchemeProportionInfo flexible_reward_proportion_info = 3;
+}
+
+message RecordMinerReplacementInput {
+ string old_pubkey = 1;
+ string new_pubkey = 2;
+ int64 current_term_number = 3;
+ bool is_old_pubkey_evil = 4;
+}
+
+message StringList {
+ repeated string value = 1;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/vote_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/vote_contract.proto
new file mode 100644
index 00000000..2c7e0e64
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/vote_contract.proto
@@ -0,0 +1,311 @@
+/**
+ * Vote contract.
+ */
+syntax = "proto3";
+
+package Vote;
+
+import "aelf/core.proto";
+import "google/protobuf/timestamp.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option csharp_namespace = "AElf.Contracts.Vote";
+
+service VoteContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Vote.VoteContractState";
+
+ // Create a voting activity.
+ rpc Register (VotingRegisterInput) returns (google.protobuf.Empty) {
+ }
+
+ // After successfully creating a voting activity, others are able to vote.
+ rpc Vote (VoteInput) returns (google.protobuf.Empty) {
+ }
+
+ // A voter can withdraw the token after the lock time.
+ rpc Withdraw (WithdrawInput) returns (google.protobuf.Empty) {
+ }
+
+ // Save the result of the specified number of votes and generates a new round votes.
+ rpc TakeSnapshot (TakeSnapshotInput) returns (google.protobuf.Empty) {
+ }
+
+ // Add an option to a voting activity.
+ rpc AddOption (AddOptionInput) returns (google.protobuf.Empty) {
+ }
+
+ // Remove an option from a voting activity.
+ rpc RemoveOption (RemoveOptionInput) returns (google.protobuf.Empty) {
+ }
+
+ // Add multiple options to a voting activity.
+ rpc AddOptions (AddOptionsInput) returns (google.protobuf.Empty) {
+ }
+
+ // Remove multiple options from a voting activity.
+ rpc RemoveOptions (RemoveOptionsInput) returns (google.protobuf.Empty) {
+ }
+
+ // Get a voting activity information.
+ rpc GetVotingItem (GetVotingItemInput) returns (VotingItem) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get a voting result according to the provided voting activity id and snapshot number.
+ rpc GetVotingResult (GetVotingResultInput) returns (VotingResult) {
+ option (aelf.is_view) = true;
+ }
+
+ // Gets the latest result according to the voting activity id.
+ rpc GetLatestVotingResult (aelf.Hash) returns (VotingResult) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the voting record according to vote id.
+ rpc GetVotingRecord (aelf.Hash) returns (VotingRecord) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the voting record according to vote ids.
+ rpc GetVotingRecords (GetVotingRecordsInput) returns (VotingRecords) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get all voted information according to voter address.
+ rpc GetVotedItems (aelf.Address) returns (VotedItems) {
+ option (aelf.is_view) = true;
+ }
+
+ // Get the vote ids according to voting activity id.
+ rpc GetVotingIds (GetVotingIdsInput) returns (VotedIds) {
+ option (aelf.is_view) = true;
+ }
+}
+
+message VotingRegisterInput {
+ // The start time of the voting.
+ google.protobuf.Timestamp start_timestamp = 1;
+ // The end time of the voting.
+ google.protobuf.Timestamp end_timestamp = 2;
+ // The token symbol which will be accepted.
+ string accepted_currency = 3;
+ // Whether the vote will lock token.
+ bool is_lock_token = 4;
+ // The total number of snapshots of the vote.
+ int64 total_snapshot_number = 5;
+ // The list of options.
+ repeated string options = 6;
+}
+
+message VotingItem {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The token symbol which will be accepted.
+ string accepted_currency = 2;
+ // Whether the vote will lock token.
+ bool is_lock_token = 3;
+ // The current snapshot number.
+ int64 current_snapshot_number = 4;
+ // The total snapshot number.
+ int64 total_snapshot_number = 5;
+ // The list of options.
+ repeated string options = 6;
+ // The register time of the voting activity.
+ google.protobuf.Timestamp register_timestamp = 7;
+ // The start time of the voting.
+ google.protobuf.Timestamp start_timestamp = 8;
+ // The end time of the voting.
+ google.protobuf.Timestamp end_timestamp = 9;
+ // The start time of current round of the voting.
+ google.protobuf.Timestamp current_snapshot_start_timestamp = 10;
+ // The sponsor address of the voting activity.
+ aelf.Address sponsor = 11;
+}
+
+message VoteInput {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The address of voter.
+ aelf.Address voter = 2;
+ // The amount of vote.
+ int64 amount = 3;
+ // The option to vote.
+ string option = 4;
+ // The vote id.
+ aelf.Hash vote_id = 5;
+ // Whether vote others.
+ bool is_change_target = 6;
+}
+
+message WithdrawInput {
+ // The vote id.
+ aelf.Hash vote_id = 1;
+}
+
+message GetVotingResultInput {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The snapshot number.
+ int64 snapshot_number = 2;
+}
+
+message VotingResult {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The voting result, option -> amount of votes,
+ map results = 2;
+ // The snapshot number.
+ int64 snapshot_number = 3;
+ // The total number of voters.
+ int64 voters_count = 4;
+ // The start time of this snapshot.
+ google.protobuf.Timestamp snapshot_start_timestamp = 5;
+ // The end time of this snapshot.
+ google.protobuf.Timestamp snapshot_end_timestamp = 6;
+ // Total votes received during the process of this snapshot.
+ int64 votes_amount = 7;
+}
+
+message TakeSnapshotInput {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The snapshot number to take.
+ int64 snapshot_number = 2;
+}
+
+message VotingRecord {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The address of voter.
+ aelf.Address voter = 2;
+ // The snapshot number.
+ int64 snapshot_number = 3;
+ // The amount of vote.
+ int64 amount = 4;
+ // The time of withdraw.
+ google.protobuf.Timestamp withdraw_timestamp = 5;
+ // The time of vote.
+ google.protobuf.Timestamp vote_timestamp = 6;
+ // Whether the vote had been withdrawn.
+ bool is_withdrawn = 7;
+ // The option voted.
+ string option = 8;
+ // Whether vote others.
+ bool is_change_target = 9;
+}
+
+message AddOptionInput {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The new option to add.
+ string option = 2;
+}
+
+message RemoveOptionInput {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The option to remove.
+ string option = 2;
+}
+
+message AddOptionsInput {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The new options to add.
+ repeated string options = 2;
+}
+
+message RemoveOptionsInput {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The options to remove.
+ repeated string options = 2;
+}
+
+message VotedItems {
+ // The voted ids.
+ map voted_item_vote_ids = 1;
+}
+
+message VotedIds {
+ // The active vote ids.
+ repeated aelf.Hash active_votes = 1;
+ // The withdrawn vote ids.
+ repeated aelf.Hash withdrawn_votes = 2;
+}
+
+message GetVotingIdsInput {
+ // The address of voter.
+ aelf.Address voter = 1;
+ // The voting activity id.
+ aelf.Hash voting_item_id = 2;
+}
+
+message GetVotingItemInput {
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+}
+
+message GetVotingRecordsInput {
+ // The vote ids.
+ repeated aelf.Hash ids = 1;
+}
+
+message VotingRecords {
+ // The voting records.
+ repeated VotingRecord records = 1;
+}
+
+message Voted {
+ option (aelf.is_event) = true;
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The address of voter.
+ aelf.Address voter = 2;
+ // The snapshot number.
+ int64 snapshot_number = 3;
+ // The amount of vote.
+ int64 amount = 4;
+ // The time of vote.
+ google.protobuf.Timestamp vote_timestamp = 5;
+ // The option voted.
+ string option = 6;
+ // The vote id.
+ aelf.Hash vote_id = 7;
+}
+
+message Withdrawn {
+ option (aelf.is_event) = true;
+ // The vote id.
+ aelf.Hash vote_id = 1;
+ aelf.Hash voting_item_id = 2;
+ int64 amount = 3;
+ string option = 4;
+ aelf.Address voter = 5;
+}
+
+message VotingItemRegistered {
+ option (aelf.is_event) = true;
+ // The voting activity id.
+ aelf.Hash voting_item_id = 1;
+ // The token symbol which will be accepted.
+ string accepted_currency = 2;
+ // Whether the vote will lock token.
+ bool is_lock_token = 3;
+ // The current snapshot number.
+ int64 current_snapshot_number = 4;
+ // The total number of snapshots of the vote.
+ int64 total_snapshot_number = 5;
+ // The register time of the voting activity.
+ google.protobuf.Timestamp register_timestamp = 6;
+ // The start time of the voting.
+ google.protobuf.Timestamp start_timestamp = 7;
+ // The end time of the voting.
+ google.protobuf.Timestamp end_timestamp = 8;
+ // The start time of current round of the voting.
+ google.protobuf.Timestamp current_snapshot_start_timestamp = 9;
+ // The sponsor address of the voting activity.
+ aelf.Address sponsor = 10;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Protobuf/Protobuf/whitelist_contract.proto b/modules/AElf.Client.Protobuf/Protobuf/whitelist_contract.proto
new file mode 100644
index 00000000..37ce7afd
--- /dev/null
+++ b/modules/AElf.Client.Protobuf/Protobuf/whitelist_contract.proto
@@ -0,0 +1,581 @@
+syntax = "proto3";
+
+package whitelist;
+
+import "aelf/core.proto";
+import "aelf/options.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+import "acs1.proto";
+
+option csharp_namespace = "AElf.Contracts.Whitelist";
+
+service WhitelistContract {
+ option (aelf.csharp_state) = "AElf.Contracts.Whitelist.WhitelistContractState";
+ option (aelf.base) = "acs1.proto";
+
+ rpc Initialize (google.protobuf.Empty) returns (google.protobuf.Empty) {
+ }
+
+ //For Managers.
+ //Create whitelist.
+ rpc CreateWhitelist (CreateWhitelistInput) returns (aelf.Hash){
+ }
+
+ //Add tag info or extraInfo.
+ rpc AddExtraInfo (AddExtraInfoInput) returns (aelf.Hash){
+ }
+
+ //Add multiple addresses to an existing whitelist.
+ rpc AddAddressInfoListToWhitelist (AddAddressInfoListToWhitelistInput) returns (google.protobuf.Empty){
+ }
+
+ //Remove multiple addresses from an existing whitelist.
+ rpc RemoveAddressInfoListFromWhitelist (RemoveAddressInfoListFromWhitelistInput) returns (google.protobuf.Empty){
+ }
+
+ //Remove tag info.
+ rpc RemoveTagInfo (RemoveTagInfoInput) returns (google.protobuf.Empty){
+ }
+
+ //Disable whitelist according to the whitelist_id.
+ rpc DisableWhitelist (aelf.Hash) returns (google.protobuf.Empty){
+ }
+
+ //Re-enable whitelist according to the whitelist_id.
+ rpc EnableWhitelist (aelf.Hash) returns (google.protobuf.Empty){
+ }
+
+ //Update state: Whether the whitelist is allowed to be cloned.
+ rpc ChangeWhitelistCloneable(ChangeWhitelistCloneableInput) returns (google.protobuf.Empty){
+ }
+
+ //Update whitelist extraInfo according to the whitelist_id and extraInfo.
+ rpc UpdateExtraInfo (UpdateExtraInfoInput) returns (google.protobuf.Empty){
+ }
+
+ //Transfer Manager.
+ rpc TransferManager (TransferManagerInput) returns (google.protobuf.Empty){
+ }
+
+ //Add manager.
+ rpc AddManagers (AddManagersInput) returns (google.protobuf.Empty){
+ }
+
+ //Remove manager.
+ rpc RemoveManagers (RemoveManagersInput) returns (google.protobuf.Empty){
+ }
+
+ //Reset whitelist according to the whitelist_id and project_id.
+ rpc ResetWhitelist (ResetWhitelistInput) returns (google.protobuf.Empty){
+ }
+
+
+ //For Subscribers.
+ //Subscribe whitelist.
+ rpc SubscribeWhitelist (SubscribeWhitelistInput) returns (aelf.Hash){
+ }
+
+ // Cancel subscribe according to the subscribe_id.
+ rpc UnsubscribeWhitelist (aelf.Hash) returns (google.protobuf.Empty){
+ }
+
+ //After used,address and extra info will be added into the consumedList.
+ rpc ConsumeWhitelist (ConsumeWhitelistInput) returns (google.protobuf.Empty){
+ }
+
+ //Clone whitelist.
+ rpc CloneWhitelist (CloneWhitelistInput) returns (aelf.Hash){
+ }
+
+ //Add subscribe whitelist manager.
+ rpc AddSubscribeManagers (AddSubscribeManagersInput) returns (google.protobuf.Empty){
+ }
+
+ //Remove subscribe whitelist manager.
+ rpc RemoveSubscribeManagers (RemoveSubscribeManagersInput) returns (google.protobuf.Empty){
+ }
+
+
+ //Views.
+ //Get whitelist_id list according to the manager.
+ rpc GetWhitelistByManager (aelf.Address) returns (WhitelistIdList){
+ option (aelf.is_view) = true;
+ }
+
+ //Get existing whitelist according to the whitelist_id.
+ rpc GetWhitelist (aelf.Hash) returns (WhitelistInfo){
+ option (aelf.is_view) = true;
+ }
+
+ //Get whitelist detail extraInfo according to the whitelist_id.
+ rpc GetWhitelistDetail (aelf.Hash) returns(ExtraInfoList){
+ option (aelf.is_view) = true;
+ }
+
+ //Get whitelist id by project_id.
+ rpc GetWhitelistByProject(aelf.Hash) returns (WhitelistIdList){
+ option (aelf.is_view) = true;
+ }
+
+ //Get extraInfo according to the tag_id.
+ rpc GetExtraInfoByTag (GetExtraInfoByTagInput) returns (ExtraInfo){
+ option (aelf.is_view) = true;
+ }
+
+ //Get tag info according to the tag_info_id.
+ rpc GetTagInfoByHash (aelf.Hash) returns (TagInfo){
+ option (aelf.is_view) = true;
+ }
+
+ //Get tagInfoId list according to the whitelist_id and project_id.
+ rpc GetExtraInfoIdList(GetExtraInfoIdListInput) returns (HashList){
+ option (aelf.is_view) = true;
+ }
+
+ //Get tagId according to the whitelist_id and address.
+ rpc GetTagIdByAddress(GetTagIdByAddressInput) returns (aelf.Hash){
+ option (aelf.is_view) = true;
+ }
+
+ //Get TagInfo according to the address and whitelist_id.
+ rpc GetExtraInfoByAddress(GetExtraInfoByAddressInput) returns (TagInfo){
+ option (aelf.is_view) = true;
+ }
+
+ //Whether the address exists in the whitelist according to the whitelist_id and address.
+ rpc GetAddressFromWhitelist(GetAddressFromWhitelistInput) returns (google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+
+ //Whether the extraInfo (address+TagInfoId) exists in the whitelist according to the whitelist_id and address.
+ rpc GetExtraInfoFromWhitelist(GetExtraInfoFromWhitelistInput) returns (google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+
+ //Whether the tagInfo exists in the whitelist according to the whitelist_id,project_id,tagInfo(tagName,info).
+ rpc GetTagInfoFromWhitelist(GetTagInfoFromWhitelistInput) returns (google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+
+ //Get manager list according to the whitelist_id.
+ rpc GetManagerList(aelf.Hash) returns (AddressList){
+ option (aelf.is_view) = true;
+ }
+
+ //Get subscribe manager list according to the subscribe_id.
+ rpc GetSubscribeManagerList(aelf.Hash) returns (AddressList){
+ option (aelf.is_view) = true;
+ }
+
+ //Whether manager exist in whitelist.
+ rpc GetManagerExistFromWhitelist(GetManagerExistFromWhitelistInput) returns (google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+
+ //Get subscribe whitelist info according to the subscribe_id.
+ rpc GetSubscribeWhitelist (aelf.Hash) returns (SubscribeWhitelistInfo){
+ option (aelf.is_view) = true;
+ }
+
+ //Get subscribe_id list according to the manager.
+ rpc GetSubscribeIdByManager (aelf.Address) returns (HashList){
+ option (aelf.is_view) = true;
+ }
+
+ //Get consumed list according to the subscribe_id.
+ rpc GetConsumedList (aelf.Hash) returns (ConsumedList){
+ option (aelf.is_view) = true;
+ }
+
+ //After consumed,get available whitelist according to the subscribe_id.
+ rpc GetAvailableWhitelist (aelf.Hash) returns (ExtraInfoIdList){
+ option (aelf.is_view) = true;
+ }
+
+ //Whether the extraInfo exist in the available whitelist.
+ rpc GetFromAvailableWhitelist (GetFromAvailableWhitelistInput) returns (google.protobuf.BoolValue){
+ option (aelf.is_view) = true;
+ }
+
+
+}
+
+//Structs.
+
+message WhitelistInfo {
+ //The whitelist id.
+ aelf.Hash whitelist_id = 1;
+ //The project id.
+ aelf.Hash project_id = 2;
+ //The list of address and extra info in this whitelist.
+ ExtraInfoIdList extra_info_id_list = 3;
+ //Whether the whitelist is available.
+ bool is_available = 4;
+ //Whether the whiteList can be cloned.
+ bool is_cloneable = 5;
+ string remark = 6;
+ aelf.Hash clone_from = 7;
+ aelf.Address creator = 8;
+ AddressList manager = 9;
+ StrategyType strategy_type = 10;
+}
+
+//Pricing strategy
+message PriceTag{
+ string symbol = 1;
+ int64 amount = 2;
+}
+
+enum StrategyType{
+ Basic = 0;
+ Price = 1;
+ Customize = 2;
+}
+
+message ExtraInfoIdList {
+ repeated ExtraInfoId value = 1;
+}
+
+message ExtraInfoId {
+ AddressList address_list = 1;
+ aelf.Hash id = 2;
+}
+
+message ExtraInfoList {
+ repeated ExtraInfo value = 1;
+}
+
+message ExtraInfo {
+ AddressList address_list = 1;
+ TagInfo info = 2;
+}
+
+message TagInfo {
+ string tag_name = 1;
+ bytes info = 2;
+}
+
+message TagInfoList{
+ repeated TagInfo value = 1;
+}
+
+message WhitelistIdList{
+ repeated aelf.Hash whitelist_id = 1;
+}
+
+message SubscribeWhitelistInfo {
+ //The subscribe id.
+ aelf.Hash subscribe_id = 1;
+ //The project id.
+ aelf.Hash project_id = 2;
+ //The whitelist id.
+ aelf.Hash whitelist_id = 3;
+ aelf.Address subscriber = 4;
+ //Manager list.
+ AddressList manager_list = 5;
+}
+
+message ConsumedList {
+ //The subscribe id.
+ aelf.Hash subscribe_id = 1;
+ //The whitelist id.
+ aelf.Hash whitelist_id = 2;
+ //The consumed address and extra info list in this whitelist.
+ ExtraInfoIdList extra_info_id_list = 3;
+}
+
+message AddressList {
+ repeated aelf.Address value = 1;
+}
+
+message HashList{
+ repeated aelf.Hash value = 1;
+}
+
+//Inputs.
+
+//message InitializeInput{
+//
+//}
+
+message CreateWhitelistInput {
+ ExtraInfoList extra_info_list = 1;
+ bool is_cloneable = 2;
+ string remark = 3;
+ aelf.Address creator = 4;
+ AddressList manager_list = 5;
+ aelf.Hash project_id = 6;
+ StrategyType strategy_type = 7;
+}
+
+message AddAddressInfoListToWhitelistInput {
+ aelf.Hash whitelist_id = 1;
+ ExtraInfoIdList extra_info_id_list = 2;
+}
+
+message RemoveAddressInfoListFromWhitelistInput{
+ aelf.Hash whitelist_id = 1;
+ ExtraInfoIdList extra_info_id_list = 2;
+}
+
+message ChangeWhitelistCloneableInput{
+ aelf.Hash whitelist_id = 1;
+ bool is_cloneable = 2;
+}
+
+message AddExtraInfoInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Hash project_id = 2;
+ TagInfo tag_info = 3;
+ AddressList address_list = 4;
+}
+
+message RemoveTagInfoInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Hash project_id = 2;
+ aelf.Hash tag_id = 3;
+}
+
+message UpdateExtraInfoInput{
+ aelf.Hash whitelist_id = 1;
+ ExtraInfoId extra_info_list = 2;
+}
+
+message SubscribeWhitelistInput{
+ //The project id.
+ aelf.Hash project_id = 1;
+ //The whitelist id.
+ aelf.Hash whitelist_id = 2;
+ //Subscriber.
+ aelf.Address subscriber = 3;
+ //Manager list.
+ AddressList manager_list = 4;
+}
+
+message ConsumeWhitelistInput{
+ aelf.Hash subscribe_id = 1;
+ aelf.Hash whitelist_id = 2;
+ ExtraInfoId extra_info_id = 3;
+}
+
+message CloneWhitelistInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Address creator = 2;
+ AddressList manager_list = 3;
+ aelf.Hash project_id = 4;
+}
+
+message TransferManagerInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Address manager = 2;
+}
+
+message GetFromAvailableWhitelistInput{
+ aelf.Hash subscribe_id = 1;
+ ExtraInfoId extra_info_id = 2;
+}
+
+message AddManagersInput{
+ aelf.Hash whitelist_id = 1;
+ AddressList manager_list = 2;
+}
+
+message AddSubscribeManagersInput{
+ aelf.Hash subscribe_id = 1;
+ AddressList manager_list = 2;
+}
+
+message RemoveManagersInput{
+ aelf.Hash whitelist_id = 1;
+ AddressList manager_list = 2;
+}
+
+message RemoveSubscribeManagersInput{
+ aelf.Hash subscribe_id = 1;
+ AddressList manager_list = 2;
+}
+
+message GetTagIdByAddressInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Address address = 2;
+}
+
+message GetExtraInfoByAddressInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Address address = 2;
+}
+
+message GetExtraInfoIdListInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Hash project_id = 2;
+}
+
+message GetExtraInfoByTagInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Hash tag_info_id = 2;
+}
+
+message GetAddressFromWhitelistInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Address address = 2;
+}
+
+message GetExtraInfoFromWhitelistInput{
+ aelf.Hash whitelist_id = 1;
+ ExtraInfoId extra_info_id = 2;
+}
+
+message GetTagInfoFromWhitelistInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Hash project_id = 2;
+ TagInfo tag_info = 3;
+}
+
+message GetManagerExistFromWhitelistInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Address manager = 2;
+}
+
+message ResetWhitelistInput{
+ aelf.Hash whitelist_id = 1;
+ aelf.Hash project_id = 2;
+}
+
+//Events.
+
+message WhitelistCreated {
+ option (aelf.is_event) = true;
+ //The whitelist id.
+ aelf.Hash whitelist_id = 1;
+ //The list of address and extra info in this whitelist.
+ ExtraInfoIdList extra_info_id_list = 2;
+ //Whether the whitelist is available.
+ bool is_available = 3;
+ bool is_cloneable = 4;
+ string remark = 5;
+ aelf.Hash clone_from = 6;
+ aelf.Address creator = 7;
+ AddressList manager = 8;
+ aelf.Hash project_id = 9;
+ StrategyType strategy_type = 10;
+
+}
+
+message WhitelistSubscribed {
+ option (aelf.is_event) = true;
+ //The subscribe id.
+ aelf.Hash subscribe_id = 1;
+ //The project id.
+ aelf.Hash project_id = 2;
+ //The whitelist id.
+ aelf.Hash whitelist_id = 3;
+ //Subscriber.
+ aelf.Address subscriber = 4;
+ //Manager list.
+ AddressList manager_list = 5;
+}
+
+message WhitelistUnsubscribed{
+ option (aelf.is_event) = true;
+ aelf.Hash subscribe_id = 1;
+ aelf.Hash project_id = 2;
+ aelf.Hash whitelist_id = 3;
+}
+
+message WhitelistAddressInfoAdded {
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ ExtraInfoIdList extra_info_id_list = 2;
+}
+
+message WhitelistAddressInfoRemoved {
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ ExtraInfoIdList extra_info_id_list = 2;
+}
+
+message WhitelistDisabled {
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ bool is_available = 2;
+}
+
+message WhitelistReenable{
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ bool is_available = 2;
+}
+
+message ConsumedListAdded {
+ option (aelf.is_event) = true;
+ aelf.Hash subscribe_id = 1;
+ aelf.Hash whitelist_id = 2;
+ ExtraInfoIdList extra_info_id_list = 3;
+}
+
+message IsCloneableChanged{
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ bool is_cloneable = 2;
+}
+
+message TagInfoAdded{
+ option (aelf.is_event) = true;
+ aelf.Hash tag_info_id = 1;
+ TagInfo tag_info = 2;
+ aelf.Hash project_id = 3;
+ aelf.Hash whitelist_id = 4;
+}
+
+message TagInfoRemoved{
+ option (aelf.is_event) = true;
+ aelf.Hash tag_info_id = 1;
+ TagInfo tag_info = 2;
+ aelf.Hash project_id = 3;
+ aelf.Hash whitelist_id = 4;
+}
+
+message ExtraInfoUpdated {
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ ExtraInfoId extra_info_id_before = 2;
+ ExtraInfoId extra_info_id_after = 3;
+}
+
+message ManagerTransferred{
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ aelf.Address transfer_from = 2;
+ aelf.Address transfer_to = 3;
+}
+
+message ManagerAdded{
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ AddressList manager_list = 2;
+}
+
+message ManagerRemoved{
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ AddressList manager_list = 2;
+}
+
+message WhitelistReset{
+ option (aelf.is_event) = true;
+ aelf.Hash whitelist_id = 1;
+ aelf.Hash project_id = 2;
+}
+
+message SubscribeManagerAdded{
+ option (aelf.is_event) = true;
+ aelf.Hash subscribe_id = 1;
+ AddressList manager_list = 2;
+}
+
+message SubscribeManagerRemoved{
+ option (aelf.is_event) = true;
+ aelf.Hash subscribe_id = 1;
+ AddressList manager_list = 2;
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Report/AElf.Client.Report.csproj b/modules/AElf.Client.Report/AElf.Client.Report.csproj
new file mode 100644
index 00000000..4c2cb352
--- /dev/null
+++ b/modules/AElf.Client.Report/AElf.Client.Report.csproj
@@ -0,0 +1,34 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TextTemplatingFileGenerator
+ ReportService.g.cs
+
+
+
+
+
+ True
+ True
+ ReportService.tt
+
+
+
+
diff --git a/modules/AElf.Client.Report/AElfClientReportModule.cs b/modules/AElf.Client.Report/AElfClientReportModule.cs
new file mode 100644
index 00000000..8f0a0429
--- /dev/null
+++ b/modules/AElf.Client.Report/AElfClientReportModule.cs
@@ -0,0 +1,12 @@
+using AElf.Client.Core;
+using Volo.Abp.Modularity;
+
+namespace AElf.Client.Report;
+
+[DependsOn(
+ typeof(AElfClientModule),
+ typeof(CoreAElfModule)
+)]
+public class AElfClientReportModule : AbpModule
+{
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Report/ContractService.ttinclude b/modules/AElf.Client.Report/ContractService.ttinclude
new file mode 100644
index 00000000..ee5f7dba
--- /dev/null
+++ b/modules/AElf.Client.Report/ContractService.ttinclude
@@ -0,0 +1,58 @@
+<#@ template language="C#"#>
+<#@ output extension=".g.cs"#>
+<#@ import namespace="System.Collections.Generic" #>
+<#+
+ public string ContractName = "Report";
+
+ public List ContractMethodInfoList = new()
+ {
+ new ContractMethodInfo("ProposeReport", "CallbackInput"),
+ new ContractMethodInfo("ConfirmReport"),
+ new ContractMethodInfo("RejectReport"),
+ };
+
+ public class ContractMethodInfo
+ {
+ public ContractMethodInfo(string methodName)
+ {
+ MethodName = methodName;
+ }
+
+ public ContractMethodInfo(string methodName, string parameterTypeName)
+ {
+ MethodName = methodName;
+ _parameterTypeName = parameterTypeName;
+ }
+
+ public string MethodName { get; set; }
+ private string _parameterTypeName;
+
+ public string ParameterTypeName
+ {
+ get => _parameterTypeName ?? $"{MethodName}Input";
+ set => _parameterTypeName = value;
+ }
+
+ public string InputName => ConvertMethodNameToInputName(MethodName);
+ }
+
+ ///
+ /// Generates text for a given sequence of items, automatically adding the necessary spacing
+ ///
+ public void GenerateTextForItems(IReadOnlyList items, Action factory)
+ {
+ for (int i = 0; i < items.Count; i++)
+ {
+ // Insert a blank line after the first item
+ if (i > 0) WriteLine("");
+
+ // Invoke the factory with the current item
+ factory(items [i]);
+ }
+ }
+
+ public static string ConvertMethodNameToInputName(string methodName)
+ {
+ return $"{char.ToLowerInvariant(methodName[0])}{methodName.Substring(1)}Input";
+ }
+#>
diff --git a/modules/AElf.Client.Report/ReportService.cs b/modules/AElf.Client.Report/ReportService.cs
new file mode 100644
index 00000000..70d6d680
--- /dev/null
+++ b/modules/AElf.Client.Report/ReportService.cs
@@ -0,0 +1,84 @@
+using AElf.Client.Core;
+using AElf.Client.Core.Options;
+using AElf.Contracts.Report;
+using AElf.Types;
+using Google.Protobuf;
+using Google.Protobuf.WellKnownTypes;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.Client.Report;
+
+public interface IReportService
+{
+ Task ProposeReportAsync(string chainId, CallbackInput proposeReportInput);
+
+ Task ConfirmReportAsync(string chainId, ConfirmReportInput confirmReportInput);
+
+ Task RejectReportAsync(string chainId, RejectReportInput rejectReportInput);
+
+ Task GetRawReportAsync(string chainId, GetRawReportInput getRawReportInput);
+
+ Task GetReportAsync(string chainId, GetReportInput getReportInput);
+}
+
+public class ReportService : ContractServiceBase, IReportService, ITransientDependency
+{
+ private readonly IAElfClientService _clientService;
+ protected override string SmartContractName { get; } = "ReportContract";
+
+ public ReportService(IAElfClientService clientService)
+ {
+ _clientService = clientService;
+ }
+
+ public async Task ProposeReportAsync(string chainId, CallbackInput proposeReportInput)
+ {
+ var tx = await PerformSendTransactionAsync("ProposeReport", proposeReportInput, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task ConfirmReportAsync(string chainId, ConfirmReportInput confirmReportInput)
+ {
+ var tx = await PerformSendTransactionAsync("ConfirmReport", confirmReportInput, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task RejectReportAsync(string chainId, RejectReportInput rejectReportInput)
+ {
+ var tx = await PerformSendTransactionAsync("RejectReport", rejectReportInput, chainId);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), chainId)
+ };
+ }
+
+ public async Task GetRawReportAsync(string chainId, GetRawReportInput getRawReportInput)
+ {
+ var result =
+ await _clientService.ViewAsync(GetContractAddress(chainId), "GetRawReport",
+ getRawReportInput, AElfChainAliasOptions.Value.Mapping[chainId]);
+ var actualResult = new StringValue();
+ actualResult.MergeFrom(result);
+ return actualResult;
+ }
+
+ public async Task GetReportAsync(string chainId, GetReportInput getReportInput)
+ {
+ var result =
+ await _clientService.ViewAsync(GetContractAddress(chainId), "GetReport",
+ getReportInput, AElfChainAliasOptions.Value.Mapping[chainId]);
+ var actualResult = new Contracts.Report.Report();
+ actualResult.MergeFrom(result);
+ return actualResult;
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client.Report/ReportService.tt b/modules/AElf.Client.Report/ReportService.tt
new file mode 100644
index 00000000..074d3a95
--- /dev/null
+++ b/modules/AElf.Client.Report/ReportService.tt
@@ -0,0 +1,54 @@
+<#@include file="ContractService.ttinclude" #><#@ import namespace="System.Diagnostics.Contracts" #>
+using AElf.Client.Core;
+using AElf.Client.Core.Options;
+using AElf.Contracts.<#=ContractName#>;
+using AElf.Types;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace AElf.Client.<#=ContractName#>;
+
+public interface I<#=ContractName#>Service
+{
+<#
+ GenerateTextForItems(ContractMethodInfoList, item =>
+ {
+#>
+ Task <#=item.MethodName#>Async(<#=item.ParameterTypeName#> <#=item.InputName#>);
+<#
+ });
+#>
+}
+
+public class <#=ContractName#>Service : ContractServiceBase, I<#=ContractName#>Service, ITransientDependency
+{
+ private readonly IAElfClientService _clientService;
+ private readonly AElfClientConfigOptions _clientConfigOptions;
+
+ protected <#=ContractName#>Service(IAElfClientService clientService,
+ IOptionsSnapshot clientConfigOptions,
+ IOptionsSnapshot contractOptions) : base(clientService,
+ Address.FromBase58(contractOptions.Value.ContractAddressList["<#=ContractName#>ContractAddress"]))
+ {
+ _clientService = clientService;
+ _clientConfigOptions = clientConfigOptions.Value;
+ }
+
+<#
+ GenerateTextForItems(ContractMethodInfoList, item =>
+ {
+#>
+ public async Task <#=item.MethodName#>Async(<#=item.ParameterTypeName#> <#=item.InputName#>)
+ {
+ var useClientAlias = _clientConfigOptions.ClientAlias;
+ var tx = await PerformSendTransactionAsync("<#=item.MethodName#>", <#=item.InputName#>, useClientAlias);
+ return new SendTransactionResult
+ {
+ Transaction = tx,
+ TransactionResult = await PerformGetTransactionResultAsync(tx.GetHash().ToHex(), useClientAlias)
+ };
+ }
+<#
+ });
+#>
+}
\ No newline at end of file
diff --git a/modules/AElf.Client/AElf.Client.csproj b/modules/AElf.Client/AElf.Client.csproj
new file mode 100644
index 00000000..e6d508f3
--- /dev/null
+++ b/modules/AElf.Client/AElf.Client.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net6.0
+ enable
+ enable
+ AElf.Client
+ This is a C# client library, used to communicate with the AElf API.
+ AElf
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/AElf.Client/AElfClient.Block.cs b/modules/AElf.Client/AElfClient.Block.cs
new file mode 100644
index 00000000..b6c73014
--- /dev/null
+++ b/modules/AElf.Client/AElfClient.Block.cs
@@ -0,0 +1,44 @@
+using AElf.Client.Dto;
+using AElf.Client.Services;
+
+namespace AElf.Client;
+
+public partial class AElfClient : IBlockAppService
+{
+ ///
+ /// Get height of the current chain.
+ ///
+ /// Height
+ public async Task GetBlockHeightAsync()
+ {
+ var url = GetRequestUrl(_baseUrl, "api/blockChain/blockHeight");
+ return await _httpService.GetResponseAsync(url);
+ }
+
+ ///
+ /// Get information of a block by given block hash. Optional whether to include transaction information.
+ ///
+ ///
+ ///
+ /// Block information
+ public async Task GetBlockByHashAsync(string blockHash, bool includeTransactions = false)
+ {
+ AssertValidHash(blockHash);
+ var url = GetRequestUrl(_baseUrl,
+ $"api/blockChain/block?blockHash={blockHash}&includeTransactions={includeTransactions}");
+ return await _httpService.GetResponseAsync(url);
+ }
+
+ ///
+ /// Get information of a block by specified height. Optional whether to include transaction information.
+ ///
+ ///
+ ///
+ /// Block information
+ public async Task GetBlockByHeightAsync(long blockHeight, bool includeTransactions = false)
+ {
+ var url = GetRequestUrl(_baseUrl,
+ $"api/blockChain/blockByHeight?blockHeight={blockHeight}&includeTransactions={includeTransactions}");
+ return await _httpService.GetResponseAsync(url);
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client/AElfClient.Chain.cs b/modules/AElf.Client/AElfClient.Chain.cs
new file mode 100644
index 00000000..e42eb0fd
--- /dev/null
+++ b/modules/AElf.Client/AElfClient.Chain.cs
@@ -0,0 +1,69 @@
+using AElf.Client.Dto;
+
+namespace AElf.Client;
+
+public partial class AElfClient : IChainAppService
+{
+ ///
+ /// Get the current status of the block chain.
+ ///
+ /// Description of current status
+ public async Task GetChainStatusAsync()
+ {
+ var url = GetRequestUrl(_baseUrl, "api/blockChain/chainStatus");
+ var chainStatus = await _httpService.GetResponseAsync(url);
+ if (chainStatus == null)
+ {
+ throw new AElfClientException("Failed to get chain status");
+ }
+
+ return chainStatus;
+ }
+
+ ///
+ /// Get the definitions of proto-buff related to a contract.
+ ///
+ ///
+ /// Definitions of proto-buff
+ public async Task GetContractFileDescriptorSetAsync(string? address)
+ {
+ AssertValidAddress(address);
+ var url = GetRequestUrl(_baseUrl, $"api/blockChain/contractFileDescriptorSet?address={address}");
+ var set = await _httpService.GetResponseAsync(url);
+ if (set == null)
+ {
+ throw new AElfClientException("Failed to get chain status");
+ }
+
+ return set;
+ }
+
+ ///
+ /// Gets the status information of the task queue.
+ ///
+ /// Information of the task queue
+ public async Task> GetTaskQueueStatusAsync()
+ {
+ var url = GetRequestUrl(_baseUrl, "api/blockChain/taskQueueStatus");
+
+ var taskQueueInfoList = await _httpService.GetResponseAsync>(url);
+ if (taskQueueInfoList == null)
+ {
+ throw new AElfClientException("Failed to get chain status");
+ }
+
+ return taskQueueInfoList;
+ }
+
+ ///
+ /// Get id of the chain.
+ ///
+ /// ChainId
+ public async Task GetChainIdAsync()
+ {
+ var chainStatus = await GetChainStatusAsync();
+ var base58ChainId = chainStatus.ChainId;
+ var chainId = ChainHelper.ConvertBase58ToChainId(base58ChainId);
+ return chainId;
+ }
+}
\ No newline at end of file
diff --git a/modules/AElf.Client/AElfClient.Client.cs b/modules/AElf.Client/AElfClient.Client.cs
new file mode 100644
index 00000000..fd455c2e
--- /dev/null
+++ b/modules/AElf.Client/AElfClient.Client.cs
@@ -0,0 +1,265 @@
+using AElf.Client.Dto;
+using AElf.Client.Extensions;
+using AElf.Client.Model;
+using AElf.Client.Services;
+using AElf.Cryptography;
+using AElf.Cryptography.ECDSA;
+using Google.Protobuf;
+using Google.Protobuf.WellKnownTypes;
+
+namespace AElf.Client;
+
+public partial class AElfClient : IClientService
+{
+ ///
+ /// Verify whether this sdk successfully connects the chain.
+ ///
+ /// IsConnected or not
+ public async Task IsConnectedAsync()
+ {
+ try
+ {
+ await GetChainStatusAsync();
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Get the address of genesis contract.
+ ///
+ /// Address
+ public async Task GetGenesisContractAddressAsync()
+ {
+ var statusDto = await GetChainStatusAsync();
+ var genesisAddress = statusDto.GenesisContractAddress;
+ return genesisAddress;
+ }
+
+ ///
+ /// Get address of a contract by given contractNameHash.
+ ///
+ ///
+ /// Address
+ public async Task GetContractAddressByNameAsync(Hash contractNameHash)
+ {
+ var from = GetAddressFromPrivateKey(AElfClientConstants.DefaultPrivateKey);
+ var to = await GetGenesisContractAddressAsync();
+ var transaction = await GenerateTransactionAsync(from, to, "GetContractAddressByName", contractNameHash);
+ var txWithSig = SignTransaction(AElfClientConstants.DefaultPrivateKey, transaction);
+
+ var response = await ExecuteTransactionAsync(new ExecuteTransactionDto
+ {
+ RawTransaction = txWithSig.ToByteArray().ToHex()
+ });
+ var byteArray = ByteArrayHelper.HexStringToByteArray(response);
+ var address = Address.Parser.ParseFrom(byteArray);
+
+ return address;
+ }
+
+ ///
+ /// Build a transaction from the input parameters.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Transaction unsigned
+ public async Task GenerateTransactionAsync(string? from, string? to,
+ string methodName, IMessage input)
+ {
+ try
+ {
+ AssertValidAddress(to);
+ var chainStatus = await GetChainStatusAsync();
+ var transaction = new Transaction
+ {
+ From = from.ToAddress(),
+ To = Address.FromBase58(to),
+ MethodName = methodName,
+ Params = input.ToByteString(),
+ RefBlockNumber = chainStatus.BestChainHeight,
+ RefBlockPrefix = ByteString.CopyFrom(Hash.LoadFromHex(chainStatus.BestChainHash).Value
+ .Take(4).ToArray())
+ };
+
+ return transaction;
+ }
+ catch (Exception ex)
+ {
+ throw new AElfClientException($"Failed to generate transaction: {ex.Message}");
+ }
+ }
+
+ ///
+ /// Convert the Address to the displayed string:symbol_base58-string_base58-string-chain-id
+ ///
+ ///
+ ///
+ public async Task GetFormattedAddressAsync(Address address)
+ {
+ var tokenContractAddress =
+ await GetContractAddressByNameAsync(HashHelper.ComputeFrom("AElf.ContractNames.Token"));
+ var fromAddress = GetAddressFromPrivateKey(AElfClientConstants.DefaultPrivateKey);
+ var toAddress = tokenContractAddress.ToBase58();
+ var methodName = "GetPrimaryTokenSymbol";
+ var param = new Empty();
+
+ var transaction = await GenerateTransactionAsync(fromAddress, toAddress, methodName, param);
+ var txWithSign = SignTransaction(AElfClientConstants.DefaultPrivateKey, transaction);
+
+ var result = await ExecuteTransactionAsync(new ExecuteTransactionDto
+ {
+ RawTransaction = txWithSign.ToByteArray().ToHex()
+ });
+
+ var symbol = StringValue.Parser.ParseFrom(ByteArrayHelper.HexStringToByteArray(result));
+ var chainIdString = (await GetChainStatusAsync()).ChainId;
+
+ return $"{symbol.Value}_{address.ToBase58()}_{chainIdString}";
+ }
+
+ ///
+ /// Sign a transaction using private key.
+ ///
+ ///
+ ///
+ /// Transaction signed
+ public Transaction SignTransaction(string? privateKeyHex, Transaction transaction)
+ {
+ var transactionData = transaction.GetHash().ToByteArray();
+
+ privateKeyHex ??= AElfClientConstants.DefaultPrivateKey;
+
+ // Sign the hash
+ var privateKey = ByteArrayHelper.HexStringToByteArray(privateKeyHex);
+ var signature = CryptoHelper.SignWithPrivateKey(privateKey, transactionData);
+ transaction.Signature = ByteString.CopyFrom(signature);
+
+ return transaction;
+ }
+
+ ///
+ /// Sign a transaction using private key.
+ ///
+ ///
+ ///
+ /// Transaction signed
+ public Transaction SignTransaction(byte[]? privateKey, Transaction transaction)
+ {
+ var transactionData = transaction.GetHash().ToByteArray();
+
+ privateKey ??= ByteArrayHelper.HexStringToByteArray(AElfClientConstants.DefaultPrivateKey);
+
+ // Sign the hash
+ var signature = CryptoHelper.SignWithPrivateKey(privateKey, transactionData);
+ transaction.Signature = ByteString.CopyFrom(signature);
+
+ return transaction;
+ }
+
+ ///
+ /// Get the account address through the public key.
+ ///
+ ///
+ /// Account
+ public string GetAddressFromPubKey(string pubKey)
+ {
+ var publicKey = ByteArrayHelper.HexStringToByteArray(pubKey);
+ var address = Address.FromPublicKey(publicKey);
+ return address.ToBase58();
+ }
+
+ ///
+ /// Get the account address through the private key.
+ ///
+ ///
+ ///
+ public string? GetAddressFromPrivateKey(string? privateKeyHex)
+ {
+ var address = Address.FromPublicKey(GetAElfKeyPair(privateKeyHex).PublicKey);
+ return address.ToBase58();
+ }
+
+ public KeyPairInfo GenerateKeyPairInfo()
+ {
+ var keyPair = CryptoHelper.GenerateKeyPair();
+ var privateKey = keyPair.PrivateKey.ToHex();
+ var publicKey = keyPair.PublicKey.ToHex();
+ var address = GetAddressFromPrivateKey(privateKey);
+
+ return new KeyPairInfo
+ {
+ PrivateKey = privateKey,
+ PublicKey = publicKey,
+ Address = address
+ };
+ }
+
+ #region private methods
+
+ private ECKeyPair GetAElfKeyPair(string? privateKeyHex)
+ {
+ var privateKey = ByteArrayHelper.HexStringToByteArray(privateKeyHex);
+ var keyPair = CryptoHelper.FromPrivateKey(privateKey);
+
+ return keyPair;
+ }
+
+ private string GetRequestUrl(string baseUrl, string relativeUrl)
+ {
+ var uri = new Uri(baseUrl + (baseUrl.EndsWith("/") ? "" : "/"));
+ return new Uri(uri, relativeUrl).ToString();
+ }
+
+ private void AssertValidAddress(params string?[] addresses)
+ {
+ try
+ {
+ foreach (var address in addresses)
+ {
+ Address.FromBase58(address);
+ }
+ }
+ catch (Exception)
+ {
+ throw new AElfClientException(Error.Message[Error.InvalidAddress]);
+ }
+ }
+
+ private void AssertValidHash(params string[] hashes)
+ {
+ try
+ {
+ foreach (var hash in hashes)
+ {
+ Hash.LoadFromHex(hash);
+ }
+ }
+ catch (Exception)
+ {
+ throw new AElfClientException(Error.Message[Error.InvalidBlockHash]);
+ }
+ }
+
+ private void AssertValidTransactionId(params string[] transactionIds)
+ {
+ try
+ {
+ foreach (var transactionId in transactionIds)
+ {
+ Hash.LoadFromHex(transactionId);
+ }
+ }
+ catch (Exception)
+ {
+ throw new AElfClientException(Error.Message[Error.InvalidTransactionId]);
+ }
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/modules/AElf.Client/AElfClient.Net.cs b/modules/AElf.Client/AElfClient.Net.cs
new file mode 100644
index 00000000..5b4d4fb7
--- /dev/null
+++ b/modules/AElf.Client/AElfClient.Net.cs
@@ -0,0 +1,80 @@
+using System.Net.Http.Headers;
+using System.Text;
+using AElf.Client.Dto;
+using AElf.Client.Helper;
+using AElf.Client.Services;
+
+namespace AElf.Client;
+
+public partial class AElfClient : INetAppService
+{
+ ///
+ /// Attempt to add a node to the connected network nodes.Input parameter contains the ipAddress of the node.
+ ///
+ ///
+ ///
+ ///
+ /// Add successfully or not
+ public async Task AddPeerAsync(string ipAddress, string? userName, string? password)
+ {
+ if (!EndpointHelper.TryParse(ipAddress, out var endpoint))
+ {
+ return false;
+ }
+
+ var url = GetRequestUrl(_baseUrl, "api/net/peer");
+ var parameters = new Dictionary
+ {
+ { "address", endpoint?.ToString() ?? AElfClientConstants.LocalEndpoint },
+ };
+
+ return await _httpService.PostResponseAsync(url, parameters,
+ authenticationHeaderValue: GetAuthenticationHeaderValue(userName, password));
+ }
+
+ ///
+ /// Attempt to remove a node from the connected network nodes by given the ipAddress.
+ ///
+ ///
+ ///
+ ///
+ /// Delete successfully or not
+ public async Task RemovePeerAsync(string ipAddress, string? userName, string? password)
+ {
+ if (!EndpointHelper.TryParse(ipAddress, out var endpoint))
+ {
+ return false;
+ }
+
+ var url = GetRequestUrl(_baseUrl, $"api/net/peer?address={endpoint}");
+ return await _httpService.DeleteResponseAsObjectAsync