#include <uosiolib/uosio.hpp> //合约库的头文件
#include <uosiolib/print.hpp> //使用打印输出,调试时候用
using namespace uosio; //uos合约的命名空间,接口都是在这个命名空间内
class [[uosio::contract]] addressbook : public uosio::contract {
//[[uosio::contract]]表示这个是合约,名称为 addressbook,必须从uosio::contract 继承
public:
using contract::contract; //直接使用 contract::contract 类型
addressbook(name receiver, name code, datastream<const char*> ds): contract(receiver, code, ds) {} //构造函数
[[uosio::action]]
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
require_auth(user); //需要 user用户的授权,即user用户发起的交易就可以执行。
address_index addresses(_code, _code.value);
auto iterator = addresses.find(user.value); //在表中查找user的对象
if( iterator == addresses.end() ) //没找到则插入
{
addresses.emplace(user, [&]( auto& row ){
row.key = user;
row.first_name = first_name;
row.last_name = last_name;
row.street = street;
row.city = city;
row.state = state;
send_summary(user, " successfully emplaced record to addressbook");
increment_counter(user, "emplace");
});
}
else { //找到记录则更新
std::string changes;
addresses.modify(iterator, user, [&]( auto& row ) {
if(row.first_name != first_name) { //如果新的名字和旧名字不一样
row.first_name = first_name; //使用新名字替换旧名字
changes += "first name "; //记载操作记录
}
if(row.last_name != last_name) {
row.last_name = last_name;
changes += "last name ";
}
if(row.state != state) {
row.state = state;
changes += "state ";
}
});
if(changes.length() > 0) {
send_summary(user, "successfully modified record in addressbook. Fields changed: " + changes); //发送通知信息
increment_counter(user, "modify"); //用于操作统计
} else {
send_summary(user, "called upsert, but request resulted in no changes.");
}
}
}
[[uosio::action]]
void erase(name user) { //删除操作
require_auth(user);
address_index addresses(_code, _code.value);
auto iterator = addresses.find(user.value);
uosio_assert(iterator != addresses.end(), "Record does not exist");
addresses.erase(iterator);
send_summary(user, " successfully erased record from addressbook");
increment_counter(user, "erase");
}
[[uosio::action]] //通知操作。合约本身有执行自己的权限
void notify(name user, std::string msg) {
require_auth(get_self()); //合约本身有执行自己的权限
require_recipient(user); //通知 user用户
}
private:
struct [[uosio::table]] person { //合约的数据结构
name key;
std::string first_name;
std::string last_name;
std::string street;
std::string city;
std::string state;
uint64_t primary_key() const { return key.value; }
};
void send_summary(name user, std::string message) { //发送通知信息
action(
permission_level{get_self(),"active"_n},
get_self(),
"notify"_n,
std::make_tuple(user, name{user}.to_string() + message)
).send();
};
void increment_counter(name user, std::string type) { //发送计数交易
action counter = action(
permission_level{get_self(),"active"_n}, //合约发布者的 active权限
"abcounter"_n, //合约发布者名称
"count"_n, //合约发布者发布的函数
std::make_tuple(user, type)
);
counter.send();
}
typedef uosio::multi_index<"people"_n, person> address_index; //合约表的索引结构
};
UOSIO_DISPATCH( addressbook, (upsert)(notify)(erase)) //申明合约可以被调用的接口