pubmod abigen_bindings {pubmod contract_a_mod {structSomeCustomStruct{/*...*/}; // other custom types used in the contractstructContractA {/*...*/};implContractA {/*...*/}; // ... }pubmod contract_b_mod { // ... }pubmod my_script_mod { // ... }pubmod my_predicate_mod{ // ... }pubmod shared_types{ // ... }}pubuse contract_a_mod::{/*..*/};pubuse contract_b_mod::{/*..*/};pubuse my_predicate_mod::{/*..*/};pubuse shared_types::{/*..*/};
Each ProgramType gets its own mod based on the name given in the abigen!. Inside the respective mods, the custom types used by that program are generated, and the bindings through which the actual calls can be made.
One extra mod called shared_types is generated if abigen! detects that the given programs share types. Instead of each mod regenerating the type for itself, the type is lifted out into the shared_types module, generated only once, and then shared between all program bindings that use it. Reexports are added to each mod so that even if a type is deemed shared, you can still access it as though each mod had generated the type for itself (i.e. my_contract_mod::SharedType).
A type is deemed shared if its name and definition match up. This can happen either because you've used the same library (a custom one or a type from the stdlib) or because you've happened to define the exact same type.
Finally, pub use statements are inserted, so you don't have to fully qualify the generated types. To avoid conflict, only types that have unique names will get a pub use statement. If you find rustc can't find your type, it might just be that there is another generated type with the same name. To fix the issue just qualify the path by doing abigen_bindings::whatever_contract_mod::TheType.
Icon InfoCircle
Note:
It is highly encouraged that you generate all your bindings in one abigen! call. Doing it in this manner will allow type sharing and avoid name collisions you'd normally get when calling abigen! multiple times inside the same namespace. If you choose to proceed otherwise, keep in mind the generated code overview presented above and appropriately separate the abigen! calls into different modules to resolve the collision.
Normally when using types from libraries in your contract, script or predicate, they'll be generated directly under the main mod of your program bindings, i.e. a type in a contract binding MyContract imported from a library some_library would be generated under abigen_bindings::my_contract_mod::SomeLibraryType.
This can cause problems if you happen to have two types with the same name in different libraries of your program.
This behavior can be changed to include the library path by compiling your Sway project with the following:
forc build --json-abi-with-callpaths
Now the type from the previous example will be generated under abigen_bindings::my_contract_mod::some_library::SomeLibraryType.
This might only become relevant if your type isn't reexported. This can happen, as explained previously, if your type does not have a unique name across all bindings inside one abigen! call. You'll then need to fully qualify the access to it.
Including type paths will eventually become the default and the flag will be removed.
use fuels::prelude::*;// Replace with your own JSON abi path (relative to the root of your crate)abigen!(Contract( name ="MyContractName", abi ="examples/rust_bindings/src/abi.json"));
Note: that is all generated code. No need to write any of that. Ever. The generated code might look different from one version to another, this is just an example to give you an idea of what it looks like.
Then, you're able to use it to call the actual methods on the deployed contract:
// This will generate your contract's methods onto `MyContract`.// This means an instance of `MyContract` will have access to all// your contract's methods that are running on-chain!abigen!(Contract( name ="MyContract", abi ="packages/fuels/tests/contracts/contract_test/out/debug/contract_test-abi.json"));// This is an instance of your contract which you can use to make calls to your functionslet contract_instance =MyContract::new(contract_id_2, wallet);let response = contract_instance.methods().initialize_counter(42) // Build the ABI call.call() // Perform the network call.await?;assert_eq!(42, response.value);let response = contract_instance.methods().increment_counter(10).call().await?;assert_eq!(52, response.value);