-
Notifications
You must be signed in to change notification settings - Fork 50
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
Utilize ABI for improved ergonomics #227
Comments
Linking this repo as it will be relevant for others https://github.com/near/near-abi-client-rs As for supplying the interface through a generic, that could be interesting, but I don't know how you would go about attaching the functions on the contract object to call directly. Also, feels like it would be less maintenance lift to just cut out the middle step of generating the abi file and maybe have some proc macro or build script that takes in the project root rather than the abi file? |
Yeah, this sounds reasonable to me. Just a couple of notes on things that immediately jump out at me from the current API.
Given all this, I think the best way forward is to change the interface of the code generated pub struct AbiClient {
contract_id: AccountId,
}
impl AbiClient {
pub fn new(contract_id: AccountId) -> Self;
pub fn id(&self) -> &AccountId;
pub fn view(&self) -> ViewMethod;
pub fn call(&self, signer: &workspaces::Account) -> CallMethod;
}
pub struct ViewMethod<'a> {
client: &'a AbiClient,
}
impl<'a> ViewMethod<'a> {
pub async fn get_status(&self) -> Result<ViewResultDetails>;
}
pub struct CallMethod<'a> {
client: &'a AbiClient,
actions: Vec<Action>,
gas: Gas,
deposit: Deposit,
}
// batchable by default
impl<'a> CallMethod<'a> {
pub fn set_status(self, message: String) -> Self;
}
// small nit here, potential identifier conflict
impl<'a> CallMethod<'a> {
pub fn gas(self, gas: Gas) -> Self;
pub fn deposit(self, deposit: Deposit) -> Self;
pub async fn transact(self) -> Result<ExecutionFinalResult>;
} And for the consumer of this API: pub mod status_msg {
use workspaces::abi;
abi::generate!(Client for "abis/status_message.json");
}
let worker = workspaces::sandbox().await?;
let contract = worker.dev_deploy(include_bytes!("status_message.wasm")).await?;
// here, env::signer_account_id() == env::current_account_id()
let client = status_msg::Client::new(contract.id().clone());
let signer_id = "miraclx.near".parse::<AccountId>()?;
let signer = Account::from_secret_key(signer_id, SK, &worker);
// call functions
client
.call(&signer)
.set_status("testing...".to_owned())
.set_status("I'm a teapot ;-)".to_owned())
.gas(parse_gas!("1 Tgas"))
.deposit(parse_near!("1 N"))
.transact()
.await?;
// view functions
assert!(
client.view().get_status(account.id()).await?,
"I'm a teapot ;-)"
); The only nit is the potential conflict between the identifiers |
I don't think there is anything ready, but shouldn't be too difficult to implement.
I think both options have the right to exist. Suppose I don't have access to the contract's source code, but I have a wasm file with embedded ABI. |
@miraclx I feel like all that might just introduce too many ways to call into the same thing. A little bit more verbose than the initial syntax I suggested, but we can continue to use purely let status_msg: workspaces::AbiContract<status_msg::AbiClient> =
worker.dev_deploy("status_message.wasm")
.with_abi::<status_msg::AbiClient>()
.await?;
let method: Function = status_msg.set_status("some message");
account.call(method)
.gas(...)
.deposit(...)
.transact()
.await?;
account.batch()
.call(method)
.call(other_method)
.transact()
.await?; Which wouldn't require you guys to change too much of the ABI generation code if at all. |
Hm, that's a neat alternative. Although, neither Also, let method: Function = status_msg
.set_status("some message")
.gas(...)
.deposit(...); But, I certainly like this interface, as it cleans things up a bit, and also solves the nit (potential identifier conflict) in my first proposal. But I'm not sure the types ( Another unresolved point is using |
Definitely taking a little liberty with the current API, which I should've mentioned haha. But probably something like the following signature is what is more realistic: Account::{call, view}(AccountId, Into<Function>) which shouldn't break any of the current usage since we can have
With the above signature of
I see, yeah then we probably need a different type for this kind of case. Maybe something like what we have current for |
With the imminent release of SDK 4.1 with ABI support, it would be great if we can improve the ergonomics of calling into contract functions, with the addition of a way to supply the ABI:
I'm not sure what the embedded ABI version would look like though. Is there currently some way to grab the resulting rust types from the wasm file?
@austinabell @itegulov @miraclx WDYT?
The text was updated successfully, but these errors were encountered: