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

[bitshares] propose and bundle transaction

parent b2252da1
No related branches found
No related tags found
No related merge requests found
......@@ -33,8 +33,11 @@ class BitShares(object):
:param str rpcpassword: RPC password *(optional)*
:param bool nobroadcast: Do **not** broadcast a transaction! *(optional)*
:param bool debug: Enable Debugging *(optional)*
:param array,dict,string keys: Predefine the wif keys to shortcut the wallet database
:param bool offline: Boolean to prevent connecting to network (defaults to ``False``)
:param array,dict,string keys: Predefine the wif keys to shortcut the wallet database *(optional)*
:param bool offline: Boolean to prevent connecting to network (defaults to ``False``) *(optional)*
:param str proposer: Propose a transaction using this proposer *(optional)*
:param int expiration: Delay in seconds until transactions are supposed to expire *(optional)*
:param bool bundle: Do not broadcast transactions right away, but allow to bundle operations *(optional)*
Three wallet operation modes are possible:
......@@ -106,11 +109,12 @@ class BitShares(object):
self.rpc = None
self.debug = debug
self.offline = kwargs.get("offline", False)
self.nobroadcast = kwargs.get("nobroadcast", False)
self.unsigned = kwargs.get("unsigned", False)
self.offline = bool(kwargs.get("offline", False))
self.nobroadcast = bool(kwargs.get("nobroadcast", False))
self.unsigned = bool(kwargs.get("unsigned", False))
self.expiration = int(kwargs.get("expiration", 30))
self.proposer = kwargs.get("proposer", None)
self.bundle = bool(kwargs.get("bundle", False))
if not self.offline:
self._connect(node=node,
......@@ -119,6 +123,7 @@ class BitShares(object):
**kwargs)
self.wallet = Wallet(self.rpc, **kwargs)
self.txbuffer = TransactionBuilder(bitshares_instance=self)
def _connect(self,
node="",
......@@ -169,19 +174,23 @@ class BitShares(object):
posting permission. Neither can you use different
accounts for different operations!
"""
tx = TransactionBuilder(bitshares_instance=self)
tx.appendOps(ops)
# Append transaction
self.txbuffer.appendOps(ops)
if self.unsigned:
tx.addSigningInformation(account, permission)
return tx
# In case we don't want to sign anything
self.txbuffer.addSigningInformation(account, permission)
return self.txbuffer
elif self.bundle:
# In case we want to add more ops to the tx (bundle)
self.txbuffer.appendSigner(account, permission)
else:
tx.appendSigner(account, permission)
tx.sign()
# default behavior: sign + broadcast
self.txbuffer.appendSigner(account, permission)
self.txbuffer.sign()
return self.txbuffer.broadcast()
return tx.broadcast()
def sign(self, tx, wifs=[]):
def sign(self, tx=None, wifs=[]):
""" Sign a provided transaction witht he provided key(s)
:param dict tx: The transaction to be signed and returned
......@@ -190,18 +199,25 @@ class BitShares(object):
from the wallet as defined in "missing_signatures" key
of the transactions.
"""
tx = TransactionBuilder(tx, bitshares_instance=self)
tx.appendMissingSignatures(wifs)
tx.sign()
return tx.json()
if tx:
txbuffer = TransactionBuilder(tx, bitshares_instance=self)
else:
txbuffer = self.txbuffer
txbuffer.appendWif(wifs)
txbuffer.appendMissingSignatures()
txbuffer.sign()
return txbuffer.json()
def broadcast(self, tx):
def broadcast(self, tx=None):
""" Broadcast a transaction to the BitShares network
:param tx tx: Signed transaction to broadcast
"""
tx = TransactionBuilder(tx)
return tx.broadcast()
if tx:
# If tx is provided, we broadcast the tx
return TransactionBuilder(tx).broadcast()
else:
return self.txbuffer.broadcast()
def info(self):
""" Returns the global properties
......
......@@ -31,10 +31,9 @@ class TransactionBuilder(dict):
:param list ops: One or a list of operations
"""
if isinstance(ops, list):
for op in ops:
self.op.append(op)
self.ops.extend(ops)
else:
self.op.append(ops)
self.ops.append(ops)
def appendSigner(self, account, permission):
""" Try to obtain the wif key from the wallet by telling which account
......@@ -66,7 +65,7 @@ class TransactionBuilder(dict):
def appendWif(self, wif):
""" Add a wif that should be used for signing of the transaction.
"""
"""
if wif:
try:
PrivateKey(wif)
......@@ -79,7 +78,7 @@ class TransactionBuilder(dict):
store
"""
if self.bitshares.proposer:
ops = [operations.Op_wrapper(op=o) for o in list(self.op)]
ops = [operations.Op_wrapper(op=o) for o in list(self.ops)]
proposer = Account(
self.bitshares.proposer,
bitshares_instance=self.bitshares
......@@ -94,7 +93,7 @@ class TransactionBuilder(dict):
})
ops = [Operation(ops)]
else:
ops = [Operation(o) for o in list(self.op)]
ops = [Operation(o) for o in list(self.ops)]
ops = transactions.addRequiredFees(self.bitshares.rpc, ops)
expiration = transactions.formatTimeFromNow(self.bitshares.expiration)
......@@ -170,13 +169,16 @@ class TransactionBuilder(dict):
except Exception as e:
raise e
self.clear()
return self
def clear(self):
""" Clear the transaction builder and start from scratch
"""
self.op = []
self.ops = []
self.wifs = []
super(TransactionBuilder, self).__init__({})
def addSigningInformation(self, account, permission):
""" This is a private method that adds side information to a
......@@ -214,7 +216,7 @@ class TransactionBuilder(dict):
"""
return dict(self)
def appendMissingSignatures(self, wifs=[]):
def appendMissingSignatures(self):
""" Store which accounts/keys are supposed to sign the transaction
This method is used for an offline-signer!
......
*********
Tutorials
*********
Bundle Many Operations
----------------------
With BitShares, you can bundle multiple operations into a single
transactions. This can be used to do a multi-send (one sender, multiple
receivers), but it also allows to use any other kind of operation. The
advantage here is that the user can be sure that the operations are
executed in the same order as they are added to the transaction.
.. code-block:: python
from pprint import pprint
from bitshares import BitShares
testnet = BitShares(
"wss://node.testnet.bitshares.eu",
nobroadcast=True,
bundle=True,
)
testnet.wallet.unlock("supersecret")
testnet.transfer("init0", 1, "TEST", account="xeroc")
testnet.transfer("init1", 1, "TEST", account="xeroc")
testnet.transfer("init2", 1, "TEST", account="xeroc")
testnet.transfer("init3", 1, "TEST", account="xeroc")
pprint(testnet.broadcast())
Proposing a Transaction
-----------------------
In BitShares, you can propose a transactions to any account. This is
used to facilitate on-chain multisig transactions. With
python-bitshares, you can do this simply by using the ``proposer``
attribute:
.. code-block:: python
from pprint import pprint
from bitshares import BitShares
testnet = BitShares(
"wss://node.testnet.bitshares.eu",
proposer="xeroc"
)
testnet.wallet.unlock("supersecret")
pprint(testnet.transfer("init0", 1, "TEST", account="xeroc"))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment