Skip to content

Commit 49dd994

Browse files
feruzmrelativityboy
authored andcommitted
resolves #39, delegate power (#104)
1 parent 812783e commit 49dd994

8 files changed

Lines changed: 291 additions & 0 deletions

File tree

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Delegate STEEM POWER
2+
3+
_In this tutorial, we will learn how to delegate power to other users using Steemconnect as well as with Client-side signing method._
4+
5+
This tutorial runs on the main Steem blockchain. And accounts queried/searched are real accounts with their available VESTS balances and estimated STEEM POWER holdings.
6+
7+
## Intro
8+
9+
This tutorial will show few functions such as querying account by name and getting account vesting balance. We then convert VESTS to STEEM POWER for convenience of user. And allow user to choose portion or all holdings of VESTS to delegate other users. A simple HTML interface is provided to capture the account with search and its VESTS balance as well as allowing interactively delegate.
10+
11+
## Steps
12+
13+
1. [**App setup**](#app-setup) Setup `dsteem` to use the proper connection and network.
14+
2. [**Search account**](#search-account) Get account details after input has account name
15+
3. [**Calculate and Fill form**](#fill-form) Calculate available vesting shares and Fill form with details
16+
4. [**Delegate power**](#delegate-power) Delegate VESTS with Steemconnect or Client-side signing.
17+
18+
#### 1. App setup <a name="app-setup"></a>
19+
20+
Below we have `dsteem` pointing to the production network with the proper chainId, addressPrefix, and endpoint. There is a `public/app.js` file which holds the Javascript segment of this tutorial. In the first few lines we define the configured library and packages:
21+
22+
```javascript
23+
const dsteem = require('dsteem');
24+
let opts = {};
25+
//connect to production server
26+
opts.addressPrefix = 'STM';
27+
opts.chainId =
28+
'0000000000000000000000000000000000000000000000000000000000000000';
29+
//connect to server which is connected to the network/production
30+
const client = new dsteem.Client('https://api.steemit.com');
31+
```
32+
33+
#### 2. Search account <a name="search-account"></a>
34+
35+
After account name field is filled with some name, we do automatic search for account by name when input is focused out. HTML input forms can be found in the `index.html` file. The values are pulled from that screen with the below:
36+
37+
```javascript
38+
const accSearch = document.getElementById('username').value;
39+
const _account = await client.database.call('get_accounts', [[accSearch]]);
40+
console.log(`_account:`, _account);
41+
```
42+
43+
#### 3. Calculate and Fill form <a name="fill-form"></a>
44+
45+
After we fetched account data, we will fill form with VESTS balance and show current balance details. Note, that in order to get available VESTS balance we will have to check if account is already powering down and how much is powering down, how much of VESTS were delegated out which locks them from being powered down. Available balance will be in `avail` variable, next for convenience of user, we convert available VESTS to STEEM with `getDynamicGlobalProperties` function and fill form fields accordingly.
46+
47+
```javascript
48+
const name = _account[0].name;
49+
const avail = parseFloat(_account[0].vesting_shares) - (parseFloat(_account[0].to_withdraw) - parseFloat(_account[0].withdrawn)) / 1e6 - parseFloat(_account[0].delegated_vesting_shares);
50+
51+
const props = await client.database.getDynamicGlobalProperties();
52+
const vestSteem = parseFloat(parseFloat(props.total_vesting_fund_steem) *
53+
(parseFloat(avail) / parseFloat(props.total_vesting_shares)),6);
54+
55+
const balance = `Available Vests for ${name}: ${avail} VESTS ~ ${vestSteem} STEEM POWER<br/><br/>`;
56+
document.getElementById('accBalance').innerHTML = balance;
57+
document.getElementById('steem').value = avail+' VESTS';
58+
```
59+
60+
Once form is filled with maximum available VESTS balance, you can choose portion or lesser amount of VESTS to delegate other user.
61+
62+
#### 4. Delegate power <a name="delegate-power"></a>
63+
64+
We have 2 options on how to delegate others. Steemconnect and Client-side signing options. By default we generate Steemconnect link to delegate power (delegate vesting shares), but you can choose client signing option to delegate right inside tutorial, note client-side signing will require Active Private key to perform the operation.
65+
66+
In order to enable client signing, we will generate operation and also show Active Private key (wif) field to sign transaction client side.
67+
Below you can see example of operation and signing transaction, after successful operation broadcast result will be shown in user interface. It will be block number that transaction was included.
68+
69+
```javascript
70+
window.submitTx = async () => {
71+
const privateKey = dsteem.PrivateKey.fromString(
72+
document.getElementById('wif').value
73+
);
74+
const op = [
75+
'delegate_vesting_shares',
76+
{
77+
delegator: document.getElementById('username').value,
78+
delegatee: document.getElementById('account').value,
79+
vesting_shares: document.getElementById('steem').value,
80+
},
81+
];
82+
client.broadcast.sendOperations([op], privateKey).then(
83+
function(result) {
84+
document.getElementById('result').style.display = 'block';
85+
document.getElementById(
86+
'result'
87+
).innerHTML = `<br/><p>Included in block: ${
88+
result.block_num
89+
}</p><br/><br/>`;
90+
},
91+
function(error) {
92+
console.error(error);
93+
}
94+
);
95+
};
96+
```
97+
98+
That's it!
99+
100+
### To run this tutorial
101+
102+
1. clone this repo
103+
1. `cd tutorials/25_delegate_power`
104+
1. `npm i`
105+
1. `npm run dev-server` or `npm run start`
106+
1. After a few moments, the server should be running at [http://localhost:3000/](http://localhost:3000/)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const Koa = require('koa');
2+
const app = new Koa();
3+
const serve = require('koa-static');
4+
app.use(serve('./public'));
5+
6+
app.listen(3000);
7+
8+
console.log('listening on port 3000');
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "25_delegate_power",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "webpack && node ./index.js",
8+
"test": "echo \"Error: no test specified\" && exit 1",
9+
"dev-server":
10+
"./node_modules/.bin/webpack-dev-server --mode development --content-base ./public --port 3000"
11+
},
12+
"author": "",
13+
"license": "ISC",
14+
"dependencies": {
15+
"bootstrap": "^4.1.0",
16+
"dsteem": "^0.8.7",
17+
"koa": "^2.5.0",
18+
"koa-static": "^4.0.2"
19+
},
20+
"devDependencies": {
21+
"css-loader": "^0.28.11",
22+
"style-loader": "^0.21.0",
23+
"webpack": "^4.3.0",
24+
"webpack-cli": "^2.0.13",
25+
"webpack-dev-server": "^3.1.3"
26+
}
27+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const dsteem = require('dsteem');
2+
let opts = {};
3+
//connect to production server
4+
opts.addressPrefix = 'STM';
5+
opts.chainId =
6+
'0000000000000000000000000000000000000000000000000000000000000000';
7+
//connect to server which is connected to the network/production
8+
const client = new dsteem.Client('https://api.steemit.com');
9+
10+
//submitAcc function from html input
11+
const max = 5;
12+
window.submitAcc = async () => {
13+
const accSearch = document.getElementById('username').value;
14+
15+
const _account = await client.database.call('get_accounts', [[accSearch]]);
16+
console.log(`_account:`, _account);
17+
18+
const name = _account[0].name;
19+
const avail =
20+
parseFloat(_account[0].vesting_shares) -
21+
(parseFloat(_account[0].to_withdraw) -
22+
parseFloat(_account[0].withdrawn)) /
23+
1e6 -
24+
parseFloat(_account[0].delegated_vesting_shares);
25+
26+
const props = await client.database.getDynamicGlobalProperties();
27+
const vestSteem = parseFloat(
28+
parseFloat(props.total_vesting_fund_steem) *
29+
(parseFloat(avail) / parseFloat(props.total_vesting_shares)),
30+
6
31+
);
32+
33+
const balance = `Available Vests for ${name}: ${avail} VESTS ~ ${vestSteem} STEEM POWER<br/><br/>`;
34+
document.getElementById('accBalance').innerHTML = balance;
35+
document.getElementById('steem').value =
36+
Number(avail).toFixed(6) + ' VESTS';
37+
};
38+
window.openSC = async () => {
39+
const link = `https://steemconnect.com/sign/delegate-vesting-shares?delegator=${
40+
document.getElementById('username').value
41+
}&vesting_shares=${document.getElementById('steem').value}&delegatee=${
42+
document.getElementById('account').value
43+
}`;
44+
window.open(link);
45+
};
46+
window.submitTx = async () => {
47+
const privateKey = dsteem.PrivateKey.fromString(
48+
document.getElementById('wif').value
49+
);
50+
const op = [
51+
'delegate_vesting_shares',
52+
{
53+
delegator: document.getElementById('username').value,
54+
delegatee: document.getElementById('account').value,
55+
vesting_shares: document.getElementById('steem').value,
56+
},
57+
];
58+
client.broadcast.sendOperations([op], privateKey).then(
59+
function(result) {
60+
document.getElementById('result').style.display = 'block';
61+
document.getElementById(
62+
'result'
63+
).innerHTML = `<br/><p>Included in block: ${
64+
result.block_num
65+
}</p><br/><br/>`;
66+
},
67+
function(error) {
68+
console.error(error);
69+
}
70+
);
71+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.account {
2+
font-weight: bold;
3+
}
4+
table {
5+
font-family: arial, sans-serif;
6+
border-collapse: collapse;
7+
width: 100%;
8+
}
9+
10+
td,
11+
th {
12+
border: 1px solid #dddddd;
13+
text-align: left;
14+
padding: 8px;
15+
width: 50% !important;
16+
}
17+
18+
tr:nth-child(even) {
19+
background-color: #dddddd;
20+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<html>
2+
<head>
3+
<title>Delegate Power</title>
4+
<script src="bundle.js"></script>
5+
</head>
6+
<body>
7+
<div class="container" id="content"><br/>
8+
<h4>Account</h4>
9+
<input id="username" type="text" size="65" placeholder="enter account name" class="form-control"><br><input id="submitSearch" type="button" value="Search" onclick="submitAcc()" class="btn btn-primary"><br>
10+
<div class="list-group account" id="accBalance"></div>
11+
<h5>VESTS to delegate:</h5>
12+
<input id="steem" type="text" size="65" placeholder="0.000000 VESTS" class="form-control"><br>
13+
<h5>To account:</h5>
14+
<input id="account" type="text" size="65" placeholder="username of delegatee" class="form-control"><br>
15+
<h5>How would you like to delegate STEEM POWER/VESTS?</h5>
16+
<table>
17+
<tr>
18+
<th>Steemconnect</th>
19+
<th>Client-side</th>
20+
</tr>
21+
<tr>
22+
<td>
23+
<input id="openSC" type="button" value="Steemconnect" onclick="openSC()" class="btn btn-primary">
24+
</td>
25+
<td>
26+
<div id="client">
27+
<h5>Active Private key:</h5>
28+
<input id="wif" type="text" size="65" placeholder="wif" class="form-control"><br>
29+
<input id="submitTx" type="button" value="Submit" onclick="submitTx()" class="btn btn-primary"><br/>
30+
</div>
31+
</td>
32+
</tr>
33+
</table>
34+
<div id="result" style="display: none;"></div>
35+
</div>
36+
</body>
37+
</html>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import 'bootstrap/dist/css/bootstrap.min.css'
2+
import './index.css'
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var path = require('path');
2+
module.exports = {
3+
entry: ['./public/app.js', './public/style.scss'],
4+
output: {
5+
path: path.resolve(__dirname, 'public'),
6+
filename: 'bundle.js',
7+
},
8+
devtool: 'source-map',
9+
module: {
10+
rules: [
11+
{
12+
test: /\.css$/,
13+
use: ['style-loader', 'css-loader'],
14+
},
15+
],
16+
},
17+
performance: {
18+
hints: process.env.NODE_ENV === 'production' ? 'warning' : false,
19+
},
20+
};

0 commit comments

Comments
 (0)