diff --git a/.gitignore b/.gitignore index 564a8be..df096f8 100644 --- a/.gitignore +++ b/.gitignore @@ -115,4 +115,6 @@ dmypy.json # Tests test.py -testy.py \ No newline at end of file +testy.py +.vscode +.VSCodeCounter \ No newline at end of file diff --git a/README.md b/README.md index 835de61..7526668 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ ***PNRW is a Python Wrapper for the Nano RPC protocol.*** +***PNRW supports Banano as well!*** + --- ![badge](https://img.shields.io/pypi/dm/pnrw?style=for-the-badge) @@ -72,6 +74,14 @@ import pnrw node = pnrw.Node("mynano.ninja/api/node") # Create a new node instance ``` +#### Starting code for Banano + +```py +import pnrw + +node = pnrw.Node("kaliumapi.appditto.com/api", banano=True) # Create a new node instance +``` + #### Getting basic node information ```py @@ -83,7 +93,7 @@ print(node.block_count()) # Check node block count print(node.version()["protocol_version"]) # Print protocol version of node print(node.uptime()) # Print node uptime in seconds ``` - + #### Showing current account balance ```py @@ -97,6 +107,17 @@ myBalance = node.rai_from_raw(balance["balance"]) # Convert from raw to Nano print(f"I currently have {myBalance} Nano!") ``` +#### Convert units + +```py +from pnrw import convert + +print(convert.convert(123,"nano","knano")) # convert 123 Nano to kNano +print(convert.convert(456,"ban","banoshi")) # convert 456 Banano to banoshi +``` + + + --- ## Differences from official commands diff --git a/pnrw/__init__.py b/pnrw/__init__.py index da4cedc..83a50e3 100644 --- a/pnrw/__init__.py +++ b/pnrw/__init__.py @@ -1,3 +1,4 @@ -from .pnrwf import Node as N +from .pnrwf import Node + +from . import convert from . import exceptions -Node = N \ No newline at end of file diff --git a/pnrw/convert.py b/pnrw/convert.py new file mode 100644 index 0000000..9788634 --- /dev/null +++ b/pnrw/convert.py @@ -0,0 +1,27 @@ +""" +https://nanoo.tools/unit-converter +""" + +table = {"raw":1} + +def _table(currency="nano"): + if currency.lower() == "nano": + for i, p in enumerate(["G","M","k","","m","u"]): + inRaw = 10 ** (33-(i*3)) + table[p+currency] = inRaw + elif currency.lower() == "ban": + for i, p in enumerate(["Gban","Mban","kban","ban","banoshi"]): + if p != "banoshi": + t = 3 + else: + t = 11 + i = 1 + inRaw = 10 ** (33-(i*t)) + table[p] = inRaw + + +def convert(amount, From, To): + return amount*(table[From]/table[To]) + +_table() +_table("ban") \ No newline at end of file diff --git a/pnrw/pnrwf.py b/pnrw/pnrwf.py index a85d778..14e6cde 100644 --- a/pnrw/pnrwf.py +++ b/pnrw/pnrwf.py @@ -37,12 +37,15 @@ def _validate_ip(s): def _validate_address(s): - if s.startswith("nano_") == False and s.startswith("ban_") == False: + if s.startswith("nano_") == False and s.startswith("ban_") == False and s.startswith("xrb_") == False: raise AddressInvalid(s) else: if s.startswith("nano_"): if len(s) != 65: raise AddressInvalid(s) + if s.startswith("xrb_"): + if len(s) != 65: + raise AddressInvalid(s) elif s.startswith("ban_"): if len(s) != 64: raise AddressInvalid(s) @@ -76,6 +79,9 @@ def __init__(self, ip, port="Default", dontUseHTTPS=False, headers="Default", ba if headers == "Default": self.headers = {'Content-type': 'application/json', 'Accept': '*/*', "Accept-Encoding": "gzip, deflate, br", "Connection": "keep-alive"} + if banano: + self.headers = { + 'Content-type': 'application/json', "Connection": "keep-alive"} else: self.headers = headers @@ -270,8 +276,15 @@ def block_info(self, json_block, Hash): "subtype": response["subtype"], } - # blocks - # blocks_info + def blocks_info(self, json_block, hashes): + response = self._request( + {"action": "blocks_info", "json_block": json_block, "hashes": hashes}) + return response["blocks"] + + def blocks(self, json_block, hashes): + response = self._request( + {"action": "blocks", "json_block": json_block, "hashes": hashes}) + return response["blocks"] def bootstrap(self, address, port): response = self._request( @@ -305,7 +318,7 @@ def bootstrap_status(self): "attempts": [] } for i in response["attempts"]: - ret["attempts"].append(i) # WORK ON DATATYPE CONVERSION + ret["attempts"].append(i) return ret @@ -525,15 +538,58 @@ def version(self, account): "build_info": response["build_info"] } - # unchecked + def unchecked(self, json_block, count): + response = self._request( + {"action": "unchecked", "json_block": json_block, "count": count}) + ret = {} + for i in response["blocks"]: + ret[i] = { + "type": response["blocks"][i]["type"], + "account": response["blocks"][i]["account"], + "previous": response["blocks"][i]["previous"], + "representative": response["blocks"][i]["representative"], + "balance": int(response["blocks"][i]["balance"]), + "link": response["blocks"][i]["link"], + "link_as_account": response["blocks"][i]["link_as_account"], + "signature": response["blocks"][i]["signature"], + "work": response["blocks"][i]["work"] + } + return ret def unchecked_clear(self): response = self._request({"action": "unchecked_clear"}) return response["success"] - # unchecked_get - # unchecked_keys - # unopened + def unchecked_get(self, json_block, Hash): + response = self._request( + {"action": "unchecked_get", "json_block": json_block, "hash": Hash}) + return { + "modified_timestamp": int(response["modified_timestamp"]), + "contents": { + "type": response["contents"]["type"], + "account": response["contents"]["account"], + "previous": response["contents"]["previous"], + "representative": response["contents"]["representative"], + "balance": int(response["contents"]["balance"]), + "link": response["contents"]["link"], + "link_as_account": response["contents"]["link_as_account"], + "signature": response["contents"]["signature"], + "work": response["contents"]["work"] + } + } + + def unchecked_keys(self, json_block, key, count): + response = self._request( + {"action": "unchecked_keys", "json_block": json_block, "key": key, "count": count}) + return response["unchecked"] + + def unopened(self, account, count): + response = self._request( + {"action": "unopened", "account": account, "count": count}) + ret = {} + for i in response["accounts"]: + ret[i] = int(response["accounts"][i]) + return ret def uptime(self): response = self._request({"action": "uptime"}) @@ -543,7 +599,14 @@ def work_cancel(self, Hash): response = self._request({"action": "work_cancel", "hash": Hash}) return response - # work_generate + def work_generate(self, Hash): + response = self._request({"action": "work_generate", "hash": Hash}) + return { + "work": response["work"], + "difficulty": response["difficulty"], + "multiplier": float(response["multiplier"]), + "hash": response["hash"] + } def work_peer_add(self, address, port): response = self._request( @@ -558,7 +621,15 @@ def work_peers_clear(self): response = self._request({"action": "work_peer_add"}) return response["success"] - # work validate + def work_validate(self, work, Hash): + response = self._request( + {"action": "work_validate", "work": work, "hash": Hash}) + return { + "valid_all": int(response["valid_all"]), + "valid_receive": int(response["valid_receive"]), + "difficulty": response["difficulty"], + "multiplier": float(response["multiplier"]) + } def account_create(self, wallet): response = self._request( @@ -681,7 +752,10 @@ def wallet_destroy(self, wallet): {"action": "wallet_destroy", "wallet": wallet}) return int(response["destroyed"]) - # wallet_export + def wallet_export(self, wallet): + response = self._request( + {"action": "wallet_export", "wallet": wallet}) + return json.loads(response["json"]) def wallet_frontiers(self, wallet): response = self._request( diff --git a/setup.py b/setup.py index c46c542..313e836 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name='pnrw', - version='0.1.2', + version='0.1.4', description='Python Nanocurrency RPC Wrapper', long_description=long_description, long_description_content_type="text/markdown", @@ -25,4 +25,4 @@ "PNRW is a Python wrapper for the Nanocurrency RPC protocol" ), python_requires='>=3.6' -) \ No newline at end of file +)