Beispiel #1
0
    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))
Beispiel #3
0
    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")
Beispiel #4
0
    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))
Beispiel #5
0
    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))
Beispiel #6
0
    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
Beispiel #7
0
    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))
Beispiel #8
0
    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..."
            )
Beispiel #9
0
    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")