Read data from blockchain
There are several types of things you can read from a blockchain. These are various queries to blockchain RPC node, contract get-methods and contract events.
Usually you will connect your dApp to existing smart contract system, deployed on-chain by a smart-contract developer. Thus, you will have an address (a string, that usually looks like 0:abcdef…7890
) and an ABI (.json
file) of a contract you want to interact with.
In each example below, we will assume that you have following definitions of the address and ABI:
- ever-sdk-js
- everscale-inpage-provider
const abi = require('path/to/Contract.abi.json');
const address = "0:deadbeef...00";
import { Address } from 'everscale-inpage-provider';
// Note that it is important to use `as const` when exporting the ABI constant
import contractABI from "path/to/Contract.ts";
const contractAddress = new Address("0:deadbeef...00");
Invoke a get-method
- ever-sdk-js
- everscale-inpage-provider
// Execute the get method `getTimestamp` on the latest account's state
// This can be managed in 3 steps:
// 1. Download the latest Account State (BOC)
// 2. Encode message
// 3. Execute the message locally on the downloaded state
const [account, message] = await Promise.all([
// Download the latest state (BOC)
// See more info about query method here
// https://github.com/tonlabs/ever-sdk/blob/master/docs/mod_net.md#query_collection
client.net.query_collection({
collection: 'accounts',
filter: { id: { eq: address } },
result: 'boc'
})
.then(({ result }) => result[0].boc)
.catch(() => {
throw Error(`Failed to fetch account data`)
}),
// Encode the message with `getTimestamp` call
client.abi.encode_message({
abi,
address,
call_set: {
function_name: 'getTimestamp',
input: {}
},
signer: { type: 'None' }
}).then(({ message }) => message)
]);
// Execute `getTimestamp` get method (execute the message locally on TVM)
// See more info about run_tvm method here
// https://github.com/tonlabs/ever-sdk/blob/master/docs/mod_tvm.md#run_tvm
response = await client.tvm.run_tvm({ message, account, abi });
console.log('Contract reacted to your getTimestamp:', response.decoded.output);
// Create Contract wrapper using ABI and an address
const example = new provider.Contract(contractABI, contractAddress);
// Execute the get method `getTimestamp` on the latest account's state
const response = await example.methods.getTimestamp({}).call();
console.log('Contract reacted to your getTimestamp:', response);
Fetch or subscribe to contract events
- ever-sdk-js
- everscale-inpage-provider
// Query events
result = await client.net.query({
query: `query MyQuery($address: String!, $cursor: String, $count: Int, $start_seq_no: Int, end_seq_no: Int) {
blockchain {
account(address: $address){
messages(
master_seq_no_range: { start: $start_seq_no, end: $end_seq_no }
first: $count,
msg_type: [ExtOut, ExtIn, IntIn, IntOut],
after: $cursor
) {
edges {
node { id, created_at }
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
}`,
variables:{address, cursor, count, start_seq_no, end_seq_no}
});
...
// Subscribe to events
const messageSubscription = await TonClient.default.net.subscribe_collection({
collection: "messages",
filter: {
dst: { eq: your-contract-address },
msg_type:{ in: [0,1,2] }
},
result: "boc"
}, <callback function>
});
// Create a subscriber
const subscriber = new provider.Subscriber();
// Subscribe to contract events
const contractEvents = example.events(subscriber);
// Listen to contract events
contractEvents.on(event => {
console.log('contractEvent', event);
});
// Unsubscribe from contract events
contractEvents.unsubscribe();
Decode message
- ever-sdk-js
const decoded = (await client.abi.decode_message({
abi: abiContract(HelloEventsContract.abi),
message: boc,
}));
switch (decoded.body_type) {
case MessageBodyType.Input:
log_.push(`External inbound message, function "${decoded.name}", fields: ${JSON.stringify(decoded.value)}` );
break;
case MessageBodyType.Output:
log_.push(`External outbound message (return) of function "${decoded.name}", fields: ${JSON.stringify(decoded.value)}`);
break;
case MessageBodyType.Event:
log_.push(`External outbound message (event) "${decoded.name}", fields: ${JSON.stringify(decoded.value)}`);
break;
}
Subscribe to updates
- ever-sdk-js
// Account updates
const accountSubscription = await TonClient.default.net.subscribe_collection({
collection: "accounts",
filter: { id: { eq: address } },
result: "balance",
}, (params, responseType) => {
if (responseType === ResponseType.Custom) {
console.log("Account has updated. Current balance is ", parseInt(params.result.balance));
}
});
...
// Account messages
const messageSubscription = await TonClient.default.net.subscribe_collection({
collection: "messages",
filter: {
src: { eq: address },
OR: {
dst: { eq: address },
}
},
result: "boc",
}, async (params, responseType) => {
try {
if (responseType === ResponseType.Custom) {
const decoded = (await TonClient.default.abi.decode_message({
abi: abiContract(your-contract-abi),
message: params.result.boc,
}));
switch (decoded.body_type) {
case MessageBodyType.Input:
console.log(`External inbound message, function "${decoded.name}", parameters: `, JSON.stringify(decoded.value));
break;
case MessageBodyType.Output:
console.log(`External outbound message, function "${decoded.name}", result`, JSON.stringify(decoded.value));
break;
case MessageBodyType.Event:
console.log(`External outbound message, event "${decoded.name}", parameters`, JSON.stringify(decoded.value));
break;
}
}
} catch (err) {
console.log('>>>', err);
}
});
Read arbitrary data from blockchain
In most cases, the starting point for reading blockchain data is an account address. But sometimes you may want to perform arbitrary queries.
For such cases, the fullnode GraphQL API is a perfect solution. There is a public Evercloud infrastructure for that. Head over to Evercloud Docs to read more.
It is fully opensource, so you may want to deploy your own full node instance with Graph QL interface. You can also reconfigure it for your dApp needs. For example - build various custom indexes according to your smart contract system architecture. Head over to Graph QL Server repository to learn more details.
Links
Explore the full guides to reading blockchain data in Ever SDK here:
https://docs.everos.dev/ever-sdk/guides/work_with_contracts/run_abi_get_method
https://docs.everos.dev/ever-sdk/guides/work_with_contracts/work_with_events
https://docs.everos.dev/ever-sdk/guides/work_with_contracts/decode_message
https://docs.everos.dev/ever-sdk/guides/queries_and_subscriptions/subscribe_to_updates
Advanced guide for working with Surf keeper provider is here.
If you use everscale-inpage-provider
, see more docs and guides here: