This is a hands-on tutorial that walks through building a simple refuel automation using a JS script. Perfect for getting familiar with core API types and execution flows.
While the Execution Layer provides the foundational security and access control for automations, the Orchestration Layer enhances it with scheduling capabilities. For complex automation scenarios that go beyond the standard scheduling API, developers can directly utilize the core execution endpoints. Let's explore this flexibility through an example.
A Simple Cross Chain Refuel BOT
An automation built using Console Automation APIs that helps keep ETH balances topped up across different chains.
Users can subscribe by providing:
A refuelAddress to monitor
minAmount of ETH to maintain
List of chains to watch
The automation checks if the refuelAddress drops below minAmount of ETH on any of the specified chains. If it does, it automatically bridges funds to keep the balances above the minimum threshold
Creating the Automation
To create an automation, the executor must first configure the automation parameters.
Once we have the automation parameters defined, we can create a helper to sign the parameters, as this signature is required for automation creation.
constprovider=newproviders.JsonRpcProvider(RPC_URL);constsigner=newWallet(EXECUTOR_PRIVATE_KEY, provider);asyncfunctionsignAutomationRegistrationMessage(domain, types, message) {try {// Create a wallet instance using the private keyconstwallet=newethers.Wallet(privateKey);// Sign the message according to EIP-712constsignature=awaitwallet._signTypedData(domain, types, message);console.log("Signature:", signature);return signature; // Return the generated signature } catch (err) {console.error("Error signing message:", err);throw err; }}
Here, RPC_URL and EXECUTOR_PRIVATE_KEY must be configured with appropriate values.
Once the signature is ready, we can simply call the POST/executor endpoint to create the automation for the executor.
constSVC_BASE_URL="https://gtw.brahma.fi";// Function to execute the API callasyncfunctionexecuteApiCall() {try {// Generate signatureconstsignature=awaitsignMessage(msgParams.domain,msgParams.types,msgParams.message );// Prepare the data for the POST requestconstdata= { config: { feeInBPS:msgParams.message.feeInBPS, feeReceiver:msgParams.message.feeReceiver, feeToken:msgParams.message.feeToken, limitPerExecution:msgParams.message.limitPerExecution, inputTokens:msgParams.message.inputTokens, hopAddresses:msgParams.message.hopAddresses }, executor:msgParams.message.executor, signature: signature,// Use the generated signature chainId:msgParams.domain.chainId, timestamp:msgParams.message.timestamp, executorMetadata: { id:msgParams.message.clientId, name:"auto-refuel", logo:"https://smolrefuel.com/logo.png", metadata: {} } };// Make the POST request using Axiosconstresponse=awaitaxios.post(`${SVC_BASE_URL}/v1/automations/executor`, data, { headers: {"Content-Type":"application/json" } } );console.log("Create Executor response:",response.data); } catch (error) {console.error("Error creating Executor response:", error); }}
Fetching subscribers of automation
Once the automation is created, Console users will be able to subscribe to the automation from console's Automation Marketplace. The automation executors can fetch a list of all subscribers and their metadata from the API, to perform further operations.
First, the executor's registryID must be fetched in order to fetch its subscribers.
constfetchExecutorByAddress=async (address, chainId) => {try {constresp=awaitAxios.get(`${SVC_BASE_URL}/v1/automations/executor/${address}/${chainId}` );returnresp.data.data; } catch (err) {console.log("err: failed to call fetchExecutorByAddress");throw"failed to fetch executor by address"; }};
Post fetching, we can also perform further cleanup to filter out the active subscriptions.
constfetchActiveSubscriptions=async (registryID) => {try {constresponse=awaitAxios.get(`${SVC_BASE_URL}/v1/automations/executor/${registryID}/subscriptions` );constsubscriptions=response.data.data;let activeSubscriptions = [];for (let subscription of subscriptions) {// filter our if not currently activeif (subscription.status !=CANCELLED_STATUS) {activeSubscriptions.push(subscription); } }return activeSubscriptions; } catch (err) {console.log("err: failed to get subscriptions");throw"failed to get executor subscriptions"; }};
Checking if the automation should be executed for a subscriber
The automation only has to be executed, if the refuelAddress has a balance lower than the minAmount threshold on any given chain ID from chains. We define a function to perform a check to see if a target address has a low balance-