def do_select(self, args): """ Change currently active address """ if args: if BismuthUtil.valid_address(args): self.client.set_address(args) print("DONE! Address selected") else: print("Address not valid!") return if len(self.client.addresses()) < 1: print("At least two addresses are needed") return result = self._select_address() if result: try: addresses = list(filter(None, result["addresses"].split(" "))) self.client.set_address(addresses[0].strip()) print("\nDONE! Address selected") except Exception as e: logging.error(e) print(str(e))
async def operation(self, ctx, operation: str, address: str, amount: str, message: str = ''): # TODO: too much code in common with withdraw, factorize somehow. try: amount = float(amount) user = User(ctx.message.author.id) user_info = user.info() # Check the address looks ok if not BismuthUtil.valid_address(address): print("address error") await self.bot.add_reaction(ctx.message, '😟') await self.bot.say( "Address does not look ok. Command is `Pawer operation <operation> <address> <amount> [message]`" ) return if user_info and user_info['address']: # User exists and validated the terms, has an address # Make sure balance is enough balance = float(user.balance()) msg = "{} withdraw {}, balance is {} ".format( ctx.message.author.display_name, amount, balance) fees = BismuthUtil.fee_for_tx(message) print(msg) if balance < amount + 0.01: print("balance too low") await self.bot.add_reaction(ctx.message, '😟') await self.bot.say( "Not enough balance to cover amount + fee ({} Fees)". format(fees)) return send = user.send_bis_to(amount, address, data=message, operation=operation) txid = send['txid'] print("txid", txid) if txid: # answer by reaction not to pollute await self.bot.add_reaction(ctx.message, '👍') # Thumb up await self.bot.say("Done, txid is {}.".format(txid)) else: await self.bot.add_reaction(ctx.message, '👎') # Thumb down await self.bot.say("Error {}".format(send['error'])) return # Depending on channel, say or send PM em = discord.Embed(description=DISCLAIMER, colour=discord.Colour.red()) em.set_author(name="You have to create your address first:") await self.bot.say(embed=em) except Exception as e: print(str(e)) # Send a PM to the sender or answer if dedicated channel await self.bot.add_reaction(ctx.message, '👎') # Thumb down await self.bot.say("Error {}".format(e))
def execute(self, bot, update, args): username = update.effective_user.username if not Bismuth.wallet_exists(username): msg = "Accept terms and create a wallet first with:\n/accept" update.message.reply_text(msg) return if len(args) < 2 or len(args) > 4: update.message.reply_text(text=f"Usage:\n{self.get_usage()}", parse_mode=ParseMode.MARKDOWN) return send_to = args[0] amount = args[1] operation = "" if len(args) > 2: operation = args[2] data = "" if len(args) > 3: data = args[3] if not BismuthUtil.valid_address(send_to): update.message.reply_text( text=f"{emo.ERROR} Bismuth address is not valid", parse_mode=ParseMode.MARKDOWN) return if not utl.is_numeric(amount) or float(amount) < 0: update.message.reply_text( text=f"{emo.ERROR} Specified amount is not valid", parse_mode=ParseMode.MARKDOWN) return message = update.message.reply_text(text=f"{emo.WAIT} Sending...", parse_mode=ParseMode.MARKDOWN) bis = Bismuth(username) bis.load_wallet() trx = bis.send(send_to, amount, operation, data) url = f"{self.BLCK_EXPL_URL}{utl.encode_url(trx)}" if trx: bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.DONE} Done!\n[View on Block Explorer]({url})\n" f"(Available after ~1 minute)", parse_mode=ParseMode.MARKDOWN) else: bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.ERROR} Not able to send Transaction")
async def withdraw(self, ctx, address: str, amount: str, *message): """Send BIS from your wallet to any BIS address, with an optional message""" try: amount = float(amount) openfield_data = ' '.join(filter(None, message)) user = User(ctx.author.id) user_info = user.info() # Check the address looks ok if not BismuthUtil.valid_address(address): print("address error") await ctx.message.add_reaction('😟') await ctx.send( "Address does not look ok. Command is `Pawer withdraw <address> <amount> [message]`" ) return if user_info and user_info['address']: # User exists and validated the terms, has an address # Make sure balance is enough balance = float(user.balance()) msg = "{} withdraw {}, balance is {} ".format( ctx.author.display_name, amount, balance) fees = BismuthUtil.fee_for_tx(openfield_data) print(msg) if balance < amount + 0.01: print("balance too low") await ctx.message.add_reaction('😟') await ctx.send( "Not enough balance to cover amount + fee ({} Fees)". format(fees)) return send = user.send_bis_to(amount, address, data=openfield_data) txid = send['txid'] print("txid", txid) if txid: # answer by reaction not to pollute await ctx.message.add_reaction('👍') # Thumb up await ctx.send("Done, txid is {}.".format(txid)) else: await ctx.message.add_reaction('👎') # Thumb down await ctx.send("Error {}".format(send['error'])) return # Depending on channel, say or send PM em = discord.Embed(description=DISCLAIMER, colour=discord.Colour.red()) em.set_author(name="You have to create your address first:") await ctx.send(embed=em) except Exception as e: print(str(e)) # Send a PM to the sender or answer if dedicated channel await ctx.message.add_reaction('👎') # Thumb down await ctx.send("Error {}".format(e))
def execute(self, bot, update, args): if len(args) == 0: msg = f"Usage:\n{self.get_usage()}" update.message.reply_text(msg, parse_mode=ParseMode.MARKDOWN) return username = update.effective_user.username # Check if user has a wallet if not Bismuth.wallet_exists(username): msg = "Accept terms and create a wallet first with:\n/accept" update.message.reply_text(msg) return try: decode = BismuthUtil.read_url(args[0]) except Exception as e: msg = f"{emo.ERROR} Does not look like a proper BIS URL" update.message.reply_text(msg, parse_mode=ParseMode.MARKDOWN) logging.error(f"{msg}: {e}") return amount = float(decode['amount']) address = decode['recipient'] operation = decode['operation'] message = decode['openfield'] fees = BismuthUtil.fee_for_tx(message) # Check if provided address is valid if not BismuthUtil.valid_address(address): update.message.reply_text( text=f"{emo.ERROR} Provided address is not valid", parse_mode=ParseMode.MARKDOWN) return bisurl_id = self.unix_time() # Save transaction to database insert = self.get_resource("insert_bisurl.sql") self.execute_sql(insert, bisurl_id, username, address, amount, operation, message) msg = "Execute following transaction?\n\n" msg += "▸ Recipient: {}\n".format(address) msg += "▸ Amount: {:.2f} BIS\n".format(amount) msg += "▸ Operation: {}\n".format(operation) msg += "▸ Message: {}\n".format(message) msg += "▸ Fees: {} BIS\n".format(fees) update.message.reply_text(msg, reply_markup=self._keyboard(bisurl_id))
async def send(self, ctx, recipient: Union[discord.User, str], token: str, amount: int, *message): """Sends tokens to the given recipient, recipient can be a @discord_user or a bismuth address""" try: user, user_info = await Bismuth.get_user_info(ctx) if user_info is None: return if amount <= 0: await ctx.send("Amount should be above 0") return address = recipient print(recipient, type(recipient)) if type(recipient) == discord.user.User: recipient_user, recipient_user_info = await Bismuth.get_user_info( ctx, user_id=recipient.id, send_message=False) print(recipient_user, recipient_user_info) if recipient_user_info is None: await ctx.message.add_reaction('😟') await ctx.send( "Recipient user doesn't have a pawer address") return address = recipient_user_info["address"] if not BismuthUtil.valid_address(address): print("address error") await ctx.message.add_reaction('😟') await ctx.send("Recipient address does not look ok.") return balances = await self.get_balances(user_info["address"]) for balance in balances: if balance[0] == token: if balance[1] < amount: ctx.send("You only have {} {}".format( balance[1], balance[0])) return await Bismuth.operation( ctx, "token:transfer", address, "0", "{}:{}{}".format( token, amount, ":{}".format(" ".join(message)) if message else "")) break else: ctx.send("You don't own any {}".format(token)) except Exception as e: print(str(e)) await ctx.message.add_reaction('👎') # Thumb down
async def bisurl(self, ctx, bisurl: str, send: str = 'NO'): """Decode a transaction from a BIS URL. Append SEND to effectively send the tx.""" # TODO: too much code in common with withdraw, factorize somehow. try: try: decode = BismuthUtil.read_url(bisurl) except Exception as e: await ctx.message.add_reaction('😢') # Crying await ctx.send("Does not look like a proper BIS URL") return amount = float(decode['amount']) address = decode['recipient'] operation = decode['operation'] message = decode['openfield'] fees = BismuthUtil.fee_for_tx(message) decoded = "▸ Recipient: {}\n".format(address) decoded += "▸ Amount: {:.2f} $BIS\n".format(amount) decoded += "▸ Operation: {}\n".format(operation) decoded += "▸ Message: {}\n".format(message) decoded += "▸ Fees: {} $BIS\n".format(fees) if send == 'SEND': title = "Decoded BIS URL:" em = discord.Embed(description=decoded, colour=discord.Colour.green()) em.set_author(name=title) await ctx.send(embed=em) else: title = "Decoded BIS URL: (**not** sent)" decoded += " \nPaste this command again and append ` SEND` if you want to send that transaction.\n" em = discord.Embed(description=decoded, colour=discord.Colour.green()) em.set_author(name=title) await ctx.send(embed=em) return user = User(ctx.author.id) user_info = user.info() # Check the address looks ok if not BismuthUtil.valid_address(decode['recipient']): print("address error") await ctx.message.add_reaction('😟') await ctx.send( "Address does not look ok. Command is `Pawer operation <operation> <address> <amount> [message]`" ) return if user_info and user_info['address']: # User exists and validated the terms, has an address # Make sure balance is enough balance = float(user.balance()) msg = "{} withdraw {}, balance is {} ".format( ctx.author.display_name, amount, balance) fees = BismuthUtil.fee_for_tx(message) print(msg) if balance < amount + 0.01: print("balance too low") await ctx.message.add_reaction('😟') await ctx.send( "Not enough balance to cover amount + fee ({} Fees)". format(fees)) return send = user.send_bis_to(amount, address, data=message, operation=operation) txid = send['txid'] print("txid", txid) if txid: # answer by reaction not to pollute await ctx.message.add_reaction('👍') # Thumb up await ctx.send("Done, txid is {}.".format(txid)) else: await ctx.message.add_reaction('👎') # Thumb down await ctx.send("Error {}".format(send['error'])) return # Depending on channel, say or send PM em = discord.Embed(description=DISCLAIMER, colour=discord.Colour.red()) em.set_author(name="You have to create your address first:") await ctx.send(embed=em) except Exception as e: print(str(e)) # Send a PM to the sender or answer if dedicated channel await ctx.message.add_reaction('👎') # Thumb down await ctx.send("Error {}".format(e))
def execute(self, bot, update, args): user = update.effective_user.username if len(args) < 2 or len(args) > 4: update.message.reply_text(text=f"Usage:\n{self.get_usage()}", parse_mode=ParseMode.MARKDOWN) return address = args[0] amount = args[1] operation = "" if len(args) > 2: operation = args[2] data = "" if len(args) > 3: data = args[3] # Check if provided amount is valid if not utl.is_numeric(amount) or float(amount) < 0: update.message.reply_text( text=f"{emo.ERROR} Specified amount is not valid", parse_mode=ParseMode.MARKDOWN) return # Check if provided address is valid if not BismuthUtil.valid_address(address): update.message.reply_text( text=f"{emo.ERROR} Provided address is not valid", parse_mode=ParseMode.MARKDOWN) return # Check if user has a wallet if not Bismuth.wallet_exists(user): msg = "Accept terms and create a wallet first with:\n/accept" update.message.reply_text(msg) return message = update.message.reply_text(text=f"{emo.WAIT} Processing...", parse_mode=ParseMode.MARKDOWN) bis = Bismuth(user) bis.load_wallet() balance = bis.get_balance() total = float(amount) + BismuthUtil.fee_for_tx(data) # Check for sufficient funds if not utl.is_numeric(balance) or float(balance) < total: bot.edit_message_text(chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.ERROR} Not enough funds") return try: # Execute withdrawing trx = bis.send(address, amount, operation, data) except Exception as e: error = f"Error withdrawing {amount} BIS " \ f"from @{user} " \ f"to {address} " \ f"with '{operation}' " \ f"and '{data}': {e}" logging.error(error) self.notify(error) trx = None if trx: logging.debug(f"Withdraw {amount} BIS " f"from @{user} " f"to {address} " f"with '{operation}' " f"and '{data}'") # Save withdrawing to database insert = self.get_resource("insert_withdraw.sql") self.execute_sql(insert, user, address, amount) url = f"{self.BLCK_EXPL_URL}{utl.encode_url(trx)}" # Send success message bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.DONE} DONE!\n[View on Block Explorer]({url})\n" f"(Available after ~1 minute)", parse_mode=ParseMode.MARKDOWN) else: # Send error message bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text= f"{emo.ERROR} Withdrawing not executed. Something went wrong..." )
def do_send(self, args): """ Send coins to address """ if args: arg_list = list(filter(None, args.split(" "))) if args and len(arg_list) == 2: address = arg_list[0] amount = arg_list[1] operation = "" data = "" else: print("Provide following syntax\n" "send <address> <amount>") return else: question = [ { "type": "input", "name": "address", "message": "To:", }, { "type": "input", "name": "amount", "message": "Amount:", }, { "type": "input", "name": "operation", "message": "Operation:", }, { "type": "input", "name": "data", "message": "Data:", } ] res_send = prompt(question) if res_send: address = res_send["address"] if res_send["address"] else "" amount = res_send["amount"] if res_send["amount"] else "" operation = res_send["operation"] if res_send["operation"] else "" data = res_send["data"] if res_send["data"] else "" else: return if not BismuthUtil.valid_address(address): msg = f"'{address}' is not a valid address!" logging.error(msg) print(f"{msg}") return try: float(amount) except ValueError: msg = "'Amount' has to be numeric!" logging.error(msg) print(f"{msg}") return if self.client.reject_empty_msg(address) and not data: msg = "This address needs a 'Data' entry!" logging.error(msg) print(f"{msg}") return question = [ { "type": "list", "name": "send", "message": f"Send {amount} BIS?", "choices": [ "Yes", "No" ] } ] result = prompt(question) if result: if result[question[0]["name"]] == "Yes": try: reply = self.client.send( address, float(amount), operation=operation, data=data) if reply: print(f"DONE! TRXID: {reply}\n") else: print("Transaction couldn't be send") except Exception as e: logging.error(e) print(str(e))
async def send_pop(self, params=None): # TODO: factorize, common code with send. _ = self.locale.translate self.settings["page_title"] = _("Send BIS") if not self.bismuth_vars["address"]: await self.message( _("Error:") + " " + _("No Wallet"), _("Load your wallet first"), "danger", ) return # print(self.bismuth.wallet()) if self.bismuth._wallet._locked: self.message( _("Error:") + " " + _("Encrypted wallet"), _("You have to unlock your wallet first"), "danger", ) return if self.get_argument("url", False): # print("url", self.get_argument('url')) # We have an url param, confirm once decoded self.settings["page_title"] = _("Send BIS: Confirmation") type = "warning" # Do not translate title = _("Please confirm this transaction") message = _( 'Check this is what you intended to do and hit the "confirm" button' ) # self.bismuth_vars['recipient'] operation data amount decoded = BismuthUtil.read_url(self.get_argument("url")) if decoded.get("Error", False): self.message_pop(_("Error:"), _(decoded["Error"]), "warning") return # print(decoded) self.bismuth_vars["params"]["recipient"] = decoded["recipient"] # TODO: verify the sender address is a correct one # address ok? if not BismuthUtil.valid_address( self.bismuth_vars["params"]["recipient"]): await self.message_pop( _("Error:") + " " + _("Bad address"), _("Recipient address '{}' seems invalid").format( self.bismuth_vars["params"]["recipient"]), "warning", ) return self.bismuth_vars["params"]["amount"] = decoded["amount"] self.bismuth_vars["params"]["operation"] = decoded["operation"] self.bismuth_vars["params"]["data"] = decoded["openfield"] if self.bismuth_vars["params"][ "data"] == "" and self.bismuth.reject_empty_message_for( self.bismuth_vars["params"]["recipient"]): await self.message_pop( _("Error:") + " " + _("No message"), _("Sending to this recipient needs a proper message"), "danger", ) return # todo: amount ok # todo: enough balance? self.render( "transactions_sendpop_confirm.html", bismuth=self.bismuth_vars, type=type, title=title, message=message, ) elif self.get_argument("recipient", False): # We have an address param, it's a confirmation self.settings["page_title"] = _("Send BIS: Confirmation") type = "warning" # Do not translate title = _("Please confirm this transaction") message = _( 'Check this is what you intended to do and hit the "confirm" button' ) self.bismuth_vars["params"]["recipient"] = self.get_argument( "recipient") self.bismuth_vars["params"]["amount"] = self.get_argument( "amount", "0.00000000") self.bismuth_vars["params"]["operation"] = self.get_argument( "operation", "") self.bismuth_vars["params"]["data"] = self.get_argument("data", "") if self.bismuth_vars["params"][ "data"] == "" and self.bismuth.reject_empty_message_for( self.bismuth_vars["params"]["recipient"]): await self.message_pop( _("Error:") + " " + _("No message"), _("Sending to this recipient needs a proper message"), "danger", ) return # address ok? if not BismuthUtil.valid_address( self.bismuth_vars["params"]["recipient"]): await self.message_pop( _("Error:") + " " + _("Bad address"), _("Recipient address '{}' seems invalid").format( self.bismuth_vars["params"]["recipient"]), "warning", ) return # todo: amount ok # todo: enough balance? self.render( "transactions_sendpop_confirm.html", bismuth=self.bismuth_vars, type=type, title=title, message=message, ) else: self.message(_("Error:"), "No recipient", "warning")