How to handle effect webhook calls
In this example we will implement simple HTTP server in Node.js express which will handle the call to the webhook url defined in an effect registered previously.
We will receive an event when balance is received to a wallet as a result of successfully cleared intent which contains a claim targeting the wallet (either issue
or transfer
claim). Ledger will raise an event with balance-received
signal for each wallet which receives the balance. Event will be forwarded by the registered effect to our HTTP server with event body containing:
- handle - unique identifier of the event, used for idempotency
- signal - signal of the event, string
- amount - amount of balance received
- wallet - wallet record which received the balance
- symbol - symbol record of the received balance
- intent - intent record which caused balance change
We will verify the event payload and execute side-effect in external system. This side-effect can, for example, execute the transaction in banking core, send email to user, or even send new intent to the Ledger. We will use handle for idempotency check to ensure that the same event is not already processed (it can happen with retries mechanism if the ledger didn’t receive success response due to network error).
Webhook handler should acknowledge that event is delivered as soon as possible by responding with a success HTTP status code (2XX) and perform internal processing after that. Every other response status code including the network error will be considered by Ledger as failed delivery and it will retry it with exponential backoff, or stop retrying only in case of the response status code being 501 Not Implemented
. The exponential backoff uses a 20% delay step increase (1s, 1.2s, 1.44s, etc., with a maximum of 1 hour) until a confirmation in the shape of a success status code is received in the http response.
Webhook handler should verify that the event payload is signed with a known ledger key. It is a proof that it originates from this ledger instance and is not changed in transport. For that the handler should keep the public key of the ledger and use it for verification as shown in code snippet.