Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

_blockchain.py 7.2KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. ###############################################################################
  2. #
  3. # The MIT License (MIT)
  4. #
  5. # Copyright (c) typedef int GmbH
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy
  8. # of this software and associated documentation files (the "Software"), to deal
  9. # in the Software without restriction, including without limitation the rights
  10. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. # copies of the Software, and to permit persons to whom the Software is
  12. # furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included in
  15. # all copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. # THE SOFTWARE.
  24. #
  25. ###############################################################################
  26. import web3
  27. import txaio
  28. from autobahn import xbr
  29. class SimpleBlockchain(object):
  30. """
  31. Simple Ethereum blockchain XBR client.
  32. """
  33. DomainStatus_NULL = 0
  34. DomainStatus_ACTIVE = 1
  35. DomainStatus_CLOSED = 2
  36. NodeType_NULL = 0
  37. NodeType_MASTER = 1
  38. NodeType_CORE = 2
  39. NodeType_EDGE = 3
  40. NodeLicense_NULL = 0
  41. NodeLicense_INFINITE = 1
  42. NodeLicense_FREE = 2
  43. log = None
  44. backgroundCaller = None
  45. def __init__(self, gateway=None):
  46. """
  47. :param gateway: Optional explicit Ethereum gateway URL to use.
  48. If no explicit gateway is specified, let web3 auto-choose.
  49. :type gateway: str
  50. """
  51. self.log = txaio.make_logger()
  52. self._gateway = gateway
  53. self._w3 = None
  54. assert self.backgroundCaller is not None
  55. def start(self):
  56. """
  57. Start the blockchain client using the configured blockchain gateway.
  58. """
  59. assert self._w3 is None
  60. if self._gateway:
  61. w3 = web3.Web3(web3.Web3.HTTPProvider(self._gateway))
  62. else:
  63. # using automatic provider detection:
  64. from web3.auto import w3
  65. # check we are connected, and check network ID
  66. if not w3.isConnected():
  67. emsg = 'could not connect to Web3/Ethereum at: {}'.format(self._gateway or 'auto')
  68. self.log.warn(emsg)
  69. raise RuntimeError(emsg)
  70. else:
  71. print('connected to network {} at provider "{}"'.format(w3.version.network,
  72. self._gateway or 'auto'))
  73. self._w3 = w3
  74. # set new provider on XBR library
  75. xbr.setProvider(self._w3)
  76. def stop(self):
  77. """
  78. Stop the blockchain client.
  79. """
  80. assert self._w3 is not None
  81. self._w3 = None
  82. async def get_market_status(self, market_id):
  83. """
  84. :param market_id:
  85. :return:
  86. """
  87. def _get_market_status(_market_id):
  88. owner = xbr.xbrnetwork.functions.getMarketOwner(_market_id).call()
  89. if not owner or owner == '0x0000000000000000000000000000000000000000':
  90. return None
  91. else:
  92. return {
  93. 'owner': owner,
  94. }
  95. return self.backgroundCaller(_get_market_status, market_id)
  96. async def get_domain_status(self, domain_id):
  97. """
  98. :param domain_id:
  99. :type domain_id: bytes
  100. :return:
  101. :rtype: dict
  102. """
  103. def _get_domain_status(_domain_id):
  104. status = xbr.xbrnetwork.functions.getDomainStatus(_domain_id).call()
  105. if status == SimpleBlockchain.DomainStatus_NULL:
  106. return None
  107. elif status == SimpleBlockchain.DomainStatus_ACTIVE:
  108. return {'status': 'ACTIVE'}
  109. elif status == SimpleBlockchain.DomainStatus_CLOSED:
  110. return {'status': 'CLOSED'}
  111. return self.backgroundCaller(_get_domain_status, domain_id)
  112. def get_node_status(self, delegate_adr):
  113. """
  114. :param delegate_adr:
  115. :type delegate_adr: bytes
  116. :return:
  117. :rtype: dict
  118. """
  119. raise NotImplementedError()
  120. def get_actor_status(self, delegate_adr):
  121. """
  122. :param delegate_adr:
  123. :type delegate_adr: bytes
  124. :return:
  125. :rtype: dict
  126. """
  127. raise NotImplementedError()
  128. def get_delegate_status(self, delegate_adr):
  129. """
  130. :param delegate_adr:
  131. :type delegate_adr: bytes
  132. :return:
  133. :rtype: dict
  134. """
  135. raise NotImplementedError()
  136. def get_channel_status(self, channel_adr):
  137. """
  138. :param channel_adr:
  139. :type channel_adr: bytes
  140. :return:
  141. :rtype: dict
  142. """
  143. raise NotImplementedError()
  144. async def get_member_status(self, member_adr):
  145. """
  146. :param member_adr:
  147. :type member_adr: bytes
  148. :return:
  149. :rtype: dict
  150. """
  151. assert type(member_adr) == bytes and len(member_adr) == 20
  152. def _get_member_status(_member_adr):
  153. level = xbr.xbrnetwork.functions.getMemberLevel(member_adr).call()
  154. if not level:
  155. return None
  156. else:
  157. eula = xbr.xbrnetwork.functions.getMemberEula(member_adr).call()
  158. if not eula or eula.strip() == '':
  159. return None
  160. profile = xbr.xbrnetwork.functions.getMemberProfile(member_adr).call()
  161. if not profile or profile.strip() == '':
  162. profile = None
  163. return {
  164. 'eula': eula,
  165. 'profile': profile,
  166. }
  167. return self.backgroundCaller(_get_member_status, member_adr)
  168. async def get_balances(self, account_adr):
  169. """
  170. Return current ETH and XBR balances of account with given address.
  171. :param account_adr: Ethereum address of account to get balances for.
  172. :type account_adr: bytes
  173. :return: A dictionary with ``"ETH"`` and ``"XBR"`` keys and respective
  174. current on-chain balances as values.
  175. :rtype: dict
  176. """
  177. assert type(account_adr) == bytes and len(account_adr) == 20
  178. def _get_balances(_adr):
  179. balance_eth = self._w3.eth.getBalance(_adr)
  180. balance_xbr = xbr.xbrtoken.functions.balanceOf(_adr).call()
  181. return {
  182. 'ETH': balance_eth,
  183. 'XBR': balance_xbr,
  184. }
  185. return self.backgroundCaller(_get_balances, account_adr)
  186. def get_contract_adrs(self):
  187. """
  188. Get XBR smart contract addresses.
  189. :return: A dictionary with ``"XBRToken"`` and ``"XBRNetwork"`` keys and Ethereum
  190. contract addresses as values.
  191. :rtype: dict
  192. """
  193. return {
  194. 'XBRToken': xbr.xbrtoken.address,
  195. 'XBRNetwork': xbr.xbrnetwork.address,
  196. }