#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
class [[eosio::contract]] addressbook : public eosio::contract {
struct [[eosio::table]] person {
uint64_t primary_key() const { return key.value; }
uint64_t get_secondary_1() const { return age;}
void send_summary(name user, std::string message) {
permission_level{get_self(),"active"_n},
std::make_tuple(user, name{user}.to_string() + message)
void increment_counter(name user, std::string type) {
permission_level{get_self(),"active"_n},
std::make_tuple(user, type)
typedef eosio::multi_index<"person"_n, person,
indexed_by<"byage"_n, member<person, uint64_t, &person::get_secondary_1>>
using contract::contract;
addressbook(name receiver, name code, datastream<const char*> ds): contract(receiver, code, ds) {}
void upsert(name user, std::string first_name, std::string last_name, uint64_t age, std::string street, std::string city, std::string state) {
address_index addresses(_code, _code.value);
auto iterator = addresses.find(user.value);
if( iterator == addresses.end() )
addresses.emplace(user, [&]( auto& row ) {
row.first_name = first_name;
row.last_name = last_name;
send_summary(user, " successfully emplaced record to addressbook");
increment_counter(user, "emplace");
addresses.modify(iterator, user, [&]( auto& row ) {
row.first_name = first_name;
row.last_name = last_name;
send_summary(user, " successfully modified record to addressbook");
increment_counter(user, "modify");
address_index addresses(_code, _code.value);
auto iterator = addresses.find(user.value);
eosio_assert(iterator != addresses.end(), "Record does not exist");
addresses.erase(iterator);
send_summary(user, " successfully erased record from addressbook");
increment_counter(user, "erase");
void notify(name user, std::string msg) {
require_auth(get_self());
EOSIO_DISPATCH( addressbook, (upsert)(notify)(erase));