def test_encode_bis_url_new(verbose=False): recipient = "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" amount = "1.234" operation = "" openfield = "" bis_url = BismuthUtil.create_bis_url(recipient, amount, operation, openfield, legacy=False) assert bis_url == "bis://8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234///g2ietw==" recipient = "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" amount = "1.234" operation = "token:transfer" openfield = "test:1" bis_url = BismuthUtil.create_bis_url(recipient, amount, operation, openfield, legacy=False) assert bis_url == "bis://8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234/dG9rZW46dHJhbnNmZXI=/dGVzdDox/ldW-ig==" recipient = "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" amount = "1.234" operation = "token:transfer" openfield = 'test:1:{"Message":"Test message"}' bis_url = BismuthUtil.create_bis_url(recipient, amount, operation, openfield, legacy=True) assert 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"
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 test_encode_bis_url_legacy(verbose=False): recipient = "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" amount = "1.234" operation = "" openfield = "" bis_url = BismuthUtil.create_bis_url(recipient, amount, operation, openfield, legacy=True) assert bis_url == "bis://pay/8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234///Bg#w)r%}J-4Ct__J|z#_" recipient = "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" amount = "1.234" operation = "token:transfer" openfield = "test:1" bis_url = BismuthUtil.create_bis_url(recipient, amount, operation, openfield, legacy=True) assert bis_url == "bis://pay/8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742/1.234/bZ={AZaQ>wVQzC~WpV/bY*jNIxz/>H!cQZ*|L=^XYba0XP&1" recipient = "8342c1610de5d7aa026ca7ae6d21bd99b1b3a4654701751891f08742" amount = "1.234" operation = "token:transfer" openfield = 'test:1:{"Message":"Test message"}' bis_url = BismuthUtil.create_bis_url(recipient, amount, operation, openfield, legacy=True) assert 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"
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"}'
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 test_sublimate1(verbose=False): res = BismuthUtil.sublimate("Test!", 3) if verbose: print(res) res2 = BismuthUtil.condensate(res['parts']) if verbose: print(res2) assert res2["key"] == "Test!"
def test_sublimate3(verbose=False): # Test with a hex String res = BismuthUtil.sublimate("feff0102", 4) if verbose: print(res) res2 = BismuthUtil.condensate(res['parts']) if verbose: print(res2) # No case sensitivity assert res2["key"].lower() == "feff0102"
def test_sublimate2(verbose=False): res = BismuthUtil.sublimate( "Test of a longer string, that could be an ECDSA privkey for instance", 10) if verbose: print(res) res2 = BismuthUtil.condensate(res['parts']) if verbose: print(res2) assert res2[ "key"] == "Test of a longer string, that could be an ECDSA privkey for instance"
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))
def send_bis_to(self, amount, recipient, data='', operation='', check_balance=False): """ Sends BIS from current wallet to recipient, with optional data and operation If check_balance, checks the user balance is enough. Returns a dict with keys txid (txid if sudccess or None) and error ('', 'NO_WALLET','LOW_BALANCE','MP_INSERT') """ error = '' txid = None if path.isfile(self.wallet_file): BISMUTH_CLIENT.load_wallet(self.wallet_file) if check_balance: balance = BISMUTH_CLIENT.balance(for_display=False) fees = BismuthUtil.fee_for_tx(data) if float(balance) < float(amount) + fees: # TODO: better use an enum error = 'LOW_BALANCE' return {'txid': txid, 'error': error} txid = BISMUTH_CLIENT.send(recipient, amount, data=data, operation=operation) if not txid: error = 'MP_INSERT' else: error = 'NO_WALLET' return {'txid': txid, 'error': error}
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 receive(self, params=None): _ = self.locale.translate 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 address = self.bismuth_vars["server"]["address"] self.settings["page_title"] = _("Receive BIS") bisurl = "" # print("address", self.get_query_argument('address', 'no')) if self.get_query_argument("address", False): address = self.get_query_argument("address") amount = "{:0.8f}".format(float(self.get_query_argument("amount", 0))) data = self.get_query_argument("data", "") self.bismuth_vars["params"]["address"] = address self.bismuth_vars["params"]["amount"] = amount self.bismuth_vars["params"]["data"] = data bisurl = BismuthUtil.create_bis_url(address, amount, "", data) self.render( "transactions_receive.html", bismuth=self.bismuth_vars, address=address, bisurl=bisurl, )
async def freebismuth(self, ctx, tweet_url: str): """Register your #Bismuth tweet and get free bismuth""" try: amount = float(0) # amount has to be 0 operation = 'twitter' user = User(ctx.author.id) user_info = user.info() address = user_info['address'] #validate tweet url. # TODO: Validate tweet likes and retweets as per freebismuth spec if not validators.url(tweet_url): print("tweet url error") await ctx.message.add_reaction('😟') await ctx.send( "Link to the tweet does not look ok. Command is `Pawer freebismuth <tweet_url>`" ) 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()) tweet_id = re.search('/status/(\d+)', tweet_url).group(1) # Extract tweet ID msg = "{} freebismuth, tweet ID is {} ".format( ctx.author.display_name, tweet_id) fees = BismuthUtil.fee_for_tx(tweet_id) print(msg) if balance < amount + fees: print("balance too low") await ctx.message.add_reaction('😟') await ctx.send( "Not enough balance to cover fee ({} Fees)".format( fees)) return send = user.send_bis_to(amount, address, data=tweet_id, 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( "Your tweet has been registered. Txid is {}.".format( txid)) else: await ctx.message.add_reaction('👎') # Thumb down await ctx.send( "Can't register your tweet. Error {}".format( send['error'])) return 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("Can't register your tweet. Error {}".format(e))
def status(): """Get Bismuth chain status from the server""" status = BISMUTH_CLIENT.status() try: status['server'] = BISMUTH_CLIENT.current_server status['supply'] = BismuthUtil.height_to_supply(status['blocks']) except: pass return status
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")
def test_condensate(verbose=False): res = { 'count': 3, 'parts': [b'*yx\x1d\xd5', b'\x8d\xdb\xadB\xe9', b'\xf3\xc7\xa6+\x1d'], 'hash': '9382c22f' } res2 = BismuthUtil.condensate(res['parts']) if verbose: print(res2) assert res2["key"] == "Test!" assert res2["hash"] == '9382c22f'
def test_bisurl(verbose=False): url = BismuthUtil.create_bis_url( "abcdef0123456789abcdef0123456789abcdef0123456789abcdef01", 0, "op:test", "openfield_data") if verbose: print("url1", url) assert ( url == "bis://pay/abcdef0123456789abcdef0123456789abcdef0123456789abcdef01/0/Z*V$vWpi`/Z*XO9W@%+?WM5=qbYT/c89#&9#h%MeO(h*k}9I|" ) url = BismuthUtil.create_bis_url( "abcdef0123456789abcdef0123456789abcdef0123456789abcdef01", 0, "bgvp:vote", "0:8ZmHckBjxb0DB8skooVAMw==") if verbose: print("url2", url) assert ( url == "bis://pay/abcdef0123456789abcdef0123456789abcdef0123456789abcdef01/0/VrO=6I(Bb#Wd/FgiF|ZAfElLTY$oFhoK)b8ByJRzXd7Jv{/e&RE#IbWW*)0CtVGcN-=" )
async def zirco(self, ctx, amount: str, bet: str): """Play ZircoDice from your pawer wallet, with any amount less than 100 along with your bet """ try: amount = float(amount) zirco_service_address = '340c195f768be515488a6efedb958e135150b2ef3e53573a7017ac7d' user = User(ctx.author.id) user_info = user.info() # Check the bet field if bet.lower() not in ('odd', 'even'): print("OpenField data error") await ctx.message.add_reaction('😟') await ctx.send("Your bet does not look ok. Command is `Pawer zirco <amount> <odd/even>`") return # Check the bet amount if (amount - float(100)) > 0.01 : print("Bet amount too high") await ctx.message.add_reaction('😟') await ctx.send("You are betting too high. Recommended amount is less than 100`") 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 = "{} zirco {}, balance is {} ".format(ctx.author.display_name, amount, balance) fees = BismuthUtil.fee_for_tx(bet) print(msg) if balance < amount + 0.01004: 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, zirco_service_address, data=bet) txid = send['txid'] print("txid", txid) if txid: # answer by reaction not to pollute await ctx.message.add_reaction('👍') # Thumb up await ctx.send("Your bet has been placed. Txid is {}".format(txid)) await self.bot.remove_reaction(ctx.message, '⏳', self.bot.user) await self.get_zirco_status(ctx.author, txid) else: await ctx.message.add_reaction('👎') # Thumb down await ctx.send("Can't place your bet. Error {}".format(send['error'])) return 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("Can't place your bet. Error {}".format(e))
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 receive(self, params=None): query_params = self.extract_params() address = self.bismuth_vars['server']['address'] _ = self.locale.translate self.settings["page_title"] = _("Receive BIS") bisurl = '' if query_params.get('address', False): address = query_params['address'] bisurl = BismuthUtil.create_bis_url(address, query_params['amount'], '', query_params['data']) self.render("transactions_receive.html", bismuth=self.bismuth_vars, address=address, bisurl=bisurl)
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"] 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")