From b0d3ecd12e44a0452e903742a5058b3b19b8a207 Mon Sep 17 00:00:00 2001 From: Taylor Dawson Date: Sat, 24 Jun 2017 14:04:47 -0700 Subject: [PATCH 1/7] [W.I.P.] URL Build Alternate Design In order to improve code reuse, I completely redesigned the way that URLs are built. I moved the make_url function (now renamed build_url) to the Client class. I thought this to be a better solution as opposed to having the function implemented in every child class. A few changes still need to be made in order to increase readability. --- etherscan/client.py | 95 +++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 29 deletions(-) diff --git a/etherscan/client.py b/etherscan/client.py index 6bf8872..8a73db5 100644 --- a/etherscan/client.py +++ b/etherscan/client.py @@ -1,44 +1,81 @@ import requests import json - +import collections # Assume user puts his API key in the api_key.json file under variable name "key" class Client(object): dao_address = '0xbb9bc244d798123fde783fcc1c72d3bb8c189413' - URL_BASES = dict( - prefix='https://api.etherscan.io/', - module='api?module=', - action='&action=', - tag='&tag=', - offset='&offset=', - page='&page=', - sort='&sort=', - blocktype='&blocktype=', - key='&apikey=', - address='&address=', - ) - def __init__(self, address, api_key='YourApiKeyToken'): + # Constants + PREFIX = 'https://api.etherscan.io/api?' + MODULE = 'module=' + ACTION = '&action=' + TOKEN_NAME = '&tokenname=' + CONTRACT_ADDRESS = '&contractaddress=' + ADDRESS = '&address=' + OFFSET = '&offset=' + PAGE = '&page=' + SORT = '&sort=' + BLOCK_TYPE = '&blocktype=' + TO = '&to=' + VALUE = '&value=' + DATA = '&data=' + POSITION = '&=' + HEX = '&hex=' + GAS_PRICE = '&gasPrice=' + GAS = '&gas=' + START_BLOCK = '&startblock=' + END_BLOCK = '&endblock=' + BLOCKNO = '&blockno=' + TXHASH = '&txhash=' + TAG = '&tag=' + BOOLEAN = '&boolean=' + INDEX = '&index=' + API_KEY = '&apikey=' + + url_dict = {} + + def __init__(self, address, api_key=''): self.http = requests.session() - self.url = '' - self.module = '' - self.action = '' - self.tag = '' - self.offset = '' - self.page = '' - self.sort = '' - self.blocktype = '' + self.url_dict = collections.OrderedDict( + { + self.MODULE: '', + self.ADDRESS: '', + self.OFFSET: '', + self.PAGE: '', + self.SORT: '', + self.BLOCK_TYPE: '', + self.TO: '', + self.VALUE: '', + self.DATA: '', + self.POSITION: '', + self.HEX: '', + self.GAS_PRICE: '', + self.GAS: '', + self.START_BLOCK: '', + self.END_BLOCK: '', + self.BLOCKNO: '', + self.TXHASH: '', + self.TAG: '', + self.BOOLEAN: '', + self.INDEX: '', + self.API_KEY: api_key, + }) - self.API_KEY = str(api_key) + # self.url_dict[API_KEY] = str(api_key) self.check_and_get_api() - self.key = self.URL_BASES['key'] + self.API_KEY + # self.key = self.URL_BASES['key'] + self.API_KEY + if (len(address) > 20) and (type(address) == list): print("Etherscan only takes 20 addresses at a time") quit() elif (type(address) == list) and (len(address) <= 20): - self.address = self.URL_BASES['address'] + ','.join(address) + self.url_dict[self.ADDRESS] = ','.join(address) else: - self.address = self.URL_BASES['address'] + address + self.url_dict[self.ADDRESS] = address + + def build_url(self): + self.url = self.PREFIX + ''.join([k + v if v else '' for k, v in self.url_dict.items()]) # TODO: better naming def connect(self): # TODO: deal with "unknown exception" error @@ -54,11 +91,11 @@ def connect(self): print("Invalid Request") exit() else: - print("problem with connection, status code: ", req.status_code) + print("Problem with connection, status code: ", req.status_code) exit() def check_and_get_api(self): - if self.API_KEY != 'YourApiKeyToken': + if self.url_dict[self.API_KEY]: # Check if api_key is empty string pass else: - self.API_KEY = input('Please type your EtherScan.io API key: ') + self.url_dict[self.API_KEY] = input('Please type your EtherScan.io API key: ') From 7850e51b1f51402b7a328cfdbc61ab49f439834f Mon Sep 17 00:00:00 2001 From: Taylor Dawson Date: Sat, 24 Jun 2017 14:27:35 -0700 Subject: [PATCH 2/7] Updated Token class I updated the token class to comply with the new url build design. --- etherscan/tokens.py | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/etherscan/tokens.py b/etherscan/tokens.py index 195b788..82dd098 100644 --- a/etherscan/tokens.py +++ b/etherscan/tokens.py @@ -4,34 +4,19 @@ class Tokens(Client): def __init__(self, tokenname='TheDAO', api_key='YourApiKeyToken'): Client.__init__(self, address='', api_key=api_key) - self.tokenname = '&tokenname=' + tokenname - - def make_url(self, call_type=''): - if call_type == 'tokensupply': - self.url = self.URL_BASES['prefix'] \ - + self.module \ - + self.action \ - + self.tokenname \ - + self.key - elif call_type == 'tokenbalance': - self.url = self.URL_BASES['prefix'] \ - + self.module \ - + self.action \ - + self.tokenname \ - + self.address \ - + self.key + self.url_dict[self.TOKEN_NAME] = tokenname def get_total_supply(self): - self.action = self.URL_BASES['action'] + 'tokensupply' - self.module = self.URL_BASES['module'] + 'stats' - self.make_url(call_type='tokensupply') + self.url_dict[self.ACTION] = 'tokensupply' + self.url_dict[self.MODULE] = 'stats' + self.build_url() req = self.connect() return req['result'] def get_token_balance(self, address): - self.address = self.URL_BASES['address'] + address - self.module = self.URL_BASES['module'] + 'account' - self.action = self.URL_BASES['action'] + 'tokenbalance' - self.make_url(call_type='tokenbalance') + self.url_dict[self.ADDRESS] = address + self.url_dict[self.MODULE] = 'account' + self.url_dict[self.ACTION] = 'tokenbalance' + self.build_url() req = self.connect() - return req['result'] + return req['result'] \ No newline at end of file From 472421dbf692b541e0f411bc41b5566125cb77c8 Mon Sep 17 00:00:00 2001 From: Taylor Dawson Date: Wed, 19 Jul 2017 11:05:40 -0700 Subject: [PATCH 3/7] Updated .gitignore file Signed-off-by: Taylor Dawson --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0af19e5..210a6c8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ # Temporary data .ipynb_checkpoints/ /examples/stats/.ipynb_checkpoints +/.cache/ From 8e4a7e86f67d6235f5ff2c1aad98f74362d80153 Mon Sep 17 00:00:00 2001 From: "Taylor J. Dawson" Date: Wed, 19 Jul 2017 11:48:03 -0700 Subject: [PATCH 4/7] Updated files to comply with the alternative url building method --- etherscan/contracts.py | 16 ++++------------ etherscan/stats.py | 17 +++++------------ etherscan/tokens.py | 2 +- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/etherscan/contracts.py b/etherscan/contracts.py index be21fb4..c18b175 100644 --- a/etherscan/contracts.py +++ b/etherscan/contracts.py @@ -4,18 +4,10 @@ class Contract(Client): def __init__(self, address=Client.dao_address, api_key='YourApiKeyToken'): Client.__init__(self, address=address, api_key=api_key) - self.module = self.URL_BASES['module'] + 'contract' - - def make_url(self, call_type=''): - if call_type == 'getabi': - self.url = self.URL_BASES['prefix'] \ - + self.module \ - + self.action \ - + self.address \ - + self.key + self.url_dict[self.MODULE] = 'contract' def get_abi(self): - self.action = self.URL_BASES['action'] + 'getabi' - self.make_url(call_type='getabi') + self.url_dict[self.ACTION] = 'getabi' + self.build_url() req = self.connect() - return req['result'] \ No newline at end of file + return req['result'] diff --git a/etherscan/stats.py b/etherscan/stats.py index 6fe74f2..1d61ecb 100644 --- a/etherscan/stats.py +++ b/etherscan/stats.py @@ -4,23 +4,16 @@ class Stats(Client): def __init__(self, api_key='YourApiKeyToken'): Client.__init__(self, address='', api_key=api_key) - self.module = self.URL_BASES['module'] + 'stats' - - def make_url(self, call_type=''): - if call_type == 'stats': - self.url = self.URL_BASES['prefix'] \ - + self.module \ - + self.action \ - + self.key + self.url_dict[self.MODULE] = 'stats' def get_total_ether_supply(self): - self.action = self.URL_BASES['action'] + 'ethsupply' - self.make_url(call_type='stats') + self.url_dict[self.ACTION] = 'ethsupply' + self.build_url() req = self.connect() return req['result'] def get_ether_last_price(self): - self.action = self.URL_BASES['action'] + 'ethprice' - self.make_url(call_type='stats') + self.url_dict[self.ACTION] = 'ethprice' + self.build_url() req = self.connect() return req['result'] diff --git a/etherscan/tokens.py b/etherscan/tokens.py index 82dd098..43087d8 100644 --- a/etherscan/tokens.py +++ b/etherscan/tokens.py @@ -19,4 +19,4 @@ def get_token_balance(self, address): self.url_dict[self.ACTION] = 'tokenbalance' self.build_url() req = self.connect() - return req['result'] \ No newline at end of file + return req['result'] From d9178a73807b306ae26f03bed91dda3b123c4458 Mon Sep 17 00:00:00 2001 From: "Taylor J. Dawson" Date: Wed, 26 Jul 2017 11:52:23 -0700 Subject: [PATCH 5/7] Redesigned URL build To increase code reuse I have moved the build_url method from the child classes and into the parent class, 'Client'. I also desgined a highly pythonic way of contructing the url. The children classes are repsonible for setting the values of the api parameters that are located within the parent class. --- etherscan/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 178 bytes etherscan/__pycache__/accounts.cpython-36.pyc | Bin 0 -> 4728 bytes etherscan/__pycache__/client.cpython-36.pyc | Bin 0 -> 2766 bytes .../__pycache__/contracts.cpython-36.pyc | Bin 0 -> 797 bytes etherscan/__pycache__/stats.cpython-36.pyc | Bin 0 -> 1005 bytes etherscan/__pycache__/tokens.cpython-36.pyc | Bin 0 -> 1104 bytes etherscan/accounts.py | 94 +++++++----------- etherscan/client.py | 4 +- etherscan/contracts.py | 2 +- 9 files changed, 37 insertions(+), 63 deletions(-) create mode 100644 etherscan/__pycache__/__init__.cpython-36.pyc create mode 100644 etherscan/__pycache__/accounts.cpython-36.pyc create mode 100644 etherscan/__pycache__/client.cpython-36.pyc create mode 100644 etherscan/__pycache__/contracts.cpython-36.pyc create mode 100644 etherscan/__pycache__/stats.cpython-36.pyc create mode 100644 etherscan/__pycache__/tokens.cpython-36.pyc diff --git a/etherscan/__pycache__/__init__.cpython-36.pyc b/etherscan/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..669c23a0617e88bf44d6b5a21daad4b874a9a6d5 GIT binary patch literal 178 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 D?9Qh% literal 0 HcmV?d00001 diff --git a/etherscan/__pycache__/contracts.cpython-36.pyc b/etherscan/__pycache__/contracts.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e36b426b3959107fe3ae6b7114edfc3f33d90de GIT binary patch literal 797 zcmZvazi-qq6vzGIT#_DFaf~d8fh9w`u%Q!bbp?cgYbDyDRwOHpU79qP+}VlHRmXH) z`3Lw9_?NOWu`x68p6`b`;ON)CKOnHjmGsQKmxbT$!nZ>=|c%H@31>-W;Rg>Y{u5p|lVb~YgX(m81;b~s@3a&jT z2BN2Y)w^dRPyxz?T{Nz%#-v#z9$(h2IiBSo^y0j})m27v)M)Hsj4_mIOIA?u5mtb*d=h(Im?~wowK$pO@>VZIlx=dwzVT43i=@n}ypghtT2o4uqmAIx z>B+^%H!<>IKOcd<>=k$;=)Of8UN@B^Op3n>2+=zb0pk>?SqSGgB8jYiu%G9O&i- zzh`N6fT@$+Te8h>4`&M#pcv^|%D`XP3j|Dy$&(Ohj9_ z(Q{Yvy6fXw7owU(IRas67lQ#r_}mS5-Zxt&bh%Pi=~N@%zLe8iwI$65QqJ47Tz_#F zAs(r;mYe%>V9WruA7rP5hAbGOK*Suj2!_5}nZ#TKnfoQ3qFemm`7Ro*jl3qbmbec1 EKRS=LasU7T literal 0 HcmV?d00001 diff --git a/etherscan/__pycache__/stats.cpython-36.pyc b/etherscan/__pycache__/stats.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..836fd7bae3060be17a7514dd5c07dbcadbc566f1 GIT binary patch literal 1005 zcmbtT!EVz)5Z(3KjuVo$AcO?szyTro&|Z2&5o!qtAt0^P_E5{x%6J#*)Un;&wUDcD zO0Rqc2gEP=%86g##LOB(iny`S%#O$7H}CCEc1NSZ=P%{yu0zN-vbJ1^_rUZ6aDoV$ zlR1qjB`=6@1iK=FNxEc_BithrdfzFOg|zi2c_s^!!qaLoi1xtrBXE*LR1o;AZ((S} zge$x&61l<`J=i@F0N|kYj!a^7yLnpHYQM@}$>z8`mqiLh?ZVvyn}Au8hRo;!h%Tsb zJ~0Xe7i8vuu`vh$On2In(20795K3y@_L3^&=dy`BjjcjgA!ZwJo)wwlybWrVbCIPc z^4}ahJ9+&)bXr%-{GIZl@GDUR*nT{nJdRJaR5~^@k$i{`oAfME^Fvk6WNLI=HQUmh z!TU5RwxMObdWvn|ovKki075YukDbshdbwfc@BHSH;`!o2ig=(__Cp9jFqsiBI!5m- z3B{c)$wzw>cTqZ#E9|)(81@Za{DV0Ik12IevLCZToNQEEgO^x4pD13Sb{P zs*fd1$qTEtb2l(|=e;!ClqSi!Rm3}Vtk;N3=#U2RyS(2?`FHvM3k#rorLt72AvFCZ zN{t{^8|XGM+v!kSn7~_G({US#bqexC8*Z`iqw6Z}{Za9E@ie3gFD~?Pc#32$VR#0d z&r4C~7!NtWsFS>VV=r6XL=v}FOs;cMc*BUOanJ%fa0B1wrXh>`)c(cnu-fFBAPZw} QCm46#pWxtVoSGr~39{?s+W-In literal 0 HcmV?d00001 diff --git a/etherscan/__pycache__/tokens.cpython-36.pyc b/etherscan/__pycache__/tokens.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..546cd08b7c5a22c7986fa33d5bd3a99413af43cb GIT binary patch literal 1104 zcmZvb&u`N(6vyp2Nz<-l8^5`6Ldszi5;s(#Rc(dPSUR!ou&9!i#fG*^lg@U8I+fFQ z<2U&8;88{)*jz=`*qtqg=CKR^F^_UG%D7whY-Z(oX&?+zh9$gSdnzYA4A1tW-{ z8JW?TQu3MzN3bg*n5361c7%IKLhmPqWg)HnUN(`rNujqY47^>a`WYBWVk!u1YY8UY zD;hK53IB@3u4sq=T2C|~;9BJ$6=yQn(2ixlJFGTNic)pwlRdexGbx6}f~^O&2i4xz zkSSfljhBvaJ~K*|(3?6?SqDfUIEyM0I#nYPLP@Q`nNRqcT!gLy8AugyKFKGB^C~D+ z#>FHxaqDQfH;8!D-5-Rka<$CfS51Rg%#)c^0qpxq)H*c3dcBvUV=a{)nW;!Vjt&;- zI8n0$RZL}S^k}}=mSzm|X_9Zl(W6ywWCQA*`9d`z5>jb=2tqgM#YQd2&dudglpG7* z8AY%HJO>BR$&^5)0F2=1I~}y_l7Jv&>RyshbV&t!f`YhFyjCAw&ga=8_OwY1NDu0i znF&4Bf~b|>?H#=tMwP!m>>s}!RL#?Jk_iqHRgJXBbASsSwT4TXlIK>8+T6jh%@5LW zQmm}u-hcz_3LIX&2DacHfIE;G zEAU2=rbU^XxNQ|UO|m3UrP_edp>M(CMz`O8H#j_0TQI0L(cDFI57#hDtQt6Q9}VWf zE$pot1rmi{$HoA<4W{P4CV%`F`K{#A&|Fdaf4vlCMeva`kctPo{}ew*|2GRf*0 zn?33QZhDC3&y}o)&!JF646A)G0d2WK!;VEEi~ZF8#rAKoga3 (default) get normal external transactions """ if internal: - self.action = self.URL_BASES['action'] + 'txlistinternal' + self.url_dict[self.ACTION] = 'txlistinternal' else: - self.action = self.URL_BASES['action'] + 'txlist' - self.page = self.URL_BASES['page'] + str(page) - self.offset = self.URL_BASES['offset'] + str(offset) - self.sort = self.URL_BASES['sort'] + sort - self.make_url(call_type='transactions') + self.url_dict[self.ACTION] = 'txlist' + self.url_dict[self.PAGE] = str(page) + self.url_dict[self.OFFSET] = str(offset) + self.url_dict[self.SORT] = sort + self.build_url() req = self.connect() return req['result'] def get_all_transactions(self, offset=10000, sort='asc', internal=False) -> list: if internal: - self.action = self.URL_BASES['action'] + 'txlistinternal' + self.url_dict[self.ACTION] = 'txlistinternal' else: - self.action = self.URL_BASES['action'] + 'txlist' - self.page = self.URL_BASES['page'] + str(1) - self.offset = self.URL_BASES['offset'] + str(offset) - self.sort = self.URL_BASES['sort'] + sort - self.make_url(call_type='transactions') + self.url_dict[self.ACTION] = 'txlist' + self.url_dict[self.PAGE] = str(1) + self.url_dict[self.OFFSET] = str(offset) + self.url_dict[self.SORT] = sort + self.build_url() trans_list = [] while True: - self.make_url(call_type='transactions') + self.build_url() req = self.connect() if "No transactions found" in req['message']: print("Total number of transactions: {}".format(len(trans_list))) @@ -109,9 +83,9 @@ def get_all_transactions(self, offset=10000, sort='asc', internal=False) -> list else: trans_list += req['result'] # Find any character block that is a integer of any length - page_number = re.findall(r'[1-9](?:\d{0,2})(?:,\d{3})*(?:\.\d*[1-9])?|0?\.\d*[1-9]|0', self.page) + page_number = re.findall(r'[1-9](?:\d{0,2})(?:,\d{3})*(?:\.\d*[1-9])?|0?\.\d*[1-9]|0', self.url_dict[self.PAGE]) print("page {} added".format(page_number[0])) - self.page = self.URL_BASES['page'] + str(int(page_number[0]) + 1) + self.url_dict[self.PAGE] = str(int(page_number[0]) + 1) def get_blocks_mined_page(self, blocktype='blocks', page=1, offset=10000) -> list: """ @@ -124,22 +98,22 @@ def get_blocks_mined_page(self, blocktype='blocks', page=1, offset=10000) -> lis 'blocks' -> full blocks only 'uncles' -> uncles only """ - self.action = self.URL_BASES['action'] + 'getminedblocks' - self.blocktype = self.URL_BASES['blocktype'] + blocktype - self.page = self.URL_BASES['page'] + str(page) - self.offset = self.URL_BASES['offset'] + str(offset) - self.make_url(call_type='blocks') + self.url_dict[self.ACTION] = 'getminedblocks' + self.url_dict[self.BLOCK_TYPE] = blocktype + self.url_dict[self.PAGE] = str(page) + self.url_dict[self.OFFSET] = str(offset) + self.build_url() req = self.connect() return req['result'] def get_all_blocks_mined(self, blocktype='blocks', offset=10000) -> list: - self.action = self.URL_BASES['action'] + 'getminedblocks' - self.blocktype = self.URL_BASES['blocktype'] + blocktype - self.page = self.URL_BASES['page'] + str(1) - self.offset = self.URL_BASES['offset'] + str(offset) + self.url_dict[self.ACTION] = 'getminedblocks' + self.url_dict[self.BLOCK_TYPE] = blocktype + self.url_dict[self.PAGE] = str(1) + self.url_dict[self.OFFSET] = str(offset) blocks_list = [] while True: - self.make_url(call_type='blocks') + self.build_url() req = self.connect() print(req['message']) if "No transactions found" in req['message']: @@ -148,9 +122,9 @@ def get_all_blocks_mined(self, blocktype='blocks', offset=10000) -> list: else: blocks_list += req['result'] # Find any character block that is a integer of any length - page_number = re.findall(r'[1-9](?:\d{0,2})(?:,\d{3})*(?:\.\d*[1-9])?|0?\.\d*[1-9]|0', self.page) + page_number = re.findall(r'[1-9](?:\d{0,2})(?:,\d{3})*(?:\.\d*[1-9])?|0?\.\d*[1-9]|0', self.url_dict[self.PAGE]) print("page {} added".format(page_number[0])) - self.page = self.URL_BASES['page'] + str(int(page_number[0]) + 1) + self.url_dict[self.PAGE] = str(int(page_number[0]) + 1) def get_internal_by_hash(self, tx_hash=''): """ diff --git a/etherscan/client.py b/etherscan/client.py index 8a73db5..e118739 100644 --- a/etherscan/client.py +++ b/etherscan/client.py @@ -75,8 +75,8 @@ def __init__(self, address, api_key=''): self.url_dict[self.ADDRESS] = address def build_url(self): - self.url = self.PREFIX + ''.join([k + v if v else '' for k, v in self.url_dict.items()]) # TODO: better naming - + self.url = self.PREFIX + ''.join([param + val if val else '' for param, val in self.url_dict.items()]) # TODO: better naming + print(self.url) def connect(self): # TODO: deal with "unknown exception" error try: diff --git a/etherscan/contracts.py b/etherscan/contracts.py index c18b175..28c27a2 100644 --- a/etherscan/contracts.py +++ b/etherscan/contracts.py @@ -4,7 +4,7 @@ class Contract(Client): def __init__(self, address=Client.dao_address, api_key='YourApiKeyToken'): Client.__init__(self, address=address, api_key=api_key) - self.url_dict[self.MODULE] = 'contract' + self.url_dict[self.MODULE] = 'contract' def get_abi(self): self.url_dict[self.ACTION] = 'getabi' From 49438b674ba4959d631886b47d5380024155e548 Mon Sep 17 00:00:00 2001 From: "Taylor J. Dawson" Date: Tue, 1 Aug 2017 10:47:09 -0700 Subject: [PATCH 6/7] Removed a line I was using for debugging --- etherscan/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etherscan/client.py b/etherscan/client.py index e118739..5e24616 100644 --- a/etherscan/client.py +++ b/etherscan/client.py @@ -76,7 +76,7 @@ def __init__(self, address, api_key=''): def build_url(self): self.url = self.PREFIX + ''.join([param + val if val else '' for param, val in self.url_dict.items()]) # TODO: better naming - print(self.url) + def connect(self): # TODO: deal with "unknown exception" error try: From 352c7d0c3ee960bc00eaac6451b8f28f49977b6e Mon Sep 17 00:00:00 2001 From: "Taylor J. Dawson" Date: Tue, 1 Aug 2017 10:52:17 -0700 Subject: [PATCH 7/7] Removed completed TODO --- etherscan/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etherscan/client.py b/etherscan/client.py index 5e24616..e52e560 100644 --- a/etherscan/client.py +++ b/etherscan/client.py @@ -75,7 +75,7 @@ def __init__(self, address, api_key=''): self.url_dict[self.ADDRESS] = address def build_url(self): - self.url = self.PREFIX + ''.join([param + val if val else '' for param, val in self.url_dict.items()]) # TODO: better naming + self.url = self.PREFIX + ''.join([param + val if val else '' for param, val in self.url_dict.items()]) def connect(self): # TODO: deal with "unknown exception" error