├── .credo.exs ├── .formatter.exs ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── fixture └── vcr_cassettes │ ├── eth_block_number.json │ ├── eth_call.json │ ├── eth_estimate_gas.json │ ├── eth_gas_price.json │ ├── eth_get_block_by_number.json │ ├── eth_get_block_transaction_count_by_number.json │ ├── eth_get_code.json │ ├── eth_get_storage_at.json │ ├── eth_get_transaction_by_block_number_and_index.json │ ├── eth_get_transaction_by_hash.json │ ├── eth_get_transaction_count.json │ ├── eth_get_transaction_receipt.json │ ├── eth_get_uncle_by_block_number_and_index.json │ ├── eth_send_raw_transaction.json │ ├── get_balance.json │ ├── get_balances.json │ ├── get_block_and_uncle_rewards.json │ ├── get_blocks_mined.json │ ├── get_blocks_mined_offset.json │ ├── get_blocks_mined_page.json │ ├── get_contract_abi.json │ ├── get_contract_execution_status.json │ ├── get_contract_execution_status_error.json │ ├── get_contract_source.json │ ├── get_eth_price.json │ ├── get_eth_supply.json │ ├── get_internal_transactions.json │ ├── get_internal_transactions_by_hash.json │ ├── get_internal_transactions_endblock.json │ ├── get_internal_transactions_offset.json │ ├── get_internal_transactions_page.json │ ├── get_internal_transactions_sort.json │ ├── get_internal_transactions_startblock.json │ ├── get_logs.json │ ├── get_token_balance.json │ ├── get_token_supply.json │ ├── get_transaction_receipt_status.json │ ├── get_transaction_receipt_status_pre_byzantium.json │ ├── get_transactions.json │ ├── get_transactions_endblock.json │ ├── get_transactions_offset.json │ ├── get_transactions_page.json │ ├── get_transactions_sort.json │ ├── get_transactions_startblock.json │ ├── get_uncles_mined.json │ ├── get_uncles_mined_offset.json │ └── get_uncles_mined_page.json ├── lib ├── etherscan.ex └── etherscan │ ├── api.ex │ ├── api │ ├── accounts.ex │ ├── blocks.ex │ ├── contracts.ex │ ├── logs.ex │ ├── proxy.ex │ ├── stats.ex │ └── transactions.ex │ ├── constants.ex │ ├── types │ ├── block_reward.ex │ ├── block_reward_uncle.ex │ ├── contract_status.ex │ ├── internal_transaction.ex │ ├── log.ex │ ├── mined_block.ex │ ├── mined_uncle.ex │ ├── proxy_block.ex │ ├── proxy_transaction.ex │ ├── proxy_transaction_receipt.ex │ └── transaction.ex │ └── util.ex ├── mix.exs ├── mix.lock └── test ├── etherscan ├── api │ ├── accounts_test.exs │ ├── blocks_test.exs │ ├── contracts_test.exs │ ├── logs_test.exs │ ├── proxy_test.exs │ ├── stats_test.exs │ └── transactions_test.exs └── util_test.exs ├── etherscan_test.exs └── test_helper.exs /.credo.exs: -------------------------------------------------------------------------------- 1 | %{ 2 | configs: [ 3 | %{ 4 | # 5 | # Run any exec using `mix credo -C `. If no exec name is given 6 | # "default" is used. 7 | # 8 | name: "default", 9 | # 10 | # These are the files included in the analysis: 11 | files: %{ 12 | # 13 | # You can give explicit globs or simply directories. 14 | # In the latter case `**/*.{ex,exs}` will be used. 15 | # 16 | included: ["lib/", "src/", "web/", "apps/", "test/", "config/"], 17 | excluded: [~r"/_build/", ~r"/deps/"] 18 | }, 19 | # 20 | # If you create your own checks, you must specify the source files for 21 | # them here, so they can be loaded by Credo before running the analysis. 22 | # 23 | requires: [], 24 | # 25 | # If you want to enforce a style guide and need a more traditional linting 26 | # experience, you can change `strict` to `true` below: 27 | # 28 | strict: true, 29 | # 30 | # If you want to use uncolored output by default, you can change `color` 31 | # to `false` below: 32 | # 33 | color: true, 34 | # 35 | # You can customize the parameters of any check by adding a second element 36 | # to the tuple. 37 | # 38 | # To disable a check put `false` as second element: 39 | # 40 | # {Credo.Check.Design.DuplicatedCode, false} 41 | # 42 | checks: [ 43 | {Credo.Check.Consistency.ExceptionNames}, 44 | {Credo.Check.Consistency.LineEndings}, 45 | {Credo.Check.Consistency.ParameterPatternMatching}, 46 | {Credo.Check.Consistency.SpaceAroundOperators}, 47 | {Credo.Check.Consistency.SpaceInParentheses}, 48 | {Credo.Check.Consistency.TabsOrSpaces}, 49 | 50 | # You can customize the priority of any check 51 | # Priority values are: `low, normal, high, higher` 52 | # 53 | {Credo.Check.Design.AliasUsage, priority: :low}, 54 | 55 | # For some checks, you can also set other parameters 56 | # 57 | # If you don't want the `setup` and `test` macro calls in ExUnit tests 58 | # or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just 59 | # set the `excluded_macros` parameter to `[:schema, :setup, :test]`. 60 | # 61 | {Credo.Check.Design.DuplicatedCode, excluded_macros: []}, 62 | 63 | # You can also customize the exit_status of each check. 64 | # If you don't want TODO comments to cause `mix credo` to fail, just 65 | # set this value to 0 (zero). 66 | # 67 | {Credo.Check.Design.TagTODO, exit_status: 2}, 68 | {Credo.Check.Design.TagFIXME}, 69 | 70 | {Credo.Check.Readability.FunctionNames}, 71 | {Credo.Check.Readability.LargeNumbers, false}, 72 | {Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 140}, 73 | {Credo.Check.Readability.ModuleAttributeNames}, 74 | {Credo.Check.Readability.ModuleDoc}, 75 | {Credo.Check.Readability.ModuleNames}, 76 | {Credo.Check.Readability.ParenthesesOnZeroArityDefs}, 77 | {Credo.Check.Readability.ParenthesesInCondition}, 78 | {Credo.Check.Readability.PredicateFunctionNames}, 79 | {Credo.Check.Readability.PreferImplicitTry}, 80 | {Credo.Check.Readability.RedundantBlankLines}, 81 | {Credo.Check.Readability.StringSigils}, 82 | {Credo.Check.Readability.TrailingBlankLine}, 83 | {Credo.Check.Readability.TrailingWhiteSpace}, 84 | {Credo.Check.Readability.VariableNames}, 85 | {Credo.Check.Readability.Semicolons}, 86 | {Credo.Check.Readability.SpaceAfterCommas}, 87 | 88 | {Credo.Check.Refactor.DoubleBooleanNegation}, 89 | {Credo.Check.Refactor.CondStatements}, 90 | {Credo.Check.Refactor.CyclomaticComplexity}, 91 | {Credo.Check.Refactor.FunctionArity}, 92 | {Credo.Check.Refactor.LongQuoteBlocks}, 93 | {Credo.Check.Refactor.MatchInCondition}, 94 | {Credo.Check.Refactor.NegatedConditionsInUnless}, 95 | {Credo.Check.Refactor.NegatedConditionsWithElse}, 96 | {Credo.Check.Refactor.Nesting}, 97 | {Credo.Check.Refactor.PipeChainStart}, 98 | {Credo.Check.Refactor.UnlessWithElse}, 99 | 100 | {Credo.Check.Warning.BoolOperationOnSameValues}, 101 | {Credo.Check.Warning.ExpensiveEmptyEnumCheck}, 102 | {Credo.Check.Warning.IExPry}, 103 | {Credo.Check.Warning.IoInspect}, 104 | {Credo.Check.Warning.LazyLogging}, 105 | {Credo.Check.Warning.OperationOnSameValues}, 106 | {Credo.Check.Warning.OperationWithConstantResult}, 107 | {Credo.Check.Warning.UnusedEnumOperation}, 108 | {Credo.Check.Warning.UnusedFileOperation}, 109 | {Credo.Check.Warning.UnusedKeywordOperation}, 110 | {Credo.Check.Warning.UnusedListOperation}, 111 | {Credo.Check.Warning.UnusedPathOperation}, 112 | {Credo.Check.Warning.UnusedRegexOperation}, 113 | {Credo.Check.Warning.UnusedStringOperation}, 114 | {Credo.Check.Warning.UnusedTupleOperation}, 115 | {Credo.Check.Warning.RaiseInsideRescue}, 116 | 117 | # Controversial and experimental checks (opt-in, just remove `, false`) 118 | # 119 | {Credo.Check.Refactor.ABCSize, false}, 120 | {Credo.Check.Refactor.AppendSingleItem, false}, 121 | {Credo.Check.Refactor.VariableRebinding, false}, 122 | {Credo.Check.Warning.MapGetUnsafePass, false}, 123 | {Credo.Check.Consistency.MultiAliasImportRequireUse, false}, 124 | 125 | # Deprecated checks (these will be deleted after a grace period) 126 | # 127 | {Credo.Check.Readability.Specs, false}, 128 | {Credo.Check.Warning.NameRedeclarationByAssignment, false}, 129 | {Credo.Check.Warning.NameRedeclarationByCase, false}, 130 | {Credo.Check.Warning.NameRedeclarationByDef, false}, 131 | {Credo.Check.Warning.NameRedeclarationByFn, false}, 132 | 133 | # Custom checks can be created using `mix credo.gen.check`. 134 | # 135 | ] 136 | } 137 | ] 138 | } 139 | -------------------------------------------------------------------------------- /.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where 3rd-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: elixir 2 | sudo: false 3 | elixir: 4 | - 1.5 5 | - 1.6 6 | - 1.7 7 | otp_release: 8 | - 20.0 9 | - 20.1 10 | - 20.2 11 | - 20.3 12 | - 21.0 13 | env: 14 | - MIX_ENV=test 15 | script: 16 | - mix test 17 | - if [[ `elixir -v` = *"1.7"* ]]; then mix format --check-formatted; fi 18 | after_success: 19 | - mix coveralls.travis 20 | - MIX_ENV=docs mix deps.get 21 | branches: 22 | only: 23 | - master 24 | cache: 25 | directories: 26 | - _build 27 | - deps 28 | matrix: 29 | exclude: 30 | - elixir: 1.5 31 | otp_release: 21.0 32 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Etherscan Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). 6 | 7 | ## [2.0.2] 8 | ### Added 9 | - `Etherscan.get_contract_source/1` 10 | 11 | ## [2.0.1] 12 | ### Changed 13 | - Updated testnet URLs to latest versions 14 | 15 | ## [2.0.0] 16 | ### Added 17 | - `Etherscan.get_transaction_receipt_status/1` 18 | - Option to set HTTPoison options via `config :etherscan, request: []` 19 | 20 | ### Changed 21 | - `Etherscan.API.Accounts.get_balance/1` 22 | - returns balance in ether. previously wei 23 | - `Etherscan.API.Accounts.get_balances/1` 24 | - returns balance in ether. previously wei 25 | - `Etherscan.API.Logs.get_logs/1` 26 | - returns error if given an invalid address. previously made request with invalid address 27 | - `Etherscan.API.Proxy.get_eth_supply/0` 28 | - returns supply in ether. previously wei 29 | 30 | ## [0.1.5] - 2018-03-15 31 | ### Changed 32 | - Update `httpoison` to `1.0.0` 33 | 34 | ## [0.1.4] - 2017-12-09 35 | ### Added 36 | - Option to configure ethereum network via `config :etherscan, network: ` 37 | - Support for log endpoints via `Etherscan.API.Logs` 38 | - Support for Geth/Parity proxy endpoints via `Etherscan.API.Proxy` 39 | - More documentation and usage examples 40 | 41 | ## [0.1.3] - 2017-10-11 42 | ### Added 43 | - Option to configure api key via `config :etherscan, api_key: ` 44 | 45 | ## [0.1.2] - 2017-09-27 46 | ### Changed 47 | - Dependency/fixture update 48 | 49 | ## [0.1.1] - 2017-09-04 50 | ### Added 51 | - Initial test coverage 52 | 53 | ## 0.1.0 - 2017-08-26 54 | ### Added 55 | - First version 56 | 57 | [2.0.2]: https://github.com/l1h3r/etherscan/compare/2.0.1...2.0.2 58 | [2.0.1]: https://github.com/l1h3r/etherscan/compare/2.0.0...2.0.1 59 | [2.0.0]: https://github.com/l1h3r/etherscan/compare/0.1.5...2.0.0 60 | [0.1.5]: https://github.com/l1h3r/etherscan/compare/0.1.4...0.1.5 61 | [0.1.4]: https://github.com/l1h3r/etherscan/compare/0.1.3...0.1.4 62 | [0.1.3]: https://github.com/l1h3r/etherscan/compare/0.1.2...0.1.3 63 | [0.1.2]: https://github.com/l1h3r/etherscan/compare/0.1.1...0.1.2 64 | [0.1.1]: https://github.com/l1h3r/etherscan/compare/0.1.0...0.1.1 65 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 l1h3r 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Etherscan 2 | 3 | [![Build Status](https://travis-ci.org/l1h3r/etherscan.svg?branch=master)](https://travis-ci.org/l1h3r/etherscan) 4 | [![Coverage Status](https://coveralls.io/repos/github/l1h3r/etherscan/badge.svg?branch=master)](https://coveralls.io/github/l1h3r/etherscan?branch=master) 5 | [![Hex.pm](https://img.shields.io/hexpm/v/etherscan.svg?style=flat-square)](https://hex.pm/packages/etherscan) 6 | [![Hex.pm](https://img.shields.io/hexpm/dt/etherscan.svg?style=flat-square)](https://hex.pm/packages/etherscan) 7 | 8 | An Elixir wrapper for the [Etherscan](https://etherscan.io/) API 9 | 10 | [Official API Documentation](https://etherscan.io/apis) 11 | 12 | [Create API Key (optional)](https://etherscan.io/myapikey) 13 | 14 | ## Installation 15 | 16 | Etherscan is available on [Hex](https://hex.pm/). You can install the package via: 17 | 18 | ```elixir 19 | def deps do 20 | [ 21 | {:etherscan, "~> 2.0.0"} 22 | ] 23 | end 24 | ``` 25 | 26 | ## Usage 27 | 28 | #### Setting Your API Key 29 | 30 | An API key is not required to use the Etherscan API, however, you can set one with the following: 31 | 32 | ```elixir 33 | config :etherscan, 34 | api_key: "" 35 | ``` 36 | 37 | #### Using a Testnet 38 | 39 | You can use one of the test networks with the following: 40 | ```elixir 41 | config :etherscan, 42 | network: :ropsten 43 | ``` 44 | 45 | #### Setting Request Options 46 | 47 | You can set additional request options which are passed to [HTTPoison]: 48 | 49 | ```elixir 50 | config :etherscan, 51 | request: [recv_timeout: 500] 52 | ``` 53 | 54 | Check out the HTTPoison [README](https://github.com/edgurgel/httpoison#options) for all available options. 55 | 56 | [HTTPoison]: https://github.com/edgurgel/httpoison 57 | -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_block_number.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_blockNumber&apikey=&module=proxy" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":83,\"result\":\"0x5e8c36\"}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:32 GMT", 26 | "Content-Length": "46" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_call.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_call&apikey=&data=0x70a08231000000000000000000000000e16359506c028e51f16be38986ec5746251e9724&module=proxy&tag=latest&to=0xAEEF46DB4855E25702F8237E8f403FddcaF931C0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x00000000000000000000000000000000000000000000000000601d8888141c00\"}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:33 GMT", 26 | "Content-Length": "103" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_estimate_gas.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_estimateGas&apikey=&gas=0xffffff&gasPrice=0x051da038cc&module=proxy&to=0xf0160428a8552ac9bb7e050d90eeade4ddd52843&value=0xff22" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"error\":{\"code\":-32602,\"message\":\"invalid argument 0: json: cannot unmarshal hex number with leading zero digits into Go struct field CallArgs.gasPrice of type *hexutil.Big\"}}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:35 GMT", 26 | "Content-Length": "200" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_gas_price.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_gasPrice&apikey=&module=proxy" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":73,\"result\":\"0x7d2b7500\"}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:34 GMT", 26 | "Content-Length": "48" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_block_by_number.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getBlockByNumber&apikey=&boolean=true&module=proxy&tag=0x10d4f" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"difficulty\":\"0x1d95715bd14\",\"extraData\":\"0x\",\"gasLimit\":\"0x2fefd8\",\"gasUsed\":\"0x5208\",\"hash\":\"0x7eb7c23a5ac2f2d70aa1ba4e5c56d89de5ac993590e5f6e79c394e290d998ba8\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0xf927a40c8b7f6e07c5af7fa2155b4864a4112b13\",\"mixHash\":\"0x13dd2c8aec729f75aebcd79a916ecb0f7edc6493efcc6a4da8d7b0ab3ee88444\",\"nonce\":\"0xc60a782e2e69ce22\",\"number\":\"0x10d4f\",\"parentHash\":\"0xf8d01370e6e274f8188954fbee435b40c35b2ad3d4ab671f6d086cd559e48f04\",\"receiptsRoot\":\"0x0c44b7ed0fefb613ec256341aa0ffdb643e869e3a0ebc8f58e36b4e47efedd33\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x275\",\"stateRoot\":\"0xd64a0f63e2c7f541e6e6f8548a10a5c4e49fda7ac1aa80f9dddef648c7b9e25f\",\"timestamp\":\"0x55c9ea07\",\"totalDifficulty\":\"0x120d56f6821b170\",\"transactions\":[{\"blockHash\":\"0x7eb7c23a5ac2f2d70aa1ba4e5c56d89de5ac993590e5f6e79c394e290d998ba8\",\"blockNumber\":\"0x10d4f\",\"from\":\"0x4458f86353b4740fe9e09071c23a7437640063c9\",\"gas\":\"0x5208\",\"gasPrice\":\"0xba43b7400\",\"hash\":\"0xa442249820de6be754da81eafbd44a865773e4b23d7c0522d31fd03977823008\",\"input\":\"0x\",\"nonce\":\"0x1\",\"to\":\"0xbf3403210f9802205f426759947a80a9fda71b1e\",\"transactionIndex\":\"0x0\",\"value\":\"0xaa9f075c200000\",\"v\":\"0x1b\",\"r\":\"0x2c2789c6704ba2606e200e1ba4fd17ba4f0e0f94abe32a12733708c3d3442616\",\"s\":\"0x2946f47e3ece580b5b5ecb0f8c52604fa5f60aeb4103fc73adcbf6d620f9872b\"}],\"transactionsRoot\":\"0x4a5b78c13d11559c9541576834b5172fe8b18507c0f9f76454fcdddedd8dff7a\",\"uncles\":[]}}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:33 GMT", 26 | "Content-Length": "1993" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_block_transaction_count_by_number.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getBlockTransactionCountByNumber&apikey=&module=proxy&tag=0x10FB78" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x3\"}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:35 GMT", 26 | "Content-Length": "40" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_code.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getCode&address=0xf75e354c5edc8efed9b59ee9f67a80845ade7d0c&apikey=&module=proxy&tag=latest" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x3660008037602060003660003473273930d21e01ee25e4c219b63259d214872220a261235a5a03f21560015760206000f3\"}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:34 GMT", 26 | "Content-Length": "137" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_storage_at.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getStorageAt&address=0x6e03d9cce9d60f3e9f2597e13cd4c54c55330cfd&apikey=&module=proxy&position=0x0&tag=latest" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x0000000000000000000000003d0768da09ce77d25e2d998e6a7b6ed4b9116c2d\"}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:35 GMT", 26 | "Content-Length": "103" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_transaction_by_block_number_and_index.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getTransactionByBlockNumberAndIndex&apikey=&index=0x0&module=proxy&tag=0x10d4f" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"blockHash\":\"0x7eb7c23a5ac2f2d70aa1ba4e5c56d89de5ac993590e5f6e79c394e290d998ba8\",\"blockNumber\":\"0x10d4f\",\"from\":\"0x4458f86353b4740fe9e09071c23a7437640063c9\",\"gas\":\"0x5208\",\"gasPrice\":\"0xba43b7400\",\"hash\":\"0xa442249820de6be754da81eafbd44a865773e4b23d7c0522d31fd03977823008\",\"input\":\"0x\",\"nonce\":\"0x1\",\"to\":\"0xbf3403210f9802205f426759947a80a9fda71b1e\",\"transactionIndex\":\"0x0\",\"value\":\"0xaa9f075c200000\",\"v\":\"0x1b\",\"r\":\"0x2c2789c6704ba2606e200e1ba4fd17ba4f0e0f94abe32a12733708c3d3442616\",\"s\":\"0x2946f47e3ece580b5b5ecb0f8c52604fa5f60aeb4103fc73adcbf6d620f9872b\"}}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:32 GMT", 26 | "Content-Length": "595" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_transaction_by_hash.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getTransactionByHash&apikey=&module=proxy&txhash=0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"blockHash\":\"0xf64a12502afc36db3d29931a2148e5d6ddaa883a2a3c968ca2fb293fa9258c68\",\"blockNumber\":\"0x70839\",\"from\":\"0xc80fb22930b303b55df9b89901889126400add38\",\"gas\":\"0x30d40\",\"gasPrice\":\"0xba43b7400\",\"hash\":\"0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1\",\"input\":\"0xfc36e15b0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a4861636b65726e65777300000000000000000000000000000000000000000000\",\"nonce\":\"0xa7\",\"to\":\"0x03fca6077d38dd99d0ce14ba32078bd2cda72d74\",\"transactionIndex\":\"0x0\",\"value\":\"0x0\",\"v\":\"0x1c\",\"r\":\"0xe7ccdba116aa95ae8d9bdd02f619a0cdfc1f60c5740b3899865822a80cd70218\",\"s\":\"0xf200df1921ea988d16280a0873b69cb782a54e8a596d15e700710c820c8d2a9e\"}}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:32 GMT", 26 | "Content-Length": "784" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_transaction_count.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getTransactionCount&address=0x2910543af39aba0cd09dbb2d50200b3e800a63d2&apikey=&module=proxy&tag=latest" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0xaf5d\"}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:35 GMT", 26 | "Content-Length": "43" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_transaction_receipt.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getTransactionReceipt&apikey=&module=proxy&txhash=0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"blockHash\":\"0xf64a12502afc36db3d29931a2148e5d6ddaa883a2a3c968ca2fb293fa9258c68\",\"blockNumber\":\"0x70839\",\"contractAddress\":null,\"cumulativeGasUsed\":\"0x75d5\",\"from\":\"0xc80fb22930b303b55df9b89901889126400add38\",\"gasUsed\":\"0x75d5\",\"logs\":[{\"address\":\"0x03fca6077d38dd99d0ce14ba32078bd2cda72d74\",\"topics\":[\"0x24bcf19562365f6510754002f8d7b818d275886315d29c7aa04785570b97a363\"],\"data\":\"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a4861636b65726e65777300000000000000000000000000000000000000000000\",\"blockNumber\":\"0x70839\",\"transactionHash\":\"0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1\",\"transactionIndex\":\"0x0\",\"blockHash\":\"0xf64a12502afc36db3d29931a2148e5d6ddaa883a2a3c968ca2fb293fa9258c68\",\"logIndex\":\"0x0\",\"removed\":false}],\"logsBloom\":\"0x00000000000000000000000000000400000000020000000000000000400000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0xc659845f1ac4e899ff1b0666dbac5deeda33a4a5d85da71f617f352824146e40\",\"to\":\"0x03fca6077d38dd99d0ce14ba32078bd2cda72d74\",\"transactionHash\":\"0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1\",\"transactionIndex\":\"0x0\"}}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:33 GMT", 26 | "Content-Length": "1631" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_get_uncle_by_block_number_and_index.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_getUncleByBlockNumberAndIndex&apikey=&index=0x0&module=proxy&tag=0x210A9B" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"difficulty\":\"0x3db79ff5de86\",\"extraData\":\"0x7777772e62772e636f6d\",\"gasLimit\":\"0x47e7c4\",\"gasUsed\":\"0x14820\",\"hash\":\"0x5ad884f542215bbb0b7e2558b2309ce89132e559ee1b001e81b77e702b43d932\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0xbcdfc35b86bedf72f0cda046a3c16829a2ef41d1\",\"mixHash\":\"0x8d3e8e65a0803e3c023bafcd373e1d272c4f463ba0116f3e9591a8dc1e5b5018\",\"nonce\":\"0x151a6600143aad31\",\"number\":\"0x210a99\",\"parentHash\":\"0x30fe09876530e366a49b6a3aa64c26cf7cd4348aa32a6ad83564b0ea4b3830ed\",\"receiptsRoot\":\"0xf43ffa3981d0c714e1f677082fc15e69f408263f542bb98a2ac47d8d92f540fe\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x212\",\"stateRoot\":\"0xce52569ccaa08e9030fc0fa5750332f7d2bc111699e3adb6c6927b73b5c56f14\",\"timestamp\":\"0x57c515ba\",\"totalDifficulty\":null,\"transactionsRoot\":\"0x057c513a2722663a43b29d66b49809876289e3c7497b84e3bee52bb7648fba50\",\"uncles\":[]}}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:34 GMT", 26 | "Content-Length": "1423" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/eth_send_raw_transaction.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=eth_sendRawTransaction&apikey=&hex=0xf904808000831cfde080&module=proxy" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"jsonrpc\":\"2.0\",\"id\":1,\"error\":{\"code\":-32000,\"message\":\"rlp: value size exceeds available input length\"}}\n", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:36 GMT", 26 | "Content-Length": "108" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_balance.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=balance&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&module=account&tag=latest" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":\"40807168566070000000000\"}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:26 GMT", 26 | "Content-Length": "64" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_balances.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=balancemulti&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a%2C0x63a9975ba31b0b9626b34300f7f627147df1f526%2C0x198ef1ec325a96cc354c7266a038be8b5c558f67&apikey=&module=account&tag=latest" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"account\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"balance\":\"40807168566070000000000\"},{\"account\":\"0x63a9975ba31b0b9626b34300f7f627147df1f526\",\"balance\":\"332567136222827062478\"},{\"account\":\"0x198ef1ec325a96cc354c7266a038be8b5c558f67\",\"balance\":\"185178830000000000\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:30 GMT", 26 | "Content-Length": "312" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_block_and_uncle_rewards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getblockreward&apikey=&blockno=2165403&module=block" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":{\"blockNumber\":\"2165403\",\"timeStamp\":\"1472533979\",\"blockMiner\":\"0x13a06d3dfe21e0db5c016c03ea7d2509f7f8d1e3\",\"blockReward\":\"5314181600000000000\",\"uncles\":[{\"miner\":\"0xbcdfc35b86bedf72f0cda046a3c16829a2ef41d1\",\"unclePosition\":\"0\",\"blockreward\":\"3750000000000000000\"},{\"miner\":\"0x0d0c9855c722ff0c78f21e43aa275a5b8ea60dce\",\"unclePosition\":\"1\",\"blockreward\":\"3750000000000000000\"}],\"uncleInclusionReward\":\"312500000000000000\"}}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:40 GMT", 26 | "Content-Length": "460" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_blocks_mined.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getminedblocks&address=0x9dd134d14d1e65f84b706d6f205cd5b1cd03a46b&apikey=&blocktype=blocks&module=account&offset=20&page=1" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"3462296\",\"timeStamp\":\"1491118514\",\"blockReward\":\"5194770940000000000\"},{\"blockNumber\":\"2691400\",\"timeStamp\":\"1480072029\",\"blockReward\":\"5086562212310617100\"},{\"blockNumber\":\"2687700\",\"timeStamp\":\"1480018852\",\"blockReward\":\"5003251945421042780\"},{\"blockNumber\":\"2683816\",\"timeStamp\":\"1479962557\",\"blockReward\":\"5001383656218938700\"},{\"blockNumber\":\"2679545\",\"timeStamp\":\"1479897472\",\"blockReward\":\"5020577105778940320\"},{\"blockNumber\":\"2672925\",\"timeStamp\":\"1479801652\",\"blockReward\":\"5036170186197654897\"},{\"blockNumber\":\"2672392\",\"timeStamp\":\"1479793756\",\"blockReward\":\"5040843500234248393\"},{\"blockNumber\":\"2671141\",\"timeStamp\":\"1479775525\",\"blockReward\":\"5006088055733760000\"},{\"blockNumber\":\"2664645\",\"timeStamp\":\"1479683057\",\"blockReward\":\"5008800961000000000\"},{\"blockNumber\":\"2664477\",\"timeStamp\":\"1479680540\",\"blockReward\":\"5014109439959925732\"},{\"blockNumber\":\"2660846\",\"timeStamp\":\"1479630668\",\"blockReward\":\"5000000000000000000\"},{\"blockNumber\":\"2642337\",\"timeStamp\":\"1479367908\",\"blockReward\":\"5004105076553280000\"},{\"blockNumber\":\"2641419\",\"timeStamp\":\"1479355280\",\"blockReward\":\"5000000000000000000\"},{\"blockNumber\":\"2640300\",\"timeStamp\":\"1479339496\",\"blockReward\":\"5023598697640000000\"},{\"blockNumber\":\"2639848\",\"timeStamp\":\"1479332907\",\"blockReward\":\"5005179590280000000\"},{\"blockNumber\":\"2637051\",\"timeStamp\":\"1479293429\",\"blockReward\":\"5002213960000000000\"},{\"blockNumber\":\"2635543\",\"timeStamp\":\"1479271781\",\"blockReward\":\"5014593209013280000\"},{\"blockNumber\":\"2635084\",\"timeStamp\":\"1479264735\",\"blockReward\":\"5029959474298725916\"},{\"blockNumber\":\"2631348\",\"timeStamp\":\"1479210692\",\"blockReward\":\"5000000000000000000\"},{\"blockNumber\":\"2630767\",\"timeStamp\":\"1479202668\",\"blockReward\":\"5003950697023093000\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:24 GMT", 26 | "Content-Length": "1780" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_blocks_mined_offset.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getminedblocks&address=0x9dd134d14d1e65f84b706d6f205cd5b1cd03a46b&apikey=&blocktype=blocks&module=account&offset=8&page=1" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"3462296\",\"timeStamp\":\"1491118514\",\"blockReward\":\"5194770940000000000\"},{\"blockNumber\":\"2691400\",\"timeStamp\":\"1480072029\",\"blockReward\":\"5086562212310617100\"},{\"blockNumber\":\"2687700\",\"timeStamp\":\"1480018852\",\"blockReward\":\"5003251945421042780\"},{\"blockNumber\":\"2683816\",\"timeStamp\":\"1479962557\",\"blockReward\":\"5001383656218938700\"},{\"blockNumber\":\"2679545\",\"timeStamp\":\"1479897472\",\"blockReward\":\"5020577105778940320\"},{\"blockNumber\":\"2672925\",\"timeStamp\":\"1479801652\",\"blockReward\":\"5036170186197654897\"},{\"blockNumber\":\"2672392\",\"timeStamp\":\"1479793756\",\"blockReward\":\"5040843500234248393\"},{\"blockNumber\":\"2671141\",\"timeStamp\":\"1479775525\",\"blockReward\":\"5006088055733760000\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:27 GMT", 26 | "Content-Length": "736" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_blocks_mined_page.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getminedblocks&address=0x9dd134d14d1e65f84b706d6f205cd5b1cd03a46b&apikey=&blocktype=blocks&module=account&offset=4&page=3" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"2664645\",\"timeStamp\":\"1479683057\",\"blockReward\":\"5008800961000000000\"},{\"blockNumber\":\"2664477\",\"timeStamp\":\"1479680540\",\"blockReward\":\"5014109439959925732\"},{\"blockNumber\":\"2660846\",\"timeStamp\":\"1479630668\",\"blockReward\":\"5000000000000000000\"},{\"blockNumber\":\"2642337\",\"timeStamp\":\"1479367908\",\"blockReward\":\"5004105076553280000\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:28 GMT", 26 | "Content-Length": "388" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_contract_execution_status.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getstatus&apikey=&module=transaction&txhash=0x40eb908387324f2b575b4879cd9d7188f69c8fc9d87c901b9e2daaea4b442170" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":{\"isError\":\"0\",\"errDescription\":\"\"}}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:38 GMT", 26 | "Content-Length": "74" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_contract_execution_status_error.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getstatus&apikey=&module=transaction&txhash=0x15f8e5ea1079d9a0bb04a4c58ae5fe7654b5b2b4463375ff7ffb490aa0032f3a" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":{\"isError\":\"1\",\"errDescription\":\"Bad jump destination\"}}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:37 GMT", 26 | "Content-Length": "94" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_eth_price.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=ethprice&apikey=&module=stats" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":{\"ethbtc\":\"0.04259\",\"ethbtc_timestamp\":\"1534984513\",\"ethusd\":\"272.29\",\"ethusd_timestamp\":\"1534984516\"}}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:39 GMT", 26 | "Content-Length": "141" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_eth_supply.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=ethsupply&apikey=&module=stats" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":\"101493235999000000000000000\"}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:39 GMT", 26 | "Content-Length": "68" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_internal_transactions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlistinternal&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=20&page=1&sort=asc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"1959340\",\"timeStamp\":\"1469590563\",\"hash\":\"0x188089c5b945da5eca459fa2edf8df16b983d8b172b72a720632d0f97db85a90\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"7000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959349\",\"timeStamp\":\"1469590725\",\"hash\":\"0x85afcc26847057a86841a8568e881ad1c22e4e9155a347a65af44017ef2763b1\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"5000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959393\",\"timeStamp\":\"1469591193\",\"hash\":\"0x81b904768ecbba7a8ddd69bec5c8bb63e5b28bb973caae4010e4e56c55fc0462\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959740\",\"timeStamp\":\"1469595817\",\"hash\":\"0x5639c2f847fbecf5531355ec8bc903896daf53fd7d1151a3c3fa24ea1ae7956c\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"5000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1961849\",\"timeStamp\":\"1469624584\",\"hash\":\"0x7c3386ae49958663954755c02d16a7ef9c493a84d6328f49ee386d07be6369db\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1961866\",\"timeStamp\":\"1469624867\",\"hash\":\"0x545243f19ede50b8115e6165ffe509fde4bb1abc20f287cd8c49c97f39836efe\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10600000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:30 GMT", 26 | "Content-Length": "2296" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_internal_transactions_by_hash.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlistinternal&apikey=&module=account&txhash=0x40eb908387324f2b575b4879cd9d7188f69c8fc9d87c901b9e2daaea4b442170" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"1743059\",\"timeStamp\":\"1466489498\",\"from\":\"0x2cac6e4b11d6b58f6d3c1c9d5fe8faa89f60e5a2\",\"to\":\"0x66a1c3eaf0f1ffc28d209c0763ed0ca614f3b002\",\"value\":\"7106740000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"isError\":\"0\",\"errCode\":\"\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:30 GMT", 26 | "Content-Length": "320" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_internal_transactions_endblock.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlistinternal&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=1960000&module=account&offset=20&page=1&sort=asc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"1959340\",\"timeStamp\":\"1469590563\",\"hash\":\"0x188089c5b945da5eca459fa2edf8df16b983d8b172b72a720632d0f97db85a90\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"7000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959349\",\"timeStamp\":\"1469590725\",\"hash\":\"0x85afcc26847057a86841a8568e881ad1c22e4e9155a347a65af44017ef2763b1\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"5000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959393\",\"timeStamp\":\"1469591193\",\"hash\":\"0x81b904768ecbba7a8ddd69bec5c8bb63e5b28bb973caae4010e4e56c55fc0462\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959740\",\"timeStamp\":\"1469595817\",\"hash\":\"0x5639c2f847fbecf5531355ec8bc903896daf53fd7d1151a3c3fa24ea1ae7956c\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"5000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:29 GMT", 26 | "Content-Length": "1542" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_internal_transactions_offset.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlistinternal&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=2&page=1&sort=asc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"1959340\",\"timeStamp\":\"1469590563\",\"hash\":\"0x188089c5b945da5eca459fa2edf8df16b983d8b172b72a720632d0f97db85a90\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"7000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959349\",\"timeStamp\":\"1469590725\",\"hash\":\"0x85afcc26847057a86841a8568e881ad1c22e4e9155a347a65af44017ef2763b1\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"5000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:27 GMT", 26 | "Content-Length": "789" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_internal_transactions_page.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlistinternal&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=1&page=2&sort=asc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"1959349\",\"timeStamp\":\"1469590725\",\"hash\":\"0x85afcc26847057a86841a8568e881ad1c22e4e9155a347a65af44017ef2763b1\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"5000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:27 GMT", 26 | "Content-Length": "416" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_internal_transactions_sort.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlistinternal&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=20&page=1&sort=desc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"1961866\",\"timeStamp\":\"1469624867\",\"hash\":\"0x545243f19ede50b8115e6165ffe509fde4bb1abc20f287cd8c49c97f39836efe\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10600000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1961849\",\"timeStamp\":\"1469624584\",\"hash\":\"0x7c3386ae49958663954755c02d16a7ef9c493a84d6328f49ee386d07be6369db\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959740\",\"timeStamp\":\"1469595817\",\"hash\":\"0x5639c2f847fbecf5531355ec8bc903896daf53fd7d1151a3c3fa24ea1ae7956c\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"5000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959393\",\"timeStamp\":\"1469591193\",\"hash\":\"0x81b904768ecbba7a8ddd69bec5c8bb63e5b28bb973caae4010e4e56c55fc0462\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959349\",\"timeStamp\":\"1469590725\",\"hash\":\"0x85afcc26847057a86841a8568e881ad1c22e4e9155a347a65af44017ef2763b1\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"5000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1959340\",\"timeStamp\":\"1469590563\",\"hash\":\"0x188089c5b945da5eca459fa2edf8df16b983d8b172b72a720632d0f97db85a90\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"7000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:26 GMT", 26 | "Content-Length": "2296" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_internal_transactions_startblock.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlistinternal&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=20&page=1&sort=asc&startblock=1960000" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"1961849\",\"timeStamp\":\"1469624584\",\"hash\":\"0x7c3386ae49958663954755c02d16a7ef9c493a84d6328f49ee386d07be6369db\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"},{\"blockNumber\":\"1961866\",\"timeStamp\":\"1469624867\",\"hash\":\"0x545243f19ede50b8115e6165ffe509fde4bb1abc20f287cd8c49c97f39836efe\",\"from\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10600000000000000000000\",\"contractAddress\":\"\",\"input\":\"\",\"type\":\"call\",\"gas\":\"2300\",\"gasUsed\":\"0\",\"traceId\":\"0\",\"isError\":\"0\",\"errCode\":\"\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:31 GMT", 26 | "Content-Length": "794" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_logs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getLogs&address=0x33990122638b9132ca29c723bdf037f1a891a70c&apikey=&fromBlock=0&module=logs&toBlock=latest&topic0=0xf63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a8545&topic0_1_opr=and&topic1=0x72657075746174696f6e00000000000000000000000000000000000000000000&topic1_2_opr=&topic2=&topic2_3_opr=&topic3=" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"address\":\"0x33990122638b9132ca29c723bdf037f1a891a70c\",\"topics\":[\"0xf63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a8545\",\"0x72657075746174696f6e00000000000000000000000000000000000000000000\",\"0x000000000000000000000000d9b2f59f3b5c7b3c67047d2f03c3e8052470be92\"],\"data\":\"0x\",\"blockNumber\":\"0x5c958\",\"timeStamp\":\"0x561d688c\",\"gasPrice\":\"0xba43b7400\",\"gasUsed\":\"0x10682\",\"logIndex\":\"0x\",\"transactionHash\":\"0x0b03498648ae2da924f961dda00dc6bb0a8df15519262b7e012b7d67f4bb7e83\",\"transactionIndex\":\"0x\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:37 GMT", 26 | "Content-Length": "548" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_token_balance.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=tokenbalance&address=0xe04f27eb70e025b78871a2ad7eabe85e61212761&apikey=&contractaddress=0x57d90b64a1a57749b0f932f1a3395792e12e7055&module=account&tag=latest" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":\"135499\"}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:24 GMT", 26 | "Content-Length": "47" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_token_supply.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=tokensupply&apikey=&contractaddress=0x57d90b64a1a57749b0f932f1a3395792e12e7055&module=stats" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":\"21265524714464\"}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:39 GMT", 26 | "Content-Length": "55" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_transaction_receipt_status.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=gettxreceiptstatus&apikey=&module=transaction&txhash=0x513c1ba0bebf66436b5fed86ab668452b7805593c05073eb2d51d3a52f480a76" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":{\"status\":\"1\"}}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:38 GMT", 26 | "Content-Length": "53" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_transaction_receipt_status_pre_byzantium.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=gettxreceiptstatus&apikey=&module=transaction&txhash=0x40eb908387324f2b575b4879cd9d7188f69c8fc9d87c901b9e2daaea4b442170" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":{\"status\":\"\"}}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:38 GMT", 26 | "Content-Length": "52" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_transactions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlist&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=20&page=1&sort=asc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"0\",\"timeStamp\":\"1438269973\",\"hash\":\"GENESIS_ddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"nonce\":\"\",\"blockHash\":\"\",\"transactionIndex\":\"0\",\"from\":\"GENESIS\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"gas\":\"0\",\"gasPrice\":\"0\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"0\",\"gasUsed\":\"0\",\"confirmations\":\"6196278\"},{\"blockNumber\":\"47884\",\"timeStamp\":\"1438947953\",\"hash\":\"0xad1c27dd8d0329dbc400021d7477b34ac41e84365bd54b45a4019a15deb10c0d\",\"nonce\":\"0\",\"blockHash\":\"0xf2988b9870e092f2898662ccdbc06e0e320a08139e9c6be98d0ce372f8611f22\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x2910543af39aba0cd09dbb2d50200b3e800a63d2\",\"value\":\"5000000000000000000\",\"gas\":\"23000\",\"gasPrice\":\"400000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x454e34354139455138\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21612\",\"gasUsed\":\"21612\",\"confirmations\":\"6148394\"},{\"blockNumber\":\"47894\",\"timeStamp\":\"1438948043\",\"hash\":\"0x7e1503d2001cab2f432b56a62a3ee874782c8e33cbd79a664d155a758c1784a2\",\"nonce\":\"1\",\"blockHash\":\"0x2d0a9228f22fe85596d246040d4fd7dc6b1a55920bae02b68e731d55a890b315\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x2910543af39aba0cd09dbb2d50200b3e800a63d2\",\"value\":\"9001000000000000000000\",\"gas\":\"23000\",\"gasPrice\":\"400000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x454e34354139455138\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21612\",\"gasUsed\":\"21612\",\"confirmations\":\"6148384\"},{\"blockNumber\":\"49099\",\"timeStamp\":\"1438968015\",\"hash\":\"0xfa73feae5798f97ad1f2c01fa70424f90f2f4fa81d6fe9698bc4db2690b635fe\",\"nonce\":\"2\",\"blockHash\":\"0xc7e6738277354d82421c8430929c8566c4cac80ce8b2c15512dd226b1f47f146\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x2910543af39aba0cd09dbb2d50200b3e800a63d2\",\"value\":\"5000000000000000000\",\"gas\":\"23000\",\"gasPrice\":\"500000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x454e34354139455138\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21612\",\"gasUsed\":\"21612\",\"confirmations\":\"6147179\"},{\"blockNumber\":\"49109\",\"timeStamp\":\"1438968167\",\"hash\":\"0xb4b836183334510812525c79ee13722783452716f77b3fd5e4b1ec5a21f7a81e\",\"nonce\":\"3\",\"blockHash\":\"0x7549887277630a31450d802a944e8f28397b1e1f15867b6c75633675323633e4\",\"transactionIndex\":\"2\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x2910543af39aba0cd09dbb2d50200b3e800a63d2\",\"value\":\"988950000000000000000\",\"gas\":\"23000\",\"gasPrice\":\"500000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x454e34354139455138\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"64836\",\"gasUsed\":\"21612\",\"confirmations\":\"6147169\"},{\"blockNumber\":\"101773\",\"timeStamp\":\"1439827863\",\"hash\":\"0x70bc1a43c9e80caae6b69fe845ba1567826413a8e42d020837c3b09f9cad11c2\",\"nonce\":\"5\",\"blockHash\":\"0xe802363e95a7e4700058c64f308ff726eba63ec7a40083e65a0c8dd9124578fe\",\"transactionIndex\":\"5\",\"from\":\"0x1a56a50c378d21d0aa544ed9a482300c7f6e78ec\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"84512559000000000000000\",\"gas\":\"21000\",\"gasPrice\":\"100000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"126000\",\"gasUsed\":\"21000\",\"confirmations\":\"6094505\"},{\"blockNumber\":\"269968\",\"timeStamp\":\"1442872420\",\"hash\":\"0xf0ee803e146465fcebfe092041e187920832a474b1c989b36eee7e0dc6b3f09c\",\"nonce\":\"4\",\"blockHash\":\"0x4b55bddbcea00085a00903c0ddb31c2933923054a5f8ff080ec8a8bab2a33e1d\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0xc98756f014149787cee4f74328c4925dc0ce9779\",\"value\":\"700000000000000000000\",\"gas\":\"21000\",\"gasPrice\":\"300000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5926310\"},{\"blockNumber\":\"288379\",\"timeStamp\":\"1443187492\",\"hash\":\"0xda7d393b4995cec859e1fbcdb39dfc756e08b7efb17a658988bc6688fbccbc51\",\"nonce\":\"5\",\"blockHash\":\"0x65aaef94de624a53bc14c87d9a8aa668e50413ccfa2b3c9049befbba2084121b\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x4b321f615455ca04969c5057f459a4dad42781ab\",\"value\":\"5001000000000000000000\",\"gas\":\"21000\",\"gasPrice\":\"300000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5907899\"},{\"blockNumber\":\"301131\",\"timeStamp\":\"1443411359\",\"hash\":\"0x66c11e721b0651c51524f63c085b342efa4a588b4a020530b44e2040242b95bd\",\"nonce\":\"6\",\"blockHash\":\"0x0fa3050e11114f71e88182877adf98c1c32ef714ff4dee2bd9c520d09fc5b65a\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x4c3e0e3c46a5b7222060b774206c92f9cd60d338\",\"value\":\"7000000000000000000000\",\"gas\":\"21000\",\"gasPrice\":\"300000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5895147\"},{\"blockNumber\":\"305627\",\"timeStamp\":\"1443493144\",\"hash\":\"0xfba2e114f7c0d2b365c8af80e5206c6554e4a48e2001f61eaa4bf34ee79d9c30\",\"nonce\":\"7\",\"blockHash\":\"0xbbd6eea24bb6fd1fe7359a937c216665e396c5c80acadf833d50e0f622d0272e\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x7e2592a940d9e751a98dd2dcc80d65935ec5b6c7\",\"value\":\"5000000000000000000000\",\"gas\":\"21000\",\"gasPrice\":\"300000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5890651\"},{\"blockNumber\":\"350303\",\"timeStamp\":\"1444272673\",\"hash\":\"0x2946992f65ed7778c9e40a95dd52a4fd8d15ccae73eef8739219cc122bf8f9ad\",\"nonce\":\"8\",\"blockHash\":\"0x26e0b9754c684804b829c256a13f6f09da22c119e3387cc90c3be2ad678c55b3\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x8c12c0f24f0056f7c4abcca683824f6936f5e117\",\"value\":\"1000681000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5845975\"},{\"blockNumber\":\"350319\",\"timeStamp\":\"1444272955\",\"hash\":\"0x2a7c8d15c8be86cf84dc6751775095b51427b33c9e73c6636cd29e48cebe64c1\",\"nonce\":\"9\",\"blockHash\":\"0x025fd1b5b5e5257f755e9e5d4d02dbf01f1c7a01c3cf7d147461acd4cc47bdfa\",\"transactionIndex\":\"2\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x8c12c0f24f0056f7c4abcca683824f6936f5e117\",\"value\":\"4000681000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"63000\",\"gasUsed\":\"21000\",\"confirmations\":\"5845959\"},{\"blockNumber\":\"379677\",\"timeStamp\":\"1444775223\",\"hash\":\"0xfc9ef543f63a2f39ebedb9cc8e88de166688d57f907c30bbd67053370578f585\",\"nonce\":\"10\",\"blockHash\":\"0xe86fad109e59476e84abc78ea65c3b320cfc0511c3435f2cc7a739b63a26cd44\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"1000000000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5816601\"},{\"blockNumber\":\"379677\",\"timeStamp\":\"1444775223\",\"hash\":\"0xcd055d425f11db9b8dc81e3081a7369a9ad188da5f109457121f72ae223f319c\",\"nonce\":\"11\",\"blockHash\":\"0xe86fad109e59476e84abc78ea65c3b320cfc0511c3435f2cc7a739b63a26cd44\",\"transactionIndex\":\"1\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"4000000000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"42000\",\"gasUsed\":\"21000\",\"confirmations\":\"5816601\"},{\"blockNumber\":\"379688\",\"timeStamp\":\"1444775432\",\"hash\":\"0x7ba14a09d3336a61598a04e97f6147367d437b72930c0a2172685a69d47def9c\",\"nonce\":\"12\",\"blockHash\":\"0xafb42ccb23b8db61e49bc3f2173951480519d288324d4921ff6399fa4137cf95\",\"transactionIndex\":\"1\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x6a0ba7c063f30e200a3c9be07577b4409f29176e\",\"value\":\"4000000000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"259893\",\"gasUsed\":\"21000\",\"confirmations\":\"5816590\"},{\"blockNumber\":\"413150\",\"timeStamp\":\"1445358494\",\"hash\":\"0x744ed86836ed5afcfcacfc79c62a5983a2187ac5f12b3d5b0549b530b145897d\",\"nonce\":\"13\",\"blockHash\":\"0x05fa8c4ddbb92f0478e3b6cd25356685e8891b852db5233b337d72a317148633\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"5001000000000000000000\",\"gas\":\"90000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5783128\"},{\"blockNumber\":\"413522\",\"timeStamp\":\"1445365543\",\"hash\":\"0xf40c824e836da609b76797f771fe701a3e167760abd67b0981bf57f9685bd1cf\",\"nonce\":\"14\",\"blockHash\":\"0x5342d409fa1eb48c14fd55df029514b475fa942f97525b94a2df3a5aa52640ae\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"3001000000000000000000\",\"gas\":\"90000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5782756\"},{\"blockNumber\":\"420161\",\"timeStamp\":\"1445481075\",\"hash\":\"0x77ca9545f31a2f0840ae77c7aea95fd91492ce4e985e0f1dd60227e12022b75f\",\"nonce\":\"15\",\"blockHash\":\"0x5d985d0d50d5db2729a38676d6a70bb8eb75da75680cc2ed941b96d024b4ce26\",\"transactionIndex\":\"3\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"4001000000000000000000\",\"gas\":\"90000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"84000\",\"gasUsed\":\"21000\",\"confirmations\":\"5776117\"},{\"blockNumber\":\"915000\",\"timeStamp\":\"1453943772\",\"hash\":\"0x56296edd06080458694922d8d78ef4a639dc720827ce6fb1641e3cf45fa4231a\",\"nonce\":\"1110\",\"blockHash\":\"0x9f53954719ed9cf4ab3da18f42188e36cc17861dbcf3a37fd796d2d555aff000\",\"transactionIndex\":\"0\",\"from\":\"0x1c10a5aabc2555ee3027d5758c4b7b462605f972\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"2730000000000\",\"gas\":\"21000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5281278\"},{\"blockNumber\":\"1959327\",\"timeStamp\":\"1469590394\",\"hash\":\"0x44e982bc17faea0e228deb2160c1f852c1cbb99a351e45d8f1d11b79a2a37420\",\"nonce\":\"16\",\"blockHash\":\"0xd8bc9a00279dab70de3a617944a400021f30d577fcd826f0aca42bc0e1730924\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"\",\"value\":\"0\",\"gas\":\"229069\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x60606040527f37b0574a00000000000000000000000000000000000000000000000000000000606090815273882fb4240f9a11e197923d0507de9a983ed69239906337b0574a906064906020906004816000876161da5a03f1156002575050604051516000805460ff191690911761010060a860020a031916610100330217815560b59150819061008f90396000f360606040523615601d5760e060020a6000350463c96cd46f8114604f575b608160005460ff161515608357600160a060020a033316600034606082818181858883f19350505050151560b3576002565b60816000546101009004600160a060020a039081163391909116141560b3576000546101009004600160a060020a0316ff5b005b732fb0ebf2936a4027c68b79770f60f497db439ce3600034606082818181858883f19350505050151560b3576002565b56\",\"contractAddress\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"cumulativeGasUsed\":\"245719\",\"gasUsed\":\"129069\",\"confirmations\":\"4236951\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:28 GMT", 26 | "Content-Length": "11761" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_transactions_endblock.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlist&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=5000&module=account&offset=20&page=1&sort=asc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"0\",\"timeStamp\":\"1438269973\",\"hash\":\"GENESIS_ddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"nonce\":\"\",\"blockHash\":\"\",\"transactionIndex\":\"0\",\"from\":\"GENESIS\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"gas\":\"0\",\"gasPrice\":\"0\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"0\",\"gasUsed\":\"0\",\"confirmations\":\"6196278\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:26 GMT", 26 | "Content-Length": "450" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_transactions_offset.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlist&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=5&page=1&sort=asc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"0\",\"timeStamp\":\"1438269973\",\"hash\":\"GENESIS_ddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"nonce\":\"\",\"blockHash\":\"\",\"transactionIndex\":\"0\",\"from\":\"GENESIS\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"10000000000000000000000\",\"gas\":\"0\",\"gasPrice\":\"0\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"0\",\"gasUsed\":\"0\",\"confirmations\":\"6196278\"},{\"blockNumber\":\"47884\",\"timeStamp\":\"1438947953\",\"hash\":\"0xad1c27dd8d0329dbc400021d7477b34ac41e84365bd54b45a4019a15deb10c0d\",\"nonce\":\"0\",\"blockHash\":\"0xf2988b9870e092f2898662ccdbc06e0e320a08139e9c6be98d0ce372f8611f22\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x2910543af39aba0cd09dbb2d50200b3e800a63d2\",\"value\":\"5000000000000000000\",\"gas\":\"23000\",\"gasPrice\":\"400000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x454e34354139455138\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21612\",\"gasUsed\":\"21612\",\"confirmations\":\"6148394\"},{\"blockNumber\":\"47894\",\"timeStamp\":\"1438948043\",\"hash\":\"0x7e1503d2001cab2f432b56a62a3ee874782c8e33cbd79a664d155a758c1784a2\",\"nonce\":\"1\",\"blockHash\":\"0x2d0a9228f22fe85596d246040d4fd7dc6b1a55920bae02b68e731d55a890b315\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x2910543af39aba0cd09dbb2d50200b3e800a63d2\",\"value\":\"9001000000000000000000\",\"gas\":\"23000\",\"gasPrice\":\"400000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x454e34354139455138\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21612\",\"gasUsed\":\"21612\",\"confirmations\":\"6148384\"},{\"blockNumber\":\"49099\",\"timeStamp\":\"1438968015\",\"hash\":\"0xfa73feae5798f97ad1f2c01fa70424f90f2f4fa81d6fe9698bc4db2690b635fe\",\"nonce\":\"2\",\"blockHash\":\"0xc7e6738277354d82421c8430929c8566c4cac80ce8b2c15512dd226b1f47f146\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x2910543af39aba0cd09dbb2d50200b3e800a63d2\",\"value\":\"5000000000000000000\",\"gas\":\"23000\",\"gasPrice\":\"500000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x454e34354139455138\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21612\",\"gasUsed\":\"21612\",\"confirmations\":\"6147179\"},{\"blockNumber\":\"49109\",\"timeStamp\":\"1438968167\",\"hash\":\"0xb4b836183334510812525c79ee13722783452716f77b3fd5e4b1ec5a21f7a81e\",\"nonce\":\"3\",\"blockHash\":\"0x7549887277630a31450d802a944e8f28397b1e1f15867b6c75633675323633e4\",\"transactionIndex\":\"2\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x2910543af39aba0cd09dbb2d50200b3e800a63d2\",\"value\":\"988950000000000000000\",\"gas\":\"23000\",\"gasPrice\":\"500000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x454e34354139455138\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"64836\",\"gasUsed\":\"21612\",\"confirmations\":\"6147169\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:31 GMT", 26 | "Content-Length": "2747" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_transactions_page.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlist&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=20&page=2&sort=asc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"1959340\",\"timeStamp\":\"1469590563\",\"hash\":\"0x188089c5b945da5eca459fa2edf8df16b983d8b172b72a720632d0f97db85a90\",\"nonce\":\"17\",\"blockHash\":\"0xcc3ae1ed2c9052d0cadab75222c2cca8410c101d9282fd8cf907b159ba9a71a1\",\"transactionIndex\":\"11\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"7000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"348394\",\"gasUsed\":\"27964\",\"confirmations\":\"4236938\"},{\"blockNumber\":\"1959349\",\"timeStamp\":\"1469590725\",\"hash\":\"0x85afcc26847057a86841a8568e881ad1c22e4e9155a347a65af44017ef2763b1\",\"nonce\":\"18\",\"blockHash\":\"0xc6fa998c0f584a4780ad6d06eb342dd9bdd9d34555c764e1cbedc6d87e64c34a\",\"transactionIndex\":\"6\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"5000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"328134\",\"gasUsed\":\"27964\",\"confirmations\":\"4236929\"},{\"blockNumber\":\"1959393\",\"timeStamp\":\"1469591193\",\"hash\":\"0x81b904768ecbba7a8ddd69bec5c8bb63e5b28bb973caae4010e4e56c55fc0462\",\"nonce\":\"19\",\"blockHash\":\"0x03dd2d32f8ea317eab05180152b6e959751a32f3de202b3d7caf3b748273e40a\",\"transactionIndex\":\"3\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"115700\",\"gasUsed\":\"27964\",\"confirmations\":\"4236885\"},{\"blockNumber\":\"1959740\",\"timeStamp\":\"1469595817\",\"hash\":\"0x5639c2f847fbecf5531355ec8bc903896daf53fd7d1151a3c3fa24ea1ae7956c\",\"nonce\":\"20\",\"blockHash\":\"0xa9d2868228d7f078285d3bab8695c14ccee741937dc12250ed64bbd8a9c66fdb\",\"transactionIndex\":\"1\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"5000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"48964\",\"gasUsed\":\"27964\",\"confirmations\":\"4236538\"},{\"blockNumber\":\"1961849\",\"timeStamp\":\"1469624584\",\"hash\":\"0x7c3386ae49958663954755c02d16a7ef9c493a84d6328f49ee386d07be6369db\",\"nonce\":\"21\",\"blockHash\":\"0xb1e6f0b4382a0a7e04014b2e66262a8daadb83dcd9bb698eda8ed0ff8650c89c\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"262603\",\"gasUsed\":\"27964\",\"confirmations\":\"4234429\"},{\"blockNumber\":\"1961866\",\"timeStamp\":\"1469624867\",\"hash\":\"0x545243f19ede50b8115e6165ffe509fde4bb1abc20f287cd8c49c97f39836efe\",\"nonce\":\"22\",\"blockHash\":\"0x9ba94fe0b81b32593fd547c39ccbbc2fc14b1bdde4ccc6dccb79e2a304280d50\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10600000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"227901\",\"gasUsed\":\"27964\",\"confirmations\":\"4234412\"},{\"blockNumber\":\"5773191\",\"timeStamp\":\"1528765233\",\"hash\":\"0x3fd72669d115e8ed1da3cf9c02ee0b05d138203c646a8ea7808a308bbab89ea5\",\"nonce\":\"53\",\"blockHash\":\"0xb1ba670fd43bfa2f20aedc22db5cb0d3f20b8b69b74dd9c88eca736304de8991\",\"transactionIndex\":\"29\",\"from\":\"0x770f7a8e74fa129149d0cec3f3669443ee465d2e\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"1000000000000\",\"gas\":\"21000\",\"gasPrice\":\"10000000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"1986533\",\"gasUsed\":\"21000\",\"confirmations\":\"423087\"},{\"blockNumber\":\"5854973\",\"timeStamp\":\"1529978671\",\"hash\":\"0x8117ca5f01b0270d964e84e9dbac4047c15899d3724b926759b16dc4bf4039c3\",\"nonce\":\"4\",\"blockHash\":\"0xb4b84789497c5adfce1d09192d8c8bc37e52dcb021fb36d58a27119c0759446d\",\"transactionIndex\":\"8\",\"from\":\"0x1ce264616911bfd991042ee1dfd3e6df30b3d948\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"0\",\"gas\":\"21000\",\"gasPrice\":\"3000000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"462566\",\"gasUsed\":\"21000\",\"confirmations\":\"341305\"},{\"blockNumber\":\"5854994\",\"timeStamp\":\"1529978973\",\"hash\":\"0x1b5dade100a89bf52b027c27a17d07164a466fd7bc72475682b14da8d4602828\",\"nonce\":\"5\",\"blockHash\":\"0x6ab38e5a4f0749c2881e84f6e64e70a56507fe75b07e621a9239e99dc202d196\",\"transactionIndex\":\"38\",\"from\":\"0x1ce264616911bfd991042ee1dfd3e6df30b3d948\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"1000000000000\",\"gas\":\"21000\",\"gasPrice\":\"1562000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"3109356\",\"gasUsed\":\"21000\",\"confirmations\":\"341284\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:28 GMT", 26 | "Content-Length": "5056" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_transactions_sort.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlist&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=20&page=1&sort=desc&startblock=0" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"5854994\",\"timeStamp\":\"1529978973\",\"hash\":\"0x1b5dade100a89bf52b027c27a17d07164a466fd7bc72475682b14da8d4602828\",\"nonce\":\"5\",\"blockHash\":\"0x6ab38e5a4f0749c2881e84f6e64e70a56507fe75b07e621a9239e99dc202d196\",\"transactionIndex\":\"38\",\"from\":\"0x1ce264616911bfd991042ee1dfd3e6df30b3d948\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"1000000000000\",\"gas\":\"21000\",\"gasPrice\":\"1562000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"3109356\",\"gasUsed\":\"21000\",\"confirmations\":\"341284\"},{\"blockNumber\":\"5854973\",\"timeStamp\":\"1529978671\",\"hash\":\"0x8117ca5f01b0270d964e84e9dbac4047c15899d3724b926759b16dc4bf4039c3\",\"nonce\":\"4\",\"blockHash\":\"0xb4b84789497c5adfce1d09192d8c8bc37e52dcb021fb36d58a27119c0759446d\",\"transactionIndex\":\"8\",\"from\":\"0x1ce264616911bfd991042ee1dfd3e6df30b3d948\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"0\",\"gas\":\"21000\",\"gasPrice\":\"3000000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"462566\",\"gasUsed\":\"21000\",\"confirmations\":\"341305\"},{\"blockNumber\":\"5773191\",\"timeStamp\":\"1528765233\",\"hash\":\"0x3fd72669d115e8ed1da3cf9c02ee0b05d138203c646a8ea7808a308bbab89ea5\",\"nonce\":\"53\",\"blockHash\":\"0xb1ba670fd43bfa2f20aedc22db5cb0d3f20b8b69b74dd9c88eca736304de8991\",\"transactionIndex\":\"29\",\"from\":\"0x770f7a8e74fa129149d0cec3f3669443ee465d2e\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"1000000000000\",\"gas\":\"21000\",\"gasPrice\":\"10000000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"1986533\",\"gasUsed\":\"21000\",\"confirmations\":\"423087\"},{\"blockNumber\":\"1961866\",\"timeStamp\":\"1469624867\",\"hash\":\"0x545243f19ede50b8115e6165ffe509fde4bb1abc20f287cd8c49c97f39836efe\",\"nonce\":\"22\",\"blockHash\":\"0x9ba94fe0b81b32593fd547c39ccbbc2fc14b1bdde4ccc6dccb79e2a304280d50\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10600000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"227901\",\"gasUsed\":\"27964\",\"confirmations\":\"4234412\"},{\"blockNumber\":\"1961849\",\"timeStamp\":\"1469624584\",\"hash\":\"0x7c3386ae49958663954755c02d16a7ef9c493a84d6328f49ee386d07be6369db\",\"nonce\":\"21\",\"blockHash\":\"0xb1e6f0b4382a0a7e04014b2e66262a8daadb83dcd9bb698eda8ed0ff8650c89c\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"262603\",\"gasUsed\":\"27964\",\"confirmations\":\"4234429\"},{\"blockNumber\":\"1959740\",\"timeStamp\":\"1469595817\",\"hash\":\"0x5639c2f847fbecf5531355ec8bc903896daf53fd7d1151a3c3fa24ea1ae7956c\",\"nonce\":\"20\",\"blockHash\":\"0xa9d2868228d7f078285d3bab8695c14ccee741937dc12250ed64bbd8a9c66fdb\",\"transactionIndex\":\"1\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"5000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"48964\",\"gasUsed\":\"27964\",\"confirmations\":\"4236538\"},{\"blockNumber\":\"1959393\",\"timeStamp\":\"1469591193\",\"hash\":\"0x81b904768ecbba7a8ddd69bec5c8bb63e5b28bb973caae4010e4e56c55fc0462\",\"nonce\":\"19\",\"blockHash\":\"0x03dd2d32f8ea317eab05180152b6e959751a32f3de202b3d7caf3b748273e40a\",\"transactionIndex\":\"3\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"115700\",\"gasUsed\":\"27964\",\"confirmations\":\"4236885\"},{\"blockNumber\":\"1959349\",\"timeStamp\":\"1469590725\",\"hash\":\"0x85afcc26847057a86841a8568e881ad1c22e4e9155a347a65af44017ef2763b1\",\"nonce\":\"18\",\"blockHash\":\"0xc6fa998c0f584a4780ad6d06eb342dd9bdd9d34555c764e1cbedc6d87e64c34a\",\"transactionIndex\":\"6\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"5000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"328134\",\"gasUsed\":\"27964\",\"confirmations\":\"4236929\"},{\"blockNumber\":\"1959340\",\"timeStamp\":\"1469590563\",\"hash\":\"0x188089c5b945da5eca459fa2edf8df16b983d8b172b72a720632d0f97db85a90\",\"nonce\":\"17\",\"blockHash\":\"0xcc3ae1ed2c9052d0cadab75222c2cca8410c101d9282fd8cf907b159ba9a71a1\",\"transactionIndex\":\"11\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"7000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"348394\",\"gasUsed\":\"27964\",\"confirmations\":\"4236938\"},{\"blockNumber\":\"1959327\",\"timeStamp\":\"1469590394\",\"hash\":\"0x44e982bc17faea0e228deb2160c1f852c1cbb99a351e45d8f1d11b79a2a37420\",\"nonce\":\"16\",\"blockHash\":\"0xd8bc9a00279dab70de3a617944a400021f30d577fcd826f0aca42bc0e1730924\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"\",\"value\":\"0\",\"gas\":\"229069\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x60606040527f37b0574a00000000000000000000000000000000000000000000000000000000606090815273882fb4240f9a11e197923d0507de9a983ed69239906337b0574a906064906020906004816000876161da5a03f1156002575050604051516000805460ff191690911761010060a860020a031916610100330217815560b59150819061008f90396000f360606040523615601d5760e060020a6000350463c96cd46f8114604f575b608160005460ff161515608357600160a060020a033316600034606082818181858883f19350505050151560b3576002565b60816000546101009004600160a060020a039081163391909116141560b3576000546101009004600160a060020a0316ff5b005b732fb0ebf2936a4027c68b79770f60f497db439ce3600034606082818181858883f19350505050151560b3576002565b56\",\"contractAddress\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"cumulativeGasUsed\":\"245719\",\"gasUsed\":\"129069\",\"confirmations\":\"4236951\"},{\"blockNumber\":\"915000\",\"timeStamp\":\"1453943772\",\"hash\":\"0x56296edd06080458694922d8d78ef4a639dc720827ce6fb1641e3cf45fa4231a\",\"nonce\":\"1110\",\"blockHash\":\"0x9f53954719ed9cf4ab3da18f42188e36cc17861dbcf3a37fd796d2d555aff000\",\"transactionIndex\":\"0\",\"from\":\"0x1c10a5aabc2555ee3027d5758c4b7b462605f972\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"2730000000000\",\"gas\":\"21000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5281278\"},{\"blockNumber\":\"420161\",\"timeStamp\":\"1445481075\",\"hash\":\"0x77ca9545f31a2f0840ae77c7aea95fd91492ce4e985e0f1dd60227e12022b75f\",\"nonce\":\"15\",\"blockHash\":\"0x5d985d0d50d5db2729a38676d6a70bb8eb75da75680cc2ed941b96d024b4ce26\",\"transactionIndex\":\"3\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"4001000000000000000000\",\"gas\":\"90000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"84000\",\"gasUsed\":\"21000\",\"confirmations\":\"5776117\"},{\"blockNumber\":\"413522\",\"timeStamp\":\"1445365543\",\"hash\":\"0xf40c824e836da609b76797f771fe701a3e167760abd67b0981bf57f9685bd1cf\",\"nonce\":\"14\",\"blockHash\":\"0x5342d409fa1eb48c14fd55df029514b475fa942f97525b94a2df3a5aa52640ae\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"3001000000000000000000\",\"gas\":\"90000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5782756\"},{\"blockNumber\":\"413150\",\"timeStamp\":\"1445358494\",\"hash\":\"0x744ed86836ed5afcfcacfc79c62a5983a2187ac5f12b3d5b0549b530b145897d\",\"nonce\":\"13\",\"blockHash\":\"0x05fa8c4ddbb92f0478e3b6cd25356685e8891b852db5233b337d72a317148633\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"5001000000000000000000\",\"gas\":\"90000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5783128\"},{\"blockNumber\":\"379688\",\"timeStamp\":\"1444775432\",\"hash\":\"0x7ba14a09d3336a61598a04e97f6147367d437b72930c0a2172685a69d47def9c\",\"nonce\":\"12\",\"blockHash\":\"0xafb42ccb23b8db61e49bc3f2173951480519d288324d4921ff6399fa4137cf95\",\"transactionIndex\":\"1\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x6a0ba7c063f30e200a3c9be07577b4409f29176e\",\"value\":\"4000000000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"259893\",\"gasUsed\":\"21000\",\"confirmations\":\"5816590\"},{\"blockNumber\":\"379677\",\"timeStamp\":\"1444775223\",\"hash\":\"0xcd055d425f11db9b8dc81e3081a7369a9ad188da5f109457121f72ae223f319c\",\"nonce\":\"11\",\"blockHash\":\"0xe86fad109e59476e84abc78ea65c3b320cfc0511c3435f2cc7a739b63a26cd44\",\"transactionIndex\":\"1\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"4000000000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"42000\",\"gasUsed\":\"21000\",\"confirmations\":\"5816601\"},{\"blockNumber\":\"379677\",\"timeStamp\":\"1444775223\",\"hash\":\"0xfc9ef543f63a2f39ebedb9cc8e88de166688d57f907c30bbd67053370578f585\",\"nonce\":\"10\",\"blockHash\":\"0xe86fad109e59476e84abc78ea65c3b320cfc0511c3435f2cc7a739b63a26cd44\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x74723606be0bbdc49939362a182a2ef4980ebb4e\",\"value\":\"1000000000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5816601\"},{\"blockNumber\":\"350319\",\"timeStamp\":\"1444272955\",\"hash\":\"0x2a7c8d15c8be86cf84dc6751775095b51427b33c9e73c6636cd29e48cebe64c1\",\"nonce\":\"9\",\"blockHash\":\"0x025fd1b5b5e5257f755e9e5d4d02dbf01f1c7a01c3cf7d147461acd4cc47bdfa\",\"transactionIndex\":\"2\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x8c12c0f24f0056f7c4abcca683824f6936f5e117\",\"value\":\"4000681000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"63000\",\"gasUsed\":\"21000\",\"confirmations\":\"5845959\"},{\"blockNumber\":\"350303\",\"timeStamp\":\"1444272673\",\"hash\":\"0x2946992f65ed7778c9e40a95dd52a4fd8d15ccae73eef8739219cc122bf8f9ad\",\"nonce\":\"8\",\"blockHash\":\"0x26e0b9754c684804b829c256a13f6f09da22c119e3387cc90c3be2ad678c55b3\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x8c12c0f24f0056f7c4abcca683824f6936f5e117\",\"value\":\"1000681000000000000000\",\"gas\":\"100000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5845975\"},{\"blockNumber\":\"305627\",\"timeStamp\":\"1443493144\",\"hash\":\"0xfba2e114f7c0d2b365c8af80e5206c6554e4a48e2001f61eaa4bf34ee79d9c30\",\"nonce\":\"7\",\"blockHash\":\"0xbbd6eea24bb6fd1fe7359a937c216665e396c5c80acadf833d50e0f622d0272e\",\"transactionIndex\":\"0\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x7e2592a940d9e751a98dd2dcc80d65935ec5b6c7\",\"value\":\"5000000000000000000000\",\"gas\":\"21000\",\"gasPrice\":\"300000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5890651\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:29 GMT", 26 | "Content-Length": "11833" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_transactions_startblock.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=txlist&address=0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a&apikey=&endblock=&module=account&offset=20&page=1&sort=asc&startblock=500000" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"915000\",\"timeStamp\":\"1453943772\",\"hash\":\"0x56296edd06080458694922d8d78ef4a639dc720827ce6fb1641e3cf45fa4231a\",\"nonce\":\"1110\",\"blockHash\":\"0x9f53954719ed9cf4ab3da18f42188e36cc17861dbcf3a37fd796d2d555aff000\",\"transactionIndex\":\"0\",\"from\":\"0x1c10a5aabc2555ee3027d5758c4b7b462605f972\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"2730000000000\",\"gas\":\"21000\",\"gasPrice\":\"50000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"21000\",\"gasUsed\":\"21000\",\"confirmations\":\"5281278\"},{\"blockNumber\":\"1959327\",\"timeStamp\":\"1469590394\",\"hash\":\"0x44e982bc17faea0e228deb2160c1f852c1cbb99a351e45d8f1d11b79a2a37420\",\"nonce\":\"16\",\"blockHash\":\"0xd8bc9a00279dab70de3a617944a400021f30d577fcd826f0aca42bc0e1730924\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"\",\"value\":\"0\",\"gas\":\"229069\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x60606040527f37b0574a00000000000000000000000000000000000000000000000000000000606090815273882fb4240f9a11e197923d0507de9a983ed69239906337b0574a906064906020906004816000876161da5a03f1156002575050604051516000805460ff191690911761010060a860020a031916610100330217815560b59150819061008f90396000f360606040523615601d5760e060020a6000350463c96cd46f8114604f575b608160005460ff161515608357600160a060020a033316600034606082818181858883f19350505050151560b3576002565b60816000546101009004600160a060020a039081163391909116141560b3576000546101009004600160a060020a0316ff5b005b732fb0ebf2936a4027c68b79770f60f497db439ce3600034606082818181858883f19350505050151560b3576002565b56\",\"contractAddress\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"cumulativeGasUsed\":\"245719\",\"gasUsed\":\"129069\",\"confirmations\":\"4236951\"},{\"blockNumber\":\"1959340\",\"timeStamp\":\"1469590563\",\"hash\":\"0x188089c5b945da5eca459fa2edf8df16b983d8b172b72a720632d0f97db85a90\",\"nonce\":\"17\",\"blockHash\":\"0xcc3ae1ed2c9052d0cadab75222c2cca8410c101d9282fd8cf907b159ba9a71a1\",\"transactionIndex\":\"11\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"7000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"348394\",\"gasUsed\":\"27964\",\"confirmations\":\"4236938\"},{\"blockNumber\":\"1959349\",\"timeStamp\":\"1469590725\",\"hash\":\"0x85afcc26847057a86841a8568e881ad1c22e4e9155a347a65af44017ef2763b1\",\"nonce\":\"18\",\"blockHash\":\"0xc6fa998c0f584a4780ad6d06eb342dd9bdd9d34555c764e1cbedc6d87e64c34a\",\"transactionIndex\":\"6\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"5000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"328134\",\"gasUsed\":\"27964\",\"confirmations\":\"4236929\"},{\"blockNumber\":\"1959393\",\"timeStamp\":\"1469591193\",\"hash\":\"0x81b904768ecbba7a8ddd69bec5c8bb63e5b28bb973caae4010e4e56c55fc0462\",\"nonce\":\"19\",\"blockHash\":\"0x03dd2d32f8ea317eab05180152b6e959751a32f3de202b3d7caf3b748273e40a\",\"transactionIndex\":\"3\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"115700\",\"gasUsed\":\"27964\",\"confirmations\":\"4236885\"},{\"blockNumber\":\"1959740\",\"timeStamp\":\"1469595817\",\"hash\":\"0x5639c2f847fbecf5531355ec8bc903896daf53fd7d1151a3c3fa24ea1ae7956c\",\"nonce\":\"20\",\"blockHash\":\"0xa9d2868228d7f078285d3bab8695c14ccee741937dc12250ed64bbd8a9c66fdb\",\"transactionIndex\":\"1\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"5000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"48964\",\"gasUsed\":\"27964\",\"confirmations\":\"4236538\"},{\"blockNumber\":\"1961849\",\"timeStamp\":\"1469624584\",\"hash\":\"0x7c3386ae49958663954755c02d16a7ef9c493a84d6328f49ee386d07be6369db\",\"nonce\":\"21\",\"blockHash\":\"0xb1e6f0b4382a0a7e04014b2e66262a8daadb83dcd9bb698eda8ed0ff8650c89c\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10000000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"262603\",\"gasUsed\":\"27964\",\"confirmations\":\"4234429\"},{\"blockNumber\":\"1961866\",\"timeStamp\":\"1469624867\",\"hash\":\"0x545243f19ede50b8115e6165ffe509fde4bb1abc20f287cd8c49c97f39836efe\",\"nonce\":\"22\",\"blockHash\":\"0x9ba94fe0b81b32593fd547c39ccbbc2fc14b1bdde4ccc6dccb79e2a304280d50\",\"transactionIndex\":\"5\",\"from\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"to\":\"0x1bb0ac60363e320bc45fdb15aed226fb59c88e44\",\"value\":\"10600000000000000000000\",\"gas\":\"127964\",\"gasPrice\":\"20000000000\",\"isError\":\"0\",\"txreceipt_status\":\"\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"227901\",\"gasUsed\":\"27964\",\"confirmations\":\"4234412\"},{\"blockNumber\":\"5773191\",\"timeStamp\":\"1528765233\",\"hash\":\"0x3fd72669d115e8ed1da3cf9c02ee0b05d138203c646a8ea7808a308bbab89ea5\",\"nonce\":\"53\",\"blockHash\":\"0xb1ba670fd43bfa2f20aedc22db5cb0d3f20b8b69b74dd9c88eca736304de8991\",\"transactionIndex\":\"29\",\"from\":\"0x770f7a8e74fa129149d0cec3f3669443ee465d2e\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"1000000000000\",\"gas\":\"21000\",\"gasPrice\":\"10000000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"1986533\",\"gasUsed\":\"21000\",\"confirmations\":\"423087\"},{\"blockNumber\":\"5854973\",\"timeStamp\":\"1529978671\",\"hash\":\"0x8117ca5f01b0270d964e84e9dbac4047c15899d3724b926759b16dc4bf4039c3\",\"nonce\":\"4\",\"blockHash\":\"0xb4b84789497c5adfce1d09192d8c8bc37e52dcb021fb36d58a27119c0759446d\",\"transactionIndex\":\"8\",\"from\":\"0x1ce264616911bfd991042ee1dfd3e6df30b3d948\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"0\",\"gas\":\"21000\",\"gasPrice\":\"3000000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"462566\",\"gasUsed\":\"21000\",\"confirmations\":\"341305\"},{\"blockNumber\":\"5854994\",\"timeStamp\":\"1529978973\",\"hash\":\"0x1b5dade100a89bf52b027c27a17d07164a466fd7bc72475682b14da8d4602828\",\"nonce\":\"5\",\"blockHash\":\"0x6ab38e5a4f0749c2881e84f6e64e70a56507fe75b07e621a9239e99dc202d196\",\"transactionIndex\":\"38\",\"from\":\"0x1ce264616911bfd991042ee1dfd3e6df30b3d948\",\"to\":\"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a\",\"value\":\"1000000000000\",\"gas\":\"21000\",\"gasPrice\":\"1562000000\",\"isError\":\"0\",\"txreceipt_status\":\"1\",\"input\":\"0x\",\"contractAddress\":\"\",\"cumulativeGasUsed\":\"3109356\",\"gasUsed\":\"21000\",\"confirmations\":\"341284\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:31 GMT", 26 | "Content-Length": "6798" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_uncles_mined.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getminedblocks&address=0x9dd134d14d1e65f84b706d6f205cd5b1cd03a46b&apikey=&blocktype=uncles&module=account&offset=20&page=1" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"2691795\",\"timeStamp\":\"1480077905\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2681249\",\"timeStamp\":\"1479923845\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2679472\",\"timeStamp\":\"1479896464\",\"blockReward\":\"3750000000000000000\"},{\"blockNumber\":\"2677512\",\"timeStamp\":\"1479868144\",\"blockReward\":\"3750000000000000000\"},{\"blockNumber\":\"2576818\",\"timeStamp\":\"1478437614\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2572899\",\"timeStamp\":\"1478381015\",\"blockReward\":\"2500000000000000000\"},{\"blockNumber\":\"2558106\",\"timeStamp\":\"1478166518\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2553464\",\"timeStamp\":\"1478098376\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2431561\",\"timeStamp\":\"1476349451\",\"blockReward\":\"3750000000000000000\"},{\"blockNumber\":\"2404179\",\"timeStamp\":\"1475954451\",\"blockReward\":\"3750000000000000000\"},{\"blockNumber\":\"2398340\",\"timeStamp\":\"1475874069\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2396072\",\"timeStamp\":\"1475840003\",\"blockReward\":\"1875000000000000000\"},{\"blockNumber\":\"2394398\",\"timeStamp\":\"1475816504\",\"blockReward\":\"3750000000000000000\"},{\"blockNumber\":\"2394137\",\"timeStamp\":\"1475812441\",\"blockReward\":\"1875000000000000000\"},{\"blockNumber\":\"2391821\",\"timeStamp\":\"1475775443\",\"blockReward\":\"2500000000000000000\"},{\"blockNumber\":\"2370477\",\"timeStamp\":\"1475469555\",\"blockReward\":\"2500000000000000000\"},{\"blockNumber\":\"2368429\",\"timeStamp\":\"1475441215\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2365194\",\"timeStamp\":\"1475394642\",\"blockReward\":\"3750000000000000000\"},{\"blockNumber\":\"2363037\",\"timeStamp\":\"1475364544\",\"blockReward\":\"1875000000000000000\"},{\"blockNumber\":\"2362317\",\"timeStamp\":\"1475354117\",\"blockReward\":\"3750000000000000000\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:25 GMT", 26 | "Content-Length": "1780" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_uncles_mined_offset.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getminedblocks&address=0x9dd134d14d1e65f84b706d6f205cd5b1cd03a46b&apikey=&blocktype=uncles&module=account&offset=3&page=1" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"2691795\",\"timeStamp\":\"1480077905\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2681249\",\"timeStamp\":\"1479923845\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2679472\",\"timeStamp\":\"1479896464\",\"blockReward\":\"3750000000000000000\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:25 GMT", 26 | "Content-Length": "301" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /fixture/vcr_cassettes/get_uncles_mined_page.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "body": "", 5 | "headers": [], 6 | "method": "get", 7 | "options": { 8 | "recv_timeout": 20000, 9 | "connect_timeout": 20000 10 | }, 11 | "request_body": "", 12 | "url": "https://api.etherscan.io/api?action=getminedblocks&address=0x9dd134d14d1e65f84b706d6f205cd5b1cd03a46b&apikey=&blocktype=uncles&module=account&offset=4&page=3" 13 | }, 14 | "response": { 15 | "binary": false, 16 | "body": "{\"status\":\"1\",\"message\":\"OK\",\"result\":[{\"blockNumber\":\"2431561\",\"timeStamp\":\"1476349451\",\"blockReward\":\"3750000000000000000\"},{\"blockNumber\":\"2404179\",\"timeStamp\":\"1475954451\",\"blockReward\":\"3750000000000000000\"},{\"blockNumber\":\"2398340\",\"timeStamp\":\"1475874069\",\"blockReward\":\"3125000000000000000\"},{\"blockNumber\":\"2396072\",\"timeStamp\":\"1475840003\",\"blockReward\":\"1875000000000000000\"}]}", 17 | "headers": { 18 | "Cache-Control": "private", 19 | "Content-Type": "application/json; charset=utf-8", 20 | "Server": "Microsoft-IIS/10.0", 21 | "Access-Control-Allow-Origin": "*", 22 | "Access-Control-Allow-Headers": "Content-Type", 23 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 24 | "X-Frame-Options": "SAMEORIGIN", 25 | "Date": "Thu, 23 Aug 2018 00:36:24 GMT", 26 | "Content-Length": "388" 27 | }, 28 | "status_code": 200, 29 | "type": "ok" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /lib/etherscan.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan do 2 | @moduledoc """ 3 | Documentation for Etherscan. 4 | """ 5 | 6 | alias Etherscan.API 7 | 8 | defdelegate get_balance(address), to: API.Accounts 9 | defdelegate get_balances(addresses), to: API.Accounts 10 | defdelegate get_transactions(address), to: API.Accounts 11 | defdelegate get_transactions(address, params), to: API.Accounts 12 | defdelegate get_internal_transactions(address), to: API.Accounts 13 | defdelegate get_internal_transactions(address, params), to: API.Accounts 14 | defdelegate get_internal_transactions_by_hash(transaction_hash), to: API.Accounts 15 | defdelegate get_blocks_mined(address), to: API.Accounts 16 | defdelegate get_blocks_mined(address, params), to: API.Accounts 17 | defdelegate get_uncles_mined(address), to: API.Accounts 18 | defdelegate get_uncles_mined(address, params), to: API.Accounts 19 | defdelegate get_token_balance(address, token_address), to: API.Accounts 20 | 21 | defdelegate get_block_and_uncle_rewards(block_number), to: API.Blocks 22 | 23 | defdelegate get_contract_abi(address), to: API.Contracts 24 | defdelegate get_contract_source(address), to: API.Contracts 25 | 26 | defdelegate get_logs(params), to: API.Logs 27 | 28 | defdelegate eth_block_number, to: API.Proxy 29 | defdelegate eth_get_block_by_number(tag), to: API.Proxy 30 | defdelegate eth_get_uncle_by_block_number_and_index(tag, index), to: API.Proxy 31 | defdelegate eth_get_block_transaction_count_by_number(tag), to: API.Proxy 32 | defdelegate eth_get_transaction_by_hash(transaction_hash), to: API.Proxy 33 | defdelegate eth_get_transaction_by_block_number_and_index(tag, index), to: API.Proxy 34 | defdelegate eth_get_transaction_count(address), to: API.Proxy 35 | defdelegate eth_send_raw_transaction(hex), to: API.Proxy 36 | defdelegate eth_get_transaction_receipt(transaction_hash), to: API.Proxy 37 | defdelegate eth_call(to, data), to: API.Proxy 38 | defdelegate eth_get_code(address, tag), to: API.Proxy 39 | defdelegate eth_get_storage_at(address, position), to: API.Proxy 40 | defdelegate eth_gas_price, to: API.Proxy 41 | defdelegate eth_estimate_gas(params), to: API.Proxy 42 | 43 | defdelegate get_token_supply(token_address), to: API.Stats 44 | defdelegate get_eth_supply, to: API.Stats 45 | defdelegate get_eth_price, to: API.Stats 46 | 47 | defdelegate get_contract_execution_status(transaction_hash), to: API.Transactions 48 | defdelegate get_transaction_receipt_status(transaction_hash), to: API.Transactions 49 | end 50 | -------------------------------------------------------------------------------- /lib/etherscan/api.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.API do 2 | @moduledoc """ 3 | Etherscan base API module. 4 | """ 5 | 6 | use Etherscan.Constants 7 | alias Etherscan.Util 8 | 9 | defmacro __using__(_opts) do 10 | quote do 11 | import Etherscan.API 12 | end 13 | end 14 | 15 | @doc """ 16 | Checks if the provided value is a valid Ethereum address. 17 | Currently very naive... 18 | """ 19 | defmacro is_address(value) do 20 | quote do 21 | is_binary(unquote(value)) and binary_part(unquote(value), 0, 2) == "0x" 22 | end 23 | end 24 | 25 | defdelegate wrap(value, tag), to: Util 26 | defdelegate format_balance(balance), to: Util 27 | defdelegate hex_to_number(value), to: Util, as: :safe_hex_to_number 28 | 29 | @spec merge_params(params :: map(), default :: map()) :: map() 30 | def merge_params(params, default \\ %{}) do 31 | default 32 | |> Map.merge(params) 33 | |> Map.take(default |> Map.keys()) 34 | end 35 | 36 | @spec get(module :: String.t(), action :: String.t(), params :: map()) :: String.t() 37 | def get(module, action, params \\ %{}) do 38 | module 39 | |> build_url(action, params) 40 | |> HTTPoison.get!([], request_opts()) 41 | |> Map.get(:body) 42 | end 43 | 44 | @spec parse(response :: any(), opts :: Keyword.t()) :: any() 45 | def parse(response, opts \\ []) do 46 | response 47 | |> Poison.decode!(opts) 48 | |> extract() 49 | end 50 | 51 | @spec extract(response :: map()) :: any() 52 | defp extract(%{"error" => error}), do: error 53 | defp extract(%{"result" => result}), do: result 54 | defp extract(response), do: response 55 | 56 | @spec build_url(module :: String.t(), action :: String.t(), params :: map()) :: String.t() 57 | defp build_url(module, action, params) do 58 | params 59 | |> Map.put(:action, action) 60 | |> Map.put(:module, module) 61 | |> Map.put(:apikey, api_key()) 62 | |> URI.encode_query() 63 | |> (&"#{network_url()}?#{&1}").() 64 | end 65 | 66 | @spec api_key :: String.t() 67 | defp api_key do 68 | Application.get_env(:etherscan, :api_key, "") 69 | end 70 | 71 | @spec network_url :: String.t() 72 | defp network_url do 73 | case Application.get_env(:etherscan, :network) do 74 | network when network in @api_networks -> 75 | Keyword.get(@api_network_urls, network) 76 | 77 | _ -> 78 | Keyword.get(@api_network_urls, :default) 79 | end 80 | end 81 | 82 | @spec request_opts :: Keyword.t() 83 | defp request_opts do 84 | opts = Application.get_env(:etherscan, :request, []) 85 | Keyword.merge(@api_request_opts, opts) 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/etherscan/api/accounts.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.API.Accounts do 2 | @moduledoc """ 3 | Module to wrap Etherscan account endpoints. 4 | 5 | [Etherscan API Documentation](https://etherscan.io/apis#accounts) 6 | """ 7 | 8 | use Etherscan.API 9 | use Etherscan.Constants 10 | alias Etherscan.{MinedBlock, MinedUncle, Transaction, InternalTransaction} 11 | 12 | @account_transaction_default_params %{ 13 | startblock: 0, 14 | endblock: nil, 15 | sort: "asc", 16 | page: 1, 17 | offset: 20 18 | } 19 | 20 | @blocks_mined_default_params %{ 21 | page: 1, 22 | offset: 20 23 | } 24 | 25 | @doc """ 26 | Get ether balance for a single `address`. 27 | 28 | ## Example 29 | 30 | iex> Etherscan.get_balance("#{@test_address1}") 31 | {:ok, #{@test_address1_balance}} 32 | """ 33 | @spec get_balance(address :: String.t()) :: {:ok, non_neg_integer()} | {:error, atom()} 34 | def get_balance(address) when is_address(address) do 35 | "account" 36 | |> get("balance", %{address: address, tag: "latest"}) 37 | |> parse() 38 | |> format_balance() 39 | |> wrap(:ok) 40 | end 41 | 42 | def get_balance(_), do: @error_invalid_address 43 | 44 | @doc """ 45 | Get ether balance for a list of multiple `addresses`, up to a maximum of 20. 46 | 47 | ## Example 48 | 49 | iex> addresses = [ 50 | "#{@test_address1}", 51 | "#{@test_address2}", 52 | ] 53 | iex> Etherscan.get_balances(addresses) 54 | {:ok, [#{@test_address1_balance}, #{@test_address2_balance}]} 55 | """ 56 | @spec get_balances(addresses :: list(String.t())) :: {:ok, map()} | {:error, atom()} 57 | def get_balances([head | _] = addresses) 58 | when is_list(addresses) and is_address(head) and length(addresses) <= 20 do 59 | "account" 60 | |> get("balancemulti", %{address: Enum.join(addresses, ","), tag: "latest"}) 61 | |> parse() 62 | |> Enum.map(fn account -> 63 | Map.update(account, "balance", 0, &format_balance/1) 64 | end) 65 | |> wrap(:ok) 66 | end 67 | 68 | def get_balances(_), do: @error_invalid_addresses 69 | 70 | @doc """ 71 | Get a list of 'Normal' transactions by `address`. 72 | 73 | Returns up to a maximum of the last 10,000 transactions only. 74 | 75 | ## Example 76 | 77 | iex> params = %{ 78 | page: 1, # Page number 79 | offset: 10, # Max records returned 80 | sort: "asc", # Sort returned records 81 | startblock: 0, # Start block number 82 | endblock: 99999999, # End block number 83 | } 84 | iex> Etherscan.get_transactions("#{@test_address1}", params) 85 | {:ok, [%Etherscan.Transaction{}]} 86 | """ 87 | @spec get_transactions(address :: String.t(), params :: map()) :: 88 | {:ok, list(Transaction.t())} | {:error, atom()} 89 | def get_transactions(address, params \\ %{}) 90 | 91 | def get_transactions(address, params) when is_address(address) do 92 | params = 93 | params 94 | |> merge_params(@account_transaction_default_params) 95 | |> Map.put(:address, address) 96 | 97 | "account" 98 | |> get("txlist", params) 99 | |> parse(as: %{"result" => [%Transaction{}]}) 100 | |> wrap(:ok) 101 | end 102 | 103 | def get_transactions(_, _), do: @error_invalid_address 104 | 105 | @doc """ 106 | Get a list of 'Internal' transactions by `address`. 107 | 108 | Returns up to a maximum of the last 10,000 transactions only. 109 | 110 | ## Example 111 | 112 | iex> params = %{ 113 | page: 1, # Page number 114 | offset: 10, # Max records returned 115 | sort: "asc", # Sort returned records 116 | startblock: 0, # Start block number 117 | endblock: 99999999, # End block number 118 | } 119 | iex> Etherscan.get_internal_transactions("#{@test_address1}", params) 120 | {:ok, [%Etherscan.InternalTransaction{}]} 121 | """ 122 | @spec get_internal_transactions(address :: String.t(), params :: map()) :: 123 | {:ok, list(InternalTransaction.t())} | {:error, atom()} 124 | def get_internal_transactions(address, params \\ %{}) 125 | 126 | def get_internal_transactions(address, params) when is_address(address) do 127 | params = 128 | params 129 | |> merge_params(@account_transaction_default_params) 130 | |> Map.put(:address, address) 131 | 132 | "account" 133 | |> get("txlistinternal", params) 134 | |> parse(as: %{"result" => [%InternalTransaction{}]}) 135 | |> wrap(:ok) 136 | end 137 | 138 | def get_internal_transactions(_, _), do: @error_invalid_address 139 | 140 | @doc """ 141 | Get a list of 'Internal Transactions' by `transaction_hash`. 142 | 143 | Returns up to a maximum of the last 10,000 transactions only. 144 | 145 | ## Example 146 | 147 | iex> Etherscan.get_internal_transactions_by_hash("#{@test_transaction_hash}") 148 | {:ok, [%Etherscan.InternalTransaction{}]} 149 | """ 150 | @spec get_internal_transactions_by_hash(transaction_hash :: String.t()) :: 151 | {:ok, list(InternalTransaction.t())} | {:error, atom()} 152 | def get_internal_transactions_by_hash(transaction_hash) when is_address(transaction_hash) do 153 | "account" 154 | |> get("txlistinternal", %{txhash: transaction_hash}) 155 | |> parse(as: %{"result" => [%InternalTransaction{hash: transaction_hash}]}) 156 | |> wrap(:ok) 157 | end 158 | 159 | def get_internal_transactions_by_hash(_), do: @error_invalid_transaction_hash 160 | 161 | @doc """ 162 | Get a list of blocks mined by `address`. 163 | 164 | ## Example 165 | 166 | iex> params = %{ 167 | page: 1, # Page number 168 | offset: 10, # Max records returned 169 | } 170 | iex> Etherscan.get_blocks_mined("#{@test_miner_address}", params) 171 | {:ok, [%Etherscan.MinedBlock{}]} 172 | """ 173 | @spec get_blocks_mined(address :: String.t(), params :: map()) :: 174 | {:ok, list(MinedBlock.t())} | {:error, atom()} 175 | def get_blocks_mined(address, params \\ %{}) 176 | 177 | def get_blocks_mined(address, params) when is_address(address) do 178 | params = 179 | params 180 | |> merge_params(@blocks_mined_default_params) 181 | |> Map.put(:blocktype, "blocks") 182 | |> Map.put(:address, address) 183 | 184 | "account" 185 | |> get("getminedblocks", params) 186 | |> parse(as: %{"result" => [%MinedBlock{}]}) 187 | |> wrap(:ok) 188 | end 189 | 190 | def get_blocks_mined(_, _), do: @error_invalid_address 191 | 192 | @doc """ 193 | Get a list of uncles mined by `address`. 194 | 195 | ## Example 196 | 197 | iex> params = %{ 198 | page: 1, # Page number 199 | offset: 10, # Max records returned 200 | } 201 | iex> Etherscan.get_uncles_mined("#{@test_miner_address}", params) 202 | {:ok, [%Etherscan.MinedUncle{}]} 203 | """ 204 | @spec get_uncles_mined(address :: String.t(), params :: map()) :: 205 | {:ok, list(MinedUncle.t())} | {:error, atom()} 206 | def get_uncles_mined(address, params \\ %{}) 207 | 208 | def get_uncles_mined(address, params) when is_address(address) do 209 | params = 210 | params 211 | |> merge_params(@blocks_mined_default_params) 212 | |> Map.put(:blocktype, "uncles") 213 | |> Map.put(:address, address) 214 | 215 | "account" 216 | |> get("getminedblocks", params) 217 | |> parse(as: %{"result" => [%MinedUncle{}]}) 218 | |> wrap(:ok) 219 | end 220 | 221 | def get_uncles_mined(_, _), do: @error_invalid_address 222 | 223 | @doc """ 224 | Get the ERC20 token balance of the `address` for token at `token_address`. 225 | 226 | [More Info](https://etherscan.io/apis#tokens) 227 | 228 | ## Example 229 | 230 | iex> address = "#{@test_token_owner_address}" 231 | iex> token_address = "#{@test_token_address}" 232 | iex> Etherscan.get_token_balance(address, token_address) 233 | {:ok, #{@test_token_address_balance}} 234 | """ 235 | @spec get_token_balance(address :: String.t(), token_address :: String.t()) :: 236 | {:ok, non_neg_integer()} | {:error, atom()} 237 | def get_token_balance(address, token_address) 238 | when is_address(address) and is_address(token_address) do 239 | "account" 240 | |> get("tokenbalance", %{address: address, contractaddress: token_address, tag: "latest"}) 241 | |> parse() 242 | |> String.to_integer() 243 | |> wrap(:ok) 244 | end 245 | 246 | def get_token_balance(address, token_address) 247 | when not is_address(address) and is_address(token_address), 248 | do: @error_invalid_address 249 | 250 | def get_token_balance(address, token_address) 251 | when not is_address(token_address) and is_address(address), 252 | do: @error_invalid_token_address 253 | 254 | def get_token_balance(_, _), do: @error_invalid_address_and_token_address 255 | end 256 | -------------------------------------------------------------------------------- /lib/etherscan/api/blocks.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.API.Blocks do 2 | @moduledoc """ 3 | Module to wrap Etherscan block endpoints. 4 | 5 | [Etherscan API Documentation](https://etherscan.io/apis#blocks) 6 | """ 7 | 8 | use Etherscan.API 9 | use Etherscan.Constants 10 | alias Etherscan.{BlockReward, BlockRewardUncle} 11 | 12 | @doc """ 13 | Get block and uncle rewards by `block_number`. 14 | 15 | ## Example 16 | 17 | iex> Etherscan.get_block_and_uncle_rewards("#{@test_block_number}") 18 | {:ok, %Etherscan.BlockReward{uncles: [%Etherscan.BlockRewardUncle{}]}} 19 | """ 20 | @spec get_block_and_uncle_rewards(block_number :: non_neg_integer()) :: 21 | {:ok, BlockReward.t()} :: {:error, atom()} 22 | def get_block_and_uncle_rewards(block_number) 23 | when is_integer(block_number) and block_number >= 0 do 24 | "block" 25 | |> get("getblockreward", %{blockno: block_number}) 26 | |> parse(as: %{"result" => %BlockReward{uncles: [%BlockRewardUncle{}]}}) 27 | |> wrap(:ok) 28 | end 29 | 30 | def get_block_and_uncle_rewards(_), do: @error_invalid_block_number 31 | end 32 | -------------------------------------------------------------------------------- /lib/etherscan/api/contracts.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.API.Contracts do 2 | @moduledoc """ 3 | Module to wrap Etherscan contract endpoints. 4 | 5 | [Etherscan API Documentation](https://etherscan.io/apis#contracts) 6 | """ 7 | 8 | use Etherscan.API 9 | use Etherscan.Constants 10 | 11 | @doc """ 12 | Get contract ABI for contracts with verified source code, by `address`. 13 | 14 | [More Info](https://etherscan.io/contractsVerified) 15 | 16 | ## Example 17 | 18 | iex> Etherscan.get_contract_abi("#{@test_contract_address}") 19 | {:ok, [%{"name" => _, ...} | _] = contract_abi} 20 | """ 21 | @spec get_contract_abi(address :: String.t()) :: {:ok, list()} | {:error, atom()} 22 | def get_contract_abi(address) when is_address(address) do 23 | "contract" 24 | |> get("getabi", %{address: address}) 25 | |> parse() 26 | # Decode again. ABI result is JSON 27 | |> Poison.decode!() 28 | |> wrap(:ok) 29 | end 30 | 31 | def get_contract_abi(_), do: @error_invalid_address 32 | 33 | @doc """ 34 | Get contract source code for contacts with verified source code 35 | 36 | [More Info](https://etherscan.io/contractsVerified) 37 | 38 | iex> Etherscan.get_contract_source("#{@test_contract_address}") 39 | {:ok, [%{"name" => _, ...} | _] = contract_source} 40 | """ 41 | def get_contract_source(address) when is_address(address) do 42 | "contract" 43 | |> get("getsourcecode", %{address: address}) 44 | |> parse() 45 | |> wrap(:ok) 46 | end 47 | 48 | def get_contract_source(_), do: @error_invalid_address 49 | end 50 | -------------------------------------------------------------------------------- /lib/etherscan/api/logs.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.API.Logs do 2 | @moduledoc """ 3 | Module to wrap Etherscan event log endpoints. 4 | 5 | [Etherscan API Documentation](https://etherscan.io/apis#logs) 6 | """ 7 | 8 | use Etherscan.API 9 | use Etherscan.Constants 10 | alias Etherscan.Log 11 | 12 | @operators ["and", "or"] 13 | 14 | @get_logs_default_params %{ 15 | address: nil, 16 | fromBlock: 0, 17 | toBlock: "latest", 18 | topic0: nil, 19 | topic0_1_opr: nil, 20 | topic1: nil, 21 | topic1_2_opr: nil, 22 | topic2: nil, 23 | topic2_3_opr: nil, 24 | topic3: nil 25 | } 26 | 27 | @doc """ 28 | Returns a list of valid topic operators for `get_logs/1`. 29 | 30 | ## Example 31 | 32 | iex> Etherscan.API.Logs.operators() 33 | #{@operators |> inspect()} 34 | """ 35 | @spec operators :: list(String.t()) 36 | def operators, do: @operators 37 | 38 | @doc """ 39 | An alternative API to the native eth_getLogs. 40 | 41 | See `operators/0` for all valid topic operators. 42 | 43 | `params[fromBlock|toBlock]` can be a block number or the string `"latest"`. 44 | 45 | Either the `address` or `topic(x)` params are required. 46 | 47 | For API performance and security considerations, **only the first 1000 results 48 | are returned.** 49 | 50 | ## Example 51 | 52 | iex> params = %{ 53 | address: "#{@test_topic_address}", # Ethereum blockchain address 54 | fromBlock: 0, # Start block number 55 | toBlock: "latest", # End block number 56 | topic0: "#{@test_topic_0}", # The first topic filter 57 | topic0_1_opr: "and", # The topic operator between topic0 and topic1 58 | topic1: "", # The second topic filter 59 | topic1_2_opr: "and", # The topic operator between topic1 and topic2 60 | topic2: "", # The third topic filter 61 | topic2_3_opr: "and", # The topic operator between topic2 and topic3 62 | topic3: "", # The fourth topic filter 63 | } 64 | iex> Etherscan.get_logs(params) 65 | {:ok, [%Etherscan.Log{}]} 66 | """ 67 | @spec get_logs(params :: map()) :: {:ok, list(Log.t())} | {:error, atom()} 68 | def get_logs(%{address: address}) when not is_address(address), do: @error_invalid_address 69 | 70 | def get_logs(%{fromBlock: from_block}) 71 | when not (is_integer(from_block) or from_block == "latest"), 72 | do: @error_invalid_from_block 73 | 74 | def get_logs(%{toBlock: to_block}) when not (is_integer(to_block) or to_block == "latest"), 75 | do: @error_invalid_to_block 76 | 77 | def get_logs(%{topic0_1_opr: operator}) when operator not in @operators, 78 | do: @error_invalid_topic0_1_opr 79 | 80 | def get_logs(%{topic1_2_opr: operator}) when operator not in @operators, 81 | do: @error_invalid_topic1_2_opr 82 | 83 | def get_logs(%{topic2_3_opr: operator}) when operator not in @operators, 84 | do: @error_invalid_topic2_3_opr 85 | 86 | def get_logs(params) when is_map(params) do 87 | params = merge_params(params, @get_logs_default_params) 88 | 89 | "logs" 90 | |> get("getLogs", params) 91 | |> parse(as: %{"result" => [%Log{}]}) 92 | |> wrap(:ok) 93 | end 94 | 95 | def get_logs(_), do: @error_invalid_params 96 | end 97 | -------------------------------------------------------------------------------- /lib/etherscan/api/proxy.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.API.Proxy do 2 | @moduledoc """ 3 | Module to wrap Etherscan Geth/Parity proxy endpoints. 4 | 5 | [Etherscan API Documentation](https://etherscan.io/apis#proxy) 6 | """ 7 | 8 | use Etherscan.API 9 | use Etherscan.Constants 10 | alias Etherscan.{ProxyBlock, ProxyTransaction, ProxyTransactionReceipt} 11 | 12 | @eth_estimate_gas_default_params %{ 13 | to: nil, 14 | value: nil, 15 | gasPrice: nil, 16 | gas: nil 17 | } 18 | 19 | @doc """ 20 | Returns the number of most recent block. 21 | 22 | ## Example 23 | 24 | iex> Etherscan.eth_block_number() 25 | {:ok, "#{@test_proxy_block_number}"} 26 | """ 27 | def eth_block_number do 28 | "proxy" 29 | |> get("eth_blockNumber") 30 | |> parse() 31 | |> hex_to_number() 32 | |> wrap(:ok) 33 | end 34 | 35 | @doc """ 36 | Returns information about a block by block number. 37 | 38 | ## Example 39 | 40 | iex> Etherscan.eth_get_block_by_number("#{@test_proxy_block_tag}") 41 | {:ok, %Etherscan.ProxyBlock{}} 42 | """ 43 | def eth_get_block_by_number(tag) when is_binary(tag) do 44 | "proxy" 45 | |> get("eth_getBlockByNumber", %{tag: tag, boolean: true}) 46 | |> parse(as: %{"result" => %ProxyBlock{transactions: [%ProxyTransaction{}]}}) 47 | |> wrap(:ok) 48 | end 49 | 50 | def eth_get_block_by_number(_), do: @error_invalid_tag 51 | 52 | @doc """ 53 | Returns information about a uncle by block number. 54 | 55 | ## Example 56 | 57 | iex> Etherscan.eth_get_uncle_by_block_number_and_index("#{@test_proxy_uncle_tag}", "#{ 58 | @test_proxy_index 59 | }") 60 | {:ok, %{"number" => "#{@test_proxy_uncle_block_tag}", ...}} 61 | """ 62 | def eth_get_uncle_by_block_number_and_index(tag, index) 63 | when is_binary(tag) and is_binary(index) do 64 | "proxy" 65 | |> get("eth_getUncleByBlockNumberAndIndex", %{tag: tag, index: index}) 66 | |> parse() 67 | |> wrap(:ok) 68 | end 69 | 70 | def eth_get_uncle_by_block_number_and_index(tag, index) 71 | when not is_binary(tag) and is_binary(index), 72 | do: @error_invalid_tag 73 | 74 | def eth_get_uncle_by_block_number_and_index(tag, index) 75 | when not is_binary(index) and is_binary(tag), 76 | do: @error_invalid_index 77 | 78 | def eth_get_uncle_by_block_number_and_index(_, _), do: @error_invalid_tag_and_index 79 | 80 | @doc """ 81 | Returns the number of transactions in a block from a block matching the 82 | given block number. 83 | 84 | ## Example 85 | 86 | iex> Etherscan.eth_get_block_transaction_count_by_number("#{@test_proxy_transaction_tag}") 87 | {:ok, "#{@test_proxy_block_transaction_count}"} 88 | """ 89 | def eth_get_block_transaction_count_by_number(tag) when is_binary(tag) do 90 | "proxy" 91 | |> get("eth_getBlockTransactionCountByNumber", %{tag: tag}) 92 | |> parse() 93 | |> hex_to_number() 94 | |> wrap(:ok) 95 | end 96 | 97 | def eth_get_block_transaction_count_by_number(_), do: @error_invalid_tag 98 | 99 | @doc """ 100 | Returns the information about a transaction requested by transaction hash. 101 | 102 | ## Example 103 | 104 | iex> transaction_hash = "#{@test_proxy_transaction_hash}" 105 | iex> Etherscan.eth_get_transaction_by_hash(transaction_hash) 106 | {:ok, %Etherscan.ProxyTransaction{}} 107 | """ 108 | def eth_get_transaction_by_hash(transaction_hash) when is_binary(transaction_hash) do 109 | "proxy" 110 | |> get("eth_getTransactionByHash", %{txhash: transaction_hash}) 111 | |> parse(as: %{"result" => %ProxyTransaction{}}) 112 | |> wrap(:ok) 113 | end 114 | 115 | def eth_get_transaction_by_hash(_), do: @error_invalid_transaction_hash 116 | 117 | @doc """ 118 | Returns information about a transaction by block number and transaction 119 | index position. 120 | 121 | ## Example 122 | 123 | iex> Etherscan.eth_get_transaction_by_block_number_and_index("#{@test_proxy_block_tag}", "#{ 124 | @test_proxy_index 125 | }") 126 | {:ok, %Etherscan.ProxyTransaction{}} 127 | """ 128 | def eth_get_transaction_by_block_number_and_index(tag, index) 129 | when is_binary(tag) and is_binary(index) do 130 | "proxy" 131 | |> get("eth_getTransactionByBlockNumberAndIndex", %{tag: tag, index: index}) 132 | |> parse(as: %{"result" => %ProxyTransaction{}}) 133 | |> wrap(:ok) 134 | end 135 | 136 | def eth_get_transaction_by_block_number_and_index(tag, index) 137 | when not is_binary(tag) and is_binary(index), 138 | do: @error_invalid_tag 139 | 140 | def eth_get_transaction_by_block_number_and_index(tag, index) 141 | when not is_binary(index) and is_binary(tag), 142 | do: @error_invalid_index 143 | 144 | def eth_get_transaction_by_block_number_and_index(_, _), do: @error_invalid_tag_and_index 145 | 146 | @doc """ 147 | Returns the number of transactions sent from an address. 148 | 149 | ## Example 150 | 151 | iex> Etherscan.eth_get_transaction_count("#{@test_proxy_address}") 152 | {:ok, #{@test_proxy_transaction_count}} 153 | """ 154 | def eth_get_transaction_count(address) when is_binary(address) do 155 | "proxy" 156 | |> get("eth_getTransactionCount", %{address: address, tag: "latest"}) 157 | |> parse() 158 | |> hex_to_number() 159 | |> wrap(:ok) 160 | end 161 | 162 | def eth_get_transaction_count(_), do: @error_invalid_address 163 | 164 | @doc """ 165 | Creates new message call transaction or a contract creation for 166 | signed transactions. 167 | 168 | Replace the hex value with your raw hex encoded transaction that you want 169 | to send. 170 | 171 | ## Example 172 | 173 | iex> Etherscan.eth_send_raw_transaction("#{@test_proxy_hex}") 174 | {:ok, } 175 | """ 176 | def eth_send_raw_transaction(hex) when is_binary(hex) do 177 | "proxy" 178 | |> get("eth_sendRawTransaction", %{hex: hex}) 179 | |> parse() 180 | |> wrap(:ok) 181 | end 182 | 183 | def eth_send_raw_transaction(_), do: @error_invalid_hex 184 | 185 | @doc """ 186 | Returns the receipt of a transaction by transaction hash. 187 | 188 | ## Example 189 | 190 | iex> transaction_hash = "#{@test_proxy_transaction_hash}" 191 | iex> Etherscan.eth_get_transaction_receipt(transaction_hash) 192 | {:ok, %Etherscan.ProxyTransactionReceipt{}} 193 | """ 194 | def eth_get_transaction_receipt(transaction_hash) when is_binary(transaction_hash) do 195 | "proxy" 196 | |> get("eth_getTransactionReceipt", %{txhash: transaction_hash}) 197 | |> parse(as: %{"result" => %ProxyTransactionReceipt{}}) 198 | |> wrap(:ok) 199 | end 200 | 201 | def eth_get_transaction_receipt(_), do: @error_invalid_transaction_hash 202 | 203 | @doc """ 204 | Executes a new message call immediately without creating a transaction on 205 | the block chain. 206 | 207 | ## Example 208 | 209 | iex> Etherscan.eth_call("#{@test_proxy_to}", "#{@test_proxy_data}") 210 | {:ok, "#{@test_proxy_eth_call_result}"} 211 | """ 212 | def eth_call(to, data) when is_binary(to) and is_binary(data) do 213 | "proxy" 214 | |> get("eth_call", %{to: to, data: data, tag: "latest"}) 215 | |> parse() 216 | |> wrap(:ok) 217 | end 218 | 219 | def eth_call(to, data) when not is_binary(to) and is_binary(data), do: @error_invalid_to 220 | def eth_call(to, data) when not is_binary(data) and is_binary(to), do: @error_invalid_data 221 | def eth_call(_, _), do: @error_invalid_to_and_data 222 | 223 | @doc """ 224 | Returns code at a given address. 225 | 226 | ## Example 227 | 228 | iex> Etherscan.eth_get_code("#{@test_proxy_code_address}", "latest") 229 | {:ok, "#{@test_proxy_code_result}"} 230 | """ 231 | def eth_get_code(address, tag) when is_binary(address) and is_binary(tag) do 232 | "proxy" 233 | |> get("eth_getCode", %{address: address, tag: tag}) 234 | |> parse() 235 | |> wrap(:ok) 236 | end 237 | 238 | def eth_get_code(address, tag) when not is_binary(address) and is_binary(tag), 239 | do: @error_invalid_address 240 | 241 | def eth_get_code(address, tag) when not is_binary(tag) and is_binary(address), 242 | do: @error_invalid_tag 243 | 244 | def eth_get_code(_, _), do: @error_invalid_address_and_tag 245 | 246 | @doc """ 247 | Returns the value from a storage position at a given address. 248 | 249 | ## Example 250 | 251 | iex> Etherscan.eth_get_storage_at("#{@test_proxy_storage_address}", "#{ 252 | @test_proxy_storage_position 253 | }") 254 | {:ok, "#{@test_proxy_storage_result}"} 255 | """ 256 | def eth_get_storage_at(address, position) when is_binary(address) and is_binary(position) do 257 | "proxy" 258 | |> get("eth_getStorageAt", %{address: address, position: position, tag: "latest"}) 259 | |> parse() 260 | |> wrap(:ok) 261 | end 262 | 263 | def eth_get_storage_at(address, position) when not is_binary(address) and is_binary(position), 264 | do: @error_invalid_address 265 | 266 | def eth_get_storage_at(address, position) when not is_binary(position) and is_binary(address), 267 | do: @error_invalid_position 268 | 269 | def eth_get_storage_at(_, _), do: @error_invalid_address_and_position 270 | 271 | @doc """ 272 | Returns the current price per gas in wei. 273 | 274 | ## Example 275 | 276 | iex> Etherscan.eth_gas_price() 277 | {:ok, "#{@test_proxy_current_gas}"} 278 | """ 279 | def eth_gas_price do 280 | "proxy" 281 | |> get("eth_gasPrice") 282 | |> parse() 283 | |> hex_to_number() 284 | |> wrap(:ok) 285 | end 286 | 287 | @doc """ 288 | Makes a call or transaction, which won't be added to the blockchain and 289 | returns the used gas, which can be used for estimating the used gas. 290 | 291 | ## Example 292 | 293 | iex> params = %{ 294 | to: "#{@test_proxy_estimate_to}", 295 | value: "#{@test_proxy_value}", 296 | gasPrice: "#{@test_proxy_gas_price}", 297 | gas: "#{@test_proxy_gas}", 298 | } 299 | iex> Etherscan.eth_estimate_gas(params) 300 | {:ok, } 301 | """ 302 | def eth_estimate_gas(%{to: _, value: _, gasPrice: _, gas: _} = params) when is_map(params) do 303 | params = merge_params(params, @eth_estimate_gas_default_params) 304 | 305 | "proxy" 306 | |> get("eth_estimateGas", params) 307 | |> parse() 308 | |> wrap(:ok) 309 | end 310 | 311 | def eth_estimate_gas(_), do: @error_invalid_params 312 | end 313 | -------------------------------------------------------------------------------- /lib/etherscan/api/stats.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.API.Stats do 2 | @moduledoc """ 3 | Module to wrap Etherscan stats endpoints. 4 | 5 | [Etherscan API Documentation](https://etherscan.io/apis#stats) 6 | """ 7 | 8 | use Etherscan.API 9 | use Etherscan.Constants 10 | 11 | @doc """ 12 | Get total supply of ether. 13 | 14 | ## Example 15 | 16 | iex> Etherscan.get_eth_supply() 17 | {:ok, #{@test_eth_supply}} 18 | """ 19 | @spec get_eth_supply :: {:ok, non_neg_integer()} 20 | def get_eth_supply do 21 | "stats" 22 | |> get("ethsupply") 23 | |> parse() 24 | |> format_balance() 25 | |> wrap(:ok) 26 | end 27 | 28 | @doc """ 29 | Get ether price. 30 | 31 | ## Example 32 | 33 | iex> Etherscan.get_eth_price() 34 | {:ok, %{"ethbtc" => #{@test_eth_btc_price}, "ethusd" => #{@test_eth_usd_price}}} 35 | """ 36 | @spec get_eth_price :: {:ok, map()} 37 | def get_eth_price do 38 | "stats" 39 | |> get("ethprice") 40 | |> parse() 41 | |> wrap(:ok) 42 | end 43 | 44 | @doc """ 45 | Get total supply of ERC20 token, by `token_address`. 46 | 47 | [More Info](https://etherscan.io/apis#tokens) 48 | 49 | ## Example 50 | 51 | iex> Etherscan.get_token_supply("#{@test_token_address}") 52 | {:ok, #{@test_token_supply}} 53 | """ 54 | @spec get_token_supply(token_address :: String.t()) :: 55 | {:ok, non_neg_integer()} | {:error, atom()} 56 | def get_token_supply(token_address) when is_address(token_address) do 57 | "stats" 58 | |> get("tokensupply", %{contractaddress: token_address}) 59 | |> parse() 60 | |> String.to_integer() 61 | |> wrap(:ok) 62 | end 63 | 64 | def get_token_supply(_), do: @error_invalid_token_address 65 | end 66 | -------------------------------------------------------------------------------- /lib/etherscan/api/transactions.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.API.Transactions do 2 | @moduledoc """ 3 | Module to wrap Etherscan transaction endpoints. 4 | 5 | [Etherscan API Documentation](https://etherscan.io/apis#transactions) 6 | """ 7 | 8 | use Etherscan.API 9 | use Etherscan.Constants 10 | alias Etherscan.ContractStatus 11 | 12 | @doc """ 13 | Check contract execution status by `transaction_hash`. 14 | 15 | ## Examples 16 | 17 | iex> transaction_hash = "#{@test_transaction_hash}" 18 | iex> response = Etherscan.API.Transactions.get_contract_execution_status(transaction_hash) 19 | {:ok, %ContractStatus{errDescription: "", isError: "0"}} = response 20 | 21 | iex> transaction_hash = "#{@test_invalid_transaction_hash}" 22 | iex> response = Etherscan.API.Transactions.get_contract_execution_status(transaction_hash) 23 | {:ok, %ContractStatus{errDescription: "Bad jump destination", isError: "1"}} = response 24 | """ 25 | @spec get_contract_execution_status(transaction_hash :: String.t()) :: 26 | {:ok, ContractStatus.t()} | {:error, atom()} 27 | def get_contract_execution_status(transaction_hash) when is_address(transaction_hash) do 28 | "transaction" 29 | |> get("getstatus", %{txhash: transaction_hash}) 30 | |> parse(as: %{"result" => %ContractStatus{}}) 31 | |> wrap(:ok) 32 | end 33 | 34 | def get_contract_execution_status(_), do: @error_invalid_transaction_hash 35 | 36 | @doc """ 37 | Check transaction receipt status by `transaction_hash`. 38 | 39 | Pre-Byzantium fork transactions return null/empty value. 40 | """ 41 | @spec get_transaction_receipt_status(transaction_hash :: String.t()) :: 42 | {:ok, any()} | {:error, atom()} 43 | def get_transaction_receipt_status(transaction_hash) when is_address(transaction_hash) do 44 | "transaction" 45 | |> get("gettxreceiptstatus", %{txhash: transaction_hash}) 46 | |> parse() 47 | |> wrap(:ok) 48 | end 49 | 50 | def get_transaction_receipt_status(_), do: @error_invalid_transaction_hash 51 | end 52 | -------------------------------------------------------------------------------- /lib/etherscan/constants.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.Constants do 2 | @moduledoc """ 3 | A module of compile-time constants that don't have to be repeatedly defined 4 | """ 5 | 6 | defmacro __using__(_) do 7 | quote do 8 | # API 9 | @api_request_opts [ 10 | timeout: 20_000, 11 | recv_timeout: 20_000 12 | ] 13 | @api_network_urls [ 14 | default: "https://api.etherscan.io/api", 15 | ropsten: "https://api-ropsten.etherscan.io/api", 16 | kovan: "https://api-kovan.etherscan.io/api", 17 | rinkeby: "https://api-rinkeby.etherscan.io/api" 18 | ] 19 | @api_networks Keyword.keys(@api_network_urls) 20 | 21 | # Errors 22 | @error_invalid_address {:error, :invalid_address} 23 | @error_invalid_addresses {:error, :invalid_addresses} 24 | @error_invalid_transaction_hash {:error, :invalid_transaction_hash} 25 | @error_invalid_token_address {:error, :invalid_token_address} 26 | @error_invalid_index {:error, :invalid_index} 27 | @error_invalid_tag_and_index {:error, :invalid_tag_and_index} 28 | @error_invalid_tag {:error, :invalid_tag} 29 | @error_invalid_hex {:error, :invalid_hex} 30 | @error_invalid_to {:error, :invalid_to} 31 | @error_invalid_data {:error, :invalid_data} 32 | @error_invalid_to_and_data {:error, :invalid_to_and_data} 33 | @error_invalid_address_and_tag {:error, :invalid_address_and_tag} 34 | @error_invalid_position {:error, :invalid_position} 35 | @error_invalid_address_and_position {:error, :invalid_address_and_position} 36 | @error_invalid_params {:error, :invalid_params} 37 | @error_invalid_from_block {:error, :invalid_from_block} 38 | @error_invalid_to_block {:error, :invalid_to_block} 39 | @error_invalid_topic0_1_opr {:error, :invalid_topic0_1_opr} 40 | @error_invalid_topic1_2_opr {:error, :invalid_topic1_2_opr} 41 | @error_invalid_topic2_3_opr {:error, :invalid_topic2_3_opr} 42 | @error_invalid_block_number {:error, :invalid_block_number} 43 | @error_invalid_address_and_token_address {:error, :invalid_address_and_token_address} 44 | 45 | # Tests 46 | @test_address1 "0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a" 47 | @test_address2 "0x63a9975ba31b0b9626b34300f7f627147df1f526" 48 | @test_address3 "0x198ef1ec325a96cc354c7266a038be8b5c558f67" 49 | @test_miner_address "0x9dd134d14d1e65f84b706d6f205cd5b1cd03a46b" 50 | @test_token_address "0x57d90b64a1a57749b0f932f1a3395792e12e7055" 51 | @test_contract_address "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413" 52 | @test_token_owner_address "0xe04f27eb70e025b78871a2ad7eabe85e61212761" 53 | @test_transaction_hash "0x40eb908387324f2b575b4879cd9d7188f69c8fc9d87c901b9e2daaea4b442170" 54 | @test_transaction_hash_2 "0x513c1ba0bebf66436b5fed86ab668452b7805593c05073eb2d51d3a52f480a76" 55 | @test_invalid_transaction_hash "0x15f8e5ea1079d9a0bb04a4c58ae5fe7654b5b2b4463375ff7ffb490aa0032f3a" 56 | 57 | @test_topic_address "0x33990122638b9132ca29c723bdf037f1a891a70c" 58 | @test_topic_0 "0xf63780e752c6a54a94fc52715dbc5518a3b4c3c2833d301a204226548a2a8545" 59 | @test_topic_1 "0x72657075746174696f6e00000000000000000000000000000000000000000000" 60 | 61 | @test_address1_balance "40807.16856607000227086246" 62 | @test_address2_balance "332.56713622282705955513" 63 | @test_address3_balance "0.18517882999999998872" 64 | @test_token_address_balance 135_499 65 | 66 | @test_token_supply 21_265_524_714_464 67 | @test_block_number 2_165_403 68 | @test_eth_supply "101493235.99899999797344207764" 69 | @test_eth_btc_price "0.04259" 70 | @test_eth_usd_price "272.29" 71 | 72 | @test_proxy_block_number 6_196_278 73 | @test_proxy_block_tag "0x10d4f" 74 | @test_proxy_uncle_tag "0x210A9B" 75 | @test_proxy_uncle_block_tag "0x210a99" 76 | @test_proxy_transaction_tag "0x10FB78" 77 | @test_proxy_index "0x0" 78 | @test_proxy_transaction_hash "0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1" 79 | @test_proxy_address "0x2910543af39aba0cd09dbb2d50200b3e800a63d2" 80 | @test_proxy_hex "0xf904808000831cfde080" 81 | @test_proxy_to "0xAEEF46DB4855E25702F8237E8f403FddcaF931C0" 82 | @test_proxy_data "0x70a08231000000000000000000000000e16359506c028e51f16be38986ec5746251e9724" 83 | @test_proxy_code_address "0xf75e354c5edc8efed9b59ee9f67a80845ade7d0c" 84 | @test_proxy_storage_address "0x6e03d9cce9d60f3e9f2597e13cd4c54c55330cfd" 85 | @test_proxy_storage_position "0x0" 86 | @test_proxy_estimate_to "0xf0160428a8552ac9bb7e050d90eeade4ddd52843" 87 | @test_proxy_value "0xff22" 88 | @test_proxy_gas_price "0x051da038cc" 89 | @test_proxy_gas "0xffffff" 90 | @test_proxy_current_gas 2_100_000_000 91 | @test_proxy_block_transaction_count 3 92 | @test_proxy_transaction_count 44893 93 | @test_proxy_eth_call_result "0x00000000000000000000000000000000000000000000000000601d8888141c00" 94 | @test_proxy_storage_result "0x0000000000000000000000003d0768da09ce77d25e2d998e6a7b6ed4b9116c2d" 95 | @test_proxy_code_result "0x3660008037602060003660003473273930d21e01ee25e4c219b63259d214872220a261235a5a03f21560015760206000f3" 96 | end 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /lib/etherscan/types/block_reward.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.BlockReward do 2 | @moduledoc """ 3 | Etherscan module for the BlockReward struct. 4 | """ 5 | 6 | alias Etherscan.BlockRewardUncle 7 | 8 | @attributes [ 9 | :blockMiner, 10 | :blockNumber, 11 | :blockReward, 12 | :timeStamp, 13 | :uncleInclusionReward, 14 | :uncles 15 | ] 16 | 17 | defstruct @attributes 18 | 19 | @type t :: %__MODULE__{ 20 | blockMiner: String.t(), 21 | blockNumber: String.t(), 22 | blockReward: String.t(), 23 | timeStamp: String.t(), 24 | uncleInclusionReward: String.t(), 25 | uncles: list(BlockRewardUncle.t()) 26 | } 27 | end 28 | -------------------------------------------------------------------------------- /lib/etherscan/types/block_reward_uncle.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.BlockRewardUncle do 2 | @moduledoc """ 3 | Etherscan module for the BlockRewardUncle struct. 4 | """ 5 | 6 | @attributes [ 7 | :blockreward, 8 | :miner, 9 | :unclePosition 10 | ] 11 | 12 | defstruct @attributes 13 | 14 | @type t :: %__MODULE__{ 15 | blockreward: String.t(), 16 | miner: String.t(), 17 | unclePosition: String.t() 18 | } 19 | end 20 | -------------------------------------------------------------------------------- /lib/etherscan/types/contract_status.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.ContractStatus do 2 | @moduledoc """ 3 | Etherscan module for the ContractStatus struct. 4 | """ 5 | 6 | @attributes [ 7 | :isError, 8 | :errDescription 9 | ] 10 | 11 | defstruct @attributes 12 | 13 | @type t :: %__MODULE__{ 14 | isError: String.t(), 15 | errDescription: String.t() 16 | } 17 | end 18 | -------------------------------------------------------------------------------- /lib/etherscan/types/internal_transaction.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.InternalTransaction do 2 | @moduledoc """ 3 | Etherscan module for the InternalTransaction struct. 4 | """ 5 | 6 | @attributes [ 7 | :blockNumber, 8 | :contractAddress, 9 | :errCode, 10 | :from, 11 | :gas, 12 | :gasUsed, 13 | :hash, 14 | :input, 15 | :isError, 16 | :timeStamp, 17 | :to, 18 | :traceId, 19 | :type, 20 | :value 21 | ] 22 | 23 | defstruct @attributes 24 | 25 | @type t :: %__MODULE__{ 26 | blockNumber: String.t(), 27 | contractAddress: String.t(), 28 | errCode: String.t(), 29 | from: String.t(), 30 | gas: String.t(), 31 | gasUsed: String.t(), 32 | hash: String.t(), 33 | input: String.t(), 34 | isError: String.t(), 35 | timeStamp: String.t(), 36 | to: String.t(), 37 | traceId: String.t(), 38 | type: String.t(), 39 | value: String.t() 40 | } 41 | end 42 | -------------------------------------------------------------------------------- /lib/etherscan/types/log.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.Log do 2 | @moduledoc """ 3 | Etherscan module for the Log struct. 4 | """ 5 | 6 | @attributes [ 7 | :address, 8 | :blockNumber, 9 | :data, 10 | :gasPrice, 11 | :gasUsed, 12 | :logIndex, 13 | :timeStamp, 14 | :topics, 15 | :transactionHash, 16 | :transactionIndex 17 | ] 18 | 19 | defstruct @attributes 20 | 21 | @type t :: %__MODULE__{ 22 | address: String.t(), 23 | blockNumber: String.t(), 24 | data: String.t(), 25 | gasPrice: String.t(), 26 | gasUsed: String.t(), 27 | logIndex: String.t(), 28 | timeStamp: String.t(), 29 | topics: list(String.t()), 30 | transactionHash: String.t(), 31 | transactionIndex: String.t() 32 | } 33 | end 34 | -------------------------------------------------------------------------------- /lib/etherscan/types/mined_block.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.MinedBlock do 2 | @moduledoc """ 3 | Etherscan module for the MinedBlock struct. 4 | """ 5 | 6 | @attributes [ 7 | :blockNumber, 8 | :blockReward, 9 | :timeStamp 10 | ] 11 | 12 | defstruct @attributes 13 | 14 | @type t :: %__MODULE__{ 15 | blockNumber: String.t(), 16 | blockReward: String.t(), 17 | timeStamp: String.t() 18 | } 19 | end 20 | -------------------------------------------------------------------------------- /lib/etherscan/types/mined_uncle.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.MinedUncle do 2 | @moduledoc """ 3 | Etherscan module for the MinedUncle struct. 4 | """ 5 | 6 | @attributes [ 7 | :blockNumber, 8 | :blockReward, 9 | :timeStamp 10 | ] 11 | 12 | defstruct @attributes 13 | 14 | @type t :: %__MODULE__{ 15 | blockNumber: String.t(), 16 | blockReward: String.t(), 17 | timeStamp: String.t() 18 | } 19 | end 20 | -------------------------------------------------------------------------------- /lib/etherscan/types/proxy_block.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.ProxyBlock do 2 | @moduledoc """ 3 | Etherscan module for the ProxyBlock struct. 4 | """ 5 | 6 | alias Etherscan.ProxyTransaction 7 | 8 | @attributes [ 9 | :author, 10 | :difficulty, 11 | :extraData, 12 | :gasLimit, 13 | :gasUsed, 14 | :hash, 15 | :logsBloom, 16 | :miner, 17 | :mixHash, 18 | :nonce, 19 | :number, 20 | :parentHash, 21 | :receiptsRoot, 22 | :sealFields, 23 | :sha3Uncles, 24 | :size, 25 | :stateRoot, 26 | :timestamp, 27 | :totalDifficulty, 28 | :transactions, 29 | :transactionsRoot, 30 | :uncles 31 | ] 32 | 33 | defstruct @attributes 34 | 35 | @type t :: %__MODULE__{ 36 | author: String.t(), 37 | difficulty: String.t(), 38 | extraData: String.t(), 39 | gasLimit: String.t(), 40 | gasUsed: String.t(), 41 | hash: String.t(), 42 | logsBloom: String.t(), 43 | miner: String.t(), 44 | mixHash: String.t(), 45 | nonce: String.t(), 46 | number: String.t(), 47 | parentHash: String.t(), 48 | receiptsRoot: String.t(), 49 | sealFields: list(), 50 | sha3Uncles: String.t(), 51 | size: String.t(), 52 | stateRoot: String.t(), 53 | timestamp: String.t(), 54 | totalDifficulty: String.t(), 55 | transactions: list(ProxyTransaction.t()), 56 | transactionsRoot: String.t(), 57 | uncles: list() 58 | } 59 | end 60 | 61 | defimpl Poison.Decoder, for: Etherscan.ProxyBlock do 62 | alias Etherscan.Util 63 | 64 | @keys [ 65 | :difficulty, 66 | :gasLimit, 67 | :gasUsed, 68 | :number, 69 | :size, 70 | :timestamp, 71 | :totalDifficulty 72 | ] 73 | 74 | def decode(value, _options) do 75 | Enum.reduce(@keys, value, fn item, acc -> 76 | Map.update(acc, item, 0, &Util.safe_hex_to_number/1) 77 | end) 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /lib/etherscan/types/proxy_transaction.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.ProxyTransaction do 2 | @moduledoc """ 3 | Etherscan module for the ProxyTransaction struct. 4 | """ 5 | 6 | @attributes [ 7 | :blockHash, 8 | :blockNumber, 9 | :condition, 10 | :creates, 11 | :from, 12 | :gas, 13 | :gasPrice, 14 | :hash, 15 | :input, 16 | :networkId, 17 | :nonce, 18 | :publicKey, 19 | :r, 20 | :raw, 21 | :s, 22 | :standardV, 23 | :to, 24 | :transactionIndex, 25 | :v, 26 | :value 27 | ] 28 | 29 | defstruct @attributes 30 | 31 | @type t :: %__MODULE__{ 32 | blockHash: String.t(), 33 | blockNumber: String.t(), 34 | condition: String.t(), 35 | creates: String.t(), 36 | from: String.t(), 37 | gas: String.t(), 38 | gasPrice: String.t(), 39 | hash: String.t(), 40 | input: String.t(), 41 | networkId: integer(), 42 | nonce: String.t(), 43 | publicKey: String.t(), 44 | r: String.t(), 45 | raw: String.t(), 46 | s: String.t(), 47 | standardV: String.t(), 48 | to: String.t(), 49 | transactionIndex: String.t(), 50 | v: String.t(), 51 | value: String.t() 52 | } 53 | end 54 | 55 | defimpl Poison.Decoder, for: Etherscan.ProxyTransaction do 56 | alias Etherscan.Util 57 | 58 | @keys [ 59 | :gas, 60 | :gasUsed, 61 | :gasPrice, 62 | :blockNumber, 63 | :transactionIndex, 64 | :cumulativeGasUsed, 65 | :nonce, 66 | :value 67 | ] 68 | 69 | def decode(value, _options) do 70 | @keys 71 | |> Enum.reduce(value, fn item, acc -> 72 | Map.update(acc, item, 0, &Util.safe_hex_to_number/1) 73 | end) 74 | |> Map.update(:gasPrice, 0, &Util.convert/1) 75 | |> Map.update(:value, 0, &Util.convert/1) 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /lib/etherscan/types/proxy_transaction_receipt.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.ProxyTransactionReceipt do 2 | @moduledoc """ 3 | Etherscan module for the ProxyTransactionReceipt struct. 4 | """ 5 | 6 | @attributes [ 7 | :blockHash, 8 | :blockNumber, 9 | :contractAddress, 10 | :cumulativeGasUsed, 11 | :gasUsed, 12 | :logs, 13 | :logsBloom, 14 | :root, 15 | :status, 16 | :transactionHash, 17 | :transactionIndex 18 | ] 19 | 20 | defstruct @attributes 21 | 22 | @type t :: %__MODULE__{ 23 | blockHash: String.t(), 24 | blockNumber: String.t(), 25 | contractAddress: String.t(), 26 | cumulativeGasUsed: String.t(), 27 | gasUsed: String.t(), 28 | logs: list(), 29 | logsBloom: String.t(), 30 | root: String.t(), 31 | status: integer(), 32 | transactionHash: String.t(), 33 | transactionIndex: String.t() 34 | } 35 | end 36 | 37 | defimpl Poison.Decoder, for: Etherscan.ProxyTransactionReceipt do 38 | alias Etherscan.Util 39 | 40 | @keys [ 41 | :gasUsed, 42 | :blockNumber, 43 | :transactionIndex, 44 | :cumulativeGasUsed 45 | ] 46 | 47 | def decode(value, _options) do 48 | Enum.reduce(@keys, value, fn item, acc -> 49 | Map.update(acc, item, 0, &Util.safe_hex_to_number/1) 50 | end) 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/etherscan/types/transaction.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.Transaction do 2 | @moduledoc """ 3 | Etherscan module for the Transaction struct. 4 | """ 5 | 6 | @attributes [ 7 | :blockNumber, 8 | :timeStamp, 9 | :hash, 10 | :nonce, 11 | :blockHash, 12 | :transactionIndex, 13 | :from, 14 | :to, 15 | :value, 16 | :gas, 17 | :gasPrice, 18 | :isError, 19 | :txreceipt_status, 20 | :input, 21 | :contractAddress, 22 | :cumulativeGasUsed, 23 | :gasUsed, 24 | :confirmations 25 | ] 26 | 27 | defstruct @attributes 28 | 29 | @type t :: %__MODULE__{ 30 | blockNumber: String.t(), 31 | timeStamp: String.t(), 32 | hash: String.t(), 33 | nonce: String.t(), 34 | blockHash: String.t(), 35 | transactionIndex: String.t(), 36 | from: String.t(), 37 | to: String.t(), 38 | value: String.t(), 39 | gas: String.t(), 40 | gasPrice: String.t(), 41 | isError: String.t(), 42 | txreceipt_status: String.t(), 43 | input: String.t(), 44 | contractAddress: String.t(), 45 | cumulativeGasUsed: String.t(), 46 | gasUsed: String.t(), 47 | confirmations: String.t() 48 | } 49 | end 50 | -------------------------------------------------------------------------------- /lib/etherscan/util.ex: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.Util do 2 | @moduledoc false 3 | 4 | @denominations [ 5 | wei: 1, 6 | kwei: 1000, 7 | mwei: 1_000_000, 8 | gwei: 1_000_000_000, 9 | shannon: 1_000_000_000, 10 | nano: 1_000_000_000, 11 | szabo: 1_000_000_000_000, 12 | micro: 1_000_000_000_000, 13 | finney: 1_000_000_000_000_000, 14 | milli: 1_000_000_000_000_000, 15 | ether: 1_000_000_000_000_000_000 16 | ] 17 | 18 | @doc """ 19 | Formats a string representing an Ethereum balance 20 | """ 21 | @spec format_balance(balance :: String.t()) :: String.t() 22 | def format_balance(balance) do 23 | balance 24 | |> String.to_integer() 25 | |> convert() 26 | end 27 | 28 | @spec convert(number :: integer() | float(), opts :: Keyword.t()) :: String.t() 29 | def convert(number, opts \\ []) 30 | 31 | def convert(number, opts) when is_number(number) do 32 | denom = 33 | @denominations 34 | |> List.keyfind(Keyword.get(opts, :denomination, :ether), 0) 35 | |> elem(1) 36 | 37 | pretty_float(number / denom, Keyword.get(opts, :decimals, 20)) 38 | end 39 | 40 | def convert(number, opts) when is_binary(number) do 41 | number 42 | |> String.to_integer() 43 | |> convert(opts) 44 | end 45 | 46 | @doc """ 47 | Converts a float to a nicely formatted string 48 | """ 49 | @spec pretty_float(number :: float() | String.t(), decimals :: integer()) :: String.t() 50 | def pretty_float(number, decimals \\ 20) 51 | 52 | def pretty_float(number, decimals) when is_number(number) do 53 | :erlang.float_to_binary(number, [:compact, decimals: decimals]) 54 | end 55 | 56 | def pretty_float(number, decimals) when is_binary(number) do 57 | number 58 | |> String.to_float() 59 | |> pretty_float(decimals) 60 | end 61 | 62 | @doc """ 63 | Wraps a value inside a tagged Tuple using the provided tag. 64 | """ 65 | @spec wrap(value :: any(), tag :: atom()) :: {atom(), any()} 66 | def wrap(value, tag) when is_atom(tag), do: {tag, value} 67 | 68 | @spec hex_to_number(hex :: String.t()) :: {:ok, integer()} | {:error, String.t()} 69 | def hex_to_number("0x" <> hex) do 70 | hex 71 | |> Integer.parse(16) 72 | |> case do 73 | {integer, _} -> 74 | integer 75 | |> wrap(:ok) 76 | 77 | :error -> 78 | "invalid hex - #{inspect("0x" <> hex)}" 79 | |> wrap(:error) 80 | end 81 | end 82 | 83 | def hex_to_number(hex), do: "invalid hex - #{inspect(hex)}" |> wrap(:error) 84 | 85 | @spec safe_hex_to_number(hex :: String.t()) :: integer() 86 | def safe_hex_to_number(hex) do 87 | hex 88 | |> hex_to_number() 89 | |> case do 90 | {:ok, integer} -> 91 | integer 92 | 93 | {:error, _reason} -> 94 | 0 95 | end 96 | end 97 | 98 | @spec number_to_hex(number :: integer() | String.t()) :: String.t() 99 | def number_to_hex(number) when is_integer(number) do 100 | number 101 | |> Integer.to_string(16) 102 | |> (&Kernel.<>("0x", &1)).() 103 | end 104 | 105 | def number_to_hex(number) when is_binary(number) do 106 | number 107 | |> String.to_integer() 108 | |> number_to_hex() 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :etherscan, 7 | version: "2.0.2", 8 | elixir: "~> 1.5", 9 | start_permanent: Mix.env() == :prod, 10 | description: description(), 11 | package: package(), 12 | aliases: aliases(), 13 | deps: deps(), 14 | name: "Etherscan", 15 | test_coverage: [tool: ExCoveralls], 16 | preferred_cli_env: [coveralls: :test, "coveralls.detail": :test, "coveralls.html": :test] 17 | ] 18 | end 19 | 20 | def application do 21 | [ 22 | extra_applications: [:logger] 23 | ] 24 | end 25 | 26 | defp description do 27 | """ 28 | Etherscan.io API wrapper for Elixir. Provides access to ethereum blockchain data. 29 | """ 30 | end 31 | 32 | defp package do 33 | [ 34 | name: "etherscan", 35 | files: ["lib", "mix.exs", "README*", "LICENSE*"], 36 | maintainers: ["l1h3r"], 37 | licenses: ["MIT"], 38 | links: %{"GitHub" => "https://github.com/l1h3r/etherscan"} 39 | ] 40 | end 41 | 42 | defp deps do 43 | [ 44 | {:poison, "~> 3.1"}, 45 | {:httpoison, "~> 1.0"}, 46 | {:exvcr, "~> 0.9", only: :test}, 47 | {:ex_doc, "~> 0.18", only: :dev}, 48 | {:excoveralls, "~> 0.7", only: :test}, 49 | {:dialyxir, "~> 0.5", only: :dev, runtime: false}, 50 | {:credo, "~> 0.8", only: [:dev, :test], runtime: false} 51 | ] 52 | end 53 | 54 | defp aliases do 55 | [ 56 | watch: ["test --stale --listen-on-stdin"], 57 | lint: ["dialyzer", "credo"] 58 | ] 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{ 2 | "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, 3 | "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, 4 | "credo": {:hex, :credo, "0.8.10", "261862bb7363247762e1063713bb85df2bbd84af8d8610d1272cd9c1943bba63", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, 5 | "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm"}, 6 | "earmark": {:hex, :earmark, "1.2.4", "99b637c62a4d65a20a9fb674b8cffb8baa771c04605a80c911c4418c69b75439", [:mix], [], "hexpm"}, 7 | "ex_doc": {:hex, :ex_doc, "0.18.3", "f4b0e4a2ec6f333dccf761838a4b253d75e11f714b85ae271c9ae361367897b7", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, 8 | "exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], [], "hexpm"}, 9 | "excoveralls": {:hex, :excoveralls, "0.8.1", "0bbf67f22c7dbf7503981d21a5eef5db8bbc3cb86e70d3798e8c802c74fa5e27", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, 10 | "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, 11 | "exvcr": {:hex, :exvcr, "0.10.1", "cb266e5cc0d4fef12572ce6673d13f97aa3c302911010d64d51cee0690f566d1", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, 12 | "hackney": {:hex, :hackney, "1.11.0", "4951ee019df102492dabba66a09e305f61919a8a183a7860236c0fde586134b6", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, 13 | "httpoison": {:hex, :httpoison, "1.0.0", "1f02f827148d945d40b24f0b0a89afe40bfe037171a6cf70f2486976d86921cd", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, 14 | "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, 15 | "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"}, 16 | "meck": {:hex, :meck, "0.8.9", "64c5c0bd8bcca3a180b44196265c8ed7594e16bcc845d0698ec6b4e577f48188", [:rebar3], [], "hexpm"}, 17 | "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, 18 | "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, 19 | "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, 20 | "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, 21 | "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}, 22 | } 23 | -------------------------------------------------------------------------------- /test/etherscan/api/accounts_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.AccountsTest do 2 | use ExUnit.Case 3 | use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney 4 | use Etherscan.Constants 5 | alias Etherscan.{MinedBlock, MinedUncle, InternalTransaction, Transaction} 6 | 7 | setup_all do 8 | HTTPoison.start() 9 | :ok 10 | end 11 | 12 | describe "get_balance/1" do 13 | test "with valid address" do 14 | use_cassette "get_balance" do 15 | response = Etherscan.get_balance(@test_address1) 16 | assert {:ok, @test_address1_balance} = response 17 | end 18 | end 19 | 20 | test "with invalid address" do 21 | response = Etherscan.get_balance(%{}) 22 | assert {:error, :invalid_address} = response 23 | end 24 | end 25 | 26 | describe "get_balances/1" do 27 | test "with valid addresses" do 28 | use_cassette "get_balances" do 29 | response = Etherscan.get_balances([@test_address1, @test_address2, @test_address3]) 30 | 31 | assert {:ok, 32 | [ 33 | %{"account" => @test_address1, "balance" => @test_address1_balance}, 34 | %{"account" => @test_address2, "balance" => @test_address2_balance}, 35 | %{"account" => @test_address3, "balance" => @test_address3_balance} 36 | ]} = response 37 | end 38 | end 39 | 40 | test "with invalid addresses" do 41 | response = Etherscan.get_balances([%{}]) 42 | assert {:error, :invalid_addresses} = response 43 | end 44 | end 45 | 46 | describe "get_transactions/1" do 47 | test "returns a list of transaction structs" do 48 | use_cassette "get_transactions" do 49 | response = Etherscan.get_transactions(@test_address1) 50 | {:ok, blocks} = response 51 | assert [%Transaction{} | _] = blocks 52 | end 53 | end 54 | 55 | test "with invalid address" do 56 | response = Etherscan.get_transactions({:hello, :world}) 57 | assert {:error, :invalid_address} = response 58 | end 59 | end 60 | 61 | describe "get_transactions/2" do 62 | test "with startblock" do 63 | use_cassette "get_transactions_startblock" do 64 | response = Etherscan.get_transactions(@test_address1, %{startblock: 500_000}) 65 | assert {:ok, blocks} = response 66 | assert [%Transaction{blockNumber: "915000"} | _] = blocks 67 | end 68 | end 69 | 70 | test "with endblock" do 71 | use_cassette "get_transactions_endblock" do 72 | response = Etherscan.get_transactions(@test_address1, %{endblock: 5000}) 73 | assert {:ok, blocks} = response 74 | block_number = blocks |> List.last() |> Map.get(:blockNumber) 75 | assert block_number == "0" 76 | end 77 | end 78 | 79 | test "with offset" do 80 | use_cassette "get_transactions_offset" do 81 | response = Etherscan.get_transactions(@test_address1, %{offset: 5}) 82 | assert {:ok, blocks} = response 83 | assert length(blocks) == 5 84 | end 85 | end 86 | 87 | test "with page" do 88 | use_cassette "get_transactions_page" do 89 | response = Etherscan.get_transactions(@test_address1, %{page: 2}) 90 | assert {:ok, blocks} = response 91 | assert [%Transaction{blockNumber: "1959340"} | _] = blocks 92 | end 93 | end 94 | 95 | test "with sort" do 96 | use_cassette "get_transactions_sort" do 97 | response = Etherscan.get_transactions(@test_address1, %{sort: "desc"}) 98 | assert {:ok, blocks} = response 99 | assert [%Transaction{blockNumber: "5854994"} | _] = blocks 100 | end 101 | end 102 | end 103 | 104 | describe "get_internal_transactions/1" do 105 | test "returns a list of internal transaction structs" do 106 | use_cassette "get_internal_transactions" do 107 | response = Etherscan.get_internal_transactions(@test_address1) 108 | assert {:ok, blocks} = response 109 | assert [%InternalTransaction{} | _] = blocks 110 | end 111 | end 112 | 113 | test "with invalid address" do 114 | response = Etherscan.get_internal_transactions({:hello, :world}) 115 | assert {:error, :invalid_address} = response 116 | end 117 | end 118 | 119 | describe "get_internal_transactions/2" do 120 | test "with startblock" do 121 | use_cassette "get_internal_transactions_startblock" do 122 | response = Etherscan.get_internal_transactions(@test_address1, %{startblock: 1_960_000}) 123 | assert {:ok, blocks} = response 124 | assert [%InternalTransaction{blockNumber: "1961849"} | _] = blocks 125 | end 126 | end 127 | 128 | test "with endblock" do 129 | use_cassette "get_internal_transactions_endblock" do 130 | response = Etherscan.get_internal_transactions(@test_address1, %{endblock: 1_960_000}) 131 | assert {:ok, blocks} = response 132 | block_number = blocks |> List.last() |> Map.get(:blockNumber) 133 | assert block_number == "1959740" 134 | end 135 | end 136 | 137 | test "with offset" do 138 | use_cassette "get_internal_transactions_offset" do 139 | response = Etherscan.get_internal_transactions(@test_address1, %{offset: 2}) 140 | assert {:ok, blocks} = response 141 | assert length(blocks) == 2 142 | end 143 | end 144 | 145 | test "with page" do 146 | use_cassette "get_internal_transactions_page" do 147 | response = Etherscan.get_internal_transactions(@test_address1, %{offset: 1, page: 2}) 148 | assert {:ok, blocks} = response 149 | assert length(blocks) == 1 150 | end 151 | end 152 | 153 | test "with sort" do 154 | use_cassette "get_internal_transactions_sort" do 155 | response = Etherscan.get_internal_transactions(@test_address1, %{sort: "desc"}) 156 | assert {:ok, blocks} = response 157 | assert [%InternalTransaction{blockNumber: "1961866"} | _] = blocks 158 | end 159 | end 160 | end 161 | 162 | describe "get_internal_transactions_by_hash/1" do 163 | test "returns a list of internal transaction structs" do 164 | use_cassette "get_internal_transactions_by_hash" do 165 | response = Etherscan.get_internal_transactions_by_hash(@test_transaction_hash) 166 | assert {:ok, blocks} = response 167 | assert [%InternalTransaction{} | _] = blocks 168 | end 169 | end 170 | 171 | test "with invalid transaction hash" do 172 | response = Etherscan.get_internal_transactions_by_hash({:transaction}) 173 | assert {:error, :invalid_transaction_hash} = response 174 | end 175 | end 176 | 177 | describe "get_blocks_mined/1" do 178 | test "returns a list of mined block structs" do 179 | use_cassette "get_blocks_mined" do 180 | response = Etherscan.get_blocks_mined(@test_miner_address) 181 | assert {:ok, rewards} = response 182 | assert [%MinedBlock{} | _] = rewards 183 | end 184 | end 185 | 186 | test "with invalid address" do 187 | response = Etherscan.get_blocks_mined({:hello, :world}) 188 | assert {:error, :invalid_address} = response 189 | end 190 | end 191 | 192 | describe "get_blocks_mined/2" do 193 | test "get_blocks_mined with offset" do 194 | use_cassette "get_blocks_mined_offset" do 195 | response = Etherscan.get_blocks_mined(@test_miner_address, %{offset: 8}) 196 | assert {:ok, rewards} = response 197 | assert length(rewards) == 8 198 | end 199 | end 200 | 201 | test "get_blocks_mined with page" do 202 | use_cassette "get_blocks_mined_page" do 203 | response = Etherscan.get_blocks_mined(@test_miner_address, %{offset: 4, page: 3}) 204 | assert {:ok, rewards} = response 205 | assert [%MinedBlock{blockNumber: "2664645"} | _] = rewards 206 | end 207 | end 208 | end 209 | 210 | describe "get_uncles_mined/1" do 211 | test "returns a list of mined uncle structs" do 212 | use_cassette "get_uncles_mined" do 213 | response = Etherscan.get_uncles_mined(@test_miner_address) 214 | assert {:ok, rewards} = response 215 | assert [%MinedUncle{} | _] = rewards 216 | end 217 | end 218 | 219 | test "with invalid address" do 220 | response = Etherscan.get_uncles_mined({:hello, :world}) 221 | assert {:error, :invalid_address} = response 222 | end 223 | end 224 | 225 | describe "get_uncles_mined/2" do 226 | test "with offset" do 227 | use_cassette "get_uncles_mined_offset" do 228 | response = Etherscan.get_uncles_mined(@test_miner_address, %{offset: 3}) 229 | assert {:ok, rewards} = response 230 | assert length(rewards) == 3 231 | end 232 | end 233 | 234 | test "with page" do 235 | use_cassette "get_uncles_mined_page" do 236 | response = Etherscan.get_uncles_mined(@test_miner_address, %{offset: 4, page: 3}) 237 | assert {:ok, rewards} = response 238 | assert [%MinedUncle{blockNumber: "2431561"} | _] = rewards 239 | end 240 | end 241 | end 242 | 243 | describe "get_token_balance/2" do 244 | test "with valid address and token address" do 245 | use_cassette "get_token_balance" do 246 | response = Etherscan.get_token_balance(@test_token_owner_address, @test_token_address) 247 | assert {:ok, @test_token_address_balance} = response 248 | end 249 | end 250 | 251 | test "with invalid address" do 252 | response = Etherscan.get_token_balance(%{hello: "world"}, @test_token_address) 253 | assert {:error, :invalid_address} = response 254 | end 255 | 256 | test "with invalid token address" do 257 | response = Etherscan.get_token_balance(@test_token_owner_address, %{hello: "world"}) 258 | assert {:error, :invalid_token_address} = response 259 | end 260 | 261 | test "with both invalid addresses" do 262 | response = Etherscan.get_token_balance([1, 2], %{hello: "world"}) 263 | assert {:error, :invalid_address_and_token_address} = response 264 | end 265 | end 266 | end 267 | -------------------------------------------------------------------------------- /test/etherscan/api/blocks_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.BlocksTest do 2 | use ExUnit.Case 3 | use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney 4 | use Etherscan.Constants 5 | alias Etherscan.{BlockReward, BlockRewardUncle} 6 | 7 | setup_all do 8 | HTTPoison.start() 9 | :ok 10 | end 11 | 12 | describe "get_block_and_uncle_rewards/1" do 13 | test "returns a block reward struct" do 14 | use_cassette "get_block_and_uncle_rewards" do 15 | response = Etherscan.get_block_and_uncle_rewards(@test_block_number) 16 | assert {:ok, reward} = response 17 | assert %BlockReward{} = reward 18 | end 19 | end 20 | 21 | test "inclues block reward uncle structs" do 22 | use_cassette "get_block_and_uncle_rewards" do 23 | response = Etherscan.get_block_and_uncle_rewards(@test_block_number) 24 | assert {:ok, %BlockReward{uncles: uncles}} = response 25 | assert [%BlockRewardUncle{} | _] = uncles 26 | end 27 | end 28 | 29 | test "with invalid block number" do 30 | response = Etherscan.get_block_and_uncle_rewards(-5) 31 | assert {:error, :invalid_block_number} = response 32 | response = Etherscan.get_block_and_uncle_rewards("fake block") 33 | assert {:error, :invalid_block_number} = response 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /test/etherscan/api/contracts_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.ContractsTest do 2 | use ExUnit.Case 3 | use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney 4 | use Etherscan.Constants 5 | 6 | setup_all do 7 | HTTPoison.start() 8 | :ok 9 | end 10 | 11 | describe "get_contract_abi/1" do 12 | test "with valid address" do 13 | use_cassette "get_contract_abi" do 14 | assert {:ok, abi} = Etherscan.get_contract_abi(@test_contract_address) 15 | assert [%{"name" => _} | _] = abi 16 | assert [%{"type" => _} | _] = abi 17 | assert [%{"constant" => _} | _] = abi 18 | assert [%{"inputs" => _} | _] = abi 19 | assert [%{"outputs" => _} | _] = abi 20 | end 21 | end 22 | 23 | test "with invalid address" do 24 | response = Etherscan.get_contract_abi({:hello, :world}) 25 | assert {:error, :invalid_address} = response 26 | end 27 | end 28 | 29 | describe "get_contract_source/1" do 30 | test "with valid address" do 31 | use_cassette "get_contract_source" do 32 | assert {:ok, source} = Etherscan.get_contract_source(@test_contract_address) 33 | assert [%{"ABI" => _} | _] = source 34 | assert [%{"CompilerVersion" => _} | _] = source 35 | assert [%{"ConstructorArguments" => _} | _] = source 36 | assert [%{"ContractName" => _} | _] = source 37 | assert [%{"Library" => _} | _] = source 38 | assert [%{"OptimizationUsed" => _} | _] = source 39 | assert [%{"Runs" => _} | _] = source 40 | assert [%{"SourceCode" => _} | _] = source 41 | assert [%{"SwarmSource" => _} | _] = source 42 | end 43 | end 44 | 45 | test "with invalid address" do 46 | response = Etherscan.get_contract_source({:foo, :bar}) 47 | assert {:error, :invalid_address} = response 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /test/etherscan/api/logs_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.LogsTest do 2 | use ExUnit.Case 3 | use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney 4 | use Etherscan.Constants 5 | alias Etherscan.Log 6 | 7 | setup_all do 8 | HTTPoison.start() 9 | :ok 10 | end 11 | 12 | describe "get_logs/1" do 13 | test "returns a log struct" do 14 | use_cassette "get_logs" do 15 | response = 16 | %{ 17 | address: @test_topic_address, 18 | topic0: @test_topic_0, 19 | topic1: @test_topic_1, 20 | topic0_1_opr: "and" 21 | } 22 | |> Etherscan.get_logs() 23 | 24 | assert {:ok, logs} = response 25 | assert [%Log{address: @test_topic_address} = log | _] = logs 26 | assert @test_topic_0 in log.topics 27 | assert @test_topic_1 in log.topics 28 | end 29 | end 30 | 31 | test "with invalid params" do 32 | response = Etherscan.get_logs("log_params") 33 | assert {:error, :invalid_params} = response 34 | end 35 | 36 | test "with invalid address" do 37 | response = Etherscan.get_logs(%{address: "not-an-address"}) 38 | assert {:error, :invalid_address} = response 39 | end 40 | 41 | test "with invalid fromBlock string" do 42 | response = Etherscan.get_logs(%{fromBlock: "not latest"}) 43 | assert {:error, :invalid_from_block} = response 44 | end 45 | 46 | test "with invalid fromBlock type" do 47 | response = Etherscan.get_logs(%{fromBlock: nil}) 48 | assert {:error, :invalid_from_block} = response 49 | end 50 | 51 | test "with invalid toBlock string" do 52 | response = Etherscan.get_logs(%{toBlock: "not latest"}) 53 | assert {:error, :invalid_to_block} = response 54 | end 55 | 56 | test "with invalid toBlock type" do 57 | response = Etherscan.get_logs(%{toBlock: nil}) 58 | assert {:error, :invalid_to_block} = response 59 | end 60 | 61 | test "with invalid topic0_1_opr" do 62 | response = Etherscan.get_logs(%{topic0_1_opr: "a n d"}) 63 | assert {:error, :invalid_topic0_1_opr} = response 64 | end 65 | 66 | test "with invalid topic1_2_opr" do 67 | response = Etherscan.get_logs(%{topic1_2_opr: "andddd"}) 68 | assert {:error, :invalid_topic1_2_opr} = response 69 | end 70 | 71 | test "with invalid topic2_3_opr" do 72 | response = Etherscan.get_logs(%{topic2_3_opr: "banana"}) 73 | assert {:error, :invalid_topic2_3_opr} = response 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /test/etherscan/api/proxy_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.ProxyTest do 2 | use ExUnit.Case 3 | use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney 4 | use Etherscan.Constants 5 | alias Etherscan.{ProxyBlock, ProxyTransaction, ProxyTransactionReceipt} 6 | 7 | setup_all do 8 | HTTPoison.start() 9 | :ok 10 | end 11 | 12 | describe "eth_block_number/0" do 13 | test "returns the most recent block number" do 14 | use_cassette "eth_block_number" do 15 | response = Etherscan.eth_block_number() 16 | assert {:ok, @test_proxy_block_number} = response 17 | end 18 | end 19 | end 20 | 21 | describe "eth_get_block_by_number/1" do 22 | test "with valid tag returns a block struct" do 23 | use_cassette "eth_get_block_by_number" do 24 | response = Etherscan.eth_get_block_by_number(@test_proxy_block_tag) 25 | assert {:ok, %ProxyBlock{}} = response 26 | end 27 | end 28 | 29 | test "with invalid tag" do 30 | response = Etherscan.eth_get_block_by_number(%{}) 31 | assert {:error, :invalid_tag} = response 32 | end 33 | end 34 | 35 | describe "eth_get_uncle_by_block_number_and_index/2" do 36 | test "with valid tag and index" do 37 | use_cassette "eth_get_uncle_by_block_number_and_index" do 38 | response = 39 | Etherscan.eth_get_uncle_by_block_number_and_index( 40 | @test_proxy_uncle_tag, 41 | @test_proxy_index 42 | ) 43 | 44 | assert {:ok, %{"number" => @test_proxy_uncle_block_tag}} = response 45 | end 46 | end 47 | 48 | test "with invalid tag" do 49 | response = Etherscan.eth_get_uncle_by_block_number_and_index(nil, @test_proxy_index) 50 | assert {:error, :invalid_tag} = response 51 | end 52 | 53 | test "with invalid index" do 54 | response = Etherscan.eth_get_uncle_by_block_number_and_index(@test_proxy_uncle_tag, nil) 55 | assert {:error, :invalid_index} = response 56 | end 57 | 58 | test "with invalid tag and index" do 59 | response = Etherscan.eth_get_uncle_by_block_number_and_index(nil, nil) 60 | assert {:error, :invalid_tag_and_index} = response 61 | end 62 | end 63 | 64 | describe "eth_get_block_transaction_count_by_number/1" do 65 | test "with valid tag" do 66 | use_cassette "eth_get_block_transaction_count_by_number" do 67 | response = 68 | Etherscan.eth_get_block_transaction_count_by_number(@test_proxy_transaction_tag) 69 | 70 | assert {:ok, @test_proxy_block_transaction_count} = response 71 | end 72 | end 73 | 74 | test "with invalid tag" do 75 | response = Etherscan.eth_get_block_transaction_count_by_number(nil) 76 | assert {:error, :invalid_tag} = response 77 | end 78 | end 79 | 80 | describe "eth_get_transaction_by_hash/1" do 81 | test "with valid transaction hash returns a transaction struct" do 82 | use_cassette "eth_get_transaction_by_hash" do 83 | response = Etherscan.eth_get_transaction_by_hash(@test_proxy_transaction_hash) 84 | assert {:ok, %ProxyTransaction{hash: @test_proxy_transaction_hash}} = response 85 | end 86 | end 87 | 88 | test "with invalid transaction hash" do 89 | response = Etherscan.eth_get_transaction_by_hash(nil) 90 | assert {:error, :invalid_transaction_hash} = response 91 | end 92 | end 93 | 94 | describe "eth_get_transaction_by_block_number_and_index/2" do 95 | test "with valid tag and index" do 96 | use_cassette "eth_get_transaction_by_block_number_and_index" do 97 | response = 98 | Etherscan.eth_get_transaction_by_block_number_and_index( 99 | @test_proxy_block_tag, 100 | @test_proxy_index 101 | ) 102 | 103 | assert {:ok, %ProxyTransaction{}} = response 104 | end 105 | end 106 | 107 | test "with invalid tag" do 108 | response = Etherscan.eth_get_transaction_by_block_number_and_index(nil, @test_proxy_index) 109 | assert {:error, :invalid_tag} = response 110 | end 111 | 112 | test "with invalid index" do 113 | response = 114 | Etherscan.eth_get_transaction_by_block_number_and_index(@test_proxy_block_tag, nil) 115 | 116 | assert {:error, :invalid_index} = response 117 | end 118 | 119 | test "with invalid tag and index" do 120 | response = Etherscan.eth_get_transaction_by_block_number_and_index(nil, nil) 121 | assert {:error, :invalid_tag_and_index} = response 122 | end 123 | end 124 | 125 | describe "eth_get_transaction_count/1" do 126 | test "with valid address" do 127 | use_cassette "eth_get_transaction_count" do 128 | response = Etherscan.eth_get_transaction_count(@test_proxy_address) 129 | assert {:ok, @test_proxy_transaction_count} = response 130 | end 131 | end 132 | 133 | test "with invalid address" do 134 | response = Etherscan.eth_get_transaction_count(nil) 135 | assert {:error, :invalid_address} = response 136 | end 137 | end 138 | 139 | describe "eth_send_raw_transaction/1" do 140 | @tag :wip 141 | test "with valid hex" do 142 | use_cassette "eth_send_raw_transaction" do 143 | response = Etherscan.eth_send_raw_transaction(@test_proxy_hex) 144 | assert {:ok, %{"code" => -32000}} = response 145 | end 146 | end 147 | 148 | test "with invalid hex" do 149 | response = Etherscan.eth_send_raw_transaction(nil) 150 | assert {:error, :invalid_hex} = response 151 | end 152 | end 153 | 154 | describe "eth_get_transaction_receipt/1" do 155 | test "with valid transaction hash returns a transaction receipt struct" do 156 | use_cassette "eth_get_transaction_receipt" do 157 | response = Etherscan.eth_get_transaction_receipt(@test_proxy_transaction_hash) 158 | 159 | assert {:ok, %ProxyTransactionReceipt{transactionHash: @test_proxy_transaction_hash}} = 160 | response 161 | end 162 | end 163 | 164 | test "with invalid transaction hash" do 165 | response = Etherscan.eth_get_transaction_receipt(nil) 166 | assert {:error, :invalid_transaction_hash} = response 167 | end 168 | end 169 | 170 | describe "eth_call/3" do 171 | test "with valid to and data" do 172 | use_cassette "eth_call" do 173 | response = Etherscan.eth_call(@test_proxy_to, @test_proxy_data) 174 | assert {:ok, @test_proxy_eth_call_result} = response 175 | end 176 | end 177 | 178 | test "with invalid to" do 179 | response = Etherscan.eth_call(nil, @test_proxy_data) 180 | assert {:error, :invalid_to} = response 181 | end 182 | 183 | test "with invalid data" do 184 | response = Etherscan.eth_call(@test_proxy_to, nil) 185 | assert {:error, :invalid_data} = response 186 | end 187 | 188 | test "with invalid to and data" do 189 | response = Etherscan.eth_call(nil, nil) 190 | assert {:error, :invalid_to_and_data} = response 191 | end 192 | end 193 | 194 | describe "eth_get_code/2" do 195 | test "with valid address and tag" do 196 | use_cassette "eth_get_code" do 197 | response = Etherscan.eth_get_code(@test_proxy_code_address, "latest") 198 | assert {:ok, @test_proxy_code_result} = response 199 | end 200 | end 201 | 202 | test "with invalid address" do 203 | response = Etherscan.eth_get_code(nil, "latest") 204 | assert {:error, :invalid_address} = response 205 | end 206 | 207 | test "with invalid tag" do 208 | response = Etherscan.eth_get_code(@test_proxy_address, nil) 209 | assert {:error, :invalid_tag} = response 210 | end 211 | 212 | test "with invalid address and tag" do 213 | response = Etherscan.eth_get_code(nil, nil) 214 | assert {:error, :invalid_address_and_tag} = response 215 | end 216 | end 217 | 218 | describe "eth_get_storage_at/2" do 219 | test "with valid address and position" do 220 | use_cassette "eth_get_storage_at" do 221 | response = 222 | Etherscan.eth_get_storage_at(@test_proxy_storage_address, @test_proxy_storage_position) 223 | 224 | assert {:ok, @test_proxy_storage_result} = response 225 | end 226 | end 227 | 228 | test "with invalid address" do 229 | response = Etherscan.eth_get_storage_at(nil, @test_proxy_storage_position) 230 | assert {:error, :invalid_address} = response 231 | end 232 | 233 | test "with invalid position" do 234 | response = Etherscan.eth_get_storage_at(@test_proxy_storage_address, nil) 235 | assert {:error, :invalid_position} = response 236 | end 237 | 238 | test "with invalid address and position" do 239 | response = Etherscan.eth_get_storage_at(nil, nil) 240 | assert {:error, :invalid_address_and_position} = response 241 | end 242 | end 243 | 244 | describe "eth_gas_price/0" do 245 | test "returns the current price per gas" do 246 | use_cassette "eth_gas_price" do 247 | response = Etherscan.eth_gas_price() 248 | assert {:ok, @test_proxy_current_gas} = response 249 | end 250 | end 251 | end 252 | 253 | describe "eth_estimate_gas/1" do 254 | @tag :wip 255 | test "with valid params" do 256 | use_cassette "eth_estimate_gas" do 257 | params = %{ 258 | to: @test_proxy_estimate_to, 259 | value: @test_proxy_value, 260 | gasPrice: @test_proxy_gas_price, 261 | gas: @test_proxy_gas 262 | } 263 | 264 | response = Etherscan.eth_estimate_gas(params) 265 | assert {:ok, %{"code" => -32602}} = response 266 | end 267 | end 268 | 269 | test "with invalid params" do 270 | response = Etherscan.eth_estimate_gas(nil) 271 | assert {:error, :invalid_params} = response 272 | end 273 | end 274 | end 275 | -------------------------------------------------------------------------------- /test/etherscan/api/stats_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.StatsTest do 2 | use ExUnit.Case 3 | use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney 4 | use Etherscan.Constants 5 | 6 | setup_all do 7 | HTTPoison.start() 8 | :ok 9 | end 10 | 11 | describe "get_token_supply/1" do 12 | test "with valid token address" do 13 | use_cassette "get_token_supply" do 14 | response = Etherscan.get_token_supply(@test_token_address) 15 | assert {:ok, @test_token_supply} = response 16 | end 17 | end 18 | 19 | test "with invalid token address" do 20 | response = Etherscan.get_token_supply({:token}) 21 | assert {:error, :invalid_token_address} = response 22 | end 23 | end 24 | 25 | describe "get_eth_supply/0" do 26 | test "returns the current supply of eth" do 27 | use_cassette "get_eth_supply" do 28 | response = Etherscan.get_eth_supply() 29 | assert {:ok, @test_eth_supply} = response 30 | end 31 | end 32 | end 33 | 34 | describe "get_eth_price/0" do 35 | test "returns the current eth price" do 36 | use_cassette "get_eth_price" do 37 | response = Etherscan.get_eth_price() 38 | assert {:ok, price} = response 39 | assert %{"ethbtc" => @test_eth_btc_price} = price 40 | assert %{"ethusd" => @test_eth_usd_price} = price 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/etherscan/api/transactions_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.TransactionsTest do 2 | use ExUnit.Case 3 | use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney 4 | use Etherscan.Constants 5 | alias Etherscan.ContractStatus 6 | 7 | setup_all do 8 | HTTPoison.start() 9 | :ok 10 | end 11 | 12 | describe "get_contract_execution_status/1" do 13 | test "with valid transaction returns a contract status struct" do 14 | use_cassette "get_contract_execution_status" do 15 | response = Etherscan.get_contract_execution_status(@test_transaction_hash) 16 | assert {:ok, status} = response 17 | assert %ContractStatus{isError: "0"} = status 18 | end 19 | end 20 | 21 | test "with transaction error" do 22 | use_cassette "get_contract_execution_status_error" do 23 | response = Etherscan.get_contract_execution_status(@test_invalid_transaction_hash) 24 | assert {:ok, status} = response 25 | assert %ContractStatus{isError: "1", errDescription: "Bad jump destination"} = status 26 | end 27 | end 28 | 29 | test "with invalid transaction hash" do 30 | response = Etherscan.get_contract_execution_status({:transaction}) 31 | assert {:error, :invalid_transaction_hash} = response 32 | end 33 | end 34 | 35 | describe "get_transaction_receipt_status/1" do 36 | test "with valid transaction returns the transaction receipt status" do 37 | use_cassette "get_transaction_receipt_status" do 38 | response = Etherscan.get_transaction_receipt_status(@test_transaction_hash_2) 39 | assert {:ok, %{"status" => "1"}} = response 40 | end 41 | end 42 | 43 | test "with pre-byzantium transaction returns empty value" do 44 | use_cassette "get_transaction_receipt_status_pre_byzantium" do 45 | response = Etherscan.get_transaction_receipt_status(@test_transaction_hash) 46 | assert {:ok, %{"status" => ""}} = response 47 | end 48 | end 49 | 50 | test "with invalid transaction hash" do 51 | response = Etherscan.get_transaction_receipt_status("my-transaction") 52 | assert {:error, :invalid_transaction_hash} = response 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /test/etherscan/util_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Etherscan.UtilTest do 2 | use ExUnit.Case, async: true 3 | 4 | alias Etherscan.Util 5 | 6 | describe "format_balance/1" do 7 | test "with valid balance converts to ether" do 8 | assert Util.format_balance("10000000000000000000000") == "10000.0" 9 | end 10 | end 11 | 12 | describe "convert/2" do 13 | test "converts wei to kwei" do 14 | assert Util.convert(1000, denomination: :kwei) == "1.0" 15 | assert Util.convert("1000", denomination: :kwei) == "1.0" 16 | end 17 | 18 | test "converts wei to mwei" do 19 | assert Util.convert(1_000_000, denomination: :mwei) == "1.0" 20 | assert Util.convert("1000000", denomination: :mwei) == "1.0" 21 | end 22 | 23 | test "converts wei to gwei/shannon/nano" do 24 | assert Util.convert(1_000_000_000, denomination: :gwei) == "1.0" 25 | assert Util.convert(1_000_000_000, denomination: :shannon) == "1.0" 26 | assert Util.convert(1_000_000_000, denomination: :nano) == "1.0" 27 | assert Util.convert("1000000000", denomination: :gwei) == "1.0" 28 | assert Util.convert("1000000000", denomination: :shannon) == "1.0" 29 | assert Util.convert("1000000000", denomination: :nano) == "1.0" 30 | end 31 | 32 | test "converts wei to szabo/micro" do 33 | assert Util.convert(1_000_000_000_000, denomination: :szabo) == "1.0" 34 | assert Util.convert(1_000_000_000_000, denomination: :micro) == "1.0" 35 | assert Util.convert("1000000000000", denomination: :szabo) == "1.0" 36 | assert Util.convert("1000000000000", denomination: :micro) == "1.0" 37 | end 38 | 39 | test "converts wei to finney/milli" do 40 | assert Util.convert(1_000_000_000_000_000, denomination: :finney) == "1.0" 41 | assert Util.convert(1_000_000_000_000_000, denomination: :milli) == "1.0" 42 | assert Util.convert("1000000000000000", denomination: :finney) == "1.0" 43 | assert Util.convert("1000000000000000", denomination: :milli) == "1.0" 44 | end 45 | 46 | test "converts wei to ether" do 47 | assert Util.convert(1_000_000_000_000_000_000, denomination: :ether) == "1.0" 48 | assert Util.convert("1000000000000000000", denomination: :ether) == "1.0" 49 | end 50 | end 51 | 52 | describe "pretty_float/1" do 53 | test "returns float as a string" do 54 | assert Util.pretty_float(0.000034140807) == "0.000034140807" 55 | end 56 | end 57 | 58 | describe "pretty_float/2" do 59 | test "returns float as a string" do 60 | assert Util.pretty_float(0.000034140807, 8) == "0.00003414" 61 | end 62 | 63 | test "with string float" do 64 | assert Util.pretty_float("0.000034140807", 8) == "0.00003414" 65 | end 66 | end 67 | 68 | describe "wrap/2" do 69 | test "returns a tuple with the element and tag" do 70 | assert {:ok, "hello"} = Util.wrap("hello", :ok) 71 | end 72 | end 73 | 74 | describe "hex_to_number/1" do 75 | test "with valid hex converts to number" do 76 | assert {:ok, 0} = Util.hex_to_number("0x0") 77 | assert {:ok, 211} = Util.hex_to_number("0xd3") 78 | assert {:ok, 5_531_758} = Util.hex_to_number("0x54686e") 79 | end 80 | 81 | test "with invalid hex returns error" do 82 | assert {:error, "invalid hex - \"0x\""} = Util.hex_to_number("0x") 83 | assert {:error, "invalid hex - \"hello\""} = Util.hex_to_number("hello") 84 | assert {:error, "invalid hex - \"0xhello\""} = Util.hex_to_number("0xhello") 85 | assert {:error, "invalid hex - \"0d2d23d23\""} = Util.hex_to_number("0d2d23d23") 86 | end 87 | end 88 | 89 | describe "safe_hex_to_number/1" do 90 | test "with valid hex converts to number" do 91 | assert Util.safe_hex_to_number("0x0") == 0 92 | assert Util.safe_hex_to_number("0xd3") == 211 93 | assert Util.safe_hex_to_number("0x54686e") == 5_531_758 94 | end 95 | 96 | test "with invalid hex returns 0" do 97 | assert Util.safe_hex_to_number("0x") == 0 98 | assert Util.safe_hex_to_number("hello") == 0 99 | assert Util.safe_hex_to_number("0xhello") == 0 100 | assert Util.safe_hex_to_number("0d2d23d23") == 0 101 | end 102 | end 103 | 104 | describe "number_to_hex/1" do 105 | test "converts to hex" do 106 | assert Util.number_to_hex(4_735_742) == "0x4842FE" 107 | end 108 | 109 | test "with string number" do 110 | assert Util.number_to_hex("4735742") == "0x4842FE" 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /test/etherscan_test.exs: -------------------------------------------------------------------------------- 1 | # defmodule EtherscanTest do 2 | # use ExUnit.Case 3 | # end 4 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | --------------------------------------------------------------------------------