├── .editorconfig ├── LICENSE ├── composer.json └── lib └── Etherscan ├── APIConf.php ├── Api ├── AbstractApi.php ├── Account.php ├── ApiInterface.php ├── Block.php ├── Contract.php ├── EventLog.php ├── Gas.php ├── Proxy.php ├── Stats.php ├── Token.php ├── Transaction.php └── Websocket.php ├── Client.php ├── Exception ├── ErrorException.php ├── ExceptionInterface.php └── InvalidArgumentException.php ├── Helper └── UtilityHelper.php └── HttpClient ├── HttpClientInterface.php └── Request.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.yml] 12 | indent_style = space 13 | indent_size = 2 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2018-2021 Maslakou Ihar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "maslakoff/php-etherscan-api", 3 | "type": "library", 4 | "description": "PHP client for the Etherscan API", 5 | "homepage": "https://github.com/maslakoff/php-etherscan-api", 6 | "keywords": ["etherscan", "ethereum", "api", "EtherScan.io"], 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Maslakou Ihar", 11 | "email": "igormaslakoff@gmail.com", 12 | "homepage": "https://github.com/maslakoff" 13 | } 14 | ], 15 | "support": { 16 | "email": "igormaslakoff@gmail.com" 17 | }, 18 | "require": { 19 | "php": "^5.6 || ^7.0 || ^8.0" 20 | }, 21 | "require-dev": { 22 | "phpunit/phpunit": "^5.5 || ^6.0", 23 | "mockery/mockery": "~0.8", 24 | "guzzlehttp/guzzle": "~5.0" 25 | }, 26 | "autoload": { 27 | "psr-4": { "Etherscan\\": "lib/Etherscan/" } 28 | }, 29 | "autoload-dev": { 30 | "psr-4": { "Etherscan\\Tests\\": "tests/Etherscan/"} 31 | }, 32 | "minimum-stability": "dev", 33 | "prefer-stable": true 34 | } 35 | -------------------------------------------------------------------------------- /lib/Etherscan/APIConf.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class APIConf 11 | { 12 | const API_URL = "https://api.etherscan.io/api"; 13 | const API_URL_BSCSCAN = 'https://api.bscscan.com/api'; 14 | 15 | const TESTNET_GOERLI = "api-goerli"; 16 | const TESTNET_ROPSTEN = "api-ropsten"; 17 | const TESTNET_KOVAN = "api-kovan"; 18 | const TESTNET_RINKEBY = "api-rinkeby"; 19 | 20 | const NET_BSC = 'api-bscscan'; 21 | 22 | const TAG_EARLIEST = "earliest"; 23 | const TAG_LATEST = "latest"; 24 | const TAG_PENDING = "pending"; 25 | 26 | const BLOCK_TYPE_BLOCKS = "blocks"; 27 | const BLOCK_TYPE_UNCLES = "uncles"; 28 | 29 | const BLOCK_CLOSEST_BEFORE = "before"; 30 | const BLOCK_CLOSEST_AFTER = "after"; 31 | 32 | public static $blockTypes = [ 33 | self::BLOCK_TYPE_BLOCKS, self::BLOCK_TYPE_UNCLES 34 | ]; 35 | 36 | const CLIENT_TYPE_GETH = "geth"; 37 | const CLIENT_TYPE_PARITY = "parity"; 38 | public static $clientTypes = [ 39 | self::CLIENT_TYPE_GETH, self::CLIENT_TYPE_PARITY 40 | ]; 41 | 42 | const SYNC_MODE_DEFAULT = "default"; 43 | const SYNC_MODE_ARCHIVE = "archive"; 44 | public static $syncModes = [ 45 | self::SYNC_MODE_DEFAULT, self::SYNC_MODE_ARCHIVE 46 | ]; 47 | 48 | /** 49 | * Returns API URL 50 | * 51 | * @param null $net 52 | * @return string 53 | */ 54 | public static function getAPIUrl($net = null) 55 | { 56 | if (is_null($net)) { 57 | return self::API_URL; 58 | } 59 | else if($net === self::NET_BSC) { 60 | return self::API_URL_BSCSCAN; 61 | } 62 | 63 | return "https://{$net}.etherscan.io/api"; 64 | } 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /lib/Etherscan/Api/AbstractApi.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | abstract class AbstractApi implements ApiInterface 14 | { 15 | /** 16 | * The client. 17 | * 18 | * @var Client 19 | */ 20 | protected $client; 21 | 22 | /** 23 | * @var Request 24 | */ 25 | protected $request; 26 | 27 | /** 28 | * @param Client $client 29 | */ 30 | public function __construct(Client $client) 31 | { 32 | $this->client = $client; 33 | 34 | $this->request = new Request($client->getApiKeyToken(), $client->getNetName()); 35 | } 36 | } -------------------------------------------------------------------------------- /lib/Etherscan/Api/Account.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class Account extends AbstractApi 16 | { 17 | /** 18 | * Get Ether Balance for a single Address 19 | * 20 | * @param $address 21 | * @param $tag 22 | * @return mixed 23 | * @throws ErrorException 24 | */ 25 | public function balance($address, $tag = APIConf::TAG_LATEST) 26 | { 27 | return $this->request->exec([ 28 | 'module' => "account", 29 | 'action' => "balance", 30 | 'address' => $address, 31 | 'tag' => $tag 32 | ]); 33 | } 34 | 35 | /** 36 | * Get Ether Balance for multiple Addresses in a single call. 37 | * 38 | * @param string $addresses Ether address. 39 | * @param string $tag 40 | * 41 | * @return array 42 | * @throws ErrorException 43 | */ 44 | public function balanceMulti($addresses, $tag = APIConf::TAG_LATEST) 45 | { 46 | if (is_array($addresses)) { 47 | $addresses = implode(",", $addresses); 48 | } 49 | 50 | return $this->request->exec([ 51 | 'module' => "account", 52 | 'action' => "balancemulti", 53 | 'address' => $addresses, 54 | 'tag' => $tag 55 | ]); 56 | } 57 | 58 | /** 59 | * Get a list of 'Normal' Transactions by Address 60 | * (Returns up to a maximum of the last 10000 transactions only). 61 | * 62 | * @param string $address Ether address. 63 | * @param int $startBlock Starting blockNo to retrieve results 64 | * @param int $endBlock Ending blockNo to retrieve results 65 | * @param string $sort 'asc' or 'desc' 66 | * @param int $page Page number 67 | * @param int $offset Offset 68 | * 69 | * @return array 70 | * @throws ErrorException 71 | */ 72 | public function transactionListByAddress($address, $startBlock = 0, $endBlock = 99999999, $sort = "asc", $page = null, $offset = null) 73 | { 74 | $params = [ 75 | 'module' => "account", 76 | 'action' => "txlist", 77 | 'address' => $address, 78 | 'startblock' => $startBlock, 79 | 'endblock' => $endBlock, 80 | 'sort' => $sort 81 | ]; 82 | 83 | if (!is_null($page)) { 84 | $params['page'] = (int)$page; 85 | } 86 | 87 | if (!is_null($offset)) { 88 | $params['offset'] = (int)$offset; 89 | } 90 | 91 | return $this->request->exec($params); 92 | } 93 | 94 | /** 95 | * Get a list of 'Internal' Transactions by Address 96 | * (Returns up to a maximum of the last 10000 transactions only). 97 | * 98 | * @param string $address Ether address. 99 | * @param int $startBlock Starting blockNo to retrieve results 100 | * @param int $endBlock Ending blockNo to retrieve results 101 | * @param string $sort 'asc' or 'desc' 102 | * @param int $page Page number 103 | * @param int $offset Offset 104 | * 105 | * @return array 106 | * @throws ErrorException 107 | */ 108 | public function transactionListInternalByAddress($address, $startBlock = 0, $endBlock = 99999999, $sort = "asc", $page = null, $offset = null) 109 | { 110 | $params = [ 111 | 'module' => "account", 112 | 'action' => "txlistinternal", 113 | 'address' => $address, 114 | 'startblock' => $startBlock, 115 | 'endblock' => $endBlock, 116 | 'sort' => $sort 117 | ]; 118 | 119 | if (!is_null($page)) { 120 | $params['page'] = (int)$page; 121 | } 122 | 123 | if (!is_null($offset)) { 124 | $params['offset'] = (int)$offset; 125 | } 126 | 127 | return $this->request->exec($params); 128 | } 129 | 130 | /** 131 | * Get a list of 'ERC20 - Token Transfer Events' by Address 132 | * 133 | * Usage: 134 | * ERC-20 transfers from an address, specify the address parameter 135 | * ERC-20 transfers from a contract address, specify the contract address parameter 136 | * ERC-20 transfers from an address filtered by a token contract, specify both address and contract address parameters. 137 | * 138 | * @param string $address representing the address to check for balance 139 | * @param int $contractAddress representing the token contract address to check for balance 140 | * @param string $sort 'asc' or 'desc' 141 | * @param int $page Page number 142 | * @param int $offset Offset 143 | * 144 | * @throws InvalidArgumentException if missed address 145 | * 146 | * @return array 147 | * @throws ErrorException 148 | */ 149 | public function tokenERC20TransferListByAddress($address = null, $contractAddress = null, $sort = "asc", $page = null, $offset = null, $startblock = null, $endblock = null) 150 | { 151 | if (is_null($address) && is_null($contractAddress)) { 152 | throw new InvalidArgumentException('Please specify at least one address'); 153 | } 154 | 155 | $params = [ 156 | 'module' => "account", 157 | 'action' => "tokentx", 158 | 'sort' => $sort 159 | ]; 160 | 161 | if (!is_null($address)) { 162 | $params['address'] = $address; 163 | } 164 | 165 | if (!is_null($contractAddress)) { 166 | $params['contractaddress'] = $contractAddress; 167 | } 168 | 169 | if (!is_null($page)) { 170 | $params['page'] = (int)$page; 171 | } 172 | 173 | if (!is_null($offset)) { 174 | $params['offset'] = (int)$offset; 175 | } 176 | 177 | if (!is_null($startblock)) { 178 | $params['startblock'] = (int)$startblock; 179 | } 180 | 181 | if (!is_null($endblock)) { 182 | $params['endblock'] = (int)$endblock; 183 | } 184 | 185 | return $this->request->exec($params); 186 | } 187 | 188 | /** 189 | * Get a list of 'ERC721 - Token Transfer Events' by Address 190 | * 191 | * Usage: 192 | * ERC-721 transfers from an address, specify the address parameter 193 | * ERC-721 transfers from a contract address, specify the contract address parameter 194 | * ERC-721 transfers from an address filtered by a token contract, specify both address and contract address parameters. 195 | * 196 | * @param string $address representing the address to check for balance 197 | * @param int $contractAddress representing the token contract address to check for balance 198 | * @param string $sort 'asc' or 'desc' 199 | * @param int $page Page number 200 | * @param int $offset Offset 201 | * @param int $startBlock Starting blockNo to retrieve results 202 | * @param int $endBlock Ending blockNo to retrieve results 203 | * 204 | * @throws InvalidArgumentException if missed address 205 | * 206 | * @return array 207 | * @throws ErrorException 208 | */ 209 | public function tokenERC721TransferListByAddress($address = null, $contractAddress = null, $sort = "asc", $page = null, $offset = null, $startBlock = 0, $endBlock = 99999999) 210 | { 211 | if (is_null($address) && is_null($contractAddress)) { 212 | throw new InvalidArgumentException('Please specify at least one address'); 213 | } 214 | 215 | $params = [ 216 | 'module' => "account", 217 | 'action' => "tokennfttx", 218 | 'startblock' => $startBlock, 219 | 'endblock' => $endBlock, 220 | 'sort' => $sort 221 | ]; 222 | 223 | if (!is_null($address)) { 224 | $params['address'] = $address; 225 | } 226 | 227 | if (!is_null($contractAddress)) { 228 | $params['contractaddress'] = $contractAddress; 229 | } 230 | 231 | if (!is_null($page)) { 232 | $params['page'] = (int)$page; 233 | } 234 | 235 | if (!is_null($offset)) { 236 | $params['offset'] = (int)$offset; 237 | } 238 | 239 | return $this->request->exec($params); 240 | } 241 | 242 | /** 243 | * Get "Internal Transactions" by Transaction Hash. 244 | * 245 | * @param string $transactionHash 246 | * 247 | * @return array 248 | * @throws ErrorException 249 | */ 250 | public function transactionListInternalByHash($transactionHash) 251 | { 252 | return $this->request->exec([ 253 | 'module' => "account", 254 | 'action' => "txlistinternal", 255 | 'txhash' => $transactionHash 256 | ]); 257 | } 258 | 259 | /** 260 | * Get "Internal Transactions" by Block Range 261 | * 262 | * @param int $startBlock Starting blockNo to retrieve results 263 | * @param int $endBlock Ending blockNo to retrieve results 264 | * @param string $sort 'asc' or 'desc' 265 | * @param int $page Page number 266 | * @param int $offset Offset 267 | * 268 | * @return array 269 | * @throws ErrorException 270 | */ 271 | public function transactionListInternalByBlockRange($startBlock = 0, $endBlock = 99999999, $sort = "asc", $page = null, $offset = null) 272 | { 273 | $params = [ 274 | 'module' => "account", 275 | 'action' => "txlistinternal", 276 | 'startblock' => $startBlock, 277 | 'endblock' => $endBlock, 278 | 'sort' => $sort 279 | ]; 280 | 281 | if (!is_null($page)) { 282 | $params['page'] = (int)$page; 283 | } 284 | 285 | if (!is_null($offset)) { 286 | $params['offset'] = (int)$offset; 287 | } 288 | 289 | return $this->request->exec($params); 290 | } 291 | 292 | /** 293 | * Get list of Blocks Mined by Address. 294 | * 295 | * @param string $address Ether address 296 | * @param string $blockType "blocks" or "uncles" 297 | * @param int $page Page number 298 | * @param int $offset Offset 299 | * 300 | * @return array 301 | * @throws ErrorException 302 | */ 303 | public function getMinedBlocks($address, $blockType = APIConf::BLOCK_TYPE_BLOCKS, $page = null, $offset = null) 304 | { 305 | if (!in_array($blockType, APIConf::$blockTypes)) { 306 | throw new ErrorException("Invalid block type"); 307 | } 308 | 309 | $params = [ 310 | 'module' => "account", 311 | 'action' => "getminedblocks", 312 | 'address' => $address, 313 | 'blocktype' => $blockType, 314 | ]; 315 | 316 | if (!is_null($page)) { 317 | $params['page'] = (int)$page; 318 | } 319 | 320 | if (!is_null($offset)) { 321 | $params['offset'] = (int)$offset; 322 | } 323 | 324 | return $this->request->exec($params); 325 | } 326 | 327 | 328 | /** 329 | * Get Token Account Balance by known TokenName (Supported TokenNames: DGD, 330 | * MKR, FirstBlood, HackerGold, ICONOMI, Pluton, REP, SNGLS). 331 | * 332 | * or 333 | * 334 | * for TokenContractAddress. 335 | * 336 | * @param string $tokenIdentifier Token name from the list or contract address. 337 | * @param string $address Ether address. 338 | * @param string $tag 339 | * 340 | * @return array 341 | * @throws ErrorException 342 | * 343 | * @deprecated deprecated since version 1.0.1 344 | */ 345 | public function tokenBalance($tokenIdentifier, $address, $tag = APIConf::TAG_LATEST) 346 | { 347 | $params = [ 348 | 'module' => "account", 349 | 'action' => "tokenbalance", 350 | 'address' => $address, 351 | 'tag' => $tag 352 | ]; 353 | 354 | if (strlen($tokenIdentifier) === 42) { 355 | $params['contractaddress'] = $tokenIdentifier; 356 | } else { 357 | $params['tokenname'] = $tokenIdentifier; 358 | } 359 | 360 | return $this->request->exec($params); 361 | } 362 | 363 | /** 364 | * Get Historical Ether Balance for a Single Address By BlockNo 365 | * 366 | * @param string $address the string representing the address to check for balance 367 | * @param string $blockNumber the integer block number to check balance for eg. 12697906​ 368 | * 369 | * @return array 370 | * @throws \Etherscan\Exception\ErrorException 371 | */ 372 | public function getBalanceHistory($address, $blockNumber) { 373 | return $this->request->exec([ 374 | 'module' => "account", 375 | 'action' => "balancehistory", 376 | 'address' => $address, 377 | 'blockno' => $blockNumber 378 | ]); 379 | } 380 | } 381 | -------------------------------------------------------------------------------- /lib/Etherscan/Api/ApiInterface.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | interface ApiInterface 11 | { 12 | 13 | } -------------------------------------------------------------------------------- /lib/Etherscan/Api/Block.php: -------------------------------------------------------------------------------- 1 | request->exec([ 22 | 'module' => "block", 23 | 'action' => "getblockreward", 24 | 'blockno' => $blockNumber 25 | ]); 26 | } 27 | 28 | /** 29 | * Get Estimated Block Countdown Time by BlockNo. 30 | * 31 | * @param int $blockNumber block number to estimate time remaining to be mined 32 | * 33 | * @return array 34 | * @throws \Etherscan\Exception\ErrorException 35 | */ 36 | public function getBlockCountdown($blockNumber) 37 | { 38 | return $this->request->exec([ 39 | 'module' => "block", 40 | 'action' => "getblockcountdown", 41 | 'blockno' => $blockNumber 42 | ]); 43 | } 44 | 45 | /** 46 | * Get Block Number by Timestamp 47 | * 48 | * @param int $timestamp Unix timestamp in seconds 49 | * @param string $closest the closest available block to the provided timestamp 50 | * 51 | * @return array 52 | * @throws \Etherscan\Exception\ErrorException 53 | */ 54 | public function getBlockNumberByTimestamp($timestamp, $closest) 55 | { 56 | return $this->request->exec([ 57 | 'module' => "block", 58 | 'action' => "getblocknobytime", 59 | 'timestamp' => $timestamp, 60 | 'closest' => $closest 61 | ]); 62 | } 63 | 64 | /** 65 | * Get Daily Average Block Size 66 | * 67 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 68 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 69 | * @param string $sort 'asc' or 'desc' 70 | * 71 | * @return array 72 | * @throws \Etherscan\Exception\ErrorException 73 | */ 74 | public function getDailyAverageBlockSize($startdate, $enddate, $sort = "asc") 75 | { 76 | return $this->request->exec([ 77 | 'module' => "stats", 78 | 'action' => "dailyavgblocksize", 79 | 'startdate' => $startdate, 80 | 'enddate' => $enddate, 81 | 'sort' => $sort 82 | ]); 83 | } 84 | 85 | /** 86 | * Get Daily Block Count and Rewards 87 | * 88 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 89 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 90 | * @param string $sort 'asc' or 'desc' 91 | * 92 | * @return array 93 | * @throws \Etherscan\Exception\ErrorException 94 | */ 95 | public function getDailyBlockCountAndRewards($startdate, $enddate, $sort = "asc") 96 | { 97 | return $this->request->exec([ 98 | 'module' => "stats", 99 | 'action' => "dailyblkcount", 100 | 'startdate' => $startdate, 101 | 'enddate' => $enddate, 102 | 'sort' => $sort 103 | ]); 104 | } 105 | 106 | /** 107 | * Get Daily Block Rewards 108 | * 109 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 110 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 111 | * @param string $sort 'asc' or 'desc' 112 | * 113 | * @return array 114 | * @throws \Etherscan\Exception\ErrorException 115 | */ 116 | public function getDailyBlockRewards($startdate, $enddate, $sort = "asc") 117 | { 118 | return $this->request->exec([ 119 | 'module' => "stats", 120 | 'action' => "dailyblockrewards", 121 | 'startdate' => $startdate, 122 | 'enddate' => $enddate, 123 | 'sort' => $sort 124 | ]); 125 | } 126 | 127 | /** 128 | * Get Daily Average Time for A Block to be Included in the Ethereum Blockchain 129 | * 130 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 131 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 132 | * @param string $sort 'asc' or 'desc' 133 | * 134 | * @return array 135 | * @throws \Etherscan\Exception\ErrorException 136 | */ 137 | public function getDailyAverageBlockTime($startdate, $enddate, $sort = "asc") 138 | { 139 | return $this->request->exec([ 140 | 'module' => "stats", 141 | 'action' => "dailyavgblocktime", 142 | 'startdate' => $startdate, 143 | 'enddate' => $enddate, 144 | 'sort' => $sort 145 | ]); 146 | } 147 | 148 | /** 149 | * Get Daily Uncle Block Count and Rewards 150 | * 151 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 152 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 153 | * @param string $sort 'asc' or 'desc' 154 | * 155 | * @return array 156 | * @throws \Etherscan\Exception\ErrorException 157 | */ 158 | public function getDailyUncleBlockCountAndRewards($startdate, $enddate, $sort = "asc") 159 | { 160 | return $this->request->exec([ 161 | 'module' => "stats", 162 | 'action' => "dailyuncleblkcount", 163 | 'startdate' => $startdate, 164 | 'enddate' => $enddate, 165 | 'sort' => $sort 166 | ]); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /lib/Etherscan/Api/Contract.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class Contract extends AbstractApi 11 | { 12 | 13 | /** 14 | * Get Contract ABI for Verified Contract Source Codes. 15 | * (Newly verified Contracts are synched to the API servers within 5 minutes or less). 16 | * 17 | * @param string $address Ether address. 18 | * 19 | * @return array 20 | * @throws \Etherscan\Exception\ErrorException 21 | */ 22 | public function getABI($address) 23 | { 24 | return $this->request->exec([ 25 | 'module' => "contract", 26 | 'action' => "getabi", 27 | 'address' => $address 28 | ]); 29 | } 30 | 31 | /** 32 | * Get Contract ABI for Verified Contract Source Codes. 33 | * (Newly verified Contracts are synched to the API servers within 5 minutes or less). 34 | * 35 | * @param string $address Ether address. 36 | * 37 | * @return array 38 | * @throws \Etherscan\Exception\ErrorException 39 | * 40 | * @deprecated deprecated since version 1.1.1 41 | */ 42 | public function getContractABI($address) 43 | { 44 | return $this->getABI($address); 45 | } 46 | 47 | /** 48 | * Get Contract Source Code for Verified Contract Source Codes 49 | * Returns the Solidity source code of a verified smart contract. 50 | * 51 | * @param string $address Ether address. 52 | * 53 | * @return array 54 | * @throws \Etherscan\Exception\ErrorException 55 | */ 56 | public function getSourceCode($address) 57 | { 58 | return $this->request->exec([ 59 | 'module' => "contract", 60 | 'action' => "getsourcecode", 61 | 'address' => $address 62 | ]); 63 | } 64 | 65 | /** 66 | * Verify Source Code 67 | * Check Source Code Verification Submission Status 68 | * 69 | * @param string $guid Source Code GUID 70 | * 71 | * @return array 72 | * @throws \Etherscan\Exception\ErrorException 73 | */ 74 | public function checkVerifyStatus($guid) 75 | { 76 | return $this->request->exec([ 77 | 'module' => "contract", 78 | 'action' => "checkverifystatus", 79 | 'address' => $guid 80 | ]); 81 | } 82 | 83 | /** 84 | * Verify Proxy Contract 85 | * Checking Proxy Contract Verification Submission Status using cURL 86 | * 87 | * @param string $guid GUID 88 | * 89 | * @return array 90 | * @throws \Etherscan\Exception\ErrorException 91 | */ 92 | public function checkProxyVerification($guid) 93 | { 94 | return $this->request->exec([ 95 | 'module' => "contract", 96 | 'action' => "checkproxyverification", 97 | 'address' => $guid 98 | ]); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /lib/Etherscan/Api/EventLog.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class EventLog extends AbstractApi 13 | { 14 | 15 | /** 16 | * Get Event Logs 17 | * 18 | * @param $address 19 | * @param $topic 20 | * @param int $startBlock 21 | * @param string $endBlock 22 | * @return mixed 23 | * @throws \Etherscan\Exception\ErrorException 24 | */ 25 | public function getLogs($address, $topic, $startBlock = 0, $endBlock = APIConf::TAG_LATEST) 26 | { 27 | $params = [ 28 | 'module' => 'logs', 29 | 'action' => 'getLogs', 30 | 'fromBlock' => $startBlock, 31 | 'toBlock' => $endBlock, 32 | 'address' => $address, 33 | 'topic0' => $topic, 34 | ]; 35 | 36 | return $this->request->exec($params); 37 | } 38 | } -------------------------------------------------------------------------------- /lib/Etherscan/Api/Gas.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class Gas extends AbstractApi 13 | { 14 | 15 | /** 16 | * Get Estimation of Confirmation Time 17 | * Returns the estimated time, in seconds, for a transaction to be confirmed on the blockchain. 18 | * 19 | * @param $gasPrice the price paid per unit of gas, in wei 20 | * 21 | * @return mixed 22 | * @throws \Etherscan\Exception\ErrorException 23 | */ 24 | public function gasEstimate($gasPrice) 25 | { 26 | $params = [ 27 | 'module' => 'gastracker', 28 | 'action' => 'gasestimate', 29 | 'gasprice' => $gasPrice, 30 | ]; 31 | 32 | return $this->request->exec($params); 33 | } 34 | 35 | /** 36 | * Get Gas Oracle 37 | * Returns the current Safe, Proposed and Fast gas prices. 38 | * 39 | * @return mixed 40 | * @throws \Etherscan\Exception\ErrorException 41 | */ 42 | public function gasOracle() 43 | { 44 | $params = [ 45 | 'module' => 'gastracker', 46 | 'action' => 'gasoracle', 47 | ]; 48 | 49 | return $this->request->exec($params); 50 | } 51 | 52 | /** 53 | * Get Daily Average Gas Limit 54 | * Returns the historical daily average gas limit of the Ethereum network. 55 | * 56 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 57 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 58 | * @param string $sort 'asc' or 'desc' 59 | * 60 | * @return mixed 61 | * @throws \Etherscan\Exception\ErrorException 62 | */ 63 | public function getDailyAverageGasLimit($startdate, $enddate, $sort = "asc") 64 | { 65 | $params = [ 66 | 'module' => 'stats', 67 | 'action' => 'dailyavggaslimit', 68 | 'startdate' => $startdate, 69 | 'enddate' => $enddate, 70 | 'sort' => $sort 71 | ]; 72 | 73 | return $this->request->exec($params); 74 | } 75 | 76 | /** 77 | * Get Ethereum Daily Total Gas Used 78 | * Returns the total amount of gas used daily for transctions on the Ethereum network. 79 | * 80 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 81 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 82 | * @param string $sort 'asc' or 'desc' 83 | * 84 | * @return mixed 85 | * @throws \Etherscan\Exception\ErrorException 86 | */ 87 | public function getDailyTotalGasUsed($startdate, $enddate, $sort = "asc") 88 | { 89 | $params = [ 90 | 'module' => 'stats', 91 | 'action' => 'dailygasused', 92 | 'startdate' => $startdate, 93 | 'enddate' => $enddate, 94 | 'sort' => $sort 95 | ]; 96 | 97 | return $this->request->exec($params); 98 | } 99 | 100 | /** 101 | * Get Daily Average Gas Price 102 | * Returns the daily average gas price used on the Ethereum network. 103 | * 104 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 105 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 106 | * @param string $sort 'asc' or 'desc' 107 | * 108 | * @return mixed 109 | * @throws \Etherscan\Exception\ErrorException 110 | */ 111 | public function getDailyAverageGasPrice($startdate, $enddate, $sort = "asc") 112 | { 113 | $params = [ 114 | 'module' => 'stats', 115 | 'action' => 'dailyavggasprice', 116 | 'startdate' => $startdate, 117 | 'enddate' => $enddate, 118 | 'sort' => $sort 119 | ]; 120 | 121 | return $this->request->exec($params); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /lib/Etherscan/Api/Proxy.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Proxy extends AbstractApi 14 | { 15 | 16 | /** 17 | * Returns the number of most recent block 18 | * 19 | * @return array 20 | * @throws ErrorException 21 | */ 22 | public function blockNumber() 23 | { 24 | return $this->request->exec([ 25 | 'module' => "proxy", 26 | 'action' => "eth_blockNumber", 27 | ]); 28 | } 29 | 30 | /** 31 | * Returns information about a block by block number 32 | * 33 | * @param string $tag 34 | * @param booelan $full_transaction 35 | * 36 | * @return array 37 | * @throws ErrorException 38 | */ 39 | public function getBlockByNumber($tag = APIConf::TAG_LATEST, bool $full_transaction) 40 | { 41 | return $this->request->exec([ 42 | 'module' => "proxy", 43 | 'action' => "eth_getBlockByNumber", 44 | 'tag' => $tag, 45 | 'boolean' => $full_transaction 46 | ]); 47 | } 48 | 49 | /** 50 | * Returns the information about a transaction requested by transaction hash 51 | * 52 | * @param string $transactionHash 53 | * 54 | * @return array 55 | * @throws ErrorException 56 | */ 57 | public function getTransactionByHash($transactionHash) 58 | { 59 | return $this->request->exec([ 60 | 'module' => "proxy", 61 | 'action' => "eth_getTransactionByHash", 62 | 'txhash' => $transactionHash 63 | ]); 64 | } 65 | 66 | /** 67 | * Returns the number of transactions sent from an address 68 | * 69 | * @param string $address Ether address. 70 | * @param string $tag 71 | * 72 | * @return array 73 | * @throws ErrorException 74 | */ 75 | public function getTransactionCount(string $address, $tag = APIConf::TAG_LATEST) 76 | { 77 | return $this->request->exec([ 78 | 'module' => "proxy", 79 | 'action' => "eth_getTransactionCount", 80 | 'tag' => $tag, 81 | 'address' => $address 82 | ]); 83 | } 84 | 85 | /** 86 | * Creates new message call transaction or a contract creation for signed transactions 87 | * 88 | * @param string $hex raw transaction. 89 | * 90 | * @return array 91 | * @throws ErrorException 92 | */ 93 | public function sendRawTransaction($hex) 94 | { 95 | return $this->request->exec([ 96 | 'module' => "proxy", 97 | 'action' => "eth_sendRawTransaction", 98 | 'hex' => $hex 99 | ]); 100 | } 101 | 102 | /** 103 | * Returns the receipt of a transaction by transaction hash 104 | * 105 | * @param string $transactionHash 106 | * 107 | * @return array 108 | * @throws ErrorException 109 | */ 110 | public function getTransactionReceipt($transactionHash) 111 | { 112 | return $this->request->exec([ 113 | 'module' => "proxy", 114 | 'action' => "eth_getTransactionReceipt", 115 | 'txhash' => $transactionHash 116 | ]); 117 | } 118 | 119 | /** 120 | * Returns the number of most recent block 121 | * 122 | * @return array 123 | * @throws ErrorException 124 | */ 125 | public function gasPrice() 126 | { 127 | return $this->request->exec([ 128 | 'module' => "proxy", 129 | 'action' => "eth_gasPrice", 130 | ]); 131 | } 132 | 133 | /** 134 | * Makes a call or transaction, which won't be added to the blockchain and returns 135 | * the used gas, which can be used for estimating the used gas 136 | * 137 | * @param string $to 20 Bytes - The address the transaction is directed to. 138 | * @param string $value (optional) Integer of the value sent with this transaction 139 | * @param string $gasPrice (optional) Integer of the gasPrice used for each paid gas 140 | * @param string $gas (optional) Integer of the gas provided for the transaction execution. 141 | * eth_call consumes zero gas, but this parameter may be needed by some 142 | * executions. 143 | * 144 | * @return array 145 | * @throws ErrorException 146 | */ 147 | public function estimateGas($to=null, $value=null, $gasPrice=null, $gas=null) 148 | { 149 | return $this->request->exec([ 150 | 'module' => "proxy", 151 | 'action' => "eth_estimateGas", 152 | 'to' => $to, 153 | 'value' => $value, 154 | 'gasPrice' => $gasPrice, 155 | 'gas' => $gas 156 | ]); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /lib/Etherscan/Api/Stats.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Stats extends AbstractApi 15 | { 16 | /** 17 | * Get Total Supply of Ether. 18 | * Returns the current amount of Ether in circulation. 19 | * 20 | * @return array Result returned in Wei, to get value in Ether divide resultAbove / 1000000000000000000 21 | * @throws \Etherscan\Exception\ErrorException 22 | */ 23 | public function ethSupply() 24 | { 25 | return $this->request->exec([ 26 | 'module' => "stats", 27 | 'action' => "ethsupply", 28 | ]); 29 | } 30 | /** 31 | * Get Total Supply of Ether 2 32 | * Returns the current amount of Ether in circulation, ETH2 Staking rewards and EIP1559 burnt fees statistics. 33 | * 34 | * @return array Result returned in Wei, to get value in Ether divide resultAbove / 1000000000000000000 35 | * @throws \Etherscan\Exception\ErrorException 36 | */ 37 | public function eth2Supply() 38 | { 39 | return $this->request->exec([ 40 | 'module' => "stats", 41 | 'action' => "ethsupply2", 42 | ]); 43 | } 44 | 45 | /** 46 | * Get Ether LastPrice Price. 47 | * Returns the latest price of 1 ETH. 48 | * 49 | * @return array 50 | * @throws \Etherscan\Exception\ErrorException 51 | */ 52 | public function ethPrice() 53 | { 54 | return $this->request->exec([ 55 | 'module' => "stats", 56 | 'action' => "ethprice", 57 | ]); 58 | } 59 | 60 | /** 61 | * Get Ethereum Nodes Size 62 | * Returns the size of the Ethereum blockchain, in bytes, over a date range. 63 | * 64 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 65 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 66 | * @param string $clienttype the Ethereum node client to use, either geth or parity 67 | * @param string $syncmode the type of node to run, either default or archive 68 | * @param string $sort 'asc' or 'desc' 69 | * 70 | * @return array 71 | * @throws \Etherscan\Exception\ErrorException 72 | * @throws \Etherscan\Exception\InvalidArgumentException 73 | */ 74 | public function getNodesSize($startdate, $enddate, $clienttype, $syncmode, $sort = "asc") 75 | { 76 | if (!in_array($clienttype, APIConf::$clientTypes)) { 77 | throw new InvalidArgumentException("Invalid client type"); 78 | } 79 | 80 | if (!in_array($syncmode, APIConf::$syncModes)) { 81 | throw new InvalidArgumentException("Invalid sync mode type"); 82 | } 83 | 84 | return $this->request->exec([ 85 | 'module' => "stats", 86 | 'action' => "chainsize", 87 | 'startdate' => $startdate, 88 | 'enddate' => $enddate, 89 | 'clienttype' => $clienttype, 90 | 'syncmode' => $syncmode, 91 | 'sort' => $sort 92 | ]); 93 | } 94 | 95 | /** 96 | * Get Total Nodes Count 97 | * Returns the total number of discoverable Ethereum nodes. 98 | * 99 | * @return array 100 | * @throws \Etherscan\Exception\ErrorException 101 | */ 102 | public function getNodesCount() 103 | { 104 | return $this->request->exec([ 105 | 'module' => "stats", 106 | 'action' => "nodecount", 107 | ]); 108 | } 109 | 110 | /** 111 | * Get Daily Network Transaction Fee 112 | * Returns the amount of transaction fees paid to miners per day. 113 | * 114 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 115 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 116 | * @param string $sort 'asc' or 'desc' 117 | * 118 | * @return array 119 | * @throws \Etherscan\Exception\ErrorException 120 | */ 121 | public function getDailyTransactionFee($startdate, $enddate, $sort = "asc") 122 | { 123 | return $this->request->exec([ 124 | 'module' => "stats", 125 | 'action' => "dailytxnfee", 126 | 'startdate' => $startdate, 127 | 'enddate' => $enddate, 128 | 'sort' => $sort 129 | ]); 130 | } 131 | 132 | /** 133 | * Get Daily New Address Count 134 | * Returns the number of new Ethereum addresses created per day. 135 | * 136 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 137 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 138 | * @param string $sort 'asc' or 'desc' 139 | * 140 | * @return array 141 | * @throws \Etherscan\Exception\ErrorException 142 | */ 143 | public function getDailyNewAddressCount($startdate, $enddate, $sort = "asc") 144 | { 145 | return $this->request->exec([ 146 | 'module' => "stats", 147 | 'action' => "dailynewaddress", 148 | 'startdate' => $startdate, 149 | 'enddate' => $enddate, 150 | 'sort' => $sort 151 | ]); 152 | } 153 | 154 | /** 155 | * Get Daily Network Utilization 156 | * Returns the daily average gas used over gas limit, in percentage. 157 | * 158 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 159 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 160 | * @param string $sort 'asc' or 'desc' 161 | * 162 | * @return array 163 | * @throws \Etherscan\Exception\ErrorException 164 | */ 165 | public function getDailyNetworkUtilization($startdate, $enddate, $sort = "asc") 166 | { 167 | return $this->request->exec([ 168 | 'module' => "stats", 169 | 'action' => "dailynetutilization", 170 | 'startdate' => $startdate, 171 | 'enddate' => $enddate, 172 | 'sort' => $sort 173 | ]); 174 | } 175 | 176 | /** 177 | * Get Daily Average Network Hash Rate 178 | * Returns the historical measure of processing power of the Ethereum network. 179 | * 180 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 181 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 182 | * @param string $sort 'asc' or 'desc' 183 | * 184 | * @return array 185 | * @throws \Etherscan\Exception\ErrorException 186 | */ 187 | public function getDailyAverageHashRate($startdate, $enddate, $sort = "asc") 188 | { 189 | return $this->request->exec([ 190 | 'module' => "stats", 191 | 'action' => "dailyavghashrate", 192 | 'startdate' => $startdate, 193 | 'enddate' => $enddate, 194 | 'sort' => $sort 195 | ]); 196 | } 197 | 198 | /** 199 | * Get Daily Transaction Count 200 | * Returns the number of transactions performed on the Ethereum blockchain per day. 201 | * 202 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 203 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 204 | * @param string $sort 'asc' or 'desc' 205 | * 206 | * @return array 207 | * @throws \Etherscan\Exception\ErrorException 208 | */ 209 | public function getDailyTransactionCount($startdate, $enddate, $sort = "asc") 210 | { 211 | return $this->request->exec([ 212 | 'module' => "stats", 213 | 'action' => "dailytx", 214 | 'startdate' => $startdate, 215 | 'enddate' => $enddate, 216 | 'sort' => $sort 217 | ]); 218 | } 219 | 220 | /** 221 | * Get Daily Average Network Difficulty 222 | * Returns the historical mining difficulty of the Ethereum network. 223 | * 224 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 225 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 226 | * @param string $sort 'asc' or 'desc' 227 | * 228 | * @return array 229 | * @throws \Etherscan\Exception\ErrorException 230 | */ 231 | public function getDailyAverageNetworkDifficulty($startdate, $enddate, $sort = "asc") 232 | { 233 | return $this->request->exec([ 234 | 'module' => "stats", 235 | 'action' => "dailyavgnetdifficulty", 236 | 'startdate' => $startdate, 237 | 'enddate' => $enddate, 238 | 'sort' => $sort 239 | ]); 240 | } 241 | 242 | /** 243 | * Get Ether Historical Daily Market Cap 244 | * Returns the historical Ether daily market capitalization. 245 | * 246 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 247 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 248 | * @param string $sort 'asc' or 'desc' 249 | * 250 | * @return array 251 | * @throws \Etherscan\Exception\ErrorException 252 | */ 253 | public function getDailyMarketCap($startdate, $enddate, $sort = "asc") 254 | { 255 | return $this->request->exec([ 256 | 'module' => "stats", 257 | 'action' => "ethdailymarketcap", 258 | 'startdate' => $startdate, 259 | 'enddate' => $enddate, 260 | 'sort' => $sort 261 | ]); 262 | } 263 | 264 | /** 265 | * Get Ether Historical Price 266 | * Returns the historical price of 1 ETH. 267 | * 268 | * @param string $startdate the starting date in yyyy-MM-dd format, eg. 2019-02-01 269 | * @param string $enddate the ending date in yyyy-MM-dd format, eg. 2019-02-28 270 | * @param string $sort 'asc' or 'desc' 271 | * 272 | * @return array 273 | * @throws \Etherscan\Exception\ErrorException 274 | */ 275 | public function getHistoricalPrice($startdate, $enddate, $sort = "asc") 276 | { 277 | return $this->request->exec([ 278 | 'module' => "stats", 279 | 'action' => "ethdailyprice", 280 | 'startdate' => $startdate, 281 | 'enddate' => $enddate, 282 | 'sort' => $sort 283 | ]); 284 | } 285 | 286 | /** 287 | * Get Token TotalSupply by TokenName (Supported TokenNames: DGD, MKR, 288 | * FirstBlood, HackerGold, ICONOMI, Pluton, REP, SNGLS). 289 | * 290 | * or 291 | * 292 | * by ContractAddress. 293 | * 294 | * @param string $tokenIdentifier Token name from the list or contract address. 295 | * 296 | * @return array 297 | * @throws \Etherscan\Exception\ErrorException 298 | */ 299 | public function tokenSupply($tokenIdentifier) 300 | { 301 | $params = [ 302 | 'module' => "stats", 303 | 'action' => "tokensupply", 304 | ]; 305 | 306 | if (strlen($tokenIdentifier) === 42) { 307 | $params['contractaddress'] = $tokenIdentifier; 308 | } else { 309 | $params['tokenname'] = $tokenIdentifier; 310 | } 311 | 312 | return $this->request->exec($params); 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /lib/Etherscan/Api/Token.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class Token extends AbstractApi 11 | { 12 | /** 13 | * Get ERC20-Token TotalSupply by ContractAddress 14 | * Returns the current amount of an ERC-20 token in circulation. 15 | * 16 | * @param string $contractAddress the contract address of the ERC-20 token 17 | * 18 | * @return array 19 | * @throws \Etherscan\Exception\ErrorException 20 | */ 21 | public function getTokenSupply($contractAddress) 22 | { 23 | return $this->request->exec([ 24 | 'module' => "stats", 25 | 'action' => "tokensupply", 26 | 'contractaddress' => $contractAddress 27 | ]); 28 | } 29 | 30 | /** 31 | * Get ERC20-Token Account Balance for TokenContractAddress 32 | * Returns the current balance of an ERC-20 token of an address. 33 | * 34 | * @param string $contractAddress the contract address of the ERC-20 token 35 | * @param string $address the string representing the address to check for token balance 36 | * 37 | * @return array 38 | * @throws \Etherscan\Exception\ErrorException 39 | */ 40 | public function getTokenBalance($contractAddress, $address) 41 | { 42 | return $this->request->exec([ 43 | 'module' => "account", 44 | 'action' => "tokenbalance", 45 | 'contractaddress' => $contractAddress, 46 | 'address' => $address 47 | ]); 48 | } 49 | 50 | /** 51 | * Get Historical ERC20-Token TotalSupply by ContractAddress & BlockNo 52 | * Returns the amount of an ERC-20 token in circulation at a certain block height. 53 | * 54 | * @param string $contractAddress the contract address of the ERC-20 token 55 | * @param string $blockNumber the integer block number to check total supply for eg. 12697906 56 | * 57 | * @return array 58 | * @throws \Etherscan\Exception\ErrorException 59 | */ 60 | public function getTokenSupplyHistory($contractAddress, $blockNumber) 61 | { 62 | return $this->request->exec([ 63 | 'module' => "stats", 64 | 'action' => "tokensupplyhistory", 65 | 'contractaddress' => $contractAddress, 66 | 'blockno' => $blockNumber 67 | ]); 68 | } 69 | 70 | /** 71 | * Get Historical ERC20-Token Account Balance for TokenContractAddress by BlockNo 72 | * Returns the balance of an ERC-20 token of an address at a certain block height. 73 | * 74 | * @param string $contractAddress the contract address of the ERC-20 token 75 | * @param string $address the string representing the address to check for balance 76 | * @param string $blockNumber the integer block number to check total supply for eg. 12697906 77 | * 78 | * @return array 79 | * @throws \Etherscan\Exception\ErrorException 80 | */ 81 | public function getTokenBalanceHistory($contractAddress, $address, $blockNumber) 82 | { 83 | return $this->request->exec([ 84 | 'module' => "account", 85 | 'action' => "tokenbalancehistory", 86 | 'contractaddress' => $contractAddress, 87 | 'address' => $address, 88 | 'blockno' => $blockNumber 89 | ]); 90 | } 91 | 92 | /** 93 | * Get Token Info by ContractAddress 94 | * Returns project information and social media links of an ERC-20/ERC-721 token. 95 | * 96 | * @param string $contractAddress the contract address of the ERC-20/ERC-721 token to retrieve token info 97 | * 98 | * @return array 99 | * @throws \Etherscan\Exception\ErrorException 100 | */ 101 | public function getTokenInfo($contractAddress) 102 | { 103 | return $this->request->exec([ 104 | 'module' => "token", 105 | 'action' => "tokeninfo", 106 | 'contractaddress' => $contractAddress 107 | ]); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/Etherscan/Api/Transaction.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class Transaction extends AbstractApi 11 | { 12 | 13 | /** 14 | * Check Contract Execution Status (if there was an error during contract execution). 15 | * Note: isError":"0" = Pass , isError":"1" = Error during Contract Execution. 16 | * 17 | * @param string $transactionHash 18 | * 19 | * @return array 20 | * @throws \Etherscan\Exception\ErrorException 21 | */ 22 | public function getStatus($transactionHash) { 23 | return $this->request->exec([ 24 | 'module' => "transaction", 25 | 'action' => "getstatus", 26 | 'txhash' => $transactionHash 27 | ]); 28 | } 29 | 30 | /** 31 | * Check Transaction Receipt Status (Only applicable for Post Byzantium fork transactions). 32 | * Note: status: 0 = Fail, 1 = Pass. Will return null/empty value for pre-byzantium fork 33 | * 34 | * @param string $transactionHash 35 | * 36 | * @return array 37 | * @throws \Etherscan\Exception\ErrorException 38 | */ 39 | public function getTransactionReceiptStatus($transactionHash) { 40 | return $this->request->exec([ 41 | 'module' => "transaction", 42 | 'action' => "gettxreceiptstatus", 43 | 'txhash' => $transactionHash 44 | ]); 45 | } 46 | 47 | /** 48 | * Check Contract Execution Status (if there was an error during contract execution). 49 | * Note: isError":"0" = Pass , isError":"1" = Error during Contract Execution. 50 | * 51 | * @param string $transactionHash 52 | * 53 | * @return array 54 | * @throws \Etherscan\Exception\ErrorException 55 | */ 56 | public function getContractExecutionStatus($transactionHash) { 57 | return $this->getStatus($transactionHash); 58 | } 59 | } -------------------------------------------------------------------------------- /lib/Etherscan/Api/Websocket.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class Websocket extends AbstractApi 11 | { 12 | 13 | } -------------------------------------------------------------------------------- /lib/Etherscan/Client.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class Client 16 | { 17 | 18 | /** 19 | * Etherscan API key token. 20 | * 21 | * @var string 22 | */ 23 | private $apiKeyToken; 24 | 25 | /** 26 | * @var string $netName testnet name or mainnet by default. 27 | */ 28 | private $netName; 29 | 30 | public function __construct($apiKeyToken = null, $netName = null) 31 | { 32 | if (is_null($apiKeyToken)) { 33 | return; 34 | } 35 | 36 | $this->apiKeyToken = $apiKeyToken; 37 | $this->netName = $netName; 38 | } 39 | 40 | /** 41 | * @param string $name 42 | * 43 | * @throws InvalidArgumentException 44 | * 45 | * @return ApiInterface 46 | */ 47 | public function api($name) 48 | { 49 | switch ($name) { 50 | case 'account': 51 | $api = new Api\Account($this); 52 | break; 53 | case 'block': 54 | $api = new Api\Block($this); 55 | break; 56 | case 'contract': 57 | $api = new Api\Contract($this); 58 | break; 59 | break; 60 | case 'gas': 61 | $api = new Api\Gas($this); 62 | break; 63 | case 'eventLog': 64 | $api = new Api\EventLog($this); 65 | break; 66 | case 'proxy': 67 | $api = new Api\Proxy($this); 68 | break; 69 | case 'stats': 70 | $api = new Api\Stats($this); 71 | break; 72 | case 'token': 73 | $api = new Api\Token($this); 74 | break; 75 | case 'transaction': 76 | $api = new Api\Transaction($this); 77 | break; 78 | case 'websocket': 79 | $api = new Api\Websocket($this); 80 | break; 81 | default: 82 | throw new InvalidArgumentException(sprintf('Undefined api instance called: "%s"', $name)); 83 | } 84 | return $api; 85 | } 86 | 87 | /** 88 | * @return string 89 | */ 90 | public function getApiKeyToken(): string 91 | { 92 | return $this->apiKeyToken; 93 | } 94 | 95 | /** 96 | * @return string|null 97 | */ 98 | public function getNetName(): ?string 99 | { 100 | return $this->netName; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /lib/Etherscan/Exception/ErrorException.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class ErrorException extends \ErrorException implements ExceptionInterface 11 | { 12 | 13 | } -------------------------------------------------------------------------------- /lib/Etherscan/Exception/ExceptionInterface.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | interface ExceptionInterface 11 | { 12 | 13 | } -------------------------------------------------------------------------------- /lib/Etherscan/Exception/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface 11 | { 12 | } -------------------------------------------------------------------------------- /lib/Etherscan/Helper/UtilityHelper.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class UtilityHelper 11 | { 12 | 13 | /** 14 | * Converts Wei value to the Ether float value. 15 | * 16 | * @param int $amount 17 | * 18 | * @return float 19 | */ 20 | public static function convertEtherAmount($amount) { 21 | return (float)$amount / pow(10, 18); 22 | } 23 | 24 | /** 25 | * Checks if transaction is input transaction. 26 | * 27 | * @param string $address Ether address. 28 | * @param array $transactionData Transaction data. 29 | * 30 | * @return bool 31 | */ 32 | public static function isInputTransaction($address, $transactionData) { 33 | return (strtolower($transactionData['to']) === strtolower($address)); 34 | } 35 | 36 | /** 37 | * Checks if transaction is output transaction. 38 | * 39 | * @param string $address Ether address. 40 | * @param array $transactionData Transaction data. 41 | * 42 | * @return bool 43 | */ 44 | public static function isOutputTransaction($address, $transactionData) { 45 | return (strtolower($transactionData['from']) === strtolower($address)); 46 | } 47 | } -------------------------------------------------------------------------------- /lib/Etherscan/HttpClient/HttpClientInterface.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | interface HttpClientInterface 11 | { 12 | } -------------------------------------------------------------------------------- /lib/Etherscan/HttpClient/Request.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Request implements HttpClientInterface { 14 | 15 | /** 16 | * Etherscan API Key value. 17 | * 18 | * @var string 19 | */ 20 | private $apiKeyToken = ""; 21 | 22 | /** 23 | * Testnet name or Mainnet if null. 24 | * 25 | * @var string 26 | */ 27 | private $net = null; 28 | 29 | /** 30 | * cURL handle. 31 | * 32 | * @var resource 33 | */ 34 | private static $ch = null; 35 | 36 | public function __construct($apiKeyToken, $net = null) { 37 | $this->apiKeyToken = $apiKeyToken; 38 | $this->net = $net; 39 | } 40 | 41 | /** 42 | * Executes curl request to the Etherscan API. 43 | * 44 | * @param array $req Request parameters list. 45 | * 46 | * @return array JSON data. 47 | * @throws ErrorException If Curl error or Etherscan API error occurred. 48 | */ 49 | public function exec(array $req = []) { 50 | usleep(250000); 51 | 52 | // API settings 53 | $req['apikey'] = $this->apiKeyToken; 54 | 55 | // generate the POST data string 56 | $postData = http_build_query($req, '', '&'); 57 | 58 | // curl handle (initialize if required) 59 | if (is_null(self::$ch)) { 60 | self::$ch = curl_init(); 61 | curl_setopt(self::$ch, CURLOPT_RETURNTRANSFER, true); 62 | curl_setopt( 63 | self::$ch, 64 | CURLOPT_USERAGENT, 65 | 'Mozilla/4.0 (compatible; Etherscan PHP API; ' . php_uname('a') . '; PHP/' . phpversion() . ')' 66 | ); 67 | } 68 | curl_setopt(self::$ch, CURLOPT_URL, APIConf::getAPIUrl($this->net)); 69 | curl_setopt(self::$ch, CURLOPT_POSTFIELDS, $postData); 70 | curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, false); 71 | 72 | // run the query 73 | $res = curl_exec(self::$ch); 74 | if ($res === false) { 75 | throw new ErrorException("Curl error: " . curl_error(self::$ch)); 76 | } 77 | 78 | $json = json_decode($res, true); 79 | 80 | // Check for the Etherscan API error 81 | if (isset($json['error'])) { 82 | throw new ErrorException("Etherscan API error: {$json['error']}"); 83 | } 84 | 85 | return $json; 86 | } 87 | 88 | /** 89 | * Executes simple GET request to the Etherscan public API. 90 | * 91 | * @param string $url API method URL. 92 | * 93 | * @return array JSON data. 94 | */ 95 | public static function json($url) { 96 | $opts = [ 97 | 'http' => [ 98 | 'method' => 'GET', 99 | 'timeout' => 10 100 | ] 101 | ]; 102 | $context = stream_context_create($opts); 103 | $feed = file_get_contents($url, false, $context); 104 | $json = json_decode($feed, true); 105 | 106 | return $json; 107 | } 108 | 109 | } --------------------------------------------------------------------------------