Usando Queries
Aqui está a tradução técnica do trecho solicitado:
Você pode visitar a Demonstração de Consultas de Exemplos para visualizar um exemplo interativo de uma aplicação interagindo com o contrato de Demonstração de Consultas.
Este guia cobre o uso de uma solicitação simples eth_call
para obter o fornecimento total de WETH na Ethereum.
Fundamentos do RPC
Antes de explorar qualquer coisa específica de Consultas, esta página abordará como realizar um eth_call
contra um RPC público da Ethereum. Suponha que você deseje consultar o contrato WETH para obter seu fornecimento total; antes de fazer a solicitação, você precisa de algumas informações sobre o contrato que deseja chamar, incluindo:
To – o contrato a ser chamado. O endereço de WETH é 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2.
Data – o identificador do método e os parâmetros codificados em ABI, que podem ser obtidos da seguinte forma:
web3.eth.abi.encodeFunctionSignature("totalSupply()")
, que resulta em0x18160ddd
.Block ID – o número do bloco, hash ou tag. As opções de tag incluem:
latest
,safe
, oufinalized
.
A solicitação curl
preparada é a seguinte:
Solicitação JSON-RPC eth_call
eth_call
curl https://ethereum.publicnode.com -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","data":"0x18160ddd"},"latest"],"id":1}'
E a resposta correspondente seria:
Resposta JSON-RPC eth_call
eth_call
{
"jsonrpc":"2.0",
"id":1,
"result":"0x000000000000000000000000000000000000000000029fd3d129b582d7949e71"
}
Convertendo o valor retornado pela chamada executada de hexadecimal resulta no valor 3172615244782286193073777
. Você pode comparar seu resultado com a guia Read Contract no Etherscan. Seu resultado será diferente, pois o WETH é cunhado/queimado ao longo do tempo.
Construindo uma Consulta
Você pode usar o Wormhole Query SDK para construir uma consulta. Também será necessário um endpoint RPC do provedor de sua escolha. Este exemplo usa Axios para solicitações RPC. Certifique-se de que o TypeScript esteja instalado.
npm i @wormhole-foundation/wormhole-query-sdk axios
Para fazer uma EthCallQueryRequest
, você precisará de um número ou hash de bloco específico, bem como dos dados da chamada para solicitar.
Você pode solicitar o bloco mais recente de um nó público usando eth_getBlockByNumber
:
const rpc = 'https://ethereum.publicnode.com';
const latestBlock: string = (
await axios.post(rpc, {
method: 'eth_getBlockByNumber',
params: ['latest', false],
id: 1,
jsonrpc: '2.0',
})
).data?.result?.number;
Em seguida, construa os dados da chamada:
const callData: EthCallData = {
to: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
data: '0x18160ddd', // web3.eth.abi.encodeFunctionSignature("totalSupply()")
};
Por fim, reúna tudo em uma QueryRequest
:
// Forme a solicitação de consulta
const request = new QueryRequest(
0, // Nonce
[
new PerChainQueryRequest(
2, // Ethereum Wormhole Chain ID
new EthCallQueryRequest(latestBlock, [callData])
),
]
);
Essa solicitação consiste em uma PerChainQueryRequest
, que é uma EthCallQueryRequest
para Ethereum. Você pode usar console.log
para imprimir o objeto JSON e revisar a estrutura.
console.log(JSON.stringify(request, undefined, 2));
// {
// "nonce": 0,
// "requests": [
// {
// "chainId": 2,
// "query": {
// "callData": [
// {
// "to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
// "data": "0x18160ddd"
// }
// ],
// "blockTag": "0x11e9068"
// }
// }
// ],
// "version": 1
// }
Simular uma Consulta
Para facilitar os testes, o Query SDK fornece um método QueryProxyMock
. Esse método realizará a solicitação e assinará o resultado com a chave do Guardian do Devnet. A chamada mock retorna o mesmo formato que o Proxy da Consulta.
const mock = new QueryProxyMock({ 2: rpc });
const mockData = await mock.mock(request);
console.log(mockData);
// {
// signatures: ['...'],
// bytes: '...'
// }
Essa resposta é adequada para uso on-chain, mas o SDK também inclui um analisador para tornar os resultados legíveis via cliente.
const mockQueryResponse = QueryResponse.from(mockData.bytes);
const mockQueryResult = (
mockQueryResponse.responses[0].response as EthCallQueryResponse
).results[0];
console.log(
`Resultado da Consulta Mock: ${mockQueryResult} (${BigInt(mockQueryResult)})`
);
// Resultado da Consulta Mock: 0x000000000000000000000000000000000000000000029fd09d4d81addb3ccfee (3172556167631284394053614)
Testando tudo junto
import {
EthCallData,
EthCallQueryRequest,
EthCallQueryResponse,
PerChainQueryRequest,
QueryProxyMock,
QueryRequest,
QueryResponse,
} from '@wormhole-foundation/wormhole-query-sdk';
import axios from 'axios';
const rpc = 'https://ethereum.publicnode.com';
const callData: EthCallData = {
to: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
data: '0x18160ddd', // web3.eth.abi.encodeFunctionSignature("totalSupply()")
};
(async () => {
const latestBlock: string = (
await axios.post(rpc, {
method: 'eth_getBlockByNumber',
params: ['latest', false],
id: 1,
jsonrpc: '2.0',
})
).data?.result?.number;
if (!latestBlock) {
console.error(`❌ Bloco inválido retornado`);
return;
}
console.log('Último Bloco: ', latestBlock, `(${BigInt(latestBlock)})`);
const targetResponse = await axios.post(rpc, {
method: 'eth_call',
params: [callData, latestBlock],
id: 1,
jsonrpc: '2.0',
});
if (targetResponse.data.error) {
console.error(`❌ ${targetResponse.data.error.message}`);
}
const targetResult = targetResponse.data?.result;
console.log('Resultado Alvo: ', targetResult, `(${BigInt(targetResult)})`);
const request = new QueryRequest(
0, // Nonce
[
new PerChainQueryRequest(
2, // Ethereum Wormhole Chain ID
new EthCallQueryRequest(latestBlock, [callData])
),
]
);
console.log(JSON.stringify(request, undefined, 2));
const mock = new QueryProxyMock({ 2: rpc });
const mockData = await mock.mock(request);
console.log(mockData);
const mockQueryResponse = QueryResponse.from(mockData.bytes);
const mockQueryResult = (
mockQueryResponse.responses[0].response as EthCallQueryResponse
).results[0];
console.log(
`Resultado da Consulta Mock: ${mockQueryResult} (${BigInt(mockQueryResult)})`
);
})();
Teste de Fork
É comum testar contra um fork local da Mainnet com algo como:
anvil --fork-url https://ethereum.publicnode.com
Para que as solicitações mock verifiquem o contrato Core da Mainnet, você precisará substituir o conjunto de Guardians atual pela chave do Devnet usada pelo mock.
Last updated