Links

GraphQL API 1.0 migration

Described changes are to be introduced in the end of August 2023. Learn how to make the transition seamless for your applications.

About coming changes

There will be several announcements prior to the actual API transition, which is planned for approximately the end of August 2023.
The transition will first happen on Venom testnet network, later followed by other supported networks.
To stay updated on the transition, you can monitor this page or join this channel for announcements.
As TVM blockchains adoption grows, and with it blockchain load, so does the load on GraphQL API. To be able to cope with large amounts of data, GraphQL API is being refactored.

Major changes

  • The Collections API for blocks, transactions and messages in the new version will only provide data from the last 7 days. To retrieve older (archive) data of blocks, transactions end messages, you need to use the blockchain{...} API with archive: true mode on.
☝ The access to archive data will have rps limits, so make sure you don’t implement many requests per second if you specify archive: true. Limit yourself with maximum of 5 requests of archive data per second from one ip address. If you need higher rate contact @EkaterinaPantaz
  • The Accounts collection will not provide account boc, code and data anymore. Use blockchain{account(address:"address"){info{boc}}} for that.

Specification

Take a look at the updated API. Read comments carefully.
# Account.boc, code, data fields are removed from accounts collection
# Use blockchain{account(address:"addrress"){info{boc}}} instead
accounts
#works the same way
aggregateaccounts
# work on last-7-days data
blocks
transactions
messages
aggregateblocks
aggregatetransactions
aggregatemessages
# blockchain API now provides access to archive data (older than 7 days)
# by default recent data is retrieved
# to get archive data, specify archive=true flag
# archive data has bigger latency than recent data (new data is recorded there
# with a latency of a second), keep it in mind when you design UX
# and architecture of your application
blockchain{
account {
info(address: String): BlockchainAccount # works the same way
transactions(..., archive: bool default = false):BlockchainTransaction
messages(..., archive: bool default = false):BlockchainMessage
}
key_blocks(..., archive: bool default = false): BlockchainBlock
blocks(..., archive: bool default = false): BlockchainBlock
transactions(..., archive: bool default = false): BlockchainTransaction
transaction(..., archive: bool default = false): BlockchainTransaction
message(..., archive: bool default = false):BlockchainMessage
block(..., archive: bool default = false): BlockchainBlock
}
Detailed documentation of Blockchain API is available here.

Migration guide

To prepare for the transition from current functionality to the new one, and make sure it happens seamlessly, developers should migrate their queries as soon as possible - before the actual release of the new API, which will happen in the end of August 2023.
We have released a flag called 'archive' for this purpose. Currently, this flag has no functionality (the API works the same way whether archive=true or false), but it helps in migrating to the new API. When you migrate, the switch from the old API to the new one will be under the hood and invisible to your application.
Be sure to specify the archive=true flag only in places where you need to retrieve blocks, transactions end messages data older than 7 days. If you do not require old data, do not include the flag.
Accounts data is still available in full. You do not need the archive flag to get data of accounts created more than 7 days ago.
Note: If you could not find a suitable query for your use case in the blockchain API, please message @EkaterinaPantaz in Telegram, and we will see what we can do to prepare for migration in your individual case.
The Evercloud team has collected and analyzed API usage statistics and developed an updated blockchain API that covers over 95% of use cases involving archive data. If your use case falls within the <5% where the new API is or seems entirely inapplicable, please also contact @Ekaterina Pantaz, and we will work together to adapt your use case to the API or vice versa.

Query migration samples

Get account data

Get account information
Old query:
query {
accounts(filter:{
id:{
eq:"0:d707caf6df3a7c2bb0b64915613eca9d8f17ca1de0b938dfdcbb9b4ff30c4526"
}
}){
balance
boc
}
}
New query:
{
blockchain{
account(address:"0:d707caf6df3a7c2bb0b64915613eca9d8f17ca1de0b938dfdcbb9b4ff30c4526"){
info{
balance
boc
}
}
}
}

Get external outbound messages from account to :external_address

Retrieve the last 2 external outbound messages from src_address to the “:external address
Old query:
query {
messages(
filter: {
msg_type: { eq: 2 },
src: { eq: "src_address" },
dst: { eq: ":external_address" },
}
orderBy: [{path: "created_at", direction: DESC}],
limit:2
) {
body
msg_type
id
src
created_at
created_lt
dst
}
}
New query:
Get the last 2 src_address' s ExtOut messages filtered by ":external_address" counterparty and save the last message cursor for the next reads.
query {
blockchain {
account(address:"src_address") {
messages(
msg_type: [ExtOut],
counterparties: [":external_address"],
last: 2,
archive: true #specify false for realtime data
) {
edges {
node {
body
msg_type
id
src
created_at
created_lt
dst
}
cursor
}
}
}
}
}

Get account messages after timestamp

Get 100 messages of account $p3 of type $p2 created after timestamp $p1 with value>0 sorted by creation timestamp ASC.
Old query
Pagination is implemented by created_at field. To get the next 50 messages one needs to get pass the created_at value $p1 of the last message into the created_at:{gt:$p1} filter.
☝ Pagination was implemented by created_at timestamp. Please, note that this pagination is not correct and may end up with data loss in case of several messages (more than 50) created per 1 second, which may happen in highly loaded blockchains.
query {
messages (
filter : {
created_at : { gt : $p1 }
msg_type_name : { eq : $p2 }
src_account : { id : { eq : $p3 } }
value: {gt: "0x0"}
}
limit : 50
orderBy : { direction : ASC path : "created_at" } )
{
boc
body
created_at
data
id
msg_type
msg_type_name
}
}
New query
☝ This approach is reliable without data loss
# Get the start of the pagination range for the specified timestamp $p1
query{
blockchain{
start_seqno: master_seq_no_range(time_start: $p1){
start
}
}
}
Now query first page (one page is 50 messages) messages of needed types starting from $start with min value=1 nanotoken.
Available message types are
  • ExtIn (External inbound),
  • ExtOut (External outbound),
  • IntIn (Internal inbound),
  • IntOut (Internal outbound).
query{
blockchain{
account(address: $p3){
messages(master_seq_no_range:{start:$start_seqno}, msg_type:[$p2_type1, $p2_type2], min_value:"0x1", first:50, archive: true){
edges{
node{
boc
body
created_at
data
id
msg_type
msg_type_name
}
}
pageInfo{
endCursor # we got "59e5c7c0059f9522070001"
hasNextPage
}
}
}
}
}
And now the second page after endCursor = “59e5c7c0059f9522070001”
query{
blockchain{
account(address: $p3){
messages(master_seq_no_range:{start:$start_seqno}, msg_type:[$p2_type1, $p2_type2],min_value:"0x1", first:50, after:"59e5c7c0059f9522070001"){
edges{
node{
boc
body
created_at
data
id
msg_type
msg_type_name
}
}
pageInfo{
endCursor
hasNextPage
}
}
}
}
}

Get account transactions

Get last 100 account transactions in descending order
Old query
query {
transactions (
filter : {
account_addr : { eq : $p1 }
lt : { le : $p2 }
}
limit : 50
orderBy : [ { direction : DESC path : "lt" } ] )
{
boc
}
}
New query
☝ Note that sorting order in blockchain api is always in ascending order, so if you need to process the data in descending order on the client, sort it by cursor field in descending order on the client side
Here we get last 50 transactions of account
query{
blockchain{
account(address:"0:d807caf6df3a7c2bb0b64915613eca9d8f17ca1de0b938dfdcbb9b4ff30c4526"){
transactions(
last:50,
archive: true # specify false if only last 7-days-data is needed
){
edges{
node{
boc
}
cursor
}
pageInfo{
startCursor
hasPreviousPage
}
}
}
}
}
and now in the second query we get last 50 transactions before the startCursor from the result of the previous query
query{
blockchain{
account(address:"0:d807caf6df3a7c2bb0b64915613eca9d8f17ca1de0b938dfdcbb9b4ff30c4526"){
transactions(
last:50,
before:"61219b5800618b3ffc0106",
archive: true # specify false if only last 7-days-data is needed
){
edges{
node{
boc
}
cursor
}
pageInfo{
startCursor
hasPreviousPage
}
}
}
}
}

Get transaction/message/block data (including historic)

Old queries
query{
tx:
transactions(filter:{
id:{
eq:"b55173bdca10b50d3fe9b947555be5ff57bc73d0778adea54a33aa64a377cee8"
}
}){
balance_delta
account_addr
boc
}
bl: blocks(filter:{
id:{
eq:"03a990cfa633a2c281ced23221b7384d9fb9969538e000f1ec567311e9b197c4"
}
}){
workchain_id
shard
seq_no
}
bl_by_seq_no: blocks(filter:{
workchain_id:{ eq:0}
shard:{eq:"2000000000000000"}
seq_no:{eq: 17659538}
}){
workchain_id
shard
seq_no
}
msg: messages(filter:{
id:{
eq:"03322f2260a7580592f264d0a578159049cf6ac00b87a0c2c9ed5aee53e23265"
}
}){
value
src
dst
}
}
New queries:
☝ Make sure to specify archive flag according to your use-case
query{
blockchain{
tx: transaction(hash:"b55173bdca10b50d3fe9b947555be5ff57bc73d0778adea54a33aa64a377cee8", archive: true){
balance_delta
account_addr
boc
}
bl: block(hash:"03a990cfa633a2c281ced23221b7384d9fb9969538e000f1ec567311e9b197c4", archive: true){
workchain_id
shard
seq_no
gen_utime_string
}
bl_by_seq_no: block_by_seq_no(workchain:0, thread:"2000000000000000", seq_no:17659538, archive: true ){
workchain_id
shard
seq_no
gen_utime_string
}
msg: message(hash:"03322f2260a7580592f264d0a578159049cf6ac00b87a0c2c9ed5aee53e23265", archive: true){
value
src
dst
}
}
}