lemooljiang avatar

Hive社区: Hive blockchain开发指南

lemooljiang

Published: 26 Aug 2025 › Updated: 26 Aug 2025Hive社区: Hive blockchain开发指南

Hive社区: Hive blockchain开发指南

在开发喵星时重新应用了下hivejs的各个功能,把一些常用的应用场景都趟了一遍,也算有些心得。总结总结,给Hive社区的小伙伴们做些参考。

Hive dev

back2.jpg

下载与资源

hive官网 |
开发 |
hivedev

公共节点

参考

https://api.hive.blog           @blocktrades
https://api.openhive.network    @gtg
https://rpc.mahdiyari.info    @mahdiyari
https://techcoderx.com        @techcoderx
https://api.deathwing.me      @deathwing
https://hive-api.arcange.eu   @arcange

安装与使用

yarn add @hiveio/hive-js //^2.0.8
// npm install @hiveio/hive-js --save
//

import hive from '@hiveio/hive-js'
//初始化hive节点
const hiveConNode = 'https://api.openhive.network'
// const hiveConNode = 'https://api.hive.blog'
hive.api.setOptions({ url: hiveConNode})

dhive

npm install @hiveio/dhive --save

var dhive = require("@hiveio/dhive")

var client = new dhive.Client(["https://api.hive.blog", "https://api.hivekings.com", "https://api.openhive.network"])
var key = dhive.PrivateKey.fromLogin("username", "password", "posting")

Auth权限

//认证  
hive.auth.verify(name, password, auths)
eg:
let username = 'epexa'
let password = 'P5...' // 用户密码
let auths = {
    posting: [['STM6...']],
}
hive.auth.verify(username, password, auths)  //return true or false

// Generate Keys  生成公钥对
hive.auth.generateKeys(name, password, roles)
let publicKeys = hive.auth.generateKeys(newAccountName, newAccountPassword, ['owner', 'active', 'posting', 'memo'])
//返回数据
{
  owner: 'STM5sxKw1uEdryNmCj3xAxxxxxx',
  active: 'STM5iEkPwjNPw6WecgeDxxxxx',
  posting: 'STM7dKMMke2aiPTCnExxxx',
  memo: 'STM8KxMKW5t9QkweXBogdxxxxxx'
}

// Get Private Keys 从用户名和密码得到对应的公私钥
hive.auth.getPrivateKeys(name, password, roles)
let roles = ['owner', 'active', 'posting', 'memo']
let res = hive.auth.getPrivateKeys(name, password, roles)
//返回数据
 {
  owner: '5JDZPwykhCb6ZmmvSUFcTsxxxxxxxx',
  ownerPubkey: 'STM5sxKw1uEdryNmCxxxxxx',
  active: '5JSxdtFeCNGSRt18u7WDxxxxxxxx',
  activePubkey: 'STM5iEkPwjNPw6Wecxxxxx',
  posting: '5KE3ET6DD6X47VWDUCXxxxxxxxx',
  postingPubkey: 'STM7dKMMke2aixxxxxxxx',
  memo: '5JgW5NNxT7VJAQMxjtCbDmFxxxxxxxx',
  memoPubkey: 'STM8KxMKW5t9QkweXBoxxxxxx'
} 

// Is Wif //判断是否是私钥,返回 true 或 false
hive.auth.isWif(privWif)
let privWif = "5JfxkpNEBFDxxxvxxxxxxxx"
let res = hive.auth.isWif(privWif)  //true

// To Wif 从用户名和密码得到对应的私钥
hive.toWif(name, password, role)
let role = ["active"]
let res = hive.auth.toWif(name, password, role)
//返回数据
"5Jv9NHkL8TrdvJNue2EKZHQDbxxxxxxx"

// Wif Is Valid 验证公私钥对是否匹配,返回true 或 false
hive.auth.wifIsValid(privWif, pubWif)
let privWif = "5Jv9NHkL8TrdvJNubXxxxxxx"
let pubWif = "STM5f2H2rbSmVoEzrPxxxxxxxx"
let res = hive.auth.wifIsValid(privWif, pubWif)   //true


// Wif To Public 从私钥得到对应的公钥
hive.auth.wifToPublic(privWif)
let privWif = "5Jv9NHkL8TrdvJNue2qxxxxxxx"
let res = hive.auth.wifToPublic(privWif)

// Sign Transaction
hive.auth.signTransaction(trx, keys)

获取帐户数据

帐户数据几乎都在这里了,包括创建的时间,余额,点赞能量等等。

let result = await hive.api.getAccountsAsync([account])
console.log(256, result, result.length === 0)  //length为0表示帐户不存在

Hive登录逻辑

let account = "lucky"
let privWif = "5tikkkxxxxxx"
let result = await hive.api.getAccountsAsync([account])
if(result.length === 0){  
  return ('用户不存在!') 
}

//判断是否私钥
let hiveres = hive.auth.isWif(privWif)
let postWif = privWif
if(hiveres !== true){
  //获取发贴私钥(从密码)
  let role = ["posting"]
  postWif = hive.auth.toWif(account, privWif, role)
} 

//公私钥是否配对
let pubWif = result[0].posting.key_auths[0][0]
let isvalid3 = hive.auth.wifIsValid(postWif, pubWif)
if(isvalid3 === true){
  return ({
    username: account,
    wif: postWif,
    avatar: `https://images.hive.blog/u/${account}/avatar`
  })
} else {
  return ('密钥错误!')
}

发布文章

发贴或评论都是用的同一个函数,只是发帖的parent_author为空。

hive.broadcast.comment(wif, parentAuthor, parentPermlink, author, permlink, title, body, jsonMetadata, function(err, result) {
  console.log(err, result)
})  //commentAsync

//函数讲解
hive.broadcast.comment (
    wif,                 //发帖密钥
    parentAuthor,        // 如果是发帖则为空,如果是评论则为父帖作者
    parentPermlink,      // 如果是发帖则为主标签,如果是评论则为父帖地址
    author,              // 作者
    permlink,            // URL地址
    title,               // 标题 ,如果是评论则为空
    body,                // 内容
    jsonMetadata         // json
)

eg:
let wif = '5pfffff'
let parentAuthor = ''
let parentPermlink = 'cn'
let author = 'lemooljiang'
let permlink = 'kdk54gf'
let title = '这是标题'
let body = '这是正文' 
let tags = ['cn', 'miao', 'bitcoin']
let jsonMetadata = {"tags": tags, "dapp": "miao", "format": "markdown"}

hive.broadcast.comment(wif, parentAuthor, parentPermlink, author, permlink, title, body, jsonMetadata, function(err, result) {
  console.log(1234, err, result)
})

// 另一种Async写法:
let res = await hive.broadcast.commentAsync(wif, parentAuthor, parentPermlink, author, permlink, title, body, jsonMetadata)
console.log(126, res)  
/*  
{ id: '1bea63265fd12d5bf725e1d1e7083eecb6444ff5',                                                   22:17:06
  ref_block_num: 4735,
  ref_block_prefix: 588181965,
  expiration: '2025-08-04T14:27:06',
  operations: [ [ 'comment', [Object] ] ],
  extensions: [],
  signatures:
   [ '2076f2e87b1d976804eexxxxxxxx' ] }
    */

json_metadata

post.json_metadata还可以按需求写入其它的数据,有点类似MongoDB。这样的话易于对文章进行过滤,也可保存一些特殊的数据。

json_metadata: "{"tags":["cn","network-institute","markdown","html"],"app":"miao","format":"markdown"}"
eg:
let jsonMetadata = {"tags": tags, "dapp": "miao", "format": "markdown", "cover": hash, "text": text}
JSON.stringify(jsonMetadata)

一篇文章的结构

{
  author: 'lemooljiang',
  permlink: 'tfdhqbvp',
  category: 'hive-105017',
  title: '洞庭南路离奇车祸,数人伤亡',
  body: '昨晚的车祸由于发生在身边,不由感到阵阵后怕。车祸也是让人感到匪夷所思......',
  json_metadata: '{"tags":["cn","cn-reader","yueyang","caraccident"],"dapp":"larkBlog","format":"markdown"}',
  created: '2025-08-07T04:13:57',
  last_update: '2025-08-07T04:13:57',
  depth: 0,
  children: 0,
  last_payout: '1969-12-31T23:59:59',
  cashout_time: '2025-08-14T04:13:57',
  total_payout_value: '0.000 HBD',
  curator_payout_value: '0.000 HBD',
  pending_payout_value: '4.143 HBD',
  promoted: '0.000 HBD',
  replies: [],
  body_length: 403,
  author_reputation: 439510683431084,
  parent_author: '',
  parent_permlink: 'hive-105017',
  url: '/hive-105017/@lemooljiang/tfdhqbvp',
  root_title: '洞庭南路离奇车祸,数人伤亡',
  beneficiaries: [],
  max_accepted_payout: '1000000.000 HBD',
  percent_hbd: 10000,
  id: 144763251,
  author_rewards: 0,
  max_cashout_time: '1969-12-31T23:59:59',
  reward_weight: 10000,
  root_author: 'lemooljiang',
  root_permlink: 'tfdhqbvp',
  allow_replies: true,
  allow_votes: true,
  allow_curation_rewards: true,
  reblogged_by: [],
  net_votes: 37,
  children_abs_rshares: 0,
  total_pending_payout_value: '0.000 HBD',
  total_vote_weight: 13801670934098,
  vote_rshares: 13801670934098,
  net_rshares: 13801670934098,
  abs_rshares: 13801670934098,
  active_votes: [{
      percent: 7000,
      reputation: 3100979937647200,
      rshares: 5785001502757,
      time: '2025-08-07T04:17:45',
      voter: 'deanliu',
      weight: 5785001502757
    },......]
}

点赞某篇文章

hive.broadcast.vote(wif, voter, author, permlink, weight, function(err, result) {
  console.log(err, result)
})

//函数讲解
hive.broadcast.vote (
    wif,         //发帖密钥
    voter,       //点赞人
    author,      //作者
    permlink,    // URL地址
    weight       //点赞比重,100*100
)
eg:
hive.broadcast.vote(
  "5KRSmEMffffff",
  "lemooljiang",
  "starnote",
  '6ekczn-2019',
  10000,
  function(err, result) {
    console.log(8888, err, result)
  })

获取粉丝列表

hive.api.getFollowers('lemooljiang', '', 'blog', 10, function(err, result) {
  console.log(111, err, result)
})

获取关注列表

hive.api.getFollowing('lemooljiang', '', 'blog', 10, function(err, result) {
  console.log(222, err, result)
})

获取文章的函数们

getDiscussionsByXXX

//query的参数结构
string           tag;
uint32_t         limit = 0;
set<string>      filter_tags;
set<string>      select_authors;   
set<string>      select_tags;      
uint32_t         truncate_body = 0;
optional<string> start_author;
optional<string> start_permlink;
optional<string> parent_author;
optional<string> parent_permlink;

// 获取热门文章
hive.api.getDiscussionsByHot(query, function(err, result) {
  console.log(err, result)
})

eg:
hive.api.getDiscussionsByHot({tag: 'photography', limit: 1}, function(err, result) {
  console.log(err, result)
})


//获取某标签的趁势热贴(只有7天的)
hive.api.getDiscussionsByTrending({tag: 'photography', limit: 1}, function(err, result) {
  console.log(err, result)
});

eg:
getTrending(){
  let query = { tag: "cn", limit : 20 }
  hive.api.getDiscussionsByTrending(query, function(err, data) {
    //取到最后一篇文章的author和Permlink,做为下一次查询的起始点
    author.value = data[data.length - 1].author
    permlink.value = data[data.length - 1].permlink
  })
}

//获取新帖(所有日期的)
hive.api.getDiscussionsByCreated({tag: 'photography', limit: 1}, function(err, result) {
  console.log(err, result)
})

获取作者的最近文章列表

//获取最新文章
hive.api.getDiscussionsByAuthorBeforeDate(author, startPermlink, beforeDate, limit, function(err, result) {
  console.log(err, result)
})

let author = username
let beforeDate = new Date().toISOString().split('.')[0]
let startPermlink = null
let result = await hive.api.getDiscussionsByAuthorBeforeDateAsync(author, startPermlink, beforeDate, 10)
// console.log(655,result)  一次最多能取100篇

获取所有文章并保存在本地

import hive from '@hiveio/hive-js'
import fs from "fs"

//初始化hive节点
const hiveConNode = 'https://api.openhive.network'
// const hiveConNode = 'https://api.hive.blog'
hive.api.setOptions({ url: hiveConNode})

const waiting = async() => {
  return new Promise(resolve => {
      setTimeout(resolve, 6000)  //6秒
  })
}

async function getArticles(author, startPermlink, beforeDate, limit){
  let posts = []
  while(true){
    let result = await hive.api.getDiscussionsByAuthorBeforeDateAsync(author, startPermlink, beforeDate, limit)
    console.log(655,"result:",result.length)

    //如果查询数组为空,则已查询完,可以终止查询了 result: 0
    if(result.length == 0){
      console.log(8888, posts.length)  //从新到旧的数组
      break
    }

    //做一次遍历去掉重复的文章 
    result.forEach(post => {
      if (post.permlink != startPermlink) {
        //把数据规整
        let newPost = {
          "title": post.title,
          "author": post.author,
          "category": post.parent_permlink,
          "permlink": post.permlink,
          "body": post.body,
          "created": post.created,
          "tags": JSON.parse(post.json_metadata).tags  //"tags":["cn-reader","cn"]
        }
        // posts.push(post)
        posts.push(newPost)
      }
    })
    //取到最后一篇文章的Permlink,做为下一次查询的起始点
    startPermlink = result[result.length - 1].permlink  

    await waiting() //主要是因为节点的限制
  }
  
  console.log(5598, "posts", posts.length, posts[posts.length - 1].title, posts[posts.length - 1].created) 

  //保存为md文件
  let path = './2025.md'
  fs.writeFileSync(path, JSON.stringify(posts))
  console.log(666, "save ok!")

  return posts
}

let author = 'lemooljiang'  //改成自己的名字
let beforeDate = new Date().toISOString().split('.')[0]
getArticles(author, null, beforeDate, 80) //传入要查询的作者名,初始标签,初始时间,一次查询的条数(最多是100)

获取用户关注作者的文章列表

let query = {tag: body.tag, limit: body.limit, start_author: body.author, start_permlink: body.permlink}
let result = await hive.api.getDiscussionsByFeedAsync(query)

eg:
let query = {tag: "lemooljiang", limit: 10, start_author: "nie", start_permlink: "sskxiik"}
let result = await hive.api.getDiscussionsByFeedAsync(query)

获取某篇文章的回复

hive.api.getContentReplies(author, permlink, function(err, result) {
  console.log(err, result)
})

eg:
hive.api.getContentReplies('lemooljiang', 'hivejs-41', function(err, result) {
  console.log(err, result)
})

获取某篇文章的所有回复

使用递归的方法获取

async function getAllReplies(author, permlink, res=[]) {
  let replies = await hive.api.getContentRepliesAsync(author, permlink)
  let children = []
  replies.forEach(item => {
    res.push(item)
    if(item.children > 0){
      //把得到的子数据塞进 .child 中
      children.push(getAllReplies(item.author, item.permlink, item.child=[]))
    }
  })
  await Promise.all(children)
  return res
}

获取作者对别人的留言

let author = "lucky"
let query = { limit : 30, start_author: author, start_permlink: ""}
hive.api.getDiscussionsByComments(query, function(err, result) {
  console.log(265, err, result)
}

获取对作者的评论

从帐户历史中遍历获取

async function getToAuthorReplies(author, limit){
  //获取对作者的最新评论
  let replies = []
  let res = await hive.api.getAccountHistoryAsync(author, -1, limit)
  res.forEach(item => {
    if(item[1].op[0] == "comment" & item[1].op[1].parent_author == author){
      replies.push(item)
    }
  })
  return replies
}

转帐HIVE或HBD

hive.broadcast.transfer(wif, from, to, amount, memo, function(err, result) {
    console.log(err, result)
})
// wif,      from,       to,     amount, memo
// 转账私钥,发起转帐地址,转给谁, 金额,   备注
transfer("wif", "lemool", "lucky", "0.001 HBD", "You are awesome ! take some tokens")

eg:
async hiveTransfer(){
  let from = "lemooljiang"
  let to = "lucky"
  let wif = "5KNxxxxxxxxxxxxxxxx"
  // let ss = parseFloat(hivevalue).toFixed(3)
  // let amount = ss+' HIVE'
  let amount = "100.200 HIVE"  //必须是3位小数且带上单位的格式,
  let memo = "测试"
  await hive.broadcast.transferAsync(wif, from, to, amount, memo)
}

获取某位作者某篇文章的点赞

let author = "lemooljiang"
let permlink = "pvw4dotxg"
let res = await hive.api.getActiveVotesAsync(author, permlink)
console.log(566, res)

创建新用户

hive.auth.generateKeys 用于生成4组密钥(owner, active, posting, memo),
hvie.broadcast.accountCreate 用于创建账号

register() {
  let newAccountName = "betty"  //新帐户
  let newAccountPassword = "FDDjjjRxxxxxxxx"  //新帐户密码
  let publicKeys = this.steem.auth.generateKeys(newAccountName, newAccountPassword, ['owner', 'active', 'posting', 'memo'])
  let owner = { weight_threshold: 1, account_auths: [], key_auths: [[publicKeys.owner, 1]] }
  let active = { weight_threshold: 1, account_auths: [], key_auths: [[publicKeys.active, 1]] }
  let posting = { weight_threshold: 1, account_auths: [], key_auths: [[publicKeys.posting, 1]] }
  let memoKey = publicKeys.memo

  let creator = "lemooljiang"  //创建者
  let creatorWif = "5Jbfffxxxxx"  //创建者的资金密钥
  let fee = "3.000 HIVE"    //费用
  let jsonMetadata = ""
  hvie.broadcast.accountCreate(
    creatorWif,
    fee,
    creator,
    newAccountName,
    owner,
    active,
    posting,
    memoKey,
    jsonMetadata,
    (err, result) => {
      if(err){
        console.log(444, '创建失败!', err)
      }else{
        console.log(666, '创建成功!', result)
      }
    })
}

HP代理

HP代理是以VESTS来计算的

hive.broadcast.delegateVestingShares(wif, delegator, delegatee, vesting_shares, function(err, result) {
  console.log(err, result)
})
wif - 
delegator - 
delegatee - 
vesting_shares - hpvests 

//VESTS和HP换算关系
async function main() {
  let s = await hive.api.getDynamicGlobalPropertiesAsync()
  console.log(11, s)
  console.log(12, s.total_vesting_shares)
  console.log(13, s.total_vesting_fund_hive)
  console.log(14, "hp_to_vests", parseFloat(s.total_vesting_shares) / parseFloat(s.total_vesting_fund_hive))
}
main()
//
12 313254970159.720284 VESTS
13 188674228.477 HIVE
 1 HP = 1660.295487 VESTS

eg:
async delegate(){
  let wif = '5KNxxxxxxxxxxxxxxx'
  let delegator = 'lemool'
  let delegatee = "lucky"
  let a = await hive.api.getDynamicGlobalPropertiesAsync()
  let hp_to_vests = parseFloat(a.total_vesting_shares) / parseFloat(a.total_vesting_fund_hive)
  let b = '1.8' * hp_to_vests  //代理1.8个HP
  let c = b.toFixed(6)  //6位小数
  let vests = c+' VESTS'  //换算成VESTS
  await hive.broadcast.delegateVestingSharesAsync(wif, delegator, delegatee, vests)
}
////执行结果:
operations: Array(1)
0: Array(2)
0: "delegate_vesting_shares"
1:
delegatee: "tsteem.test"
delegator: "timool"
vesting_shares: "3483.359523 VESTS"
__proto__: Object
length: 2

: 1HP,07

查询代理

hive.api.getVestingDelegations('ned', '', 2, function(err, result) {
  console.log(err, result)
})  //null []

eg:
async getDelegateHP(){
  let user = 'lemooljiang'
  let res = await hive.api.getVestingDelegationsAsync(user, '', 2) 
  if(res.length == 0){
    return 0
  } else{
    return parseFloat(res[0].vesting_shares)
  }
 }

Leave Hive社区: Hive blockchain开发指南 to:

Written by

Designer , Poet , Technology enthusiasts

Read more #cn posts


Best Posts From lemooljiang

We have not curated any of lemooljiang's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From lemooljiang