EigenLayer AVS API References

Comprehensive guide to working with gRPC endpoints and API references for the Ava Protocol EigenLayer AVS, including authentication and API methods.

To interact with the Ava Protocol, start by making a request to the gRPC endpoint. The protocol is defined in the protobuf directory. A user can use any protobuf client or SDK to make calls to this gRPC endpoint.

For example, using the Node.js @grpc/grpc-js package, you can make the call as shown in this file: https://github.com/AvaProtocol/EigenLayer-AVS/blob/main/examples/example.js. You can review it to learn how to construct a gRPC client if you're not yet familiar with gRPC.

Endpoint#

Ethereum#

aggregator.avaprotocol.org:2206

This run on Ethereum mainnet, you will need to spend actual ETH here to run and test task triggering.

Holesky#

aggregator-holesky.avaprotocol.org:2206

The AVS itself is run on holesky network, but all the target chain for automation is on Sepolia. Therefore, when scheduling task, once triggered, it will be run on Sepolia. Therefore, you don't need Holešky ETH, you only need to keep Sepolia Eth in your wallet or smart wallet.

You can use a few faucet links below to get Sepolia Eth:

Local dev#

If you're running the AVS locally using our docker compose in https://github.com/AvaProtocol/EigenLayer-AVS, you can connect to this endpoint

127.0.0.1:2206

Authentication#

To start interacting with our protocol for task management, the process consists of two steps:

  • Given a wallet address, exchange it for an auth token. This auth token allows you to perform task management for that wallet.
  • For any request that requires authentication, include this auth token in request metadata.

1. Exchange an auth token#

Call the GetKey method with the following data:

  • owner: your wallet address
  • expired_at: the epoch time when your key will expire
  • signature: sign a message in the format key request for ${wallet_address} expired at ${expired_at}

The response will include a key that can be set in the metadata of subsequent requests. The token will expire at the expired_at epoch.

You can refer to this example code for guidance on how to generate the signature.

2. Making a gRPC Request#

After obtaining the auth token, for any request that requires authentication, set the authkey: ${your-key-from-above} header in the request.

Since an account needs to send an auth key generated from the signature above, no one else will be able to view your data, ensuring that your task and parameter data remain private.

API Methods#

GetSmartAccountAddress#

rpc GetSmartAccountAddress(AddressRequest) returns (AddressResp)

This endpoint retrieves the smart wallet address for a specified owner. No authentication is required because this information can also be gathered from on-chain storage.

Request#

  • owner (string): The hex address of the account owner whose smart wallet address is being requested.

Response#

  • smart_account_address (string): The retrieved smart wallet address for the specified owner.
  • nonce (string): The current nonce of the smart wallet

CreateTask#

rpc CreateTask(CreateTaskReq) returns (CreateTaskResp)

This endpoint is used to create a new task with specific actions and triggers.

Request#

  • task_type (TaskType): The type of task to create, such as ETHTransferTask or ContractExecutionTask.
  • action (TaskAction): The action associated with the task, which can be either an Ethereum transfer (eth_transfer) or a contract execution (contract_execution). The action is complex data structure, refer to [below TaskAction structure] for more document.
  • trigger (TaskTrigger): Specifies the conditions under which the task should be executed. Triggers can be based on time, contract query, or an expression. start_at (int64): The epoch time (in seconds) after which the task becomes valid and can be triggered.
  • expired_at (int64): The epoch time (in seconds) after which the task is no longer valid and will not be triggered.
  • memo (string): An optional field to store arbitrary notes or metadata related to the task.

TaskAction

TaskAction is fundamentally a union type. Depending on task type, the relevant field contains the action data.

  • ETHTransfer: Used when the task is eth transfer

    • destination (string): The hex string address of recipient.
    • amount (string): the hex string of eth amount.
  • ContractExecution: Used when the task is ContractExecutionTask

    • contract_address (string): the target contract address in hex.
    • calldata (string): the encoded contract method and its argument to be send to the contract address.
    • method (string): optinally - only use for display/format purpose.
    • encoded_params (string): optinally - only use for display/format purpose.

TaskTrigger

TaskTrigger is also a union type. Depending on task type, the relevant field contains the trigger data.

  • trigger_type: an enum of TimeCondition, ContractQueryCondition and ExpressionCondition

  • schedule: use when the trigger_type is TimeCondition.

    • fixed (array): an list of epoch timestamp when the task can be triggered.
    • cron (string): a crontab expression re-present when the task can be triggert
  • contract_query: use when trigger_type is ContractQueryCondition Query a contract, if return value is true, the task is triggered.

    • contract_address (string): target contract address in hex format
    • callmsg (string): encoded payload in hex format to send to above contract
  • expression: use when trigger_type is ExpressionCondition Perform an expression with operator and function call support by our task engine. If it's evaluated to true, the task is t riggered.

    • expression (string): the raw expression. The language that we use is expr-lang. Beside the built-in primitive support by expr-lang, We supported below functions to work with onchain data:

      • readContractData(contract_address, callmsg): the parameter is similar to contract query with contract_address and callmsg. The queried value is returned.
      • latestRoundDataChainlink": chainlinkLatestRoundData
      • bigCmp(a, b): compare to Ethereum big int, return 0 if a == b, return 1 if a > b, return -1 if a < b
      • toBigint(value): Map to Ethereum ParseBig256

Response#

  • id (string): The unique identifier of the created task.

ListTasks#

This endpoint returns a list of tasks associated with the account identified by authkey

Request#

No parameters are needed in the request.

Response#

  • tasks (repeated TaskItemResp): A list of task items associated with the account.
  • id (string): The unique identifier of the task.
  • status (TaskStatus): The current status of the task, such as Active, Completed, Failed, etc.

CancelTask#

rpc CancelTask(string) returns (google.protobuf.BoolValue)

This endpoint is used to cancel the task identified by the given ID. The task will be stopped from running. Only tasks in active status can be canceled.

Request#

  • id (string) The unique identifier of the task to be deleted.

Response#

BoolValue (google.protobuf.BoolValue): Indicates whether the cancellation was successful (true) or not (false).

DeleteTask#

rpc DeleteTask(string) returns (google.protobuf.BoolValue)

This endpoint deletes a task associated with the given task id

Request#

  • id (string) The unique identifier of the task to be deleted.

Response#

BoolValue (google.protobuf.BoolValue): Indicates whether the deletion was successful (true) or not (false).

API clients#

Becuase we use gRPC, so you can leverage the vast ecosystem of gRPC and Protocol Buffer when working with our AVS. Using protocol definition in protobuf anyone can generate a client use traditional grpc tool, or dynamically generate the client.

Useful links when working with gRPC:

NodeJS Example#

You can refer to this example for a demonstration of how to construct the gRPC client and make call. The step are as below:

  1. Generate gRPC client code with your language

    grpc_tools_node_protoc --js_out=import_style=commonjs,binary:./static_codegen/ --grpc_out=grpc_js:./static_codegen/ --proto_path=../protobuf avs.proto
    

    This step is useful because it allow you to access the primitive types, enum definion, class etc by importing the JavaScript file in directory static_codegen

  2. Initialize a gRPC client

    At minimum, this is enough to establish a dynamic client.

    const packageDefinition = protoLoader.loadSync('path/to/avs.proto', {
        keepCase: true,
        longs: String,
        enums: String,
        defaults: true,
        oneofs: true
    })
    const protoDescriptor = grpc.loadPackageDefinition(packageDefinition)
    const apProto = protoDescriptor.aggregator
    const client = new apProto.Aggregator(avsEndpoint, grpc.credentials.createInsecure())
    

    You can always access avs.proto file in https://github.com/AvaProtocol/EigenLayer-AVS/blob/main/protobuf/avs.proto. A common approach is use submodule to manage this file. We plan to eventualy automatically published this file to npm for the convenience usage.