Skip to content

Allow storing transaction arguments that include bytes

Sometimes, it is useful to send a parameter that has, as keys, some byte-encoded values (michelson byte type). However, these currently fail when trying to store the transaction arguments as JSON since the encoder will fail on the byte encoded keys. I'm currently patching djtezos as follows (quick and very dirty), but you might be interested in implementing a cleaner way of doing this:

 // djtezos/models.Transaction
 def save(self, *args, **kwargs):
     if (
         not self.amount
         and not self.function
         and not self.contract_micheline
         and not self.contract_address
     ):
         raise ValidationError('Requires amount, function or micheline')
 
     if self.contract_id and not self.contract_name:
         self.contract_name = self.contract.contract_name
 
     if self.contract_id and not self.contract_address:
         self.contract_address = self.contract.contract_address
 
     if self.state not in self.states:
         raise Exception('Invalid state', self.state)
 
+     if self.args:
+         try:
+             json.dumps(self.args)
+         except TypeError:
+             class BytesDump(json.JSONEncoder):
+                 def default(self, obj):
+                     if isinstance(obj, bytes):                   # deal with bytes
+                         return str(obj)
+                     return json.JSONEncoder.default(self, obj)   # everything else
+ 
+             self.args = json.dumps(self.args, cls=BytesDump)
 
     return super().save(*args, **kwargs)

Example of a failing argument with the current implementation:

>>> args = {"foo": b"bar"}
>>> json.dumps(args)
*** TypeError: Object of type bytes is not JSON serializable
Edited by Thomas Binétruy-Pic