ink_e2e/
lib.rs

1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Module for the logic behind ink!'s End-to-End testing framework.
16
17#![doc(
18    html_logo_url = "https://use.ink/img/crate-docs/logo.png",
19    html_favicon_url = "https://use.ink/crate-docs/favicon.png"
20)]
21
22mod backend;
23mod backend_calls;
24mod builders;
25mod client_utils;
26mod contract_build;
27mod contract_results;
28mod error;
29pub mod events;
30mod node_proc;
31mod subxt_client;
32mod xts;
33
34pub use crate::contract_build::build_root_and_contract_dependencies;
35pub use backend::{
36    BuilderClient,
37    ChainBackend,
38    ContractsBackend,
39    E2EBackend,
40};
41pub use backend_calls::{
42    CallBuilder,
43    InstantiateBuilder,
44};
45pub use builders::{
46    CreateBuilderPartial,
47    constructor_exec_input,
48};
49pub use client_utils::{
50    ContractsRegistry,
51    code_hash,
52    salt,
53};
54pub use contract_results::{
55    BareInstantiationResult,
56    CallDryRunResult,
57    CallResult,
58    ContractExecResultFor,
59    ContractResult,
60    InstantiateDryRunResult,
61    InstantiationResult,
62    UploadResult,
63};
64pub use ink_e2e_macro::test;
65pub use ink_revive_types::evm::CallTrace;
66pub use node_proc::{
67    TestNodeProcess,
68    TestNodeProcessBuilder,
69};
70pub use sp_keyring::Sr25519Keyring;
71pub use subxt::{
72    self,
73    backend::rpc::RpcClient,
74};
75pub use subxt_client::{
76    CallBuilderFinal,
77    Client,
78    Error,
79};
80pub use subxt_signer::{
81    self,
82    sr25519::{
83        self,
84        Keypair,
85        dev::*,
86    },
87};
88pub use tokio;
89pub use tracing;
90pub use tracing_subscriber;
91
92use ink::codegen::ContractCallBuilder;
93use ink_env::{
94    ContractEnv,
95    Environment,
96    call::FromAddr,
97};
98use ink_primitives::{
99    Address,
100    DepositLimit,
101    H256,
102    types::AccountIdMapper,
103};
104pub use sp_weights::Weight;
105use std::{
106    cell::RefCell,
107    sync::Once,
108};
109use xts::ReviveApi;
110
111pub use subxt::PolkadotConfig;
112
113/// We use this to only initialize `env_logger` once.
114pub static INIT: Once = Once::new();
115
116// We save the name of the currently executing test here as a mean
117// of prefixing log entries to make it easier pinning them to tests.
118thread_local! {
119    /// This prefix will be used for log output. It is set by each
120    /// `#[ink_e2e::test]` with the function name as String.
121    /// This way it is possible to distinguish the lines in stdout
122    /// and stderr, to still know which line belongs to which test.
123    pub static LOG_PREFIX: RefCell<String> = RefCell::new(String::from("no prefix set"));
124}
125
126/// Returns the name of the test which is currently executed.
127pub fn log_prefix() -> String {
128    LOG_PREFIX.with(|log_prefix| log_prefix.borrow().clone())
129}
130
131/// Writes `msg` to stdout.
132pub fn log_info(msg: &str) {
133    tracing::info!("[{}] {}", log_prefix(), msg);
134}
135
136/// Writes `msg` to stderr.
137pub fn log_error(msg: &str) {
138    tracing::error!("[{}] {}", log_prefix(), msg);
139}
140
141/// Get an ink! [`ink_primitives::AccountId`] for a given keyring account.
142pub fn account_id(account: Sr25519Keyring) -> ink_primitives::AccountId {
143    ink_primitives::AccountId::try_from(account.to_account_id().as_ref())
144        .expect("account keyring has a valid account id")
145}
146
147/// Returns the [`ink::Address`] for a given keyring account.
148///
149/// # Developer Note
150///
151/// We take the `AccountId` and return only the first twenty bytes, this
152/// is what `pallet-revive` does as well.
153pub fn address<E: Environment>(account: Sr25519Keyring) -> Address {
154    AccountIdMapper::to_address(account.to_account_id().as_ref())
155}
156
157/// Returns the [`ink::Address`] for a given account id.
158///
159/// # Developer Note
160///
161/// We take the `AccountId` and return only the first twenty bytes, this
162/// is what `pallet-revive` does as well.
163pub fn address_from_account_id<AccountId: AsRef<[u8]>>(account_id: AccountId) -> Address {
164    AccountIdMapper::to_address(account_id.as_ref())
165}
166
167/// Returns the [`ink::Address`] for a given `Keypair`.
168///
169/// # Developer Note
170///
171/// We take the `AccountId` and return only the first twenty bytes, this
172/// is what `pallet-revive` does as well.
173pub fn address_from_keypair<AccountId: From<[u8; 32]> + AsRef<[u8]>>(
174    keypair: &Keypair,
175) -> Address {
176    let account_id: AccountId = keypair_to_account(keypair);
177    address_from_account_id(account_id)
178}
179
180/// Transforms a `Keypair` into an account id.
181pub fn keypair_to_account<AccountId: From<[u8; 32]>>(keypair: &Keypair) -> AccountId {
182    AccountId::from(keypair.public_key().0)
183}
184
185/// Creates a call builder for `Contract`, based on an account id.
186pub fn create_call_builder<Contract>(
187    acc_id: Address,
188) -> <Contract as ContractCallBuilder>::Type<ink::env::DefaultAbi>
189where
190    <Contract as ContractEnv>::Env: Environment,
191    Contract: ContractCallBuilder + ContractEnv,
192    <Contract as ContractCallBuilder>::Type<ink::env::DefaultAbi>: FromAddr,
193{
194    <<Contract as ContractCallBuilder>::Type<ink::env::DefaultAbi> as FromAddr>::from_addr(
195        acc_id,
196    )
197}
198
199/// Creates a call builder for `Contract` for the specified ABI, based on an account id.
200pub fn create_call_builder_abi<Contract, Abi>(
201    acc_id: Address,
202) -> <Contract as ContractCallBuilder>::Type<Abi>
203where
204    <Contract as ContractEnv>::Env: Environment,
205    Contract: ContractCallBuilder + ContractEnv,
206    <Contract as ContractCallBuilder>::Type<Abi>: FromAddr,
207{
208    <<Contract as ContractCallBuilder>::Type<Abi> as FromAddr>::from_addr(acc_id)
209}
210
211/// Transforms `Option<<E as Environment>::Balance>>` into `DepositLimit`.
212///
213/// This function must only be used for dry-runs, a `None` will
214/// become an unrestricted deposit limit (`DepositLimit::UnsafeOnlyForDryRun`).
215fn balance_to_deposit_limit_dry_run<E: Environment>(
216    b: Option<<E as Environment>::Balance>,
217) -> DepositLimit<<E as Environment>::Balance> {
218    match b {
219        Some(v) => DepositLimit::Balance(v),
220        None => DepositLimit::UnsafeOnlyForDryRun,
221    }
222}
223
224/// Transforms `Option<<E as Environment>::Balance>>` into `DepositLimit`.
225/// This function must be used for submitting extrinsics on-chain.
226///
227/// Panics if `limit` is `None`. Make sure to execute a dry-run
228/// beforehand and use the `storage_deposit_limit` result of it here.
229fn balance_to_deposit_limit<E: Environment>(
230    limit: Option<<E as Environment>::Balance>,
231) -> DepositLimit<<E as Environment>::Balance> {
232    match limit {
233        Some(val) => DepositLimit::Balance(val),
234        None => panic!("Deposit limit must be specified for on-chain submissions."),
235    }
236}
237
238/// Transforms `DepositLimit<<E as Environment>::Balance>` into `<E as
239/// Environment>::Balance>`.
240///
241/// Panics if `limit` is unrestricted (`DepositLimit::UnsafeOnlyForDryRun`).
242fn deposit_limit_to_balance<E: Environment>(
243    limit: DepositLimit<<E as Environment>::Balance>,
244) -> <E as Environment>::Balance {
245    match limit {
246        DepositLimit::Balance(val) => val,
247        DepositLimit::UnsafeOnlyForDryRun => {
248            panic!("Unrestricted deposit limit not allowed for balance conversion!")
249        }
250    }
251}