Viem
, a Typescript library similar to ethers.js
that simplifies the process of interacting with the Oracle contract.
Attention: Follow the examples carefully. It is recommended that you first test and deploy your code on Testnet before using Pricing Sylo on Mainnet.
Initial configuration
The account used will need sufficient balance to deposit in SYLOs and pay the associated gas fees.
All values used in these examples are for Porcini, The Root Network testnet.
Copy
Ask AI
import { createWalletClient, createPublicClient, http } from 'viem';
import { rootPorcini } from 'viem/chains';
const account = privateKeyToAccount("0x123abc");
const syloTokenAddress = "0xCCcCCcCC00000C64000000000000000000000000";
const oracleAddress = "0xf459E82138096876C25cd5fbc54c487476640619";
const publicClient = createPublicClient({
chain: rootPorcini,
transport: http("https://porcini.rootnet.app"),
});
const walletClient = createWalletClient({
account,
chain: rootPorcini,
transport: http("https://porcini.rootnet.app"),
});
export default { walletClient, publicClient, syloTokenAddress, oracleAddress };
Typical User Flow
Step 1: Deposit SYLO tokens to the Oracle.Copy
Ask AI
async function depositTokens() {
// First approve the Oracle to spend your SYLO tokens
const approvalHash = await walletClient.writeContract({
address: syloTokenAddress,
abi: ERC20_ABI,
functionName: "approve",
account,
args: [oracleAddress, parseUnits("100", 18)], // 100 SYLO tokens
});
// Wait for approval transaction to be mined
await publicClient.waitForTransactionReceipt({ hash: approvalHash });
// Deposit SYLO to the Oracle contract
const depositHash = await walletClient.writeContract({
address: oracleAddress,
abi: ORACLE_ABI,
functionName: "deposit",
account,
args: [parseUnits("100", 18), account.address],
});
// Wait for deposit transaction to be mined
return await publicClient.waitForTransactionReceipt({ hash: depositHash });
}
Copy
Ask AI
async function requestTokenPrice(tokenId: string) {
const hash = await walletClient.writeContract({
address: oracleAddress,
abi: ORACLE_ABI,
functionName: "createRequest",
account,
args: [tokenId],
});
// Wait for createRequest transaction to be mined
await publicClient.waitForTransactionReceipt({ hash });
const requestId = (await publicClient.readContract({
address: oracleAddress,
abi: ORACLE_ABI,
functionName: "requestId",
})) as string;
return requestId;
}
Asset Id | Token |
---|---|
1 | ROOT |
2 | XRP |
3172 | SYLO |
17508 | ASTO |
1124 | ETH |
2148 | USDC |
8292 | WBTC |
Copy
Ask AI
async function getResponseData(requestId: string) {
</strong> // Check if request is processed
const isProcessed = await publicClient.readContract({
address: oracleAddress,
abi: ORACLE_ABI,
functionName: "isProcessed",
args: [requestId],
});
if (!isProcessed) {
console.log("Request not yet processed, try again later");
return null;
}
// Get response data
const response = (await publicClient.readContract({
address: oracleAddress,
abi: ORACLE_ABI,
functionName: "getResponse",
args: [requestId],
})) as { value: bigint; timestamp: string };
console.log(`Token price: ${formatUnits(response.value, 18)}`);
console.log(`Timestamp: ${new Date(Number(response.timestamp) * 1000)}`);
return response;
}
Copy
Ask AI
async function priceRequestWorkflow(tokenId: string) {
// Step 1
await depositTokens();
// Step 2
const requestId = await requestTokenPrice(tokenId);
console.log(`Request created with ID: ${requestId}`);
// Step 3
if (requestId) {
// Wait for daemon to emit responded event and get response data
console.log("waiting for responded event ...");
publicClient.watchEvent({
address: oracleAddress,
event: parseAbiItem("event Responded(uint256 indexed requestId)"),
onLogs: async (logs) => {
const requestId = logs[0].args.requestId;
if (requestId) {
await getResponseData(requestId.toString());
}
},
});
}
}
priceRequestWorkflow("1"); // Asset Id for ROOT
requestId
can be done in a few different ways. In this particular example, the Responded
event indicates that the Daemon has processed the request and that the token data is ready to be read.
Oracle ABI
Copy
Ask AI
[
{
"inputs": [
{
"internalType": "address",
"name": "_responder",
"type": "address"
},
{
"internalType": "uint32[]",
"name": "_tokens",
"type": "uint32[]"
},
{
"internalType": "contract IERC20",
"name": "_syloToken",
"type": "address"
},
{
"internalType": "address",
"name": "_initialManager",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "AccessControlBadConfirmation",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "bytes32",
"name": "neededRole",
"type": "bytes32"
}
],
"name": "AccessControlUnauthorizedAccount",
"type": "error"
},
{
"inputs": [],
"name": "AlreadyFulfilled",
"type": "error"
},
{
"inputs": [],
"name": "InsufficientBalance",
"type": "error"
},
{
"inputs": [],
"name": "InvalidValue",
"type": "error"
},
{
"inputs": [],
"name": "NotAllowedToken",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "recipient",
"type": "address"
}
],
"name": "AdminWithdrawal",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "Deposited",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "string",
"name": "token",
"type": "string"
}
],
"name": "Requested",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
}
],
"name": "Responded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "previousAdminRole",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "newAdminRole",
"type": "bytes32"
}
],
"name": "RoleAdminChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleGranted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleRevoked",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "string",
"name": "token",
"type": "string"
},
{
"indexed": false,
"internalType": "bool",
"name": "state",
"type": "bool"
}
],
"name": "TokenUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [],
"name": "UpdatedAmountPerRequest",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
}
],
"name": "WithdrawalForUser",
"type": "event"
},
{
"inputs": [],
"name": "DEFAULT_ADMIN_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MANAGER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "RESPONDER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "_token",
"type": "uint32"
}
],
"name": "createRequest",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32[]",
"name": "_tokens",
"type": "uint32[]"
}
],
"name": "createRequests",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_value",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_requestId",
"type": "uint256"
}
],
"name": "createResponse",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "address",
"name": "_sender",
"type": "address"
}
],
"name": "deposit",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "address",
"name": "_recipient",
"type": "address"
}
],
"name": "depositForUser",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "deposits",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32[]",
"name": "_tokens",
"type": "uint32[]"
}
],
"name": "getLatestData",
"outputs": [
{
"components": [
{
"internalType": "uint256",
"name": "timestamp",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
}
],
"internalType": "struct Oracle.Response[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_breakOnProcessed",
"type": "bool"
}
],
"name": "getPendingRequests",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_address",
"type": "address"
}
],
"name": "getRemainingRequests",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_requestId",
"type": "uint256"
}
],
"name": "getResponse",
"outputs": [
{
"components": [
{
"internalType": "uint256",
"name": "timestamp",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
}
],
"internalType": "struct Oracle.Response",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
}
],
"name": "getRoleAdmin",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "grantRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "hasRole",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_requestId",
"type": "uint256"
}
],
"name": "isProcessed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pricePerRequest",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "callerConfirmation",
"type": "address"
}
],
"name": "renounceRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "requestId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "requests",
"outputs": [
{
"internalType": "uint32",
"name": "tokenId",
"type": "uint32"
},
{
"internalType": "uint256",
"name": "timestamp",
"type": "uint256"
},
{
"internalType": "bool",
"name": "processed",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "responses",
"outputs": [
{
"internalType": "uint256",
"name": "timestamp",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "revokeRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "syloToken",
"outputs": [
{
"internalType": "contract IERC20",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "tokenData",
"outputs": [
{
"internalType": "uint256",
"name": "timestamp",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"name": "tokenNames",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"name": "tokens",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "updateAmountPerRequest",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "_token",
"type": "uint32"
},
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "bool",
"name": "_state",
"type": "bool"
}
],
"name": "updateToken",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "address",
"name": "_from",
"type": "address"
},
{
"internalType": "address",
"name": "_recipient",
"type": "address"
}
],
"name": "withdrawForUser",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "address",
"name": "_recipient",
"type": "address"
}
],
"name": "withdrawFunds",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdrawable",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]