SteemAX v0.5 Release and New Features ~ SteemAX.info Now Up And Running!

in utopian-io •  5 months ago

Repository

https://github.com/artolabs/steemax

Application Description

In case you're just now finding this, SteemAX is a web application that allows a Steemian to barter with other Steemians for an automatic exchange of upvotes for an agreed duration. Steemians are given the ability to exchange their upvotes at disproportionate ratios allowing whales and minnows to create exchanges with each other, allowing whales to avoid using bid bots to "distribute their upvote" and giving minnows a direct helping hand.

Please be sure to visit @learnelectronics for the most recent update on SteemAX!

steemax_update_v0.5.png

SteemAX can now display a list of all exchanges

for which a Steemian is involved. This can be seen by going to https://steemax.info/@steemitaccountname. If a Steemian is not a SteemAX user visiting their respective steemax.info page will redirect them to steemax.trade so they may create an account.

Notice that this is different than the domain address

for signing up and creating an invite which is https://steemax.trade. I have kept these pages separate for ease of use and security. Whereas the steemax.trade page requires authentication via SteemConnect, The steemax.info page is public and shows all the exchanges an account is currently involved with. The steemax.info page provides functionality for creating the memo messages necessary for starting, accepting, canceling and bartering. All of these actions are carried out by the user sending any amount of SBD (0.001) to @steem-ax. SteemAX processes the action then forwards the SBD to the invitee. Handling SteemAX actions this way provides the benefit of ensuring that only the holder of a Steemit owner key can commence an action. This, in conjunction with the use of recaptcha ensures that the system isn't abused by spammers.

steemax2.png

New Features

SteemAX now

  • lists all the exchanges for which a user is involved as a table at steemax.info.

  • uses steem.js to calculate vote comparisons for each exchange as listed in the exchange table.

  • uses css and javascript to give the user the ability to "start", "cancel", "accept" and "barter" on an exchange. So far the start button is completely finished. The javascript code for the other buttons has essentially been created but not the CSS or HTML.

  • if a user has not yet joined SteemAX by logging in through SteemConnect, and if that user visits steemax.info, they will be redirected to steemax.trade and presented with the login screen. However if they are a current SteemAX user then their exchange page will be accessible without logging in. This essentially makes the steemax.info page public. This was done for two reasons. 1) In an effort to keep the transparency afforded to Steemit users I've decided to make the info page as public as a Steemit account wallet. 2) Included in all invites will be the link to the invitee's Steemax.info page (steemax.info/@invitee-account-name) where they can create the acceptance memo message. If the invitee has never used SteemAX before they will then be redirected to steemax.trade where logging in with SteemConnect will automatically generate an account.

steemaxinfo.gif


need_account.gif

Steps I took

  1. First, I update the get_axlist() method to retrieve exchanges from the database for a given account.

Proof of work

  1. In order to get better control of how the HTML was delivered I split the template method into the load_template method and the make_page method. This allowed me to load "inner" blocks of HTML from the infobox.html template. These are then assembled into the exchange table.
    def load_template(self, templatefile=""):
        ''' opens a template file and loads it
        into memory stored in a variable
        '''
        templatepath = default.webpath + "/" + templatefile            
        with open(templatepath, 'r') as fh:
            try:
                template = fh.read()
            except Exception as e:
                self.msg.error_message(e)
                return None
            else:
                return template


    def make_page(self, template, **kwargs):
        ''' Fills in key / value pairs on a 
        given template
        '''
        regobj = re.compile(
            r"^(.+)(?:\n|\r\n?)((?:(?:\n|\r\n?).+)+)", 
            re.MULTILINE)
        newtemplate = regobj.sub('', template)
        for key, value in kwargs.items():
            newtemplate = re.sub(str(key), 
                                str(value), 
                                newtemplate)
        return newtemplate

I then added a new method for displaying the HTML for steemax.info.

    def info_page(self, account):
        ''' Creates the page at steemax.info that displays
        all the exchanges a user is involved in and which
        provides the options to accept, barter or cancel a 
        particular exchange.
        '''
        account = sec.filter_account(account)
        if not self.db.get_user_token(account):
            return self.auth_url();
        axlist = self.db.get_axlist(account)
        boxtemplate = self.load_template("templates/infobox.html")
        infobox = ""
        invitee = 0
        otheraccount = ""
        for value in axlist:
            if account == value[2]:
                invitee = 1
                otheraccount = value[1]
            else:
                invitee = 0
                otheraccount = value[2]
            if int(value[7]) == -1:
                memoid = str(value[6]) + ":start"
                buttoncode = '''
                <div class="button" onClick="start('{}, {}')">Start</div>'''.format(
                                value[0], 
                                otheraccount)
            if int(value[7]) == 0 or int(value[7]) > 1:
                memoid = str(value[6]) + ":accept"
                buttoncode = '''
                <div class="button" onClick="compare_votes_info('{}')">Accept</div>
                <div class="button">Cancel</div>
                <div class="button">Barter</div>'''.format(value[0])
            if int(value[7]) == 1:
                memoid = str(value[6])
                buttoncode = '''
                <div class="button">Cancel</div>'''
            if int(value[7]) != 4:
                box = self.make_page(boxtemplate,
                                AXID=value[0],
                                ACCOUNT1=value[1],
                                ACCOUNT2=value[2],
                                PERCENTAGE=value[3],
                                DURATION=value[5],
                                DARATIO=value[4],
                                MEMOID=value[6],
                                MEMOSTR=memoid,
                                INVITEE=invitee,
                                OTHERACCOUNT=otheraccount,
                                BTNCODE=buttoncode)
                infobox = infobox + box
        pagetemplate = self.load_template("templates/info.html")
        return ("\r\n" + self.make_page(pagetemplate,
                                ACCOUNT1=account,
                                INFOBOX=infobox))

Proof of work

  1. I also added the do_list method to steemax.py to do the same thing at the command line and list all exhanges of a given account.
    def do_list(self, args):
        account = input("Account (press enter for none): ")
        axlist = db.get_axlist(account)
        for value in axlist:
            print (value[1] + " vs. " + value[2])
            print ('    MemoID: ' + value[6])
            print ('    Per: ' + value[3] 
                    + '%    Ratio: ' + value[4] 
                    + ':1      Dur: ' + value[5] 
                    + ' days     Status: ' + value[7] + '\n')

Proof of work

  1. I then created the CSS for the steemax.info page, as well as completed the HTML templates to incorporate the javascript.

https://github.com/ArtoLabs/SteemAX/blob/master/website/css/info.css

https://github.com/ArtoLabs/SteemAX/blob/master/website/templates/infobox.html

https://github.com/ArtoLabs/SteemAX/blob/master/website/templates/info.html

Proof of work #1

Proof of work #2

Proof of work #3

  1. I then added a new module to handle the requests at steemax.info.
#!/usr/bin/python3
from cgi import FieldStorage
from steemax.web import Web
account = FieldStorage().getvalue('account')
code = FieldStorage().getvalue('code')
print ("Content-type: text/html")
print (Web().info_page(account))
  1. I finally updated the javascript to compare vote values using Steem.js when a user clicks the "start" button. The javascript also handles the page effects that show and hide the memo message box when the "start" button is clicked.
function start(id, account) {
    var memoid = document.getElementById("storedmemoid"+id).value;
    var memomsg = memoid + ":start";
    document.getElementById("memoid"+id).value = memomsg;
    compare_votes_info(id, account);
}
function show_item(id) {
    hide_item();
    document.getElementById("memo"+id).style.display = 'block';
    document.getElementById("memo"+id).offsetHeight;
    document.getElementById("memo"+id).style.opacity = '1';
    itemshowing = id;
}
function hide_item() {
    if (document.getElementById("memo"+itemshowing)) {
        document.getElementById("memo"+itemshowing).style.display = 'none';
        document.getElementById("memo"+itemshowing).style.opacity = '0';
    }
}
function compare_votes_info_callback(id) {
    var regex = new RegExp('[^0-9\.]', 'g');
    var ratio = document.getElementById("ratio"+id).value;
    ratio = ratio.replace(regex, '');
    var votecut = ((vote1 / vote2) * 100) / ratio;
    var exceeds = 0;
    if (votecut < 1) {votecut = 1;exceeds = 1;}
    if (votecut > 100) {votecut = 100;exceeds = 1;}
    var newvotevalue = vote2 * (votecut / 100);
    newvotevalue = parseFloat(newvotevalue).toFixed(4);
    vote1 = parseFloat(vote1).toFixed(4);
    document.getElementById("votevalue"+id).value = newvotevalue;
    document.getElementById("compare"+id).innerHTML = ("$"+vote1+" vs. $"+newvotevalue);
    show_item(id);
}
function compare_votes_info(id, account) {
    if (document.getElementById("votevalue"+id).value > 0) {
        show_item(id);
    }
    else {
        var regex = new RegExp('[^0-9\.]', 'g');
        var percentage = document.getElementById("percentage"+id).value;
        percentage = percentage.replace(regex, '');
        var ratio = document.getElementById("ratio"+id).value;
        ratio = ratio.replace(regex, '');
        var votevalue;
        var account1;
        var account2;
        var otheraccount = document.getElementById("otheraccount"+id).value;
        if (document.getElementById("invitee"+id).value == 0) {
            vote1 = myvote * (percentage / 100);
            account1 = myaccountname;
            account2 = otheraccount;
        }
        else {
            vote2 = myvote * (percentage / 100);
            account2 = myaccountname;
            account1 = otheraccount;
        }
        get_vote_value(otheraccount, 100, 4, id);
    }
}
function compare_votes_index() {
    fix_values();
    var regex = new RegExp('[^0-9\.]', 'g');
    var percentage = document.getElementById("percentage").value;
    percentage = percentage.replace(regex, '');
    var ratio = document.getElementById("ratio").value;
    ratio = ratio.replace(regex, '');
    var votevalue;
    var account1;
    var account2;
    vote1 = myvote * (percentage / 100);
    account1 = myaccountname;
    account2 = document.getElementById("accountbox").value;
    var regex = new RegExp('[^A-Za-z0-9\.\-\_]', 'g');
    account2 = account2.replace(regex, '');
    vote1 = parseFloat(vote1).toFixed(4);
    var votecut = ((vote1 / vote2) * 100) / ratio;
    var exceeds = 0;
    if (votecut < 1) {votecut = 1;exceeds = 1;}
    if (votecut > 100) {votecut = 100;exceeds = 1;}
    var newvotevalue = vote2 * (votecut / 100);
    newvotevalue = parseFloat(newvotevalue).toFixed(4);
    if (exceeds == 1) {
        if (votecut == 1) {
            votediff = newvotevalue - vote1;
            votediff = parseFloat(votediff).toFixed(6);
            document.getElementById("errormsg").innerHTML = ("@" + account2 + " is too large by $" + votediff);
        }
        if (votecut == 100) {
            votediff = vote1 - newvotevalue;
            votediff = parseFloat(votediff).toFixed(6);
            document.getElementById("errormsg").innerHTML = ("@" + account1 + " is too large by $" + votediff);
        }
        input_error(document.getElementById("percentage"));
        input_error(document.getElementById("ratio"));
    }
    else {
        document.getElementById("errormsg").innerHTML = ("$"+vote1+" vs. $"+newvotevalue);
        input_correct(document.getElementById("percentage"));
        input_correct(document.getElementById("ratio"));
    }
}


Proof of work

Technology Stack

SteemAX is written to use Python 3.5 and MySQL. The web interface for steemax.info has been written in HTML, CSS and Javascript.

Roadmap

To finish creating steemax.info I will complete the code necessary to enable the "cancel", "accept" and "barter" buttons.

Contact

Please contact Mike (Mike-A) on Discord
https://discord.gg/97GKVFC

GitHub Account

https://github.com/artolabs

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Thank you for your contribution.

  1. document.getElementById is quite outdated i.e. you may want to try Jquery or other JS framework e.g. document.getElementById("memo"+itemshowing).style.display='none' could be just replaced by something like $('memo'+itemshowing').hide()
  2. no comments at all, which is really hard to follow.
  3. it is not a good practise to declare a variable e.g. var something; and then initialize it later.
  4. The coding quality is really disappointing - and quite old fashion.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Loading...
·

Also, the only thing not commented is the website (HTML and Javascript because this will all be minified and impossible to read anyway). You seemed to be very focused on my javscript code, but apparently have nothing to say about the CSS, HTML or Python I wrote for this new feature. Where is your feedback on those languages?

Loading...

Hey @learnelectronics
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!