Source code for dposlib.rest

# -*- coding: utf-8 -*-
# © Toons

"""
:mod:`rest` module provides network loaders and root
:class:`EndPoint` ``GET``, ``POST``, ``PUT`` and ``DELETE``. See
`Ark API documentation <https://api.ark.dev/public-rest-api/getting-started>`_
to see how to use http calls.

:mod:`rest` also creates a `core <core.html>`_ module containing
:class:`Transaction` builders, :mod:`crypto` and :mod:`api` modules.

>>> from dposlib import rest
>>> rest.use("ark")
True
>>> import dposlib
>>> dlgt = dposlib.core.api.Delegate("arky")
>>> dlgt.forged
{u'rewards': 397594.0, u'total': 401908.71166083, u'fees': 4314.71166083}
>>> dposlib.core.crypto.getKeys("secret")
{'publicKey': '03a02b9d5fdd1307c2ee4652ba54d492d1fd11a7d1bb3f3a44c4a05e79f19de\
933', 'privateKey': '2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf\
527a25b', 'wif': 'SB3BGPGRh1SRuQd52h7f5jsHUg1G9ATEvSeA7L5Bz4qySQww4k7N'}
>>> dposlib.core.transfer(1, "ARfDVWZ7Zwkox3ZXtMQQY1HYSANMB88vWE", u"\u2728 si\
mple transfer vendorField")
{
  "amount": 100000000,
  "asset": {},
  "recipientId": "ARfDVWZ7Zwkox3ZXtMQQY1HYSANMB88vWE",
  "type": 0,
  "vendorField": "\u2728 simple transfer vendorField",
  "version": 1
}
>>> dposlib.core.htlcLock(1, "ARfDVWZ7Zwkox3ZXtMQQY1HYSANMB88vWE", "my secret \
lock", expiration=12, vendorField=u"\u2728 simple htlcLock vendorField")
{
  "amount": 100000000,
  "asset": {
    "lock": {
      "secretHash": "dbaed2f2747c7aa5a834b082ccb2b648648758a98d1a415b2ed9a22fd\
29d47cb",
      "expiration": {
        "type": 1,
        "value": 82567745
      }
    }
  },
  "network": 23,
  "recipientId": "ARfDVWZ7Zwkox3ZXtMQQY1HYSANMB88vWE",
  "type": 8,
  "typeGroup": 1,
  "vendorField": "\u2728 simple htlcLock vendorField",
  "version": 2
}
"""

import sys
import random
import datetime

import pytz

from importlib import import_module
from uio import req
from dposlib import net
from dposlib.blockchain import cfg
from dposlib.util.data import filter_dic


def _call(method="GET", *args, **kwargs):
    returnKey = kwargs.pop("returnKey", False)
    response = req.EndPoint._open(
        req.EndPoint.build_req(method, *args, **kwargs)
    )
    if returnKey:
        return filter_dic(response)
    else:
        return response


GET = req.EndPoint(
    method=lambda *a, **kw: [
        setattr(req.EndPoint, "peer", random.choice(cfg.peers)),
        _call("GET", *a, **dict(kw, headers=cfg.headers))
    ][-1]
)
POST = req.EndPoint(
    method=lambda *a, **kw: [
        setattr(req.EndPoint, "peer", random.choice(cfg.peers)),
        _call("POST", *a, **dict(kw, headers=cfg.headers))
    ][-1]
)
PUT = req.EndPoint(
    method=lambda *a, **kw: [
        setattr(req.EndPoint, "peer", random.choice(cfg.peers)),
        _call("PUT", *a, **dict(kw, headers=cfg.headers))
    ][-1]
)
DELETE = req.EndPoint(
    method=lambda *a, **kw: [
        setattr(req.EndPoint, "peer", random.choice(cfg.peers)),
        _call("DELETE", *a, **dict(kw, headers=cfg.headers))
    ][-1]
)


[docs]def load(name): """ Load a given blockchain package as ``dposlib.core`` module. A valid blockchain package must provide :func:`init(peer=None)` and :func:`stop()` definitions. Available blockchains are referenced in :mod:`dposli.net` module. Args: name (:class:`str`): package name to load """ if hasattr(sys.modules[__package__], "core"): try: sys.modules[__package__].core.stop() except Exception as e: sys.stdout.write("%r\n" % e) del sys.modules[__package__].core # initialize blockchain familly package try: sys.modules[__package__].core = import_module( 'dposlib.{0}'.format(name) ) except ImportError as e: raise Exception("%s package not found\n%r" % (name, e)) else: # delete real package name loaded to keep namespace clear try: sys.modules[__package__].__delattr__(name) except AttributeError: pass try: sys.modules[__package__].core.init() except Exception as e: raise Exception("package initialization error\n%r" % e)
[docs]def use(network, **kwargs): """ Sets the blockchain parameters in the ``cfg`` module and initialize blockchain package. Network options can be created or overriden using ``**kwargs`` argument. Args: network (:class:`str`): network to initialize Returns: :class:`bool`: True if network connection established """ # clear data in cfg module [cfg.__dict__.pop(k) for k in list(cfg.__dict__) if not k.startswith("_")] # initialize minimum values cfg.begintime = datetime.datetime(1970, 1, 1, tzinfo=pytz.UTC) cfg.headers = {"Content-Type": "application/json"} cfg.broadcast = 10 # maximum peer to use cfg.timeout = 5 # global timeout used within requests calls cfg.hotmode = False # offline mode set cfg.network = network # network name set cfg.peers = [] # peer list cfg.txversion = 1 # load network.net configuration data = dict(getattr(net, network)) # override some options if given data.update(**kwargs) # connect with first available seed for seed in data.pop("seeds", []): if req.connect(seed): cfg.peers.append(seed) cfg.hotmode = True break # update information on cfg module cfg.__dict__.update(data) load(cfg.familly) return cfg.hotmode