Skip to content

[BUG] Handling view functions separately to executables (for typescript bindings) #2720

Closed
@starknetdev

Description

Describe the bug
When generating the contracts.gen.ts all functions defined are execute calls that return a transaction hash. Using an example of ERC20 balance_of, there is no easy way to get the result from this hash. They should really be generated as calls.

To Reproduce

  • Clone tournament_component
  • run, cd tournaments && cd contracts && sozo build --typescript
  • inspect, contracts/bindings/typescript/contracts.gen.ts

or find the file here: contracts.gen.ts

Using the balance_of example:

Current behavior

	const erc20_mock_balanceOf = async (snAccount: Account, account: string) => {
		try {
			return await provider.execute(
				snAccount,
				{
					contractName: "erc20_mock",
					entrypoint: "balance_of",
					calldata: [account],
				},
				"tournament",
			);
		} catch (error) {
			console.error(error);
		}
	};

Expected behavior

  const erc20_mock_balance_of = async (account: Account, address: string) => {
    try {
      return await provider.call("tournament", {
        contractName: "erc20_mock",
        entrypoint: "balance_of",
        calldata: [address],
      });
    } catch (error) {
      console.error(error);
    }
  };

Additional context
From discussing with Glihm the best approach seems to be having an explicit way in Dojo of defining a view function, opposed to executable functions. Just trying to detect if a function has a return type isn't optimal as it can be useful for executables to have these (intra-contract and contract-contract calls).

Activity

glihm

glihm commented on Nov 25, 2024

@glihm
Collaborator

Thank you @starknetdev for the report here!

So yeah, sa mentioned previously, in the dojo context, every systems could be a view, and it will work. Since the world's storage is being changed, not the storage of the dojo contract itself (most of the time).

The best solution I can see here is the following, we should rely on the ABI state mutability. This state mutability is given by the following convention:

// This will be a view and the result can be obtained using a call.
fn my_view(self: @ContractState) -> u32;

// This will be an external, and the result is not obtainable (except if called from an other contract).
fn my_external(ref self: ContractState) -> u32;

So if we ensure users understand the difference, even if someone if using a view, we know a transaction may be called directly on it. But semantically, it's a view. And should always be bound to the view functionalities first (this doesn't exclude the fact that we can actually send a tx on a view).

@MartianGreed this is something we can add at the manifest level to avoid the bindgen to once again parse everything leveraging the manifest? If you already use the ABI, then it should be good to modify easily.

It may be better if the manifest itself contains, into systems, a list of views and a list of externals.

MartianGreed

MartianGreed commented on Nov 26, 2024

@MartianGreed
Contributor

ohayo ! I've fixed it here #2725 .

In sozo build command, we use the gather_dojo_data function that goes over Abi to fetch out different tokens, so in fact I was able to use StateMutability from Abi

glihm

glihm commented on Nov 26, 2024

@glihm
Collaborator

Merged in #2725, but will be available in the next patch version.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      [BUG] Handling view functions separately to executables (for typescript bindings) · Issue #2720 · dojoengine/dojo