From d2bbf926bd311fd5a9efebc9a68d37456be6790e Mon Sep 17 00:00:00 2001 From: Jay Graber Date: Tue, 11 Apr 2017 17:13:25 -0700 Subject: [PATCH] minimal functions --- README.md | 3 ++ __init__.py | 0 pyZcash/__init__.py | 0 pyZcash/__init__.pyc | Bin 0 -> 137 bytes pyZcash/examples/__init__.py | 0 pyZcash/examples/sweep_all.py | 64 +++++++++++++++++++++++ pyZcash/examples/tests.py | 39 ++++++++++++++ pyZcash/rpc/ZDaemon.py | 93 ++++++++++++++++++++++++++++++++++ pyZcash/rpc/ZDaemon.pyc | Bin 0 -> 8628 bytes pyZcash/rpc/__init__.py | 0 pyZcash/rpc/__init__.pyc | Bin 0 -> 141 bytes pyZcash/settings.py | 31 ++++++++++++ pyZcash/settings.pyc | Bin 0 -> 670 bytes 13 files changed, 230 insertions(+) create mode 100644 README.md create mode 100644 __init__.py create mode 100644 pyZcash/__init__.py create mode 100644 pyZcash/__init__.pyc create mode 100644 pyZcash/examples/__init__.py create mode 100644 pyZcash/examples/sweep_all.py create mode 100644 pyZcash/examples/tests.py create mode 100644 pyZcash/rpc/ZDaemon.py create mode 100644 pyZcash/rpc/ZDaemon.pyc create mode 100644 pyZcash/rpc/__init__.py create mode 100644 pyZcash/rpc/__init__.pyc create mode 100644 pyZcash/settings.py create mode 100644 pyZcash/settings.pyc diff --git a/README.md b/README.md new file mode 100644 index 0000000..7ba4501 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +Python API for ZCash + +Forked from 5a1t, last updated for v1.0.8 rpc interface. Incomplete diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyZcash/__init__.py b/pyZcash/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyZcash/__init__.pyc b/pyZcash/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08bd93f537569df26d55306fee233bcc65d34cbf GIT binary patch literal 137 zcmZSn%*$oq_BJA!0SXv_v;zF4FhaMd% literal 0 HcmV?d00001 diff --git a/pyZcash/examples/__init__.py b/pyZcash/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyZcash/examples/sweep_all.py b/pyZcash/examples/sweep_all.py new file mode 100644 index 0000000..14e87ca --- /dev/null +++ b/pyZcash/examples/sweep_all.py @@ -0,0 +1,64 @@ +import os.path +import sys +import time + +from pyzcash.rpc.ZDaemon import * +from pyzcash.settings import * + + +#Sweeps all unspent transparent txs, cleaning them through a temporary zaddr. +def clean_and_collect_all(taddress=TEST_TADDR, fee=DEFAULT_FEE): + zd = ZDaemon() + + print "Checking balance..." + tx_unspents = zd.getUnspentTxs() + if not len(tx_unspents): + print "No spendable txs available - visit a faucet or mine!" + exit() + + print "Generating temporary zaddress for tx..." + zaddress_full = zd.getNewRawZAddress() + zaddress = zaddress_full.get('zcaddress') + zsecret = zaddress_full.get('zcsecretkey') + + print "Generated: " + zaddress + print "Secret: " + zsecret + + print "Gathering and transmitting unspent txs..." + print "Please wait..." + notes = zd.pourAllUnspentTxs(zaddress) + encnote1 = notes.get('encryptednote1') + + + print "Found a note to use: \n--------------------------------------------\n" + encnote1 + "\n--------------------------------------------" + + print "Waiting for note to show in blockchain before spendable..." + print "This may take a few minutes..." + while zd.receiveTx(zsecret, encnote1).get('exists') is not True: + print zd.receiveTx(zsecret,encnote1) + time.sleep(5) + + print "Found note in blockchain!" + total = zd.receiveTx(zsecret, encnote1).get('amount') + print "Examined note and found total: " + str(total) + + print "Spending note to target transparent address..." + tx_response = zd.sendNoteToAddress(encnote1, zsecret, taddress, total-fee, zaddress) + + print "Sent! Check " + taddress + " shortly." + + +if __name__ == "__main__": + if len(sys.argv) <= 1: + print "Usage: python sweep_all.py " + print "Ex: python sweep_all.py mfu8LbjAq15zmCDLCwUuay9cVc2FcGuY4d" + exit() + + taddr = sys.argv[1] + if len(taddr) != len('mfu8LbjAq15zmCDLCwUuay9cVc2FcGuY4d'): + print "That doesn't look like a transparent address.. Maybe you are trying to use a zaddress?" + exit() + + print "Address looks good!" + clean_and_collect_all(taddr) + diff --git a/pyZcash/examples/tests.py b/pyZcash/examples/tests.py new file mode 100644 index 0000000..c8f659e --- /dev/null +++ b/pyZcash/examples/tests.py @@ -0,0 +1,39 @@ +import os.path +import sys + +from pyzcash.rpc.ZDaemon import * +from pyzcash.settings import * + + +def test_daemon(): + zd = ZDaemon() + + print zd.getBlockHash(100) + print zd.getBlockByHash(zd.getBlockHash(100)) + print zd.getBlockByHeight(100) + print zd.getNetworkHeight() + print zd.getNetworkDifficulty() + print zd.getTotalBalance() + print zd.getConnectionCount() + print zd.getNewAddress() + print zd.getNewZAddress() + + print zd.getUnspentTxs() + tx_amount = zd.getTxInfo(TEST_TXID).get('details')[0].get('amount') + tx = zd.createNewRawTxFromTxid(TEST_TXID) + pourtx = zd.pourRawTx(tx, TEST_ZADDR, tx_amount) + hextx = zd.signRawTx(pourtx.get('rawtxn')) + + print zd.sendRawTx(hextx.get('hex')) + + print pourtx + print hextx + +# print zd.sendNoteToAddress(encnote, TEST_ZSECRET, TEST_TADDR, 0.33, TEST_ZADDR) + +# print zd.sendNoteToAddress(encnote, TEST_ZSECRET, faucet_addr, 0.33, TEST_ZADDR) + + +if __name__ == "__main__": + test_daemon() + diff --git a/pyZcash/rpc/ZDaemon.py b/pyZcash/rpc/ZDaemon.py new file mode 100644 index 0000000..240a691 --- /dev/null +++ b/pyZcash/rpc/ZDaemon.py @@ -0,0 +1,93 @@ +import requests +import json + +from pyZcash.settings import * + +class ZDaemon(object): + + id_count = 0 + + def __init__(self, url=ZURL, user=RPCUSER, password=RPCPASSWORD, timeout=TIMEOUT): + #TODO: check utf safety + self.url = url + self.user = user.encode('utf8') + self.password = password.encode('utf8') + self.timeout = timeout + + def _call(self, method, *args): + jsondata = json.dumps({ 'version': '2', + 'method': method, + 'params': args, + 'id': self.id_count}) + + r = requests.post(self.url, auth=(self.user,self.password), data=jsondata, timeout=self.timeout) + + self.id_count += 1 + resp = json.loads(r.text) + + #TODO: deal with errors better. + error = resp['error'] + if error: + print error + + return resp['result'] + + #Block Info + def getBlockHash(self, blockheight): + return self._call('getblockhash', blockheight) + + def getBlockByHash(self, blockhash): + return self._call('getblock', blockhash) + + def getBlockByHeight(self, blockheight): + return self.getBlockByHash(self.getBlockHash(blockheight)) + + #Network Info + def getNetworkHeight(self): + return self._call('getblockcount') + + def getNetworkDifficulty(self): + return self._call('getdifficulty') + + def getVersion(self): + info = self._call('getnetworkinfo') + client = info['subversion'] + version = client.strip('/').split(':')[1] + return version + + def getConnectionCount(self): + return self._call('getconnectioncount') + + #Wallet Info (transparent) + def getTotalBalance(self, account=""): + if account: + return self._call('getbalance', account) + else: + return self._call('getbalance') + + def getUnspentTxs(self, minconf=1): + return self._call('listunspent', minconf) + + #Raw Txs + def getTxInfo(self, txid): + return self._call('gettransaction', txid) + + # taddr methods + def getNewAddress(self, account=""): + if account: + return self._call('getnewaddress', account) + else: + return self._call('getnewaddress') + + def sendTransparent(self, taddress, amount): + return self._call('sendtoaddress', taddress, amount) + + # zaddr methods + def z_getnewaddress(self): + return self._call('z_getnewaddress') + + def z_listaddresses(self): + return self._call('z_listaddresses') + + def z_listreceivedbyaddress(self, zaddr): + return self._call('z_listreceivedbyaddress', zaddr) diff --git a/pyZcash/rpc/ZDaemon.pyc b/pyZcash/rpc/ZDaemon.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b682a6ce24927c6c1b0912678152ff4b9f4c9f17 GIT binary patch literal 8628 zcmcIqTW=f36`oyElqge{EZ?NqiF0upwJ0LMZRIp@llbnW36qZG*i{=4tKE^bGPz`S zhc+dMEl?Q+3iP3G0ou2|^re5J=zD?wj6U@TwBL7Tm!w<;wPHrn4$scc&biEYE;Cf= z-!s#H3;*>nRQXQ{pC91LuAzzW=c%Sr>jTz?%cs_Cn>sH99uZKA8Jo+@>q)X&$; zd}(!Q0u#jl!B2h318LcO&rYIUzZIBPI~nlg$Q!sajWGt#g~PhfsZCj#31upr^J!VF zPpZf#r}ZfX-Xy9y@AYXFO-RoP6;*_&sc2G&85KC2yszGi$c7tqL+ktg)GPgWAJxTw7#Uwt15a~W_wNOSA>3DMVI8QH>C4b z>AWoTYeK)N^y<>!JSzR`%2*fts`F-t~ylwbAc@f%VZvSR05T-l$|SVarOf@vUc1;zsIR$!{Aj1N2o zHKA5uvVKWH`5iIP&IB>Y$F7}Jn;17qg93@{pMsT3eHmQl994DIZ}`HmN-OV7a~b** zY9CWgtHnMhs;KmjZ13Jnuv+Lpp%zz{Y7nz7?sY|M`q-pd+)iWxTE=d-BOyCM8niM? zE#pX*B$rV&zyom6kVY+D_%Y)MVYJT{=NyaD{d<%*`QDx7EqSrg78=+ug*< zO=`aEn#^W0xYN$;QOhY4G}}SshFR0IOSHYF@ijGa5~f>@1DR4vQ8SfikgKClVdPk# zL4_J&&}^Osk)1=MN^{;Me&T z;j0)hRF4cq{ul63`XyM3=r?vL{4#pJR(P(Ivp!q50207fMc%qI^kt0Fub~;*UBAj( zTrVs!0Wc!5tl|~)6*AMOc+u#Bm>CcQ#K6gmILiLQ+Tu?mCg%i#mvM?*Hx`lj(LE9Q zDmZ*ok)wEXGY%0ZcE2@|&p6}cBHtP?WCj}*n;~jo=^x`})Y5$c2;%r+AIZ(7yAtCp zBXF4nV)-HhIpXx{5|dBe=73C`t>R>}ZKuhzyHNyMuFbMUrgtTPE=m5Pn@gC>Y#MhQ z)oI3di4r>3CnXb-Q`n46Vl~6TSk{s>sE+4DF~gyAYV9E%wi5K%39k7%^QyIJ#=LRfI@$ijWO6lWpwg!fF;tBN~l2eB@eOZ#J(Noa^A1yP^2N|E|v=H4f)VV!jz?wwq)f z_`rzVhgYH%1AEElSllBIw)Y*&wO;nKp$5kiK93JJ4U#Mn|2R^9`nv7K(O86M+9iy7 zA0iyxe@1X}8i3~kZXEt;auk$4w*p&It)hqZsHYZzs%xX+kbT?=NJuQklraW5R(1uL z$?fp!va!(bgN+oQsP==n>8iTNtn4X?{(z53L1+o6VQKgI_Ko~-qTA#pg7?V(Ud ztR(_$Z!A`0t#Fv}owVIr!=gOIlZ@d&Av#w5lip=Nq`16j&YQTh(`W{vgtmh#GEGpz zx@CTHlc&Lxqrt%0Tv%bXDGFLCb?Lti7^?$&;mM0e8GQ?L1h||-9#$uke%rna8D@_1ylyLFch0rsjJM%ylGe#w&GR zSU~DR<|EaI`8m8C5kq%5fVrR}UM9N+PCG@^%5-Rphh3r2yyT7BD zr!`+~0AV)%+(1qSRpk$Mow5>rIgt|Zq1zDfGP;lXx`v?rMOrBP5 zSaad#g_naTE9K$4y`g^N zrO!0&4s3bOB&9KrXI)7Q!s(2nu&j7ki+&)W!UJJg1lbyYeVhQJAA={QAA_ae!?@fq z?#z`{RU&GmL~%*^b4VkVoo|wS$gvoc zk(G18WrjPcKcO=teiV+?XT1e)!9Q0zZavNS#Z^)hn)vbP_M8jlf))X|ml@RER$L%# z262l{GZy8Dl$`ro?=QG1kV3YMOSGsUKoy9kZc)EG|T$t@etcW zmJY6tZ8XiMTYY)TM#|O=oa#IR);Gy-tKi4L+i+iLjL!>-T}K_f*V;wy_$zp33uu%- z@16E${hBv}?-VYSX8a32T*40v9Pv|d^iL4q1V@awId-u00xCd1seqVnq2-lz8yuW%|i!Xrw?E32JgHQD>dA9c9 zC$~Snzox5rLB4U4uRru<-oDA^EjHg}bA`owQ zC_*874^73d_-7}p=c^_BPDop+PSh&ZQmu@;>MYw*t%jb7s?gQ)*~wbDR>P<&dokNpT_Qnp*#fA0Q6cHp`b8G(|m6Dxe&8wBBC;kgLx78y6 literal 0 HcmV?d00001 diff --git a/pyZcash/rpc/__init__.py b/pyZcash/rpc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyZcash/rpc/__init__.pyc b/pyZcash/rpc/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71358133db4c9268c1304dec4fa00aac9b54fe2e GIT binary patch literal 141 zcmZSn%*$oq_BJA!0SXv_v;zF4F D5H=p6 literal 0 HcmV?d00001 diff --git a/pyZcash/settings.py b/pyZcash/settings.py new file mode 100644 index 0000000..8807705 --- /dev/null +++ b/pyZcash/settings.py @@ -0,0 +1,31 @@ +import os, re +#ZCASH RPC +# Address and port of local zcashd testnet rpc +ZURL = "http://localhost:18232" +#Timeout needs to be high for any pour operations +TIMEOUT = 600 +#Default fee to use on network for txs. +DEFAULT_FEE = 0.01 + +zcashconf = os.path.expanduser('~/.zcash/zcash.conf') + +def read_config(filename): + f = open(filename) + for line in f: + if re.match('rpcuser', line): + user = line.strip('\n').split('=')[1] + if re.match('rpcpassword', line): + password = line.strip('\n').split('=')[1] + return (user, password) + +config = read_config(zcashconf) +# from zcash conf +RPCUSER = config[0] +RPCPASSWORD = config[1] + +#TESTS +#for tests (sample data here - replace with your own) +TEST_TXID = '' +TEST_ZADDR = "" +TEST_TADDR = "" +TEST_ZSECRET = "" diff --git a/pyZcash/settings.pyc b/pyZcash/settings.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b246f407a05695453e1179a3932606be8be578d GIT binary patch literal 670 zcmYLG&2ri>5EefPN!rZx(CGv8lv8btZA_-q#@I3h5<+bmgD#A*1Sb60#4^G3+UMyz zwfCO-0+l_PMmziMe!J4QquI*e%ZuOEpK$B;9 zBcq+Lk9@{v9*#^429sl_y^T5$jhcr{_VkU>eq5^kd1x`2UqgM*?zZ~NhGOUz8pe&x zk?PKNmxZxz_ZD+sb4lvOtZz;--F@l?W7im5o#&sZa=@;A$7;FG?LB;OQIXq2!*!s| z-taolhq~i<54Krw6I!}^ho%;UELTC$K~proHCeu@f??e>?N^El`u2a