Creating accounts with dsteem 0.6

in #steemdev7 years ago (edited)

dsteem 0.6

I've spent the better part of this weekend working on dsteem and just published version 0.6.0 to npm. It's pretty much feature complete at this point, but I'm going to wait a while to tag a stable release. I want to get a chance to use it in a couple of projects before cementing the APIs.

One of the reasons I created dsteem was because I felt that the current ecosystem really needs more documentation (that's what the d in dsteem stands for). Starting out I found it difficult to understand how to use the protocol and how the calls should be formatted, especially for the account creation process. So I thought that documenting that process would be useful, as well as a good showcase of what dsteem can do.


There's two ways to create accounts on the steem blockchain, you can either pay the entire account creation fee up front (6 STEEM at the time of writing, more on that later) or you can pay a smaller fee and delegate some of your Steem Power to the new account. This is the method Steemit Inc. uses to create new accounts for users that sign up.

Delegated Steem Power is like a loan, the new account gets to use a portion of your Steem Power but they can not power it down and sell it.

The minimum creation fee is decided by the witnesses, they publish a price that is used to determine the final cost of the account. The median account creation price at the time of writing is 0.2 STEEM. Yes, I just wrote that it cost 6 STEEM but that's because to get the full price you need to multiply the base fee by 30. This can seem arbitrary at first but it will make sense when you understand how the base fee is used to calculate the discount when delegating steem.

Let's start by creating an account without delegation, to do that you first need to prepare some keys for the new account:

const username = 'foo'
const password = 'barman' // ⚠️🔐💩

const ownerKey = PrivateKey.fromLogin(username, password, 'owner')
const activeKey = PrivateKey.fromLogin(username, password, 'active')
const postingKey = PrivateKey.fromLogin(username, password, 'posting')
const memoKey = PrivateKey.fromLogin(username, password, 'memo')

Run on the Playground

As you can see the keys are derived from your username and password, that is why it is a good idea to login on steemit.com with just your posting key.

Steem has three auth levels: owner, active and posting. Posting lets you post content and vote, active lets you transfer money and owner is only used to change the other keys (and itself). The memo key meant for message encryption and is currently not used on steemit.com.

Now we need to wrap the keys in something called an Authority, they can be used for lots of cool stuff like multisig and shared usage of an account, but for now we will just create the most basic authority objects possible for the keys.

const ownerAuth = {
    weight_threshold: 1,
    account_auths: [],
    key_auths: [[ownerKey.createPublic(), 1]]
}
const activeAuth = {
    weight_threshold: 1,
    account_auths: [],
    key_auths: [[activeKey.createPublic(), 1]]
}
const postingAuth = {
    weight_threshold: 1,
    account_auths: [],
    key_auths: [[postingKey.createPublic(), 1]]
}

⚠️

Take extra note that those are the public versions of the keys, the private keys are only ever used to sign transactions!

The first rule of steem is: You don't share your private key. The second rule of steem is: YOU DON'T SHARE YOUR PRIVATE KEY! Third rule of steem: Use strong passwords. Fourth rule: don't store your paper-wallet in a damp space.

That sorted we need to figure out what fee to pay for the new account, we could simply hard-code it to 6 STEEM but that could break if the witnesses arrive at a new consensus or an update to the protocol changes the constants.

So let's do it the proper way. To do that we need to connect to a steem rpc node and get the current witness consensus along with the configuration constants:

const client = new Client('wss://steemd.steemit.com')

const constants = await client.getConfig()
const chainProps = await client.getChainProperties()

const ratio = constants['STEEMIT_CREATE_ACCOUNT_WITH_STEEM_MODIFIER']
const fee = Asset.from(chainProps.account_creation_fee).multiply(ratio)

Run on the Playground

The steem chain properties are median values of what the top 21 witnesses has voted for and besides the account creation fee it also contains the maximum block size and the Steem Dollar interest rate.

There we go, 6 STEEM. Now we have everything we need to create a new account, let's construct an operation we can broadcast to the network:

const op: AccountCreateOperation = ['account_create', {
    creator: 'this-is-you',
    new_account_name: username,
    owner: ownerAuth,
    active: activeAuth,
    posting: postingAuth,
    memo_key: memoKey,
    json_metadata: '',
}]

Now we need to package the operation in a transaction, serialize it and finally sign it with the active authority of creator. That's a bit out of scope for this article so let's just use dsteem's sendOperations helper.

const creatorKey = PrivateKey.from('5rule1rule1rule1rule1')
await client.broadcast.sendOperations([op], creatorKey)

👌

Account created! Easy! 🙂 Let's create another one, with delegation this time. But first I have to let you in on a little secret, Steem Power does not actually exist, it is just a representation of how many STEEM you would have if you withdrew your vesting shares.

The steem blockchain uses the VESTS symbol to represent your vesting shares in the platform.

So to figure out how much delegation is needed we need to get the current vesting share price:

const props = await client.database.getDynamicGlobalProperties()
const sharePrice = Price.from({
    base: props.total_vesting_shares,
    quote: props.total_vesting_fund_steem
})

💰

The creation fee is discounted on a 1 to 5 basis for delegated steem, e.g. 30 delegated steem is worth 6 steem. With that info we can calculate how many VESTS we need to delegate, let's say we want to pay 0.5 STEEM as a creation fee and the rest as delegation:

const fee = Asset.from('0.500 STEEM')
const ratio = constants['STEEMIT_CREATE_ACCOUNT_DELEGATION_RATIO']
const modifier = constants['STEEMIT_CREATE_ACCOUNT_WITH_STEEM_MODIFIER']

const targetDelegation = sharePrice.convert(
    creationFee.multiply(modifier * ratio)
)
const delegation = targetDelegation.subtract(
    sharePrice.convert(fee.multiply(ratio))
)

Run on the Playground

Now we can broadcast the operation just like before, just using the account_create_with_delegation operation instead of account_create. I'll leave that as an exercise for the reader 🙂.


But you don't really need to know all this to use dsteem, it does it for you. Creating a new account is as simple as:

await client.broadcast.createAccount({
    username: 'foo', password: 'barman', creator: 'someone'
}, someonesActiveKey)

Run on the Playground

That creates the keys, figures out the correct fee and delegation amounts and broadcasts the operation. See the method's documentation for more info.

The more you know... 🐢


GitHub Repository | API Documentation | Coding Playground | Live Demo

Sort:  

Considering SteemJS-Lib by @svk is practically abandoned, I may re-write my price feed to use dsteem.

A few questions:

  1. Does it handle disconnects smoothly? i.e. automatically reconnect without just breaking
  2. Does it support other chains? e.g. GOLOS, PeerPlays
  3. Is there a browser version ready built?
  4. What versions of NodeJS does it run on?

Awesome, would love to see some more real-world usage!

  1. Yep, it even has a configurable exponential backoff. But you do need to handle retries, if a command times out for example.
  2. I think so, It works well running against my testnet which has a custom chain id and address prefix.
  3. Yep, check the ./dist/ folder in the github repo
  4. I'm testing against node 7 and 8, will probably work with 6 as well.

@someguy123 - Not to take any steem away from dsteem (pun intended), but the steem-js library is actually still actively developed at it's official home on the steemit github here: https://github.com/steemit/steem-js

It's actually what condenser uses for the live site today - the one on svk's github is outdated. It handles disconnects smoothly, supports alternative chains (at least golos), and the browser based version is ready and built.

With that being said, diversity in the steem ecosystem is a good thing and dsteem is pretty cool too :)

steem-js != steemjs-lib

They work completely differently to each other. Originally the official steemit one had practically no documentation, and I believe it lacked the functions I needed.

Of course if it's improved now, then maybe I'll try it out.

Great post! The project is interesting. I am very interested. At this point I agree with you.

i almost forgot about my peerplay tokens is that a website yet? is perry plays up nd running? will they hve a blocktrades type feature where u can sell ur peerplay tokens or will peerplays be on bittrex like golos is? or do u have any idea?

Anyway this whole post is GREAT @almost-digital you demystified the whole account creation process to explain to people why it costs 6 steem to generate an account and i am confident that it will not become a bottleneck and steem will be able to grow very fast and we will have no problem hitting 1 million actual human active users by next year and a nice $5 price of steem by the end of this year, It should be $10 if people knew how valuable the steem blockchain really wayt

imagine if facebook creatd thir own hardfork of steem and used it for facecoin? It would be HUGE! steem's DPOS delegated proof oif stake system is just the most efficient crypto cutrrency social media system out there and there is nothing like it and there will BE nothing like it!

steem happened because of the Crypto sphere! a world of self employed financially independent people came together and made something happen at the perfect time and crypto will only grow and eat up all the worlds fiat. Hyperinflation wont affect steemit. our steem iwll be so precious just like Bitcoin.../steem is going to become a very valuable altcoin

an important thing to know is that usernames are alphamnumerical only.

Took me a few tries and headscratching 2 days ago to get this.

Took me a few tries and headscratching 2 days ago to get this.

Happens to me too :)

Awesome, but still thinking Steemit as itself should consider to fix this problem. I know that it cost 9 STEEM to create a new account, but again, i agree with Steemit to charge us a little percentage for all author and curation rewards to cover this account creation cost.

Awesome documentation!!!
Tried it on a friends MacBook and it is still loading...
Is it normal to take some time?

Thanks! You're talking about the playground right?

I've seen that as well, sometimes the coding editor does not load in Safari. Reloading the page usually fixes it.

it now works, but i get a message, that the key is wrong...

Great job buy how different it is compared to steem-js? I feel it is much more appreciated to help steem-js develops better documentation and everyone use that instead of creating new packages. Just my 2 cents here.

It's faster, written in TypeScript and has 99% test coverage along with integration tests against a testnet. I'm also aiming to simplify the steemd APIs instead of just providing a 1:1 call wrapper as shown here with the account creation.

But I understand your point. I started out using steem-js and even have a commit or two in the project but to be honest I didn't like the smell of the code... and barging in to a established project and saying "Hi! I'm new here. I'm going to rewrite all your things in my own opinionated way" usually don't go over well :) I also recently wrote a WebSocket RPC client that I could reuse a lot of code from.

Great contributions on your side. I think having a 1:1 call wrapper is necessary to have a low-level API available for different use cases but I wished we could all build new high level APIs on top of that one single well maintained code.

Even so, it's a great effort on your side and maybe it's better to use a well tested code like yours for new apps. I find it a little risky for new devs to join since most of the sample codes are for steem-js and it makes your job much harder to promote your solution.

But I understand your point. I started out using steem-js and even have a commit or two in the project but to be honest I didn't like the smell of the code..

This sounds much cheaper than making accounts via anon-steem

I've made a tool to create accounts here: https://account.steem.vc
It does not do delegation yet so you every account cost 6 STEEM (that will be steem power in the new account)

Nice example. Hope you can come out with more examples. I am wondering how would one get the recent transfers for an account (the data on the wallet page) ?

Thanks! There isn't a helper to get the account history in dsteem yet but here's how you do it manually:

https://playground.steem.vc/@^0.6.0#c182038ce97d3d4d283b50fd87ed0190

thanks a lot

Thanks for putting this together! Resteemed and will definately play around with this this weekend when I have some free time

Awesome! Let me know how it goes :)

Will do! :)

amazing work

Really cool project. Im playing with it now

Coin Marketplace

STEEM 0.18
TRX 0.16
JST 0.029
BTC 63656.97
ETH 2473.22
USDT 1.00
SBD 2.66