def test_decode_bis_url_legacy(verbose=False): bis_url = "bis://pay/8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234///Bg#w)r%}J-4Ct__J|z#_" decoded = BismuthUtil.read_url(bis_url, legacy=True) if verbose: print(decoded) assert decoded[ 'recipient'] == "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" assert decoded['amount'] == "1.234" assert decoded['operation'] == "" assert decoded['openfield'] == "" bis_url = "bis://pay/8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234/bZ={AZaQ>wVQzC~WpV/bY*jNIxz/>H!cQZ*|L=^XYba0XP&1" decoded = BismuthUtil.read_url(bis_url, legacy=True) assert decoded[ 'recipient'] == "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" assert decoded['amount'] == "1.234" assert decoded['operation'] == "token:transfer" assert decoded['openfield'] == "test:1" # Now test a broken hash bis_url = "bis://pay/8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234///Ag#w)r%}J-4Ct__J|z#_" decoded = BismuthUtil.read_url(bis_url, legacy=True) if verbose: print(decoded) assert "Error" in decoded bis_url = "bis://pay/8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234/bZ={AZaQ>wVQzC~WpV/bY*jNIx#wXB28s;b75y?B03^eWpi{OZDn(FVP|C`eE/#04XIp(|p18$+t~x+8E0" decoded = BismuthUtil.read_url(bis_url, legacy=True) assert decoded[ 'recipient'] == "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" assert decoded['amount'] == "1.234" assert decoded['operation'] == "token:transfer" assert decoded['openfield'] == 'test:1:{"Message":"Test message"}'
def test_decode_bis_url_new(verbose=False): bis_url = "bis://8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234///g2ietw==" decoded = BismuthUtil.read_url(bis_url, legacy=False) if verbose: print("new", decoded) assert decoded[ 'recipient'] == "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" assert decoded['amount'] == "1.234" assert decoded['operation'] == "" assert decoded['openfield'] == "" bis_url = "bis://8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234/dG9rZW46dHJhbnNmZXI=/dGVzdDox/ldW-ig==" decoded = BismuthUtil.read_url(bis_url, legacy=False) assert decoded[ 'recipient'] == "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" assert decoded['amount'] == "1.234" assert decoded['operation'] == "token:transfer" assert decoded['openfield'] == "test:1" # Now test a broken hash bis_url = "bis://8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234///g4ietw==" decoded = BismuthUtil.read_url(bis_url, legacy=False) if verbose: print("new", decoded) assert "Error" in decoded bis_url = "bis://pay/8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234/bZ={AZaQ>wVQzC~WpV/bY*jNIx#wXB28s;b75y?B03^eWpi{OZDn(FVP|C`eE/#04XIp(|p18$+t~x+8E0" decoded = BismuthUtil.read_url(bis_url, legacy=True) assert decoded[ 'recipient'] == "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" assert decoded['amount'] == "1.234" assert decoded['operation'] == "token:transfer" assert decoded['openfield'] == 'test:1:{"Message":"Test message"}'
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 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))
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"] 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: address ok? # 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 # TODO: address ok? # 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")