Skip to main content

Required Interface

The Steer Protocol is possible due to a robust and flexible API which allows developers to build their own jobs and apps. Below is the interface for the v1.0.0 of the Steer Protocol.

info

This interface must be adhered to in order to be compatible with the Steer Protocol.

App must consist of 3 main functions:

Configuration

Most apps require configuration. JSON Schema is used to provide the proper interface between the bundle and their consumers (keeper and interfaces). The configured JSON Schema is also used to validate the configuration of the app params on the Steer Protocol when being set. The configuration object defined by the schema definition is passed into the initiliazer of the app.

tip

Hint: App creator can check if the configuration object is proper via the backtesting toolset.

Interface (Assemblyscript)

export function config(): string

Example (Assemblyscript)

export function config(): string {
return `{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Strategy Config",
"type": "object",
"expectedDataTypes": ["OHLC"],
"properties": {
"percent": {
"type": "number",
"description": "Percent for trailing stop order",
"default": 5.0
},
"poolFee": {
"description": "Pool fee percent for desired Uniswapv3 pool",
"enum" : [10000, 3000, 500, 100],
"enumNames": ["1%", "0.3%", "0.05%", "0.01%"]
},
"binWidth": {
"type": "number",
"description": "Width for liquidity position, must be a multiple of pool tick spacing",
"default": 600
}
},
"required": ["percent", "binWidth", "poolFee"]
}`;
}
info

Inside the static config, there is a extra field called expectedDataTypes which define the type of data used by the app.

Initialize

The wasm bundle will be loaded by the keeper nodes and initialized with the configuration object previously created. Any necessary values needed for execution should be stored in memory to be used when execute is called. The initialize function can be optional if no configuration is needed.

Interface (Assemblyscript)

export function initialize(config: string): void

Example (Assemblyscript)

export function initialize(config: string): void {
// Parse the config object
const configJson = <JSON.Obj>JSON.parse(config);
// Get our config variables
const _width = configJson.getInteger("binWidth");
const _percent = configJson.getNum("percent");
// Handle null case
if (_width == null || _percent == null) {
throw new Error("Invalid config");
}
// Assign values to memory
width = i32(_width._num);
percent = f32(_percent._num);
}

Execute

Execution of an app is dependent on its datasets. The datasets are passed into the execute function of the app and then used to calculate the results of the app. The results are then published on the Steer Network which will facilitate on-chain execution.

The result of a given app is dependent on the vault which is used to execute the app. For instance, for a concentrated liquidity app the tend function request should be returned. Please check with the documentation of the vault to see what the proper function and types are. Any discrepencies will cause the execution to fail.

tip

The result of the execution is passed into a class called the TransactionFactory in the node, which handles Keeper voting and on-chain execution.

info

The result is always stringified JSON. This allows for interpretation across execution environments.

Interface

public execute(_dataSources: string): string

Where the parameter _dataSources will be a stringified array with each item being the resulting data from each DataConnector in order. The string returned from the execute method will be a stringified object with the following elements:

interface transactionRequest
{
functionName: string;
typesArray: string[];
valuesArray: Type[];
}

If you wish for no action to be taken by the orchestrator (useful for cutting down on gas costs) you can return the string continue from the execution bundle.

info

This interface must be adhered to in order for actions to be completed on-chain.

functionName: This should be the function selector for the function you wish to call on the associated vault. It will have the function name followed by the input parameter types. Follow this link to learn more about function selectors.

typesArray: Very similar to the types that will be in the function selector, this array of types is used to encode the valuesArray.

valuesArray: Lastly these are the values that will be passed as the encoded parameters into the desired vault function.

info

To learn more about encoding and types visit https://docs.soliditylang.org/en/v0.8.15/abi-spec.html#types.

Example (Assemblyscript)

export function execute(_prices: string): string {
// ...custom logic...
return
`{
functionName: "tend(uint256,(int24[],int24[],uint16[]),bytes)",
typesArray: ["uint256","tuple(int24[],int24[],uint16[])","bytes"],
valuesArray: [10000, [[22920],[23040],[1]], '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff']
}`;
}

Take note of the tuple type here; the type is wrapped in parenthesis in the selector, but square brackets in the values array. Consult the Solidity Docs to correctly format complex types. If you are curious about the bytes placeholder in this example, read these observations on how we can inject time-sensitive data with consensus.

Version

Steer is ever evolving, and our interfaces might change. We will offer backwards compatibility for all versions we introduce.

Interface

export function version(): i32

As more versions are released the breaking changes will be listed here.

Example (Assemblyscript)

export function version(): i32 {
return 1;
}