Can we have a function in a smart contract to be executed automatically after some time?
for example, transfer some tokens after every 5 seconds.
Can we have a function in a smart contract to be executed automatically after some time?
for example, transfer some tokens after every 5 seconds.
First of all you need to push a transaction initially and you have to write a deferred transaction that call itself recursively after a certain period of time. You should also write some basecase . Basecase condition can be stored inside a table (need to check every time). Deferred transaction can be seen as @John Haager metion. You can write a @abi action that call this transfer action inside you recursion like this:
// @abi action
void Democontract::actionDemo(account_name from, string memo, uint64_t duration, uint64_t interval)
{
uint64_t max_delay = 50;
string appending_char = "1";
print(int(duration));
eosio_assert((((memo.length() == 11) || (memo.length() == 12))), "\n check the length of memo");
//_ttab ttabs(_self, _self);
// you use table values here from your table (if you are using table in your code )
eosio::transaction txn{};
if (duration < interval)
{
print("reached final limit all transaction executed---");
}
else if (duration >= interval)
{
uint64_t delay = 0;
//call your transfer action here
if (duration >= interval)
{
//delay interval , duration - interval
print("duration > interval_________\n");
txn.actions.emplace_back(
eosio::permission_level(from, N(active)),
N(contractname),
N(actionDemo),
std::make_tuple(from, memo, duration - interval, interval));
txn.delay_sec = max_delay;
txn.send(eosio::string_to_name(memo.c_str()), from);
}
else if (duration < interval)
{
//delay duration, 0
print("duration <====== interval_________\n");
txn.actions.emplace_back(
eosio::permission_level(from, N(active)),
N(contractname),
N(actionDemo),
std::make_tuple(from, memo, uint64_t(0), interval));
txn.delay_sec = duration;
txn.send(eosio::string_to_name(memo.c_str()), from);
}
}
You can also modify this code to execute transaction more more that 45 days interval time.I also don't write transfer action you can call it inline as i mention in comment.duration(suppose you want this for 2 days) and Max_day is the interval you want to execute your action (after a specific time interval) rest of the things you can understand easily.
The deferred transaction method will work for a while, however Block One have said that there is no guarantee that a deferred transaction will execute at all. It could simply fail and in that case your code will probably end up in a bad state if it relies on this 5 second interval transfer.
An alternative method would be to set up a cron job to call the action from a server, although this has the disadvantage of semi-centralising the system.
You can combine both worlds:
eosio::assert(now() -last_transfer > 5*ONE_SECOND,"Can't call this now, must wait at least 5 seconds");
A deferred transaction can be created and submit that will be executed at the specified future time. If you want the action to execute again, then the action can simply schedule a new deferred transaction to invoke itself.
// Create a deferred transaction
transaction out{};
out.actions.emplace_back(
permission_level{_self, "active"_n},
_self,
"myaction"_n,
std::make_tuple(actionParam)
);
out.delay_sec = refundInterval;
out.send(deferredTxID, _self);