EOS [从零开始 DAPP 开发] 11 - DAPP 业务逻辑合约开发:点赞、关注

pendingauth · 2019年07月10日 · 61 次阅读

本文转载自币乎,作者松果,原文链接:https://bihu.com/article/1448416820

这篇文章继续进行weiwendappss智能合约核心业务逻辑开发,还剩下点赞和关注功能。

点赞

点赞是微文DAPP的核心业务,也是获取WEI代币的主要方式(点赞挖矿)。

因为微文DAPP主要用于介绍开发流程,不会上线到主网,点赞挖矿逻辑和算法设计得比较简单:

  • 可以对微文或评论进行点赞;

  • 每个用户每天前10次点赞获得代币奖励;

  • 持仓代币数大于0才能获得点赞收益;

  • 每次点赞,点赞者和作者都将获得相同数量的代币;

  • 每次点赞获得(持仓代币 * 0.00001 * 100~500随机数)的代币;

  • 给自己点赞不获得收益。

点赞使用weiwendappss::like Action,代码如下:

ACTION like(name author, uint32_t type, uint64_t type_id) {
  require_auth(author);

  check_user(author);
  check(type == TYPE_POST || type == TYPE_COMMENT, "invalid like type");
  check_liked(author, type, type_id);

  if(type == TYPE_POST){
    post_t posts(_self, _self.value);
    check(posts.find(type_id) != posts.end(), "post does not exist");

    update_like_data<post_t>(author, type_id);

  }else if(type == TYPE_COMMENT){
    comment_t comments(_self, _self.value);
    check(comments.find(type_id) != comments.end(), "comment does not exist");

    update_like_data<comment_t>(author, type_id);
  }

  like_t likes(_self, _self.value);
  likes.emplace(author, [&](auto& like){
    like.id = likes.available_primary_key();
    like.type = type;
    like.type_id = type_id;
    like.author = author;    
  });  
}

首先做了权限验证和一些其他常规验证,check_liked函数用于判断微文或评论是否已经被点赞了,定义如下:

void check_liked(name author, uint32_t type, uint64_t type_id){
  bool liked = false;

  like_t likes(_self, _self.value);
  auto secondary = likes.get_index<"byauthor"_n>();

  for(auto itr = secondary.lower_bound(author.value); itr != secondary.upper_bound(author.value); itr++){
    if(itr->type == type && itr->type_id == type_id){
      liked = true;
    }
  }

  if(liked) check(false, "already liked");
}

这里使用了二级索引(Secondary Indices),因为要先找到指定点赞者的所有点赞,而按主键遍历的数据是按id排序的;

使用liketable表定义的二级索引byauthor,可以让数据按照author(点赞者)字段排序,再使用lower_bound和upper_bound函数来截取指定点赞者的所有点赞;

遍历获取到的点赞数据,如果发现有数据和传入的type、type_id都相同,就表示点赞者已经赞过了。

在进行一些常规验证后,使用update_like_data函数更新点赞相关的数据,update_like_data是一个函数模板,定义如下:

template<typename T>
void update_like_data(name liker, uint64_t type_id){

  T datas(_self, _self.value);
  auto itr = datas.find(type_id);
  auto liker_itr = users.find(liker.value);

  datas.modify(itr, same_payer, [&](auto& row){
    row.like_num++;
  });
  users.modify(users.find(itr->author.value), same_payer, [&](auto& user){
    user.like_num++;
  });

  if(liker != itr->author){

    bool istoday = is_today(liker_itr->last_like_time.sec_since_epoch());  

    if(!istoday || (istoday && liker_itr->like_times < 10)){

      auto tokens = asset(get_like_reward(liker), TOKEN_SYMBOL);

      issue_token(tokens);
      users.modify(liker_itr, same_payer, [&](auto& user){
        user.balance += tokens;
        user.last_like_time = time_point_sec(current_time_point()); 
        user.like_times = istoday ? (user.like_times + 1) : 1;
      }); 

      issue_token(tokens);
      users.modify(users.find(itr->author.value), same_payer, [&](auto& user){
        user.balance += tokens;    
      });  
      datas.modify(itr, same_payer, [&](auto& row){
        row.balance += tokens;
      }); 
    }      
  }
}

对于微文点赞和评论点赞,业务逻辑都是一样的,只是数据类型不同,因此可以用函数模板来实现这个功能;

update_like_data函数内部实现了微文DAPP的核心业务:点赞挖矿,每个用户的每天前10个赞为能量赞,每次点出能量赞,点赞者和作者都会获得随机数量的WEI代币。

完成上面所有逻辑后,点赞数据被添加到liketable表中。

关注/取关

用户可以关注或取消关注其他用户,实际上就是对followtable表增/删数据,关注使用weiwendappss::follow Action,取消关注使用weiwendappss::unfollow Action,代码如下:

/**
 * 关注
 */
ACTION follow(name from, name to) {
  require_auth(from);

  check_user(from);
  check_user(to);

  check(from != to, "can not follow yourself");

  follow_t follows(_self, _self.value);
  auto secondary = follows.get_index<"byfrom"_n>();

  for(auto itr = secondary.lower_bound(from.value); itr != secondary.upper_bound(from.value); itr++){
    if(itr->to == to){
      check(false, "already followed");
    }
  }

  follows.emplace(from, [&](auto& follow){
    follow.id = follows.available_primary_key();
    follow.from = from;
    follow.to = to;
  });
}

/**
 * 取消关注
 */
ACTION unfollow(name from, uint64_t id) {
  require_auth(from);

  follow_t follows(_self, _self.value);
  auto itr = follows.find(id);

  check(itr != follows.end(), "follow does not exist");
  check(itr->from == from, "invalid follow");

  follows.erase(itr);
}

和check_liked函数类似,follow也使用了二级索引,来判断是否是重复数据。

部署合约到Jungle测试网

到这里,weiwendappss智能合约就基本开发完成了,下面使用在Jungle测网注册的账户weiwendappss来部署合约,后续添加新的功能或者修复bug可以重新部署:

cleos -u http://jungle2.cryptolions.io set contract weiwendappss weiwendappss -p weiwendappss

Tips

项目代码在Github同步更新:https://github.com/songguo6/weiwen-dapp

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册