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


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 can now display a list of all exchanges

for which a Steemian is involved. This can be seen by going to If a Steemian is not a SteemAX user visiting their respective page will redirect them to so they may create an account.

Notice that this is different than the domain address

for signing up and creating an invite which is I have kept these pages separate for ease of use and security. Whereas the page requires authentication via SteemConnect, The page is public and shows all the exchanges an account is currently involved with. The 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.


New Features

SteemAX now

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

  • 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, they will be redirected to 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 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 page ( where they can create the acceptance memo message. If the invitee has never used SteemAX before they will then be redirected to where logging in with SteemConnect will automatically generate an account.



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:
                template =
            except Exception as e:
                return None
                return template

    def make_page(self, template, **kwargs):
        ''' Fills in key / value pairs on a 
        given template
        regobj = re.compile(
        newtemplate = regobj.sub('', template)
        for key, value in kwargs.items():
            newtemplate = re.sub(str(key), 
        return newtemplate

I then added a new method for displaying the HTML for

    def info_page(self, account):
        ''' Creates the page at 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]
                invitee = 0
                otheraccount = value[2]
            if int(value[7]) == -1:
                memoid = str(value[6]) + ":start"
                buttoncode = '''
                <div class="button" onClick="start('{}, {}')">Start</div>'''.format(
            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,
                infobox = infobox + box
        pagetemplate = self.load_template("templates/info.html")
        return ("\r\n" + self.make_page(pagetemplate,

Proof of work

  1. I also added the do_list method to 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 page, as well as completed the HTML templates to incorporate the javascript.

Proof of work #1

Proof of work #2

Proof of work #3

  1. I then added a new module to handle the requests at
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) {
    document.getElementById("memo"+id).style.display = 'block';
    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);
function compare_votes_info(id, account) {
    if (document.getElementById("votevalue"+id).value > 0) {
    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() {
    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);
    else {
        document.getElementById("errormsg").innerHTML = ("$"+vote1+" vs. $"+newvotevalue);

Proof of work

Technology Stack

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


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


Please contact Mike (Mike-A) on Discord

GitHub Account


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
Chat with us on Discord.


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?


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

Want to chat? Join us on Discord

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.28
TRX 0.08
JST 0.042
BTC 29946.49
ETH 2016.40
USDT 1.00
SBD 2.77