remote.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2026 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. proto.rune.rpc.remote: THORChain base protocol remote RPC client for the MMGen Project
  12. """
  13. import json
  14. from ....http import HTTPClient
  15. from ....rpc.remote import RemoteRPCClient
  16. # throws exception on error:
  17. def process_response(json_response, errmsg):
  18. data = json.loads(json_response)
  19. if data['result'] is None:
  20. from ....util import die
  21. die('RPCFailure', errmsg)
  22. return data['result']
  23. # HTTP POST, JSON-RPC response:
  24. class ThornodeRemoteRPCClient(HTTPClient):
  25. timeout = 30
  26. def __init__(self, cfg, proto, *, network_proto=None, host=None):
  27. for k, v in proto.rpc_remote_rpc_params.items():
  28. setattr(self, k, v)
  29. super().__init__(cfg, network_proto=network_proto, host=host)
  30. # HTTP GET, params in query string, JSON-RPC response:
  31. class ThornodeRemoteRESTClient(HTTPClient):
  32. http_hdrs = {'Content-Type': 'application/json'}
  33. timeout = 5
  34. def __init__(self, cfg, proto, *, network_proto=None, host=None):
  35. for k, v in proto.rpc_remote_rest_params.items():
  36. setattr(self, k, v)
  37. super().__init__(cfg, network_proto=network_proto, host=host)
  38. class THORChainRemoteRPCClient(RemoteRPCClient):
  39. server_proto = 'THORChain'
  40. def __init__(self, cfg, proto):
  41. for k, v in proto.rpc_remote_params.items():
  42. setattr(self, k, v)
  43. super().__init__(cfg, proto)
  44. self.caps = ('lbl_id',)
  45. self.rest_api = ThornodeRemoteRESTClient(cfg, proto)
  46. self.rpc_api = ThornodeRemoteRPCClient(cfg, proto)
  47. def get_balance(self, addr, *, block=None):
  48. res = process_response(
  49. self.rest_api.get(path=f'/bank/balances/{addr}'),
  50. errmsg = f'address ‘{addr}’ not found in blockchain')
  51. rune_res = [d for d in res if d['denom'] == 'rune']
  52. assert len(rune_res) == 1, f'{rune_res}: result length is not one!'
  53. return self.proto.coin_amt(int(rune_res[0]['amount']), from_unit='satoshi')
  54. def get_account_info(self, addr, *, block=None):
  55. return process_response(
  56. self.rest_api.get(path=f'/auth/accounts/{addr}'),
  57. errmsg = f'address ‘{addr}’ not found in blockchain')['value']
  58. def get_tx_info(self, txid):
  59. return process_response(
  60. self.rpc_api.post(
  61. path = '/tx',
  62. data = {'hash': '0x' + txid}),
  63. errmsg = f'get info for transaction {txid} failed')
  64. def tx_op(self, txhex, op=None):
  65. assert isinstance(txhex, str)
  66. assert op in ('check_tx', 'broadcast_tx_sync', 'broadcast_tx_async')
  67. return process_response(
  68. self.rpc_api.post(
  69. path = '/' + op,
  70. data = {'tx': '0x' + txhex}),
  71. errmsg = f'transaction operation ‘{op}’ failed')