事前準(zhǔn)備
在使用NODE.JS 調(diào)用EOS API之前,首先需要先準(zhǔn)備一個(gè)EOS的網(wǎng)絡(luò)。(如果主網(wǎng)都沒(méi)有,那還調(diào)用個(gè)毛線)
可以用EOS主網(wǎng),或者是現(xiàn)成的測(cè)試網(wǎng)絡(luò),又或者是本地搭建的網(wǎng)絡(luò)。
我這里為了測(cè)試方便,使用了官方的測(cè)試網(wǎng)絡(luò)。
地址:https://monitor.jungletestnet.io/

注冊(cè)賬號(hào)
- 登錄頁(yè)面之后點(diǎn)擊 Create Account 開(kāi)始創(chuàng)建賬號(hào)
- 輸入賬號(hào)名
tmd111111111 - 輸入公共鑰
EOS6paeQBGNDhbYwoseHLUeLA4LH4ATq9FYT9eW3AYkotC93UbjS2 - 最后點(diǎn)擊 create
這個(gè)操作是將 用戶(hù)名 與 公鑰 進(jìn)行綁定。
用戶(hù)名必須是12位,包含小寫(xiě)字母與數(shù)字1 ~ 5。
公鑰是根據(jù)私鑰生成的,而私鑰是根據(jù)根據(jù)一套復(fù)雜規(guī)則隨機(jī)生成的。
也可以用這個(gè)網(wǎng)站可以生成一套公私鑰。
以下是我生成的公私鑰。
私鑰:5Jg3KWnT2cUsKvmiJYRo7iULfwyhunVU3uDrZEAvjtq2GpABiJQ
公鑰:EOS6paeQBGNDhbYwoseHLUeLA4LH4ATq9FYT9eW3AYkotC93UbjS2

獲取測(cè)試幣
- 注冊(cè)成功后
- 點(diǎn)擊 Faucet 獲取測(cè)試幣
- 填入自己的賬號(hào)
tmd111111111 - 點(diǎn)擊 Send Coint
連接主網(wǎng)
模組安裝
連接主網(wǎng)需要用到 eosjs node-fetch text-encoding eosjs-ecc 這些模組
npm install eosjs@beta node-fetch text-encoding eosjs-ecc
// eosjs-ecc 是在node環(huán)境下生成公私鑰匙的。
模組調(diào)用
注意: eosjs模組api變化很快,要注意使用的版本,這里使用的是
20.0.0-beta2
const { Api, JsonRpc, RpcError, JsSignatureProvider } = require('eosjs');
// 只有在node.js環(huán)境下,才需要以下模組; 瀏覽器不需要引入這個(gè)模組。
const fetch = require('node-fetch');
// 只有在node.js / IE11 /IE Edge 瀏覽器環(huán)境下,需要以下模組;
const { TextDecoder, TextEncoder } = require('text-encoding');
// 這里的私鑰填寫(xiě)剛才生成的私鑰
const privateKey = "5Jg3KWnT2cUsKvmiJYRo7iULfwyhunVU3uDrZEAvjtq2GpABiJQ";
const signatureProvider = new JsSignatureProvider([privateKey]);
// rpc 對(duì)象可以運(yùn)行 eos的rpc命令
// rpc 命令查詢(xún) https://eosio.github.io/eosjs/classes/json_rpc.jsonrpc.html
const rpc = new JsonRpc('http://145.239.133.201:8888', { fetch });
// api 對(duì)象可以運(yùn)行eos的合約,比如轉(zhuǎn)賬,創(chuàng)建賬號(hào)等等(需要費(fèi)用的操作)
const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() });
測(cè)試鏈接
// rpc對(duì)象支持promise,所以使用 async/await 函數(shù)運(yùn)行rpc命令
const runRpc = async () => {
// 獲取主網(wǎng)信息
const info = await rpc.get_info();
console.log(info);
// 獲取賬號(hào)tmd111111111的信息
const accountInfo = await rpc.get_account('tmd111111111');
console.log(accountInfo);
//獲取賬號(hào)tmd111111111的資產(chǎn)
const balance = await rpc.get_currency_balance('eosio.token','tmd111111111');
console.log(balance);
//獲取賬號(hào)操作歷史
const actionHistory = await rpc.history_get_actions('tmd111111111');
console.log(actionHistory);
};
runRpc().catch(err=>{
console.log("rpc error: ",err)
});
如果一切正常會(huì)打印出查詢(xún)結(jié)果。這個(gè)查詢(xún)結(jié)果比較長(zhǎng),我就不貼出來(lái)了。
運(yùn)行合約
在eos系統(tǒng)中,創(chuàng)建賬號(hào)或者轉(zhuǎn)賬都可以認(rèn)為是運(yùn)行合約。
創(chuàng)建賬號(hào)
創(chuàng)建賬號(hào)前,需要生成公私鑰,需要使用
eosjs-ecc模組
const newPrivateKey = await ecc.randomKey();
const newPublicKey = ecc.privateToPublic(newPrivateKey);
console.log(newPrivateKey, newPublicKey);
// 本次生成結(jié)果是
// newPublicKey EOS7hKV4FDKyFacdqCnXvanGv5p8YBPDwvD3km7P36pwb1do4b3wP
// newPrivateKey 5Jm73Ngn3aH9FcukWd1djvxq9iyoidxHhvaxzDigA19D42MhHEN
發(fā)起創(chuàng)建賬號(hào)這個(gè)合約需要三個(gè)步驟,并且這三個(gè)要打包在一起,同時(shí)發(fā)起。
- 將用戶(hù)名與公鑰綁在一起
- 為新用戶(hù)租借網(wǎng)絡(luò)帶寬與cpu
- 為新用戶(hù)購(gòu)買(mǎi)內(nèi)存
注意:創(chuàng)建賬號(hào)的參數(shù)中有可能使用
newact或者name,具體要看區(qū)塊鏈的版本,以及根據(jù)報(bào)錯(cuò)信息進(jìn)行修改,以下的例子是兩個(gè)都寫(xiě)上了。
const result = await api.transact({
actions: [{
// 這個(gè)account是指合約名
account: 'eosio',
// 創(chuàng)建新賬號(hào)的action名
name: 'newaccount',
authorization: [{
actor: 'tmd111111111',
permission: 'active',
}],
data: {
creator: 'tmd111111111',
// 這里的name指的是新用戶(hù)的名字,在內(nèi)部測(cè)試時(shí)候用的是name這個(gè)字段。
name: 'tmdqqqqqqqqq',
// newcat 是公測(cè)鏈,新用戶(hù)名的參數(shù),可能版本不一樣,字段不一樣
newact:'tmdqqqqqqqqq',
owner: {
threshold: 1,
keys: [{
// 寫(xiě)入上面新生成的公鑰
key: 'EOS7hKV4FDKyFacdqCnXvanGv5p8YBPDwvD3km7P36pwb1do4b3wP',
weight: 1
}],
accounts: [],
waits: []
},
active: {
threshold: 1,
keys: [{
// 寫(xiě)入上面新生成的公鑰
key: 'EOS7hKV4FDKyFacdqCnXvanGv5p8YBPDwvD3km7P36pwb1do4b3wP',
weight: 1
}],
accounts: [],
waits: []
},
},
},
{
account: 'eosio',
// 購(gòu)買(mǎi)內(nèi)存的action名
name: 'buyrambytes',
authorization: [{
actor: 'tmd111111111',
permission: 'active',
}],
data: {
payer: 'tmd111111111',
receiver: 'tmdqqqqqqqqq',
bytes: 3000,
},
},
{
account: 'eosio',
// 抵押資產(chǎn)的action名,用于租用帶寬與cpu,抵押資產(chǎn),抵押的越多,帶寬和cup就越多
name: 'delegatebw',
authorization: [{
actor: 'tmd111111111',
permission: 'active',
}],
data: {
from: 'tmd111111111',
receiver: 'tmdqqqqqqqqq',
// 這里的貨幣單位,要查詢(xún)一下系統(tǒng)貨幣的名稱(chēng)才能填,可能是SYS或者EOS
stake_net_quantity: '1.0000 EOS',
stake_cpu_quantity: '1.0000 EOS',
transfer: false,
}
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
});
console.log(result)
};
createAccount().catch(err=>{
console.log("api error: ",err)
});
轉(zhuǎn)賬
轉(zhuǎn)賬操作就比較簡(jiǎn)單了
注意:轉(zhuǎn)賬金額一定要帶四位小數(shù)
const transfer = async () => {
const result = await api.transact({
actions: [{
account: 'eosio.token',
name: 'transfer',
authorization: [{
actor: 'tmd111111111',
permission: 'active',
}],
data: {
from: 'tmd111111111',
to: 'tmdqqqqqqqqq',
quantity: '10.1234 EOS',
memo: '',
},
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
});
console.dir(result);
};
transfer().catch(err=>{
console.log("transfer error: ",err)
});
創(chuàng)建賬號(hào)和成功后,可以用rpc命令檢查一下是否成功
const accountInfo2 = await rpc.get_account('tmdqqqqqqqqq');
console.log(accountInfo2);
使用postman獲取區(qū)塊數(shù)據(jù)
在命令行中打印區(qū)塊信息可能比較難看清楚,eos也支持直接的http請(qǐng)求查詢(xún)數(shù)據(jù)。
api查詢(xún)列表
例子:
在postman中查詢(xún)賬號(hào)tmd111111111的操作歷史

- 請(qǐng)求地址:
http://145.239.133.201:8888/v1/history/get_actions - 請(qǐng)求方式:
POST - 請(qǐng)求頭:
Content-Type:application/json - 請(qǐng)求體:
{"account_name" : "tmd111111111"}
通證創(chuàng)建
要在nodejs環(huán)境發(fā)行通證的話,必須要把要在命令行把eosio.token部署到區(qū)塊鏈上。
詳情請(qǐng)看EOS發(fā)幣指南
api.transact({
actions: [{
// 合約名,已經(jīng)在命令行把eosio.token 這個(gè)合約部署到了賬號(hào)tmd111111111下面,
// 所以這里的用戶(hù)名也就是合約名寫(xiě)自己賬號(hào)名tmd111111111。
account: 'tmd111111111',
// 創(chuàng)建代幣
name: 'create',
authorization: [{
// 執(zhí)行者賬號(hào),也就是自己的賬號(hào)
actor: 'tmd111111111',
permission: 'active',
}],
data: {
// 代幣發(fā)行方,也就是自己,必須指定一個(gè)代幣執(zhí)行者,必須要有這個(gè)賬號(hào)的執(zhí)行權(quán),
// 并且該賬號(hào)一定也要部署了eosio.token這個(gè)合約。
// 一般情況也是寫(xiě)自己的賬號(hào)名
issuer: 'tmd111111111',
// 指定代幣都發(fā)行量、名稱(chēng)與精度,這里都精度是4位小數(shù)。
maximum_supply: '999999.0000 NND',
can_freeze: 0,
can_recall: 0,
can_whitelist: 0
},
},
{
// 合約名,已經(jīng)在命令行吧eosio.token 這個(gè)合約部署到了賬號(hào)tmd111111111下面,
// 所以這里的用戶(hù)名也就是合約名寫(xiě)自己tmd111111111。
account: 'tmd111111111',
// 發(fā)放代幣,把上一步造好的代幣發(fā)給一個(gè)接收者,這里也是寫(xiě)自己
name: 'issue',
authorization: [{
// 合約執(zhí)行方,這里當(dāng)然是寫(xiě)自己啦
actor: 'tmd111111111',
permission: 'active',
}],
data: {
// 代幣的接收者,這里可以填寫(xiě)任意合法的地址,這里寫(xiě)了自己的地址。
to: 'tmd111111111',
quantity: '999999.0000 NND',
memo: "create 999999.0000 NND"
}
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
}).then(console.log).catch(console.log);