Просмотр исходного кода

feat(blockchain): 添加区块链相关功能和测试命令

- 新增 Test 命令类,实现 TRON 和 BSC/ETH网络的区块链操作示例- 添加 get_token_info 和 do_request 辅助函数,用于获取代币信息和发起 CURL 请求
- 在 command.php 中注册 Test命令
- 新增 .idea 目录下的 IDE 配置文件,优化开发环境
kirin 6 месяцев назад
Родитель
Сommit
de50f85c2b
100 измененных файлов с 9042 добавлено и 197 удалено
  1. 8 0
      .idea/.gitignore
  2. 6 0
      .idea/inspectionProfiles/Project_Default.xml
  3. 16 0
      .idea/jsLinters/jshint.xml
  4. 8 0
      .idea/modules.xml
  5. 74 0
      .idea/php.xml
  6. 77 0
      .idea/shrx.iml
  7. 6 0
      .idea/vcs.xml
  8. 205 0
      application/admin/command/Test.php
  9. 1 0
      application/command.php
  10. 75 12
      application/common.php
  11. 146 106
      application/config.php
  12. 7 1
      composer.json
  13. 1134 78
      composer.lock
  14. 173 0
      extend/blockchain/TronService.php
  15. 183 0
      extend/blockchain/Web3Service.php
  16. 42 0
      extend/blockchain/web3/Bep20.php
  17. 40 0
      extend/blockchain/web3/Bep721.php
  18. 16 0
      extend/blockchain/web3/Callback.php
  19. 56 0
      extend/blockchain/web3/Credential.php
  20. 68 0
      extend/blockchain/web3/Kit.php
  21. 89 0
      extend/blockchain/web3/NodeClient.php
  22. 185 0
      extend/blockchain/web3/SmartContract.php
  23. 134 0
      extend/blockchain/web3/Transactor.php
  24. 14 0
      extend/blockchain/web3/helper.php
  25. 257 0
      extend/blockchain/web3/json/bep20.json
  26. 636 0
      extend/blockchain/web3/src/Contract.php
  27. 399 0
      extend/blockchain/web3/src/Contracts/Ethabi.php
  28. 273 0
      extend/blockchain/web3/src/Contracts/SolidityType.php
  29. 86 0
      extend/blockchain/web3/src/Contracts/Types/Address.php
  30. 81 0
      extend/blockchain/web3/src/Contracts/Types/Boolean.php
  31. 100 0
      extend/blockchain/web3/src/Contracts/Types/Bytes.php
  32. 97 0
      extend/blockchain/web3/src/Contracts/Types/DynamicBytes.php
  33. 39 0
      extend/blockchain/web3/src/Contracts/Types/IType.php
  34. 82 0
      extend/blockchain/web3/src/Contracts/Types/Integer.php
  35. 90 0
      extend/blockchain/web3/src/Contracts/Types/Str.php
  36. 82 0
      extend/blockchain/web3/src/Contracts/Types/Uinteger.php
  37. 180 0
      extend/blockchain/web3/src/Eth.php
  38. 44 0
      extend/blockchain/web3/src/Formatters/AddressFormatter.php
  39. 33 0
      extend/blockchain/web3/src/Formatters/BigNumberFormatter.php
  40. 30 0
      extend/blockchain/web3/src/Formatters/BooleanFormatter.php
  41. 38 0
      extend/blockchain/web3/src/Formatters/HexFormatter.php
  42. 23 0
      extend/blockchain/web3/src/Formatters/IFormatter.php
  43. 44 0
      extend/blockchain/web3/src/Formatters/IntegerFormatter.php
  44. 34 0
      extend/blockchain/web3/src/Formatters/NumberFormatter.php
  45. 35 0
      extend/blockchain/web3/src/Formatters/OptionalQuantityFormatter.php
  46. 37 0
      extend/blockchain/web3/src/Formatters/PostFormatter.php
  47. 47 0
      extend/blockchain/web3/src/Formatters/QuantityFormatter.php
  48. 30 0
      extend/blockchain/web3/src/Formatters/StringFormatter.php
  49. 47 0
      extend/blockchain/web3/src/Formatters/TransactionFormatter.php
  50. 57 0
      extend/blockchain/web3/src/Methods/Eth/Accounts.php
  51. 60 0
      extend/blockchain/web3/src/Methods/Eth/BlockNumber.php
  52. 70 0
      extend/blockchain/web3/src/Methods/Eth/Call.php
  53. 58 0
      extend/blockchain/web3/src/Methods/Eth/Coinbase.php
  54. 64 0
      extend/blockchain/web3/src/Methods/Eth/CompileLLL.php
  55. 64 0
      extend/blockchain/web3/src/Methods/Eth/CompileSerpent.php
  56. 64 0
      extend/blockchain/web3/src/Methods/Eth/CompileSolidity.php
  57. 67 0
      extend/blockchain/web3/src/Methods/Eth/EstimateGas.php
  58. 61 0
      extend/blockchain/web3/src/Methods/Eth/GasPrice.php
  59. 74 0
      extend/blockchain/web3/src/Methods/Eth/GetBalance.php
  60. 66 0
      extend/blockchain/web3/src/Methods/Eth/GetBlockByHash.php
  61. 71 0
      extend/blockchain/web3/src/Methods/Eth/GetBlockByNumber.php
  62. 67 0
      extend/blockchain/web3/src/Methods/Eth/GetBlockTransactionCountByHash.php
  63. 69 0
      extend/blockchain/web3/src/Methods/Eth/GetBlockTransactionCountByNumber.php
  64. 71 0
      extend/blockchain/web3/src/Methods/Eth/GetCode.php
  65. 58 0
      extend/blockchain/web3/src/Methods/Eth/GetCompilers.php
  66. 64 0
      extend/blockchain/web3/src/Methods/Eth/GetFilterChanges.php
  67. 64 0
      extend/blockchain/web3/src/Methods/Eth/GetFilterLogs.php
  68. 61 0
      extend/blockchain/web3/src/Methods/Eth/GetLogs.php
  69. 72 0
      extend/blockchain/web3/src/Methods/Eth/GetStorageAt.php
  70. 66 0
      extend/blockchain/web3/src/Methods/Eth/GetTransactionByBlockHashAndIndex.php
  71. 68 0
      extend/blockchain/web3/src/Methods/Eth/GetTransactionByBlockNumberAndIndex.php
  72. 64 0
      extend/blockchain/web3/src/Methods/Eth/GetTransactionByHash.php
  73. 74 0
      extend/blockchain/web3/src/Methods/Eth/GetTransactionCount.php
  74. 64 0
      extend/blockchain/web3/src/Methods/Eth/GetTransactionReceipt.php
  75. 66 0
      extend/blockchain/web3/src/Methods/Eth/GetUncleByBlockHashAndIndex.php
  76. 68 0
      extend/blockchain/web3/src/Methods/Eth/GetUncleByBlockNumberAndIndex.php
  77. 67 0
      extend/blockchain/web3/src/Methods/Eth/GetUncleCountByBlockHash.php
  78. 72 0
      extend/blockchain/web3/src/Methods/Eth/GetUncleCountByBlockNumber.php
  79. 58 0
      extend/blockchain/web3/src/Methods/Eth/GetWork.php
  80. 61 0
      extend/blockchain/web3/src/Methods/Eth/Hashrate.php
  81. 58 0
      extend/blockchain/web3/src/Methods/Eth/Mining.php
  82. 64 0
      extend/blockchain/web3/src/Methods/Eth/NewBlockFilter.php
  83. 61 0
      extend/blockchain/web3/src/Methods/Eth/NewFilter.php
  84. 58 0
      extend/blockchain/web3/src/Methods/Eth/NewPendingTransactionFilter.php
  85. 61 0
      extend/blockchain/web3/src/Methods/Eth/ProtocolVersion.php
  86. 64 0
      extend/blockchain/web3/src/Methods/Eth/SendRawTransaction.php
  87. 64 0
      extend/blockchain/web3/src/Methods/Eth/SendTransaction.php
  88. 66 0
      extend/blockchain/web3/src/Methods/Eth/Sign.php
  89. 61 0
      extend/blockchain/web3/src/Methods/Eth/SubmitHashrate.php
  90. 65 0
      extend/blockchain/web3/src/Methods/Eth/SubmitWork.php
  91. 58 0
      extend/blockchain/web3/src/Methods/Eth/Syncing.php
  92. 64 0
      extend/blockchain/web3/src/Methods/Eth/UninstallFilter.php
  93. 158 0
      extend/blockchain/web3/src/Methods/EthMethod.php
  94. 24 0
      extend/blockchain/web3/src/Methods/IMethod.php
  95. 29 0
      extend/blockchain/web3/src/Methods/IRPC.php
  96. 215 0
      extend/blockchain/web3/src/Methods/JSONRPC.php
  97. 58 0
      extend/blockchain/web3/src/Methods/Net/Listening.php
  98. 61 0
      extend/blockchain/web3/src/Methods/Net/PeerCount.php
  99. 58 0
      extend/blockchain/web3/src/Methods/Net/Version.php
  100. 58 0
      extend/blockchain/web3/src/Methods/Personal/ListAccounts.php

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 6 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="JSHint" enabled="true" level="ERROR" enabled_by_default="true" />
+  </profile>
+</component>

+ 16 - 0
.idea/jsLinters/jshint.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JSHintConfiguration" version="2.13.0" use-config-file="true" use-custom-config-file="true" custom-config-file-path="$PROJECT_DIR$/public/assets/libs/jquery/src/.jshintrc">
+    <option bitwise="true" />
+    <option browser="true" />
+    <option curly="true" />
+    <option eqeqeq="true" />
+    <option forin="true" />
+    <option maxerr="50" />
+    <option noarg="true" />
+    <option noempty="true" />
+    <option nonew="true" />
+    <option strict="true" />
+    <option undef="true" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/shrx.iml" filepath="$PROJECT_DIR$/.idea/shrx.iml" />
+    </modules>
+  </component>
+</project>

+ 74 - 0
.idea/php.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PhpIncludePathManager">
+    <include_path>
+      <path value="$PROJECT_DIR$/vendor/markbaker/complex" />
+      <path value="$PROJECT_DIR$/vendor/markbaker/matrix" />
+      <path value="$PROJECT_DIR$/vendor/mdanter/ecc" />
+      <path value="$PROJECT_DIR$/vendor/alipayrsa2/lotusphp_runtime" />
+      <path value="$PROJECT_DIR$/vendor/endroid/qr-code" />
+      <path value="$PROJECT_DIR$/vendor/myclabs/php-enum" />
+      <path value="$PROJECT_DIR$/vendor/ezyang/htmlpurifier" />
+      <path value="$PROJECT_DIR$/vendor/alipayrsa2/aop" />
+      <path value="$PROJECT_DIR$/vendor/phpoffice/phpspreadsheet" />
+      <path value="$PROJECT_DIR$/vendor/phpmailer/phpmailer" />
+      <path value="$PROJECT_DIR$/vendor/fgrosse/phpasn1" />
+      <path value="$PROJECT_DIR$/vendor/kornrunner/keccak" />
+      <path value="$PROJECT_DIR$/vendor/kornrunner/secp256k1" />
+      <path value="$PROJECT_DIR$/vendor/phpseclib/phpseclib" />
+      <path value="$PROJECT_DIR$/vendor/iexbase/tron-api" />
+      <path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
+      <path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
+      <path value="$PROJECT_DIR$/vendor/monolog/monolog" />
+      <path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
+      <path value="$PROJECT_DIR$/vendor/symfony/psr-http-message-bridge" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/cache" />
+      <path value="$PROJECT_DIR$/vendor/overtrue/pinyin" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
+      <path value="$PROJECT_DIR$/vendor/overtrue/wechat" />
+      <path value="$PROJECT_DIR$/vendor/overtrue/socialite" />
+      <path value="$PROJECT_DIR$/vendor/pimple/pimple" />
+      <path value="$PROJECT_DIR$/vendor/simplito/bigint-wrapper-php" />
+      <path value="$PROJECT_DIR$/vendor/simplito/bn-php" />
+      <path value="$PROJECT_DIR$/vendor/composer" />
+      <path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
+      <path value="$PROJECT_DIR$/vendor/topthink/think-installer" />
+      <path value="$PROJECT_DIR$/vendor/simplito/elliptic-php" />
+      <path value="$PROJECT_DIR$/vendor/topthink/think-captcha" />
+      <path value="$PROJECT_DIR$/vendor/psr/log" />
+      <path value="$PROJECT_DIR$/vendor/psr/container" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-message" />
+      <path value="$PROJECT_DIR$/vendor/mtdowling/cron-expression" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-factory" />
+      <path value="$PROJECT_DIR$/vendor/sc0vu/web3.php" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-client" />
+      <path value="$PROJECT_DIR$/vendor/karsonzhang/fastadmin-addons" />
+      <path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
+      <path value="$PROJECT_DIR$/vendor/ratchet/pawl" />
+      <path value="$PROJECT_DIR$/vendor/ratchet/rfc6455" />
+      <path value="$PROJECT_DIR$/vendor/web3p/web3.php" />
+      <path value="$PROJECT_DIR$/vendor/evenement/evenement" />
+      <path value="$PROJECT_DIR$/vendor/fig/http-message-util" />
+      <path value="$PROJECT_DIR$/vendor/react/stream" />
+      <path value="$PROJECT_DIR$/vendor/react/cache" />
+      <path value="$PROJECT_DIR$/vendor/react/event-loop" />
+      <path value="$PROJECT_DIR$/vendor/react/promise" />
+      <path value="$PROJECT_DIR$/vendor/react/promise-timer" />
+      <path value="$PROJECT_DIR$/vendor/react/http" />
+      <path value="$PROJECT_DIR$/vendor/react/async" />
+      <path value="$PROJECT_DIR$/vendor/react/socket" />
+      <path value="$PROJECT_DIR$/vendor/react/dns" />
+      <path value="$PROJECT_DIR$/vendor/web3p/rlp" />
+      <path value="$PROJECT_DIR$/vendor/web3p/ethereum-util" />
+      <path value="$PROJECT_DIR$/vendor/web3p/ethereum-tx" />
+      <path value="$PROJECT_DIR$/vendor/fenguoz/tron-php" />
+      <path value="$PROJECT_DIR$/vendor/ionux/phactor" />
+    </include_path>
+  </component>
+  <component name="PhpProjectSharedConfiguration" php_language_level="7" />
+</project>

+ 77 - 0
.idea/shrx.iml

@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/markbaker/complex" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/markbaker/matrix" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/mdanter/ecc" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/alipayrsa2/lotusphp_runtime" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/endroid/qr-code" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/php-enum" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ezyang/htmlpurifier" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/alipayrsa2/aop" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpoffice/phpspreadsheet" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpmailer/phpmailer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/fgrosse/phpasn1" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/kornrunner/keccak" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/kornrunner/secp256k1" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpseclib/phpseclib" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/iexbase/tron-api" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/maennchen/zipstream-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/monolog/monolog" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/options-resolver" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/psr-http-message-bridge" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/overtrue/pinyin" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/overtrue/wechat" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/overtrue/socialite" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/pimple/pimple" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/simplito/bigint-wrapper-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/simplito/bn-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/simple-cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/topthink/think-installer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/simplito/elliptic-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/topthink/think-captcha" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-message" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/mtdowling/cron-expression" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-factory" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sc0vu/web3.php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-client" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/karsonzhang/fastadmin-addons" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ratchet/pawl" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ratchet/rfc6455" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/web3p/web3.php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/evenement/evenement" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/fig/http-message-util" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/stream" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/event-loop" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/promise" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/promise-timer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/http" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/async" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/socket" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/react/dns" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/web3p/rlp" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/web3p/ethereum-util" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/web3p/ethereum-tx" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/fenguoz/tron-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ionux/phactor" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 205 - 0
application/admin/command/Test.php

@@ -0,0 +1,205 @@
+<?php
+
+namespace app\admin\command;
+
+use blockchain\TronService;
+use blockchain\Web3Service;
+use IEXBase\TronAPI\Provider\HttpProvider;
+use IEXBase\TronAPI\Tron;
+use think\console\Command;
+use think\console\Input;
+use think\console\input\Option;
+use think\console\Output;
+use think\Exception;
+use think\Log;
+use Tron\Address;
+
+class Test extends Command
+{
+    protected function configure()
+    {
+        $this->setName('test')
+            ->setDescription('测试');
+    }
+
+    protected function execute(Input $input, Output $output)
+    {
+
+    }
+
+
+    /**
+     * tron归集参考,遍历所有有余额的地址,处理归集操作,即可将余额归到一个地址
+     * @param array $money_info
+     * @param string $summary_address
+     * @param Address $gas_address
+     * @return bool
+     * @throws Exception
+     */
+    public function summary(array $money_info, string $summary_address, Address $gas_address): bool
+    {
+        //实例化TRON
+        $service = TronService::instance('usdt');
+        //实例化出款地址[有Usdt余额的用户钱包]
+        $address = new Address($money_info['address'], $money_info['privateKey'], $money_info['hexAddress']);
+        //获取代币余额
+        $balance = $service->tokenBalance($money_info['address']);
+        //USDT余额大于0,触发归集
+        if ($balance > 0) {
+            //查询地址中主币【GAS费余额】
+            $trx_balance = $service->balance($money_info['address']);
+            if ($trx_balance < 30) {
+                //如果主币小于30个,即gas费不够【BSC的gas费需要比较少,大约0.001个bnb就不少了,按照实际情况设置】
+                //计算要达到30个trx需要再转几个给用户地址
+                $trade_trx = ceil(30 - $trx_balance);
+                //处理手续费转账,从系统地址分配gas给用户
+                //查询系统地址的TRX余额
+                $gas_trx_balance = $service->balance($gas_address->address);
+                //系统地址TRX余额不足,退出处理
+                if ($gas_trx_balance < $trade_trx + 2) {
+                    Log::error('手续费账户余额不足');
+                    return false;
+                }
+                try {
+                    //执行转账
+                    $res = $service->transfer($gas_address, $address, $trade_trx);
+                    if (isset($res->txID)) {
+                        Log::error('转账TRX交易哈希:' . $res->txID);
+                        return true;
+                    } else {
+                        Log::error('转账TRX失败');
+                        return false;
+                    }
+                } catch (\Exception $e) {
+                    Log::error('转账TRX失败' . $e->getMessage());
+                    return false;
+                }
+            } else {
+                //账户内TRX充足,执行USDT转账交易
+                try {
+                    //将账户内的USDT余额转入归集指定地址
+                    $res = $service->tokenTransfer($address, new Address($summary_address), $balance);
+                    @file_put_contents('trasfer.txt', json_encode($res), FILE_APPEND);
+                    if ($res['status']) {
+                        Log::error('转账交易哈希:' . $res['data']->txID);
+                        return true;
+                    } else {
+                        Log::error('转账失败' . $res['msg']);
+                        return false;
+                    }
+                } catch (\Exception $e) {
+                    Log::error('转账失败' . $e->getMessage());
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * TRON方法示例
+     */
+    private function trx()
+    {
+        /**
+         * TRON实例化
+         */
+        $service = TronService::instance('usdt');
+        /**
+         * 创建地址
+         * @returns array ['私钥','地址','16进制地址']
+         */
+        var_dump($service->createAddress());
+        /**
+         * 获取主币余额
+         * @param string $address 要查询的钱包地址
+         */
+        var_dump($service->balance('TNUe3TpMjvM5svbQEEgunP91VtsimNSiZY'));
+        /**
+         * 获取代币余额
+         * @param string $address 要查询的钱包地址
+         */
+        var_dump($service->tokenBalance('TNUe3TpMjvM5svbQEEgunP91VtsimNSiZY'));
+
+        /**
+         * 获取钱包地址的代币转账记录
+         * @param string $address 要查询的钱包地址
+         * @param int $start_time 开始时间 13位时间戳
+         */
+        var_dump($service->getTransfer('TNUe3TpMjvM5svbQEEgunP91VtsimNSiZY', 0));
+
+        /**
+         * 实例化出账地址
+         */
+        $from = new Address('地址', '私钥', '16位地址');
+        /**
+         * 实例化收款地址
+         */
+        $to = new Address('地址');
+        /**
+         * 主币转账
+         * @param Address $from 出账地址
+         * @param Address $to 收款地址
+         * @param float $amount 转账数量
+         */
+        var_dump($service->transfer($from, $to, 1));
+        /**
+         * 代币转账
+         * @param Address $from 出账地址
+         * @param Address $to 收款地址
+         * @param float $amount 转账数量
+         */
+        var_dump($service->tokenTransfer($from, $to, 1));
+    }
+
+
+    /**
+     * BSC/ETH方法示例
+     */
+    private function web3()
+    {
+        /**
+         * 实例化
+         * @param string $chain 网络 可选bsc和eth
+         * @param string $contact 代币名,在config.php内配置
+         * @param string $private_key 私钥,可选,默认实例化config中配置了私钥的地址
+         */
+        $service = Web3Service::instance('bsc', 'usdt', '');
+        /**
+         * 创建地址
+         * @return array ['地址','私钥']
+         */
+        var_dump($service->createAddress());
+        /**
+         * 获取实例化的代币余额
+         * @param string $address 要查询的钱包地址
+         */
+        var_dump($service->getTokenBalance('0xE32f0a35F11Fd40B1949552C9Bdcfa6D080527C5'));
+        /**
+         * 获取主币余额
+         * @param string $address 要查询的钱包地址
+         */
+        var_dump($service->getBalance('0xB52cc871c8f15579d9C10fEF36fF95E9dA3fDe69'));
+        /**
+         * 获取最近的转账记录 不要隔太久,最多支持10000个区块,每个区块大约3秒
+         * @param array $from 要查询的来源地址
+         * @param array $to 要查询的去向地址
+         * @param int $last_time 上次查询的时间
+         */
+        var_dump($service->getLastTransfer([], ['0xE32f0a35F11Fd40B1949552C9Bdcfa6D080527C5']));
+        /**
+         * 代币转账
+         * 从实例化的地址转出实例化的代币到指定地址
+         * @param string $to 接受地址
+         * @param int $amount 转账数量
+         */
+        var_dump($service->transferToken('0xE32f0a35F11Fd40B1949552C9Bdcfa6D080527C5', 1000));
+        /**
+         * 主币转账
+         * 从实例化的地址转出主币到指定地址
+         * @param string $to 接受地址
+         * @param int $amount 转账数量
+         */
+        var_dump($service->transfer('0xE32f0a35F11Fd40B1949552C9Bdcfa6D080527C5', 0.001));
+    }
+}

+ 1 - 0
application/command.php

@@ -17,4 +17,5 @@ return [
     'app\admin\command\Min',
     'app\admin\command\Addon',
     'app\admin\command\Api',
+    'app\admin\command\Test',
 ];

+ 75 - 12
application/common.php

@@ -2,12 +2,14 @@
 
 // 公共助手函数
 
+use think\Config;
+
 if (!function_exists('__')) {
 
     /**
      * 获取语言变量值
      * @param string $name 语言变量名
-     * @param array  $vars 动态变量值
+     * @param array $vars 动态变量值
      * @param string $lang 语言
      * @return mixed
      */
@@ -29,7 +31,7 @@ if (!function_exists('format_bytes')) {
 
     /**
      * 将字节转换为可读文本
-     * @param int    $size      大小
+     * @param int $size 大小
      * @param string $delimiter 分隔符
      * @return string
      */
@@ -47,7 +49,7 @@ if (!function_exists('datetime')) {
 
     /**
      * 将时间戳转换为日期时间
-     * @param int    $time   时间戳
+     * @param int $time 时间戳
      * @param string $format 日期时间格式
      * @return string
      */
@@ -62,7 +64,7 @@ if (!function_exists('human_date')) {
 
     /**
      * 获取语义化时间
-     * @param int $time  时间
+     * @param int $time 时间
      * @param int $local 本地时间
      * @return string
      */
@@ -76,14 +78,14 @@ if (!function_exists('cdnurl')) {
 
     /**
      * 获取上传资源的CDN的地址
-     * @param string  $url    资源相对地址
+     * @param string $url 资源相对地址
      * @param boolean $domain 是否显示域名 或者直接传入域名
      * @return string
      */
     function cdnurl($url, $domain = false)
     {
         $regex = "/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i";
-        $url = preg_match($regex, $url) ? $url : \think\Config::get('upload.cdnurl') . $url;
+        $url = preg_match($regex, $url) ? $url : Config::get('upload.cdnurl') . $url;
         if ($domain && !preg_match($regex, $url)) {
             $domain = is_bool($domain) ? request()->domain() : $domain;
             $url = $domain . $url;
@@ -97,7 +99,7 @@ if (!function_exists('is_really_writable')) {
 
     /**
      * 判断文件或文件夹是否可写
-     * @param    string $file 文件或目录
+     * @param string $file 文件或目录
      * @return    bool
      */
     function is_really_writable($file)
@@ -126,8 +128,8 @@ if (!function_exists('rmdirs')) {
 
     /**
      * 删除文件夹
-     * @param string $dirname  目录
-     * @param bool   $withself 是否删除自身
+     * @param string $dirname 目录
+     * @param bool $withself 是否删除自身
      * @return boolean
      */
     function rmdirs($dirname, $withself = true)
@@ -156,7 +158,7 @@ if (!function_exists('copydirs')) {
     /**
      * 复制文件夹
      * @param string $source 源文件夹
-     * @param string $dest   目标文件夹
+     * @param string $dest 目标文件夹
      */
     function copydirs($source, $dest)
     {
@@ -192,7 +194,7 @@ if (!function_exists('addtion')) {
 
     /**
      * 附加关联字段数据
-     * @param array $items  数据列表
+     * @param array $items 数据列表
      * @param mixed $fields 渲染的来源字段
      * @return array
      */
@@ -264,7 +266,7 @@ if (!function_exists('var_export_short')) {
 
     /**
      * 返回打印数组结构
-     * @param string $var    数组
+     * @param string $var 数组
      * @param string $indent 缩进字符
      * @return string
      */
@@ -362,3 +364,64 @@ if (!function_exists('hsv2rgb')) {
         ];
     }
 }
+
+
+if (!function_exists('get_token_info')) {
+    /**
+     * 获取token信息
+     * @param $token
+     * @param string $field
+     * @param mixed $default
+     * @param string $chain
+     * @return mixed|string
+     */
+    function get_token_info(string $chain, $token, string $field = '', $default = '')
+    {
+        $token = strtolower($token);
+        $info = Config::get('blockchain.' . $chain);
+        if ($field) return $info['tokens'][$token][$field] ?? $default;
+        return $info['tokens'][$token] ?? $default;
+    }
+}
+
+if (!function_exists('do_request')) {
+    /**
+     * CURL 请求接口
+     * @param string $url 请求地址
+     * @param array $data 请求参数
+     * @param array $header 请求头
+     * @param bool $post true:post请求 false:get请求
+     * @param bool $json post请求时 请求数据打包方式是否为json
+     * @param int $format 数据打包为json格式时打包的格式值 来自json_encode
+     * @param bool $form post请求时 请求数据是否为表单 同时为false时为http提交 优先级高于json
+     * @return bool|false|string
+     */
+    function do_request($url, $data, $header = null, $post = true, $json = false, $format = 0, $form = false)
+    {
+        $curl = curl_init();
+        curl_setopt($curl, CURLOPT_URL, $url);
+        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
+        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+        if ($post) {
+            curl_setopt($curl, CURLOPT_POST, 1);
+            if (!$json && !$form) {
+                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
+            } else if ($json && !$form) {
+                curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data, $format));
+            } else {
+                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
+            }
+        }
+        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+        if ($header) {
+            curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
+            curl_setopt($curl, CURLOPT_HEADER, 0);
+        }
+        $result = curl_exec($curl);
+        if (curl_errno($curl)) {
+            return json_encode(['status' => curl_errno($curl), 'msg' => '请求失败']);
+        }
+        curl_close($curl);
+        return $result;
+    }
+}

+ 146 - 106
application/config.php

@@ -16,169 +16,169 @@ return [
     // | 应用设置
     // +----------------------------------------------------------------------
     // 应用命名空间
-    'app_namespace'          => 'app',
+    'app_namespace' => 'app',
     // 应用调试模式
-    'app_debug'              => Env::get('app.debug', true),
+    'app_debug' => Env::get('app.debug', true),
     // 应用Trace
-    'app_trace'              => Env::get('app.trace', false),
+    'app_trace' => Env::get('app.trace', false),
     // 应用模式状态
-    'app_status'             => '',
+    'app_status' => '',
     // 是否支持多模块
-    'app_multi_module'       => true,
+    'app_multi_module' => true,
     // 入口自动绑定模块
-    'auto_bind_module'       => false,
+    'auto_bind_module' => false,
     // 注册的根命名空间
-    'root_namespace'         => [],
+    'root_namespace' => [],
     // 扩展函数文件
-    'extra_file_list'        => [THINK_PATH . 'helper' . EXT],
+    'extra_file_list' => [THINK_PATH . 'helper' . EXT],
     // 默认输出类型
-    'default_return_type'    => 'html',
+    'default_return_type' => 'html',
     // 默认AJAX 数据返回格式,可选json xml ...
-    'default_ajax_return'    => 'json',
+    'default_ajax_return' => 'json',
     // 默认JSONP格式返回的处理方法
-    'default_jsonp_handler'  => 'jsonpReturn',
+    'default_jsonp_handler' => 'jsonpReturn',
     // 默认JSONP处理方法
-    'var_jsonp_handler'      => 'callback',
+    'var_jsonp_handler' => 'callback',
     // 默认时区
-    'default_timezone'       => 'PRC',
+    'default_timezone' => 'PRC',
     // 是否开启多语言
-    'lang_switch_on'         => true,
+    'lang_switch_on' => true,
     // 默认全局过滤方法 用逗号分隔多个
-    'default_filter'         => '',
+    'default_filter' => '',
     // 默认语言
-    'default_lang'           => 'zh-cn',
+    'default_lang' => 'zh-cn',
     // 应用类库后缀
-    'class_suffix'           => false,
+    'class_suffix' => false,
     // 控制器类后缀
-    'controller_suffix'      => false,
+    'controller_suffix' => false,
     // +----------------------------------------------------------------------
     // | 模块设置
     // +----------------------------------------------------------------------
     // 默认模块名
-    'default_module'         => 'index',
+    'default_module' => 'index',
     // 禁止访问模块
-    'deny_module_list'       => ['common', 'admin'],
+    'deny_module_list' => ['common', 'admin'],
     // 默认控制器名
-    'default_controller'     => 'Index',
+    'default_controller' => 'Index',
     // 默认操作名
-    'default_action'         => 'index',
+    'default_action' => 'index',
     // 默认验证器
-    'default_validate'       => '',
+    'default_validate' => '',
     // 默认的空控制器名
-    'empty_controller'       => 'Error',
+    'empty_controller' => 'Error',
     // 操作方法后缀
-    'action_suffix'          => '',
+    'action_suffix' => '',
     // 自动搜索控制器
     'controller_auto_search' => true,
     // +----------------------------------------------------------------------
     // | URL设置
     // +----------------------------------------------------------------------
     // PATHINFO变量名 用于兼容模式
-    'var_pathinfo'           => 's',
+    'var_pathinfo' => 's',
     // 兼容PATH_INFO获取
-    'pathinfo_fetch'         => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
+    'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
     // pathinfo分隔符
-    'pathinfo_depr'          => '/',
+    'pathinfo_depr' => '/',
     // URL伪静态后缀
-    'url_html_suffix'        => 'html',
+    'url_html_suffix' => 'html',
     // URL普通方式参数 用于自动生成
-    'url_common_param'       => false,
+    'url_common_param' => false,
     // URL参数方式 0 按名称成对解析 1 按顺序解析
-    'url_param_type'         => 0,
+    'url_param_type' => 0,
     // 是否开启路由
-    'url_route_on'           => true,
+    'url_route_on' => true,
     // 路由使用完整匹配
-    'route_complete_match'   => false,
+    'route_complete_match' => false,
     // 路由配置文件(支持配置多个)
-    'route_config_file'      => ['route'],
+    'route_config_file' => ['route'],
     // 是否强制使用路由
-    'url_route_must'         => false,
+    'url_route_must' => false,
     // 域名部署
-    'url_domain_deploy'      => false,
+    'url_domain_deploy' => false,
     // 域名根,如thinkphp.cn
-    'url_domain_root'        => '',
+    'url_domain_root' => '',
     // 是否自动转换URL中的控制器和操作名
-    'url_convert'            => true,
+    'url_convert' => true,
     // 默认的访问控制器层
-    'url_controller_layer'   => 'controller',
+    'url_controller_layer' => 'controller',
     // 表单请求类型伪装变量
-    'var_method'             => '_method',
+    'var_method' => '_method',
     // 表单ajax伪装变量
-    'var_ajax'               => '_ajax',
+    'var_ajax' => '_ajax',
     // 表单pjax伪装变量
-    'var_pjax'               => '_pjax',
+    'var_pjax' => '_pjax',
     // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
-    'request_cache'          => false,
+    'request_cache' => false,
     // 请求缓存有效期
-    'request_cache_expire'   => null,
+    'request_cache_expire' => null,
     // +----------------------------------------------------------------------
     // | 模板设置
     // +----------------------------------------------------------------------
-    'template'               => [
+    'template' => [
         // 模板引擎类型 支持 php think 支持扩展
-        'type'         => 'Think',
+        'type' => 'Think',
         // 模板路径
-        'view_path'    => '',
+        'view_path' => '',
         // 模板后缀
-        'view_suffix'  => 'html',
+        'view_suffix' => 'html',
         // 模板文件名分隔符
-        'view_depr'    => DS,
+        'view_depr' => DS,
         // 模板引擎普通标签开始标记
-        'tpl_begin'    => '{',
+        'tpl_begin' => '{',
         // 模板引擎普通标签结束标记
-        'tpl_end'      => '}',
+        'tpl_end' => '}',
         // 标签库标签开始标记
         'taglib_begin' => '{',
         // 标签库标签结束标记
-        'taglib_end'   => '}',
-        'tpl_cache'    => true,
+        'taglib_end' => '}',
+        'tpl_cache' => true,
     ],
     // 视图输出字符串内容替换,留空则会自动进行计算
-    'view_replace_str'       => [
+    'view_replace_str' => [
         '__PUBLIC__' => '',
-        '__ROOT__'   => '',
-        '__CDN__'    => '',
+        '__ROOT__' => '',
+        '__CDN__' => '',
     ],
     // 默认跳转页面对应的模板文件
-    'dispatch_success_tmpl'  => APP_PATH . 'common' . DS . 'view' . DS . 'tpl' . DS . 'dispatch_jump.tpl',
-    'dispatch_error_tmpl'    => APP_PATH . 'common' . DS . 'view' . DS . 'tpl' . DS . 'dispatch_jump.tpl',
+    'dispatch_success_tmpl' => APP_PATH . 'common' . DS . 'view' . DS . 'tpl' . DS . 'dispatch_jump.tpl',
+    'dispatch_error_tmpl' => APP_PATH . 'common' . DS . 'view' . DS . 'tpl' . DS . 'dispatch_jump.tpl',
     // +----------------------------------------------------------------------
     // | 异常及错误设置
     // +----------------------------------------------------------------------
     // 异常页面的模板文件
-    'exception_tmpl'         => APP_PATH . 'common' . DS . 'view' . DS . 'tpl' . DS . 'think_exception.tpl',
+    'exception_tmpl' => APP_PATH . 'common' . DS . 'view' . DS . 'tpl' . DS . 'think_exception.tpl',
     // 错误显示信息,非调试模式有效
-    'error_message'          => '你所浏览的页面暂时无法访问',
+    'error_message' => '你所浏览的页面暂时无法访问',
     // 显示错误信息
-    'show_error_msg'         => false,
+    'show_error_msg' => false,
     // 异常处理handle类 留空使用 \think\exception\Handle
-    'exception_handle'       => '',
+    'exception_handle' => '',
     // +----------------------------------------------------------------------
     // | 日志设置
     // +----------------------------------------------------------------------
-    'log'                    => [
+    'log' => [
         // 日志记录方式,内置 file socket 支持扩展
-        'type'  => 'File',
+        'type' => 'File',
         // 日志保存目录
-        'path'  => LOG_PATH,
+        'path' => LOG_PATH,
         // 日志记录级别
         'level' => [],
     ],
     // +----------------------------------------------------------------------
     // | Trace设置 开启 app_trace 后 有效
     // +----------------------------------------------------------------------
-    'trace'                  => [
+    'trace' => [
         // 内置Html Console 支持扩展
         'type' => 'Html',
     ],
     // +----------------------------------------------------------------------
     // | 缓存设置
     // +----------------------------------------------------------------------
-    'cache'                  => [
+    'cache' => [
         // 驱动方式
-        'type'   => 'File',
+        'type' => 'File',
         // 缓存保存目录
-        'path'   => CACHE_PATH,
+        'path' => CACHE_PATH,
         // 缓存前缀
         'prefix' => '',
         // 缓存有效期 0表示永久缓存
@@ -187,97 +187,137 @@ return [
     // +----------------------------------------------------------------------
     // | 会话设置
     // +----------------------------------------------------------------------
-    'session'                => [
-        'id'             => '',
+    'session' => [
+        'id' => '',
         // SESSION_ID的提交变量,解决flash上传跨域
         'var_session_id' => '',
         // SESSION 前缀
-        'prefix'         => 'think',
+        'prefix' => 'think',
         // 驱动方式 支持redis memcache memcached
-        'type'           => '',
+        'type' => '',
         // 是否自动开启 SESSION
-        'auto_start'     => true,
+        'auto_start' => true,
     ],
     // +----------------------------------------------------------------------
     // | Cookie设置
     // +----------------------------------------------------------------------
-    'cookie'                 => [
+    'cookie' => [
         // cookie 名称前缀
-        'prefix'    => '',
+        'prefix' => '',
         // cookie 保存时间
-        'expire'    => 0,
+        'expire' => 0,
         // cookie 保存路径
-        'path'      => '/',
+        'path' => '/',
         // cookie 有效域名
-        'domain'    => '',
+        'domain' => '',
         //  cookie 启用安全传输
-        'secure'    => false,
+        'secure' => false,
         // httponly设置
-        'httponly'  => '',
+        'httponly' => '',
         // 是否使用 setcookie
         'setcookie' => true,
     ],
     //分页配置
-    'paginate'               => [
-        'type'      => 'bootstrap',
-        'var_page'  => 'page',
+    'paginate' => [
+        'type' => 'bootstrap',
+        'var_page' => 'page',
         'list_rows' => 15,
     ],
     //验证码配置
-    'captcha'                => [
+    'captcha' => [
         // 验证码字符集合
-        'codeSet'  => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
+        'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
         // 验证码字体大小(px)
         'fontSize' => 18,
         // 是否画混淆曲线
         'useCurve' => false,
         //使用中文验证码
-        'useZh'    => false,
+        'useZh' => false,
         // 验证码图片高度
-        'imageH'   => 40,
+        'imageH' => 40,
         // 验证码图片宽度
-        'imageW'   => 130,
+        'imageW' => 130,
         // 验证码位数
-        'length'   => 4,
+        'length' => 4,
         // 验证成功后是否重置
-        'reset'    => true
+        'reset' => true
     ],
     // +----------------------------------------------------------------------
     // | Token设置
     // +----------------------------------------------------------------------
-    'token'                  => [
+    'token' => [
         // 驱动方式
-        'type'     => 'Mysql',
+        'type' => 'Mysql',
         // 缓存前缀
-        'key'      => 'i3d6o32wo8fvs1fvdpwens',
+        'key' => 'i3d6o32wo8fvs1fvdpwens',
         // 加密方式
         'hashalgo' => 'ripemd160',
         // 缓存有效期 0表示永久缓存
-        'expire'   => 0,
+        'expire' => 0,
     ],
     //FastAdmin配置
-    'fastadmin'              => [
+    'fastadmin' => [
         //是否开启前台会员中心
-        'usercenter'            => true,
+        'usercenter' => true,
         //会员注册验证码类型email/mobile/wechat/text/false
         'user_register_captcha' => 'text',
         //登录验证码
-        'login_captcha'         => false,
+        'login_captcha' => false,
         //登录失败超过10次则1天后重试
-        'login_failure_retry'   => false,
+        'login_failure_retry' => false,
         //是否同一账号同一时间只能在一个地方登录
-        'login_unique'          => false,
+        'login_unique' => false,
         //是否开启IP变动检测
-        'loginip_check'         => true,
+        'loginip_check' => true,
         //登录页默认背景图
-        'login_background'      => "/assets/img/loginbg.jpg",
+        'login_background' => "/assets/img/loginbg.jpg",
         //是否启用多级菜单导航
-        'multiplenav'           => false,
+        'multiplenav' => false,
         //自动检测更新
-        'checkupdate'           => false,
+        'checkupdate' => false,
         //版本号
-        'version'               => '1.0.0.20200506_beta',
+        'version' => '1.0.0.20200506_beta',
         //API接口地址
-        'api_url'               => 'https://api.fastadmin.net',
+        'api_url' => 'https://api.fastadmin.net',
+    ],
+    'blockchain' => [
+        'bsc' => [
+            'node' => 'empty-quiet-sunset.bsc.quiknode.pro/69b72a1ee6e3efe4ad03d31b04a9a1b0c8a6e6d3',
+            'blockTimeArea' => 0.5,
+            'tokens' => [
+                'usdt' => [
+//                    'address' => '0x55d398326f99059fF775485246999027B3197955',//USDT合约地址
+                    'address' => '0x8f5f8daC38461E5b1A6b230D30433f8A593CCD57',//USDT测试合约地址
+                    'decimal' => 18,
+//                    'decimal' => 18,
+                    'private_key' => '0294f6a2b958585b6bf07b44ceeb1c0eb18796e64e2ecc107c0d4df8fcc0a646',
+                    'type' => 'bep20',
+                ],
+            ],
+        ],
+        'eth' => [
+            'node' => 'mainnet.infura.io',
+            'blockTimeArea' => 10,
+            'tokens' => [
+                'usdt' => [
+//                    'address' => '0x55d398326f99059fF775485246999027B3197955',//USDT合约地址
+                    'address' => '0x8f5f8daC38461E5b1A6b230D30433f8A593CCD57',//USDT测试合约地址
+                    'decimal' => 18,
+//                    'decimal' => 18,
+                    'private_key' => '0294f6a2b958585b6bf07b44ceeb1c0eb18796e64e2ecc107c0d4df8fcc0a646',
+                    'type' => 'bep20',
+                ],
+            ],
+        ],
+        'trc' => [
+            'node' => 'https://api.trongrid.io',
+            'tokens' => [
+                'usdt' => [
+                    'address' => 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
+                    'decimal' => 6,
+                    'private_key' => '',
+                ]
+            ],
+        ],
     ],
 ];

+ 7 - 1
composer.json

@@ -26,7 +26,13 @@
         "overtrue/pinyin": "~3.0",
         "phpoffice/phpspreadsheet": "^1.2",
       "ext-curl": "*",
-        "iexbase/tron-api": "^3.0"
+        "iexbase/tron-api": "^3.0",
+        "web3p/web3.php": "^0.3.2",
+      "ext-gmp": "*",
+        "web3p/ethereum-tx": "^0.4.3",
+      "ext-bcmath": "*",
+        "fenguoz/tron-php": "^1.3",
+      "ext-json": "*"
     },
     "config": {
         "preferred-install": "dist",

Разница между файлами не показана из-за своего большого размера
+ 1134 - 78
composer.lock


+ 173 - 0
extend/blockchain/TronService.php

@@ -0,0 +1,173 @@
+<?php
+
+
+namespace blockchain;
+
+
+use GuzzleHttp\Client;
+use think\Config;
+use Tron\Address;
+use Tron\Api;
+use Tron\Exceptions\TronErrorException;
+use Tron\TRC20;
+use Tron\TRX;
+
+class TronService
+{
+
+    const API_URI = 'https://api.trongrid.io';
+    public static $trxWallet;
+    public static $address;
+    public static $decimal;
+    public static $api;
+
+    public function __construct(string $address, int $decimal)
+    {
+        if (!$address) {
+            self::$trxWallet = null;
+        }
+        $config = Config::get('blockchain.trc');
+        $uri = $config['node'] ?? self::API_URI;
+        self::$api = new Api(new Client(['base_uri' => $uri]));
+        $config = [
+            'contract_address' => $address,// USDT TRC20
+            'decimals' => $decimal,
+        ];
+        self::$trxWallet = new TRC20(self::$api, $config);
+        self::$address = $address;
+        self::$decimal = $decimal;
+    }
+
+    /**
+     * @param string $money_type
+     * @return TronService
+     */
+    public static function instance(string $money_type): TronService
+    {
+        $config = Config::get('blockchain.trc');
+        $money_types = $config['tokens'];
+
+        $address = $money_types[$money_type]['address'] ?? "";
+        $decimal = $money_types[$money_type]['decimal'] ?? 0;
+
+        return new self($address, $decimal);
+    }
+
+    //TODO main
+
+    /**
+     * 生成地址
+     * @return array
+     */
+    public function createAddress(): array
+    {
+        if (!self::$trxWallet) {
+            return [
+                'privateKey' => '',
+                'address' => '',
+                'hexAddress' => ''
+            ];
+        }
+        try {
+            $address = self::$trxWallet->generateAddress();
+            return [
+                'privateKey' => $address->privateKey,
+                'address' => $address->address,
+                'hexAddress' => $address->hexAddress
+            ];
+        } catch (\Exception $e) {
+            return [
+                'privateKey' => '',
+                'address' => '',
+                'hexAddress' => ''
+            ];
+        }
+    }
+
+    /**
+     * 余额
+     * @param string $address
+     * @return float
+     */
+    public function tokenBalance(string $address): float
+    {
+        if (!self::$trxWallet) {
+            return 0;
+        }
+        try {
+            $balance = self::$trxWallet->balance(new Address($address));
+            return (float)$balance;
+        } catch (\Exception $e) {
+            return 0;
+        }
+    }
+
+
+    public function balance(string $address)
+    {
+        $address = new Address($address);
+        $trx = new TRX(self::$api);
+        return $trx->balance($address);
+    }
+
+
+    /**
+     * 交易
+     * @param Address $from
+     * @param Address $to
+     * @param float $amount
+     * @return array
+     */
+    public function transfer(Address $from, Address $to, float $amount): array
+    {
+        try {
+            $trx = new TRX(self::$api);
+            $transfer = $trx->transfer($from, $to, $amount);
+            return ['msg' => 'success', 'data' => $transfer, 'status' => true];
+        } catch (\Exception $e) {
+            return ['msg' => $e->getMessage(), 'status' => false, 'data' => $e->getTrace()];
+        }
+    }
+
+    /**
+     * 交易
+     * @param Address $from
+     * @param Address $to
+     * @param float $amount
+     * @return array
+     */
+    public function tokenTransfer(Address $from, Address $to, float $amount): array
+    {
+        if (!self::$trxWallet) {
+            return ['msg' => '代币不支持转账', 'status' => false];
+        }
+        try {
+            $transfer = self::$trxWallet->transfer($from, $to, $amount);
+            return ['msg' => 'success', 'data' => $transfer, 'status' => true];
+        } catch (\Exception $e) {
+            return ['msg' => $e->getMessage(), 'status' => false, 'data' => $e->getTrace()];
+        }
+    }
+
+    /**
+     * 获取交易
+     * @param $address
+     * @param $start_time
+     * @return array
+     */
+    public function getTransfer($address, $start_time): array
+    {
+        $contract_address = self::$address;
+        try {
+            $uri = "https://api.trongrid.io/v1/accounts/{$address}/transactions/trc20";
+            return json_decode(do_request($uri, [
+                'min_timestamp' => $start_time,
+                'limit' => 200,
+                'contract_address' => $contract_address,
+                'order_by' => 'block_timestamp,asc'
+            ], null, false), true);
+        } catch (\Exception $e) {
+            return ['msg' => $e->getMessage(), 'status' => false, 'data' => $e->getTrace()];
+        }
+    }
+}

+ 183 - 0
extend/blockchain/Web3Service.php

@@ -0,0 +1,183 @@
+<?php
+
+namespace blockchain;
+
+use BI\BigInteger;
+use blockchain\web3\Bep20;
+use blockchain\web3\Bep721;
+use blockchain\web3\Callback;
+use blockchain\web3\Credential;
+use blockchain\web3\Kit;
+use blockchain\web3\NodeClient;
+use think\Config;
+use think\Exception;
+use Web3p\EthereumUtil\Util;
+
+class Web3Service
+{
+
+    /** @var Bep20|Bep721 $token */
+    private static $token;
+
+    private static $decimal;
+
+    private static $address;
+
+    private static $kit;
+
+    private static $blockTimeArea;
+
+
+    public function __construct($chain, $contact, $decimal, $type, $private_key)
+    {
+        $node = NodeClient::create($chain, 'mainNet');
+        $credential = Credential::fromKey($private_key);
+        self::$kit = new Kit($node, $credential);
+        self::$address = $credential->getAddress();
+        self::$token = self::$kit->$type($contact);
+        self::$decimal = $decimal;
+        self::$blockTimeArea = Config::get('blockchain.' . $chain)['blockTimeArea'] ?? 1;
+    }
+
+
+    /**
+     * @param $token
+     * @return Web3Service
+     * @throws Exception
+     */
+    public static function instance($chain, $token, $private_key = ''): Web3Service
+    {
+        if ($chain != 'bsc' && $chain != 'eth') {
+            throw new Exception('暂不支持该链');
+        }
+        if (!get_token_info($chain, $token, 'address')) {
+            throw new Exception('未定义Token');
+        }
+        return new self($chain, get_token_info($chain, $token, 'address'), get_token_info($chain, $token, 'decimal'), get_token_info($chain, $token, 'type'), $private_key ?: get_token_info($chain, $token, 'private_key'));
+    }
+
+    public function createAddress()
+    {
+        $address = Credential::create();
+        return [
+            'address' => $address->getAddress(),
+            'private_key' => $address->getPrivateKey()
+        ];
+    }
+
+    /**
+     * 签名转地址
+     * @param $str
+     * @param $sign
+     * @return string
+     * @throws Exception
+     */
+    public function signToAddress($str, $sign)
+    {
+        $util = new Util();
+        if (strlen($sign) != 132) {
+            throw new Exception('签名格式错误,类型:001');
+        }
+        if (!$util->isHex($sign)) {
+            throw new Exception('签名格式错误,类型:002');
+        }
+
+        $sign_str = $util->stripZero($sign);
+        $r = substr($sign_str, 0, 64);
+        $s = substr($sign_str, 64, 64);
+        $v = substr($sign_str, 128, 2);
+
+        $message = $util->hashPersonalMessage($str);
+
+        $public_key = $util->recoverPublicKey($message, $r, $s, hexdec($v) - 27);
+
+        return strtolower($util->publicKeyToAddress($public_key));
+    }
+
+    /**
+     * 获取地址
+     * @return string
+     */
+    public function getAddress()
+    {
+        return self::$address;
+    }
+
+    public function getBalance($address)
+    {
+        return bcdiv(self::$kit->balanceOf($address)->toString(), bcpow(10, 18), 18);
+    }
+
+    public function getTokenBalance($address)
+    {
+        return bcdiv(self::$token->balanceOf($address)->toString(), bcpow(10, self::$decimal), self::$decimal);
+    }
+
+    public function getLastTransfer($from = [], $to = [], $last_time = 0)
+    {
+        if ($last_time <= 0) $last_time = time() - 5000;
+        $time_area = bcsub(time(), $last_time);
+        $num = bcdiv($time_area, self::$blockTimeArea, 0);
+        if ($num <= 0) $num = 0;
+        if ($num > 10000) $num = 10000;
+        return self::$token->getTransferEvents($from, $to, $num ? bcsub(self::$token->getBlockNumber(), $num) : 'latest');
+    }
+
+    public function getBlockTransfer($block, $transferHash)
+    {
+        $res = self::$token->getTransferEvents([], [], $block, $block);
+        $ress = [];
+        foreach ($res as $v) {
+            if ($v->transactionHash == $transferHash) {
+                $ress[] = $v;
+            }
+        }
+        return $ress;
+    }
+
+    public function getTransferInfo($tx_hash)
+    {
+        return self::$token->getTransactionReceipt($tx_hash);
+    }
+
+    public function transferToken($to, $amount)
+    {
+        return self::$token->transfer($to, bcmul($amount, bcpow(10, self::$decimal)));
+    }
+
+    public function transfer($to, $amount)
+    {
+        $num = bcmul($amount, bcpow(10, 18));
+        $num = '0x' . (new BigInteger($num))->toHex();
+        return self::$kit->transfer($to, $num);
+    }
+
+    public function getBNBTransferInfo($tx_hash)
+    {
+        return self::$token->getTransactionReceipt($tx_hash);
+    }
+
+    public function estimateTransferGas($to, $amount)
+    {
+        $cb = new Callback();
+        self::$token->estimateGas("transfer", self::$address, $to, bcmul($amount, bcpow(10, self::$decimal)), $cb);
+        return $cb->result->toString();
+    }
+
+    public function getData($name, ...$args)
+    {
+        $data = self::$token->getData($name, ...$args);
+        $tx = [
+            'data' => '0x' . $data,
+            'to' => self::$token->getToAddress()
+        ];
+        return $tx;
+    }
+
+    public function totalSupply()
+    {
+        $data = self::$token->totalSupply();
+        $value = $data->toString();
+        return bcdiv($value, bcpow(10, self::$decimal), self::$decimal);
+    }
+}

+ 42 - 0
extend/blockchain/web3/Bep20.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace blockchain\web3;
+
+
+define('ABI_BEP20', file_get_contents(APP_PATH . '/../extend/blockchain/web3/json/bep20.json'));
+
+define('EVENTSIG_TRANSFER', '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef');
+
+class Bep20 extends SmartContract
+{
+    function __construct($client, $credential, $address)
+    {
+        parent::__construct($client, $credential, ABI_BEP20);
+        $this->at($address);
+    }
+
+    function getTransferEvents($from = [], $to = [], $fromBlock = 'latest', $toBlock = 'latest')
+    {
+        $toTopic = function ($addr) {
+            $addr = preg_replace('/^0x/', '', $addr);
+            return '0x' . str_pad($addr, 64, '0', STR_PAD_LEFT);
+        };
+        $from = array_map($toTopic, $from);
+        $to = array_map($toTopic, $to);
+        return $this->queryEvents([EVENTSIG_TRANSFER, $from, $to], $fromBlock, $toBlock);
+    }
+
+    function getBlockNumber()
+    {
+        $cb = new Callback();
+        $this->eth->blockNumber($cb);
+        return $cb->result->toString();
+    }
+
+    function getTransactionReceipt($tx_hash)
+    {
+        $cb = new Callback();
+        $this->eth->getTransactionReceipt($tx_hash, $cb);
+        return $cb->result;
+    }
+}

+ 40 - 0
extend/blockchain/web3/Bep721.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace blockchain\web3;
+
+
+define('ABI_BEP721', file_get_contents('bep721.json'));
+
+class Bep721 extends SmartContract
+{
+    function __construct($client, $credential, $address)
+    {
+        parent::__construct($client, $credential, ABI_BEP721);
+        $this->at($address);
+    }
+
+    function getTransferEvents($from = [], $to = [], $fromBlock = 'latest', $toBlock = 'latest')
+    {
+        $toTopic = function ($addr) {
+            $addr = preg_replace('/^0x/', '', $addr);
+            return '0x' . str_pad($addr, 64, '0', STR_PAD_LEFT);
+        };
+        $from = array_map($toTopic, $from);
+        $to = array_map($toTopic, $to);
+        return $this->queryEvents([EVENTSIG_TRANSFER, $from, $to], $fromBlock, $toBlock);
+    }
+
+    function getBlockNumber()
+    {
+        $cb = new Callback();
+        $this->eth->blockNumber($cb);
+        return $cb->result->toString();
+    }
+
+    function getTransactionReceipt($tx_hash)
+    {
+        $cb = new Callback();
+        $this->eth->getTransactionReceipt($tx_hash, $cb);
+        return $cb->result;
+    }
+}

+ 16 - 0
extend/blockchain/web3/Callback.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace blockchain\web3;
+
+class Callback
+{
+    public $result;
+
+    function __invoke($error, $result)
+    {
+        //$this->error = $error;
+        if ($error) throw $error;
+        $this->result = $result;
+    }
+}
+

+ 56 - 0
extend/blockchain/web3/Credential.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace blockchain\web3;
+
+use Elliptic\EC;
+use kornrunner\Keccak;
+use Web3p\EthereumTx\Transaction;
+
+class Credential
+{
+    private $keyPair;
+
+    public function __construct($keyPair)
+    {
+        $this->keyPair = $keyPair;
+    }
+
+    public function getPublicKey()
+    {
+        return $this->keyPair->getPublic()->encode('hex');
+    }
+
+    public function getPrivateKey()
+    {
+        return $this->keyPair->getPrivate()->toString(16, 2);
+    }
+
+    public function getAddress()
+    {
+        $pubkey = $this->getPublicKey();
+        return "0x" . substr(Keccak::hash(substr(hex2bin($pubkey), 1), 256), 24);
+    }
+
+    public function signTransaction($raw)
+    {
+        $txreq = new Transaction($raw);
+        $privateKey = $this->getPrivateKey();
+        $signed = '0x' . $txreq->sign($privateKey);
+        return $signed;
+    }
+
+    public static function create()
+    {
+        $ec = new EC('secp256k1');
+        $keyPair = $ec->genKeyPair();
+        return new self($keyPair);
+    }
+
+    public static function fromKey($privateKey)
+    {
+        $ec = new EC('secp256k1');
+        $keyPair = $ec->keyFromPrivate($privateKey);
+        return new self($keyPair);
+    }
+
+}

+ 68 - 0
extend/blockchain/web3/Kit.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace blockchain\web3;
+
+use Exception;
+
+class Kit
+{
+    protected $client;
+    protected $credential;
+    protected $transactor;
+
+    function __construct($client, $credential)
+    {
+        $this->client = $client;
+        $this->credential = $credential;
+
+        $this->transactor = new Transactor($client, $credential);
+    }
+
+    function getSender()
+    {
+        return $this->credential->getAddress();
+    }
+
+    function balanceOf($addr)
+    {
+        return $this->client->getBalance($addr);
+    }
+
+    function transfer($to, $value)
+    {
+        $tx = [
+            'to' => $to,
+            'value' => $value
+        ];
+        return $this->transactor->transact($tx);
+    }
+
+    //abi, bytecode, args...
+    function deployContract()
+    {
+        $args = func_get_args();
+        if (count($args) < 2) {
+            throw new Exception('no enough deploy parameters');
+        }
+        $abi = array_shift($args);
+        $bytecode = array_shift($args);
+        $contract = new SmartContract($this->client, $this->credential, $abi);
+        $contract->bytecode($bytecode);
+        return $contract->instantiate(...$args);
+    }
+
+    function waitForConfirmation($txid, $timeout = 300)
+    {
+        return $this->client->waitForConfirmation($txid, $timeout);
+    }
+
+    function bep20($addr)
+    {
+        return new Bep20($this->client, $this->credential, $addr);
+    }
+
+    function bep721($addr)
+    {
+        return new Bep721($this->client, $this->credential, $addr);
+    }
+}

+ 89 - 0
extend/blockchain/web3/NodeClient.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace blockchain\web3;
+
+use Exception;
+use blockchain\web3\src\Providers\HttpProvider;
+use blockchain\web3\src\RequestManagers\HttpRequestManager;
+use blockchain\web3\src\Web3;
+use think\Cache;
+use think\Config;
+
+class NodeClient extends Web3
+{
+    const Main_Net = 'bsc-dataseed.binance.org';
+    const Test_Net = 'https://data-seed-prebsc-1-s1.binance.org:8545/';
+
+    function __construct($url)
+    {
+        $provider = new HttpProvider(
+            new HttpRequestManager($url, 300) //timeout
+        );
+        parent::__construct($provider);
+    }
+
+    static function create($chain, $network)
+    {
+        if ($network === 'mainNet') return self::mainNet($chain);
+        if ($network === 'testNet') return self::testNet();
+        throw new Exception('unsupported network');
+    }
+
+    static function testNet()
+    {
+        return new self(self::Test_Net);
+    }
+
+    static function mainNet($chain)
+    {
+        $info = Config::get('blockchain.' . $chain);
+        return new self('https://' . ($info['node'] ?? self::Main_Net) . '/');
+    }
+
+    function getBalance($addr)
+    {
+        $cb = new Callback;
+        $this->getEth()->getBalance($addr, $cb);
+
+        return $cb->result;
+    }
+
+    function broadcast($rawtx)
+    {
+        $cb = new Callback;
+        $this->getEth()->sendRawTransaction($rawtx, $cb);
+
+        return $cb->result;
+    }
+
+    function getReceipt($txid)
+    {
+        $cb = new Callback;
+        $this->getEth()->getTransactionReceipt($txid, $cb);
+
+        return $cb->result;
+    }
+
+    function waitForConfirmation($txid, $timeout = 300)
+    {
+        $expire = time() + $timeout;
+        while (time() < $expire) {
+            try {
+                $receipt = $this->getReceipt($txid);
+                if (!is_null($receipt)) return $receipt;
+                sleep(2);
+            } catch (Exception $e) {
+            }
+        }
+        throw new Exception('tx not confirmed yet.');
+    }
+
+    function getBlockByNumber()
+    {
+        $cb = new Callback;
+        $number = hex(436);
+        $this->getEth()->getBlockByNumber($number, true, $cb);
+
+        return $cb->result;
+    }
+}

+ 185 - 0
extend/blockchain/web3/SmartContract.php

@@ -0,0 +1,185 @@
+<?php
+
+namespace blockchain\web3;
+
+use Exception;
+use blockchain\web3\src\Contract;
+use blockchain\web3\src\Utils;
+
+class SmartContract extends Contract
+{
+    protected $web3;
+
+    //context
+    protected $gasPrice;
+    protected $gasLimit;
+    protected $value;
+    protected $credential;
+
+    protected $txMethods = [];
+    protected $viewMethods = [];
+    protected $eventSignatures = [];
+
+    public function __construct($web3, $credential, $abi)
+    {
+        parent::__construct($web3->provider, $abi);
+        $this->web3 = $web3;
+        $this->credential = $credential;
+        foreach ($this->events as $name => $event) {
+            $sig = $this->ethabi->encodeEventSignature($event);
+            $this->eventSignatures[$sig] = $event;
+        }
+        foreach ($this->functions as $function) {
+            if ($function['stateMutability'] == 'view') {
+                $this->viewMethods[] = $function['name'];
+            } else {
+                $this->txMethods[] = $function['name'];
+            }
+        }
+    }
+
+    public function setGasPrice($price)
+    {
+        if (!$price) {
+            unset($this->gasPrice);
+        } else {
+            $this->gasPrice = $price;
+        }
+        return $this;
+    }
+
+    public function setGasLimit($limit)
+    {
+        if (!$limit) {
+            unset($this->gasLimit);
+        } else {
+            $this->gasLimit = $limit;
+        }
+        return $this;
+    }
+
+    public function setValue($value)
+    {
+        if (!$value) {
+            unset($this->value);
+        } else {
+            $this->value = $value;
+        }
+        return $this;
+    }
+
+    public function setCredential($credential)
+    {
+        $this->credential = $credential;
+        return $this;
+    }
+
+    protected function transact($tx): string
+    {
+        if (!isset($this->credential)) {
+            throw new \Exception('credential not set');
+        }
+        $transactor = new Transactor($this->web3, $this->credential);
+        $tx['to'] = $this->getToAddress();
+        return $transactor->transact($tx);
+    }
+
+    protected function isTxMethod($name)
+    {
+        return in_array($name, $this->txMethods);
+    }
+
+    protected function isViewMethod($name)
+    {
+        return in_array($name, $this->viewMethods);
+    }
+
+    public function instantiate()
+    {
+        $args = func_get_args();
+
+        $data = $this->getData(...$args);
+        $tx = [
+            'data' => '0x' . $data
+        ];
+        return $this->transact($tx);
+    }
+
+    public function __call($name, $args)
+    {
+        if ($this->isTxMethod($name)) {
+            $data = $this->getData($name, ...$args);
+            $tx = [
+                'data' => '0x' . $data
+            ];
+            return $this->transact($tx);
+        }
+        if ($this->isViewMethod($name)) {
+            $cb = new Callback;
+            $args[] = $cb;
+            $this->call($name, ...$args);
+            $values = array_values($cb->result);
+            return count($values) > 1 ? $values : $values[0];
+        }
+        throw new Exception('method not supported');
+    }
+
+    public function queryEvents($topics = [], $fromBlock = 'latest', $toBlock = 'latest')
+    {
+        if (is_numeric($fromBlock)) {
+            $fromBlock = Utils::toHex($fromBlock, true);
+        }
+        if (is_numeric($toBlock)) {
+            $toBlock = Utils::toHex($toBlock, true);
+        }
+        $filter = [
+            'fromBlock' => $fromBlock,
+            'toBlock' => $toBlock,
+            'address' => $this->getToAddress(),
+            'topics' => $topics
+        ];
+        $cb = new Callback;
+        $this->web3->eth->getLogs($filter, $cb);
+        $decodedEvents = [];
+        foreach ($cb->result as $log) {
+            if (!array_key_exists($log->topics[0], $this->eventSignatures)) {
+                $msg = sprintf("unknown event: %s, skip", $log->topics[0]);
+                echo $msg . PHP_EOL;
+                continue;
+            }
+
+            $eventAbi = $this->eventSignatures[$log->topics[0]];
+
+            $types = [];
+            $names = [];
+            for ($i = 0; $i < count($eventAbi['inputs']); $i++) {
+                $types[] = $eventAbi['inputs'][$i]['type'];
+                $names[] = $eventAbi['inputs'][$i]['name'];
+            }
+            $params = '';
+            for ($i = 1; $i < count($log->topics); $i++) {
+                $params = $params . Utils::stripZero($log->topics[$i]);
+            }
+            $params = $params . Utils::stripZero($log->data);
+            //echo $eventAbi['name'] . ' => ' . $params . PHP_EOL;
+            $decodedParams = $this->ethabi->decodeParameters($types, $params);
+
+            $decodedEvent = (object)[
+                'blockHash' => $log->blockHash,
+                'blockNumber' => $log->blockNumber,
+                'transactionHash' => $log->transactionHash,
+                'removed' => $log->removed,
+                'address' => $log->address,
+                'name' => $eventAbi['name'],
+                'params' => []
+            ];
+            for ($i = 0; $i < count($names); $i++) {
+                $decodedEvent->params[$names[$i]] = $decodedParams[$i];
+            }
+            $decodedEvents[] = $decodedEvent;
+        }
+
+        return $decodedEvents;
+    }
+
+}

+ 134 - 0
extend/blockchain/web3/Transactor.php

@@ -0,0 +1,134 @@
+<?php
+
+namespace blockchain\web3;
+
+use BI\BigInteger;
+use Exception;
+use blockchain\web3\src\Contract;
+use blockchain\web3\src\Utils;
+
+class Transactor
+{
+    protected $web3;
+
+    //context
+    protected $gasPrice;
+    protected $gasLimit;
+    protected $value;
+    protected $credential;
+
+    public function __construct($web3, $credential)
+    {
+        $this->web3 = $web3;
+        $this->credential = $credential;
+    }
+
+    public function setGasPrice($price = null)
+    {
+        $this->gasPrice = $price;
+        return $this;
+    }
+
+    public function setGasLimit($limit = null)
+    {
+        $this->gasLimit = $limit;
+        return $this;
+    }
+
+    public function setValue($value = null)
+    {
+        $this->value = $value;
+        return $this;
+    }
+
+    public function setCredential($credential)
+    {
+        $this->credential = $credential;
+        return $this;
+    }
+
+    protected function netVersion()
+    {
+        $cb = new Callback;
+        $this->web3->net->version($cb);
+        return $cb->result;
+    }
+
+    protected function getTransactionCount($address)
+    {
+        $cb = new Callback;
+        $this->web3->eth->getTransactionCount($address, 'pending', $cb);
+        return '0x' . $cb->result->toHex();
+    }
+
+    protected function estimateGasPrice()
+    {
+        $cb = new Callback;
+        $this->web3->eth->gasPrice($cb);
+        return '0x' . $cb->result->toHex();
+    }
+
+    protected function estimateGasUsage($tx)
+    {
+        //var_dump($tx);
+        $cb = new Callback;
+        $this->web3->eth->estimateGas($tx, $cb);
+        return '0x' . $cb->result->toHex();
+    }
+
+    public function transact($tx): string
+    {
+        if (!isset($this->credential)) {
+            throw new Exception('credential not set');
+        }
+
+        $from = $this->credential->getAddress();
+
+        $tx['from'] = $from;
+
+        if (!isset($tx['nonce'])) {
+            $tx['nonce'] = $this->getTransactionCount($from);
+        }
+
+        if (!isset($tx['chainId'])) {
+            $tx['chainId'] = $this->netVersion();
+        }
+
+        if (!isset($tx['value'])) {
+            if (isset($this->value)) {
+                $tx['value'] = $this->value;
+            } else {
+                $tx['value'] = '0x0';
+            }
+        }
+
+        if (!isset($tx['gasPrice'])) {
+            if (isset($this->gasPrice)) {
+                $tx['gasPrice'] = $this->gasPrice;
+            } else {
+                $tx['gasPrice'] = $this->estimateGasPrice();
+            }
+        }
+
+
+        if (!isset($tx['gasLimit'])) {
+            if (isset($this->gasLimit)) {
+                $tx['gasLimit'] = $this->gasLimit;
+            } else {
+                $originChainId = $tx['chainId'];
+                $tx['chainId'] = '0x' . (new BigInteger($originChainId))->toHex();
+                $tx['gasLimit'] = $this->estimateGasUsage($tx);
+                $tx['chainId'] = $originChainId;
+            }
+        }
+
+
+        $stx = $this->credential->signTransaction($tx);
+
+        $cb = new Callback;
+        $this->web3->eth->sendRawTransaction($stx, $cb);
+
+        return $cb->result;
+    }
+
+}

+ 14 - 0
extend/blockchain/web3/helper.php

@@ -0,0 +1,14 @@
+<?php
+//gmp extension required
+
+function hex($str, $prefix = true)
+{
+    $bn = gmp_init($str);
+    $ret = gmp_strval($bn, 16);
+    return $prefix ? '0x' . $ret : $ret;
+}
+
+function bn($n)
+{
+    return new phpseclib\Math\BigInteger($n);
+}

+ 257 - 0
extend/blockchain/web3/json/bep20.json

@@ -0,0 +1,257 @@
+[
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "owner",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "spender",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "value",
+        "type": "uint256"
+      }
+    ],
+    "name": "Approval",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "from",
+        "type": "address"
+      },
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "to",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "uint256",
+        "name": "value",
+        "type": "uint256"
+      }
+    ],
+    "name": "Transfer",
+    "type": "event"
+  },
+  {
+    "constant": true,
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "_owner",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "spender",
+        "type": "address"
+      }
+    ],
+    "name": "allowance",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "constant": false,
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "spender",
+        "type": "address"
+      },
+      {
+        "internalType": "uint256",
+        "name": "amount",
+        "type": "uint256"
+      }
+    ],
+    "name": "approve",
+    "outputs": [
+      {
+        "internalType": "bool",
+        "name": "",
+        "type": "bool"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "constant": true,
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "account",
+        "type": "address"
+      }
+    ],
+    "name": "balanceOf",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "constant": true,
+    "inputs": [],
+    "name": "decimals",
+    "outputs": [
+      {
+        "internalType": "uint8",
+        "name": "",
+        "type": "uint8"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "constant": true,
+    "inputs": [],
+    "name": "getOwner",
+    "outputs": [
+      {
+        "internalType": "address",
+        "name": "",
+        "type": "address"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "constant": true,
+    "inputs": [],
+    "name": "name",
+    "outputs": [
+      {
+        "internalType": "string",
+        "name": "",
+        "type": "string"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "constant": true,
+    "inputs": [],
+    "name": "symbol",
+    "outputs": [
+      {
+        "internalType": "string",
+        "name": "",
+        "type": "string"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "constant": true,
+    "inputs": [],
+    "name": "totalSupply",
+    "outputs": [
+      {
+        "internalType": "uint256",
+        "name": "",
+        "type": "uint256"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "constant": false,
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "recipient",
+        "type": "address"
+      },
+      {
+        "internalType": "uint256",
+        "name": "amount",
+        "type": "uint256"
+      }
+    ],
+    "name": "transfer",
+    "outputs": [
+      {
+        "internalType": "bool",
+        "name": "",
+        "type": "bool"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "nonpayable",
+    "type": "function"
+  },
+  {
+    "constant": false,
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "sender",
+        "type": "address"
+      },
+      {
+        "internalType": "address",
+        "name": "recipient",
+        "type": "address"
+      },
+      {
+        "internalType": "uint256",
+        "name": "amount",
+        "type": "uint256"
+      }
+    ],
+    "name": "transferFrom",
+    "outputs": [
+      {
+        "internalType": "bool",
+        "name": "",
+        "type": "bool"
+      }
+    ],
+    "payable": false,
+    "stateMutability": "nonpayable",
+    "type": "function"
+  }
+]

+ 636 - 0
extend/blockchain/web3/src/Contract.php

@@ -0,0 +1,636 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ *
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ *
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Providers\Provider;
+use blockchain\web3\src\Providers\HttpProvider;
+use blockchain\web3\src\RequestManagers\RequestManager;
+use blockchain\web3\src\RequestManagers\HttpRequestManager;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Eth;
+use blockchain\web3\src\Contracts\Ethabi;
+use blockchain\web3\src\Contracts\Types\Address;
+use blockchain\web3\src\Contracts\Types\Boolean;
+use blockchain\web3\src\Contracts\Types\Bytes;
+use blockchain\web3\src\Contracts\Types\DynamicBytes;
+use blockchain\web3\src\Contracts\Types\Integer;
+use blockchain\web3\src\Contracts\Types\Str;
+use blockchain\web3\src\Contracts\Types\Uinteger;
+use blockchain\web3\src\Validators\AddressValidator;
+use blockchain\web3\src\Validators\HexValidator;
+use blockchain\web3\src\Formatters\AddressFormatter;
+use blockchain\web3\src\Validators\StringValidator;
+
+class Contract
+{
+    /**
+     * provider
+     *
+     * @var \blockchain\web3\src\Providers\Provider
+     */
+    protected $provider;
+
+    /**
+     * abi
+     *
+     * @var array
+     */
+    protected $abi;
+
+    /**
+     * constructor
+     *
+     * @var array
+     */
+    protected $constructor = [];
+
+    /**
+     * functions
+     *
+     * @var array
+     */
+    protected $functions = [];
+
+    /**
+     * events
+     *
+     * @var array
+     */
+    protected $events = [];
+
+    /**
+     * toAddress
+     *
+     * @var string
+     */
+    protected $toAddress;
+
+    /**
+     * bytecode
+     *
+     * @var string
+     */
+    protected $bytecode;
+
+    /**
+     * eth
+     *
+     * @var \blockchain\web3\src\Eth
+     */
+    protected $eth;
+
+    /**
+     * ethabi
+     *
+     * @var \blockchain\web3\src\Contracts\Ethabi
+     */
+    protected $ethabi;
+
+    /**
+     * construct
+     *
+     * @param string|\blockchain\web3\src\Providers\Provider $provider
+     * @param string|\stdClass|array $abi
+     * @return void
+     */
+    public function __construct($provider, $abi)
+    {
+        if (is_string($provider) && (filter_var($provider, FILTER_VALIDATE_URL) !== false)) {
+            // check the uri schema
+            if (preg_match('/^https?:\/\//', $provider) === 1) {
+                $requestManager = new HttpRequestManager($provider);
+
+                $this->provider = new HttpProvider($requestManager);
+            }
+        } else if ($provider instanceof Provider) {
+            $this->provider = $provider;
+        }
+        $abi = Utils::jsonToArray($abi, 5);
+
+        foreach ($abi as $item) {
+            if (isset($item['type'])) {
+                if ($item['type'] === 'function') {
+                    $this->functions[$item['name']] = $item;
+                } elseif ($item['type'] === 'constructor') {
+                    $this->constructor = $item;
+                } elseif ($item['type'] === 'event') {
+                    $this->events[$item['name']] = $item;
+                }
+            }
+        }
+        $this->abi = $abi;
+        $this->eth = new Eth($this->provider);
+        $this->ethabi = new Ethabi([
+            'address' => new Address,
+            'bool' => new Boolean,
+            'bytes' => new Bytes,
+            'dynamicBytes' => new DynamicBytes,
+            'int' => new Integer,
+            'string' => new Str,
+            'uint' => new Uinteger,
+        ]);
+    }
+
+    /**
+     * call
+     *
+     * @param string $name
+     * @param array $arguments
+     * @return void
+     */
+    // public function __call($name, $arguments)
+    // {
+    //     if (empty($this->provider)) {
+    //         throw new \RuntimeException('Please set provider first.');
+    //     }
+    //     $class = explode('\\', get_class());
+    //     if (preg_match('/^[a-zA-Z0-9]+$/', $name) === 1) {
+    //     }
+    // }
+
+    /**
+     * get
+     *
+     * @param string $name
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        $method = 'get' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], []);
+        }
+        return false;
+    }
+
+    /**
+     * set
+     *
+     * @param string $name
+     * @param mixed $value
+     * @return mixed
+     */
+    public function __set($name, $value)
+    {
+        $method = 'set' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], [$value]);
+        }
+        return false;
+    }
+
+    /**
+     * getProvider
+     *
+     * @return \blockchain\web3\src\Providers\Provider
+     */
+    public function getProvider()
+    {
+        return $this->provider;
+    }
+
+    /**
+     * setProvider
+     *
+     * @param \blockchain\web3\src\Providers\Provider $provider
+     * @return $this
+     */
+    public function setProvider($provider)
+    {
+        if ($provider instanceof Provider) {
+            $this->provider = $provider;
+        }
+        return $this;
+    }
+
+    /**
+     * getFunctions
+     *
+     * @return array
+     */
+    public function getFunctions()
+    {
+        return $this->functions;
+    }
+
+    /**
+     * getEvents
+     *
+     * @return array
+     */
+    public function getEvents()
+    {
+        return $this->events;
+    }
+
+    /**
+     * @return string
+     */
+    public function getToAddress()
+    {
+        return $this->toAddress;
+    }
+
+    /**
+     * getConstructor
+     *
+     * @return array
+     */
+    public function getConstructor()
+    {
+        return $this->constructor;
+    }
+
+    /**
+     * getAbi
+     *
+     * @return array
+     */
+    public function getAbi()
+    {
+        return $this->abi;
+    }
+
+    /**
+     * setAbi
+     *
+     * @param string $abi
+     * @return $this
+     */
+    public function setAbi($abi)
+    {
+        return $this->abi($abi);
+    }
+
+    /**
+     * getEthabi
+     *
+     * @return array
+     */
+    public function getEthabi()
+    {
+        return $this->ethabi;
+    }
+
+    /**
+     * getEth
+     *
+     * @return \blockchain\web3\src\Eth
+     */
+    public function getEth()
+    {
+        return $this->eth;
+    }
+
+    /**
+     * setBytecode
+     *
+     * @param string $bytecode
+     * @return $this
+     */
+    public function setBytecode($bytecode)
+    {
+        return $this->bytecode($bytecode);
+    }
+
+    /**
+     * setToAddress
+     *
+     * @param string $bytecode
+     * @return $this
+     */
+    public function setToAddress($address)
+    {
+        return $this->at($address);
+    }
+
+    /**
+     * at
+     *
+     * @param string $address
+     * @return $this
+     */
+    public function at($address)
+    {
+        if (AddressValidator::validate($address) === false) {
+            throw new InvalidArgumentException('Please make sure address is valid.');
+        }
+        $this->toAddress = AddressFormatter::format($address);
+
+        return $this;
+    }
+
+    /**
+     * bytecode
+     *
+     * @param string $bytecode
+     * @return $this
+     */
+    public function bytecode($bytecode)
+    {
+        if (HexValidator::validate($bytecode) === false) {
+            throw new InvalidArgumentException('Please make sure bytecode is valid.');
+        }
+        $this->bytecode = Utils::stripZero($bytecode);
+
+        return $this;
+    }
+
+    /**
+     * abi
+     *
+     * @param string $abi
+     * @return $this
+     */
+    public function abi($abi)
+    {
+        if (StringValidator::validate($abi) === false) {
+            throw new InvalidArgumentException('Please make sure abi is valid.');
+        }
+        $abi = Utils::jsonToArray($abi, 5);
+
+        foreach ($abi as $item) {
+            if (isset($item['type'])) {
+                if ($item['type'] === 'function') {
+                    $this->functions[$item['name']] = $item;
+                } elseif ($item['type'] === 'constructor') {
+                    $this->constructor = $item;
+                } elseif ($item['type'] === 'event') {
+                    $this->events[$item['name']] = $item;
+                }
+            }
+        }
+        $this->abi = $abi;
+
+        return $this;
+    }
+
+    /**
+     * new
+     * Deploy a contruct with params.
+     *
+     * @param mixed
+     * @return void
+     */
+    public function new()
+    {
+        if (isset($this->constructor)) {
+            $constructor = $this->constructor;
+            $arguments = func_get_args();
+            $callback = array_pop($arguments);
+
+            if (count($arguments) < count($constructor['inputs'])) {
+                throw new InvalidArgumentException('Please make sure you have put all constructor params and callback.');
+            }
+            if (is_callable($callback) !== true) {
+                throw new \InvalidArgumentException('The last param must be callback function.');
+            }
+            if (!isset($this->bytecode)) {
+                throw new \InvalidArgumentException('Please call bytecode($bytecode) before new().');
+            }
+            $params = array_splice($arguments, 0, count($constructor['inputs']));
+            $data = $this->ethabi->encodeParameters($constructor, $params);
+            $transaction = [];
+
+            if (count($arguments) > 0) {
+                $transaction = $arguments[0];
+            }
+            $transaction['data'] = '0x' . $this->bytecode . Utils::stripZero($data);
+
+            $this->eth->sendTransaction($transaction, function ($err, $transaction) use ($callback) {
+                if ($err !== null) {
+                    return call_user_func($callback, $err, null);
+                }
+                return call_user_func($callback, null, $transaction);
+            });
+        }
+    }
+
+    /**
+     * send
+     * Send function method.
+     *
+     * @param mixed
+     * @return void
+     */
+    public function send()
+    {
+        if (isset($this->functions)) {
+            $arguments = func_get_args();
+            $method = array_splice($arguments, 0, 1)[0];
+            $callback = array_pop($arguments);
+
+            if (!is_string($method) || !isset($this->functions[$method])) {
+                throw new InvalidArgumentException('Please make sure the method exists.');
+            }
+            $function = $this->functions[$method];
+
+            if (count($arguments) < count($function['inputs'])) {
+                throw new InvalidArgumentException('Please make sure you have put all function params and callback.');
+            }
+            if (is_callable($callback) !== true) {
+                throw new \InvalidArgumentException('The last param must be callback function.');
+            }
+            $params = array_splice($arguments, 0, count($function['inputs']));
+            $data = $this->ethabi->encodeParameters($function, $params);
+            $functionName = Utils::jsonMethodToString($function);
+            $functionSignature = $this->ethabi->encodeFunctionSignature($functionName);
+            $transaction = [];
+
+            if (count($arguments) > 0) {
+                $transaction = $arguments[0];
+            }
+            $transaction['to'] = $this->toAddress;
+            $transaction['data'] = $functionSignature . Utils::stripZero($data);
+
+            $this->eth->sendTransaction($transaction, function ($err, $transaction) use ($callback) {
+                if ($err !== null) {
+                    return call_user_func($callback, $err, null);
+                }
+                return call_user_func($callback, null, $transaction);
+            });
+        }
+    }
+
+    /**
+     * call
+     * Call function method.
+     *
+     * @param mixed
+     * @return void
+     */
+    public function call()
+    {
+        if (isset($this->functions)) {
+            $arguments = func_get_args();
+            $method = array_splice($arguments, 0, 1)[0];
+            $callback = array_pop($arguments);
+
+            if (!is_string($method) || !isset($this->functions[$method])) {
+                throw new InvalidArgumentException('Please make sure the method exists.');
+            }
+            $function = $this->functions[$method];
+
+            if (count($arguments) < count($function['inputs'])) {
+                throw new InvalidArgumentException('Please make sure you have put all function params and callback.');
+            }
+            if (is_callable($callback) !== true) {
+                throw new \InvalidArgumentException('The last param must be callback function.');
+            }
+            $params = array_splice($arguments, 0, count($function['inputs']));
+            $data = $this->ethabi->encodeParameters($function, $params);
+            $functionName = Utils::jsonMethodToString($function);
+            $functionSignature = $this->ethabi->encodeFunctionSignature($functionName);
+            $transaction = [];
+
+            if (count($arguments) > 0) {
+                $transaction = $arguments[0];
+            }
+            $transaction['to'] = $this->toAddress;
+            $transaction['data'] = $functionSignature . Utils::stripZero($data);
+
+            $this->eth->call($transaction, function ($err, $transaction) use ($callback, $function) {
+                if ($err !== null) {
+                    return call_user_func($callback, $err, null);
+                }
+                $decodedTransaction = $this->ethabi->decodeParameters($function, $transaction);
+
+                return call_user_func($callback, null, $decodedTransaction);
+            });
+        }
+    }
+
+    /**
+     * estimateGas
+     * Estimate function gas.
+     *
+     * @param mixed
+     * @return void
+     */
+    public function estimateGas()
+    {
+        if (isset($this->functions) || isset($this->constructor)) {
+            $arguments = func_get_args();
+            $callback = array_pop($arguments);
+
+            if (empty($this->toAddress) && !empty($this->bytecode)) {
+                $constructor = $this->constructor;
+
+                if (count($arguments) < count($constructor['inputs'])) {
+                    throw new InvalidArgumentException('Please make sure you have put all constructor params and callback.');
+                }
+                if (is_callable($callback) !== true) {
+                    throw new \InvalidArgumentException('The last param must be callback function.');
+                }
+                if (!isset($this->bytecode)) {
+                    throw new \InvalidArgumentException('Please call bytecode($bytecode) before estimateGas().');
+                }
+                $params = array_splice($arguments, 0, count($constructor['inputs']));
+                $data = $this->ethabi->encodeParameters($constructor, $params);
+                $transaction = [];
+
+                if (count($arguments) > 0) {
+                    $transaction = $arguments[0];
+                }
+                $transaction['to'] = '';
+                $transaction['data'] = '0x' . $this->bytecode . Utils::stripZero($data);
+            } else {
+                $method = array_splice($arguments, 0, 1)[0];
+                $from = array_splice($arguments, 0, 1)[0];
+
+                if (!is_string($method) && !isset($this->functions[$method])) {
+                    throw new InvalidArgumentException('Please make sure the method is existed.');
+                }
+                $function = $this->functions[$method];
+
+                if (count($arguments) < count($function['inputs'])) {
+                    throw new InvalidArgumentException('Please make sure you have put all function params and callback.');
+                }
+                if (is_callable($callback) !== true) {
+                    throw new \InvalidArgumentException('The last param must be callback function.');
+                }
+                $params = array_splice($arguments, 0, count($function['inputs']));
+                $data = $this->ethabi->encodeParameters($function, $params);
+                $functionName = Utils::jsonMethodToString($function);
+                $functionSignature = $this->ethabi->encodeFunctionSignature($functionName);
+                $transaction = [];
+
+                if (count($arguments) > 0) {
+                    $transaction = $arguments[0];
+                }
+                $transaction['from'] = $from;
+                $transaction['to'] = $this->toAddress;
+                $transaction['data'] = $functionSignature . Utils::stripZero($data);
+            }
+
+            $this->eth->estimateGas($transaction, function ($err, $gas) use ($callback) {
+                if ($err !== null) {
+                    return call_user_func($callback, $err, null);
+                }
+                return call_user_func($callback, null, $gas);
+            });
+        }
+    }
+
+    /**
+     * getData
+     * Get the function method call data.
+     * With this function, you can send signed contract function transaction.
+     * 1. Get the funtion data with params.
+     * 2. Sign the data with user private key.
+     * 3. Call sendRawTransaction.
+     *
+     * @param mixed
+     * @return void
+     */
+    public function getData()
+    {
+        if (isset($this->functions) || isset($this->constructor)) {
+            $arguments = func_get_args();
+            $functionData = '';
+
+            if (empty($this->toAddress) && !empty($this->bytecode)) {
+                $constructor = $this->constructor;
+
+                if (count($arguments) < count($constructor['inputs'])) {
+                    throw new InvalidArgumentException('Please make sure you have put all constructor params and callback.');
+                }
+                if (!isset($this->bytecode)) {
+                    throw new \InvalidArgumentException('Please call bytecode($bytecode) before getData().');
+                }
+                $params = array_splice($arguments, 0, count($constructor['inputs']));
+                $data = $this->ethabi->encodeParameters($constructor, $params);
+                $functionData = $this->bytecode . Utils::stripZero($data);
+            } else {
+                $method = array_splice($arguments, 0, 1)[0];
+
+                if (!is_string($method) && !isset($this->functions[$method])) {
+                    throw new InvalidArgumentException('Please make sure the method is existed.');
+                }
+                $function = $this->functions[$method];
+
+                if (count($arguments) < count($function['inputs'])) {
+                    throw new InvalidArgumentException('Please make sure you have put all function params and callback.');
+                }
+                $params = array_splice($arguments, 0, count($function['inputs']));
+                $data = $this->ethabi->encodeParameters($function, $params);
+                $functionName = Utils::jsonMethodToString($function);
+                $functionSignature = $this->ethabi->encodeFunctionSignature($functionName);
+                $functionData = Utils::stripZero($functionSignature) . Utils::stripZero($data);
+            }
+            return $functionData;
+        }
+    }
+}

+ 399 - 0
extend/blockchain/web3/src/Contracts/Ethabi.php

@@ -0,0 +1,399 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts;
+
+use InvalidArgumentException;
+use stdClass;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IntegerFormatter;
+
+class Ethabi
+{
+    /**
+     * types
+     * 
+     * @var array
+     */
+    protected $types = [];
+
+    /**
+     * construct
+     * 
+     * @param array $types
+     * @return void
+     */
+    public function __construct($types=[])
+    {
+        if (!is_array($types)) {
+            $types = [];
+        }
+        $this->types = $types;
+    }
+
+    /**
+     * get
+     * 
+     * @param string $name
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        $method = 'get' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], []);
+        }
+        return false;
+    }
+
+    /**
+     * set
+     * 
+     * @param string $name
+     * @param mixed $value
+     * @return mixed
+     */
+    public function __set($name, $value)
+    {
+        $method = 'set' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], [$value]);
+        }
+        return false;
+    }
+
+    /**
+     * callStatic
+     * 
+     * @param string $name
+     * @param array $arguments
+     * @return void
+     */
+    public static function __callStatic($name, $arguments)
+    {
+        // 
+    }
+
+    /**
+     * encodeFunctionSignature
+     * 
+     * @param string|stdClass|array $functionName
+     * @return string
+     */
+    public function encodeFunctionSignature($functionName)
+    {
+        if (!is_string($functionName)) {
+            $functionName = Utils::jsonMethodToString($functionName);
+        }
+        return mb_substr(Utils::sha3($functionName), 0, 10);
+    }
+
+    /**
+     * encodeEventSignature
+     * 
+     * @param string|stdClass|array $functionName
+     * @return string
+     */
+    public function encodeEventSignature($functionName)
+    {
+        if (!is_string($functionName)) {
+            $functionName = Utils::jsonMethodToString($functionName);
+        }
+        return Utils::sha3($functionName);
+    }
+
+    /**
+     * encodeParameter
+     * 
+     * @param string $type
+     * @param mixed $param
+     * @return string
+     */
+    public function encodeParameter($type, $param)
+    {
+        if (!is_string($type)) {
+            throw new InvalidArgumentException('The type to encodeParameter must be string.');
+        }
+        return $this->encodeParameters([$type], [$param]);
+    }
+
+    /**
+     * encodeParameters
+     * 
+     * @param stdClass|array $types
+     * @param array $params
+     * @return string
+     */
+    public function encodeParameters($types, $params)
+    {
+        // change json to array
+        if ($types instanceof stdClass && isset($types->inputs)) {
+            $types = Utils::jsonToArray($types, 2);
+        }
+        if (is_array($types) && isset($types['inputs'])) {
+            $inputTypes = $types;
+            $types = [];
+
+            foreach ($inputTypes['inputs'] as $input) {
+                if (isset($input['type'])) {
+                    $types[] = $input['type'];
+                }
+            }
+        }
+        if (count($types) !== count($params)) {
+            throw new InvalidArgumentException('encodeParameters number of types must equal to number of params.');
+        }
+        $typesLength = count($types);
+        $solidityTypes = $this->getSolidityTypes($types);
+
+        foreach ($types as $key => $type) {
+            $match = [];
+
+            if (preg_match('/^([a-zA-Z]+)/', $type, $match) === 1) {
+                if (isset($this->types[$match[0]])) {
+                    $className = $this->types[$match[0]];
+
+                    if (call_user_func([$this->types[$match[0]], 'isType'], $type) === false) {
+                        throw new InvalidArgumentException('Unsupport solidity parameter type: ' . $type);
+                    }
+                    $solidityTypes[$key] = $className;
+                }
+            }
+        }
+        $encodes = array_fill(0, $typesLength, '');
+
+        foreach ($solidityTypes as $key => $type) {
+            $encodes[$key] = call_user_func([$type, 'encode'], $params[$key], $types[$key]);
+        }
+        $dynamicOffset = 0;
+
+        foreach ($solidityTypes as $key => $type) {
+            $staticPartLength = $type->staticPartLength($types[$key]);
+            $roundedStaticPartLength = floor(($staticPartLength + 31) / 32) * 32;
+
+            if ($type->isDynamicType($types[$key]) || $type->isDynamicArray($types[$key])) {
+                $dynamicOffset += 32;
+            } else {
+                $dynamicOffset += $roundedStaticPartLength;
+            }
+        }
+        return '0x' . $this->encodeMultiWithOffset($types, $solidityTypes, $encodes, $dynamicOffset);
+    }
+
+    /**
+     * decodeParameter
+     * 
+     * @param string $type
+     * @param mixed $param
+     * @return string
+     */
+    public function decodeParameter($type, $param)
+    {
+        if (!is_string($type)) {
+            throw new InvalidArgumentException('The type to decodeParameter must be string.');
+        }
+        return $this->decodeParameters([$type], $param)[0];
+    }
+
+    /**
+     * decodeParameters
+     * 
+     * @param stdClass|array $type
+     * @param string $param
+     * @return string
+     */
+    public function decodeParameters($types, $param)
+    {
+        if (!is_string($param)) {
+            throw new InvalidArgumentException('The type or param to decodeParameters must be string.');
+        }
+
+        // change json to array
+        if ($types instanceof stdClass && isset($types->outputs)) {
+            $types = Utils::jsonToArray($types, 2);
+        }
+        if (is_array($types) && isset($types['outputs'])) {
+            $outputTypes = $types;
+            $types = [];
+
+            foreach ($outputTypes['outputs'] as $output) {
+                if (isset($output['type'])) {
+                    $types[] = $output['type'];
+                }
+            }
+        }
+        $typesLength = count($types);
+        $solidityTypes = $this->getSolidityTypes($types);
+        $offsets = array_fill(0, $typesLength, 0);
+
+        for ($i=0; $i<$typesLength; $i++) {
+            $offsets[$i] = $solidityTypes[$i]->staticPartLength($types[$i]);
+        }
+        for ($i=1; $i<$typesLength; $i++) {
+            $offsets[$i] += $offsets[$i - 1];
+        }
+        for ($i=0; $i<$typesLength; $i++) {
+            $offsets[$i] -= $solidityTypes[$i]->staticPartLength($types[$i]);
+        }
+        $result = [];
+        $param = mb_strtolower(Utils::stripZero($param));
+
+        for ($i=0; $i<$typesLength; $i++) {
+            if (isset($outputTypes['outputs'][$i]['name']) && empty($outputTypes['outputs'][$i]['name']) === false) {
+                $result[$outputTypes['outputs'][$i]['name']] = $solidityTypes[$i]->decode($param, $offsets[$i], $types[$i]);
+            } else {
+                $result[$i] = $solidityTypes[$i]->decode($param, $offsets[$i], $types[$i]);
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * getSolidityTypes
+     * 
+     * @param array $types
+     * @return array
+     */
+    protected function getSolidityTypes($types)
+    {
+        if (!is_array($types)) {
+            throw new InvalidArgumentException('Types must be array');
+        }
+        $solidityTypes = array_fill(0, count($types), 0);
+
+        foreach ($types as $key => $type) {
+            $match = [];
+
+            if (preg_match('/^([a-zA-Z]+)/', $type, $match) === 1) {
+                if (isset($this->types[$match[0]])) {
+                    $className = $this->types[$match[0]];
+
+                    if (call_user_func([$this->types[$match[0]], 'isType'], $type) === false) {
+                        // check dynamic bytes
+                        if ($match[0] === 'bytes') {
+                            $className = $this->types['dynamicBytes'];
+                        } else {
+                            throw new InvalidArgumentException('Unsupport solidity parameter type: ' . $type);
+                        }
+                    }
+                    $solidityTypes[$key] = $className;
+                }
+            }
+        }
+        return $solidityTypes;
+    }
+
+    /**
+     * encodeWithOffset
+     * 
+     * @param string $type
+     * @param \blockchain\web3\src\Contracts\SolidityType $solidityType
+     * @param mixed $encode
+     * @param int $offset
+     * @return string
+     */
+    protected function encodeWithOffset($type, $solidityType, $encoded, $offset)
+    {
+        if ($solidityType->isDynamicArray($type)) {
+            $nestedName = $solidityType->nestedName($type);
+            $nestedStaticPartLength = $solidityType->staticPartLength($type);
+            $result = $encoded[0];
+
+            if ($solidityType->isDynamicArray($nestedName)) {
+                $previousLength = 2;
+
+                for ($i=0; $i<count($encoded); $i++) {
+                    if (isset($encoded[$i - 1])) {
+                        $previousLength += abs($encoded[$i - 1][0]);
+                    }
+                    $result .= IntegerFormatter::format($offset + $i * $nestedStaticPartLength + $previousLength * 32);
+                }
+            }
+            for ($i=0; $i<count($encoded); $i++) {
+                // $bn = Utils::toBn($result);
+                // $divided = $bn->divide(Utils::toBn(2));
+
+                // if (is_array($divided)) {
+                //     $additionalOffset = (int) $divided[0]->toString();
+                // } else {
+                //     $additionalOffset = 0;
+                // }
+                $additionalOffset = floor(mb_strlen($result) / 2);
+                $result .= $this->encodeWithOffset($nestedName, $solidityType, $encoded[$i], $offset + $additionalOffset);
+            }
+            return mb_substr($result, 64);
+        } elseif ($solidityType->isStaticArray($type)) {
+            $nestedName = $solidityType->nestedName($type);
+            $nestedStaticPartLength = $solidityType->staticPartLength($type);
+            $result = '';
+
+            if ($solidityType->isDynamicArray($nestedName)) {
+                $previousLength = 0;
+
+                for ($i=0; $i<count($encoded); $i++) {
+                    if (isset($encoded[$i - 1])) {
+                        $previousLength += abs($encoded[$i - 1])[0];
+                    }
+                    $result .= IntegerFormatter::format($offset + $i * $nestedStaticPartLength + $previousLength * 32);
+                }
+            }
+            for ($i=0; $i<count($encoded); $i++) {
+                // $bn = Utils::toBn($result);
+                // $divided = $bn->divide(Utils::toBn(2));
+
+                // if (is_array($divided)) {
+                //     $additionalOffset = (int) $divided[0]->toString();
+                // } else {
+                //     $additionalOffset = 0;
+                // }
+                $additionalOffset = floor(mb_strlen($result) / 2);
+                $result .= $this->encodeWithOffset($nestedName, $solidityType, $encoded[$i], $offset + $additionalOffset);
+            }
+            return $result;
+        }
+        return $encoded;
+    }
+
+    /**
+     * encodeMultiWithOffset
+     * 
+     * @param array $types
+     * @param array $solidityTypes
+     * @param array $encodes
+     * @param int $dynamicOffset
+     * @return string
+     */
+    protected function encodeMultiWithOffset($types, $solidityTypes, $encodes, $dynamicOffset)
+    {
+        $result = '';
+
+        foreach ($solidityTypes as $key => $type) {
+            if ($type->isDynamicType($types[$key]) || $type->isDynamicArray($types[$key])) {
+                $result .= IntegerFormatter::format($dynamicOffset);
+                $e = $this->encodeWithOffset($types[$key], $type, $encodes[$key], $dynamicOffset);
+                $dynamicOffset += floor(mb_strlen($e) / 2);
+            } else {
+                $result .= $this->encodeWithOffset($types[$key], $type, $encodes[$key], $dynamicOffset);
+            }
+        }
+        foreach ($solidityTypes as $key => $type) {
+            if ($type->isDynamicType($types[$key]) || $type->isDynamicArray($types[$key])) {
+                $e = $this->encodeWithOffset($types[$key], $type, $encodes[$key], $dynamicOffset);
+                // $dynamicOffset += floor(mb_strlen($e) / 2);
+                $result .= $e;
+            }
+        }
+        return $result;
+    }
+}

+ 273 - 0
extend/blockchain/web3/src/Contracts/SolidityType.php

@@ -0,0 +1,273 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts;
+
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IntegerFormatter;
+
+class SolidityType
+{
+    /**
+     * construct
+     * 
+     * @return void
+     */
+    // public function  __construct() {}
+
+    /**
+     * get
+     * 
+     * @param string $name
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        $method = 'get' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], []);
+        }
+        return false;
+    }
+
+    /**
+     * set
+     * 
+     * @param string $name
+     * @param mixed $value
+     * @return mixed;
+     */
+    public function __set($name, $value)
+    {
+        $method = 'set' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], [$value]);
+        }
+        return false;
+    }
+
+    /**
+     * callStatic
+     * 
+     * @param string $name
+     * @param array $arguments
+     * @return void
+     */
+    // public static function __callStatic($name, $arguments) {}
+
+    /**
+     * nestedTypes
+     * 
+     * @param string $name
+     * @return mixed
+     */
+    public function nestedTypes($name)
+    {
+        if (!is_string($name)) {
+            throw new InvalidArgumentException('nestedTypes name must string.');
+        }
+        $matches = [];
+
+        if (preg_match_all('/(\[[0-9]*\])/', $name, $matches, PREG_PATTERN_ORDER) >= 1) {
+            return $matches[0];
+        }
+        return false;
+    }
+
+    /**
+     * nestedName
+     * 
+     * @param string $name
+     * @return string
+     */
+    public function nestedName($name)
+    {
+        if (!is_string($name)) {
+            throw new InvalidArgumentException('nestedName name must string.');
+        }
+        $nestedTypes = $this->nestedTypes($name);
+
+        if ($nestedTypes === false) {
+            return $name;
+        }
+        return mb_substr($name, 0, mb_strlen($name) - mb_strlen($nestedTypes[count($nestedTypes) - 1]));
+    }
+
+    /**
+     * isDynamicArray
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isDynamicArray($name)
+    {
+        $nestedTypes = $this->nestedTypes($name);
+
+        return $nestedTypes && preg_match('/[0-9]{1,}/', $nestedTypes[count($nestedTypes) - 1]) !== 1;
+    }
+
+    /**
+     * isStaticArray
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isStaticArray($name)
+    {
+        $nestedTypes = $this->nestedTypes($name);
+
+        return $nestedTypes && preg_match('/[0-9]{1,}/', $nestedTypes[count($nestedTypes) - 1]) === 1;
+    }
+
+    /**
+     * staticArrayLength
+     * 
+     * @param string $name
+     * @return int
+     */
+    public function staticArrayLength($name)
+    {
+        $nestedTypes = $this->nestedTypes($name);
+
+        if ($nestedTypes === false) {
+            return 1;
+        }
+        $match = [];
+
+        if (preg_match('/[0-9]{1,}/', $nestedTypes[count($nestedTypes) - 1], $match) === 1) {
+            return (int) $match[0];
+        }
+        return 1;
+    }
+
+    /**
+     * staticPartLength
+     * 
+     * @param string $name
+     * @return int
+     */
+    public function staticPartLength($name)
+    {
+        $nestedTypes = $this->nestedTypes($name);
+
+        if ($nestedTypes === false) {
+            $nestedTypes = ['[1]'];
+        }
+        $count = 32;
+
+        foreach ($nestedTypes as $type) {
+            $num = mb_substr($type, 1, 1);
+
+            if (!is_numeric($num)) {
+                $num = 1;
+            } else {
+                $num = intval($num);
+            }
+            $count *= $num;
+        }
+
+        return $count;
+    }
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType()
+    {
+        return false;
+    }
+
+    /**
+     * encode
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function encode($value, $name)
+    {
+        if ($this->isDynamicArray($name)) {
+            $length = count($value);
+            $nestedName = $this->nestedName($name);
+            $result = [];
+            $result[] = IntegerFormatter::format($length);
+
+            foreach ($value as $val) {
+                $result[] = $this->encode($val, $nestedName);
+            }
+            return $result;
+        } elseif ($this->isStaticArray($name)) {
+            $length = $this->staticArrayLength($name);
+            $nestedName = $this->nestedName($name);
+            $result = [];
+
+            foreach ($value as $val) {
+                $result[] = $this->encode($val, $nestedName);
+            }
+            return $result;
+        }
+        return $this->inputFormat($value, $name);
+    }
+
+    /**
+     * decode
+     * 
+     * @param mixed $value
+     * @param string $offset
+     * @param string $name
+     * @return array
+     */
+    public function decode($value, $offset, $name)
+    {
+        if ($this->isDynamicArray($name)) {
+            $arrayOffset = (int) Utils::toBn('0x' . mb_substr($value, $offset * 2, 64))->toString();
+            $length = (int) Utils::toBn('0x' . mb_substr($value, $arrayOffset * 2, 64))->toString();
+            $arrayStart = $arrayOffset + 32;
+
+            $nestedName = $this->nestedName($name);
+            $nestedStaticPartLength = $this->staticPartLength($nestedName);
+            $roundedNestedStaticPartLength = floor(($nestedStaticPartLength + 31) / 32) * 32;
+            $result = [];
+
+            for ($i=0; $i<$length * $roundedNestedStaticPartLength; $i+=$roundedNestedStaticPartLength) {
+                $result[] = $this->decode($value, $arrayStart + $i, $nestedName);
+            }
+            return $result;
+        } elseif ($this->isStaticArray($name)) {
+            $length = $this->staticArrayLength($name);
+            $arrayStart = $offset;
+
+            $nestedName = $this->nestedName($name);
+            $nestedStaticPartLength = $this->staticPartLength($nestedName);
+            $roundedNestedStaticPartLength = floor(($nestedStaticPartLength + 31) / 32) * 32;
+            $result = [];
+
+            for ($i=0; $i<$length * $roundedNestedStaticPartLength; $i+=$roundedNestedStaticPartLength) {
+                $result[] = $this->decode($value, $arrayStart + $i, $nestedName);
+            }
+            return $result;
+        } elseif ($this->isDynamicType()) {
+            $dynamicOffset = (int) Utils::toBn('0x' . mb_substr($value, $offset * 2, 64))->toString();
+            $length = (int) Utils::toBn('0x' . mb_substr($value, $dynamicOffset * 2, 64))->toString();
+            $roundedLength = floor(($length + 31) / 32);
+            $param = mb_substr($value, $dynamicOffset * 2, ( 1 + $roundedLength) * 64);
+            return $this->outputFormat($param, $name);
+        }
+        $length = $this->staticPartLength($name);
+        $param = mb_substr($value, $offset * 2, $length * 2);
+
+        return $this->outputFormat($param, $name);
+    }
+}

+ 86 - 0
extend/blockchain/web3/src/Contracts/Types/Address.php

@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts\Types;
+
+use blockchain\web3\src\Contracts\SolidityType;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IntegerFormatter;
+
+class Address extends SolidityType implements IType
+{
+    /**
+     * construct
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * isType
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isType($name)
+    {
+        return (preg_match('/^address(\[([0-9]*)\])*$/', $name) === 1);
+    }
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType()
+    {
+        return false;
+    }
+
+    /**
+     * inputFormat
+     * to do: iban
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function inputFormat($value, $name)
+    {
+        $value = (string) $value;
+
+        if (Utils::isAddress($value)) {
+            $value = mb_strtolower($value);
+
+            if (Utils::isZeroPrefixed($value)) {
+                $value = Utils::stripZero($value);
+            }
+        }
+        $value = IntegerFormatter::format($value);
+
+        return $value;
+    }
+
+    /**
+     * outputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function outputFormat($value, $name)
+    {
+        return '0x' . mb_substr($value, 24, 40);
+    }
+}

+ 81 - 0
extend/blockchain/web3/src/Contracts/Types/Boolean.php

@@ -0,0 +1,81 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts\Types;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Contracts\SolidityType;
+use blockchain\web3\src\Contracts\Types\IType;
+
+class Boolean extends SolidityType implements IType
+{
+    /**
+     * construct
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * isType
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isType($name)
+    {
+        return (preg_match('/^bool(\[([0-9]*)\])*$/', $name) === 1);
+    }
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType()
+    {
+        return false;
+    }
+
+    /**
+     * inputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function inputFormat($value, $name)
+    {
+        if (!is_bool($value)) {
+            throw new InvalidArgumentException('The value to inputFormat function must be boolean.');
+        }
+        $value = (int) $value;
+
+        return '000000000000000000000000000000000000000000000000000000000000000' . $value;
+    }
+
+    /**
+     * outputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function outputFormat($value, $name)
+    {
+        $value = (int) mb_substr($value, 63, 1);
+
+        return (bool) $value;
+    }
+}

+ 100 - 0
extend/blockchain/web3/src/Contracts/Types/Bytes.php

@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts\Types;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Contracts\SolidityType;
+use blockchain\web3\src\Contracts\Types\IType;
+
+class Bytes extends SolidityType implements IType
+{
+    /**
+     * construct
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * isType
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isType($name)
+    {
+        return (preg_match('/^bytes([0-9]{1,})(\[([0-9]*)\])*$/', $name) === 1);
+    }
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType()
+    {
+        return false;
+    }
+
+    /**
+     * inputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function inputFormat($value, $name)
+    {
+        if (!Utils::isHex($value)) {
+            throw new InvalidArgumentException('The value to inputFormat must be hex bytes.');
+        }
+        $value = Utils::stripZero($value);
+
+        // if (mb_strlen($value) % 2 !== 0) {
+        //     throw new InvalidArgumentException('The value to inputFormat has invalid length. Value: ' . $value);
+        // }
+
+        if (mb_strlen($value) > 64) {
+            throw new InvalidArgumentException('The value to inputFormat is too long.');
+        }
+        $l = floor((mb_strlen($value) + 63) / 64);
+        $padding = (($l * 64 - mb_strlen($value) + 1) >= 0) ? $l * 64 - mb_strlen($value) : 0;
+
+        return $value . implode('', array_fill(0, $padding, '0'));
+    }
+
+    /**
+     * outputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function outputFormat($value, $name)
+    {
+        $checkZero = str_replace('0', '', $value);
+
+        if (empty($checkZero)) {
+            return '0';
+        }
+        if (preg_match('/^bytes([0-9]*)/', $name, $match) === 1) {
+            $size = intval($match[1]);
+            $length = 2 * $size;
+            $value = mb_substr($value, 0, $length);
+        }
+        return '0x' . $value;
+    }
+}

+ 97 - 0
extend/blockchain/web3/src/Contracts/Types/DynamicBytes.php

@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts\Types;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Contracts\SolidityType;
+use blockchain\web3\src\Contracts\Types\IType;
+
+class DynamicBytes extends SolidityType implements IType
+{
+    /**
+     * construct
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * isType
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isType($name)
+    {
+        return (preg_match('/^bytes(\[([0-9]*)\])*$/', $name) === 1);
+    }
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType()
+    {
+        return true;
+    }
+
+    /**
+     * inputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function inputFormat($value, $name)
+    {
+        if (!Utils::isHex($value)) {
+            throw new InvalidArgumentException('The value to inputFormat must be hex bytes.');
+        }
+        $value = Utils::stripZero($value);
+
+        // if (mb_strlen($value) % 2 !== 0) {
+        //     throw new InvalidArgumentException('The value to inputFormat has invalid length.');
+        // }
+        $bn = Utils::toBn(mb_strlen($value) / 2);
+        $bnHex = $bn->toHex(true);
+        $padded = mb_substr($bnHex, 0, 1);
+        $l = floor((mb_strlen($value) + 63) / 64);
+        $padding = (($l * 64 - mb_strlen($value) + 1) >= 0) ? $l * 64 - mb_strlen($value) : 0;
+
+        return implode('', array_fill(0, 64-mb_strlen($bnHex), $padded)) . $bnHex . $value . implode('', array_fill(0, $padding, '0'));
+    }
+
+    /**
+     * outputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function outputFormat($value, $name)
+    {
+        $checkZero = str_replace('0', '', $value);
+
+        if (empty($checkZero)) {
+            return '0';
+        }
+        $size = intval(Utils::toBn(mb_substr($value, 0, 64))->toString());
+        $length = 2 * $size;
+        
+        return '0x' . mb_substr($value, 64, $length);
+    }
+}

+ 39 - 0
extend/blockchain/web3/src/Contracts/Types/IType.php

@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts\Types;
+
+interface IType
+{
+    /**
+     * isType
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isType($name);
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType();
+
+    /**
+     * inputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function inputFormat($value, $name);
+}

+ 82 - 0
extend/blockchain/web3/src/Contracts/Types/Integer.php

@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts\Types;
+
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Contracts\SolidityType;
+use blockchain\web3\src\Contracts\Types\IType;
+use blockchain\web3\src\Formatters\IntegerFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class Integer extends SolidityType implements IType
+{
+    /**
+     * construct
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * isType
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isType($name)
+    {
+        return (preg_match('/^int([0-9]{1,})?(\[([0-9]*)\])*$/', $name) === 1);
+    }
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType()
+    {
+        return false;
+    }
+
+    /**
+     * inputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function inputFormat($value, $name)
+    {
+        return IntegerFormatter::format($value);
+    }
+
+    /**
+     * outputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function outputFormat($value, $name)
+    {
+        $match = [];
+
+        if (preg_match('/^[0]+([a-f0-9]+)$/', $value, $match) === 1) {
+            // due to value without 0x prefix, we will parse as decimal
+            $value = '0x' . $match[1];
+        }
+        return BigNumberFormatter::format($value);
+    }
+}

+ 90 - 0
extend/blockchain/web3/src/Contracts/Types/Str.php

@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts\Types;
+
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Contracts\SolidityType;
+use blockchain\web3\src\Contracts\Types\IType;
+use blockchain\web3\src\Formatters\IntegerFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class Str extends SolidityType implements IType
+{
+    /**
+     * construct
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * isType
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isType($name)
+    {
+        return (preg_match('/^string(\[([0-9]*)\])*$/', $name) === 1);
+    }
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType()
+    {
+        return true;
+    }
+
+    /**
+     * inputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function inputFormat($value, $name)
+    {
+        $value = Utils::toHex($value);
+        $prefix = IntegerFormatter::format(mb_strlen($value) / 2);
+        $l = floor((mb_strlen($value) + 63) / 64);
+        $padding = (($l * 64 - mb_strlen($value) + 1) >= 0) ? $l * 64 - mb_strlen($value) : 0;
+
+        return $prefix . $value . implode('', array_fill(0, $padding, '0'));
+    }
+
+    /**
+     * outputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function outputFormat($value, $name)
+    {
+        $strLen = mb_substr($value, 0, 64);
+        $strValue = mb_substr($value, 64);
+        $match = [];
+
+        if (preg_match('/^[0]+([a-f0-9]+)$/', $strLen, $match) === 1) {
+            $strLen = BigNumberFormatter::format('0x' . $match[1])->toString();
+        }
+        $strValue = mb_substr($strValue, 0, (int) $strLen * 2);
+
+        return Utils::hexToBin($strValue);
+    }
+}

+ 82 - 0
extend/blockchain/web3/src/Contracts/Types/Uinteger.php

@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Contracts\Types;
+
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Contracts\SolidityType;
+use blockchain\web3\src\Contracts\Types\IType;
+use blockchain\web3\src\Formatters\IntegerFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class Uinteger extends SolidityType implements IType
+{
+    /**
+     * construct
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * isType
+     * 
+     * @param string $name
+     * @return bool
+     */
+    public function isType($name)
+    {
+        return (preg_match('/^uint([0-9]{1,})?(\[([0-9]*)\])*$/', $name) === 1);
+    }
+
+    /**
+     * isDynamicType
+     * 
+     * @return bool
+     */
+    public function isDynamicType()
+    {
+        return false;
+    }
+
+    /**
+     * inputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function inputFormat($value, $name)
+    {
+        return IntegerFormatter::format($value);
+    }
+
+    /**
+     * outputFormat
+     * 
+     * @param mixed $value
+     * @param string $name
+     * @return string
+     */
+    public function outputFormat($value, $name)
+    {
+        $match = [];
+
+        if (preg_match('/^[0]+([a-f0-9]+)$/', $value, $match) === 1) {
+            // due to value without 0x prefix, we will parse as decimal
+            $value = '0x' . $match[1];
+        }
+        return BigNumberFormatter::format($value);
+    }
+}

+ 180 - 0
extend/blockchain/web3/src/Eth.php

@@ -0,0 +1,180 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ *
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ *
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src;
+
+use blockchain\web3\src\Providers\Provider;
+use blockchain\web3\src\Providers\HttpProvider;
+use blockchain\web3\src\RequestManagers\RequestManager;
+use blockchain\web3\src\RequestManagers\HttpRequestManager;
+
+class Eth
+{
+    /**
+     * provider
+     *
+     * @var \blockchain\web3\src\Providers\Provider
+     */
+    protected $provider;
+
+    /**
+     * methods
+     *
+     * @var array
+     */
+    private $methods = [];
+
+    /**
+     * allowedMethods
+     *
+     * @var array
+     */
+    private $allowedMethods = [
+        'eth_protocolVersion', 'eth_syncing', 'eth_coinbase', 'eth_mining', 'eth_hashrate', 'eth_gasPrice', 'eth_accounts', 'eth_blockNumber', 'eth_getBalance', 'eth_getStorageAt', 'eth_getTransactionCount', 'eth_getBlockTransactionCountByHash', 'eth_getBlockTransactionCountByNumber', 'eth_getUncleCountByBlockHash', 'eth_getUncleCountByBlockNumber', 'eth_getUncleByBlockHashAndIndex', 'eth_getUncleByBlockNumberAndIndex', 'eth_getCode', 'eth_sign', 'eth_sendTransaction', 'eth_sendRawTransaction', 'eth_call', 'eth_estimateGas', 'eth_getBlockByHash', 'eth_getBlockByNumber', 'eth_getTransactionByHash', 'eth_getTransactionByBlockHashAndIndex', 'eth_getTransactionByBlockNumberAndIndex', 'eth_getTransactionReceipt', 'eth_getCompilers', 'eth_compileSolidity', 'eth_compileLLL', 'eth_compileSerpent', 'eth_getWork', 'eth_newFilter', 'eth_newBlockFilter', 'eth_newPendingTransactionFilter', 'eth_uninstallFilter', 'eth_getFilterChanges', 'eth_getFilterLogs', 'eth_getLogs', 'eth_submitWork', 'eth_submitHashrate'
+    ];
+
+    /**
+     * construct
+     *
+     * @param string|\blockchain\web3\src\Providers\Provider $provider
+     * @return void
+     */
+    public function __construct($provider)
+    {
+        if (is_string($provider) && (filter_var($provider, FILTER_VALIDATE_URL) !== false)) {
+            // check the uri schema
+            if (preg_match('/^https?:\/\//', $provider) === 1) {
+                $requestManager = new HttpRequestManager($provider);
+
+                $this->provider = new HttpProvider($requestManager);
+            }
+        } else if ($provider instanceof Provider) {
+            $this->provider = $provider;
+        }
+    }
+
+    /**
+     * call
+     *
+     * @param string $name
+     * @param array $arguments
+     * @return void
+     */
+    public function __call($name, $arguments)
+    {
+        if (empty($this->provider)) {
+            throw new \RuntimeException('Please set provider first.');
+        }
+
+        $class = explode('\\', get_class());
+
+        if (preg_match('/^[a-zA-Z0-9]+$/', $name) === 1) {
+            $method = strtolower($class[count($class) - 1]) . '_' . $name;
+
+            if (!in_array($method, $this->allowedMethods)) {
+                throw new \RuntimeException('Unallowed rpc method: ' . $method);
+            }
+            if ($this->provider->isBatch) {
+                $callback = null;
+            } else {
+                $callback = array_pop($arguments);
+
+                if (is_callable($callback) !== true) {
+                    throw new \InvalidArgumentException('The last param must be callback function.');
+                }
+            }
+            if (!array_key_exists($method, $this->methods)) {
+                // new the method
+                $methodClass = sprintf("\blockchain\web3\src\Methods\%s\%s", ucfirst($class[count($class) - 1]), ucfirst($name));
+                $methodObject = new $methodClass($method, $arguments);
+                $this->methods[$method] = $methodObject;
+            } else {
+                $methodObject = $this->methods[$method];
+            }
+            if ($methodObject->validate($arguments)) {
+                $inputs = $methodObject->transform($arguments, $methodObject->inputFormatters);
+                $methodObject->arguments = $inputs;
+                $this->provider->send($methodObject, $callback);
+            }
+        }
+    }
+
+    /**
+     * get
+     *
+     * @param string $name
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        $method = 'get' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], []);
+        }
+        return false;
+    }
+
+    /**
+     * set
+     *
+     * @param string $name
+     * @param mixed $value
+     * @return mixed
+     */
+    public function __set($name, $value)
+    {
+        $method = 'set' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], [$value]);
+        }
+        return false;
+    }
+
+    /**
+     * getProvider
+     *
+     * @return \blockchain\web3\src\Providers\Provider
+     */
+    public function getProvider()
+    {
+        return $this->provider;
+    }
+
+    /**
+     * setProvider
+     *
+     * @param \blockchain\web3\src\Providers\Provider $provider
+     * @return bool
+     */
+    public function setProvider($provider)
+    {
+        if ($provider instanceof Provider) {
+            $this->provider = $provider;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * batch
+     *
+     * @param bool $status
+     * @return void
+     */
+    public function batch($status)
+    {
+        $status = is_bool($status);
+
+        $this->provider->batch($status);
+    }
+}

+ 44 - 0
extend/blockchain/web3/src/Formatters/AddressFormatter.php

@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+use blockchain\web3\src\Formatters\IntegerFormatter;
+
+class AddressFormatter implements IFormatter
+{
+    /**
+     * format
+     * to do: iban
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        $value = (string) $value;
+
+        if (Utils::isAddress($value)) {
+            $value = mb_strtolower($value);
+
+            if (Utils::isZeroPrefixed($value)) {
+                return $value;
+            }
+            return '0x' . $value;
+        }
+        $value = IntegerFormatter::format($value, 40);
+
+        return '0x' . $value;
+    }
+}

+ 33 - 0
extend/blockchain/web3/src/Formatters/BigNumberFormatter.php

@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+
+class BigNumberFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        $value = Utils::toString($value);
+        $bn = Utils::toBn($value);
+
+        return $bn;
+    }
+}

+ 30 - 0
extend/blockchain/web3/src/Formatters/BooleanFormatter.php

@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+
+class BooleanFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return bool
+     */
+    public static function format($value)
+    {
+        return (bool) $value;
+    }
+}

+ 38 - 0
extend/blockchain/web3/src/Formatters/HexFormatter.php

@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+
+class HexFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        $value = Utils::toString($value);
+        $value = mb_strtolower($value);
+
+        if (Utils::isZeroPrefixed($value)) {
+            return $value;
+        } else {
+            $value = Utils::toHex($value, true);
+        }
+        return $value;
+    }
+}

+ 23 - 0
extend/blockchain/web3/src/Formatters/IFormatter.php

@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+interface IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value);
+}

+ 44 - 0
extend/blockchain/web3/src/Formatters/IntegerFormatter.php

@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+
+class IntegerFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        $value = (string) $value;
+        $arguments = func_get_args();
+        $digit = 64;
+
+        if (isset($arguments[1]) && is_numeric($arguments[1])) {
+            $digit = intval($arguments[1]);
+        }
+        $bn = Utils::toBn($value);
+        $bnHex = $bn->toHex(true);
+        $padded = mb_substr($bnHex, 0, 1);
+
+        if ($padded !== 'f') {
+            $padded = '0';
+        }        
+        return implode('', array_fill(0, $digit-mb_strlen($bnHex), $padded)) . $bnHex;
+    }
+}

+ 34 - 0
extend/blockchain/web3/src/Formatters/NumberFormatter.php

@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+
+class NumberFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return int
+     */
+    public static function format($value)
+    {
+        $value = Utils::toString($value);
+        $bn = Utils::toBn($value);
+        $int = (int) $bn->toString();
+
+        return $int;
+    }
+}

+ 35 - 0
extend/blockchain/web3/src/Formatters/OptionalQuantityFormatter.php

@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class OptionalQuantityFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        if (TagValidator::validate($value)) {
+            return $value;
+        }
+        return QuantityFormatter::format($value);
+    }
+}

+ 37 - 0
extend/blockchain/web3/src/Formatters/PostFormatter.php

@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class PostFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        if (isset($value['priority'])) {
+            $value['priority'] = QuantityFormatter::format($value['priority']);
+        }
+        if (isset($value['ttl'])) {
+            $value['ttl'] = QuantityFormatter::format($value['ttl']);
+        }
+        return $value;
+    }
+}

+ 47 - 0
extend/blockchain/web3/src/Formatters/QuantityFormatter.php

@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+
+class QuantityFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        $value = Utils::toString($value);
+
+        if (Utils::isZeroPrefixed($value)) {
+            // test hex with zero ahead, hardcode 0x0
+            if ($value === '0x0' || strpos($value, '0x0') !== 0) {
+                return $value;
+            }
+            $hex = preg_replace('/^0x0+(?!$)/', '', $value);
+        } else {
+            $bn = Utils::toBn($value);
+            $hex = $bn->toHex(true);
+        }
+        if (empty($hex)) {
+            $hex = '0';
+        } else {
+            $hex = preg_replace('/^0+(?!$)/', '', $hex);
+        }
+        return '0x' . $hex;
+    }
+}

+ 30 - 0
extend/blockchain/web3/src/Formatters/StringFormatter.php

@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+
+class StringFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        return Utils::toString($value);
+    }
+}

+ 47 - 0
extend/blockchain/web3/src/Formatters/TransactionFormatter.php

@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Formatters;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Utils;
+use blockchain\web3\src\Formatters\IFormatter;
+use blockchain\web3\src\Formatters\HexFormatter;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class TransactionFormatter implements IFormatter
+{
+    /**
+     * format
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    public static function format($value)
+    {
+        if (isset($value['gas'])) {
+            $value['gas'] = QuantityFormatter::format($value['gas']);
+        }
+        if (isset($value['gasPrice'])) {
+            $value['gasPrice'] = QuantityFormatter::format($value['gasPrice']);
+        }
+        if (isset($value['value'])) {
+            $value['value'] = QuantityFormatter::format($value['value']);
+        }
+        if (isset($value['data'])) {
+            $value['data'] = HexFormatter::format($value['data']);
+        }
+        if (isset($value['nonce'])) {
+            $value['nonce'] = QuantityFormatter::format($value['nonce']);
+        }
+        return $value;
+    }
+}

+ 57 - 0
extend/blockchain/web3/src/Methods/Eth/Accounts.php

@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use blockchain\web3\src\Methods\EthMethod;
+
+class Accounts extends EthMethod
+{
+  /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 60 - 0
extend/blockchain/web3/src/Methods/Eth/BlockNumber.php

@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class BlockNumber extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 70 - 0
extend/blockchain/web3/src/Methods/Eth/Call.php

@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Validators\CallValidator;
+use blockchain\web3\src\Formatters\TransactionFormatter;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+
+class Call extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        CallValidator::class, [
+            TagValidator::class, QuantityValidator::class
+        ]
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        TransactionFormatter::class, OptionalQuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [
+        1 => 'latest'
+    ];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Eth/Coinbase.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class Coinbase extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+    
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/CompileLLL.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\StringValidator;
+use blockchain\web3\src\Formatters\StringFormatter;
+
+class CompileLLL extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        StringValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        StringFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/CompileSerpent.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\StringValidator;
+use blockchain\web3\src\Formatters\StringFormatter;
+
+class CompileSerpent extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        StringValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        StringFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/CompileSolidity.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\StringValidator;
+use blockchain\web3\src\Formatters\StringFormatter;
+
+class CompileSolidity extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        StringValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        StringFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 67 - 0
extend/blockchain/web3/src/Methods/Eth/EstimateGas.php

@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TransactionValidator;
+use blockchain\web3\src\Formatters\TransactionFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class EstimateGas extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        TransactionValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        TransactionFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 61 - 0
extend/blockchain/web3/src/Methods/Eth/GasPrice.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class GasPrice extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 74 - 0
extend/blockchain/web3/src/Methods/Eth/GetBalance.php

@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Validators\AddressValidator;
+use blockchain\web3\src\Formatters\AddressFormatter;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class GetBalance extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        AddressValidator::class, [
+            TagValidator::class, QuantityValidator::class
+        ]
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        AddressFormatter::class, OptionalQuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [
+        1 => 'latest'
+    ];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 66 - 0
extend/blockchain/web3/src/Methods/Eth/GetBlockByHash.php

@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\BlockHashValidator;
+use blockchain\web3\src\Validators\BooleanValidator;
+use blockchain\web3\src\Formatters\HexFormatter;
+use blockchain\web3\src\Formatters\BooleanFormatter;
+
+class GetBlockByHash extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        BlockHashValidator::class, BooleanValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        HexFormatter::class, BooleanFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 71 - 0
extend/blockchain/web3/src/Methods/Eth/GetBlockByNumber.php

@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\BooleanValidator;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+use blockchain\web3\src\Formatters\BooleanFormatter;
+
+class GetBlockByNumber extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        [
+            QuantityValidator::class, TagValidator::class
+        ], BooleanValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        OptionalQuantityFormatter::class, BooleanFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [
+        0 => 'latest'
+    ];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 67 - 0
extend/blockchain/web3/src/Methods/Eth/GetBlockTransactionCountByHash.php

@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\BlockHashValidator;
+use blockchain\web3\src\Formatters\HexFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class GetBlockTransactionCountByHash extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        BlockHashValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        HexFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BignumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 69 - 0
extend/blockchain/web3/src/Methods/Eth/GetBlockTransactionCountByNumber.php

@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class GetBlockTransactionCountByNumber extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        OptionalQuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [
+        'latest'
+    ];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 71 - 0
extend/blockchain/web3/src/Methods/Eth/GetCode.php

@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Validators\AddressValidator;
+use blockchain\web3\src\Formatters\AddressFormatter;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+
+class GetCode extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        AddressValidator::class, [
+            TagValidator::class, QuantityValidator::class
+        ]
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        AddressFormatter::class, OptionalQuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [
+        1 => 'latest'
+    ];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Eth/GetCompilers.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class GetCompilers extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/GetFilterChanges.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class GetFilterChanges extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/GetFilterLogs.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class GetFilterLogs extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 61 - 0
extend/blockchain/web3/src/Methods/Eth/GetLogs.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\FilterValidator;
+
+class GetLogs extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        FilterValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 72 - 0
extend/blockchain/web3/src/Methods/Eth/GetStorageAt.php

@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Validators\AddressValidator;
+use blockchain\web3\src\Formatters\AddressFormatter;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+
+class GetStorageAt extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        AddressValidator::class, QuantityValidator::class, [
+            TagValidator::class, QuantityValidator::class
+        ]
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        AddressFormatter::class, QuantityFormatter::class, OptionalQuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [
+        2 => 'latest'
+    ];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 66 - 0
extend/blockchain/web3/src/Methods/Eth/GetTransactionByBlockHashAndIndex.php

@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\BlockHashValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\HexFormatter;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class GetTransactionByBlockHashAndIndex extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        BlockHashValidator::class, QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        HexFormatter::class, QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 68 - 0
extend/blockchain/web3/src/Methods/Eth/GetTransactionByBlockNumberAndIndex.php

@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class GetTransactionByBlockNumberAndIndex extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        [
+            TagValidator::class, QuantityValidator::class
+        ], QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        OptionalQuantityFormatter::class, QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/GetTransactionByHash.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\BlockHashValidator;
+use blockchain\web3\src\Formatters\HexFormatter;
+
+class GetTransactionByHash extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        BlockHashValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        HexFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 74 - 0
extend/blockchain/web3/src/Methods/Eth/GetTransactionCount.php

@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Validators\AddressValidator;
+use blockchain\web3\src\Formatters\AddressFormatter;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class GetTransactionCount extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        AddressValidator::class, [
+            TagValidator::class, QuantityValidator::class
+        ]
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        AddressFormatter::class, OptionalQuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [
+        1 => 'latest'
+    ];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/GetTransactionReceipt.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\BlockHashValidator;
+use blockchain\web3\src\Formatters\HexFormatter;
+
+class GetTransactionReceipt extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        BlockHashValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        HexFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 66 - 0
extend/blockchain/web3/src/Methods/Eth/GetUncleByBlockHashAndIndex.php

@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\BlockHashValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\HexFormatter;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class GetUncleByBlockHashAndIndex extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        BlockHashValidator::class, QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        HexFormatter::class, QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 68 - 0
extend/blockchain/web3/src/Methods/Eth/GetUncleByBlockNumberAndIndex.php

@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class GetUncleByBlockNumberAndIndex extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        [
+            TagValidator::class, QuantityValidator::class
+        ], QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        OptionalQuantityFormatter::class, QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 67 - 0
extend/blockchain/web3/src/Methods/Eth/GetUncleCountByBlockHash.php

@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\BlockHashValidator;
+use blockchain\web3\src\Formatters\HexFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class GetUncleCountByBlockHash extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        BlockHashValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        HexFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 72 - 0
extend/blockchain/web3/src/Methods/Eth/GetUncleCountByBlockNumber.php

@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TagValidator;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\OptionalQuantityFormatter;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class GetUncleCountByBlockNumber extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        [
+            TagValidator::class, QuantityValidator::class
+        ]
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        OptionalQuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [
+        'latest'
+    ];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Eth/GetWork.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class GetWork extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 61 - 0
extend/blockchain/web3/src/Methods/Eth/Hashrate.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class Hashrate extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+    
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Eth/Mining.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class Mining extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+    
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/NewBlockFilter.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class NewBlockFilter extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 61 - 0
extend/blockchain/web3/src/Methods/Eth/NewFilter.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\FilterValidator;
+
+class NewFilter extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        FilterValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Eth/NewPendingTransactionFilter.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class NewPendingTransactionFilter extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 61 - 0
extend/blockchain/web3/src/Methods/Eth/ProtocolVersion.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class ProtocolVersion extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/SendRawTransaction.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\HexValidator;
+use blockchain\web3\src\Formatters\HexFormatter;
+
+class SendRawTransaction extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        HexValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        HexFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/SendTransaction.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\TransactionValidator;
+use blockchain\web3\src\Formatters\TransactionFormatter;
+
+class SendTransaction extends EthMethod
+{
+   /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        TransactionValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        TransactionFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 66 - 0
extend/blockchain/web3/src/Methods/Eth/Sign.php

@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\AddressValidator;
+use blockchain\web3\src\Validators\HexValidator;
+use blockchain\web3\src\Formatters\AddressFormatter;
+use blockchain\web3\src\Formatters\HexFormatter;
+
+class Sign extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        AddressValidator::class, HexValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        AddressFormatter::class, HexFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 61 - 0
extend/blockchain/web3/src/Methods/Eth/SubmitHashrate.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\BlockHashValidator;
+
+class SubmitHashrate extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        BlockHashValidator::class, BlockHashValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 65 - 0
extend/blockchain/web3/src/Methods/Eth/SubmitWork.php

@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\NonceValidator;
+use blockchain\web3\src\Validators\BlockHashValidator;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class SubmitWork extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        NonceValidator::class, BlockHashValidator::class, BlockHashValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Eth/Syncing.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class Syncing extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 64 - 0
extend/blockchain/web3/src/Methods/Eth/UninstallFilter.php

@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Eth;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Validators\QuantityValidator;
+use blockchain\web3\src\Formatters\QuantityFormatter;
+
+class UninstallFilter extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [
+        QuantityValidator::class
+    ];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [
+        QuantityFormatter::class
+    ];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 158 - 0
extend/blockchain/web3/src/Methods/EthMethod.php

@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods;
+
+use InvalidArgumentException;
+use RuntimeException;
+use blockchain\web3\src\Methods\IMethod;
+use blockchain\web3\src\Methods\JSONRPC;
+
+class EthMethod extends JSONRPC implements IMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+
+    /**
+     * getInputFormatters
+     * 
+     * @return array
+     */
+    public function getInputFormatters()
+    {
+        return $this->inputFormatters;
+    }
+
+    /**
+     * getOutputFormatters
+     * 
+     * @return array
+     */
+    public function getOutputFormatters()
+    {
+        return $this->outputFormatters;
+    }
+
+    /**
+     * validate
+     * 
+     * @param array $params
+     * @return bool
+     */
+    public function validate(&$params)
+    {
+        if (!is_array($params)) {
+            throw new InvalidArgumentException('Please use array params when call validate.');
+        }
+        $rules = $this->validators;
+
+        if (count($params) < count($rules)) {
+            if (!isset($this->defaultValues) || empty($this->defaultValues)) {
+                throw new InvalidArgumentException('The params are less than validators.');
+            }
+            $defaultValues = $this->defaultValues;
+
+            foreach ($defaultValues as $key => $value) {
+                if (!isset($params[$key])) {
+                    $params[$key] = $value;
+                }
+
+            }
+        } elseif (count($params) > count($rules)) {
+            throw new InvalidArgumentException('The params are more than validators.');
+        }
+        foreach ($rules as $key => $rule) {
+            if (isset($params[$key])) {
+                if (is_array($rule)) {
+                    $isError = true;
+
+                    foreach ($rule as $subRule) {
+                        if (call_user_func([$subRule, 'validate'], $params[$key]) === true) {
+                            $isError = false;
+                            break;
+                        }
+                    }
+                    if ($isError) {
+                        throw new RuntimeException('Wrong type of ' . $this->method . ' method argument ' . $key . '.');
+                    }
+                } else {
+                    if (call_user_func([$rule, 'validate'], $params[$key]) === false) {
+                        throw new RuntimeException('Wrong type of ' . $this->method . ' method argument ' . $key . '.');
+                    }
+                }
+            } else {
+                throw new RuntimeException($this->method . ' method argument ' . $key . ' doesn\'t have default value.');
+            }
+        }
+        return true;
+    }
+
+    /**
+     * transform
+     * 
+     * @param array $params
+     * @param array $rules
+     * @return array
+     */
+    public function transform($params, $rules)
+    {
+        if (!is_array($params)) {
+            throw new InvalidArgumentException('Please use array params when call transform.');
+        }
+        if (!is_array($rules)) {
+            throw new InvalidArgumentException('Please use array rules when call transform.');
+        }
+        foreach ($params as $key => $param) {
+            if (isset($rules[$key])) {
+                $formatted = call_user_func([$rules[$key], 'format'], $param);
+                $params[$key] = $formatted;
+            }
+        }
+        return $params;
+    }
+}

+ 24 - 0
extend/blockchain/web3/src/Methods/IMethod.php

@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods;
+
+interface IMethod
+{
+    /**
+     * transform
+     * 
+     * @param array &$data
+     * @param array $rules
+     * @return array
+     */
+    public function transform($data, $rules);
+}

+ 29 - 0
extend/blockchain/web3/src/Methods/IRPC.php

@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods;
+
+interface IRPC
+{
+    /**
+     * __toString
+     * 
+     * @return array
+     */
+    public function __toString();
+
+    /**
+     * toPayload
+     * 
+     * @return array
+     */
+    public function toPayload();
+}

+ 215 - 0
extend/blockchain/web3/src/Methods/JSONRPC.php

@@ -0,0 +1,215 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\IRPC;
+
+class JSONRPC implements IRPC
+{
+    /**
+     * id
+     * 
+     * @var int
+     */
+    protected $id = 0;
+
+    /**
+     * rpcVersion
+     * 
+     * @var string
+     */
+    protected $rpcVersion = '2.0';
+
+    /**
+     * method
+     * 
+     * @var string
+     */
+    protected $method = '';
+
+    /**
+     * arguments
+     * 
+     * @var array
+     */
+    protected $arguments = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    public function __construct($method, $arguments)
+    {
+        $this->method = $method;
+        $this->arguments = $arguments;
+    }
+
+    /**
+     * get
+     * 
+     * @param string $name
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        $method = 'get' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], []);
+        }
+        return false;
+    }
+
+    /**
+     * set
+     * 
+     * @param string $name
+     * @param mixed $value
+     * @return mixed
+     */
+    public function __set($name, $value)
+    {
+        $method = 'set' . ucfirst($name);
+
+        if (method_exists($this, $method)) {
+            return call_user_func_array([$this, $method], [$value]);
+        }
+        return false;
+    }
+
+    /**
+     * __toString
+     * 
+     * @return string
+     */
+    public function __toString()
+    {
+        $payload = $this->toPayload();
+
+        return json_encode($payload);
+    }
+
+    /**
+     * setId
+     * 
+     * @param int $id
+     * @return bool
+     */
+    public function setId($id)
+    {
+        if (!is_int($id)) {
+            throw new InvalidArgumentException('Id must be integer.');
+        }
+        $this->id = $id;
+
+        return true;
+    }
+
+    /**
+     * getId
+     * 
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * getRpcVersion
+     * 
+     * @return string
+     */
+    public function getRpcVersion()
+    {
+        return $this->rpcVersion;
+    }
+
+    /**
+     * getMethod
+     * 
+     * @return string
+     */
+    public function getMethod()
+    {
+        return $this->method;
+    }
+
+    /**
+     * setArguments
+     * 
+     * @param array $arguments
+     * @return bool
+     */
+    public function setArguments($arguments)
+    {
+        if (!is_array($arguments)) {
+            throw new InvalidArgumentException('Please use array when call setArguments.');
+        }
+        $this->arguments = $arguments;
+
+        return true;
+    }
+
+    /**
+     * getArguments
+     * 
+     * @return array
+     */
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    /**
+     * toPayload
+     * 
+     * @return array
+     */
+    public function toPayload()
+    {
+        if (empty($this->method) || !is_string($this->method)) {
+            throw new InvalidArgumentException('Please check the method set properly.');
+        }
+        if (empty($this->id)) {
+            $id = rand();
+        } else {
+            $id = $this->id;
+        }
+        $rpc = [
+            'id' => $id,
+            'jsonrpc' => $this->rpcVersion,
+            'method' => $this->method
+        ];
+
+        if (count($this->arguments) > 0) {
+            $rpc['params'] = $this->arguments;
+        }
+        return $rpc;
+    }
+
+    /**
+     * toPayloadString
+     * 
+     * @return string
+     */
+    public function toPayloadString()
+    {
+        $payload = $this->toPayload();
+
+        return json_encode($payload);
+    }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Net/Listening.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Net;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class Listening extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 61 - 0
extend/blockchain/web3/src/Methods/Net/PeerCount.php

@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Net;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+use blockchain\web3\src\Formatters\BigNumberFormatter;
+
+class PeerCount extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [
+        BigNumberFormatter::class
+    ];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Net/Version.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Net;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class Version extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

+ 58 - 0
extend/blockchain/web3/src/Methods/Personal/ListAccounts.php

@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of web3.php package.
+ * 
+ * (c) Kuan-Cheng,Lai <alk03073135@gmail.com>
+ * 
+ * @author Peter Lai <alk03073135@gmail.com>
+ * @license MIT
+ */
+
+namespace blockchain\web3\src\Methods\Personal;
+
+use InvalidArgumentException;
+use blockchain\web3\src\Methods\EthMethod;
+
+class ListAccounts extends EthMethod
+{
+    /**
+     * validators
+     * 
+     * @var array
+     */
+    protected $validators = [];
+
+    /**
+     * inputFormatters
+     * 
+     * @var array
+     */
+    protected $inputFormatters = [];
+
+    /**
+     * outputFormatters
+     * 
+     * @var array
+     */
+    protected $outputFormatters = [];
+
+    /**
+     * defaultValues
+     * 
+     * @var array
+     */
+    protected $defaultValues = [];
+
+    /**
+     * construct
+     * 
+     * @param string $method
+     * @param array $arguments
+     * @return void
+     */
+    // public function __construct($method='', $arguments=[])
+    // {
+    //     parent::__construct($method, $arguments);
+    // }
+}

Некоторые файлы не были показаны из-за большого количества измененных файлов