CallbackConsumer
The CallbackConsumer
is a simple, easy-to-inherit interface that developers can use in their smart contracts to create one-time reqests for off-chain output, delivered via callback.
It is best used when your contract does not need to create a recurring Subscription and instead requests off-chain compute in an asynchronous callback fashion.
Using this consumer
Install dependencies
Before getting started, ensure you have installed the Infernet SDK in your Solidity smart contract project. You can follow the installation instructions found in the introduction.
Inherit CallbackConsumer.sol
In your smart contract, you must inherit the CallbackConsumer.sol
abstract contract found in infernet/core/consumers/Callback.sol
:
import {CallbackConsumer} from "infernet/core/consumers/Callback.sol";
contract MyContract is CallbackConsumer {}
Initialize the consumer
Once inherited, you must provide the address to the Infernet registry
contract (see Coordinator if unfamiliar) to the CallbackConsumer
constructor:
import {CallbackConsumer} from "infernet/core/consumers/Callback.sol";
contract MyContract is CallbackConsumer {
constructor(address registry) CallbackConsumer(registry) {}
}
Request container compute via callback
By default, the CallbackConsumer
exposes a _requestCompute()
function (technical reference) that allows initiating a one-time callback request for compute.
We can use this function to execute an example call to run our off-chain test-model
ML container workflow with some example feature inputs abcde
and request a response from a single node:
Keen observers will notice that, behind-the-scenes, a one-time callback
request is simply implemented as a
Subscription that has frequency == 1
(only
processed once) and period == 0
(immediately available for response from an
Infernet node).
import {CallbackConsumer} from "infernet/core/consumers/Callback.sol";
contract MyContract is CallbackConsumer {
constructor(address registry) CallbackConsumer(registry) {}
function callMyModel() external {
_requestCompute(
"test-model", // Container ID for our ML model
bytes("abcde"), // Inputs
1, // Only 1 responding node
// No payment
address(0),
0,
address(0),
// No proof verification
address(0)
)
}
}
Receive container output via callback
By default, the CallbackConsumer
exposes a _receiveCompute()
function (technical reference) which is called every time your smart contract receives a callback response from an Infernet node. This is where you should consume your response outputs, do proof verification, or store response data.
In our example, we will simply push the received output
from our test workflow above to an outputs
array for future consumption.
Note that the _receiveCompute()
function can only be called by the
Coordinator
, and, in-kind, registered and active Infernet nodes. The
entrypoint for the Coordinator
is the authorized
rawReceiveCompute
function.
import {CallbackConsumer} from "infernet/core/consumers/Callback.sol";
contract MyContract is CallbackConsumer {
bytes[] public outputs;
constructor(address registry) CallbackConsumer(registry) {}
function _receiveCompute(
uint32 subscriptionId,
uint32 interval,
uint16 redundancy,
address node,
bytes calldata input,
bytes calldata output,
bytes calldata proof,
bytes32 containerId,
uint256 index
) internal override {
// We simply track `output` for future consumption in our callback
outputs.push(output);
}
function callMyModel() external {
_requestCompute(
"test-model", // Container ID for our ML model
bytes("abcde"), // Inputs
1, // Only 1 responding node
// No payment
address(0),
0,
address(0),
// No proof verification
address(0)
)
}
}
Test your implementation
That's all it takes to get started with the CallbackConsumer
! You're now ready to test your implementation with mock data (see testing best practices) and deploy your contracts.