Esempio n. 1
0
    def post(self, request):
        print("enter wallet send")
        try:
            data = JSONParser().parse(request)
            wallet_id = data.get('wallet_id')
            address = data.get('address')
            amount = data.get('amount')
            print('wallet_id ' + str(wallet_id))
            print('address ' + str(address))
            '''
            print('wallet starts')
            srv = BitcoindClient()
            print(srv.getutxos('1CRkjhJgWC6tPNdfqnXRgYDPniSScHenuP'))
            print('bitcoin fee created')
            '''

            wallet = HDWallet(wallet_id, db_uri=db_uri)
            print(' wallet.username ',
                  wallet.key_for_path('m/44\'/0\'/1\'/0/0'))

            user = User.objects.filter(username=wallet.username)
            print('user', user)
            if user.count() > 0:
                user = user[0]
                print('wallets  ', wallet, ' user_id ', user.user_id)

                from_wallet_key = wallet.key(wallet.name)
                print('from wallet key', from_wallet_key.key_id)
                print('to wallet key as same ', wallet.key(address))

                # print('performing txn update  update db')
                # wallet.transactions_update(account_id=user.user_id,key_id=from_wallet.key_id)

                utx = wallet.utxos_update(account_id=user.user_id)
                wallet.info()
                wallet.get_key()
                print('key change', wallet.get_key_change())
                utxos = wallet.utxos(account_id=user.user_id)
                res = wallet.send_to(address, amount)
                print("Send transaction result:")
                if res.hash:
                    print("Successfully send, tx id:", res.hash)
                else:
                    print("TX not send, result:", res.errors)

                return JsonResponse(res.as_dict(), safe=False)

        except Exception as e:
            track = traceback.format_exc()
            logger.exception(track)
            raise e
Esempio n. 2
0
        raise ValueError(
            "Number of cosigners (%d) is different then expected. SIG_N=%d" %
            (len(key_list), SIGS_N))
    wallet3o5 = HDWallet.create_multisig(WALLET_NAME,
                                         key_list,
                                         SIGS_REQUIRED,
                                         sort_keys=True,
                                         network=NETWORK)
    wallet3o5.new_key()

    print("\n\nA multisig wallet with 1 key has been created on this system")
else:
    wallet3o5 = HDWallet(WALLET_NAME)

print("\nUpdating UTXO's...")
wallet3o5.utxos_update()
wallet3o5.info()
utxos = wallet3o5.utxos()

# Creating transactions just like in a normal wallet, then send raw transaction to other cosigners. They
# can sign the transaction with there on key and pass it on to the next signer or broadcast it to the network.
# You can use sign_raw.py to import and sign a raw transaction.

# Example
# if utxos:
#     print("\nNew unspent outputs found!")
#     print("Now a new transaction will be created to sweep this wallet and send bitcoins to a testnet faucet")
#     send_to_address = 'mv4rnyY3Su5gjcDNzbMLKBQkBicCtHUtFB'
#     res = wallet3o5.sweep(send_to_address, min_confirms=0)
#     if 'transaction' in res:
#         print("Now send the raw transaction hex to one of the other cosigners to sign using sign_raw.py")
Esempio n. 3
0
def main():
    print("Command Line Wallet for BitcoinLib\n")
    # --- Parse commandline arguments ---
    args = parse_args()

    databasefile = DEFAULT_DATABASE
    if args.database:
        databasefile = os.path.join(BCL_DATABASE_DIR, args.database)

    if args.generate_key:
        passphrase = get_passphrase(args)
        passphrase = ' '.join(passphrase)
        seed = binascii.hexlify(Mnemonic().to_seed(passphrase))
        hdkey = HDKey.from_seed(seed, network=args.network)
        print(
            "Private master key, to create multisig wallet on this machine: %s"
            % hdkey.wif())
        print(
            "Public account key, to share with other cosigner multisig wallets: %s"
            %
            hdkey.public_master(witness_type=args.witness_type, multisig=True))
        print("Network: %s" % hdkey.network.name)
        clw_exit()

    # List wallets, then exit
    if args.list_wallets:
        print("BitcoinLib wallets:")
        for w in wallets_list(databasefile=databasefile):
            if 'parent_id' in w and w['parent_id']:
                continue
            print("[%d] %s (%s) %s" %
                  (w['id'], w['name'], w['network'], w['owner']))
        clw_exit()

    # Delete specified wallet, then exit
    if args.wallet_remove:
        if not wallet_exists(args.wallet_name, databasefile=databasefile):
            clw_exit("Wallet '%s' not found" % args.wallet_name)
        inp = input(
            "\nWallet '%s' with all keys and will be removed, without private key it cannot be restored."
            "\nPlease retype exact name of wallet to proceed: " %
            args.wallet_name)
        if inp == args.wallet_name:
            if wallet_delete(args.wallet_name,
                             force=True,
                             databasefile=databasefile):
                clw_exit("\nWallet %s has been removed" % args.wallet_name)
            else:
                clw_exit("\nError when deleting wallet")
        else:
            clw_exit("\nSpecified wallet name incorrect")

    wlt = None
    if args.wallet_name and not args.wallet_name.isdigit(
    ) and not wallet_exists(args.wallet_name, databasefile=databasefile):
        if not args.create_from_key and input(
                "Wallet %s does not exist, create new wallet [yN]? " %
                args.wallet_name).lower() != 'y':
            clw_exit('Aborted')
        wlt = create_wallet(args.wallet_name, args, databasefile)
        args.wallet_info = True
    else:
        try:
            wlt = HDWallet(args.wallet_name, databasefile=databasefile)
            if args.passphrase is not None:
                print(
                    "WARNING: Using passphrase option for existing wallet ignored"
                )
            if args.create_from_key is not None:
                print(
                    "WARNING: Using create_from_key option for existing wallet ignored"
                )
        except WalletError as e:
            clw_exit("Error: %s" % e.msg)

    if wlt is None:
        clw_exit("Could not open wallet %s" % args.wallet_name)

    if args.import_private:
        if wlt.import_key(args.import_private):
            clw_exit("Private key imported")
        else:
            clw_exit("Failed to import key")

    if args.wallet_recreate:
        wallet_empty(args.wallet_name)
        print("Removed transactions and generated keys from this wallet")
    if args.update_utxos:
        wlt.utxos_update()
    if args.update_transactions:
        wlt.scan(scan_gap_limit=5)

    if args.export_private:
        if wlt.scheme == 'multisig':
            for w in wlt.cosigner:
                if w.main_key and w.main_key.is_private:
                    print(w.main_key.wif)
        elif not wlt.main_key or not wlt.main_key.is_private:
            print("No private key available for this wallet")
        else:
            print(wlt.main_key.wif)
        clw_exit()

    if args.network is None:
        args.network = wlt.network.name

    tx_import = None
    if args.import_tx_file:
        try:
            fn = args.import_tx_file
            f = open(fn, "r")
        except FileNotFoundError:
            clw_exit("File %s not found" % args.import_tx_file)
        try:
            tx_import = ast.literal_eval(f.read())
        except (ValueError, SyntaxError):
            tx_import = f.read()
    if args.import_tx:
        try:
            tx_import = ast.literal_eval(args.import_tx)
        except (ValueError, SyntaxError):
            tx_import = args.import_tx
    if tx_import:
        if isinstance(tx_import, dict):
            wt = wlt.transaction_import(tx_import)
        else:
            wt = wlt.transaction_import_raw(tx_import, network=args.network)
        wt.sign()
        if args.push:
            res = wt.send()
            if res:
                print("Transaction pushed to network. Transaction ID: %s" %
                      wt.hash)
            else:
                print("Error creating transaction: %s" % wt.error)
        wt.info()
        print("Signed transaction:")
        print_transaction(wt)
        clw_exit()

    if args.receive:
        keys = wlt.get_key(network=args.network, number_of_keys=args.receive)
        if args.receive != 1:
            keys += wlt.get_key_change(network=args.network,
                                       number_of_keys=args.receive)
        keys = [keys] if not isinstance(keys, list) else keys
        print("Receive address(es):")
        for key in keys:
            addr = key.address
            print(addr)
            if QRCODES_AVAILABLE and args.receive == 1:
                qrcode = pyqrcode.create(addr)
                print(qrcode.terminal())
        if not QRCODES_AVAILABLE and args.receive == 1:
            print(
                "Install qr code module to show QR codes: pip install pyqrcode"
            )
        clw_exit()
    if args.create_transaction == []:
        clw_exit("Missing arguments for --create-transaction/-t option")
    if args.create_transaction:
        if args.fee_per_kb:
            clw_exit("Fee-per-kb option not allowed with --create-transaction")
        try:
            wt = create_transaction(wlt, args.create_transaction, args)
        except WalletError as e:
            clw_exit("Cannot create transaction: %s" % e.msg)
        wt.sign()
        print("Transaction created")
        wt.info()
        if args.push:
            wt.send()
            if wt.pushed:
                print("Transaction pushed to network. Transaction ID: %s" %
                      wt.hash)
            else:
                print("Error creating transaction: %s" % wt.error)
        else:
            print(
                "\nTransaction created but not send yet. Transaction dictionary for export: "
            )
            print_transaction(wt)
        clw_exit()
    if args.sweep:
        if args.fee:
            clw_exit("Fee option not allowed with --sweep")
        offline = True
        print("Sweep wallet. Send all funds to %s" % args.sweep)
        if args.push:
            offline = False
        wt = wlt.sweep(args.sweep,
                       offline=offline,
                       network=args.network,
                       fee_per_kb=args.fee_per_kb)
        if not wt:
            clw_exit(
                "Error occurred when sweeping wallet: %s. Are UTXO's available and updated?"
                % wt)
        wt.info()
        if args.push:
            if wt.pushed:
                print("Transaction pushed to network. Transaction ID: %s" %
                      wt.hash)
            elif not wt:
                print("Cannot sweep wallet, are UTXO's updated and available?")
            else:
                print("Error sweeping wallet: %s" % wt.error)
        else:
            print(
                "\nTransaction created but not send yet. Transaction dictionary for export: "
            )
            print_transaction(wt)
        clw_exit()

    # print("Updating wallet")
    if args.network == 'bitcoinlib_test':
        wlt.utxos_update()
    print("Wallet info for %s" % wlt.name)
    wlt.info()
Esempio n. 4
0
class BitcoinWallet(Wallet):
    """
    This class is responsible for handling your wallet of bitcoins.

    NOTE: all imports of bitcoinlib should be local. The reason for this is that we are patching the bitcoinlib_main
          method in the __init__ method of the class (since we need access to the Tribler state directory) and
          we can only import bitcoinlib *after* patching the bitcoinlib main file.
    """
    TESTNET = False

    def __init__(self, wallet_dir):
        super(BitcoinWallet, self).__init__()

        bitcoinlib_main.initialize_lib(wallet_dir)
        from bitcoinlib.wallets import wallet_exists, HDWallet

        self.network = 'testnet' if self.TESTNET else 'bitcoin'
        self.wallet_dir = wallet_dir
        self.min_confirmations = 0
        self.wallet = None
        self.unlocked = True
        self.db_path = os.path.join(wallet_dir, 'wallets.sqlite')
        self.wallet_name = 'tribler_testnet' if self.TESTNET else 'tribler'

        if wallet_exists(self.wallet_name, databasefile=self.db_path):
            self.wallet = HDWallet(self.wallet_name, databasefile=self.db_path)
            self.created = True

    def get_name(self):
        return 'Bitcoin'

    def get_identifier(self):
        return 'BTC'

    def create_wallet(self):
        """
        Create a new bitcoin wallet.
        """
        from bitcoinlib.wallets import wallet_exists, HDWallet, WalletError

        if wallet_exists(self.wallet_name, databasefile=self.db_path):
            return fail(
                RuntimeError(
                    f"Bitcoin wallet with name {self.wallet_name} already exists."
                ))

        self._logger.info("Creating wallet in %s", self.wallet_dir)
        try:
            self.wallet = HDWallet.create(self.wallet_name,
                                          network=self.network,
                                          databasefile=self.db_path)
            self.wallet.new_key('tribler_payments')
            self.wallet.new_key('tribler_change', change=1)
            self.created = True
        except WalletError as exc:
            self._logger.error("Cannot create BTC wallet!")
            return fail(exc)
        return succeed(None)

    def get_balance(self):
        """
        Return the balance of the wallet.
        """
        if self.created:
            self.wallet.utxos_update(networks=self.network)
            return succeed({
                "available":
                self.wallet.balance(network=self.network),
                "pending":
                0,
                "currency":
                'BTC',
                "precision":
                self.precision()
            })

        return succeed({
            "available": 0,
            "pending": 0,
            "currency": 'BTC',
            "precision": self.precision()
        })

    async def transfer(self, amount, address):
        balance = await self.get_balance()

        if balance['available'] >= int(amount):
            self._logger.info(
                "Creating Bitcoin payment with amount %f to address %s",
                amount, address)
            tx = self.wallet.send_to(address, int(amount))
            return str(tx.hash)
        raise InsufficientFunds("Insufficient funds")

    def monitor_transaction(self, txid):
        """
        Monitor a given transaction ID. Returns a Deferred that fires when the transaction is present.
        """
        monitor_future = Future()

        async def monitor():
            transactions = await self.get_transactions()
            for transaction in transactions:
                if transaction['id'] == txid:
                    self._logger.debug("Found transaction with id %s", txid)
                    monitor_future.set_result(None)
                    monitor_task.cancel()

        self._logger.debug("Start polling for transaction %s", txid)
        monitor_task = self.register_task(f"btc_poll_{txid}",
                                          monitor,
                                          interval=5)

        return monitor_future

    def get_address(self):
        if not self.created:
            return ''
        return self.wallet.keys(name='tribler_payments',
                                is_active=False)[0].address

    def get_transactions(self):
        if not self.created:
            return succeed([])

        from bitcoinlib.transactions import Transaction
        from bitcoinlib.wallets import DbTransaction, DbTransactionInput

        # Update all transactions
        self.wallet.transactions_update(network=self.network)

        txs = self.wallet._session.query(DbTransaction.raw, DbTransaction.confirmations,
                                         DbTransaction.date, DbTransaction.fee)\
            .filter(DbTransaction.wallet_id == self.wallet.wallet_id)\
            .all()
        transactions = []

        for db_result in txs:
            transaction = Transaction.import_raw(db_result[0],
                                                 network=self.network)
            transaction.confirmations = db_result[1]
            transaction.date = db_result[2]
            transaction.fee = db_result[3]
            transactions.append(transaction)

        # Sort them based on locktime
        transactions.sort(key=lambda tx: tx.locktime, reverse=True)

        my_keys = [
            key.address
            for key in self.wallet.keys(network=self.network, is_active=False)
        ]

        transactions_list = []
        for transaction in transactions:
            value = 0
            input_addresses = []
            output_addresses = []
            for tx_input in transaction.inputs:
                input_addresses.append(tx_input.address)
                if tx_input.address in my_keys:
                    # At this point, we do not have the value of the input so we should do a database query for it
                    db_res = self.wallet._session.query(
                        DbTransactionInput.value).filter(
                            hexlify(tx_input.prev_hash) ==
                            DbTransactionInput.prev_hash, tx_input.output_n_int
                            == DbTransactionInput.output_n).all()
                    if db_res:
                        value -= db_res[0][0]

            for tx_output in transaction.outputs:
                output_addresses.append(tx_output.address)
                if tx_output.address in my_keys:
                    value += tx_output.value

            transactions_list.append({
                'id':
                transaction.hash,
                'outgoing':
                value < 0,
                'from':
                ','.join(input_addresses),
                'to':
                ','.join(output_addresses),
                'amount':
                abs(value),
                'fee_amount':
                transaction.fee,
                'currency':
                'BTC',
                'timestamp':
                time.mktime(transaction.date.timetuple()),
                'description':
                f'Confirmations: {transaction.confirmations}'
            })

        return succeed(transactions_list)

    def min_unit(self):
        return 100000  # The minimum amount of BTC we can transfer in this market is 1 mBTC (100000 Satoshi)

    def precision(self):
        return 8
Esempio n. 5
0
class BitcoinWallet(Wallet):
    """
    This class is responsible for handling your wallet of bitcoins.

    NOTE: all imports of bitcoinlib should be local. The reason for this is that we are patching the bitcoinlib_main
          method in the __init__ method of the class (since we need access to the Tribler state directory) and
          we can only import bitcoinlib *after* patching the bitcoinlib main file.
    """
    TESTNET = False

    def __init__(self, wallet_dir):
        super(BitcoinWallet, self).__init__()

        bitcoinlib_main.initialize_lib(wallet_dir)
        from bitcoinlib.wallets import wallet_exists, HDWallet

        self.network = 'testnet' if self.TESTNET else 'bitcoin'
        self.wallet_dir = wallet_dir
        self.min_confirmations = 0
        self.wallet = None
        self.unlocked = True
        self.db_path = os.path.join(wallet_dir, 'wallets.sqlite')
        self.wallet_name = 'tribler_testnet' if self.TESTNET else 'tribler'

        if wallet_exists(self.wallet_name, databasefile=self.db_path):
            self.wallet = HDWallet(self.wallet_name, databasefile=self.db_path)
            self.created = True

    def get_name(self):
        return 'Bitcoin'

    def get_identifier(self):
        return 'BTC'

    def create_wallet(self):
        """
        Create a new bitcoin wallet.
        """
        from bitcoinlib.wallets import wallet_exists, HDWallet, WalletError

        if wallet_exists(self.wallet_name, databasefile=self.db_path):
            return fail(RuntimeError("Bitcoin wallet with name %s already exists." % self.wallet_name))

        self._logger.info("Creating wallet in %s", self.wallet_dir)
        try:
            self.wallet = HDWallet.create(self.wallet_name, network=self.network, databasefile=self.db_path)
            self.wallet.new_key('tribler_payments')
            self.wallet.new_key('tribler_change', change=1)
            self.created = True
        except WalletError as exc:
            self._logger.error("Cannot create BTC wallet!")
            return fail(Failure(exc))
        return succeed(None)

    def get_balance(self):
        """
        Return the balance of the wallet.
        """
        if self.created:
            self.wallet.utxos_update(networks=self.network)
            return succeed({
                "available": self.wallet.balance(network=self.network),
                "pending": 0,
                "currency": 'BTC',
                "precision": self.precision()
            })

        return succeed({"available": 0, "pending": 0, "currency": 'BTC', "precision": self.precision()})

    def transfer(self, amount, address):
        def on_balance(balance):
            if balance['available'] >= int(amount):
                self._logger.info("Creating Bitcoin payment with amount %f to address %s", amount, address)
                tx = self.wallet.send_to(address, int(amount))
                return str(tx.hash)
            else:
                return fail(InsufficientFunds("Insufficient funds"))

        return self.get_balance().addCallback(on_balance)

    def monitor_transaction(self, txid):
        """
        Monitor a given transaction ID. Returns a Deferred that fires when the transaction is present.
        """
        monitor_deferred = Deferred()

        @inlineCallbacks
        def monitor_loop():
            transactions = yield self.get_transactions()
            for transaction in transactions:
                if transaction['id'] == txid:
                    self._logger.debug("Found transaction with id %s", txid)
                    monitor_deferred.callback(None)
                    monitor_lc.stop()

        self._logger.debug("Start polling for transaction %s", txid)
        monitor_lc = self.register_task("btc_poll_%s" % txid, LoopingCall(monitor_loop))
        monitor_lc.start(5)

        return monitor_deferred

    def get_address(self):
        if not self.created:
            return ''
        return self.wallet.keys(name='tribler_payments', is_active=False)[0].address

    def get_transactions(self):
        if not self.created:
            return succeed([])

        from bitcoinlib.transactions import Transaction
        from bitcoinlib.wallets import DbTransaction, DbTransactionInput

        # Update all transactions
        self.wallet.transactions_update(network=self.network)

        txs = self.wallet._session.query(DbTransaction.raw, DbTransaction.confirmations,
                                         DbTransaction.date, DbTransaction.fee)\
            .filter(DbTransaction.wallet_id == self.wallet.wallet_id)\
            .all()
        transactions = []

        for db_result in txs:
            transaction = Transaction.import_raw(db_result[0], network=self.network)
            transaction.confirmations = db_result[1]
            transaction.date = db_result[2]
            transaction.fee = db_result[3]
            transactions.append(transaction)

        # Sort them based on locktime
        transactions.sort(key=lambda tx: tx.locktime, reverse=True)

        my_keys = [key.address for key in self.wallet.keys(network=self.network, is_active=False)]

        transactions_list = []
        for transaction in transactions:
            value = 0
            input_addresses = []
            output_addresses = []
            for tx_input in transaction.inputs:
                input_addresses.append(tx_input.address)
                if tx_input.address in my_keys:
                    # At this point, we do not have the value of the input so we should do a database query for it
                    db_res = self.wallet._session.query(DbTransactionInput.value).filter(
                        hexlify(tx_input.prev_hash) == DbTransactionInput.prev_hash,
                        tx_input.output_n_int == DbTransactionInput.output_n).all()
                    if db_res:
                        value -= db_res[0][0]

            for tx_output in transaction.outputs:
                output_addresses.append(tx_output.address)
                if tx_output.address in my_keys:
                    value += tx_output.value

            transactions_list.append({
                'id': transaction.hash,
                'outgoing': value < 0,
                'from': ','.join(input_addresses),
                'to': ','.join(output_addresses),
                'amount': abs(value),
                'fee_amount': transaction.fee,
                'currency': 'BTC',
                'timestamp': time.mktime(transaction.date.timetuple()),
                'description': 'Confirmations: %d' % transaction.confirmations
            })

        return succeed(transactions_list)

    def min_unit(self):
        return 100000  # The minimum amount of BTC we can transfer in this market is 1 mBTC (100000 Satoshi)

    def precision(self):
        return 8
Esempio n. 6
0
from bitcoinlib.mnemonic import Mnemonic
from bitcoinlib.keys import HDKey
try:
    input = raw_input
except NameError:
    pass

WALLET_NAME = "Multisig_3of5"

wlt = HDWallet(WALLET_NAME)

# If you want to sign on an offline PC, export utxo dictionary to offline PC
# utxos = {...}
# wlt.utxos_update(utxos=utxos)

wlt.utxos_update()
wlt.info()

# Paste your raw transaction here or enter in default input
raw_tx = ''
if not raw_tx:
    raw_tx = input("Paste raw transaction hex: ")

passphrase = input("Enter passphrase: ")
password = input("Enter password []:")
seed = Mnemonic().to_seed(passphrase, password)
hdkey = HDKey.from_seed(seed, network=wlt.network.network_name)

t = wlt.transaction_import_raw(raw_tx)
t.sign(hdkey)
Esempio n. 7
0
            print("     HDKey('%s', key_type='single', witness_type='%s')" %
                  (key.wif_private(), WITNESS_TYPE))
        else:
            print("     '%s'," % key.wif_private())
    print("]")
    print(
        "wlt = HDWallet.create('%s', key_list, sigs_required=2, witness_type='%s', network='%s')"
        % (WALLET_NAME, WITNESS_TYPE, NETWORK))
    print("wlt.get_key()")
    print("wlt.info()")
else:
    from bitcoinlib.config.config import BITCOINLIB_VERSION, BCL_DATABASE_DIR
    online_wallet = HDWallet(WALLET_NAME,
                             db_uri=BCL_DATABASE_DIR +
                             '/bitcoinlib.tmp.sqlite')
    online_wallet.utxos_update()
    online_wallet.info()
    utxos = online_wallet.utxos()
    if utxos:
        print("\nNew unspent outputs found!")
        print(
            "Now a new transaction will be created to sweep this wallet and send bitcoins to a testnet faucet"
        )
        send_to_address = 'n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi'
        t = online_wallet.sweep(send_to_address, min_confirms=0)
        print(t.raw_hex())
        print(
            "Now copy-and-paste the raw transaction hex to your Offline PC and sign it there with a second signature:"
        )
        print("\nfrom bitcoinlib.wallets import HDWallet")
        print("")
Esempio n. 8
0
class BitcoinWallet(Wallet):
    """
    This class is responsible for handling your wallet of bitcoins.
    """
    TESTNET = False

    def __init__(self, wallet_dir):
        super(BitcoinWallet, self).__init__()

        self.network = 'testnet' if self.TESTNET else 'bitcoin'
        self.wallet_dir = wallet_dir
        self.min_confirmations = 0
        self.wallet = None
        self.unlocked = True
        self.db_path = os.path.join(wallet_dir, 'wallets.sqlite')
        self.wallet_name = 'tribler_testnet' if self.TESTNET else 'tribler'

        if wallet_exists(self.wallet_name, databasefile=self.db_path):
            self.wallet = HDWallet(self.wallet_name, databasefile=self.db_path)
            self.created = True

    def get_name(self):
        return 'Bitcoin'

    def get_identifier(self):
        return 'BTC'

    def create_wallet(self):
        """
        Create a new bitcoin wallet.
        """
        self._logger.info("Creating wallet in %s", self.wallet_dir)
        try:
            self.wallet = HDWallet.create(self.wallet_name, network=self.network, databasefile=self.db_path)
            self.wallet.new_key('tribler_payments')
            self.wallet.new_key('tribler_change', change=1)
            self.created = True
        except WalletError as exc:
            self._logger.error("Cannot create BTC wallet!")
            return fail(Failure(exc))
        return succeed(None)

    def get_balance(self):
        """
        Return the balance of the wallet.
        """
        if self.created:
            self.wallet.utxos_update(networks=self.network)
            return succeed({
                "available": self.wallet.balance(network=self.network),
                "pending": 0,
                "currency": 'BTC',
                "precision": self.precision()
            })

        return succeed({"available": 0, "pending": 0, "currency": 'BTC', "precision": self.precision()})

    def transfer(self, amount, address):
        def on_balance(balance):
            if balance['available'] >= amount:
                self._logger.info("Creating Bitcoin payment with amount %f to address %s", amount, address)
                tx = self.wallet.send_to(address, int(amount))
                return str(tx.hash)
            else:
                return fail(InsufficientFunds())

        return self.get_balance().addCallback(on_balance)

    def monitor_transaction(self, txid):
        """
        Monitor a given transaction ID. Returns a Deferred that fires when the transaction is present.
        """
        monitor_deferred = Deferred()

        @inlineCallbacks
        def monitor_loop():
            transactions = yield self.get_transactions()
            for transaction in transactions:
                if transaction['id'] == txid:
                    self._logger.debug("Found transaction with id %s", txid)
                    monitor_deferred.callback(None)
                    monitor_lc.stop()

        self._logger.debug("Start polling for transaction %s", txid)
        monitor_lc = self.register_task("btc_poll_%s" % txid, LoopingCall(monitor_loop))
        monitor_lc.start(5)

        return monitor_deferred

    def get_address(self):
        if not self.created:
            return ''
        return self.wallet.keys(name='tribler_payments', is_active=False)[0].address

    def get_transactions(self):
        if not self.created:
            return succeed([])

        # Update all transactions
        self.wallet.transactions_update(network=self.network)

        txs = self.wallet._session.query(DbTransaction.raw, DbTransaction.confirmations,
                                         DbTransaction.date, DbTransaction.fee)\
            .filter(DbTransaction.wallet_id == self.wallet.wallet_id)\
            .all()
        transactions = []

        for db_result in txs:
            transaction = Transaction.import_raw(db_result[0], network=self.network)
            transaction.confirmations = db_result[1]
            transaction.date = db_result[2]
            transaction.fee = db_result[3]
            transactions.append(transaction)

        # Sort them based on locktime
        transactions.sort(key=lambda tx: tx.locktime, reverse=True)

        my_keys = [key.address for key in self.wallet.keys(network=self.network, is_active=False)]

        transactions_list = []
        for transaction in transactions:
            value = 0
            input_addresses = []
            output_addresses = []
            for tx_input in transaction.inputs:
                input_addresses.append(tx_input.address)
                if tx_input.address in my_keys:
                    # At this point, we do not have the value of the input so we should do a database query for it
                    db_res = self.wallet._session.query(DbTransactionInput.value).filter(
                        tx_input.prev_hash.encode('hex') == DbTransactionInput.prev_hash,
                        tx_input.output_n_int == DbTransactionInput.output_n).all()
                    if db_res:
                        value -= db_res[0][0]

            for tx_output in transaction.outputs:
                output_addresses.append(tx_output.address)
                if tx_output.address in my_keys:
                    value += tx_output.value

            transactions_list.append({
                'id': transaction.hash,
                'outgoing': value < 0,
                'from': ','.join(input_addresses),
                'to': ','.join(output_addresses),
                'amount': abs(value),
                'fee_amount': transaction.fee,
                'currency': 'BTC',
                'timestamp': time.mktime(transaction.date.timetuple()),
                'description': 'Confirmations: %d' % transaction.confirmations
            })

        return succeed(transactions_list)

    def min_unit(self):
        return 100000  # The minimum amount of BTC we can transfer in this market is 1 mBTC (100000 Satoshi)

    def precision(self):
        return 8
Esempio n. 9
0
    name='Wallet Error',
    db_uri=test_database)
try:
    w.import_key(key='T43gB4F6k1Ly3YWbMuddq13xLb56hevUDP3RthKArr7FPHjQiXpp', network='litecoin')
except WalletError as e:
    print("Import litecoin key in bitcoin wallet gives an EXPECTED error: %s" % e)

print("\n=== Normalize BIP32 key path ===")
key_path = "m/44h/1'/0p/2000/1"
print("Raw: %s, Normalized: %s" % (key_path, normalize_path(key_path)))

print("\n=== Send test bitcoins to an address ===")
wallet_import = HDWallet('TestNetWallet', db_uri=test_database)
for _ in range(10):
    wallet_import.new_key()
wallet_import.utxos_update(99)
wallet_import.info()
utxos = wallet_import.utxos(99)
try:
    res = wallet_import.send_to('mxdLD8SAGS9fe2EeCXALDHcdTTbppMHp8N', 1000, 99)
    print("Send transaction result:")
    if res.hash:
        print("Successfully send, tx id:", res.hash)
    else:
        print("TX not send, result:", res.errors)
except WalletError as e:
    print("TX not send, error: %s" % e.msg)
except Exception as e:
    print(e)

#
Esempio n. 10
0
    print("from bitcoinlib.wallets import HDWallet")
    print("from bitcoinlib.keys import HDKey")
    print("")
    print("key_list = [")
    print("    '%s'," % key_list[0].account_multisig_key().wif_public())
    print("    '%s'," % key_list[1].wif())
    print("    HDKey('%s', key_type='single')" % key_list[2].wif_public())
    print("]")
    print(
        "wlt = HDWallet.create_multisig('%s', key_list, 2, sort_keys=True, network='%s')"
        % (WALLET_NAME, NETWORK))
    print("wlt.new_key()")
    print("wlt.info()")
else:
    thispc_wallet = HDWallet(WALLET_NAME)
    thispc_wallet.utxos_update()
    thispc_wallet.info()
    utxos = thispc_wallet.utxos()
    if utxos:
        print("\nNew unspent outputs found!")
        print(
            "Now a new transaction will be created to sweep this wallet and send bitcoins to a testnet faucet"
        )
        send_to_address = 'n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi'
        res = thispc_wallet.sweep(send_to_address, min_confirms=0)

        assert 'transaction' in res
        print(
            "Now copy-and-paste the raw transaction hex to your Other PC and sign it there with a second signature:"
        )
        print("\nfrom bitcoinlib.wallets import HDWallet")
class BitcoinlibWallet(Wallet):
    """
    Superclass used for the implementation of bitcoinlib wallets.
    """

    def __init__(self, wallet_dir, testnet, network, currency):
        if network not in SUPPORTED_NETWORKS:
            raise UnsupportedNetwork(network)

        super(BitcoinlibWallet, self).__init__()

        self.network = network
        self.wallet_name = f'tribler_{self.network}'
        self.testnet = testnet
        self.unlocked = True

        self.currency = currency
        self.wallet_dir = wallet_dir
        self.min_confirmations = 0
        self.wallet = None
        self.db_path = os.path.join(wallet_dir, 'wallets.sqlite')

        if wallet_exists(self.wallet_name, db_uri=self.db_path):
            self.wallet = HDWallet(self.wallet_name, db_uri=self.db_path)
            self.created = True

        self.lib_init()

    def cfg_init(self):
        """
        Adjusts the bitcoinlib configuration for the creation of a wallet.
        """
        config = ConfigParser()

        config['locations'] = {}
        locations = config['locations']
        locations['data_dir'] = self.wallet_dir.__str__()
        # locations['database_dir'] = 'database'
        # locations['default_databasefile'] = 'bitcoinlib.sqlite'
        # locations['default_databasefile_cache'] = 'bitcoinlib_cache.sqlite'
        locations['log_file'] = self.network + '_log.log'

        config['common'] = {}
        common = config['common']
        # common['allow_database_threads'] = 'True'
        # common['timeout_requests'] = '5'
        # common['default_language'] = 'english'
        common['default_network'] = self.network
        # common['default_witness_type'] = ''
        # common['service_caching_enabled'] = 'True'

        config['logs'] = {}
        logs = config['logs']
        logs['enable_bitcoinlib_logging'] = 'False'
        logs['loglevel'] = 'INFO'

        return config

    def lib_init(self):
        """
        Initializes bitcoinlib by creating a configuration file and
        setting the environmental variable.
        """
        cfg_name = 'bcl_config.ini'

        config = self.cfg_init()
        with open(cfg_name, 'w') as configfile:
            config.write(configfile)

        os.environ['BCL_CONFIG_FILE'] = os.path.abspath(cfg_name)

    def get_identifier(self):
        return self.currency

    def get_name(self):
        return self.network

    def create_wallet(self):
        if self.created:
            return fail(RuntimeError(f"{self.network} wallet with name {self.wallet_name} already exists."))

        self._logger.info("Creating wallet in %s", self.wallet_dir)
        try:
            self.wallet = HDWallet.create(self.wallet_name, network=self.network, db_uri=self.db_path)
            self.wallet.new_key('tribler_payments')
            self.wallet.new_key('tribler_change', change=1)
            self.created = True
        except WalletError as exc:
            self._logger.error("Cannot create %s wallet!", self.network)
            return fail(exc)
        return succeed(None)

    def get_balance(self):
        if not self.created:
            return succeed({
                "available": 0,
                "pending": 0,
                "currency": self.currency,
                "precision": self.precision()
            })

        self.wallet.utxos_update(networks=self.network)

        return succeed({
            "available": self.wallet.balance(network=self.network),
            "pending": 0,
            "currency": self.currency,
            "precision": self.precision()
        })

    async def transfer(self, amount, address):
        balance = await self.get_balance()

        if balance['available'] >= int(amount):
            self._logger.info("Creating %s payment with amount %d to address %s",
                              self.network, int(amount), address)
            tx = self.wallet.send_to(address, int(amount))
            return str(tx.hash)
        raise InsufficientFunds("Insufficient funds")

    def get_address(self):
        if not self.created:
            return succeed('')
        return succeed(self.wallet.keys(name='tribler_payments', is_active=False)[-1].address)

    def get_transactions(self):
        if not self.created:
            return succeed([])

        # Update all transactions
        self.wallet.transactions_update(network=self.network)

        # TODO: 'Access to a protected member _session of a class'
        txs = self.wallet._session.query(DbTransaction.raw, DbTransaction.confirmations,
                                         DbTransaction.date, DbTransaction.fee) \
            .filter(DbTransaction.wallet_id == self.wallet.wallet_id) \
            .all()
        transactions = []

        for db_result in txs:
            transaction = Transaction.import_raw(db_result[0], network=self.network)
            transaction.confirmations = db_result[1]
            transaction.date = db_result[2]
            transaction.fee = db_result[3]
            transactions.append(transaction)

        # Sort them based on locktime
        transactions.sort(key=lambda tx: tx.locktime, reverse=True)

        my_keys = [key.address for key in self.wallet.keys(network=self.network, is_active=False)]

        transactions_list = []
        for transaction in transactions:
            value = 0
            input_addresses = []
            output_addresses = []
            for tx_input in transaction.inputs:
                input_addresses.append(tx_input.address)
                if tx_input.address in my_keys:
                    # At this point, we do not have the value of the input so we should do a database query for it
                    db_res = self.wallet._session.query(DbTransactionInput.value).filter(
                        hexlify(tx_input.prev_hash) == DbTransactionInput.prev_hash,
                        tx_input.output_n_int == DbTransactionInput.output_n).all()
                    if db_res:
                        value -= db_res[0][0]  # TODO: db_res[0][0] not an int, but hash string (value/fee expected?)

            for tx_output in transaction.outputs:
                output_addresses.append(tx_output.address)
                if tx_output.address in my_keys:
                    value += tx_output.value

            transactions_list.append({
                'id': transaction.hash,
                'outgoing': value < 0,
                'from': ','.join(input_addresses),
                'to': ','.join(output_addresses),
                'amount': abs(value),
                'fee_amount': transaction.fee,
                'currency': self.currency,
                'timestamp': time.mktime(transaction.date.timetuple()),
                'description': f'Confirmations: {transaction.confirmations}'
            })

        return succeed(transactions_list)

    def min_unit(self):
        return 100000  # For LTC, BTC and DASH, the minimum trade should be 100.000 basic units (Satoshi, duffs)

    def precision(self):
        return 8       # The precision for LTC, BTC and DASH is the same.

    def is_testnet(self):
        return self.testnet