Datai SDK API Reference
Command Line Interface (CLI)
Datai CLI is a collection of helpers and tools to help you build, test and deploy projections. It consists of a few key parts.
create-datai-app
Executed with npx create-datai-app
, this command will create a new Datai project in the current directory. Generally one datai project is enough for all your projection development needs. A Datai App is a scaffolding/contaienr for all your projections.
This command will create a project in the current directory with the following structure:
Directory.devcontainer
- …
DirectoryAPI
- …
Directorygraph-node
- …
Directoryprojections
Directoryassembly
Directorylibs
- …
Directoryprotocols
- …
Directorytemplates
- …
Directorytypescript
- …
.devcontainer
Configuration of the VS Code Dev Containers for the project.
API
Protocol buffer definitions for the Datai API used by the host application to communicate with the subgraph and the watcher.
graph-node
Configuration for the local Graph Node that will be used to deploy the subgraph and the watcher.
projections
Projections are the main part of the Datai project. They are divided into two main parts: assembly
and typescript
.
assembly
Main part of the projection. It contains all the protocol definitions, templates and libraries used to build the projection.
libs
Contains libraries that can be used across multiple protocols and templates.
protocols
Contains yaml filtes that define protocol data sources and graph templates.
templates
Contains projection implementations that use protocol definitions from the folder above. Templates have a substructure of network folders. This is important becuase the build scripts will be looking for projections based on the specified network.
- …
Directorytemplates
Directorymainnet
- …
Directoryarbitrum
- …
- …
- …
typescript
Contains scripts written in TypeScript that will be used to compile, build and deploy the projection.
build
Executed with yarn
this script will compile projection’s subgraph and watcher code into a format that can be deployed to graph-node
It’s important to remember how you name your projection files and templates. They directly tie back to the folder structure. For example:
yarn build uniswap2_liquidity uniswap2 liquidity_pool mainnet
This will take the projection configuration from projections/assembly/protocols/uniswap2.liquidity_pool/mainnet/uniswap2_liquidity.yaml
as well as the template files from projections/assembly/templates/mainnet/uniswap2_liquidity
and compile them into a format that can be deployed to graph-node
.
Let’s break it down into parts:
projections/assembly/protocols/<PROTOCOL>.<MODULE>/<NETWORK>/<TEMPLATE>.yaml
projections/assembly/templates/<NETWORK>/<TEMPLATE>
Partial builds
If you want to build only the subgraph or the watcher, you can use the following arguments.
Build just the subgraph
Build just the watcher
deploy
Executed with yarn
this script will deploy the compiled projection to graph-node
. The argument reference is the same as the build
script.
The result will be a deployed subgraph and watcher on the specified network. Pay attention to the name of your subgraph and watcher that you’ve been given by the network. It follows this pattern:
<PROTOCOL>__<MODULE>___NETWORK
For example
uniswap2__liquidity_pool___mainnet
Partial deploys
If you want to deploy only the subgraph or the watcher, you can use the following arguments.
Deploy just the subgraph
Deploy just the watcher
Schema
Common Entities
type User @entity(immutable: true)
The User
entity represents a user of the protocol. It is marked as immutable because the user’s ID should not change. The user entity has a one-to-many relationship with UserPosition
entities.
This entity is used to locate a user in the Datai Network when called by a gateway.
enum UpdateType
Update type tells the watcher on what condition a position should be updated in the network.
SCHEDULE
@Miquel I need your help here
EVENT
@Miquel I need your help here
type UpdateTrigger @entity
@Miquel I need your help here
type PositionUpdateTrigger @entity
@Miquel I need your help here
interface UserPosition
@Miquel I need your help here
Protocol Specific Entities
Generally each protocol will have its own set of entities that are specific to the protocol. You may want to store LP pair data, token metadata or protocol specific identifiers of positions.
Subgraph
Subgraph is responsible for crawling the network block by block and saving a trigger every time a user enters a position in a protocol. It then registers the position for the watcher to observe and compute the position balances.
SDK Function Reference
There are a few key functions you’ll be using to successfully create a projection.
ensureUpdateTrigger(positionId: ID!): Boolean
This function is used in event mappings to ensure that an UpdateTrigger
exists for a given UserPosition
. Use it to abort the execution of registering a user position if the trigger already exists.
registerUser(userId: ID!): User
Accepts a user ID and returns the User
entity. If the user does not exist, it will create a new user entity.
Watcher
SDK Function Reference
export function GetActivePositions(): void
Every watcher needs to export a function called GetActivePositions
. This function is called by the host application to compute the active positions of a user.
activePositions.inputPosition<T>()
A function that injects a position id into the watcher from a registered trigger in the subgraph.
<T>
Type of a specific position entity that the watcher will be computing. For example Uniswap2UserPosition
. A UserPosition
entity must contain an id. The id should be composed of <WALLET>-<POSITION_ID>
.
class ActivePositionsResult()
A class that is used to store and mutate the computed active positions of a user.
tokenBalance(tokenBalances: Array<TokenBalancePd>, index: i32): TokenBalance
A function that returns a token balance of a specific token at a given index.
findBalance(tokenBalances: Array<TokenBalancePd>, tokenAddress: Address, tokenId: BigInt | null = null): BigInt | null
A function that returns the balance of a specific token in the token balances array.
setBalance(tokenBalances: Array<TokenBalancePb>, balance: BigInt, tokenAddress: Address, tokenId: BigInt | null = null): void
A function that sets the balance of a specific token in the token balances array.
supplyBalance(tokenAddress: Address, tokenId: BigInt | null = null): BigInt | null
A function that returns the supply balance of a specific token.
setSupplyBalance(tokenAddress: Address, balance: BigInt, tokenId: BigInt | null): void
A function that sets the supply balance of a specific token.
borrowBalance(tokenAddress: Address, tokenId: BigInt | null = null): BigInt | null
A function that returns the borrow balance of a specific token.
setBorrowBalance(tokenAddress: Address, balance: BigInt, tokenId: BigInt | null): void
A function that sets the borrow balance of a specific token.
rewardBalance(tokenAddress: Address, tokenId: BigInt | null = null): BigInt | null
A function that returns the reward balance of a specific token.
setRewardBalance(tokenAddress: Address, balance: BigInt, tokenId: BigInt | null): void
A function that sets the reward balance of a specific token.
set poolAddress(address: Address)
A function that sets the pool address of the active position.
get poolAddress(): Address
A function that returns the pool address of the active position.
set unlockTime(seconds: i64)
A function that sets the unlock time of the active position. Useful for time-locked positions like staked or vested.
get unlockTime(): i64
A function that returns the unlock time of the active position.
setPositionTokenBalance(tokenAddress: Address, balance: BigInt, tokenId: BigInt | null = null): void
A function that sets the token balance of the active position. This is different to setBalance as it indicates the balance of the token that represents the position. For example a rebasible token one could find in Aave or Compound protocols. Similarly this could be an LP token in Uniswap or Sushiswap.