Example #1
0
def counterparty_post(payload):
    url = 'http://{}:{}/api/'.format(config.RPC_CONNECT, config.RPC_PORT)
    auth = HTTPBasicAuth(config.RPC_USER, config.RPC_PASSWORD)
    headers = {'content-type': 'application/json'}
    try:
        response = requests.post(url=url,
                                 data=json.dumps(payload),
                                 auth=auth,
                                 headers=headers)
    except (requests.exceptions.SSLError, requests.exceptions.Timeout,
            requests.exceptions.ConnectionError,
            requests.exceptions.HTTPError) as e:

        raise MessageProducerError(e)

    if response is None:
        raise MessageProducerError('Cannot communicate with {}'.format(url))
    elif response.status_code not in (200, 500):
        msg = str(
            response.status_code) + ' ' + response.reason + ' ' + response.text
        raise MessageProducerError(msg)

    response_json = response.json()
    if 'error' not in response_json.keys() or response_json['error'] == None:
        response = response_json['result']
    else:
        raise MessageProducerError(response_json['error'])

    return response
Example #2
0
def create_issuance(**kwargs):
    """
    :param kwargs:
     {
        "redisData": {
          "redisChannel": "id"
        },
        "input": {
          "method": "issuance",
          "params": {
            "source": "PhGWKbvaTdU7MMgmuktGCaVQN93Rxvye7d",
            "quantity": 10000000000,
            "asset": "TRUEBTC5",
            "description": "Some desc here"
          }
        }
    }
    :return:
    signed tx hex
    """
    required_params = ["asset", "source", "quantity", "description"]

    # STEP 1: validation
    # TODO: Improve validation
    # 1.1 check for required params
    for required_param in required_params:
        if required_param not in kwargs:
            raise MessageProducerError(
                "Following parameter `{}` is required".format(required_param))

    # 1.2 check for registered address
    ico = Ico()
    ico_info = ico.get_by_source_address(kwargs.get('source'))

    if not ico_info:
        # not registered attempt
        raise MessageProducerError(
            "Following address `{}` is not registered as ICO address".format(
                kwargs.get('source')))

    if not ico_info['is_approved']:
        raise MessageProducerError(
            "Following ICO {} on `{}` address is not approved".format(
                ico_info['asset'], kwargs.get('source')))

    # STEP 2: create_issuance in party
    payload = {
        'method': 'create_issuance',
        'params': kwargs,
        'jsonrpc': '2.0',
        'id': 0
    }
    # unsigned tx hex
    unsigned_tx_hex = counterparty_post(payload)
    # STEP 3: Sign and Send to the paicoin blockchain
    signed_tx_hex = sign_and_send(unsigned_tx_hex)
    return signed_tx_hex
Example #3
0
def send_asset(**kwargs):
    """
    :param kwargs:
     {
        "redisData": {
          "redisChannel": "id"
        },
        "input": {
          "method": "send",
          "params": {
            "source": "PhGWKbvaTdU7MMgmuktGCaVQN93Rxvye7d",
            "destination": "PhGWKbvaTdU7MMgmuktGCaVQN93Rxvye7d",
            "quantity": 10,
            "asset": "TRUEBTC5",
          }
        }
    }
    :return:
    signed tx hex
    """
    send_params = ['source', 'destination', 'asset', 'quantity']

    if not all(k in kwargs for k in send_params):
        raise MessageProducerError(
            "Following parameters {} are required".format(send_params))

    payload = {
        'method': 'create_send',
        'params': kwargs,
        'jsonrpc': '2.0',
        'id': 0
    }
    # TODO: add response validation
    unsigned_tx_hex = counterparty_post(payload)
    return sign_and_send(unsigned_tx_hex)
Example #4
0
    def get_message_body(message):
        try:
            message_data = json.loads(message)
        except ValueError:
            raise MessageProducerError(
                "Incoming message couldn't not be json parsed")

        return message_data
Example #5
0
    def _validate_incoming_message(self, message_data):

        for field_id in self.root_nodes:
            if field_id not in message_data:
                msg = "Incoming message does not contain {} field".format(
                    field_id)
                raise MessageProducerError(msg)

        if len(message_data) != len(self.root_nodes):
            msg = "Incoming message contains unspecified fields.\nIt should contain only {}".format(
                ', '.join(self.root_nodes))
            raise MessageProducerError(msg)

        if 'redisChannel' not in message_data['redisData']:
            raise MessageProducerError(
                "Incoming message redisData must contain redisChannel field")

        if 'method' not in message_data['input']:
            raise MessageProducerError(
                "Incoming message input must contain method name")
Example #6
0
    def process_message(self, message):

        self.error = False
        self.logger.info(message)

        message_body = self.get_message_body(message)
        self._validate_incoming_message(message_body)

        redis_channel = message_body['redisData']['redisChannel']
        self._status_reporting_provider.set_publish_channel(redis_channel)

        method = message_body['input']['method']
        params = message_body['input']['params']

        # TODO: Process message
        if method == 'register_ico':
            # returns source address
            source_address = register_ico(**params)
            response = {'source_address': source_address}
        elif method == 'list_ico':
            # list of all created icos
            # TODO: add minimum filter params
            list_ico = get_all_icos()
            response = {'all_ico': list_ico}
        elif method == 'get_ico_info':
            # returns info about ico
            ico_info = get_ico_info(id=params['id'])
            response = {'ico_info': ico_info}
        elif method == 'issuance':
            # do issuance
            signed_hex = create_issuance(**params)
            response = {'signed_tx_hex': signed_hex}
        elif method == 'get_unpaid_transactions':
            # returns unpaid ICO transactions
            unpaid_transactions = get_unpaid_transactions(unpaid=True)
            response = {'unpaid_transactions': unpaid_transactions}
        elif method == 'send':
            # send asset
            response = send_asset(**params)
        else:
            self.logger.error("Invalid method {}, use {} instead".format(
                method, self._allowed_methods))
            raise MessageProducerError(
                "Invalid method {}, use {} instead".format(
                    method, self._allowed_methods))

        self.publish_processing_status(100, 'Finished worker', response)
Example #7
0
def sign_and_send(unsigned_tx_hex):
    sign_payload = {
        'method': 'signrawtransaction',
        'params': [unsigned_tx_hex]
    }
    # FIXME: Update responses in paicoin
    response = paicoin_post(sign_payload)
    if response.status_code in [200, 500]:
        response_json = response.json()
        signed_hex = response_json['result']['hex']
        # STEP 3.2: send raw transaction

        send_payload = {'method': 'sendrawtransaction', 'params': [signed_hex]}

        response = paicoin_post(send_payload)
        if response.status_code in [200, 500]:
            response_json = response.json()
            tx_id = response_json['result']

            return tx_id
    else:
        raise MessageProducerError(
            'Could not communicate with paicoin rpc server')
Example #8
0
def register_ico(**kwargs):
    """
    :param message:
        {
            "redisData": {
              "redisChannel": "id"
            },
            "input": {
              "method": "register_ico",
              "params": {
                "return_address": "PiJgSZgm2z5EhBg4msPXCxL3W2DMhP9ihV",
                "quantity": 10000000,
                "asset": "TRUEBTC",
                "price": 1,
                "start_date": "2018-08-31 12:00:00",
                "end_date": "2018-08-31 12:00:00",
                "hard_cap": 1000000000,
                "soft_cap": 100000000000,
                "details": {
                    "description": "Some TRUE description"
                 }
              }
            }
        }
    :return:
    address
    (?????)
    """
    # TODO: Add more parameters
    required_params = [
        'return_address', 'asset', 'quantity', 'price', 'start_date',
        'end_date', 'hard_cap', 'soft_cap'
    ]

    # STEP 1: validation
    # TODO: Improve validation
    # check for required params
    for required_param in required_params:
        if required_param not in kwargs:
            raise MessageProducerError(
                "Following parameter `{}` is required".format(required_param))

    # STEP 2: Generate associated address for income transactions in smartnode paicoin
    address = generate_address(kwargs.get('return_address'))

    # STEP 3: Save to ICO model
    params = {
        'asset':
        kwargs.get('asset'),
        'return_address':
        kwargs.get('return_address'),
        'source_address':
        address,
        'details':
        json.dumps(kwargs.get('details')) if kwargs.get('details') else None
    }
    try:
        ico = Ico()
        ico.save_ico(**params)
    except sqlalchemy.exc.IntegrityError as e:
        raise MessageProducerError(e)

    # STEP 4: Create config
    if not os.path.exists(ICO_CONFIG_DIR):
        os.makedirs(ICO_CONFIG_DIR)

    ico_config_path = os.path.join(ICO_CONFIG_DIR, address)
    if not os.path.exists(ico_config_path):
        os.mkdir(ico_config_path)
    # config
    ico_config = {
        'required_parameters': {
            'asset':
            kwargs.get('asset'),
            'quantity':
            kwargs.get('quantity'),
            'description':
            kwargs.get('description'),
            'source_address':
            address,
            'return_address':
            kwargs.get('return_address'),
            'price':
            kwargs.get('price'),
            'start_date':
            kwargs.get('start_date'),
            'end_date':
            kwargs.get('start_date'),
            'auto_payments':
            kwargs.get('auto_payments')
            if kwargs.get('auto_payments') else True,
        },
        'optional_parameters': {
            'soft_cap': kwargs.get('soft_cap'),
            'hard_cap': kwargs.get('hard_cap'),
            'asset_long_name': kwargs.get('asset_long_name')
        },
        'additional_parameters': {
            'details': kwargs.get('details')
        }
    }
    with open(
            os.path.join(ico_config_path,
                         '{}.conf.json'.format(kwargs.get('asset'))),
            'w+') as file:
        json.dump(ico_config, file, indent=4)

    return address