Пример #1
0
    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}
Пример #2
0
    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))
Пример #3
0
    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))
Пример #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))
Пример #5
0
    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))
Пример #6
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))
Пример #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))
Пример #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..."
            )