def balance(bot, update): """ Fetches and returns the balance (in USD) """ if not checks.check_username(update): return create_user(update.message.from_user.username) key = Key(get_wif(update.message.from_user.username)) balance = key.get_balance("usd") return update.message.reply_text("You have: $" + str(balance))
def __init__(self, testing=False, unittest_prkey=''): if testing == True: self.testing = testing self.private_key = read_drive(testing) self.key = PrivateKeyTestnet(self.private_key) elif unittest_prkey != '': self.testing = testing self.private_key = unittest_prkey self.key = Key(self.private_key) else: self.testing = testing self.private_key = read_drive(testing) self.key = Key(self.private_key)
def create_user(username): """Checks if a Telegram user is present in the database. Returns True if a user is created, False otherwise. """ db.connect(reuse_if_open=True) key = Key() try: User.create(username=username, bch_address=key.address, wif=key.to_wif()) db.close() return True except IntegrityError: db.close() return False
def index(): if 'user' not in session: session['user'] = secrets.token_hex() key = Key() wif = key.to_wif() # Stores the keys in the cookies session['wif'] = wif session['address'] = key.address return render_template( 'index.html', eb_link=EVENT_BRIBE_LINK, address=session['address'], wif=session['wif'], )
def to_key_pairs(cls, mnemonic): w = wallet.create_wallet(network="bch", seed=mnemonic, children=1) wif = w['wif'] key = Key(wif) address = key.address keypair = {"private_key_WIF": wif, "address": address} return keypair
def send_bitcash_message(message): if len(message.encode('utf-8')) > 213: raise ValueError(message + "超长,长度是:" + len(message.encode('utf-8'))) else: config = get_systemconfigs() key = Key(config.private_key) upspents = key.get_unspents() logger.info(upspents) logger.info(key.address) outputs = [ (config.outaddress, 10056, 'satoshi'), ] try: txhash, txid = key.send(outputs, message=message, fee=config.default_fee) logging.info('{m}交易成功,txid:{txid}'.format(m=message, txid=txid)) return (txhash, txid) except Exception as e: logging.error('{m}交易失败,异常:{e}'.format(m=message, e=str(e))) raise e
def withdraw(bot, update, args): """ Withdraws BCH to user's wallet """ if not checks.check_username(update): return if update.message.chat.type != "private": # check if in DM return bot.send_message( chat_id=update.effective_chat.id, text="Private message me to withdraw your money", ) if len(args) != 2: message = ("Usage: /withdraw [amount] [address]\n\n" "You may also withdraw everything at once using:" " /withdraw all [address]") return update.message.reply_text(message) address = checks.check_address(update, args[1]) if not address: # does not send anything if address is False return wif = get_wif(update.message.from_user.username) key = Key(wif) if args[0] == "all": sent_amount = 1000 currency = "satoshi" else: amount = args[0].replace("$", "") if not checks.amount_is_valid(amount): return update.message.reply_text(amount + " is not a valid amount") currency = "usd" sent_amount = float(amount) - 0.01 # after 1 cent fee outputs = [ (address, sent_amount, currency), ] key.get_unspents() try: if args[0] == "all": tx_id = key.send(outputs, fee=1, leftover=address) else: tx_id = key.send(outputs, fee=1) except Exception: return update.message.reply_text("Transaction failed!") return update.message.reply_text("Sent! Transaction ID: " + tx_id)
def withdraw(bot, update, args): """ Withdraws BCH to user's wallet """ if not checks.check_username(update): return if update.message.chat.type != 'private': # check if in DM return bot.send_message( chat_id=update.effective_chat.id, text='Private message me to withdraw your money') if len(args) != 2: message = 'Usage: /withdraw [amount] [address]\n\n'\ 'You may also withdraw everything at once using:'\ ' /withdraw all [address]' return update.message.reply_text(message) address = checks.check_address(update, args[1]) if not address: # does not send anything if address is False return wif = get_wif(update.message.from_user.username) key = Key(wif) if args[0] == 'all': sent_amount = 1000 currency = 'satoshi' else: amount = args[0].replace('$', '') if not checks.amount_is_valid(amount): return update.message.reply_text(amount + ' is not a valid amount') currency = 'usd' sent_amount = float(amount) - 0.01 # after 1 cent fee outputs = [ (address, sent_amount, currency), ] key.get_unspents() try: if args[0] == 'all': tx_id = key.send(outputs, fee=1, leftover=address) else: tx_id = key.send(outputs, fee=1) except Exception: return update.message.reply_text('Transaction failed!') return update.message.reply_text('Sent! Transaction ID: ' + tx_id)
def __init__(self, prkey): self.prkey = Key(prkey)
class Wallet: def __init__(self, testing=False, unittest_prkey=''): if testing == True: self.testing = testing self.private_key = read_drive(testing) self.key = PrivateKeyTestnet(self.private_key) elif unittest_prkey != '': self.testing = testing self.private_key = unittest_prkey self.key = Key(self.private_key) else: self.testing = testing self.private_key = read_drive(testing) self.key = Key(self.private_key) def bch_address(self): return self.key.address def bch_segwit_address(self): return self.key.segwit_address def bch_balance(self, currency="bch"): spinner.start() balance = self.key.get_balance(currency) spinner.stop() return balance def bch_history(self): spinner.start() transactions = self.key.get_transactions() spinner.stop() print("") print(colorama.Fore.GREEN + str(len(transactions)) + " transactions:") print("") for transaction in transactions: print("[ " + transaction + " ]") # perform a transaction def transaction(self, recipient_addr, amount, currency): cashaddr = re.match( '^((bitcoincash|bchreg|bchtest):)?(q|p)[a-z0-9]{41}$', recipient_addr) legacyaddr = re.match('^([13][a-km-zA-HJ-NP-Z1-9]{25,34})', recipient_addr) caplegacyaddr = re.match('^((BITCOINCASH:)?(Q|P)[A-Z0-9]{41})$', recipient_addr) if not any([cashaddr, legacyaddr, caplegacyaddr]): print(colorama.Fore.RED + "Transaction aborted: Invalid bitcoin cash address.") exit() print('You are about to send {} {} to {}'.format( str(amount), currency.upper(), recipient_addr)) amount_left = float(self.bch_balance(currency)) - amount if amount_left <= 0: print(colorama.Fore.RED + 'You don\'t have enough funds to perform the transaction.') exit() if currency == 'usd': print("You will have ${} left on your wallet.".format( str(amount_left))) elif currency == 'bch': print("You will have {} BCH left on your wallet.".format( str(amount_left))) elif currency == 'eur': print("You will have {}€ left on your wallet.".format( str(amount_left))) elif currency == 'gbp': print("You will have £{} left on your wallet.".format( str(amount_left))) elif currency == 'jpy': print("You will have ¥{} left on your wallet.".format( str(amount_left))) print("") decision = input( 'Are you sure you want to perform this transaction? yes | no\n') if decision != 'yes': print("") print(colorama.Fore.RED + 'Transaction aborted') exit() else: try: spinner.start() transaction_id = self.key.send([(recipient_addr, amount, currency)]) spinner.stop() print(colorama.Fore.GREEN + 'Success: ' + colorama.Fore.WHITE + transaction_id) except InsufficientFunds: print( colorama.Fore.RED + 'You don\'t have enough funds to perform the transaction.') def bch_tx_fee(self): fee = get_fee() return fee
def tip(bot, update, args): """ Sends Bitcoin Cash on-chain """ if not checks.check_username(update): return if len(args) != 2 and not update.message.reply_to_message: return update.message.reply_text("Usage: /tip [amount] [username]") if "@" in args[0]: # this swaps args[0] and args[1] in case user input username before # amount (e.g. /tip @merc1er $1) - the latter will still work tmp = args[1] args[1] = args[0] args[0] = tmp amount = args[0].replace("$", "") if not checks.amount_is_valid(amount): return update.message.reply_text(amount + " is not a valid amount.") if update.message.reply_to_message: recipient_username = update.message.reply_to_message.from_user.username if not recipient_username: return update.message.reply_text( "You cannot tip someone who has not set a username.") else: recipient_username = args[1] if not checks.username_is_valid(recipient_username): return update.message.reply_text(recipient_username + " is not a valid username.") recipient_username = recipient_username.replace("@", "") sender_username = update.message.from_user.username if recipient_username == sender_username: return update.message.reply_text("You cannot send money to yourself.") create_user(recipient_username) # IMPROVE recipient_address = get_address(recipient_username) sender_wif = get_wif(sender_username) key = Key(sender_wif) balance = key.get_balance("usd") # checks the balance if float(amount) > float(balance): return update.message.reply_text("You don't have enough funds! " + "Type /deposit to add funds!!") fee = float(amount) * FEE_PERCENTAGE sent_amount = float(amount) - 0.01 if fee < 0.01: outputs = [ (recipient_address, sent_amount, "usd"), ] else: sent_amount -= fee # deducts fee outputs = [ (recipient_address, sent_amount, "usd"), (FEE_ADDRESS, fee, "usd"), ] try: key.send(outputs, fee=1) except Exception: return bot.send_message( chat_id=update.effective_chat.id, text="Transaction failed!", parse_mode=ParseMode.MARKDOWN, ) return bot.send_message( chat_id=update.effective_chat.id, text="You sent $" + amount + " to " + recipient_username, )
def bch_network(net=CRYPTO_NETWORK, prkey=None): if net == 'mainnet': key = Key(prkey) elif net == 'testnet': key = PrivateKeyTestnet(prkey) return key
return satoshi_to_currency_cached(satoshi, 'bch') def is_address_valid(address): return convert.is_valid(address) def send(address, amount): outputs = [ (address, amount, 'bch'), ] try: return key.send(outputs) except: return false if key_exists(): print('Debug: key exists') priv_key = open(PRIVATE_KEY, 'r') key = Key(priv_key.read()) else: print('Debug: key does not exists') key = Key() create_path(PRIVATE_KEY) priv_key = open(PRIVATE_KEY, 'w') priv_key.write(key.to_wif()) priv_key.close() img = pyqrcode.create(key.address) img.svg(QR)
def broadcast(op, token_address=None): orbit = API() ''' messages = orbit.prepare(op, limit=MESSAGE_LIMIT) for message in messages: if len(message) > MESSAGE_LIMIT: raise AssertionError("The data is too large") # sanity check if orbit.parse(b''.join(messages), combined=True) != op: raise AssertionError('Re-parsing the prepared bytes of this operation does not return the same values') ''' interactive = True if not stdin.isatty(): key = stdin.readline().rstrip() interactive = False else: print() value = False while not value: value = input( " Enter wallet name (leave blank to list), '@' for private key: " ) # TODO: "or '!' to self-sign" if not value: print() list_wallets() print() elif value == '@': value = getpass(" Enter private key (hex): ") if value: key = value #elif value == '!': # self = True # confirm = False else: print() try: key = get_key(value, display=False) except ValueError as e: print() print("Sorry: {}".format(e)) value = False print() print("Loading wallet...") wallet = Key.from_hex(key[0]) print(" Your Address: {}".format(wallet.address)) print(" Balance: {} satoshi".format(wallet.get_balance())) print(" Unspents:") for unspent in wallet.unspents: print(" {}".format(unspent)) print(" {} unspent transaction{}".format( len(wallet.unspents), "" if len(wallet.unspents) == 1 else "s")) print() print("Preparing transaction...") if not token_address: token_address = wallet.address print(" Token Address: {}".format(token_address)) try: message = orbit.prepare(token_address, op) except InvalidAddress as e: raise ValueError("An invalid bitcoincash address was entered") #print(message) if len(message) > MESSAGE_LIMIT: raise ValueError( "The data is too large; try reducing some text or removing optional data" ) # sanity check parsed = orbit.parse(message) if parsed != (token_address, op): #print(parsed) raise AssertionError( 'Re-parsing the prepared bytes of this operation does not return the same values' ) ''' sig = Address.sign(wallet, token_address) token = Address(token_address, wallet.public_key, sig) token_messages = orbit.prepare(token, limit=MESSAGE_LIMIT) for token_message in token_messages: if len(token_message) > MESSAGE_LIMIT: raise AssertionError("The token address data is too large") # sanity check if orbit.parse(b''.join(token_messages), combined=True) != token: raise AssertionError('Re-parsing the prepared bytes of the token address operation does not return the same values') ''' fee = get_fee() #fee = 1 if interactive: print() print( " Enter fee per byte in satoshi ({} is currently recommended),". format(fee)) userfee = input(" leave blank to use the recommended fee: ") if userfee: fee = int(userfee) if fee < 1: raise ValueError('Fee must be at least 1 satoshi') print() print("------------------------------------------") print("CAREFULLY REVIEW THE FOLLOWING TRANSACTION") print("------------------------------------------") print() print(" Signer's Address:") print(" {}".format(wallet.address)) print() print(" Token Address:") print(" {}".format(token_address)) print() #print(" {}".format(token.__str__(' '))) print(" {}".format(op.__str__(' '))) print() print(" Fee/byte: {} satoshi".format(fee)) if interactive: print() confirm = input( " Type 'confirm' if you are sure you want to broadcast this transaction: " ) if confirm != "confirm": raise ValueError("User abort") # TODO: attempt broadcast through ORBIT node first, use bitcash wallet as fallback print() #print("Waiting 60 seconds to broadcast (rate limit?)...") #sleep(60) #token_messages.extend(messages) #print(token_messages) try: print("Broadcasting...") #tx = wallet.send([], fee=fee, message=token_messages) tx = wallet.send([], fee=fee, message=message) print('Transaction: {}'.format(tx)) return tx except ConnectionError as e: raise ValueError( "Unable to broadcast, try again later or try increasing the fee: {}" .format(e)) except InsufficientFunds as e: raise ValueError(e)