Skip to content

Add new realtime sendRawTransaction API which directly return receipt#532

Draft
KyrinCode wants to merge 1 commit intodev-oldfrom
kyrin/realtime-api
Draft

Add new realtime sendRawTransaction API which directly return receipt#532
KyrinCode wants to merge 1 commit intodev-oldfrom
kyrin/realtime-api

Conversation

@KyrinCode
Copy link

@KyrinCode KyrinCode commented May 29, 2025

To test the latency of this new zkevm_sendRawTransaction API compared with previous eth_sendRawTransaction & eth_getTransactionReceipt under make run test env. I run 10 times each for request sending to seq & rpc.

  1. legacy way: first eth_sendRawTransaction, then polling eth_getTransactionReceipt with 500ms interval

Sent to seq:

  • min: 517.32ms
  • max: 1019.63ms
  • avg: 567.30ms

Sent to rpc:

  • min: 3.56s
  • max: 4.09s
  • avg: 3.61s
  1. realtime way: zkevm_sendRawTransaction

Sent to seq:

  • min: 101.32ms
  • max: 717.77ms
  • avg: 317.40ms

Sent to rpc:

  • min: 3.14s
  • max: 4.06s
  • avg: 3.49s

The test script is below.

const { ethers } = require("ethers");
const axios = require("axios");
require('dotenv').config();

const RPC_URL = "http://localhost:8124"; // https://rpc.xlayer.tech http://localhost:8123

const privateKey = process.env.PRIVATE_KEY

const wallet = new ethers.Wallet(privateKey);

const toAddress = "TO_ADDRESS";
const valueEth = "0.001";

async function waitForReceipt(txHash, maxAttempts = 60) {
  for (let i = 0; i < maxAttempts; i++) {
    const receiptRes = await axios.post(RPC_URL, {
      jsonrpc: "2.0",
      method: "eth_getTransactionReceipt",
      params: [txHash],
      id: 3
    });

    if (receiptRes.data.result) {
      return receiptRes.data.result;
    }

    console.log(`Waiting for receipt... Attempt ${i + 1}/${maxAttempts}`);
    await new Promise(resolve => setTimeout(resolve, 500));
  }
  throw new Error("Timeout waiting for transaction receipt");
}

(async () => {
    console.log("Wallet address:", wallet.address);

    const nonceRes = await axios.post(RPC_URL, {
        jsonrpc: "2.0",
        method: "eth_getTransactionCount",
        params: [wallet.address, "latest"],
        id: 1
    });

    const nonce = parseInt(nonceRes.data.result, 16);
    console.log(`Nonce: ${nonce}`);

    const tx = {
        nonce,
        to: toAddress,
        value: ethers.parseEther(valueEth).toString(),
        gasLimit: "21000",
        gasPrice: ethers.parseUnits("5", "gwei").toString(),
        chainId: 195,
        type: 0,
    };

    console.log("Transaction object:", JSON.stringify(tx, null, 2));

    const signedTx = await wallet.signTransaction(tx);
    console.log("Signed Tx:", signedTx);

    const sendRes = await axios.post(RPC_URL, {
        jsonrpc: "2.0",
        method: "zkevm_sendRawTransaction",
        params: [signedTx],
        id: 2
    });

    // console.log("Full response:", JSON.stringify(sendRes.data, null, 2));

    if (sendRes.data.error) {
        console.error("Transaction error:", sendRes.data.error);
        const errorMessage = sendRes.data.error.message;
        const txHashMatch = errorMessage.match(/0x[a-fA-F0-9]{64}/);
        if (txHashMatch) {
            const txHash = txHashMatch[0];
            console.log("Extracted Transaction Hash:", txHash);
            
            try {
                const receipt = await waitForReceipt(txHash);
                console.log("Transaction Receipt:", receipt);
            } catch (error) {
                console.error("Error waiting for receipt:", error.message);
            }
        }
    } else {
        console.log("Transaction Result:", sendRes.data.result);
    }
})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant