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

Implement NEP264 host function and refactor ext contract API #740

Closed
austinabell opened this issue Mar 1, 2022 · 0 comments · Fixed by #742
Closed

Implement NEP264 host function and refactor ext contract API #740

austinabell opened this issue Mar 1, 2022 · 0 comments · Fixed by #742

Comments

@austinabell
Copy link
Contributor

austinabell commented Mar 1, 2022

NEP264, or function calls allowing splitting unused gas among async function calls near/NEPs#264 is being implemented here near/nearcore#6285.

The current API looks something like

#[ext_contract(ext)]
 pub trait ExtCrossContract { 
 fn some_method(a: u8) -> String; 
 } 
 ...

let contract_account_id: AccountId = todo!();
 ext::some_method(/* parameters ***/, contract_account_id, 0 /*** deposit amount ***/, 5_000_000_000_000 /*** static amount of gas to attach */)

Where the limitations are that: 1. It's confusing which order deposit and gas are in 2. Not intuitive what the extra parameters are and where the function parameters end 3. Need to specify a static amount of gas 4. Need to define a trait with ext_contract where the macro will actually not use the trait at all (very confusing when there can be multiple traits in code with the same name) 5. The ext_contract API is not tied to the actual methods in any way, changes in one can silently cause bugs

and the initial proposition, noted in the NEP and in an exploratory PR for implementing this within the SDK, was to change the API to something like:

 ext::some_method(/* parameters */, contract_account_id)
 // Optional config
 .with_amount(1 /* default deposit of 0 */)
 .with_static_gas(5_000_000_000_000 /* default of 0 */)
 .with_unused_gas_weight(2 /* default 1 */)

Where this is a builder pattern but uses the same ext_contract API. From experimenting in the PR linked above, the issue is that this result type of this must be an abstraction above Promise which causes some unideal patterns when migrating because an additional into_promise() method is required to convert it to this type. Also, it's a bit unideal that the account_id is still mixed with the method parameters, which can still be confusing. Finally, the issue of this external API not being tied to the callable one still causes issues.

So my proposal, and what I will experiment with, is having an ext method being added to any near_bindgen struct which will generate roughly the following:

#[must_use]
 pub struct MyContractExt 

 { .. }

 impl MyContractExt {

 pub fn with_amount(self) -> Self { .. } 

 pub fn with_static_gas(self) -> Self 

 { .. }

 pub fn with_unused_gas_weight(self) -> Self { .. } 

 }

impl MyContract {
 pub fn ext(account_id: AccountId) -> MyContractExt 

 { ... } 

 }

and will generate, for every public method within #<span class="error">[near_bindgen]</span>:

impl MyContractExt {
 pub fn some_method(self, a: u8) -> Promise 

 { .. } 

 ....
 }

where the API to use will look roughly like:

 MyContract::ext(contract_account_id)
 // Optional config
 .with_amount(1 /* default deposit of 0 */)
 .with_static_gas(5_000_000_000_000 /* default of 0 */)
 .with_unused_gas_weight(2 /* default 1 */)

 // Then call any method to schedule the function call
 .some_method(/* parameters */)

This solves basically all of the issues mentioned above, but the tradeoff is that the config attributes have to be defined before the method is called, which might not be intuitive for everyone, but it makes logical sense.

Another side benefit of this is that it does not rely on Promise being scheduled on Drop so frees up that API to change in the future.

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

Successfully merging a pull request may close this issue.

1 participant