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"}'
예제 #5
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))
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"
예제 #9
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))
예제 #10
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))
예제 #11
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}
예제 #12
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))
예제 #13
0
 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,
     )
예제 #14
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))
예제 #15
0
 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
예제 #16
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")
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'
예제 #18
0
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-="
    )
예제 #19
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))
예제 #20
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
예제 #21
0
 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)
예제 #22
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))
예제 #23
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..."
            )
예제 #24
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))
예제 #25
0
    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")