Explorar el Código

transfer assets impl

kunickyd hace 3 años
padre
commit
c8bf26a44d
Se han modificado 1 ficheros con 67 adiciones y 3 borrados
  1. 67 3
      app.py

+ 67 - 3
app.py

@@ -1,12 +1,14 @@
-from flask import Flask, json, request, jsonify
+from flask import Flask, request, jsonify
 from json import JSONEncoder
 
 # Here are Iroha dependencies.
 # Python library generally consists of 3 parts:
 # Iroha, IrohaCrypto and IrohaGrpc which we need to import:
 import os
+import binascii
 from iroha import IrohaCrypto
 from iroha import Iroha, IrohaGrpc
+from werkzeug.wrappers import response
 
 # Here is the information about the environment and admin account information:
 IROHA_HOST_ADDR = os.getenv('IROHA_HOST_ADDR', '127.0.0.1')
@@ -23,7 +25,9 @@ net = IrohaGrpc('{}:{}'.format(IROHA_HOST_ADDR, IROHA_PORT))
 
 
 class MyEncoder(JSONEncoder):
-        def default(self, o):
+        def default(self, o):      
+            if isinstance(o, bytes):
+                return str(o, encoding='utf-8')
             return o.__dict__
 
 app = Flask(__name__)
@@ -40,6 +44,27 @@ class Asset:
 class Assets:
     assets = []
 
+class StatefulValidationError:
+    name = ""    
+    description = ""
+    solution = ""
+
+    def __init__(self, name = "", description = "", solution = ""):
+        self.name = name
+        self.description = description
+        self.solution = solution
+
+transferAssetsValidationErrors = [
+    StatefulValidationError("Could not transfer asset", "Internal error happened", "Try again or contact developers"),
+    StatefulValidationError("No such permissions", "Command's creator does not have permission to transfer asset from his account", "Grant the necessary permission"),
+    StatefulValidationError("No such source account", "Cannot find account with such id to transfer money from", "Make sure source account id is correct"),
+    StatefulValidationError("No such destination account", "Cannot find account with such id to transfer money to", "Make sure destination account id is correct"),
+    StatefulValidationError("No such asset found", "Cannot find such asset", "Make sure asset name and precision are correct"),
+    StatefulValidationError("Not enough balance", "Source account's balance is too low to perform the operation", "Add asset to account or choose lower value to subtract"),
+    StatefulValidationError("Too much asset to transfer", "Resulting asset quantity of destination account would exceed the allowed maximum", "Make sure that the final destination value is less than 2^256 / 10^asset_precision"),
+    StatefulValidationError("Too long description", "Too long description", "Ensure that description length matches the criteria above (or just shorten it)")
+]    
+
 @app.get("/accounts/<string:accountId>/assets/")
 def get_account_assets(accountId): #TODO: add validation and error handling
 
@@ -58,4 +83,43 @@ def get_account_assets(accountId): #TODO: add validation and error handling
     for asset in data:
         response.assets.append(Asset(asset.asset_id, asset.balance))
 
-    return jsonify(response)
+    return jsonify(response)
+
+@app.post("/assets/transfer/")
+def transfer_assets():
+    data = request.get_json()
+
+    if data["transfers"] and len(data["transfers"]) > 1:
+        commands = []
+
+        for transfer in data["transfers"]:
+            commands.append(
+                iroha.command('TransferAsset', src_account_id = transfer["source"], dest_account_id = transfer["destination"],
+                    asset_id = transfer["asset"], description = transfer["description"], amount = str(transfer["amount"]))
+            )
+        
+        transaction = iroha.transaction(commands)
+        hex_hash = binascii.hexlify(IrohaCrypto.hash(transaction))
+
+        IrohaCrypto.sign_transaction(transaction, ADMIN_PRIVATE_KEY)
+        net.send_tx(transaction)
+
+        #TODO speed up status reading  
+        transactionStates = []
+        for status in net.tx_status_stream(transaction):
+            transactionStates.append(status)
+
+            if(status[0] == "STATEFUL_VALIDATION_SUCCESS"):
+                break
+
+            if(status[0] == "STATEFUL_VALIDATION_FAILED"):
+                return jsonify({
+                    "transactionHash" : hex_hash,
+                    "error" : transferAssetsValidationErrors[status[2] - 1]
+                }), 400
+
+    #TODO send URL to newly created transaction in Content-Location header
+    return jsonify({ 
+        "transactionHash" : hex_hash,
+        # "transactionStates" : transactionStates
+         })