This plan outlines the steps to create a new Durable Object, ChainhookAggregatorDO, for managing and relaying blockchain events from an external chainhook service. It follows modern Cloudflare best practices, including RPC-style communication and SQLite-backed storage, and aligns with the project's existing architecture as described in docs/START.md.
-
Create New Durable Object File:
- Create
src/durable-objects/chainhook-aggregator-do.ts. - Define the
ChainhookAggregatorDOclass extendingDurableObject. - Add a constructor and placeholder RPC methods (
handleEvent,getStatus) and analarm()handler to establish the basic structure.
- Create
-
Update Worker Configuration:
- In
worker-configuration.d.ts, update theEnvinterface to include:CHAINHOOK_AGGREGATOR_DO: DurableObjectNamespace<ChainhookAggregatorDO>; HIRO_PLATFORM_API_KEY: string; // For the external service RELAY_WORKER_URL: string; // The endpoint for the relay logic
- In
wrangler.toml(or.jsonc):- Add a new durable object binding for
CHAINHOOK_AGGREGATOR_DO. - Add a migration for
ChainhookAggregatorDOusingnew_sqlite_classesto enable the SQLite backend. - Add secrets for
HIRO_PLATFORM_API_KEYandRELAY_WORKER_URL.
- Add a new durable object binding for
- In
-
Update Entrypoint for Routing (
src/index.ts):- Export the new
ChainhookAggregatorDOclass. - Add a new route like
/chainhook-event/[do-name]to the mainfetchhandler. This will be the public endpoint the external chainhook service calls. - This route handler will:
- Get the DO stub via
env.CHAINHOOK_AGGREGATOR_DO.idFromName('[do-name]'). - Call an RPC method on the stub (e.g.,
await stub.handleEvent(request)), forwarding the request.
- Get the DO stub via
- Export the new
-
Implement the
ChainhookAggregatorDOConstructor:- Initialize services like
Logger. - Use
ctx.blockConcurrencyWhile()to load the DO's state (e.g.,chainhook_id,last_block_hash) fromthis.ctx.storage. If state doesn't exist, trigger the initial chainhook creation logic and set the first alarm.
- Initialize services like
-
Implement State Management:
- Define class properties for the DO's state (
chainhook_id,last_activity_timestamp, etc.). - Use
this.ctx.storage.put()to persist state to durable storage after it's modified.
- Define class properties for the DO's state (
-
Implement RPC Method:
handleEvent(request):- This method receives the webhook payload from the main worker.
- Log the raw request body. This fulfills the requirement to capture the payload structure for future typing.
- Extract the
block_hashand updatelast_activity_timestampin storage. - Forward the payload to the
RELAY_WORKER_URLusingfetch(). - Log the result of the forwarding action.
-
Implement RPC Method:
getStatus():- Create this method to return the DO's current state from memory for debugging purposes, as planned in
START.md.
- Create this method to return the DO's current state from memory for debugging purposes, as planned in
-
Implement
alarm()Handler:- The alarm will periodically trigger this method.
- Inside, implement the health check: call the Hiro Platform API to get the status of the managed
chainhook_id. - If the hook is unhealthy or stale, log the issue and trigger a recreation method.
- Finally, call
this.ctx.storage.setAlarm()to schedule the next health check.
-
Implement Chainhook Creation/Recreation Logic:
- Create a private method (e.g.,
_recreateChainhook()). - This method will make an authenticated API call to the Hiro Platform to create a new chainhook, providing the public URL for the webhook (
/chainhook-event/[do-name]). - It will store the new
chainhook_idinthis.ctx.storage.
- Create a private method (e.g.,