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

Typescript bindings: add support for multicall and VRF #2833

Open
rsodre opened this issue Dec 20, 2024 · 0 comments
Open

Typescript bindings: add support for multicall and VRF #2833

rsodre opened this issue Dec 20, 2024 · 0 comments

Comments

@rsodre
Copy link

rsodre commented Dec 20, 2024

Is your feature request related to a problem? Please describe.

The contracts.gen.ts interface created by sozo build —-typescript does not allow multi-call transactions.

These are common uses of multi-call:

  • To use the cartridge VRF service, we need to send a request_random on the same call, or else it will not be picked by the paymaster and will not work.
  • When the player needs to pay for something, we send an approve transaction before the contract call.

Describe the solution you'd like

This is a function from contracts.gen.ts, it does not allow the inclusion of other calls in provider.execute().

const bank_charge = async (snAccount: Account | AccountInterface, payer: string, value: Bignumberish) => {
  try {
    return await provider.execute(
      snAccount,
      {
        contractName: "bank",
        entrypoint: "charge",
        calldata: [payer, value],
      },
      "pistols",
    );
  } catch (error) {
    console.error(error);
  }
};

It would be better to have one function that would only create the Call object, and another to execute it. It would also allow queueing shopping cart transactions (as in Loot Survivor) to be executed later.

// avoid breaking changes, allow using the same function as to execute single transactions
const bank_charge = async (snAccount: Account | AccountInterface, payer: string, value: Bignumberish) => {
  try {
    return await this.execute(
      snAccount,
      [this.bank_calls_charge(payer, value)]
    );
  } catch (error) {
    console.error(error);
  }
};

// this new function will only build the Call object...
const bank_calls_charge (payer: string, value: Bignumberish): Call => {
  return parseDojoCall(
    provider.manifest,
    "pistols", 
    {
      contractName: "bank",
      entrypoint: "charge",
      calldata: [payer, value],
    }
  );
};

// create another new function to execute multicalls
// avoid breaking changes, allow using the same function as to execute single transactions
const execute = async (snAccount: Account | AccountInterface, calls: AllowArray<DojoCall | Call>) => {
  try {
    return await account.execute(
      snAccount,
      calls
    );
  } catch (error) {
    console.error(error);
  }
};

// single call usage (no changes)
client.bank.charge(account, recipient, amount);

// mutli-call usage
client.execute(account, [
  client.token.calls.approve(spender, amount)
  client.bank.calls.charge(recipient, amount)
]);
client.execute(account, [
  controller.calls.vrf(game_contract),
  client.actions.calls.do_the_thing()
]);

I would also move nameSpace inside DojoCall, and remove it from parseDojoCall() and execute(). Besides making it simpler, this would allow multi-calls with functions from different namespaces:

type DojoCall = {
    nameSpace: string;
    contractName: string;
    entrypoint: string;
    calldata: RawArgs | Calldata;
};

// remove nameSpace from parseDojoCall()
export const parseDojoCall = (manifest: any, call: DojoCall | Call): Call

// remove nameSpace from execute()
execute(account: Account | AccountInterface, call: AllowArray<DojoCall | Call>, details?: UniversalDetails): Promise<InvokeFunctionResponse>

Describe alternatives you've considered

Using a custom contract call, not using contracts.gen.ts

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

1 participant