Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zkApp.fetchEvents() throws Gateway Time-out error on devnet #1777

Open
dfstio opened this issue Jul 27, 2024 · 10 comments
Open

zkApp.fetchEvents() throws Gateway Time-out error on devnet #1777

dfstio opened this issue Jul 27, 2024 · 10 comments

Comments

@dfstio
Copy link

dfstio commented Jul 27, 2024

On mainnet, both zkApp.fetchEvents() and fetchEvents({ publicKey: contractAddress }) work.
On devnet, fetchEvents({ publicKey: contractAddress }) work, while zkApp.fetchEvents() throws Gateway Time-out error.

The code to reproduce:

import { NameContractV2 } from "minanft";
import { PublicKey, Mina, fetchEvents } from "o1js";

const contractAddress =
  "B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT";

const Devnet1 = {
  mina: ["https://api.minascan.io/node/devnet/v1/graphql"],
  archive: ["https://api.minascan.io/archive/devnet/v1/graphql"],
};

describe("Should get events", () => {
  it(`should get events`, async () => {
    const networkInstance = Mina.Network({
      mina: "https://api.minascan.io/node/devnet/v1/graphql",
      archive: "https://api.minascan.io/archive/devnet/v1/graphql",
    });
    Mina.setActiveInstance(networkInstance);

    const address = PublicKey.fromBase58(contractAddress);
    const zkApp = new NameContractV2(address);
    console.log("Fetching events for", address.toBase58());
    try {
      const events1 = await fetchEvents({ publicKey: contractAddress });
      console.log("Events1:", events1?.length);
      const events2 = await zkApp.fetchEvents();
      console.log("Events2:", events2?.length);
    } catch (e) {
      console.error("Error fetching events", e);
    }
  });
});

The log:

[2:38:49 PM] Fetching events for B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT
[2:38:50 PM] Events1: 145
Error fetching events Error: Gateway Time-out
    at fetchEvents2 (/Users/mike/Documents/DeFi/MinaNFT/minanft-tools/node_modules/o1js/dist/node/index.cjs:22299:11)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at fetchEvents (/Users/mike/Documents/DeFi/MinaNFT/minanft-tools/node_modules/o1js/dist/node/index.cjs:19878:10)
    at NameContractV2.fetchEvents (/Users/mike/Documents/DeFi/MinaNFT/minanft-tools/node_modules/o1js/dist/node/index.cjs:24751:19)
    at Object.<anonymous> (/Users/mike/Documents/DeFi/MinaNFT/minanft-tools/tests/issue.test.ts:26:23)
@dfstio
Copy link
Author

dfstio commented Jul 27, 2024

The issue seems to be related to the argument start that zkApp.fetchEvents() use inside o1js code:
https://github.com/o1-labs/o1js/blob/main/src/lib/mina/zkapp.ts#L1041

The updated example:

import { NameContractV2 } from "minanft";
import { PublicKey, Mina, fetchEvents, Field, UInt32 } from "o1js";

const contractAddress =
  "B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT";

describe("Should get events", () => {
  it(`should get events`, async () => {
    const networkInstance = Mina.Network({
      mina: "https://api.minascan.io/node/devnet/v1/graphql",
      archive: "https://api.minascan.io/archive/devnet/v1/graphql",
    });
    Mina.setActiveInstance(networkInstance);

    const address = PublicKey.fromBase58(contractAddress);
    const zkApp = new NameContractV2(address);
    console.log("Fetching events for", address.toBase58());
    try {
      const events1 = await fetchEvents({ publicKey: contractAddress });
      console.log("Events1:", events1?.length);
      const events2 = await Mina.fetchEvents(address, Field(1));
      console.log("Events2:", events2?.length);
      const events3 = await Mina.fetchEvents(address, Field(1), {
        from: UInt32.from(0),
      });
      console.log("Events3:", events3?.length);
      const events4 = await zkApp.fetchEvents();
      console.log("Events4:", events2?.length);
    } catch (e) {
      console.error("Error fetching events", e);
    }
  });
});

The log:

[3:29:47 PM] Fetching events for B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT
[3:29:48 PM] Events1: 145
[3:29:49 PM] Events2: 145
Error fetching events Error: Gateway Time-out
    at fetchEvents2 (/Users/mike/Documents/DeFi/MinaNFT/minanft-tools/node_modules/o1js/dist/node/index.cjs:22299:11)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at Object.fetchEvents (/Users/mike/Documents/DeFi/MinaNFT/minanft-tools/node_modules/o1js/dist/node/index.cjs:19878:10)
    at Object.<anonymous> (/Users/mike/Documents/DeFi/MinaNFT/minanft-tools/tests/issue1.test.ts:23:23)

@dfstio
Copy link
Author

dfstio commented Jul 27, 2024

It can be related to #1426

@dfstio
Copy link
Author

dfstio commented Jul 28, 2024

I've found a workaround using the method described in #1775
Replacing

const events4 = await zkApp.fetchEvents();

with

const events4 = await zkApp.fetchEvents(UInt32.from(321138));

makes this code work

@45930
Copy link
Contributor

45930 commented Aug 20, 2024

@dfstio, can you share your project config for running this test? I ran npm i minafnt in a new zkapp-cli project and tried to run your example code, but I got this error:

SyntaxError: Unexpected token 'export'

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)
      at Object.<anonymous> (src/common/transactions.ts:16:1)
      at Object.<anonymous> (src/common/common.ts:6:1)
      at Object.<anonymous> (src/node/index.ts:1:1)
      at Object.<anonymous> (node_modules/minanft/lib/ts/src/storage/arweave.js:7:35)
      at Object.<anonymous> (node_modules/minanft/lib/ts/src/minanft.js:20:19)
      at Object.<anonymous> (node_modules/minanft/lib/ts/src/index.js:22:14)

If you could share your ts config and package json, or just link me to the repo so I can play around, I'd appreciate it!

@45930
Copy link
Contributor

45930 commented Aug 20, 2024

I am able to run the file by converting it from a test to a simple script, but I am getting a different error before I reach the timeout:

Fetching events for B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT
Events1: 167
Error fetching events Error: Must call Mina.setActiveInstance first
    at Object.noActiveInstance (/Users/coby/Projects/scratch_projects/o1js-1777/node_modules/o1js/dist/node/index.cjs:20309:9)
    at fetchEvents (/Users/coby/Projects/scratch_projects/o1js-1777/node_modules/o1js/dist/node/index.cjs:20333:31)
    at NameContractV2.fetchEvents (/Users/coby/Projects/scratch_projects/o1js-1777/node_modules/o1js/dist/node/index.cjs:25357:25)
    at main (file:///Users/coby/Projects/scratch_projects/o1js-1777/build/src/repro.js:20:37)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async file:///Users/coby/Projects/scratch_projects/o1js-1777/build/src/repro.js:27:1

Of course, I've kept the line: Mina.setActiveInstance(networkInstance);.

@45930
Copy link
Contributor

45930 commented Aug 20, 2024

Ok, I am able to reproduce this issue by removing the minanft library dependency. I tried normalizing all o1js versions to 1.4.0, but I continued to have issues from multiple versions of the library.

Simplified reproduction script:

import { PublicKey, Mina, fetchEvents, SmartContract, state, Field, State } from "o1js";

class NFTContractV2 extends SmartContract { 
  @state(Field) name = State<Field>();
}

const contractAddress =
"B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT";

const Devnet1 = {
  mina: ["https://api.minascan.io/node/devnet/v1/graphql"],
  archive: ["https://api.minascan.io/archive/devnet/v1/graphql"],
};


const networkInstance = Mina.Network({
    mina: "https://api.minascan.io/node/devnet/v1/graphql",
    archive: "https://api.minascan.io/archive/devnet/v1/graphql",
});
Mina.setActiveInstance(networkInstance);

const address = PublicKey.fromBase58(contractAddress);
const zkApp = new NFTContractV2(address);

console.log("Fetching events for", address.toBase58());
try {
    const events1 = await fetchEvents({ publicKey: contractAddress });
    console.log("Events1:", events1?.length);
    const events2 = await zkApp.fetchEvents();
    console.log("Events2:", events2?.length);
} catch (e) {
    console.error("Error fetching events", e);
}

@45930
Copy link
Contributor

45930 commented Aug 20, 2024

Digging deeper into the implementation, this seems to be a difference in default parameters between fetch.fetchEvents and zkapp.fetchEvents, where the latter adds extra parameters.

The difference in final graphQL query looks like this:

Fetching events for B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT
Filter options:  {}
Query:  events(input: { address: "B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT", tokenId: "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf" }) {
Events1: 165
Filter options:  { from: UInt32 { value: Field { value: [Array] } }, to: undefined }
Query:  events(input: { address: "B62qs2NthDuxAT94tTFg6MtuaP1gaBxTZyNv9D3uQiQciy1VsaimNFT", tokenId: "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf", from: 0 }) {
Error fetching events Error: Gateway Time-out

@45930
Copy link
Contributor

45930 commented Aug 20, 2024

I will open a quick PR to make the default behavior the same, and raise this issue further with our node team to understand why the difference between nothing and 0 is causing timeouts.

@dfstio
Copy link
Author

dfstio commented Aug 20, 2024

@dfstio, can you share your project config for running this test? I ran npm i minafnt in a new zkapp-cli project and tried to run your example code, but I got this error:

SyntaxError: Unexpected token 'export'

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)
      at Object.<anonymous> (src/common/transactions.ts:16:1)
      at Object.<anonymous> (src/common/common.ts:6:1)
      at Object.<anonymous> (src/node/index.ts:1:1)
      at Object.<anonymous> (node_modules/minanft/lib/ts/src/storage/arweave.js:7:35)
      at Object.<anonymous> (node_modules/minanft/lib/ts/src/minanft.js:20:19)
      at Object.<anonymous> (node_modules/minanft/lib/ts/src/index.js:22:14)

If you could share your ts config and package json, or just link me to the repo so I can play around, I'd appreciate it!

minanft is a library and you can use yarn to install it and run the tests:
yarn

@Trivo25 Trivo25 closed this as completed Oct 14, 2024
@dfstio
Copy link
Author

dfstio commented Oct 14, 2024

I'm having this issue now on mainnet, too, with the MinaNFT contract. I've just checked again and have received the message Gateway Time-out

This problem arises with time, as soon as you have more than 300 events. The workaround I use now is to use pagination:

const MAX_BLOCKS = 10000;
const currentBlock = Number((await fetchLastBlock()).blockchainLength);
const firstBlock: number = chain === "mainnet" ? 365480 : 321138;
const events: any[] = [];
let from = firstBlock;
let to =
      firstBlock + MAX_BLOCKS > currentBlock
        ? currentBlock
        : firstBlock + MAX_BLOCKS;
while (from < currentBlock) {
      console.log("Fetching events from", from, "to", to);
      const fetchedEvents = await zkApp.fetchEvents(
        UInt32.from(from),
        UInt32.from(to)
      );
      if (fetchedEvents === undefined) {
        console.error("Events fetch error");
        return;
      }
      events.push(...fetchedEvents);
      from = to + 1;
      to = from + MAX_BLOCKS > currentBlock ? currentBlock : from + MAX_BLOCKS;
    }

Vote to reopen this issue

@Trivo25 Trivo25 reopened this Oct 15, 2024
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

No branches or pull requests

3 participants