示例#1
0
    def post(self):

        try:

            address = self.get_argument("address")

            if len(address) != 34 or (not str(address).startswith('T')):
                raise Exception("invalid address")

            trx = Trx(
                Tron(full_node=TRON_RPC_URL,
                     solidity_node=TRON_RPC_URL,
                     event_server=TRON_RPC_URL))

            account_info = trx.get_account(address=address)

            if 'balance' in account_info:
                decBalance = Decimal(
                    account_info['balance']) / Decimal('1000000')
                fmtBalance = str(
                    decBalance.quantize(Decimal("0.000000"),
                                        getattr(decimal, 'ROUND_DOWN')))
            else:
                fmtBalance = '0.000000'

            self.write(
                json.dumps(BaseHandler.success_ret_with_data(fmtBalance),
                           default=decimal_default))

            pass
        except Exception as e:
            self.write(
                json.dumps(BaseHandler.error_ret_with_data("error: %s" % e)))
            logging.error("error:{0} in {1}".format(e, get_linenumber()))
示例#2
0
    async def send_trx(self, from_address, private_key, to_address, amount):
        account = Tron(private_key=private_key, default_address=from_address)
        account_api = Trx(account)
        amount_sun = amount * 1e6
        tx = await self._request('POST',
                                 '/wallet/createtransaction',
                                 owner_address=self.to_hex(
                                     from_address.encode()),
                                 to_address=self.to_hex(to_address.encode()),
                                 amount=int(amount_sun))

        signed_tx = account_api.sign(tx)

        return await self._request('POST', '/wallet/broadcasttransaction',
                                   **signed_tx)
示例#3
0
    async def send_token(self, from_address, private_key, to_address, token_id,
                         amount):
        account = Tron(private_key=private_key, default_address=from_address)
        account_api = Trx(account)
        amount_sun = amount * 1e6

        tx = await self._request(
            'POST',
            '/wallet/transferasset',
            owner_address=self.to_hex(from_address.encode()),
            to_address=self.to_hex(to_address.encode()),
            amount=int(amount_sun),
            asset_name=codecs.encode(str(token_id).encode(), 'hex').decode())

        signed_tx = account_api.sign(tx)

        return await self._request('POST', '/wallet/broadcasttransaction',
                                   **signed_tx)
示例#4
0
    def post(self):

        try:

            address = self.get_argument("address")

            if len(address) != 34 or (not str(address).startswith('T')):
                raise Exception("invalid address")

            trx = Trx(
                Tron(full_node=TRON_RPC_URL,
                     solidity_node=TRON_RPC_URL,
                     event_server=TRON_RPC_URL))

            account_info = trx.get_account(address=address)

            if 'balance' in account_info:
                decBalance = Decimal(
                    account_info['balance']) / Decimal('1000000')
                fmtBalance = decBalance.quantize(
                    Decimal("0.000000"), getattr(decimal, 'ROUND_DOWN'))
            else:
                fmtBalance = '0.000000'

            is_active = 'create_time' in account_info  #账户是否已经激活

            rsp_data = {
                'address': address,
                'balance': str(fmtBalance),
                'active': is_active
                #其他代币资产信息可以根据资产id进行获取, 如TRC20-USDT , 此是后话
            }

            logging.info(f'{rsp_data}')

            self.write(
                json.dumps(BaseHandler.success_ret_with_data(rsp_data),
                           default=decimal_default))

            pass
        except Exception as e:
            self.write(
                json.dumps(BaseHandler.error_ret_with_data("error: %s" % e)))
            logging.error("error:{0} in {1}".format(e, get_linenumber()))
示例#5
0
    def post(self):

        trx = Trx(
            Tron(full_node=TRON_RPC_URL,
                 solidity_node=TRON_RPC_URL,
                 event_server=TRON_RPC_URL))

        try:
            signed_trx = self.get_argument_from_json("data")
            order_id = self.get_argument_from_json("orderId")

            is_exist, txid, tx_json = self.get_order_from_db(order_id)
            if is_exist:
                self.write(
                    json.dumps(BaseHandler.success_ret_with_data(tx_json),
                               default=decimal_default))
                return

            signed_trx_jsonobj = json.loads(signed_trx)
            ret = trx.broadcast(signed_trx_jsonobj)

            if 'result' in ret and ret['result'] == True:
                self.write(
                    json.dumps(BaseHandler.success_ret_with_data(ret),
                               default=decimal_default))

                #如果广播成功, 则插入数据库
                if ret['result'] == True:
                    self.insert_txid_into_db(order_id=order_id,
                                             txid=ret['transaction']['txID'],
                                             tx_json_str=json.dumps(ret))
            else:
                errmsg = json.dumps(ret)
                self.write(json.dumps(BaseHandler.error_ret_with_data(errmsg)))

        except Exception as e:
            logging.error("TRX_SendRawTransaction: {}".format(e))
            self.write(
                json.dumps(BaseHandler.error_ret_with_data("error: %s" % e)))

        pass
示例#6
0
    def process(self, symbol: str = 'TRX') -> list:

        #每次只查部分地址, 以防http超时
        strSql = f"""SELECT  address FROM tb_trx_active_addrs WHERE `symbol`='{symbol}' AND `balance` >= 1 ORDER BY `balance` DESC LIMIT 25;"""
        sqlRet = sql.run(strSql)

        addrs = []
        for item in sqlRet:
            if "address" in item:
                if item['address'] not in addrs: addrs.append(item["address"])

        trx = Trx(
            Tron(full_node=TRON_RPC_URL,
                 solidity_node=TRON_RPC_URL,
                 event_server=TRON_RPC_URL))

        retList = []

        for addr in addrs:
            account_info = trx.get_account(address=addr)
            if 'balance' in account_info:
                decBalance = Decimal(
                    account_info['balance']) / Decimal('1000000')
                fmtBalance = decBalance.quantize(
                    Decimal("0.000000"), getattr(decimal, 'ROUND_DOWN'))
            else:
                fmtBalance = '0.000000'

            if Decimal(fmtBalance) < Decimal('1.0'):
                logging.info(
                    f"{addr}'s balance({fmtBalance}) is less than 1.0TRX,  skip it."
                )
                continue

            retList.append({
                'address': addr,
                'balance': str(fmtBalance),
                'symbol': symbol
            })

        return retList
示例#7
0
    def post(self):
        try:

            trx = Trx(
                Tron(full_node=TRON_RPC_URL,
                     solidity_node=TRON_RPC_URL,
                     event_server=TRON_RPC_URL))

            src_acct = self.get_argument("src_acct")
            dst_acct = self.get_argument("dst_acct")
            stramount = self.get_argument("amount")

            src_acct = src_acct.strip()
            dst_acct = dst_acct.strip()
            stramount = stramount.strip()

            if len(src_acct) != 34 or (not str(src_acct).startswith('T')):
                raise Exception("invalid src address")

            if len(dst_acct) != 34 or (not str(dst_acct).startswith('T')):
                raise Exception("invalid dst address")

            amount = float(stramount)

            tx = trx.tron.transaction_builder.send_transaction(
                to=dst_acct, amount=amount, account=src_acct)

            self.modify_expiration(tx)

            tx['signature'] = ['this_is_placeholder_for_signature']

            rsp_data = {
                'raw_trx_json_str': json.dumps(tx),
                'digest': tx['txID']
            }

            logging.info(f'{rsp_data}')

            self.write(
                json.dumps(BaseHandler.success_ret_with_data(rsp_data),
                           default=decimal_default))

            pass
        except Exception as e:
            logging.error("TRX_CreateRawTransaction: {}".format(e))
            self.write(
                json.dumps(BaseHandler.error_ret_with_data("error: %s" % e)))

        pass
示例#8
0
    def __init__(self):

        self.N_BLOCK_COUNT_EACH_TIME = 5

        self.tron = Tron(full_node=full_node,
                         solidity_node=solidity_node,
                         event_server=event_server)

        self.api = Trx(tron=self.tron)

        # self.connected = self.tron.is_connected()

        self.addrs = self._GetExDepositAddrsFromDB()
        logging.info("len(addrs) : {}".format(len(self.addrs)))

        #使用 dict提高查询速度
        self.hex_addrs = set()
        for addr in self.addrs:
            self.hex_addrs.add(
                str(self.tron.address.to_hex(address=addr)).lower())

        logging.info("hex_addr: {}".format(self.hex_addrs))

        pass
def main():
    logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
    logger = logging.getLogger()

    full_node = 'https://api.trongrid.io'
    solidity_node = 'https://api.trongrid.io'
    event_server = 'https://api.trongrid.io'



    privkey = "你的私钥"


    tron = Tron(full_node=full_node,
                solidity_node=solidity_node,
                event_server=event_server,
                private_key=privkey)


    trx = Trx(tron)


    from_addr = 'TPcUx2iwjomVzmX3CHDDYmnEPJFTVeyqqS'
    to_addr = 'TDUjsjJzQABwVv8DnLVDZ778uKQ7X5Fs7E'
    options = {
        'from' : from_addr
    }

    amount = float(0.123)

    # receipt = trx.send_transaction( to=to_addr, amount=amount, options=options )


    #构造交易
    tx = trx.tron.transaction_builder.send_transaction(
        to_addr,
        amount,
        options['from']
    )








    if  False:
        sign = trx.sign(tx)

        sleep(61)  # 休眠 61秒  广播时报错:  {'code': 'TRANSACTION_EXPIRATION_ERROR', 'message': 'transaction expired'}

        result = trx.broadcast(sign)
        pprint(result)

        return



    old_expiration_hex = my_encode_int64(tx['raw_data']['expiration'])

    #改变 raw_data.expiration,  增加一个小时
    tx['raw_data']['expiration'] +=  3600 * 1000

    new_expiration_hex = my_encode_int64(tx['raw_data']['expiration'])

    #也要改变  raw_data_hex 中相应的字段

    # tmp_hex = tx['raw_data_hex'][30:]
    # tx['raw_data_hex'] = tx['raw_data_hex'][0:30]



    raw_data_hex = str(tx['raw_data_hex'])
    index =  raw_data_hex.find(old_expiration_hex)
    logger.info( "index : {}".format( index) )

    new_raw_data_hex = raw_data_hex.replace(old_expiration_hex, new_expiration_hex)

    old_txid = hashlib.sha256( unhexlify( tx['raw_data_hex'] )).hexdigest()

    new_txid = hashlib.sha256( unhexlify( new_raw_data_hex) ).hexdigest()

    if old_txid == tx['txID'] :
        logger.info('txid 比对成功!')
    else:
        logger.info('txid比对失败!')

    tx['txID'] = new_txid


    sign = trx.sign(tx)


    my_sig = new_ecsign( unhexlify( new_txid), unhexlify( privkey) )

    logger.info( type(hexlify(my_sig)) )
    logger.info( type(sign['signature'][0] ))

    logger.info( "我的签名: {}".format( str(hexlify(my_sig), encoding='latin') ))

    logger.info("原始签名: {}".format( sign['signature'][0] ))

    if sign['signature'][0] == str(hexlify(my_sig), encoding='latin'):
        logger.info('签名对比成功!')
    else:
        logger.info('签名对比失败')



    sleep(61)  #休眠 61秒,  来测试修改 expiration的效果

    result = trx.broadcast(sign)
    pprint(result)

    #测试成功  txid为:  8c2b0a40812be8bcee3f92587e6824dc5a6035572cffe13707211821085ea7d3

    pass
示例#10
0
class TrxScanner(object):
    def __init__(self):

        self.N_BLOCK_COUNT_EACH_TIME = 5

        self.tron = Tron(full_node=full_node,
                         solidity_node=solidity_node,
                         event_server=event_server)

        self.api = Trx(tron=self.tron)

        # self.connected = self.tron.is_connected()

        self.addrs = self._GetExDepositAddrsFromDB()
        logging.info("len(addrs) : {}".format(len(self.addrs)))

        #使用 dict提高查询速度
        self.hex_addrs = set()
        for addr in self.addrs:
            self.hex_addrs.add(
                str(self.tron.address.to_hex(address=addr)).lower())

        logging.info("hex_addr: {}".format(self.hex_addrs))

        pass

    def _GetExDepositAddrsFromDB(self):
        try:
            sqlstr = """SELECT DISTINCT `address` from `tb_trx_deposit_addrs`;"""
            sql_result = sql.run(sqlstr)
            addrs = []
            for item in sql_result:
                if 'address' not in item: continue
                addrs.append(item['address'].strip())
            return addrs
        except Exception as e:
            logging.error(" _GetAddresses() error: {}".format(e))
            return []

    def _PushTxIntoDB(self, tx: dict):
        strSql = """INSERT INTO tb_trx_deposit(`txid`,`timestamp`,`from`,`to`,`amount`,`symbol`,`confirmations`, `block_number`) """
        strSql += f"""VALUES('{tx['txid']}',{tx['timestamp']},'{tx['from']}',
                            '{tx['to']}','{tx['amount']}','{tx['symbol']}',{tx['confirmations']}, {tx['blocknumber']}) """

        strSql += """ ON DUPLICATE KEY UPDATE `confirmations`={}; """.format(
            tx['confirmations'])
        logging.info("sql: {}  ".format(strSql))

        sqlRet = sql.run(strSql)

    def _UpdateActiveBalance(self, addr: str):

        account_info = self.api.get_account(address=addr)

        if 'balance' in account_info:
            decBalance = Decimal(account_info['balance']) / Decimal('1000000')
            fmtBalance = decBalance.quantize(Decimal("0.000000"),
                                             getattr(decimal, 'ROUND_DOWN'))
        else:
            fmtBalance = '0.000000'

        strSql = """INSERT INTO `tb_trx_active_addrs`(`symbol`, `address`, `balance`)"""
        strSql += f"""VALUES('TRX', '{addr}', {fmtBalance})"""
        strSql += """ON DUPLICATE KEY  UPDATE `balance`=VALUES(`balance`);"""

        logging.info("sql: {}  ".format(strSql))

        sqlRet = sql.run(strSql)

        pass

    def _GetDepositTrxsFromBlockRange(self, nStart: int, nEnd: int):

        logging.info("starting get block {} to {}".format(nStart, nEnd))

        #TODO: 可以增加 visible字段, 地址会以 Base58格式返回; 如果是代币, assetname会是代币名称
        blocks_info = self.api.get_block_range(start=nStart, end=nEnd)
        if not blocks_info:
            raise Exception("blocks_info is none")

        rettrxs = []

        for oneblock in blocks_info:

            try:
                if 'transactions' not in oneblock:
                    continue

                transactions = oneblock['transactions']
                for tx in transactions:
                    valueinfo = tx['raw_data']['contract'][0]['parameter'][
                        'value']

                    # 只包含   amount,  owner_address,  to_address
                    if len(valueinfo) != 3:
                        logging.info("valueinfo's length is not 3, pass it! ")
                        continue

                    if 'amount' not in valueinfo:
                        logging.info(
                            "amount not in valueinfo, it's not normal TRX transaction"
                        )
                        continue

                    dst_hex_addr = valueinfo['to_address']
                    src_hex_addr = valueinfo['owner_address']

                    # 如果from地址是交易所的地址(一般是归集操作)
                    if src_hex_addr in self.hex_addrs:
                        src_b58_addr = str(self.tron.address.from_hex(
                            valueinfo['owner_address']),
                                           encoding='utf8')
                        self._UpdateActiveBalance(addr=src_b58_addr)

                    if dst_hex_addr not in self.hex_addrs:
                        logging.info("addr {} is not exchange addr".format(
                            dst_hex_addr))
                        continue
                    else:  #如果目的地址是交易所的地址, 则跟新活跃地址表的余额, 方便后期归集
                        dst_b58_addr = str(
                            self.tron.address.from_hex(dst_hex_addr),
                            encoding='utf8')
                        self._UpdateActiveBalance(addr=dst_b58_addr)

                    src_b58_addr = str(
                        self.tron.address.from_hex(src_hex_addr),
                        encoding='utf8')
                    dst_b58_addr = str(
                        self.tron.address.from_hex(dst_hex_addr),
                        encoding='utf8')
                    txid = tx['txID']
                    blocknumber = oneblock['block_header']['raw_data'][
                        'number']
                    timestamp = int(tx['raw_data']['timestamp'] / 1000)

                    damount = Decimal(str(
                        valueinfo['amount'])) / Decimal('1000000')
                    stramount = damount.quantize(
                        Decimal("0.000000"), getattr(decimal, 'ROUND_DOWN'))

                    successed = ("SUCCESS" == tx['ret'][0]['contractRet'])
                    if not successed:
                        logging.info("tx {} is not successed tx".format(txid))
                        continue

                    txinfo = {
                        'txid': txid,
                        'to': dst_b58_addr,
                        'from': src_b58_addr,
                        'amount': stramount,
                        'timestamp': timestamp,
                        'blocknumber': blocknumber,
                        'confirmations': 100,
                        'symbol': 'TRX'
                    }

                    logging.info('found a deposit tx: {}'.format(txinfo))

                    rettrxs.append(txinfo)

            except Exception as e:
                logging.error(e)
                continue

        return rettrxs

    def __GetScanStartBlock(self, strCoinType):
        """
        从数据库中获取币种的 扫描的起始区块
        """

        #类型判断
        assert (isinstance(strCoinType, str))

        #对参数进行检查
        #注意sql注入
        strType = strCoinType.lower()
        sqlRet = sql.run(
            """SELECT start_block FROM t_scan_start WHERE coin_type='{0}';""".
            format(strType))
        if len(sqlRet) > 0:
            item = sqlRet[0]
            if 'start_block' in item:
                nRet = int(str(item['start_block']), 10)
                return nRet
        return 0

    def __GetLatestBlockNumber(self):
        while True:
            try:
                block = self.api.get_current_block()
                number = block['block_header']['raw_data']['number']
                return number
            except Exception as e:
                logging.error("{},  will try again".format(e))

    def StartScan(self):

        nLatestestBlock = self.__GetLatestBlockNumber()
        nStartBlock = self.__GetScanStartBlock('trx')

        # for n in range(nStartBlock, nLatestestBlock + 1):
        n = nStartBlock

        while n < nLatestestBlock + 1:

            nTmpEnd = n + self.N_BLOCK_COUNT_EACH_TIME if n + self.N_BLOCK_COUNT_EACH_TIME <= nLatestestBlock + 1 else nLatestestBlock + 1

            txs = self._GetDepositTrxsFromBlockRange(n, nTmpEnd)

            for tx in txs:
                self._PushTxIntoDB(tx)

            # 保存本次扫描的结束区块高度
            strSql = """update t_scan_start set start_block={0} where coin_type='{1}';""".format(
                nTmpEnd - 1, 'trx')
            logging.info("sql : {}".format(strSql))
            sql.run(strSql)

            n = nTmpEnd

        pass