REMP (Reliable External Messaging Protocol) is a set of protocols and data structures that are designed to keep trace of incoming external messages and predict with a high probability whether a message will be processed successfully.
REMP adds some additional guarantees/features for external messages processing:
1. Replay protection
If a message is processed and added into an accepted block, then the same message (that is, the message with the same hash) will not be collated for some time period. If the message has some expiration time (corresponding to the time period), then this effectively makes efficient replay protection.
2. No messages are lost
You only need to send the message once. If there will be a possibility to accept it and add it to a block, then it will be done. Message loss may occur only for blockchain overloading reasons.
3. One can trace the message processing.
There are several checkpoints on the message processing path (when validators received the message, when message was added to a block, when the block was finalized, etc). Upon reaching certain checkpoints one can predict that the message will be successfully processed with a high accuracy - most messages can be considered to be processed when validators acknowledge that they were received (this happens in 100-200 ms; after that it’s highly unlikely that the message is declined). Thus, depending on the message importance one may trade efficiency for reliability in the software, choosing not to trace further processing results. On the other hand, if a transaction is really important, then you can wait till the block with the transaction result is issued.
During validation, as the message passes through various stages (that is, changes some statuses), validator sends receipts about each.
This guide teaches to work with REMP and REMP receipts in EVER SDK.
Pass this endpoint as a parameter when running the example.
Working with REMP statuses
The sample sends a message to a predeployed test contract.
(async () => {try {console.log('Sending messsage and waiting for REMP events.');const { transaction } =awaitclient.processing.process_message( { send_events:true, message_encode_params: { address:CONTRACT_ADDRESS, abi:abiContract(CONTRACT_ABI), call_set: { function_name:'touch', }, signer:signerNone(), }, }, responseHandler, );console.log( [`The message has been processed.`,`${rempEventCnt} REMP events received`,`Transaction id: ${transaction.id}, status ${transaction.status_name}`, ].join('\n'), );client.close(); } catch (error) {if (error.code ===504) {console.error('Network is inaccessible.'); } else {console.error(error); }process.exit(1); }
After the message is sent all REMP events related to the message are received and printed, tracing the message processing by validators.
Note: By REMP events one can predict with a high probability that the message will be processed successfully, before the processing is complete. Depending on message importance, you can choose to consider it processed as soon as the corresponding receipt arrives and not spend time and resources waiting for further status receipts.
functionresponseHandler(params, responseType) {// Tip: Always wrap the logic inside responseHandler in a try-catch block// or you will be surprised by non-informative errors due to the context// in which the handler is executedtry {if (responseType ===100/* GraphQL data received */) {const { type,json,error } = params;assert.ok(type,'Event always has type');if (type.startsWith('Remp')) { rempEventCnt++;// All REMP event types starts with `Remp`// https://docs.everos.dev/ever-sdk/reference/types-and-methods/mod_processing#processingeventassert.ok(json || error,'All REMP event has `json` or `error` property');if (json) {// We print all REMP events.console.log(`\tREMP event type: ${type}, kind: ${json.kind}`);// but you can pay attention to only a few kinds of events:if (json.kind ==='IncludedIntoBlock') {console.log('\t^^^ this message is probably to be processed successfully'); }if (json.kind ==='IncludedIntoAcceptedBlock') {console.log('\t^^^ this message is highly likely to be processed successfully', ); } }if (error) {// Errors here indicate that there was a problem processing the REMP.// This does not mean that the message cannot be processed successfully,// it only means that the SDK just didn't get the next status at the expected time, see// TonClient config params: `first_remp_status_timeout`, `next_remp_status_timeout`// https://docs.everos.dev/ever-sdk/reference/types-and-methods/mod_client#networkconfig// // In this case, the SDK switches to the scenario of waiting for a standby transaction (sequential block reading).
console.log(`\tREMP event type: ${type}, code: ${error.code}, message: ${error.message}`, ); } } else {// In this example we are interested only in REMP events, so we skip// other events like `WillFetchFirstBlock`, `WillSend`, `DidSend`.// console.log(`Basic event ${type}`); } } else {// See full list of error codes here:// https://docs.everos.dev/ever-sdk/reference/types-and-methods/mod_net#neterrorcodeconsole.log('ERROR', params, responseType); } } catch (err) {console.log(err); }