4 dakika
Subgraph Örnek Uygulamalar 4 - eth_calls Kullanımından Kaçınarak Endeksleme Hızını Artırma
Özet
eth_calls
are calls that can be made from a Subgraph to an Ethereum node. These calls take a significant amount of time to return data, slowing down indexing. If possible, design smart contracts to emit all the data you need so you don’t need to use eth_calls
.
eth_calls
Kullanımından Kaçınmanın Önemi
Subgraphs are optimized to index event data emitted from smart contracts. A Subgraph can also index the data coming from an eth_call
, however, this can significantly slow down Subgraph indexing as eth_calls
require making external calls to smart contracts. The responsiveness of these calls relies not on the Subgraph but on the connectivity and responsiveness of the Ethereum node being queried. By minimizing or eliminating eth_calls in our Subgraphs, we can significantly improve our indexing speed.
Bir eth_call
Nasıl Görünür?
eth_calls
are often necessary when the data required for a Subgraph is not available through emitted events. For example, consider a scenario where a Subgraph needs to identify whether ERC20 tokens are part of a specific pool, but the contract only emits a basic Transfer
event and does not emit an event that contains the data that we need:
1event Transfer(address indexed from, address indexed to, uint256 value);
Diyelim ki token’ların havuz üyeliği, getPoolInfo
adlı bir durum değişkeni ile belirleniyor. Bu verileri sorgulamak için şu tarz bir eth_call
kullanmamız gerekir:
1import { Address } from '@graphprotocol/graph-ts'2import { ERC20, Transfer } from '../generated/ERC20/ERC20'3import { TokenTransaction } from '../generated/schema'45export function handleTransfer(event: Transfer): void {6 let transaction = new TokenTransaction(event.transaction.hash.toHex())78 // Belirtilen adrese ERC20 sözleşme örneğini bağla:9 let instance = ERC20.bind(event.address)1011 // eth_call aracılığıyla havuz bilgilerini al12 let poolInfo = instance.getPoolInfo(event.params.to)1314 transaction.pool = poolInfo.toHexString()15 transaction.from = event.params.from.toHexString()16 transaction.to = event.params.to.toHexString()17 transaction.value = event.params.value1819 transaction.save()20}
This is functional, however is not ideal as it slows down our Subgraph’s indexing.
eth_calls
’ı Ortadan Kaldırma
İdeal olarak, akıllı sözleşme gerekli tüm verileri olaylar içinde yayacak şekilde güncellenmelidir. Örneğin, havuz bilgilerini olaya dahil edecek şekilde akıllı sözleşmeyi değiştirmek, eth_calls
ihtiyacını ortadan kaldırabilir:
1event TransferWithPool(address indexed from, address indexed to, uint256 value, bytes32 indexed poolInfo);
With this update, the Subgraph can directly index the required data without external calls:
1import { Address } from '@graphprotocol/graph-ts'2import { ERC20, TransferWithPool } from '../generated/ERC20/ERC20'3import { TokenTransaction } from '../generated/schema'45export function handleTransferWithPool(event: TransferWithPool): void {6 let transaction = new TokenTransaction(event.transaction.hash.toHex())78 transaction.pool = event.params.poolInfo.toHexString()9 transaction.from = event.params.from.toHexString()10 transaction.to = event.params.to.toHexString()11 transaction.value = event.params.value1213 transaction.save()14}
Bu metot eth_calls
ihtiyacını ortadan kaldırdığı için çok daha verimlidir.
eth_calls
’ı Optimize Etme
Eğer akıllı sözleşmeyi değiştirmek mümkün değilse ve eth_calls
kullanmak gerekli ise, Simon Emanuel Schmid tarafından yazılan “Subgraph Endeksleme Performansını Kolayca İyileştirin: eth_calls’ı Azaltın” makalesini okuyarak eth_calls’i optimize etmenin çeşitli stratejilerini öğrenebilirsiniz.
eth_call
Çağrılarının Fazla Çalışma Yükünü Azaltma
Kaldırılamayan eth_calls
’lar manifesto içinde deklare edilerek sebep oldukları çalışma zamanı yükü en aza indirilebilir. graph-node
bir bloğu işlerken, belirtilen tüm eth_calls’ı işleyiciler çalıştırılmadan önce paralel olarak gerçekleştirir. Deklare edilmeyen çağrılar ise işleyiciler çalıştırıldığında sıralı olarak yürütülür. Paralel çağrılar, çağrılara harcanan toplam süreyi azaltmaya yardımcı olur; ancak bu süreyi tamamen ortadan kaldıramaz.
Şu anda eth_calls
yalnızca olay işleyicileri için deklare edilebilir. Manifesto içerisinde şu şekilde yazılabilir:
1event: TransferWithPool(address indexed, address indexed, uint256, bytes32 indexed)2handler: handleTransferWithPool3calls:4 ERC20.poolInfo: ERC20[event.address].getPoolInfo(event.params.to)
Sarıyla vurgulanan bölüm çağrı deklarasyonudur. İki nokta üst üste öncesindeki kısım yalnızca hata mesajları için kullanılan bir metin etiketidir. İki noktadan sonraki kısım ise Contract[address].function(params)
formundadır. Adres ve parametreler için izin verilen değerler event.address
ve event.params.<name>
şeklindedir.
İşleyici, bu eth_call
sonucuna bir önceki bölümde olduğu gibi sözleşmeye bağlanarak ve çağrıyı yaparak erişir. graph-node, deklare edilen eth_calls
sonuçlarını bellekte önbelleğe alır. İşleyiciden yapılan çağrı, sonuçları gerçek bir RPC çağrısı yapıp almak yerine, önbellekten alır.
Note: Declared eth_calls can only be made in Subgraphs with specVersion >= 1.2.0.
Sonuç
You can significantly improve indexing performance by minimizing or eliminating eth_calls
in your Subgraphs.