A Job Specification is primarily made up of two parts: Initiators and Tasks. Tasks define what work is done and in which order. Initiators define when work should start.
Chainlink nodes ship with built in core adapters and initiators. In order to make Chainlink easily extendable, it supports External Adapters and External Initiators.
To decide when a Chainlink node should trigger Job Runs, users may want to act on all kinds of criteria. Each service a user may want to integrate has a different API, instead of expecting all of these services to meet Chainlink’s API, the Chainlink node allows for a thin proxy to be defined to easily extend functionality. Maybe a user wants push notifications from an external service to execute a Job Run.
Efficiently polling an external service is another great use case for a External Initiator. Another common use case is hooking up Chainlink to watch a blockchain that has not yet been integrated into the Chainlink Core node.
Communicating with the External Initiator
Communication between External Initiators is handled by the Initiator Bridge. Initiator Bridges handle the authentication to and from the External Initiator and where to send the messages.
When creating a Bridge two parameters are required: a Name and a URL. The Name is used in subsequent Job Specifications as an easy way to identify the Initiator that is triggering new Runs. The URL specifies where to send messages to the External Initiator.
When the Bridge is created it generates two pairs of credentials: Outgoing and Incoming. The Outgoing Access Key and Secret are used to authenticate messages sent from the Core to the External Initiator. The Incoming Access Key and Secret are used to authenticate messages sent from the External Initiator to the Core.
1. Neil, the node operator, spins up an External Initiator, and creates an Initiator Bridge pointing to the External Initiator.
Neil then configures the External Initiator with the credentials to secure communication to and from the External Initiator.
2. Neil creates a Job, whose Job Specification uses the External Initiator, on the Core.
3. The Core sends the External Initiator parameters from the Job Spec to the External Initiator and the Job ID, via the Initiator Bridge with Outgoing Credentials.
4. The External Initiator does whatever setup it needs to listen for events, e.g. subscribing to notifications or begin polling an external service.
5. The External Initiator uses arbitrary services/criteria/logic to decide when to notify the Initiator that it should run the job.
6. The External Initiator notifies the Core that it should run the Job. It sends the Job ID along with any Run Request parameters for initiating the Run, and authenticates with Incoming Credentials.
7. The Core creates a new Run of the Job initiated with whatever Run Request parameters, kicking off a new Run and triggering any necessary side effects.
Remove a Job
8. When a Job finishes, whether it hits its
endAt deadline or it is archived, the Core sends a DELETE request to the External Initiator with the Job ID.
9. The External Initiator then does any cleanup necessary related to the Job.
Imagine that Neil, the node operator, wants to offer a service where he will watch deposits to a Bitcoin address, and report those deposits on the Ethereum chain. Neil knows he can use the Bitcoin ZeroMQ integration to efficiently subscribe to push notifications from a Bitcoin node.
Neil spins up an instance of a Bitcoin node with ZeroMQ and builds a External Initiator to efficiently trigger Runs on his node.
Step 1: Neil registers a Bridge between his Chainlink node and his Bitcoin External Initiator.
Carol, the contract creator, wants to receive notifications about her Bitcoin address on Ethereum. She finds out on the Chainlink Market that Neil offers this service and asks Neil to send notifications about her address, 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.
Step 2: Neil creates a Job, with ID 789, whose Specification includes a External Initiator with parameters stating that it should listen to Carol’s Bitcoin address for updates.
Step 3: Upon Job creation, Neil’s node notifies the External Initiator that it wants to listen for updates to Carol’s address.
Step 4: The External Initiator opens a ZeroMQ subscription to the Bitcoin Node, listening for any updates to 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.
Now, for every payment that Carol receives to her Bitcoin address the following workflow is kicked off:
Step 5: The Bitcoin Node sends a ZeroMQ message to the External Initiator, informing it of that 558 Sats (or 0.00000558 Bitcoin) was just paid to 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.
Step 6: The External Initiator receives the ZeroMQ message and translates it into a Chainlink message, it sends a message to the Core as a Run Request, with Job ID 789 and params
Step 7: The Chainlink Core receives the Run Request from the External Initiator, with Job ID 789, and triggers a new Run for the Job. It takes the Run Request parameters, and sends them in an Ethereum transaction, indicating the 558 Satoshis paid to 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.
Step 8: The Chainlink Core reaches the end deadline for the Job and sends a DELETE request to the External Initiator with the Job ID 789.
Step 9: The External Initiator closes its ZeroMQ subscription to the Bitcoin node for address 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.