Skip to content
Snippets Groups Projects
Commit e8f24047 authored by Fabian Schuh's avatar Fabian Schuh
Browse files

[Blockchain] allow to subscribe for blocks and operations

parent 9f7b220c
No related branches found
No related tags found
No related merge requests found
from .block import Block
from . import bitshares as bts
from .utils import parse_time
class Blockchain(object):
def __init__(
self,
bitshares_instance=None,
mode="irreversible"
):
""" This class allows to access the blockchain and read data
from it
:param BitShares bitshares_instance: BitShares() instance to use when accesing a RPC
:param str mode: (default) Irreversible block
(``irreversible``) or actual head block (``head``)
"""
if not bitshares_instance:
bitshares_instance = bts.BitShares()
self.bitshares = bitshares_instance
if mode == "irreversible":
self.mode = 'last_irreversible_block_num'
elif mode == "head":
mode == "head_block_number"
else:
raise ValueError("invalid value for 'mode'!")
def info(self):
""" This call returns the *dynamic global properties*
"""
return self.bitshares.rpc.get_dynamic_global_properties()
def get_current_block_num(self):
""" This call returns the current block
"""
return self.info().get(self.mode)
def get_current_block(self):
""" This call returns the current block
"""
return Block(self.get_current_block(self.mode))
def blocks(self, **kwargs):
""" Yield Blocks as a generator
:param int start: Start at this block
:param int stop: Stop at this block
"""
return self.bitshares.rpc.block_stream(**kwargs)
def operations(self, **kwargs):
""" Yield specific operations as a generator
:param array opNames: List of operations to filter by
:param int start: Start at this block
:param int stop: Stop at this block
"""
return self.bitshares.rpc.stream(**kwargs)
import time
from datetime import datetime
def formatTime(t):
""" Properly Format Time for permlinks
"""
return datetime.utcfromtimestamp(t).strftime("%Y%m%dt%H%M%S%Z")
def formatTimeString(t):
""" Properly Format Time for permlinks
"""
return datetime.strptime(t, '%Y-%m-%dT%H:%M:%S')
def formatTimeFromNow(secs=0):
""" Properly Format Time that is `x` seconds in the future
:param int secs: Seconds to go in the future (`x>0`) or the
past (`x<0`)
:return: Properly formated time for Graphene (`%Y-%m-%dT%H:%M:%S`)
:rtype: str
"""
return datetime.utcfromtimestamp(time.time() + int(secs)).strftime('%Y-%m-%dT%H:%M:%S')
def parse_time(block_time):
"""Take a string representation of time from the blockchain, and parse it into datetime object.
"""
return datetime.strptime(block_time, '%Y-%m-%dT%H:%M:%S')
def time_diff(time1, time2):
return parse_time(time1) - parse_time(time2)
......@@ -214,7 +214,7 @@ class BitSharesNodeRPC(GrapheneWebsocketRPC):
# Sleep for one block
time.sleep(block_interval)
def stream(self, opName, *args, **kwargs):
def stream(self, opName=None, *args, **kwargs):
""" Yield specific operations (e.g. transfers) only
:param str opName: Name of the operation, e.g. transfer,
......@@ -242,8 +242,13 @@ class BitSharesNodeRPC(GrapheneWebsocketRPC):
continue
for tx in block["transactions"]:
for op in tx["operations"]:
if getOperationNameForId(op[0]) == opName:
yield op[1]
if not opName or getOperationNameForId(op[0]) == opName:
yield {
**op[1],
"type": op[0],
"timestamp": block.get("timestamp"),
# "block_num": block.get("block_num"), # not part of the block data
}
def rpcexec(self, payload):
""" Execute a call by sending the payload.
......
......@@ -24,6 +24,15 @@ from .objects import (
)
def getOperationNameForId(i):
""" Convert an operation id into the corresponding string
"""
for key in operations:
if int(operations[key]) is int(i):
return key
return "Unknown Operation ID %d" % i
class Transfer(GrapheneObject):
def __init__(self, *args, **kwargs):
if isArgsThisClass(self, args):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment