コード例 #1
0
    def __init__(self):
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'nrve-niche-config.json'), 'r') as f:
            config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'network-wallets.json'), 'r') as f:
            network_wallets_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'db-config.json'), 'r') as f:
            self.db_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'smtp-config.json'), 'r') as f:
            self.smtp_config = json.load(f)

        super().__init__(NetworkType[config['network']],
                         'nrve-niche-payment-handler')

        self.smart_contract = SmartContract(config['smart_contract'])
        self.niche_payment_address = config['niche_payment_address']
        self.niche_payment_storage_address = config[
            'niche_payment_storage_address']

        self.setup_wallet(
            network_wallets_config[config['network']]['wallet_path'])

        # decorate the event handler methods dynamically now that we have loaded the SC
        self.sc_notify = self.smart_contract.on_notify(self.sc_notify)
コード例 #2
0
    def __init__(self, contract_hash, wallet_path, wallet_pass):
        super(SurTokenContract, self).__init__()
        self.daemon = True

        self.contract_hash = contract_hash
        self.wallet_path = wallet_path
        self.wallet_pass = to_aes_key(wallet_pass)

        self.smart_contract = SmartContract(contract_hash)
        self.invoke_queue = Queue()

        self.tx_in_progress = None
        self.wallet = None

        settings.set_log_smart_contract_events(False)

        @self.smart_contract.on_notify
        def sc_notify(event):
            logger.info("SmartContract Runtime.Notify event: %s", event)

            # Make sure that the event payload list has at least one element.
            if not len(event.event_payload):
                return

            # The event payload list has at least one element. As developer of the smart contract
            # you should know what data-type is in the bytes, and how to decode it. In this example,
            # it's just a string, so we decode it with utf-8:
            logger.info("- payload part 1: %s",
                        event.event_payload[0].decode("utf-8"))
    def __init__(self):

        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'neo-nrve-config.json'), 'r') as f:
            config = json.load(f)

        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'network-wallets.json'), 'r') as f:
            network_wallets_config = json.load(f)

        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'db-config.json'), 'r') as f:
            self.db_config = json.load(f)

        super().__init__(NetworkType[config['network']],
                         'neo-nrve-eventhandler')

        self.smart_contract_hash = config['smart_contract']
        self.smart_contract = SmartContract(self.smart_contract_hash)

        self.wait_whitelist_tx_processing_seconds = config[
            'wait_whitelist_tx_processing_seconds']
        self.wait_load_addresses_to_whitelist_seconds = config[
            'wait_load_addresses_to_whitelist_seconds']

        self.addresses_to_whitelist_count = config[
            'addresses_to_whitelist_count']

        self.setup_wallet(
            network_wallets_config[config['network']]['wallet_path'])
コード例 #4
0
    def __init__(self):
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'bulk-tx-config.json'), 'r') as f:
            config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', config['job_config_file']), 'r') as f:
            job_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'network-wallets.json'), 'r') as f:
            network_wallets_config = json.load(f)

        super().__init__(NetworkType[config['network']], 'bulk-process-tx')

        self.test_only = config['test_only']

        self.operation = job_config['operation']
        self.operation_args_array_length = job_config[
            'operation_args_array_length']
        self.expected_result_count = job_config['expected_result_count']
        try:
            self.from_addr = job_config['from_addr']
        except KeyError:
            pass

        self.jobs = job_config['jobs']

        # Setup the smart contract instance
        self.smart_contract_hash = config['smart_contract']
        self.smart_contract = SmartContract(self.smart_contract_hash)

        # decorate the event handler methods dynamically now that we have loaded the SC
        self.sc_notify = self.smart_contract.on_notify(self.sc_notify)
        self.sc_storage = self.smart_contract.on_storage(self.sc_storage)
        self.sc_execution = self.smart_contract.on_execution(self.sc_execution)

        self.setup_wallet(
            network_wallets_config[config['network']]['wallet_path'])
コード例 #5
0
    def __init__(self, disable_auto_whitelist):
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'neo-nrve-config.json'), 'r') as f:
            config = json.load(f)
        if not disable_auto_whitelist:
            with open(
                    os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                 'config', 'network-wallets.json'), 'r') as f:
                network_wallets_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'db-config.json'), 'r') as f:
            self.db_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'smtp-config.json'), 'r') as f:
            self.smtp_config = json.load(f)

        super().__init__(NetworkType[config['network']],
                         'neo-nrve-eventhandler')

        self.smart_contract_hash = config['smart_contract']
        self.smart_contract = SmartContract(self.smart_contract_hash)
        self.old_smart_contract = SmartContract(config['old_smart_contract'])
        self.ignore_blocks_older_than = config['ignore_blocks_older_than']

        # decorate the event handler method dynamically now that we have loaded the SCs
        self.sc_notify = self.old_smart_contract.on_notify(self.sc_notify)
        self.sc_notify = self.smart_contract.on_notify(self.sc_notify)

        if not disable_auto_whitelist:
            self.setup_wallet(
                network_wallets_config[config['network']]['wallet_path'])
        else:
            self.setup_network()

        self.disable_auto_whitelist = disable_auto_whitelist
コード例 #6
0
class TokenSaleEventHandler(BlockchainMain):

    smart_contract_hash = None

    # Setup the smart contract instance
    smart_contract = None
    old_smart_contract = None

    db_config = None
    smtp_config = None

    ignore_blocks_older_than = None

    disable_auto_whitelist = None

    wallet_needs_recovery = False

    whitelists_to_process = []
    whitelist_tx_processing = None

    def __init__(self, disable_auto_whitelist):
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'neo-nrve-config.json'), 'r') as f:
            config = json.load(f)
        if not disable_auto_whitelist:
            with open(
                    os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                 'config', 'network-wallets.json'), 'r') as f:
                network_wallets_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'db-config.json'), 'r') as f:
            self.db_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'smtp-config.json'), 'r') as f:
            self.smtp_config = json.load(f)

        super().__init__(NetworkType[config['network']],
                         'neo-nrve-eventhandler')

        self.smart_contract_hash = config['smart_contract']
        self.smart_contract = SmartContract(self.smart_contract_hash)
        self.old_smart_contract = SmartContract(config['old_smart_contract'])
        self.ignore_blocks_older_than = config['ignore_blocks_older_than']

        # decorate the event handler method dynamically now that we have loaded the SCs
        self.sc_notify = self.old_smart_contract.on_notify(self.sc_notify)
        self.sc_notify = self.smart_contract.on_notify(self.sc_notify)

        if not disable_auto_whitelist:
            self.setup_wallet(
                network_wallets_config[config['network']]['wallet_path'])
        else:
            self.setup_network()

        self.disable_auto_whitelist = disable_auto_whitelist

    def sc_notify(self, event):

        event_payload = event.event_payload

        if not isinstance(
                event_payload, ContractParameter
        ) or event_payload.Type != ContractParameterType.Array:
            self.logger.info(
                "[invalid event_payload] SmartContract Runtime.Notify event: %s",
                event)
            return

        payload = event_payload.Value

        # Make sure that the event payload list has at least one element.
        if not len(payload):
            self.logger.info(
                "[no event_payload] SmartContract Runtime.Notify event: %s",
                event)
            return

        if event.test_mode:
            self.logger.info(
                "[test_mode] SmartContract Runtime.Notify event: %s", event)
            return

        if not event.execution_success:
            self.logger.info(
                "[execution_success=false] SmartContract Runtime.Notify event: %s",
                event)
            return

        # The event payload list has at least one element. As developer of the smart contract
        # you should know what data-type is in the bytes, and how to decode it. In this example,
        # it's just a string, so we decode it with utf-8:
        event_type = payload[0].Value.decode("utf-8")
        block_number = event.block_number

        if self.ignore_blocks_older_than and block_number < self.ignore_blocks_older_than:
            return

        timestamp = self.blockchain.GetHeaderByHeight(block_number).Timestamp

        # bl: event.contract_hash is a UInt160, so convert it to a hex string
        contract_hash = event.contract_hash.ToString()
        # bl: event.tx_hash is a UInt256, so convert it to a hex string
        tx_hash = event.tx_hash.ToString()

        # bl: we only care about refunds for the old smart contract
        if contract_hash == self.old_smart_contract.contract_hash and event_type != 'refund':
            return

        connection = self.get_connection()

        try:
            with connection.cursor() as cursor:
                if event_type == 'kyc_registration' or event_type == 'kyc_deregistration':
                    address = self.get_address(payload[1].Value)
                    self.logger.info("- %s: %s", event_type, address)
                    sql = "update `NarrativeUserNeoAddress` set whitelisted = %s where neoAddress = %s"
                    args = (1 if event_type == 'kyc_registration' else 0,
                            address)
                elif event_type == 'contribution':
                    # from, neo, tokens
                    address = self.get_address(payload[1].Value)
                    # based on the smart contract, we know these should always be whole numbers
                    neo = (int)(payload[2].Value / 100000000)
                    tokens = (int)(payload[3].Value / 100000000)
                    self.logger.info("- %s: %s: %s NEO (%s NRVE) (tx: %s)",
                                     event_type, address, neo, tokens, tx_hash)
                    sql = (
                        "insert into `NarrativeContribution` (transactionId, neo, nrveTokens, transactionDate, neoAddress_oid)\n"
                        "select %s, %s, %s, from_unixtime(%s), na.oid\n"
                        "from NarrativeUserNeoAddress na\n"
                        "where na.neoAddress = %s")
                    args = (tx_hash, neo, tokens, timestamp, address)
                elif event_type == 'refund':
                    # to, amount
                    address = self.get_address(payload[1].Value)
                    # based on the smart contract, the amount should always be a whole number
                    amount = (int)(payload[2].Value / 100000000)
                    log = "%s: %s: %s NEO [%s] (tx: %s)" % (
                        event_type, address, amount, contract_hash, tx_hash)
                    self.logger.info('- ' + log)
                    sql = (
                        "insert into `NarrativeRefund` (transactionId, contractHash, neo, transactionDate, neoAddress)\n"
                        "values (%s, %s, %s, from_unixtime(%s), %s)")
                    args = (tx_hash, contract_hash, amount, timestamp, address)
                    self.send_email("Narrative Refund Required", log)
                elif event_type == 'transfer' or event_type == 'approve':
                    # bl: ignore NEP5 transfers and approvals. don't care about those, and there will be a lot!
                    return
                else:
                    self.logger.warn("Unhandled event: %s", event)
                    return

                # Create a new record
                cursor.execute(sql, args)

                if cursor.rowcount != 1:
                    self.logger.error('ERROR: Failed recording event: %s',
                                      event)

            # connection is not autocommit by default. So you must commit to save
            # your changes.
            connection.commit()
        except MySQLError as e:
            self.logger.error('ERROR: event %s: {!r}, errno is {}'.format(
                event, e, e.args[0]))
        finally:
            connection.close()

        # if this is the whitelist tx we are waiting for, then clear it out so the next can be processed!
        if not self.disable_auto_whitelist and self.whitelist_tx_processing and tx_hash == self.whitelist_tx_processing.ToString(
        ):
            self.whitelist_tx_processing = None

    def get_connection(self):
        # Connect to the database
        return pymysql.connect(host=self.db_config['host'],
                               user=self.db_config['user'],
                               password=self.db_config['password'],
                               db=self.db_config['db'],
                               charset='utf8mb4',
                               cursorclass=pymysql.cursors.DictCursor)

    def send_email(self, subject, body):
        msg = MIMEText(body)
        msg['Subject'] = subject
        msg['From'] = self.smtp_config['from_address']
        msg['To'] = self.smtp_config['to_address']

        # Send the message via our own SMTP server.
        # bl: production servers user port 587
        s = smtplib.SMTP(self.smtp_config['host'], self.smtp_config['port'])
        if self.smtp_config['use_tls']:
            s.starttls()
        s.send_message(msg)
        s.quit()

    async def custom_background_code(self):
        count = 0
        while True:
            await asyncio.sleep(1)

            count += 1
            if (count % 60) == 0:
                self.logger.info("Block %s / %s",
                                 str(Blockchain.Default().Height),
                                 str(Blockchain.Default().HeaderHeight))
                count = 0

            # when disabling auto-whitelisting, nothing further to do here
            if self.disable_auto_whitelist:
                continue

            # already have a whitelist that we are waiting to process? then just keep waiting until that transaction comes through
            if self.whitelist_tx_processing:
                continue

            # load addresses to whitelist every 15 seconds, but only if the list is empty
            if not self.whitelists_to_process:
                # look for NEO addresses to whitelist every 15 seconds
                if (count % 15) != 0:
                    continue
                self.load_addresses_to_whitelist()

            # no whitelists to process? then keep waiting
            if not self.whitelists_to_process:
                continue

            if self.wallet_needs_recovery:
                await self.recover_wallet()
                self.wallet_needs_recovery = False
            else:
                await self.wallet_sync()

            addresses_to_whitelist = self.whitelists_to_process[0:6]
            self.whitelists_to_process = self.whitelists_to_process[6:]

            self.logger.debug('whitelisting addresses: %s',
                              addresses_to_whitelist)
            result = await self.test_invoke([
                self.smart_contract_hash, 'crowdsale_register',
                str(addresses_to_whitelist)
            ], len(addresses_to_whitelist), False)

            if not result:
                # transaction failed? wallet probably out-of-sync (insufficient funds) so reload it
                self.wallet_needs_recovery = True
                # we need to try to process this refund again, so add it back in to the list
                self.whitelists_to_process = addresses_to_whitelist + self.whitelists_to_process
            else:
                # transaction successfully relayed? then let's set the tx Hash that we're waiting for
                self.whitelist_tx_processing = result.Hash

    def load_addresses_to_whitelist(self):
        connection = self.get_connection()
        try:
            with connection.cursor() as cursor:
                sql = (
                    "select na.neoAddress from `NarrativeUser` u\n"
                    "inner join `NarrativeUserNeoAddress` na on na.oid = u.primaryNeoAddress_oid\n"
                    "where na.whitelisted = 0\n"
                    "and u.hasVerifiedEmailAddress = 1\n"
                    "and u.kycStatus = 3;")
                cursor.execute(sql)

                rows = cursor.fetchall()

                for row in rows:
                    self.whitelists_to_process.append(row['neoAddress'])
        except MySQLError as e:
            self.logger.error(
                'ERROR: selecting whitelist addresses: {!r}, errno is {}'.
                format(e, e.args[0]))
        finally:
            connection.close()
コード例 #7
0
ファイル: smart-contract.py プロジェクト: kartava/neo-python
from logzero import logger
from twisted.internet import reactor, task

from neo.contrib.smartcontract import SmartContract
from neo.SmartContract.ContractParameter import ContractParameter, ContractParameterType
from neo.Network.NodeLeader import NodeLeader
from neo.Core.Blockchain import Blockchain
from neo.Implementations.Blockchains.LevelDB.LevelDBBlockchain import LevelDBBlockchain
from neo.Settings import settings

# If you want the log messages to also be saved in a logfile, enable the
# next line. This configures a logfile with max 10 MB and 3 rotations:
# settings.set_logfile("/tmp/logfile.log", max_bytes=1e7, backup_count=3)

# Setup the smart contract instance
smart_contract = SmartContract("6537b4bd100e514119e3a7ab49d520d20ef2c2a4")


# Register an event handler for Runtime.Notify events of the smart contract.
@smart_contract.on_notify
def sc_notify(event):
    logger.info("SmartContract Runtime.Notify event: %s", event)

    # Make sure that the event payload list has at least one element.
    if not isinstance(
            event.event_payload, ContractParameter
    ) or event.event_payload.Type != ContractParameterType.Array or not len(
            event.event_payload.Value):
        return

    # The event payload list has at least one element. As developer of the smart contract
コード例 #8
0
from neocore.KeyPair import KeyPair
import coinmarketcap
from neocore.BigInteger import BigInteger
from neo.Core.Helper import Helper

import random

# If you want the log messages to also be saved in a logfile, enable the
# next line. This configures a logfile with max 10 MB and 3 rotations:
# settings.set_logfile("/tmp/logfile.log", max_bytes=1e7, backup_count=3)

# Setup the smart contract instance
# This is online voting v0.5

#smart_contract_hash = "7dc2db1227a8518146dc41c55dfafa97d9a83c27"
smart_contract = SmartContract(smart_contract_hash)
#wallet_hash = 'Aaaapk3CRx547bFvkemgc7z2xXewzaZtdP'
#wallet_arr = Helper.AddrStrToScriptHash(wallet_hash).ToArray()

Wallet = None

buffer = None

normalisation = 300


def test_invoke_contract(args):
    if not Wallet:
        print("where's the wallet")
        return
    if args and len(args) > 0:
コード例 #9
0
from time import sleep

from logzero import logger
from twisted.internet import reactor, task

from neo.contrib.smartcontract import SmartContract
from neo.Network.NodeLeader import NodeLeader
from neo.Core.Blockchain import Blockchain
from neo.Implementations.Blockchains.LevelDB.LevelDBBlockchain import LevelDBBlockchain
from neo.Settings import settings

from google.cloud import pubsub_v1

from neocore.Cryptography import Crypto

smart_contract = SmartContract(os.environ["CONTRACT"])
publisher = pubsub_v1.PublisherClient()
topic = publisher.topic_path("astrum-world", "neo")


def parse_arg(input):
    if isinstance(input, int):
        return input
    try:
        return input.decode('utf-8')
    except:
        pass
    if len(input) == 20:
        try:
            return Crypto.scripthash_to_address(input)
        except:
コード例 #10
0
ファイル: monitor_contract.py プロジェクト: soros1321/trinity
from logzero import logger

from twisted.internet import reactor, task

from neo.contrib.smartcontract import SmartContract
from neo.Network.NodeLeader import NodeLeader
from neo.Core.Blockchain import Blockchain
from neo.Implementations.Blockchains.LevelDB.LevelDBBlockchain import LevelDBBlockchain
from neo.Settings import settings

from channel_manager.channel import get_channelnames_via_address, Channel, State
from channel_manager.manager import close_channel
from utils.channel import split_channel_name
from crypto.Cryptography.Helper import hash_to_wallet_address, bytes_to_hex_string, hex2interger

smart_contract = SmartContract(Configure["TNC"].replace("0x", ""))
ContractAddr = Configure["ContractAddr"]
DepositIN = []
DepositOut = []


# Register an event handler for Runtime.Notify events of the smart contract.
@smart_contract.on_notify
def sc_notify(event):
    logger.info("SmartContract Runtime.Notify event: %s", event)

    if not len(event.event_payload):
        return

    logger.info("- payload part 1: %s", event.event_payload[0].decode("utf-8"))
    tx_type = event.event_payload[0]
コード例 #11
0
class BulkProcess(BlockchainMain):
    # from InputParser
    parser = ZeroOrMore(
        Regex(r'\[[^]]*\]') | Regex(r'"[^"]*"') | Regex(r'\'[^\']*\'')
        | Regex(r'[^ ]+'))

    smart_contract_hash = None

    operation = None
    operation_args_array_length = None
    expected_result_count = None
    from_addr = None

    test_only = False

    wallet_needs_recovery = False

    smart_contract = None

    job = None

    jobs = None

    jobs_processed = 0
    tx_processing = None

    def __init__(self):
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'bulk-tx-config.json'), 'r') as f:
            config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', config['job_config_file']), 'r') as f:
            job_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'network-wallets.json'), 'r') as f:
            network_wallets_config = json.load(f)

        super().__init__(NetworkType[config['network']], 'bulk-process-tx')

        self.test_only = config['test_only']

        self.operation = job_config['operation']
        self.operation_args_array_length = job_config[
            'operation_args_array_length']
        self.expected_result_count = job_config['expected_result_count']
        try:
            self.from_addr = job_config['from_addr']
        except KeyError:
            pass

        self.jobs = job_config['jobs']

        # Setup the smart contract instance
        self.smart_contract_hash = config['smart_contract']
        self.smart_contract = SmartContract(self.smart_contract_hash)

        # decorate the event handler methods dynamically now that we have loaded the SC
        self.sc_notify = self.smart_contract.on_notify(self.sc_notify)
        self.sc_storage = self.smart_contract.on_storage(self.sc_storage)
        self.sc_execution = self.smart_contract.on_execution(self.sc_execution)

        self.setup_wallet(
            network_wallets_config[config['network']]['wallet_path'])

    def pre_start(self):
        # trigger the first job to be processed
        self.process_job()

    def sc_notify(self, event):
        if not event.execution_success:
            return

        prefix = ""
        if event.test_mode:
            prefix = "[test_mode]"
        elif event.tx_hash != self.tx_processing:
            # only emit notify events for the transaction that we are waiting on
            return

        self.logger.info(
            prefix + "[SmartContract.Runtime.Notify] [%s] [tx %s] %s",
            event.contract_hash, event.tx_hash, event.event_payload)

    def sc_storage(self, event):
        prefix = ""
        if event.test_mode:
            prefix = "[test_mode]"
        elif event.tx_hash != self.tx_processing:
            # only emit notify events for the transaction that we are waiting on
            return

        self.logger.info(prefix + "[%s] [%s] [tx %s] %s", event.event_type,
                         event.contract_hash, event.tx_hash,
                         event.event_payload)

    def sc_execution(self, event):
        # only emit execution events for the transaction that we are waiting on
        if event.tx_hash != self.tx_processing:
            return

        if not event.execution_success:
            self.logger.error(
                "[execution_success=false][SmartContract.Runtime.Notify] [%s] [tx %s] %s",
                event.contract_hash, event.tx_hash, event.event_payload)
            return

        prefix = ""
        if event.test_mode:
            prefix = "[test_mode]"

        self.logger.info(
            prefix + "[SmartContract.Execution.Success] [%s] [tx %s] %s",
            event.contract_hash, event.tx_hash, event.event_payload)

        if not event.test_mode:
            self.jobs_processed += 1
            self.process_job()

    def process_job(self):
        jobs_remaining = len(self.jobs)

        self.logger.debug("%s jobs processed. %s jobs remaining.",
                          self.jobs_processed, jobs_remaining)

        self.tx_processing = None

        if jobs_remaining > 0:
            # just pop a job off the array to process next
            self.job = self.jobs[0]
            self.jobs = self.jobs[1:]
        else:
            # change the jobs array to None (from an empty array) to indicate we are done and can shut down
            self.jobs = None

    def custom_background_code(self):
        """ Custom code run in a background thread. Prints the current block height.

        This function is run in a daemonized thread, which means it can be instantly killed at any
        moment, whenever the main thread quits. If you need more safety, don't use a  daemonized
        thread and handle exiting this thread in another way (eg. with signals and events).
        """
        while True:
            sleep(1)

            if not self.job:
                # no more jobs? then shut 'er down!
                if self.jobs is None:
                    self.shutdown()

                # if it's a refund job, then check to see if we have the transaction recorded yet. if not, keep waiting.
                # note that this will give an info log "Could not find transaction for hash b'xxx'" every second until the tx is processed.
                if self.is_refund_job() and self.tx_processing:
                    tx, height = Blockchain.Default().GetTransaction(
                        self.tx_processing)
                    # the tx will have a height once it's completed!
                    if height > -1:
                        # the tx has been processed, so process the next refund!
                        self.jobs_processed += 1
                        self.process_job()
                continue

            if self.wallet_needs_recovery:
                self.recover_wallet()
                self.wallet_needs_recovery = False
            else:
                self.wallet_sync()

            # special handling for sending refunds
            if self.is_refund_job():
                self.process_refund_job()
            else:
                self.process_testinvoke_job()

    def is_refund_job(self):
        return self.operation == 'send'

    def process_refund_job(self):
        if len(self.job) != self.operation_args_array_length:
            self.logger.error(
                'ERROR! must have exactly %d operation args, not %d. skipping! %s',
                self.operation_args_array_length, len(self.job), self.job)
            self.job = None
            self.process_job()
            return

        # bl: tx can fail if there are no connected peers, so wait for one
        self.wait_for_peers()

        self.logger.debug('processing refund: %s', self.job)
        # in case we have to rebuild the wallet and try the job again, pass in a new list to construct_and_send
        # since internally the method actually has a side effect of modifying the array to strip out the from address
        result = construct_and_send(None, self.wallet, list(self.job), False)

        if not result:
            self.wallet_needs_recovery = True
        else:
            self.job = None
            self.tx_processing = result.Hash

    def process_testinvoke_job(self):
        job_args = self.parser.parseString(self.operation + " " +
                                           str(self.job))
        job_args = job_args[0:]

        if len(job_args) != 2:
            self.logger.error(
                'ERROR! must have only 2 args (operation, params). skipping! %s',
                job_args)
            self.job = None
            self.process_job()
            return

        operation_params = parse_param(job_args[1])
        if len(operation_params) != self.operation_args_array_length:
            self.logger.error(
                'ERROR! must have exactly %d operation args, not %d. skipping! %s',
                self.operation_args_array_length, len(operation_params),
                job_args)
            self.job = None
            self.process_job()
            return

        args = [self.smart_contract_hash] + job_args
        self.logger.debug('processing job: %s', args)
        result = self.test_invoke(args, self.expected_result_count,
                                  self.test_only, self.from_addr)

        if not result:
            # transaction failed? wallet probably out-of-sync (insufficient funds) so reload it
            self.wallet_needs_recovery = True
        else:
            # this job has been invoked, so clear it out. on to the next.
            self.job = None
            if self.test_only:
                # when testing but not relaying transactions, we just continue to the next job
                self.jobs_processed += 1
                self.process_job()
            else:
                # transaction successfully relayed? then let's set the tx Hash that we're waiting for
                self.tx_processing = result.Hash
コード例 #12
0
class NichePaymentHandler(BlockchainMain):

    # Setup the smart contract instance
    smart_contract = None

    nrve_token_symbol = "NRVE"
    niche_payment_address = None

    db_config = None
    smtp_config = None

    wallet_needs_recovery = False

    transfers_to_process = []
    transfer_tx_processing = None

    def __init__(self):
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'nrve-niche-config.json'), 'r') as f:
            config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'db-config.json'), 'r') as f:
            self.db_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'smtp-config.json'), 'r') as f:
            self.smtp_config = json.load(f)

        super().__init__(NetworkType[config['network']],
                         'nrve-niche-payment-handler')

        self.smart_contract = SmartContract(config['smart_contract'])
        self.niche_payment_address = config['niche_payment_address']

        self.setup_network()

        # decorate the event handler methods dynamically now that we have loaded the SC
        self.sc_notify = self.smart_contract.on_notify(self.sc_notify)

    def sc_notify(self, event):
        try:
            self.do_sc_notify(event)
        except Exception as e:
            print("Could not process notify event: %s" % e)
            traceback.print_stack()
            traceback.print_exc()
            raise e

    def do_sc_notify(self, event):

        event_payload = event.event_payload

        if not isinstance(
                event_payload, ContractParameter
        ) or event_payload.Type != ContractParameterType.Array:
            self.logger.info(
                "[invalid event_payload] SmartContract Runtime.Notify event: %s",
                event)
            return

        payload = event_payload.Value

        # Make sure that the event payload list has at least one element.
        if not len(payload):
            self.logger.info(
                "[no event_payload] SmartContract Runtime.Notify event: %s",
                event)
            return

        if event.test_mode:
            self.logger.info(
                "[test_mode] SmartContract Runtime.Notify event: %s", event)
            return

        if not event.execution_success:
            self.logger.info(
                "[execution_success=false] SmartContract Runtime.Notify event: %s",
                event)
            return

        # The event payload list has at least one element. As developer of the smart contract
        # you should know what data-type is in the bytes, and how to decode it. In this example,
        # it's just a string, so we decode it with utf-8:
        event_type = payload[0].Value.decode("utf-8")

        # Only looking for transfer events, so ignore everything else
        if event_type != 'transfer':
            return

        self.logger.info("[event_payload] Processing event: %s", event)

        # To address
        to_address = self.get_address(payload[2].Value)

        # Ignore transfers between other accounts. only care about payments to the niche payment address
        if to_address != self.niche_payment_address:
            self.logger.info("- ignoring unknown %s: to %s; not %s",
                             event_type, to_address,
                             self.niche_payment_address)
            return

        # From address & NRVE amount
        from_address = self.get_address(payload[1].Value)
        raw_nrve_amount = payload[3].Value
        # bl: there can be different data types returned in the amount payload for some reason, so detect which it is (BigInteger/int or bytes)
        if isinstance(raw_nrve_amount, int):
            nrve_amount = raw_nrve_amount
        else:
            nrve_amount = int.from_bytes(raw_nrve_amount, 'little')

        # bl: event.tx_hash is a UInt256, so convert it to a hex string
        tx_hash = event.tx_hash.ToString()

        self.process_nrve_transaction(event, event_type, from_address,
                                      nrve_amount, tx_hash)

    def process_nrve_transaction(self, event, event_type, from_address,
                                 nrve_amount, tx_hash):

        # Connect to the database
        connection = pymysql.connect(host=self.db_config['host'],
                                     user=self.db_config['user'],
                                     password=self.db_config['password'],
                                     db=self.db_config['db'],
                                     charset='utf8mb4',
                                     cursorclass=pymysql.cursors.DictCursor)

        try:
            with connection.cursor() as cursor:
                log = "- payment %s: from %s: %s NRVE (tx: %s)" % (
                    event_type, from_address, nrve_amount, tx_hash)
                self.logger.info(log)
                sql = ("select oid from `NrvePayment`\n"
                       "where fromNeoAddress = %s\n"
                       "and nrveAmount = %s\n"
                       "and paymentStatus = 0\n"
                       "and transactionId is null\n"
                       "for update;")

                args = (from_address, nrve_amount)
                cursor.execute(sql, args)

                if cursor.rowcount == 0:
                    # This could be one of two scenarios:
                    #   1. Transaction does not exist, making it invalid (Refund).
                    #   2. Transaction was processed by a different thread (transactionId has been updated to a non-null value).
                    self.handle_unknown_transaction(connection, event,
                                                    from_address, nrve_amount,
                                                    tx_hash)
                    return

                elif cursor.rowcount > 1:
                    subject = 'FATAL! Identified multiple payments by unique key. Should not be possible!'
                    self.logger.error(subject + ': %s', event)
                    self.send_email(
                        subject,
                        self.format_error_message(
                            {"Transaction Id": tx_hash},
                            {"From Address": from_address},
                            {"To Address": self.niche_payment_address},
                            {"NRVE Amount": nrve_amount},
                            {"Number of Transactions": cursor.rowcount}))
                    return

                block = self.blockchain.GetHeaderByHeight(event.block_number)

                # when a payment is outstanding, it will be recorded with the expected "from address", the proper
                # nrveAmount (in "neurons") and a paymentStatus of 0 which indicates it's pending payment
                sql = ("update `NrvePayment`\n"
                       "set transactionId = %s\n"
                       ", transactionDate = from_unixtime(%s)\n"
                       ", foundByExternalApi = 0\n"
                       "where fromNeoAddress = %s\n"
                       "and nrveAmount = %s\n"
                       "and paymentStatus = 0\n"
                       "and transactionId is null;")
                args = (tx_hash, block.Timestamp, from_address, nrve_amount)

                # Create a new record
                cursor.execute(sql, args)

                if cursor.rowcount != 1:
                    subject = 'Failed updating payment. Should not be possible since it was already locked for update'
                    self.logger.error(subject + ': %s', event)
                    self.send_email(
                        subject,
                        self.format_error_message(
                            {"Transaction Id": tx_hash},
                            {"From Address": from_address},
                            {"To Address": self.niche_payment_address},
                            {"NRVE Amount": nrve_amount}))
                    return

                self.send_email("Successful Niche Payment", log)

            # connection is not autocommit by default. So you must commit to save your changes.
            connection.commit()

        except MySQLError as e:
            error_message = 'ERROR: event %s: {!r}, errno is {}'.format(
                event, e, e.args[0])
            self.logger.error(error_message)
            self.send_email('Niche Payment Error', error_message)

        finally:
            connection.close()

    def handle_unknown_transaction(self, connection, event, from_address,
                                   nrve_amount, tx_hash):

        try:
            with connection.cursor() as cursor:
                sql = (
                    "select oid from `NrvePayment` where transactionId = %s;")
                params = tx_hash
                cursor.execute(sql, params)

                if cursor.rowcount == 0:
                    # Send refund email
                    subject = 'Failed identifying niche payment. ' + self.network_type + ' refund required!'
                    self.logger.error(subject + ': %s', event)
                    self.send_email(
                        subject,
                        self.format_error_message(
                            {"Transaction Id": tx_hash},
                            {"From Address": from_address},
                            {"To Address": self.niche_payment_address},
                            {"NRVE Amount": nrve_amount}))
                    return

                elif cursor.rowcount == 1:
                    # Transaction is valid, no need to process any further.
                    self.logger.info(
                        "Transaction %s was already processed by a different thread.",
                        tx_hash)
                    return

                else:
                    self.logger.error(
                        "FATAL! Found %s records for transaction %s. ",
                        cursor.rowcount, tx_hash)
                    return

        except MySQLError as e:
            error_message = 'ERROR: event %s: {!r}, errno is {}'.format(
                event, e, e.args[0])
            self.logger.error(error_message)
            self.send_email('Unable to verify Niche Payment status.',
                            error_message)

    def send_email(self, subject, body):
        msg = MIMEText(body)
        msg['Subject'] = subject
        msg['From'] = 'Narrative ' + self.network_type + ' <' + self.smtp_config[
            'from_address'] + '>'
        msg['To'] = self.smtp_config['to_address']

        # Send the message via our own SMTP server.
        # bl: production servers user port 587
        s = smtplib.SMTP(self.smtp_config['host'], self.smtp_config['port'])
        if self.smtp_config['use_tls']:
            s.starttls()
        if self.smtp_config['username']:
            s.login(self.smtp_config['username'], self.smtp_config['password'])
        s.send_message(msg)
        s.quit()

    @staticmethod
    def format_error_message(*args):
        message = ''
        for eachDict in args:
            for key, value in eachDict.items():
                if message != '':
                    message += "\n"
                message += str(key) + ": " + str(value)
        return message
コード例 #13
0
    def __init__(self, contract_hash, wallet_path, wallet_pass):
        super(LootMarketsSmartContract, self).__init__()
        self.daemon = True

        self.contract_hash = contract_hash
        self.wallet_path = wallet_path
        self.wallet_pass = wallet_pass

        self.smart_contract = SmartContract(contract_hash)
        self.invoke_queue = Queue()

        # Setup redis cache.
        self.redis_cache = redis.StrictRedis(host='localhost', port=6379, db=0)

        self.calling_transaction = None
        self.tx_in_progress = None
        self.wallet = None

        settings.set_log_smart_contract_events(False)

        # Setup handler for smart contract Runtime.Notify event.
        # Here we listen to all notify events.
        @self.smart_contract.on_notify
        def sc_notify(event):
            """ This method catches Runtime.Notify calls, and updates the relevant cache. """

            # Log the received smart contract event.
            logger.info("- SmartContract Event: %s", str(event))
            event_name = event.event_payload[0].decode("utf-8")

            # ==== General Events ====
            # Smart contract events that are not specific to a marketplace.

            # Event: balance_of
            if event_name == "balance_of":
                # Convert the given script hash to an address.
                script_hash = event.event_payload[1]
                sh = UInt160.UInt160(data=script_hash)
                address = Crypto.ToAddress(sh)
                balance = int.from_bytes(event.event_payload[2], 'little')
                # Save the balance to the cache.
                logger.info("- Balance of %s updated to %s LOOT", address,
                            balance)
                self.redis_cache.set("balance:%s" % address, int(balance))
                return

            # Event: get_marketplace_owner
            if event_name == "get_marketplace_owner":
                marketplace = event.event_payload[1].decode("utf-8")
                script_hash = event.event_payload[2]
                sh = UInt160.UInt160(data=script_hash)
                address = Crypto.ToAddress(sh)
                logger.info("- Owner of %s: %s", marketplace, address)
                self.redis_cache.set("owner:%s" % marketplace, address)
                return

            # ==== Marketplace Events ====
            # Events that are specific to a marketplace.

            # Get the name of the marketplace, if it is none this is not a marketplace operation, return.
            marketplace = event.event_payload[1]
            if marketplace is not None:
                marketplace = marketplace.decode("utf-8")
            else:
                return

            # Ignore smart contract events that are not on our marketplace being used.
            if marketplace != self.marketplace:
                return

            # Event: get_inventory
            if event_name == "get_inventory":
                # Convert the script hash to an address.
                script_hash = event.event_payload[2]
                sh = UInt160.UInt160(data=script_hash)
                address = Crypto.ToAddress(sh)

                # After being converted from a byte to an int, append each element to the list.
                inventory = []
                for i in event.event_payload[3]:
                    item_id = int.from_bytes(i, 'little')
                    inventory.append(item_id)

                # Update the inventory in the redis cache.
                logger.info("- Setting inventory of %s to %s", address,
                            inventory)
                self.redis_cache.set("inventory:%s" % address, inventory)
                self.redis_cache.set("inventoryUpdatedAt:%s" % address,
                                     int(time.time()))

            # Event: get_all_offers
            if event_name == "get_all_offers":
                retrieved_offers = event.event_payload[2]
                # Decode all the offers given in the payload.
                offers = []
                for i in retrieved_offers:
                    # Offer is received like 'offer\x03' so we convert to 'offer3'.
                    # We don't want to show the cached offers to the players.
                    i = i.decode("utf-8")
                    index = ord(i.split('offer')[1])
                    offer_id = 'offer' + str(index)
                    if offer_id not in self.cached_offers:
                        offers.append(offer_id)

                # Log the information and save to the cache.
                logger.info("-Setting offers in marketplace: %s", offers)
                self.redis_cache.set("offers", offers)
                self.redis_cache.set("timeOffersUpdated", str(datetime.now()))

            # Event: get_offer
            if event_name == "get_offer":
                print("Event: get_offer")
                # Get all the relevant information about the offer.
                offer = event.event_payload[2]
                address = offer[0]
                offer_id_encoded = offer[1]

                # If the offer is empty, return.
                if not offer:
                    return

                # We receive the offer index sent from contract in format e.g. "offer\x03", convert to "offer3".
                index = ord(offer_id_encoded.decode().split('offer')[1])
                offer_id = 'offer' + str(index)

                # Decode the bytes into integers.
                item_id = int.from_bytes(offer[2], 'little')
                price = int.from_bytes(offer[3], 'little')

                # Convert the script hash to an address.
                script_hash = address
                sh = UInt160.UInt160(data=script_hash)
                address = Crypto.ToAddress(sh)

                # Put the offer information in a list and save it to the redis cache with the offer id as the key.
                offer_information = [address, offer_id, item_id, price]
                logger.info("-Setting offer:%s to %s", offer_id,
                            offer_information)
                self.redis_cache.set(offer_id, offer_information)

            # Event: Market/Item operation
            # The game/operator must know if these operations were successfully completed within the smart contract.
            # All of these notify events are sent in the same format.
            if event_name in ("cancel_offer", "buy_offer", "put_offer",
                              "give_items", "remove_item"):
                # Convert the script hash to address.
                script_hash = event.event_payload[2]
                sh = UInt160.UInt160(data=script_hash)
                address = Crypto.ToAddress(sh)
                # Check if the operation was successfully completed within the smart contract.
                operation_successful = event.event_payload[3]
                # Save the address, and result to the cache with the event_name used as a key.
                self.redis_cache.set(event_name + "%s" % address,
                                     operation_successful)
                logger.info(
                    "-" + event_name + " of address %s was completed: %s",
                    address, operation_successful)
コード例 #14
0
from neo.Implementations.Notifications.LevelDB.NotificationDB import NotificationDB
from neo.Settings import settings

from neo.Network.api.decorators import json_response, gen_authenticated_decorator, catch_exceptions

from neo.Implementations.Wallets.peewee.UserWallet import UserWallet
from neo.Prompt.Commands.Invoke import InvokeContract, TestInvokeContract, test_invoke
from neo.contrib.smartcontract import SmartContract

import urllib.request


# setup the protocol to be used
PROTOCOL_CONFIG = os.path.join(parent_dir, "protocol.privnet.json")
# Setup the smart contract instance
smart_contract = SmartContract("0b93cde1096433b2d1d9ddf74f85a7c6e266c4dc")


@smart_contract.on_notify
def sc_notify(event):
    logger.info("SmartContract Runtime.Notify event: %s", event)

    # Make sure that the event payload list has at least one element.
    if not len(event.event_payload):
        return

    # The event payload list has at least one element. As developer of the smart contract
    # you should know what data-type is in the bytes, and how to decode it. In this example,
    # it's just a string, so we decode it with utf-8:
    logger.info("- payload part 1: %s", event.event_payload[0].decode("utf-8"))
コード例 #15
0
ファイル: NRCReceiver.py プロジェクト: neo-robotics/NRC
from socket import *
from base58 import b58encode
from threading import Thread

from neo.Settings import settings
from neocore.Cryptography.Crypto import Crypto
from neo.Core.Blockchain import Blockchain
from neo.Implementations.Blockchains.LevelDB.LevelDBBlockchain import LevelDBBlockchain
from neo.Implementations.Wallets.peewee.UserWallet import UserWallet
from neo.Network.NodeLeader import NodeLeader
from neo.Prompt.Commands.Invoke import InvokeContract, TestInvokeContract
from neo.contrib.smartcontract import SmartContract
from twisted.internet import reactor, task

contract_address = "3c6a0ee4cecadfd6d3fd06fd7e7eedfa6d57dfe1"
smart_contract = SmartContract(contract_address)


@smart_contract.on_notify
def sc_notify(event):
    global receiver

    if len(event.event_payload) != 3:
        return

    receiver.addGeo(event.event_payload)


class NRCReceiver:
    def __init__(self, walletPath, walletPwd):
        self.open_wallet(walletPath, walletPwd)
コード例 #16
0
ファイル: simple_recorder.py プロジェクト: wy/neo-futures
from logzero import logger
from twisted.internet import reactor, task

from neo.contrib.smartcontract import SmartContract
from neo.Network.NodeLeader import NodeLeader
from neo.Core.Blockchain import Blockchain
from neo.Implementations.Blockchains.LevelDB.LevelDBBlockchain import LevelDBBlockchain
from neo.Settings import settings
from neocore.BigInteger import BigInteger

# If you want the log messages to also be saved in a logfile, enable the
# next line. This configures a logfile with max 10 MB and 3 rotations:
# settings.set_logfile("/tmp/logfile.log", max_bytes=1e7, backup_count=3)

# Setup the smart contract instance
smart_contract = SmartContract("d5537fc7dea2150d250e9d5f0cd67b8b248b3fdf")


# Register an event handler for Runtime.Notify events of the smart contract.
@smart_contract.on_notify
def sc_notify(event):
    logger.info("SmartContract Runtime.Notify event: %s", event)

    # Make sure that the event payload list has at least one element.
    if not len(event.event_payload):
        return

    # The event payload list has at least one element. As developer of the smart contract
    # you should know what data-type is in the bytes, and how to decode it. In this example,
    # it's just a string, so we decode it with utf-8:
    byte_array = event.event_payload[0]
コード例 #17
0
class NichePaymentHandler(BlockchainMain):

    # Setup the smart contract instance
    smart_contract = None

    nrve_token_symbol = "NRVE"
    niche_payment_address = None
    niche_payment_storage_address = None

    db_config = None
    smtp_config = None

    wallet_needs_recovery = False

    transfers_to_process = []
    transfer_tx_processing = None

    def __init__(self):
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'nrve-niche-config.json'), 'r') as f:
            config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'network-wallets.json'), 'r') as f:
            network_wallets_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'db-config.json'), 'r') as f:
            self.db_config = json.load(f)
        with open(
                os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'config', 'smtp-config.json'), 'r') as f:
            self.smtp_config = json.load(f)

        super().__init__(NetworkType[config['network']],
                         'nrve-niche-payment-handler')

        self.smart_contract = SmartContract(config['smart_contract'])
        self.niche_payment_address = config['niche_payment_address']
        self.niche_payment_storage_address = config[
            'niche_payment_storage_address']

        self.setup_wallet(
            network_wallets_config[config['network']]['wallet_path'])

        # decorate the event handler methods dynamically now that we have loaded the SC
        self.sc_notify = self.smart_contract.on_notify(self.sc_notify)

    def sc_notify(self, event):
        try:
            self.do_sc_notify(event)
        except Exception as e:
            print("Could not process notify event: %s" % e)
            traceback.print_stack()
            traceback.print_exc()
            raise e

    def do_sc_notify(self, event):

        # Make sure that the event payload list has at least one element.
        if not len(event.event_payload):
            self.logger.info(
                "[no event_payload] SmartContract Runtime.Notify event: %s",
                event)
            return

        if event.test_mode:
            self.logger.info(
                "[test_mode] SmartContract Runtime.Notify event: %s", event)
            return

        if not event.execution_success:
            self.logger.info(
                "[execution_success=false] SmartContract Runtime.Notify event: %s",
                event)
            return

        # The event payload list has at least one element. As developer of the smart contract
        # you should know what data-type is in the bytes, and how to decode it. In this example,
        # it's just a string, so we decode it with utf-8:
        event_type = event.event_payload[0].decode("utf-8")

        # only looking for transfer events, so ignore everything else
        if event_type != 'transfer':
            return

        # from, to, amount
        from_address = self.get_address(event.event_payload[1])
        to_address = self.get_address(event.event_payload[2])
        raw_nrve_amount = event.event_payload[3]
        # bl: there can be different data types returned in the amount payload for some reason, so detect which it is (BigInteger/int or bytes)
        if isinstance(raw_nrve_amount, int):
            nrve_amount = raw_nrve_amount
        else:
            nrve_amount = int.from_bytes(raw_nrve_amount, 'little')

        # bl: event.tx_hash is a UInt256, so convert it to a hex string
        tx_hash = event.tx_hash.ToString()

        # if this is an outbound NRVE transfer from our payment wallet, then it's a transfer!
        if from_address == self.niche_payment_address:
            # in order to move on to the next transfer, we just need to clear the tx, assuming it's the right one!
            if self.transfer_tx_processing and tx_hash == self.transfer_tx_processing.ToString(
            ):
                if to_address == self.niche_payment_storage_address:
                    self.logger.info(
                        "- payment storage %s: to %s: %s NRVE (tx: %s)",
                        event_type, to_address, nrve_amount, tx_hash)
                else:
                    self.logger.info("- refund %s: to %s: %s NRVE (tx: %s)",
                                     event_type, to_address, nrve_amount,
                                     tx_hash)
                self.transfer_tx_processing = None
            else:
                log = "%s: to %s: %s NRVE (tx: %s)" % (event_type, to_address,
                                                       nrve_amount, tx_hash)
                self.logger.warn("- unexpected outbound transfer! %s", log)
                self.send_email("Unexpected Outbound Transfer", log)
            return

        # ignore transfers between other accounts. only care about payments to the niche payment address
        if to_address != self.niche_payment_address:
            return

        block_number = event.block_number

        timestamp = self.blockchain.GetHeaderByHeight(block_number).Timestamp

        # Connect to the database
        connection = pymysql.connect(host=self.db_config['host'],
                                     user=self.db_config['user'],
                                     password=self.db_config['password'],
                                     db=self.db_config['db'],
                                     charset='utf8mb4',
                                     cursorclass=pymysql.cursors.DictCursor)

        try:
            with connection.cursor() as cursor:
                log = "- payment %s: from %s: %s NRVE (tx: %s)" % (
                    event_type, from_address, nrve_amount, tx_hash)
                self.logger.info(log)
                sql = ("select oid from `NicheAuctionInvoicePayment`\n"
                       "where fromNeoAddress = %s\n"
                       "and nrveAmount = %s\n"
                       "and paymentStatus = 0\n"
                       "and transactionId is null\n"
                       "for update;")
                args = (from_address, nrve_amount)
                cursor.execute(sql, args)

                if cursor.rowcount == 0:
                    self.logger.error(
                        'Failed identifying payment. Returning to sender: %s',
                        event)
                    self.transfer_payment(from_address, nrve_amount)
                    return
                elif cursor.rowcount > 1:
                    self.logger.error(
                        'FATAL! Identified multiple payments by unique key. Should not be possible! %s',
                        event)
                    self.transfer_payment(from_address, nrve_amount)
                    return

                # when a payment is outstanding, it will be recorded with the expected from address, the proper nrveAmount (in "neurons")
                # and a paymentStatus of 0 which indicates it's pending payment
                sql = ("update `NicheAuctionInvoicePayment`\n"
                       "set transactionId = %s\n"
                       ", transactionDate = from_unixtime(%s)\n"
                       "where fromNeoAddress = %s\n"
                       "and nrveAmount = %s\n"
                       "and paymentStatus = 0\n"
                       "and transactionId is null;")
                args = (tx_hash, timestamp, from_address, nrve_amount)

                # Create a new record
                cursor.execute(sql, args)

                if cursor.rowcount != 1:
                    self.logger.error(
                        'Failed updating payment. Should not be possible since it was already locked for update: %s',
                        event)
                    return

                # send the NRVE to the payment storage address
                self.transfer_payment(self.niche_payment_storage_address,
                                      nrve_amount)

                self.send_email("Successful Niche Payment", log)

            # connection is not autocommit by default. So you must commit to save
            # your changes.
            connection.commit()
        except MySQLError as e:
            error_message = 'ERROR: event %s: {!r}, errno is {}'.format(
                event, e, e.args[0])
            self.logger.error(error_message)
            self.send_email('Niche Payment Error', error_message)
        finally:
            connection.close()

    def send_email(self, subject, body):
        msg = MIMEText(body)
        msg['Subject'] = subject
        msg['From'] = self.smtp_config['from_address']
        msg['To'] = self.smtp_config['to_address']

        # Send the message via our own SMTP server.
        # bl: production servers user port 587
        s = smtplib.SMTP(self.smtp_config['host'], self.smtp_config['port'])
        if self.smtp_config['use_tls']:
            s.starttls()
        s.send_message(msg)
        s.quit()

    def transfer_payment(self, from_address, nrve_amount):
        self.transfers_to_process.append([from_address, nrve_amount])
        print('transfers_to_process %s', self.transfers_to_process)

    def custom_background_code(self):
        count = 0
        while True:
            sleep(1)

            count += 1
            if (count % 60) == 0:
                self.logger.info("Block %s / %s",
                                 str(Blockchain.Default().Height),
                                 str(Blockchain.Default().HeaderHeight))
                count = 0

            # already have a transfer that we are waiting to process? then just keep waiting until that transaction comes through
            if self.transfer_tx_processing:
                continue

            # no transfers? then keep waiting
            if not self.transfers_to_process:
                continue

            if self.wallet_needs_recovery:
                self.recover_wallet()
                self.wallet_needs_recovery = False
            else:
                self.wallet_sync()

            transfer = self.transfers_to_process[0]
            self.transfers_to_process = self.transfers_to_process[1:]
            if len(transfer) != 2:
                self.logger.error(
                    'ERROR! transfer must have exactly 2 args. skipping! %s',
                    transfer)
                continue

            to_address = transfer[0]
            if to_address == self.niche_payment_storage_address:
                self.logger.debug('processing payment storage: %s', transfer)
            else:
                self.logger.debug('processing refund: %s', transfer)
            token = get_asset_id(self.wallet, self.nrve_token_symbol)
            print('found token %s', token)
            result = do_token_transfer(token, self.wallet,
                                       self.niche_payment_address, to_address,
                                       transfer[1], False)

            if not result:
                # transaction failed? wallet probably out-of-sync (insufficient funds) so reload it
                self.wallet_needs_recovery = True
                # we need to try to process this transfer again, so add it back in to the list
                self.transfers_to_process = [transfer
                                             ] + self.transfers_to_process
            else:
                # transaction successfully relayed? then let's set the tx Hash that we're waiting for
                self.transfer_tx_processing = result.Hash
コード例 #18
0
from neo.Network.NodeLeader import NodeLeader
from twisted.internet import reactor, task
from neo.Core.Blockchain import Blockchain, Events
from neo.SmartContract.StateReader import StateReader
from neo.Implementations.Blockchains.LevelDB.LevelDBBlockchain import LevelDBBlockchain
from neo.Settings import settings
from neocore.Cryptography.Crypto import Crypto
from neocore.UInt160 import UInt160

import discord

client = discord.Client()

DISCORD_TOKEN = ''
CHANNEL_ID = ''
smart_contract = SmartContract('2d838efcda02e9b6bc42ce21ce34acad14b58923')


@smart_contract.on_notify
def sc_notify(event):
    if len(event.event_payload):
        #print("***** got new notify payload {}".format(event.event_payload[0]))
        if event.event_payload[0].decode("utf-8") == 'new_king':
            address = event.event_payload[1]
            bounty = int(event.event_payload[2])
            newKingMessage = ''
            if len(event.event_payload[3]) > 0:
                name = event.event_payload[3].decode("utf-8", "ignore")
                newKingMessage = '{} is now king. Next bounty is {} TUT'.format(
                    name, bounty / 100000000)
            else:
コード例 #19
0
# If you want to enable logging to a file, set the filename here:
LOGFILE = os.getenv("NEO_REST_LOGFILE", None)

# Internal: if LOGFILE is set, file logging will be setup with max
# 10 MB per file and 3 rotations:
if LOGFILE:
    settings.set_logfile(LOGFILE, max_bytes=1e7, backup_count=3)

# Internal: get the API token from an environment variable
API_AUTH_TOKEN = os.getenv("NEO_REST_API_TOKEN", None)
if not API_AUTH_TOKEN:
    raise Exception("No NEO_REST_API_TOKEN environment variable found!")

# Internal: setup the smart contract instance
smart_contract = SmartContract(SMART_CONTRACT_HASH)

# Internal: setup the klein instance
app = Klein()

# Internal: generate the @authenticated decorator with valid tokens
authenticated = gen_authenticated_decorator(API_AUTH_TOKEN)

#
# Smart contract event handler for Runtime.Notify events
#


@smart_contract.on_notify
def sc_notify(event):
    logger.info("SmartContract Runtime.Notify event: %s", event)
コード例 #20
0
from neo.contrib.smartcontract import SmartContract
from neo.Network.NodeLeader import NodeLeader
from neo.Core.Blockchain import Blockchain
from neo.Implementations.Blockchains.LevelDB.LevelDBBlockchain import LevelDBBlockchain
from neo.Settings import settings
from neocore.Cryptography.Crypto import Crypto, UInt160

from dotenv import load_dotenv
load_dotenv(os.path.abspath(os.path.join('.', '.env')))

# If you want the log messages to also be saved in a logfile, enable the
# next line. This configures a logfile with max 10 MB and 3 rotations:
# settings.set_logfile("/tmp/logfile.log", max_bytes=1e7, backup_count=3)

# Setup the smart contract instance
smart_contract = SmartContract("fdb94040d3578817cc9293f95b8ddae75d87ac57")


# Register an event handler for Runtime.Notify events of the smart contract.
@smart_contract.on_notify
def sc_notify(event):
    logger.info("SmartContract Runtime.Notify event: %s", event)

    # Make sure that the event payload list has at least one element.
    if not len(event.event_payload):
        return

    # The event payload list has at least one element. As developer of the smart contract
    # you should know what data-type is in the bytes, and how to decode it. In this example,
    # it's just a string, so we decode it with utf-8: