Skip to content

Commit 6e2e86b

Browse files
authored
feat: deploy and use global contracts from UI excluding action builder. (#456)
* Added support for the new global contracts [(NEP-591)](https://github.com/near/NEPs/blob/053cb244fd4b836cea12652e12b4de10891b3c54/neps/nep-0591.md) * The action builder will be addressed separately. ```bash # Deploy immutable hash version. Account id is prompted as signer ./target/release/near contract deploy-as-global use-file ./code.wasm as-global-hash round-toad.testnet network-config testnet sign-with-keychain send # Deploy mutable account id version. Account id is prompted as global contract account id ./target/release/near contract deploy-as-global use-file ./code.wasm as-global-account-id round-toad.testnet network-config testnet sign-with-keychain # Deploy code to your account (regular/original way). Please note that we kept it backward-compatible ./target/release/near contract deploy round-toad.testnet use-file ./code.wasm without-init-call network-config testnet # Deploy code with a global account id ./target/release/near contract deploy round-toad.testnet use-global-account-id some-contract.testnet without-init-call network-config testnet # Deploy code with a global hash ./target/release/near contract deploy round-toad.testnet use-global-hash 6iVtdTk6jtPtUtJM6NVZSJ7FuhEpFvVog85pizcej3UK without-init-call network-config testnet ``` @race-of-sloths
1 parent facc2c0 commit 6e2e86b

File tree

6 files changed

+348
-46
lines changed

6 files changed

+348
-46
lines changed

src/commands/contract/deploy/initialize_mode/call_function_type/mod.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use inquire::CustomType;
22

33
#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
4-
#[interactive_clap(input_context = super::super::ContractFileContext)]
4+
#[interactive_clap(input_context = super::super::GenericDeployContext)]
55
#[interactive_clap(output_context = CallFunctionActionContext)]
66
pub struct CallFunctionAction {
77
/// What is the name of the function?
@@ -23,14 +23,14 @@ pub struct CallFunctionActionContext {
2323
global_context: crate::GlobalContext,
2424
receiver_account_id: near_primitives::types::AccountId,
2525
signer_account_id: near_primitives::types::AccountId,
26-
code: Vec<u8>,
26+
deploy_action: near_primitives::transaction::Action,
2727
function_name: String,
2828
function_args: Vec<u8>,
2929
}
3030

3131
impl CallFunctionActionContext {
3232
pub fn from_previous_context(
33-
previous_context: super::super::ContractFileContext,
33+
previous_context: super::super::GenericDeployContext,
3434
scope: &<CallFunctionAction as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
3535
) -> color_eyre::eyre::Result<Self> {
3636
let function_args =
@@ -42,7 +42,7 @@ impl CallFunctionActionContext {
4242
global_context: previous_context.global_context,
4343
receiver_account_id: previous_context.receiver_account_id,
4444
signer_account_id: previous_context.signer_account_id,
45-
code: previous_context.code,
45+
deploy_action: previous_context.deploy_action,
4646
function_name: scope.function_name.clone(),
4747
function_args,
4848
})
@@ -51,7 +51,7 @@ impl CallFunctionActionContext {
5151

5252
impl CallFunctionAction {
5353
fn input_function_args_type(
54-
_context: &super::super::ContractFileContext,
54+
_context: &super::super::GenericDeployContext,
5555
) -> color_eyre::eyre::Result<
5656
Option<super::super::super::call_function::call_function_args_type::FunctionArgsType>,
5757
> {
@@ -76,7 +76,7 @@ pub struct PrepaidGasContext {
7676
global_context: crate::GlobalContext,
7777
receiver_account_id: near_primitives::types::AccountId,
7878
signer_account_id: near_primitives::types::AccountId,
79-
code: Vec<u8>,
79+
deploy_action: near_primitives::transaction::Action,
8080
function_name: String,
8181
function_args: Vec<u8>,
8282
gas: crate::common::NearGas,
@@ -91,7 +91,7 @@ impl PrepaidGasContext {
9191
global_context: previous_context.global_context,
9292
receiver_account_id: previous_context.receiver_account_id,
9393
signer_account_id: previous_context.signer_account_id,
94-
code: previous_context.code,
94+
deploy_action: previous_context.deploy_action,
9595
function_name: previous_context.function_name,
9696
function_args: previous_context.function_args,
9797
gas: scope.gas,
@@ -155,11 +155,7 @@ impl DepositContext {
155155
signer_id: signer_account_id.clone(),
156156
receiver_id: receiver_account_id.clone(),
157157
actions: vec![
158-
near_primitives::transaction::Action::DeployContract(
159-
near_primitives::transaction::DeployContractAction {
160-
code: previous_context.code.clone(),
161-
},
162-
),
158+
previous_context.deploy_action.clone(),
163159
near_primitives::transaction::Action::FunctionCall(Box::new(
164160
near_primitives::transaction::FunctionCallAction {
165161
method_name: previous_context.function_name.clone(),

src/commands/contract/deploy/initialize_mode/mod.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use strum::{EnumDiscriminants, EnumIter, EnumMessage};
33
mod call_function_type;
44

55
#[derive(Debug, Clone, EnumDiscriminants, interactive_clap_derive::InteractiveClap)]
6-
#[interactive_clap(context = super::ContractFileContext)]
6+
#[interactive_clap(context = super::GenericDeployContext)]
77
#[strum_discriminants(derive(EnumMessage, EnumIter))]
88
/// Select the need for initialization:
99
pub enum InitializeMode {
@@ -16,7 +16,7 @@ pub enum InitializeMode {
1616
}
1717

1818
#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
19-
#[interactive_clap(input_context = super::ContractFileContext)]
19+
#[interactive_clap(input_context = super::GenericDeployContext)]
2020
#[interactive_clap(output_context = NoInitializeContext)]
2121
pub struct NoInitialize {
2222
#[interactive_clap(named_arg)]
@@ -25,18 +25,18 @@ pub struct NoInitialize {
2525
}
2626

2727
#[derive(Debug, Clone)]
28-
pub struct NoInitializeContext(super::ContractFileContext);
28+
pub struct NoInitializeContext(super::GenericDeployContext);
2929

3030
impl NoInitializeContext {
3131
pub fn from_previous_context(
32-
previous_context: super::ContractFileContext,
32+
previous_context: super::GenericDeployContext,
3333
_scope: &<NoInitialize as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
3434
) -> color_eyre::eyre::Result<Self> {
35-
Ok(Self(super::ContractFileContext {
35+
Ok(Self(super::GenericDeployContext {
3636
global_context: previous_context.global_context,
3737
receiver_account_id: previous_context.receiver_account_id,
3838
signer_account_id: previous_context.signer_account_id,
39-
code: previous_context.code,
39+
deploy_action: previous_context.deploy_action,
4040
}))
4141
}
4242
}
@@ -52,11 +52,7 @@ impl From<NoInitializeContext> for crate::commands::ActionContext {
5252
Ok(crate::commands::PrepopulatedTransaction {
5353
signer_id: signer_account_id.clone(),
5454
receiver_id: receiver_account_id.clone(),
55-
actions: vec![near_primitives::transaction::Action::DeployContract(
56-
near_primitives::transaction::DeployContractAction {
57-
code: item.0.code.clone(),
58-
},
59-
)],
55+
actions: vec![item.0.deploy_action.clone()],
6056
})
6157
}
6258
});

src/commands/contract/deploy/mod.rs

Lines changed: 138 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use color_eyre::eyre::Context;
2+
use strum::{EnumDiscriminants, EnumIter, EnumMessage};
23

34
pub mod initialize_mode;
45

@@ -9,9 +10,34 @@ pub struct Contract {
910
#[interactive_clap(skip_default_input_arg)]
1011
/// What is the contract account ID?
1112
account_id: crate::types::account_id::AccountId,
12-
#[interactive_clap(named_arg)]
13-
/// Specify a path to wasm file
14-
use_file: ContractFile,
13+
#[interactive_clap(subcommand)]
14+
/// Specify a deploy mode
15+
deploy_mode: DeployModes,
16+
}
17+
18+
#[derive(Debug, EnumDiscriminants, Clone, interactive_clap::InteractiveClap)]
19+
#[interactive_clap(context = ContractContext)]
20+
#[strum_discriminants(derive(EnumMessage, EnumIter))]
21+
#[non_exhaustive]
22+
/// Choose a contract action:
23+
pub enum DeployModes {
24+
#[strum_discriminants(strum(
25+
message = "use-file - Deploy a contract using a wasm file"
26+
))]
27+
/// Deploy a contract using a wasm file
28+
UseFile(ContractFile),
29+
30+
#[strum_discriminants(strum(
31+
message = "use-global-hash - Deploy a contract using a global contract code hash"
32+
))]
33+
/// Deploy a contract using a global contract code hash
34+
UseGlobalHash(ContractHash),
35+
36+
#[strum_discriminants(strum(
37+
message = "use-global-account-id - Deploy a contract using an account ID"
38+
))]
39+
/// Deploy a contract using an global contract account ID
40+
UseGlobalAccountId(ContractAccountId),
1541
}
1642

1743
#[derive(Debug, Clone)]
@@ -45,6 +71,14 @@ impl Contract {
4571
}
4672
}
4773

74+
#[derive(Debug, Clone)]
75+
pub struct GenericDeployContext {
76+
pub global_context: crate::GlobalContext,
77+
pub receiver_account_id: near_primitives::types::AccountId,
78+
pub signer_account_id: near_primitives::types::AccountId,
79+
pub deploy_action: near_primitives::transaction::Action,
80+
}
81+
4882
#[derive(Debug, Clone, interactive_clap_derive::InteractiveClap)]
4983
#[interactive_clap(input_context = ContractContext)]
5084
#[interactive_clap(output_context = ContractFileContext)]
@@ -55,13 +89,7 @@ pub struct ContractFile {
5589
initialize: self::initialize_mode::InitializeMode,
5690
}
5791

58-
#[derive(Debug, Clone)]
59-
pub struct ContractFileContext {
60-
pub global_context: crate::GlobalContext,
61-
pub receiver_account_id: near_primitives::types::AccountId,
62-
pub signer_account_id: near_primitives::types::AccountId,
63-
pub code: Vec<u8>,
64-
}
92+
pub struct ContractFileContext(GenericDeployContext);
6593

6694
impl ContractFileContext {
6795
pub fn from_previous_context(
@@ -71,11 +99,109 @@ impl ContractFileContext {
7199
let code = std::fs::read(&scope.file_path).wrap_err_with(|| {
72100
format!("Failed to open or read the file: {:?}.", &scope.file_path.0,)
73101
})?;
74-
Ok(Self {
102+
Ok(Self(GenericDeployContext {
75103
global_context: previous_context.global_context,
76104
receiver_account_id: previous_context.receiver_account_id,
77105
signer_account_id: previous_context.signer_account_id,
78-
code,
106+
deploy_action: near_primitives::transaction::Action::DeployContract(
107+
near_primitives::action::DeployContractAction { code },
108+
),
109+
}))
110+
}
111+
}
112+
113+
impl From<ContractFileContext> for GenericDeployContext {
114+
fn from(item: ContractFileContext) -> Self {
115+
item.0
116+
}
117+
}
118+
119+
#[derive(Debug, Clone, interactive_clap_derive::InteractiveClap)]
120+
#[interactive_clap(input_context = ContractContext)]
121+
#[interactive_clap(output_context = ContractHashContext)]
122+
pub struct ContractHash {
123+
/// What is a global contract code hash?
124+
pub hash: crate::types::crypto_hash::CryptoHash,
125+
#[interactive_clap(subcommand)]
126+
initialize: self::initialize_mode::InitializeMode,
127+
}
128+
129+
pub struct ContractHashContext(GenericDeployContext);
130+
131+
impl ContractHashContext {
132+
pub fn from_previous_context(
133+
previous_context: ContractContext,
134+
scope: &<ContractHash as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
135+
) -> color_eyre::eyre::Result<Self> {
136+
Ok(Self(GenericDeployContext {
137+
global_context: previous_context.global_context,
138+
receiver_account_id: previous_context.receiver_account_id,
139+
signer_account_id: previous_context.signer_account_id,
140+
deploy_action: near_primitives::transaction::Action::UseGlobalContract(Box::new(
141+
near_primitives::action::UseGlobalContractAction {
142+
contract_identifier:
143+
near_primitives::action::GlobalContractIdentifier::CodeHash(
144+
scope.hash.into(),
145+
),
146+
},
147+
)),
148+
}))
149+
}
150+
}
151+
152+
impl From<ContractHashContext> for GenericDeployContext {
153+
fn from(item: ContractHashContext) -> Self {
154+
item.0
155+
}
156+
}
157+
158+
#[derive(Debug, Clone, interactive_clap_derive::InteractiveClap)]
159+
#[interactive_clap(input_context = ContractContext)]
160+
#[interactive_clap(output_context = ContractAccountIdContext)]
161+
pub struct ContractAccountId {
162+
#[interactive_clap(skip_default_input_arg)]
163+
/// What is a global contract account ID?
164+
pub global_contract_account_id: crate::types::account_id::AccountId,
165+
#[interactive_clap(subcommand)]
166+
initialize: self::initialize_mode::InitializeMode,
167+
}
168+
169+
impl ContractAccountId {
170+
pub fn input_global_contract_account_id(
171+
context: &ContractContext,
172+
) -> color_eyre::eyre::Result<Option<crate::types::account_id::AccountId>> {
173+
crate::common::input_non_signer_account_id_from_used_account_list(
174+
&context.global_context.config.credentials_home_dir,
175+
"What is a global contract account ID?",
176+
)
177+
}
178+
}
179+
180+
pub struct ContractAccountIdContext(GenericDeployContext);
181+
182+
impl ContractAccountIdContext {
183+
pub fn from_previous_context(
184+
previous_context: ContractContext,
185+
scope: &<ContractAccountId as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
186+
) -> color_eyre::eyre::Result<GenericDeployContext> {
187+
Ok(GenericDeployContext {
188+
global_context: previous_context.global_context,
189+
receiver_account_id: previous_context.receiver_account_id,
190+
signer_account_id: previous_context.signer_account_id,
191+
deploy_action: near_primitives::transaction::Action::UseGlobalContract(Box::new(
192+
near_primitives::action::UseGlobalContractAction {
193+
contract_identifier:
194+
near_primitives::action::GlobalContractIdentifier::AccountId(
195+
scope.global_contract_account_id.clone().into(),
196+
),
197+
},
198+
)),
79199
})
80200
}
81201
}
202+
203+
impl From<ContractAccountIdContext> for GenericDeployContext {
204+
fn from(item: ContractAccountIdContext) -> Self {
205+
item.0
206+
}
207+
}

0 commit comments

Comments
 (0)