Steem-JS to dMania: How to create your own front-end for Steem dApps

in #utopian-io7 years ago (edited)

SteemJSdMania.png

Preface

The reason I am making this tutorial is because I have personally been unable to upload a meme using dMania several times, and also because I think it is really interesting and important for people to understand just how most dApps access the blockchain. I was going to make this tutorial earlier on Steemit but I was waiting for @zombee to patch out the ability for people to post without declaring beneficiaries, as that might have been a bit of a breach. Plus now I can test out Utopian.io with a premier post and I'm loving it so far. Now onto the tutorial!

In this tutorial, you will learn:

  • How to set up a basic browser environment for Steem-JS.
  • How to find out what attributes dApps require, in order for a post in the blockchain to be displayed in said dApps.
  • Post a comment with Steem-JS and modify its options so that it fits the attributes required by dMania.

Requirements

Since I believe there are already tutorials on how to download Steem-JS plus the ability to use the CDN link (which didn't work for me), I'll start from the directory where it downloads from npm. The docs I use for Steem-JS which include cdn and install directions: https://github.com/steemit/steem-js/tree/master/doc

  • A Steem-JS download.
  • A web browser, this tutorial being confirmed on Firefox, Chrome, and Edge.
  • A text editor of your choice, I'm using Brackets.

Difficulty

  • Basic

Tutorial Contents

Step 1 : Preparing your environment.

After you have downloaded Steem-JS, the console should tell you where the install location is, and after navigating to it, this is what it should look like:

steemprep1.jpg

Double click on the dist folder which holds the important files for the browser and you'll get this:

steemprep2.jpg

From here, simply copy the steem.min JavaScript file and the steem.min.js Linker Address Map file into a folder containing your project. You do not need the steem.min.js Linker Address Map for Steem-JS to work, but I used to get errors without it so I just include it out of habit.

The only two other things you need besides the steem library, are:

  • An index.html file that serves as a run-time environment coupled with your browser.
  • A main.js file where the actual functionality will be written.

To make these, usually all you need to do is save a text file with the "save as type" set to "All" and type out "index.html" and "main.js" as the names of the files. Otherwise as long as you reference your js file correctly in your html file, the names could be anything. Here is what my finished project folder looks like:

steemprep3.jpg

Step 2 : Prep Code.

Since I will not be making an html GUI for this tutorial, the only thing I will be doing with the index.html file will be loading and running the JavaScript code needed for accessing and writing to the Steem blockchain. After you open your index.html file, here is the code to properly format the page and load both the steem library and your own js file:

index.html

<!DOCTYPE html>
<html>
<head>
    
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="steem.min.js"></script>
    <script src="main.js"></script>
    
</head>
    
<body>
    
    <h3>Steem-JS to dMania page title</h3>
    
</body>
</html>

Since the steem library and my main.js file are both in the exact same directory as my index.html file, I only need to reference them by name to load them. If they are in their own folders, then you'd have to write something like:

<script src="folderName/steem.min.js"></script>
<script src="folderName/main.js"></script>

It is also very important to have the steem.min.js (this is not the linker map) above your main.js so that your main.js file is loaded after the steem library has finished loading.

As for the main.js file, the only prep I will make is adding which RPC node I want to connect to and an event listener for when my html file has finished loading. If you are using the latest Steem-JS download, neither is necessary. My Steem-JS library is older, so I'm explicitly setting the now default https://api.steemit.com RPC node. The event listener is not needed here as we will not be using a GUI, but good to know about since it forces the JavaScript within it to wait until the page has loaded so references to html elements will work.

main.js

steem.api.setOptions({ url: 'https://api.steemit.com' });

window.addEventListener('DOMContentLoaded', function () {
    
}, false);

Step 3 : Finding out what makes a dMania post a dMania post.

Now onto the meat of this tutorial, the main two things needed to figure out what dMania adds to posts making them specific to dMania are the Steem-JS steem.api.getContent() API call, and https://steemd.com/

The way I am going to use Steem-JS is simply by calling the steem.api.getContent() function two or three times for different posts, then checking their differences. This function has three arguments, the first is the author's account name, the second is the permlink, and the third is a callback function or an anonymous function. I will make a function with three copies of the steem.api.getContent calls in there, then just for consistency, call that function in the html loaded event listener, which looks like this:

main.js

steem.api.setOptions({ url: 'https://api.steemit.com' });

window.addEventListener('DOMContentLoaded', function () {
    comparePosts();
}, false);

function comparePosts() {
    steem.api.getContent('greatlife', 'i-should-buy-a-boat-zg1hbmlh-6ptmj', function (err, result) {
        console.log(err, result);
        
        steem.api.getContent('loshcat', 'steem-local-usd-fiat-to-steem-and-sbd-website-showcase-concept-1', function (err, result) {
            console.log(err, result);
            
            steem.api.getContent('loshcat', 'and-just-when-you-got-in-zg1hbmlh-quh98', function (err, result) {
                console.log(err, result);
            });
        });
    });
}

The one at the top I got directly from dMania, and it will be what the non-dMania posts are compared to. The other two are my most recent posts, one made in Steemit and unrelated to dMania, the second a failed attempt by me to get my home-brew post listed on dMania. The one in the middle is the unrelated one, and the one on the bottom is the failed attempt. The reason why each consecutive call is within the anonymous function of the previous one, is to force them to be called in the same order as I wrote them. This is so when you are looking at the browser console, it's easier to compare. Otherwise it will just log whichever API call made it back first.

If you do not know what the permlink is, it is what comes after the name in the address bar in both Steemit and dMania:

plinklook.jpg

Now, after you've got all that and saved it,

  • Double-clicking on your html file should open it in your browser.
  • Then you right-click and push "inspect element".
  • Then you click on the console tab and expand it up.

It should look like this:

console1.jpg

There should be three objects representing the three posts we retrieved. By clicking on each object, you can expand it and finally be able to cross reference each attribute to see the differences between a post made on Steemit and one made on dMania. Now, you don't actually need to look at each and every single thing. Usually all you need is the post's JSON metadata and extra stuff that is connected to payouts such as beneficiaries.

Here is what the JSON metadata's are comparing a dMania post and a pure Steemit post:

dMania

json_metadata: "{\"tags\":[\"dmania\",\"meme\",\"funny\",\"vincentb\"],\"image\":[\"https://s3-eu-west-1.amazonaws.com/dmania-images/oh-wait-5bp8f71._wtf!_q.jpg\"],\"app\":\"dmania/0.7\"}"

Steemit

json_metadata: "{\"tags\":[\"steem\",\"steemit\",\"cryptocurrency\",\"steemlocal\",\"life\"],\"users\":[\"guest123\",\"xtar\"],\"image\":[\"https://steemitimages.com/DQmaFdLRbWmQmuErYA5G34c1yh89yQF6KUQ4Auuc8yZKySb/ordertable.png\",\"https://steemitimages.com/DQmXk9bd38gTAGdduLXyzAwZJR7GeoYfcpDGSU12GKp3oNs/buypanel.png\",\"https://steemitimages.com/DQmQYjcNxEVQggHqNcUdERYzE6VbGZEXX1z8tUmyyAsxKpE/orderspanel.png\",\"https://steemitimages.com/DQmcK6dreece2rsQmGnZW8E8j8k5kHvzcuhHa7XC97vEAP8/xtarescrow.png\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}"

Prettied up: dMania

json_metadata: {
    "tags": ["dmania", "meme", "funny", "vincentb"],
    "image": ["//s3-eu-west-1.amazonaws.com/dmania-images/oh-wait-5bp8f71._wtf!_q.jpg"],
    "app": "dmania/0.7"
}

Steemit

json_metadata: {
    "tags": ["steem", "steemit", "cryptocurrency", "steemlocal", "life"],
    "users": ["guest123", "xtar"],
    "image": ["//steemitimages.com/DQmaFdLRbWmQmuErYA5G34c1yh89yQF6KUQ4Auuc8yZKySb/ordertable.png", "//steemitimages.com/DQmXk9bd38gTAGdduLXyzAwZJR7GeoYfcpDGSU12GKp3oNs/buypanel.png", "//steemitimages.com/DQmQYjcNxEVQggHqNcUdERYzE6VbGZEXX1z8tUmyyAsxKpE/orderspanel.png", "//steemitimages.com/DQmcK6dreece2rsQmGnZW8E8j8k5kHvzcuhHa7XC97vEAP8/xtarescrow.png"],
    "app": "steemit/0.1",
    "format": "markdown"
}

I already know that every dMania post has the first tag as "dmania" so just the above information leads me to three major conclusions. The first tag should probably be "dmania" and the "app" key:value pair should be "dmania" as well. Since the versions change but you don't want to de-list previous content, I assume the version number does not matter. Lastly, the amount of images in the "image" key:value array may need to equal 1 to avoid image-less posts. With these three things in mind, I was able to easily post dmania memes by myself a while ago, but since then things have changed and those memes are now de-listed.

Due to the abrupt de-listing, I noticed that the "chosen ones" system for beneficiaries was displayed at the bottom of each meme and figured that was it. I was waiting for it anyway because before, you could game the system essentially by listing your memes without supporting dMania. The next step then, is figuring out how to add beneficiaries since the documentation for Steem-JS still seems poor.

I figured it out by looking at https://steemd.com/ and searching a username that had very recently posted a meme on dMania. This is what I found:

steemdlk.jpg

The picture above pointed me toward the steem.broadcast.commentOptions() Steem-JS function as well as telling me what the arguments are. The only two I am going to look at are the "percent_steem_dollars" and "extensions." Percent steem dollars is the option that determines what percentages you want your rewards in, with 10000 meaning 50/50 as usual, and 0 meaning 100% power up.

The extensions one was a bit trickier, but steemd tells you everything you need to know. Each box represents an array with the numbers in the gray representing an index. Names with stuff after them represent an object or JSON. I was able to determine that the way to set the options to fit with dMania is as below:

steem.broadcast.commentOptions(
    '5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg',
    'guest123',
    'any-permlink',
    '1000000.000 SBD',
    10000,
    true,
    true, 
    [[0, {
        "beneficiaries": [
            {
                "account": "dmania", // Necessary
                "weight": 1000
            },
            {
                "account": "towardsthesun",
                "weight": 500
            },
            {
                "account": "slipknot",
                "weight": 500
            },
            {
                "account": "guest123",
                "weight": 500
            }
        ]
    }]],
    function (err, result) {
        console.log(err, result);
    }
);

After a test or two, I also determined that "dmania" needs to have a weight of 1000 and that there need to be 4 beneficiaries. Also that one of them could be the same as the author if you wanted to be a bit scummy.

Step 4 : Finishing main.js code.

With everything we were able to find out from the process above. The only thing left to do is finish the main.js code:

main.js

steem.api.setOptions({ url: 'https://api.steemit.com' });

window.addEventListener('DOMContentLoaded', function () {
    //comparePosts();
    postToDmania();
}, false);

function comparePosts() {
    steem.api.getContent('greatlife', 'i-should-buy-a-boat-zg1hbmlh-6ptmj', function (err, result) {
        console.log(err, result);
        
        steem.api.getContent('loshcat', 'steem-local-usd-fiat-to-steem-and-sbd-website-showcase-concept-1', function (err, result) {
            console.log(err, result);
            
            steem.api.getContent('loshcat', 'and-just-when-you-got-in-zg1hbmlh-quh98', function (err, result) {
                console.log(err, result);
            });
        });
    });
}

function postToDmania() {
    steem.broadcast.comment(
        '5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg',    // Your Steemit Private Posting Key.
        '',              // Keep empty if making original post, otherwise this is the author of the content you are commenting to.
        'dmania',        // The category or First Tag, if comment, then the permlink of the content you are commenting to.
        'guest123',      // Author ie. Your account name.
        'any-permlink',  // Permlink ie. dynamically created permlink for your comment or content.
        'Post Title',    // Title; if comment to content - leave empty. For dMania post - fill out.
        '<center>\n<a href=\"https://dmania.lol/post/guest123/any-permlink\">\n<img src=\"https://cdn-images-1.medium.com/max/1000/1*OxpVLWSX5y5xqJyvVjoY_Q.png\">\n</a>\n<h3><a href=\"https://dmania.lol/post/guest123/any-permlink\">View post on dMania</a></h3><a href=\"https://dmania.lol\">\n<img src=\"https://dmania.lol/assets/img/dmania_steemit_post.png\">\n</a></center>\n<hr>\n Text Area.', // Copied from legit dMania post to retain consistency. Links to dMania have the author/permlink replaced. Image link also replaced.
        {
            tags: ['dmania', 'meme', 'funny', 'cryptocurrency', 'money'],
            image: ['//cdn-images-1.medium.com/max/1000/1*OxpVLWSX5y5xqJyvVjoY_Q.png'],
            app: 'dmania/0.6'
        },               // Json Metadata
        function (err, result) {
            console.log(err, result);
            
            if (!err) {
                steem.broadcast.commentOptions(
                    '5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg',
                    'guest123',
                    'any-permlink',
                    '1000000.000 SBD',
                    10000,
                    true,
                    true,
                    [[0, {
                        "beneficiaries": [
                            {
                                "account": "dmania", // Necessary
                                "weight": 1000
                            },
                            {
                                "account": "towardsthesun",
                                "weight": 500
                            },
                            {
                                "account": "slipknot",
                                "weight": 500
                            },
                            {
                                "account": "guest123",
                                "weight": 500
                            }
                        ]
                    }]],
                    function (err, result) {
                        console.log(err, result);
                        setTimeout(deleteComment, 10000);
                    }
                );
            }
        }
    );
}

function deleteComment() {
    steem.broadcast.deleteComment('5JRaypasxMx1L97ZUX7YuC5Psb5EAbF821kkAGtBj7xCJFQcbLg',
        'guest123',
        'any-permlink',
        function(err, result) {
            console.log(err, result);
        }
    );
}

Things to note:

  • I got rid of the "https:" in the image array of the metadata to prevent the picture from showing up. You need to add it back for this to work.
  • I am using the public @guest123 tester account so that the above code works for everyone instantly.
  • The setTimeout(deleteComment, 10000); above makes our code wait for ten seconds before deleting the meme just because some bot might upvote it and prevent us from deleting it.
  • The steem.broadcast.commentOptions() function is used in the callback anon function of the steem.broadcast.comment() function to make it so immediately after the comment is made, the options change will begin.
  • if (!err) makes it so the attempt to change the comment options is only done if the post was successfully broadcast.
  • You can put whatever you want in the last four tags.
  • The body of the post does not seem to matter, but all I did was copy it from a legit dMania post and replaced the dMania and image links in the same format as they were, with "author/permlink"
  • You can couple your meme with a complete blog post since the body of the post does not seem to be consequential in how it's displayed on dMania. I believe it is the image link in the JSON_metadata "image" key:value array that determines what is displayed on dMania.
  • If you drag a picture on top of the Steemit markdown text area, it will be uploaded and converted to a link. That link is permanent and you do not have to submit the post, meaning you can drop some images at Steemit, get the links, and clear the post. Now you can use those links anywhere you want. It's what I did.

Postface

And there it is. If you have the above code in your main.js and index.html, all you need to do is double-click on the html file after saving everything and boom, you just posted a meme on dMania. If you have dMania open on the "new" tab, then refresh a few times, you should see whatever picture you used listed at the top. After waiting about ten seconds, it should disappear.

I actually wanted to post my latest meme onto dMania using the above method, but I did not have the comment options at the ready so before I could update it, @sarmizegetusa liked it and prevented me from being able to add beneficiaries. I thought it was hilarious, so huge thanks to @sarmizegetusa as I actually learned that you couldn't add beneficiaries on a liked post. This has been fun, and I hope everyone enjoys the tutorial.



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Your post is pretty complex but I think I know what your post is about. I'm starting to learn some HTML and CSS code, I'm not up to this kind of coding level yet. Like how you added slipknot has one of the account names. Instead of Dtube or Dmania there needs to be a Dporn, am I right?

I mean, the band is good, but the two extra beneficiary account names I just got from the dMania supporters list near the bottom. As for your last question... I plead the fifth.

Seems interesting, I am all for dApps of any kind (for the most part) being made on the Steem blockchain. As for their funding system using a BitShares asset and awarding curation rewards to holders, I'm curious how it'll pan out considering all the conversion and currency back-propagation. I also didn't see anything about where videos would be stored, as problems could arise in both a central and dTube/decentral case.

Hey @loshcat I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • This is your first accepted contribution here in Utopian. Welcome!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x

That sweet 50 rep has eluded me until now. Thanks!

@loshcat, Approve is not my ability, but I can upvote you.

Can I contact you for some coding job?

Yes you can, but depending on how advanced it is, I may not have the expertise or the time.

You can contact me at: [email protected]

Thank you for the contribution. It has been approved.

You can contact us on Discord.
[utopian-moderator]

Coin Marketplace

STEEM 0.17
TRX 0.13
JST 0.027
BTC 60510.42
ETH 2615.72
USDT 1.00
SBD 2.60