You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, when calling createScheduledData, you need to pass a blockHeight: number of when to trigger the event. Of course, if you're using emulated blocks or a chain that has a deterministic block time, this works fine. However, not all networks have this and not all use-cases benefit from emulated blocks.
It is actually possible right now to do this even without emulated blocks. You can do this using the following trick:
Schedule an event for next block
Once the event from (1) triggers, check the timestamp in the header
If the timestamp is less than your target, just schedule an event again
Of course this works, but it's ugly to do this from a user perspective. It feels like something that is an engine-level feature
There are two ways we could handle this at the engine level:
Reschedule every block: just like mentioned above, we could reschedule the event every block on their behalf until the right time has come. All this requires is tracking in the database some new target timestamp
Advantage: requires minimal code change
Disadvantage: constantly recreating events like this messes with statistics and explorers for the game (ex: Unblock EVM RPC emulation #411) because it's constantly spamming transactions (although at least they all get deleted)
Create a new event type: instead of using the scheduled data which requires a block, we should have some new event system that instead uses a timestamp (or make the block field optional in the existing system, along with a new timestamp field). Then, when it's time for an STF call, we check if there any events with a timestamp ready to use
Advantage: we don't need to constantly re-create scheduled data. It can just be a single event that gets triggered when necessary
Disadvantage: requires handling of this new block-less schedule data type
Note: it's not really possible to have timers trigger the STF without a block being made, as this functionally ends up being equivalent to the emulated block feature
Additional consideration: timezones
If you want to schedule events at a specific time instead of a block, it's reasonable you may want to schedule for a specific timezone (ex: midnight PST). However, this has two unfortunate problems:
Timezones change: some areas have daylight savings so the time mapping changes during the year. Additionally, if some US states decide to abolish daylight savings, the mapping of Unix timestamp to midnight changes as well. In practice, as long as all nodes apply this change at the same time in the same way, it won't cause any issues.
Tricky support: to solve the problem mentioned in (1), we need a library to maps timezones in a way that is not only smart enough to handle things like daylight savings, but to also keep that library up-to-date to take into account any laws pass that affect timezones of importance
Implementing timezones: Date api
One option for implementing this is using nodejs's built-in support for the IANA timezone database. Although this is great as it means no external dependencies are required, it does come with some issues:
It means that to update your timezone database, you also need to update your nodejs version
The nodejs version of the database is not guaranteed to match the version used by your browser
However, if we did us the nodejs route, the code to start a timer based on midnight Japan starting from the first block would look like the following unfortunately long code block.
conststartBlockDate=newDate(blockHeader.timestamp);const[hours,minutes,seconds]=startBlockDate.toLocaleString('en-US',{timeZone: 'Asia/Singapore',// insert the desired timezone herehour: 'numeric',hour12: false,minute: 'numeric',second: 'numeric',}).split(':').map(Number);// since we can't know when a day ends (it ends at a different time during leap seconds for example)// we instead subtract time back to 00:00constmidnightDate=newDate(startBlockDate.getTime()-(hours*60*60+minutes*60+seconds)*1000);midnightDate.setUTCMilliseconds(0);// we want to ignore ms, which are timezone independent anyway// add a day to get the next day// DANGER: this can be subtly wrong if "next day" on your machine is different than "next day" in the timezone you're interested in. To fix this, you would have to do another round of `toLocaleString` and adjust any offset// but I think at this point this code block has conveyed the built-in Date API is definitely not the way to go due to its complexitymidnightDate.setDate(midnightDate.getDate()+1);// this is our final timestamp we want!midnightDate.getTime()
Implementing timezones: Temporal api
There is an upcoming Temporal API coming to browsers and nodejs. It's currently supported on zero plaforms, but it is at stage 3 and the API is nice
// you need this import until Temporal is standardizedimport{Temporal}from'temporal-polyfill';constmidnightTimestamp=Temporal.Instant.fromEpochMilliseconds(blockHeader.timestamp).toZonedDateTimeISO('Asia/Singapore')// insert your timezone here.add({days: 1}).startOfDay().epochMilliseconds
Implementing timezones: dayjs package
This is a popular data management library in JS. It's not built-in, but it gets us a similar API as what Temporal would give us
constdayjs=require('dayjs');constutc=require('dayjs/plugin/utc');consttimezone=require('dayjs/plugin/timezone');dayjs.extend(utc);dayjs.extend(timezone);letspecificTimestamp=newDate();constnextDay=dayjs(blockHeader.timestamp).tz('Asia/Singapore')// insert your timezone here.add(1,'day').startOf('day').valueOf();
The text was updated successfully, but these errors were encountered:
Currently, when calling
createScheduledData
, you need to pass ablockHeight: number
of when to trigger the event. Of course, if you're using emulated blocks or a chain that has a deterministic block time, this works fine. However, not all networks have this and not all use-cases benefit from emulated blocks.It is actually possible right now to do this even without emulated blocks. You can do this using the following trick:
Of course this works, but it's ugly to do this from a user perspective. It feels like something that is an engine-level feature
There are two ways we could handle this at the engine level:
Note: it's not really possible to have timers trigger the STF without a block being made, as this functionally ends up being equivalent to the emulated block feature
Additional consideration: timezones
If you want to schedule events at a specific time instead of a block, it's reasonable you may want to schedule for a specific timezone (ex: midnight PST). However, this has two unfortunate problems:
Implementing timezones:
Date
apiOne option for implementing this is using
nodejs
's built-in support for the IANA timezone database. Although this is great as it means no external dependencies are required, it does come with some issues:However, if we did us the nodejs route, the code to start a timer based on midnight Japan starting from the first block would look like the following unfortunately long code block.
Implementing timezones:
Temporal
apiThere is an upcoming
Temporal
API coming to browsers and nodejs. It's currently supported on zero plaforms, but it is at stage 3 and the API is niceImplementing timezones:
dayjs
packageThis is a popular data management library in JS. It's not built-in, but it gets us a similar API as what Temporal would give us
The text was updated successfully, but these errors were encountered: