FuelLabs / fuel-indexer

🗃 The Fuel indexer is a standalone service that can be used to index various components of the Fuel blockchain.
https://docs.fuel.network/docs/indexer/
140 stars 66 forks source link

Add support for multiple contract ABIs #1491

Open ra0x3 opened 10 months ago

ra0x3 commented 10 months ago
ra0x3 commented 10 months ago

@segfault-magnet

segfault-magnet commented 10 months ago
  • Given how we use the JSON ABI I'm wondering if this is even possible?

I'm not familiar with how the JSON ABI is used by the indexer, except for the part where Abigen is called with the abi files.

  • We iterate over the JSON ABI to collect all types for a given JSON ABI
  • This would mean that collecting these types for multiple/separate JSON ABIs would lead to type collisions?
    • type A in contract1 might have type ID 4, and type B in contract2 might also have type ID 4
  • I know that we can take multiple JSON ABI paths and pass them to the SDK via multiple AbigenTargets, but I don't think it's possible to integrate all the other non-SDK indexer functionality - since it all works for types from a single contract

The SDK avoids type collisions by namespacing the generated types. Each Contract/Script or Predicate gets its own mod. Sometimes that is not enough since a contract can have multiple libraries with types that have the same name but different implementations. For that case forc needs to be called with a flag that will enable "call paths", this makes forc generate a JSON abi with the path of each custom type (i.e. "some::library::Error", and "some_other::library::Error" instead of just "Error" and "Error"). We use that information to generate mods for every type, just like they would have had over in Sway.

  • We'd have to get all types from all contract ABIs then effectively re-assign new TypeDeclarations to them, with new type IDs - which sounds fraught with danger? 🥲

I don't know the inner workings. The idea of assigning a TypeDeclaration to a type is unfamiliar. Over in the SDK, we generate a type from a TypeDeclaration and the TypeDeclaration is thrown away after that.

* Especially tricky with something like predicates where the original type ID (from the SDK) is important

Also not familiar with how predicates in the indexer would work.

ra0x3 commented 10 months ago

@segfault-magnet

not familiar

dmihal commented 10 months ago

Do you have an example of what the manifest would look like with multiple ABIs?

Coming from The Graph, it's always a bit confusing that the manifest doesn't have a list of contracts. Would this change add that?

ra0x3 commented 10 months ago

@dmihal Definitely.

So with the merge of #886 the new manifest format will be

namespace: fuel_indexer_test
fuel_client: ~
schema: packages/fuel-indexer-tests/indexers/fuel-indexer-test/schema/fuel_indexer_test.graphql
start_block: ~
end_block: ~
contract:
  abi: packages/fuel-indexer-tests/sway/test-contract1/out/debug/test-contract1-abi.json
  subscriptions:
    - fuel1vrwlw55qkc8xgn5sljjlawhlkqjgstczqwcyakx8a80c42tpqc8qv23p4k
identifier: index1
module:
  wasm: target/wasm32-unknown-unknown/release/fuel_indexer_test.wasm
resumable: true
predicates:
  templates:
    - name: TestPredicate1
      abi: packages/fuel-indexer-tests/sway/test-predicate1/out/debug/test-predicate1-abi.json
      id: 0xcfd60aa414972babde16215e0cb5a2739628831405a7ae81a9fc1d2ebce87145
    - name: TestPredicate2
      id: 0xb16545fd38b82ab5178d79c71ad0ce54712cbdcee22f722b08db278e77d1bcbc
      abi: packages/fuel-indexer-tests/sway/test-predicate2/out/debug/test-predicate2-abi.json

And if we were to include multiple contract ABIs, it would simply be updated to:

namespace: fuel_indexer_test
fuel_client: ~
schema: packages/fuel-indexer-tests/indexers/fuel-indexer-test/schema/fuel_indexer_test.graphql
start_block: ~
end_block: ~
contract:
  abi: 
    - packages/fuel-indexer-tests/sway/test-contract1/out/debug/test-contract1-abi.json
    - packages/fuel-indexer-tests/sway/test-contract1/out/debug/test-contract2-abi.json
    - packages/fuel-indexer-tests/sway/test-contract1/out/debug/test-contract3-abi.json
  subscriptions:
    - fuel1vrwlw55qkc8xgn5sljjlawhlkqjgstczqwcyakx8a80c42tpqc8qv23p4k
identifier: index1
module:
  wasm: target/wasm32-unknown-unknown/release/fuel_indexer_test.wasm
resumable: true
predicates:
  templates:
    - name: TestPredicate1
      abi: packages/fuel-indexer-tests/sway/test-predicate1/out/debug/test-predicate1-abi.json
      id: 0xcfd60aa414972babde16215e0cb5a2739628831405a7ae81a9fc1d2ebce87145
    - name: TestPredicate2
      id: 0xb16545fd38b82ab5178d79c71ad0ce54712cbdcee22f722b08db278e77d1bcbc
      abi: packages/fuel-indexer-tests/sway/test-predicate2/out/debug/test-predicate2-abi.json
dmihal commented 10 months ago

So is fuel1vrwlw55qkc8xgn5sljjlawhlkqjgstczqwcyakx8a80c42tpqc8qv23p4k the contract that's being indexed? How would it look if there's multiple contracts being indexed, eich with it's own ABI?

Is there a reason we don't have a contracts section similar to the predicates section?

ra0x3 commented 10 months ago

@dmihal By "similar to the predicates section" I think you're meaning tucked in as a Map object

- key1: value1
  key2: value2
  key3: value3