Skip to content

Instantly share code, notes, and snippets.

@datchley
Created September 1, 2017 17:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save datchley/6b0c9fe795c7e79256840a339968dcd7 to your computer and use it in GitHub Desktop.
Save datchley/6b0c9fe795c7e79256840a339968dcd7 to your computer and use it in GitHub Desktop.
Some testing code to generate proper eosd API calls.
const fetch = require('isomorphic-fetch');
function pad(number) {
if (number < 10) {
return '0' + number;
}
return number;
}
// eosd currently has issues with "real" ISO time format,
// so we remove the milliseconds and 'Z' ending
const formatISO = d =>
d.getUTCFullYear() +
'-' + pad(d.getUTCMonth() + 1) +
'-' + pad(d.getUTCDate()) +
'T' + pad(d.getUTCHours()) +
':' + pad(d.getUTCMinutes()) +
':' + pad(d.getUTCSeconds())
// '.' + (d.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) +
// 'Z';
// Example block returned from /v1/chain/get_info
// providing information about the head of the blockchain
var block_info = {
"head_block_num": 50,
"last_irreversible_block_num": 32,
"head_block_id": "00000032ef4abccc5fefd86c67623e5e640cdde6b6472b42bc6a868e2fb93655",
"head_block_time": "2017-08-31T17:57:54",
"head_block_producer": "inits",
"recent_slots": "1111111111111111111111111111111111111111111111111111111111111111",
"participation_rate": "1.00000000000000000"
};
const wrappedFetch = (url, options = {}) => {
console.log(`wrappedFetch(${url})`);
const opts = {
method: 'POST',
redirect: 'follow',
headers: new Headers({
'Content-type': 'text/json; charset=utf-8'
}),
...options
};
console.log(`-> options:\n ${JSON.stringify(opts, null, 2)}`);
return fetch(url, opts)
.then(resp => {
if (resp.ok) {
return resp.json();
}
resp.text().then(message => {
throw new Error(`request to ${url} failed: ${message}`);
});
})
.catch(error => {
console.error(error);
});
}
const eosd = 'http://104.198.175.158:8888';
const endpoints = {
'newaccount': '/v1/chain/push_transaction',
'transfer': '/v1/chain/push_transaction',
'getinfo': '/v1/chain/get_info',
'getaccount': '/v1/chain/get_account',
'gettxnhistory': '/v1/account_history/get_transactions'
};
const url = type => `${eosd}${endpoints[type]}`;
const getHead = () => wrappedFetch(url('getinfo'));
const request = async (type, data) => {
const endpoint = url(type);
try {
const head = await getHead();
const payload = getReqJSON(type, head, data);
console.log(`Sending payload: ${JSON.stringify(payload, null, 2)}`);
const json = wrappedFetch(endpoint, { body: JSON.stringify(payload) });
return json;
}
catch (e) {
console.error(`Request for ${type} failed: ${e}`);
}
}
// Grab the first 32bits from the 2nd 64 bit chunk and convert to uint
const getRefBlockPrefix = (info, offset=8) => new Buffer(info.head_block_id, 'hex').readUInt32LE(offset);
// Generate a reference block prefix the same as Steemit does (but for Browser)
// const getRefBlockPrefix = (info, offset=4) => {
// const len = info.head_block_id.length / 2; // hex 2 chars per 8-bits
// let buf = new Uint8Array(len);
// for (var i = 0; i < len; ++i) {
// var parsed = parseInt(info.head_block_id.substr(i*2, 2), 16);
// buf[i] = parsed;
// }
// return ((buf[offset]) |
// (buf[offset + 1] << 8) |
// (buf[offset + 2] << 16)) +
// (buf[offset + 3] * 0x1000000);
// }
// Generate a reference block number, same as Steemit
const getRefBlockNum = info => info.head_block_num & 0xFFFF; // (info.head_block_num - 3) & 0xFFFF;
// Generate an expiration date, 1 hour from time on head block
// returned from /v1/chain/get_info
const getExpiration = info => {
const dt = new Date(info.head_block_time + 'Z');
return formatISO(dt);
// return new Date(
// dt.getTime() +
// 60 * 60 * 1000
// ).toISOString();
}
//
// Demo Data
//
const owner = 'inita';
const ownerKeys = {
"owner": {
"threshold": 1,
"keys": [{
"key": "EOS4toFS3YXEQCkuuw1aqDLrtHim86Gz9u3hBdcBw5KNPZcursVHq",
"weight": 1
}],
"accounts": []
},
"active": {
"threshold": 1,
"keys": [{
"key": "EOS7d9A3uLe6As66jzN8j44TXJUqJSK3bFjjEEqR4oTvNAB3iM9SA",
"weight": 1
}],
"accounts": []
},
"recovery": {
"threshold": 1,
"keys": [],
"accounts": [{
"permission": {
"account": "inita",
"permission": "active"
},
"weight": 1
}]
}
};
const messages = {
newaccount: {
"code": "eos",
"type": "newaccount",
"authorization": [{
"account": "inita",
"permission": "active"
}],
"data": {
"creator": "inita",
"name": "tester",
...ownerKeys,
"deposit": "0.00000001 EOS"
}
},
transfer: {
"code": "eos",
"type": "transfer",
"authorization": [{
"account": "inita",
"permission": "active"
}],
"data": {
"from": "inita",
"to": "test",
"amount": 100,
"memo": "this is a memo"
}
}
};
const genHeader = block => ({
"refBlockNum": getRefBlockNum(block),
"refBlockPrefix": getRefBlockPrefix(block),
"expiration": getExpiration(block),
});
const genScope = (type, data) => {
if (type === 'newaccount') {
return [ "eos", "inita" ]; // hard coded for demo
}
if (type === 'transfer') {
return [ data.from, data.to ]; // parties in transfer
}
// wha'chew talkin' 'bout, Willis?!
throw new TypeError(`can not create scope for unknown txn type '${type}'`);
};
const genMessages = (type, data) => {
if (type === 'newaccount') {
return [{
...messages[type],
data: {
...messages[type].data,
name: data.name
}
}];
}
if (type === 'transfer') {
return [{
...messages[type],
data
}];
}
// wha'chew talkin' 'bout, Willis?!
throw new TypeError(`can not create scope for unknown txn type '${type}'`);
}
// newaccount:
// @param data [Object] - w/ properties: `name`
// transfer:
// @param data [Object] - w/ properties: `to`, `from`, `amount`[, `memo`]
//
const getReqJSON = (type, head, data={}) => {
switch(type) {
// POST type calls
case "newaccount":
case "transfer":
return {
...genHeader(head),
scope: genScope(type, data),
messages: genMessages(type, data),
signatures: []
};
// GET type calls
case "getinfo":
return {};
case "getaccount":
return {
name: data.name
};
case "gettxnhistory":
return {
account_name: data.name,
skip_seq: data.start || 0,
num_seq: data.count || 25
};
default:
return data;
}
}
// console.log(
// getReqJSON('newaccount', block_info, { name: 'tester' })
// );
// console.log(
// getReqJSON('transfer', block_info, { to: 'tester', from: 'inita', amount: 100, memo: "charity" })
// );
// console.log(
// getReqJSON('getinfo', block_info)
// );
// console.log(
// getReqJSON('getaccount', block_info, { name: 'tester' })
// );
// console.log(
// getReqJSON('gettxnhistory', block_info, { name: 'tester' })
// );
getHead()
.then(block =>
console.log(`Got chain head:\n ${JSON.stringify(block, null, 2)}`)
)
.catch(e =>
console.error('FAIL!: ', e)
);
request('newaccount', { name: 'tester2' })
.then(resp =>
console.log(`Got response:\n ${JSON.stringify(resp, null, 2)}`)
)
.catch(e =>
console.error('FAIL!: ', e)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment