The BVSSquaring library
One of the main reasons for the library’s existence is to centralize code that would otherwise be dispersed across various locations. This is true for the BVSSquaring
library, an abstraction library designed to streamline interactions with the specific BVS contract used in the Hello World BVS demo. Multiple programs (such as the aggregator, monitor, caller, etc.) can share its functionalities, enhancing reusability and testability.
We recommend each BVS to have it's own BVS abstraction library. However, know that the abstraction library may look quite different from the BVSSquaring
example as the needs could be vastly different,
// Interface declerations. The BindClient contains methods to create a new task,
// respond to task, read the input of a task, read the result of task and finishing
// initliaztion of a BVSSquaring instance
type BVSSquaring interface {
BindClient(string)
CreateNewTask(context.Context, int64) (*coretypes.ResultTx, error)
RespondToTask(ctx context.Context, taskId int64, result int64, operators string) (*coretypes.ResultTx, error)
GetTaskInput(int64) (*wasmtypes.QuerySmartContractStateResponse, error)
GetTaskResult(int64) (*wasmtypes.QuerySmartContractStateResponse, error)
}
// The implementation of BVSSquaring.
type bvsSquaringImpl struct {
io io.ChainIO
executeOptions *types.ExecuteOptions
queryOptions *types.QueryOptions
}
// BindClient finishes initlization first made by NewBVSSquaring()
// it setups contract execution and query options to be used later.
func (a *bvsSquaringImpl) BindClient(contractAddress string) {
// Setup contract execution options
a.executeOptions = &types.ExecuteOptions{
ContractAddr: contractAddress,
ExecuteMsg: []byte{},
Funds: "",
GasAdjustment: 1.2,
GasPrice: sdktypes.NewInt64DecCoin("uosmo", 1),
Gas: 200000,
Memo: "test tx",
Simulate: true,
}
// Setup query options
a.queryOptions = &types.QueryOptions{
ContractAddr: contractAddress,
QueryMsg: []byte{},
}
}
// Under the hood, CreateNewTask() invokes the cotract with the CreateNewTaskReq type
// this triggers the CosmWasm contract's execute() method
func (a *bvsSquaringImpl) CreateNewTask(ctx context.Context, input int64) (*coretypes.ResultTx, error) {
// Prepare the message to be sent to the contract. Here we instenshate a variable
// of type CreateNewTaskReq and containing our input variable
msg := types.CreateNewTaskReq{
CreateNewTask: types.CreateNewTask{
Input: input,
},
}
// Serialze the message and assign it into executeOptions
msgBytes, err := json.Marshal(msg)
(*a.executeOptions).ExecuteMsg = msgBytes
if err != nil {
return nil, err
}
// SendTransaction invokes the contract's execut() method on-chain
return a.io.SendTransaction(ctx, *a.executeOptions)
}
// RespondToTask() is used by aggregator to send results back to the BVS contract
func (a *bvsSquaringImpl) RespondToTask(ctx context.Context, taskId int64, result int64, operators string) (*coretypes.ResultTx, error) {
// Like CreateNewTask(). It constructs the message to be sent to the contract
msg := types.RespondToTaskReq{
RespondToTask: types.RespondToTask{
TaskId: taskId,
Result: result,
Operators: operators,
},
}
// Serialze the message and assign it into executeOptions
msgBytes, err := json.Marshal(msg)
(*a.executeOptions).ExecuteMsg = msgBytes
if err != nil {
return nil, err
}
// SendTransaction invokes the contract's execut() method on-chain
return a.io.SendTransaction(ctx, *a.executeOptions)
}
// GetTaskInput() queries the BVS contract about the input of a past task
func (a *bvsSquaringImpl) GetTaskInput(taskId int64) (*wasmtypes.QuerySmartContractStateResponse, error) {
// You'd be very familare with this now. Construt a message of the same type
// as the ones accepts on-chain.
msg := types.GetTaskInputReq{
GetTaskInput: types.GetTaskInput{
TaskId: taskId,
},
}
// Serialize the message. Unlike above examples we don't need to execute
// anything (there's nothing to write, we only want to read), thus Query()
// will be the method we use
msgBytes, err := json.Marshal(msg)
(*a.queryOptions).QueryMsg = msgBytes
if err != nil {
return nil, err
}
// Queries the contract and return result
return a.io.QueryContract(*a.queryOptions)
}
func (a *bvsSquaringImpl) GetTaskResult(taskId int64) (*wasmtypes.QuerySmartContractStateResponse, error) {
// DITTO. Construt a message to be sent to the contact
msg := types.GetTaskResultReq{
GetTaskResult: types.GetTaskResult{
TaskId: taskId,
},
}
// Serialize the message and prepare to qeury the contract
msgBytes, err := json.Marshal(msg)
(*a.queryOptions).QueryMsg = msgBytes
if err != nil {
return nil, err
}
// Queries the contract and return result
return a.io.QueryContract(*a.queryOptions)
}
// Create a new instance of BVSSquaring
func NewBVSSquaring(chainIO io.ChainIO) BVSSquaring {
return &bvsSquaringImpl{
io: chainIO,
}
}
Last updated