Esempio n. 1
0
def receipt_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        dragonnet.process_receipt_v1(content)
    except NotImplementedError as e:
        raise exceptions.BadRequest(str(e))
    return helpers.flask_http_response(200, helpers.format_success(True))
Esempio n. 2
0
def query_transactions_v1(params: Dict[str, Any],
                          parse: bool = True) -> "RSearch":
    """invoke queries on redisearch indexes
    Args:
        params: Dictionary of redisearch query options
        parse: If true, parse the transaction payload before returning
    Returns:
        {"results": [], "total": total} storage objects matching search query
    """
    if not params.get("transaction_type"):
        raise exceptions.ValidationException(
            "transaction_type must be supplied for transaction queries")
    try:
        query_result = redisearch.search(
            index=params["transaction_type"],
            query_str=params["q"],
            only_id=params.get("id_only"),
            verbatim=params.get("verbatim"),
            offset=params.get("offset"),
            limit=params.get("limit"),
            sort_by=params.get("sort_by"),
            sort_asc=params.get("sort_asc"),
        )
    except redis.exceptions.ResponseError as e:
        error_str = str(e)
        # Detect if this is a syntax error; if so, throw it back as a 400 with the message
        if error_str.startswith("Syntax error"):
            raise exceptions.BadRequest(error_str)
        # If unknown index, user provided a bad transaction type
        elif error_str == "Unknown Index name":
            raise exceptions.BadRequest("Invalid transaction type")
        else:
            raise
    result: "RSearch" = {"total": query_result.total, "results": []}
    if params.get("id_only"):
        result["results"] = [x.id for x in query_result.docs]
    else:
        transactions = []
        for doc in query_result.docs:
            block_id = doc.block_id
            transaction_id = doc.id
            retrieved_txn = storage.select_transaction(block_id,
                                                       transaction_id)
            if parse:
                retrieved_txn["payload"] = json.loads(retrieved_txn["payload"])
            transactions.append(retrieved_txn)
        result["results"] = transactions
    return result
Esempio n. 3
0
def query_blocks_v1(params: Dict[str, Any], parse: bool = False) -> "RSearch":
    """Returns block matching block id, with query parameters accepted.
    Args:
        block_id: string Block id to search for.
        params: Dictionary of redisearch query options
        parse: whether or not we should parse contents
    """
    try:
        query_result = redisearch.search(
            index=redisearch.Indexes.block.value,
            query_str=params["q"],
            only_id=params.get("id_only"),
            offset=params.get("offset"),
            limit=params.get("limit"),
            sort_by=params.get("sort_by"),
            sort_asc=params.get("sort_asc"),
        )
    except redis.exceptions.ResponseError as e:
        # Detect if this is a syntax error; if so, throw it back as a 400 with the message
        if str(e).startswith("Syntax error"):
            raise exceptions.BadRequest(str(e))
        else:
            raise
    result: "RSearch" = {"total": query_result.total, "results": []}
    if params.get("id_only"):
        result["results"] = [x.id for x in query_result.docs]
    else:
        blocks = []
        for block in query_result.docs:
            blocks.append(get_block_by_id_v1(block.id, parse))
        result["results"] = blocks
    return result
Esempio n. 4
0
 def sign_transaction(self, raw_transaction: Dict[str, Any]) -> str:
     """Sign a transaction for this network
     Args:
         raw_transaction: The dictionary of the raw transaction containing:
             to: hex string of the to address
             value: The amount of eth (in wei) to send (in hex string)
             data: Optional hex string for arbitrary data
             nonce: Optional field for nonce (will automatically determine if not provided)
             gasPrice: Optional field to set gasPrice of the transaction (as a hex string in wei)
             gas: Optional gas limit for this transaction (as a hex string). Defaults to 60000
     Returns:
         String of the signed transaction as hex
     """
     raw_transaction["from"] = self.address
     raw_transaction["chainId"] = self.chain_id
     if not raw_transaction.get("nonce"):
         raw_transaction["nonce"] = self.w3.toHex(
             self.w3.eth.getTransactionCount(self.address))
     if not raw_transaction.get("gasPrice"):
         raw_transaction["gasPrice"] = self.w3.toHex(
             self._calculate_transaction_fee())
     if not raw_transaction.get("gas"):
         # TODO proper gas limit estimation
         raw_transaction["gas"] = self.w3.toHex(STANDARD_GAS_LIMIT)
     try:
         _log.info(f"[ETHEREUM] Signing raw transaction: {raw_transaction}")
         return self.w3.eth.account.sign_transaction(
             raw_transaction, self.priv_key).rawTransaction.hex()
     except Exception as e:
         raise exceptions.BadRequest(f"Error signing transaction: {e}")
Esempio n. 5
0
def get_transaction_v1(transaction_id: str) -> Tuple[str, int, Dict[str, str]]:
    if not transaction_id:
        raise exceptions.BadRequest("Paramterer 'transaction_id' is required'")

    should_parse = flask.request.headers.get("Parse-Payload") != "false"
    return helpers.flask_http_response(
        200, transactions.get_transaction_v1(transaction_id, should_parse))
Esempio n. 6
0
    def _build_transaction_msg(self, raw_transaction: Dict[str, Any]) -> Dict:
        """Build a formatted transaction for this network from the base parameters
        Args:
            amount (int): amount of token in transaction
            to_address (str): hex of the address to send to
            symbol (str, optional): the exchange symbol for the token (defaults to 'BNB')
            memo (str, optional): string of data to publish in the transaction (defaults to '')
        Returns:
            dict of the constructed transaction
        """
        amount = raw_transaction["amount"]
        if amount <= 0:
            raise exceptions.BadRequest("[BINANCE] Amount in transaction cannot be less than or equal to 0.")

        symbol = raw_transaction.get("symbol") or "BNB"
        memo = raw_transaction.get("memo") or ""

        inputs = {"address": self.address, "coins": [{"amount": amount, "denom": symbol}]}
        outputs = {"address": raw_transaction["to_address"], "coins": [{"amount": amount, "denom": symbol}]}
        response = self._fetch_account()
        transaction_data = {
            "account_number": response["account_number"],
            "sequence": response["sequence"],
            "from": self.address,
            "msgs": [{"type": "cosmos-sdk/Send", "inputs": [inputs], "outputs": [outputs]}],
            "memo": memo,
        }
        return transaction_data
Esempio n. 7
0
def public_blockchain_transaction_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    data = flask.request.json

    if not data.get("network"):
        raise exceptions.ValidationException("Invalid parameter: network")
    try:
        if data["network"] in ["BTC_MAINNET", "BTC_TESTNET3"]:
            _validate_bitcoin_transaction_v1(data.get("transaction"))
        elif data["network"] in [
                "ETH_MAINNET", "ETH_ROPSTEN", "ETC_MAINNET", "ETC_MORDEN"
        ]:
            _validate_ethereum_transaction_v1(data.get("transaction"))
        else:
            raise exceptions.ValidationException(
                "User input did not match JSON schema")
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    return helpers.flask_http_response(
        200,
        interchain.legacy_sign_blockchain_transaction_v1(
            data["network"], data["transaction"]))
Esempio n. 8
0
 def sign_transaction(self, raw_transaction: Dict[str, Any]) -> str:
     """Sign a transaction for this network
     Args:
         amount (int): amount of token in transaction
         to_address (str): hex of the address to send to
         symbol (str, optional): the exchange symbol for the token (defaults to 'BNB')
         memo (str, optional): string of data to publish in the transaction (defaults to '')
     Returns:
         String of the signed transaction as base64
     """
     built_transaction = self._build_transaction_msg(raw_transaction)
     try:
         if self.testnet:
             tx = TestBnbTransaction.from_obj(built_transaction)
         else:  # mainnet
             tx = BnbTransaction.from_obj(built_transaction)
         _log.info(
             f"[BINANCE] Signing raw transaction: {tx.signing_json()}")
         mykeys = keys.DCKeys(pull_keys=False)
         mykeys.initialize(private_key_string=self.b64_private_key)
         signature = base64.b64decode(
             mykeys.make_binance_signature(content=tx.signing_json()))
         tx.apply_sig(signature, self.pub.serialize(compressed=True))
         signed_transaction_bytes = tx.encode()
         # signed_transaction expected to be base64, not hex:
         return base64.b64encode(signed_transaction_bytes).decode("ascii")
     except Exception as e:
         raise exceptions.BadRequest(
             f"[BINANCE] Error signing transaction: {e}")
Esempio n. 9
0
def create_binance_interchain_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_binance_network_create_v1(data)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        201, interchain.create_binance_interchain_v1(data))
Esempio n. 10
0
def get_smart_contract_logs_v1(
        contract_id: str) -> Tuple[str, int, Dict[str, str]]:
    since = flask.request.args.get("since")
    tail = cast(Any, flask.request.args.get("tail"))
    try:
        tail = int(tail)
    except Exception:
        raise exceptions.BadRequest("Invalid parameter for tail")

    return helpers.flask_http_response(
        200, smart_contracts.get_logs_v1(contract_id, since, tail))
Esempio n. 11
0
def update_bitcoin_interchain_v1(name: str) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_bitcoin_network_update_v1(data)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        200, interchain.update_bitcoin_interchain_v1(name, data))
Esempio n. 12
0
def set_default_network_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_set_default_interchain_v1(data)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        200,
        interchain.set_default_interchain_v1(data["blockchain"], data["name"]))
Esempio n. 13
0
def update_contract_v1(contract_id: str) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    update = flask.request.json

    try:
        _validate_sc_update_v1(update)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException("User input did not match JSON schema")

    return helpers.flask_http_response(202, smart_contracts.update_contract_v1(contract_id, update))
Esempio n. 14
0
def create_binance_transaction_v1(name: str,
                                  **kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_binance_transaction_v1(data)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        200, interchain.sign_interchain_transaction_v1("binance", name, data))
Esempio n. 15
0
def create_ethereum_interchain_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_ethereum_network_create_v1(data)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    return helpers.flask_http_response(
        201, interchain.create_ethereum_interchain_v1(data))
Esempio n. 16
0
def create_bitcoin_transaction_v1(
        name: str) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")
    data = flask.request.json
    try:
        _validate_bitcoin_transaction_v1(data)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    return helpers.flask_http_response(
        200, interchain.sign_interchain_transaction_v1("bitcoin", name, data))
Esempio n. 17
0
def register_transaction_type_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        _validate_create_txn_type_v1(content)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException("User input did not match JSON schema")

    transaction_types.register_transaction_type_v1(content)
    return helpers.flask_http_response(200, helpers.format_success(True))
def post_contract_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    contract = flask.request.json

    try:
        _validate_sc_create_v1(contract)
        if contract.get("custom_indexes"):
            helpers.verify_custom_indexes_options(contract.get("custom_indexes"))
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException("User input did not match JSON schema")

    return helpers.flask_http_response(202, smart_contracts.create_contract_v1(contract))
Esempio n. 19
0
def post_transaction_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    txn = flask.request.json

    try:
        _validate_txn_create_v1(txn)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        201, transactions.submit_transaction_v1(txn, flask.request.headers.get("X-Callback-URL"), api_key=kwargs["used_auth_key"])
    )
Esempio n. 20
0
def enqueue_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json
    deadline = int(cast(str, flask.request.headers.get(
        "deadline"))) if flask.request.headers.get("deadline") else 30

    try:
        _validate_broadcast_schema_v1(content)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    dragonnet.enqueue_item_for_verification_v1(content, deadline)
    return helpers.flask_http_response(200, helpers.format_success(True))
def register_transaction_type_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        _validate_create_txn_type_v1(content)
        if content.get("custom_indexes"):
            helpers.verify_custom_indexes_options(content["custom_indexes"])
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    transaction_types.register_transaction_type_v1(content)
    return helpers.flask_http_response(200, helpers.format_success(True))
Esempio n. 22
0
def dragonnet_auth_v1() -> Tuple[str, int, Dict[str, str]]:
    """
    Create a new DragonNet interchain communication key pair with the requester (unauthenticated by design)
    """
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    body = flask.request.json

    try:
        _validate_interchain_auth_v1(body)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    dragonnet.register_interchain_auth_v1(body)
    return helpers.flask_http_response(201, helpers.format_success(True))
Esempio n. 23
0
def update_api_key_v1(key_id: str) -> Tuple[str, int, Dict[str, str]]:
    if not key_id:
        raise exceptions.ValidationException("Invalid parameter: key_id")

    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    body = flask.request.json

    try:
        _validate_api_key_update_v1(body)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    api_keys.update_api_key_v1(key_id, body["nickname"])
    return helpers.flask_http_response(200, helpers.format_success(True))
Esempio n. 24
0
def update_transaction_type_v1(txn_type: str) -> Tuple[str, int, Dict[str, str]]:
    if not txn_type:
        raise exceptions.ValidationException("Invalid parameter: txn_type")

    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        _validate_update_txn_type_v1(content)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException("User input did not match JSON schema")

    transaction_types.update_transaction_type_v1(txn_type, content["custom_indexes"])
    return helpers.flask_http_response(200, helpers.format_success(True))
Esempio n. 25
0
def post_transaction_v1() -> Tuple[str, int, Dict[str, str]]:
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    txn = flask.request.json

    try:
        _validate_txn_create_v1(txn)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    return helpers.flask_http_response(
        201,
        transactions.submit_transaction_v1(
            txn, flask.request.headers.get("X-Callback-URL")))
Esempio n. 26
0
def get_sc_heap_v1(key: str) -> Tuple[str, int]:
    """
    /v1/get/<contract_id>/HEAP/<key>
    method = GET
    path = '/' seperate string where the left side is the contract_id
            and the right side is the object key in the heap
    Get a value from the smart contract heap in storage
    """
    initial_index = key.find("/")
    if initial_index == -1:
        raise exceptions.BadRequest("Path must look like /v1/get/<contract_id>/<object_key>")
    contract_id = key[:initial_index]
    path = key[initial_index:]
    return (
        smart_contracts.heap_get_v1(contract_id, path),
        200,
    )  # Explicitly not using helpers.flask_http_response, because response isn't necessarily JSON
Esempio n. 27
0
 def _fetch_account(self):
     """Fetch the account metadata for an address
     Returns:
         response containing account metadata
     """
     _log.info(f"[BINANCE] Fetching address metadata for {self.address}")
     path = f"account/{self.address}"  # params expected inside path string
     try:
         response = self._call_node_api(path)
         if response.status_code == 404:
             _log.warning("[BINANCE] 404 response from Binance node:")
             _log.warning("[BINANCE] Address not found -- likely has zero funds.")
             raise exceptions.BadRequest("[BINANCE] Error fetching metadata from 'account' endpoint.")
         return response.json()
     except exceptions.InterchainConnectionError:
         _log.warning("[BINANCE] Non 200 response from Binance node.")
         _log.warning("[BINANCE] May have been a 500 Bad Request or a 404 Not Found.")
         raise exceptions.InterchainConnectionError("[BINANCE] Error fetching metadata from 'account' endpoint.")
Esempio n. 28
0
def post_transaction_bulk_v1(**kwargs) -> Tuple[str, int, Dict[str, str]]:
    """
    Enqueue bulk transactions to be processed
    """
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        _validate_bulk_txn_create_v1(content)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    response = transactions.submit_bulk_transaction_v1(content, api_key=kwargs["used_auth_key"])
    if not response["201"]:
        return helpers.flask_http_response(400, response)
    return helpers.flask_http_response(207, response)
Esempio n. 29
0
def post_transaction_bulk_v1() -> Tuple[str, int, Dict[str, str]]:
    """
    Enqueue bulk transactions to be processed
    """
    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    content = flask.request.json

    try:
        _validate_bulk_txn_create_v1(content)
    except fastjsonschema.JsonSchemaException:
        raise exceptions.ValidationException(
            "User input did not match JSON schema")

    response = transactions.submit_bulk_transaction_v1(content)
    if not response["201"]:
        return helpers.flask_http_response(400, response)
    return helpers.flask_http_response(207, response)
Esempio n. 30
0
def update_api_key_v1(key_id: str,
                      **kwargs) -> Tuple[str, int, Dict[str, str]]:
    if not key_id:
        raise exceptions.ValidationException("Invalid parameter: key_id")

    if not flask.request.is_json:
        raise exceptions.BadRequest("Could not parse JSON")

    body = flask.request.json

    try:
        _validate_api_key_update_v1(body)
    except fastjsonschema.JsonSchemaException as e:
        raise exceptions.ValidationException(str(e))

    return helpers.flask_http_response(
        200,
        api_keys.update_api_key_v1(key_id, body.get("nickname"),
                                   body.get("permissions_document")))