Inline Actions - Discussion

Welcome to the discussion thread about this lecture section. Here you can feel free to discuss the topic at hand and ask questions.

Hi @filip can you take a quick look for me - the contract compiled and created the abi & wasm files. I am adding, modifying and removing dogs but the event is not firing the event to notify that something has changed.

S-Mac-Pro:src seamo$ cleos push action inline modify ‘[4, “toto”, 7]’ -p seamo
executed transaction: 9d01af002c3e178af0a4185056c33bacfd456eee4131e775a6f4943308980143 112 bytes 227 us
/esc for text #) # inline <= inline::modify {“dog_id”:4,“dog_name”:“toto”,“age”:7}
warning: transaction executed locally, but may not be confirmed by the network yet ]
S-Mac-Pro:src seamo$ cleos push action inline modify ‘[4, “lolo”, 6]’ -p seamo
executed transaction: b7f21aea5f8113864de533c84a4ad597c1e42318174b147788f49b1708b8a8ba 112 bytes 215 us
/esc for text #) # inline <= inline::modify {“dog_id”:4,“dog_name”:“lolo”,“age”:6}
warning: transaction executed locally, but may not be confirmed by the network yet ]
S-Mac-Pro:src seamo$

---- code –

#include <eosio/eosio.hpp>
#include <eosio/print.hpp>

using namespace eosio;

CONTRACT hellotable : public contract {
public:
using contract::contract;

hellotable(name receiver, name code, datastream<const char*> ds):contract(receiver, code, ds) {}

ACTION insert(name owner, std::string dog_name, int age){
  require_auth(owner);
  dog_index dogs(get_self(), get_self().value);
  // owner will need to have the resources available to pay for the contract storage.
  dogs.emplace(owner, [&](auto& row){ //lambda function to initialise the row(s) we use.
    row.id = dogs.available_primary_key();
    row.dog_name = dog_name;
    row.age = age;
    row.owner = owner;
  });
  send_summary(owner, "inserted dog");
}

ACTION erase(int dog_id){
  dog_index dogs(get_self(), get_self().value);

  // the next two lines are not necessary for the delete but if not used anyone could delete anyones dog.
  auto dog = dogs.get(dog_id, "unable to find dog."); //this returns the data
  require_auth(dog.owner);

  auto iterator = dogs.find(dog_id); // this returns the position of the data (ike a pointer to the data)
  dogs.erase(iterator); //iterator is used to modify and delete rows.
  send_summary(dog.owner, "erased dog");
}

ACTION modify(int dog_id, std::string dog_name, int age){
  //get the index of the table
  dog_index dogs(get_self(), get_self().value);

  //fetch the current data of our dog
  auto dog = dogs.get(dog_id, "unable to find dog."); //this returns the data
  //require auth the owner
  require_auth(dog.owner);

  //get the iterator to be able to find and modify the row in the table
  auto iterator = dogs.find(dog_id);

  dogs.modify(iterator, dog.owner, [&](auto& row){
    row.age = age;
    row.dog_name = dog_name;
  });
  send_summary(dog.owner, "modified dog");
}

//remove all dogs by a specific owner
ACTION removeall(name owner){
  dog_index dogs(get_self(), get_self().value);
  auto owner_index = dogs.get_index<"byowner"_n>(); // this gives access to the second index
  auto iterator = owner_index.find(owner.value);

  while (iterator != owner_index.end()){
    // modify dog row etc.. add, delete, print etc..
    owner_index.erase(iterator);
    iterator = owner_index.find(owner.value);
  }
  send_summary(owner, "removedall dog");
}

ACTION notify(name owner, std::string msg){
  require_auth(get_self()); //inline action call to notify
  require_recipient(owner); // notifies the user that action was complete - reciept to user (action made on behalf of the user)

}

private:
TABLE dog{
int id;
std::string dog_name;
int age;
name owner;

uint64_t primary_key() const {return id;}
uint64_t by_owner() const {return owner.value;}

};

// triggers the notify function
void send_summary(name owner, std::string message){
action(
permission_level{get_self(), “active”_n},
get_self(),
“notify”_n,
std::make_tuple(owner, message)
).send();
}
typedef multi_index<“dogs”_n, dog, indexed_by<“byowner”_n, const_mem_fun<dog, uint64_t, &dog::by_owner>>> dog_index;

};

Hmmm, I copied your code and tried it myself. It worked for me. So I can’t find any errors there.

Did you add the eosio.code permission to your inline account? And are you sure you have the latest contract deployed to that account?

Hmmm indeed!!! Thanks a million for looking into it for me… I’ll go back over it and see if I missed a step… I am on the latest version of EOS “server_version_string”: “v1.8.2”. I have moved on and about to start the DApp stuff now. Everything worked for me apart from the inline action stuff. I will rewrite & redo the commands to see what I missed. Thanks again!! I really appreciate the reply!!

1 Like

Okay, created a folder and rewrote my project.

Tried compiling it, stuck at Warning, action <notify> does not have a ricardian contract.

3 mins gone at the time of posting still stuck.

Tried restarting the process, same result.

@filip any help will be appreciated.

UPDATE
30 minutes gone.

Sorry for the slow response. I have been sick for the past week.

That’s just a warning, not an error. You are good to continue. We have no need of a ricardian contract. I explain what that is later on in the course.

1 Like

@filip Still having problems getting pass : eosio-cpp -abigen -I include -R resource -contract hellotable -o hellotable.wasm src/hellotable.cpp

error: error reading ‘/Users/cherrybluemoon/src/hellotable.cpp’

1 error generated.

OR: eosio-cpp -abigen -o hellotable.wasm src/hellotable.cpp

Hi @filip, I have a questio: if a smart contract has permission to execute inline actions on behalf of an user account, how does the user know which actions will be executed? Wouldn’t it be possible for the contract to steal tokens from the user, for example?

I might have misunderstood your question, but that’s why we have the require statements? to create checkpoints in the code.
Ivo