diff --git a/Cargo.lock b/Cargo.lock index 4b5fb1e..bfc9981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3473,6 +3473,7 @@ dependencies = [ "frame-system", "log", "pallet-assets", + "pallet-nfts 31.0.0", "parity-scale-codec", "pop-chain-extension", "scale-info", @@ -3917,7 +3918,7 @@ dependencies = [ "frame-system", "log", "pallet-assets", - "pallet-nfts", + "pallet-nfts 30.0.0", "parity-scale-codec", "scale-info", "sp-runtime", @@ -3943,13 +3944,29 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-nfts" +version = "31.0.0" +dependencies = [ + "enumflags2", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", +] + [[package]] name = "pallet-nfts-runtime-api" version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0ca7a0446d2d3c27f726a016c6366218df2e0bfef9ed35886b252cfa9757f6c" dependencies = [ - "pallet-nfts", + "pallet-nfts 30.0.0", "parity-scale-codec", "sp-api", "sp-std", @@ -4737,7 +4754,7 @@ dependencies = [ "pallet-message-queue", "pallet-multisig", "pallet-nft-fractionalization", - "pallet-nfts", + "pallet-nfts 31.0.0", "pallet-nfts-runtime-api", "pallet-preimage", "pallet-proxy", diff --git a/README.md b/README.md index 2e17b48..807895b 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,151 @@ -

Pop DRink! (forked from DRink!)

-

Dechained Ready-to-play ink! playground

+
+

Pop DRink!

-> [!IMPORTANT] -> This repository is customized and maintained for Pop API contract end-to-end testing. -> -> Quasi tests must be run with `cargo test --release`. +R0GUE Logo -# Pop Sandbox +[![Twitter URL](https://img.shields.io/twitter/follow/Pop?style=social)](https://x.com/onpopio/) +[![Twitter URL](https://img.shields.io/twitter/follow/R0GUE?style=social)](https://twitter.com/gor0gue) +[![Telegram](https://img.shields.io/badge/Telegram-gray?logo=telegram)](https://t.me/onpopio) -Implementation of the [`pop_drink::Sandbox`](https://github.com/r0gue-io/pop-drink) struct for the Pop Network runtimes (located in `pop-node/runtime`) required for the quasi testing with `drink`. +Forked version of [inkdevhub/drink](https://github.com/inkdevhub/drink) for E2E testing smart contract using [Pop API](https://github.com/r0gue-io/pop-node/tree/main/pop-api) with [Pop Network runtimes](https://github.com/r0gue-io/pop-node/tree/main/runtime). -In the context of quasi-testing with pop-drink, a sandbox refers to an isolated runtime environment that simulates the behavior of a full node, without requiring an actual node. It can emulate key processes (where runtime `pallets` are involved) such as block initialization, execution, and block finalization. +
+ +## Overview + +About the repository folder structure: + +- [pop-drink](/crates/pop-drink): Provides utility methods for testing contract methods with DRink! and Pop Network runtimes. +- [examples](/crates/drink/examples): A collection of example contracts tested with DRink! +- [drink](/crates/drink/drink): DRink! is a toolbox for ink! developers that allows for a fully functional ink! contract development without any running node. +- [ink-sandbox](/crates/ink-sandbox): Sandbox refers to an isolated runtime environment that simulates the behavior of a full node, without requiring an actual node. +- [drink-cli](/crates/drink/drink-cli): Simple command line tool to help you play with your local contracts in a convenient way. ## Getting Started -### Installation +Add `pop-drink` crate to your contract `Cargo.toml`: ```toml -pop_drink = { version = "1.0.0", package = "pop-drink" } +drink = { version = "1.0.0", package = "pop-drink" } ``` -### Import Sandbox for the specific runtime +### Setup a testing environment -- For `devnet` runtime +Please see ["Quick start with DRink!"](/crates/drink/examples/quick-start-with-drink/README.md) for a detailed explanation. -Implementation of the sandbox runtime environment for `devnet` runtime located in `pop-node/runtime/devnet` +Add the below code at the top of your contract test file to setup [Sandbox](TODO) for the [**Pop Network Devnet**](https://github.com/r0gue-io/pop-node/tree/main/runtime/devnet) runtime. ```rs -use pop_sandbox::DevnetSandbox; +#[derive(Default)] +struct Sandbox; + +// Implement `Sandbox` environment for the Pop Network Devnet runtime. +drink::impl_sandbox!(Sandbox, drink::devnet::Runtime, ALICE); ``` -- For `testnet` runtime +## Writing tests -Implementation of the sandbox runtime environment for `testnet` runtime located in `pop-node/runtime/testnet` +### Writing tests -```rs -use pop_sandbox::TestnetSandbox; +Your typical test module will look like (See ["Quick start with DRink!"](/crates/drink/examples/quick-start-with-drink/README.md) example tests): + +```rust +#[cfg(test)] +mod tests { + use drink::session::{Session, NO_ARGS, None, NO_SALT}; + + #[drink::contract_bundle_provider] + enum BundleProvider {} + + #[drink::test] + fn deploy_and_call_a_contract(mut session: Session) -> Result<(), Box> { + let result: bool = session + .deploy_bundle_and(BundleProvider::local(), "new", &["true"], NO_SALT, None)? + .call_and("flip", NO_ARGS, None)? + .call_and("flip", NO_ARGS, None)? + .call_and("flip", NO_ARGS, None)? + .call("get", NO_ARGS, None)??; + assert_eq!(result, false); + } +} ``` -- For `mainnet` runtime +So, firstly, you declare a bundle provider like: -Implementation of the sandbox runtime environment for `mainnet` runtime located in `pop-node/runtime/mainnet` +```rust +#[drink::contract_bundle_provider] +enum BundleProvider {} +``` -```rs -use pop_sandbox::MainnetSandbox; +It will take care of building all contract dependencies in the compilation phase and gather all contract bundles into a single registry. +Then, you will be able to get a contract bundle by calling: + +```rust +let bundle = BundleProvider::local()?; // for the contract from the current crate +let bundle = BundleProvider::Flipper.bundle()?; // for the contract from the `flipper` crate +``` + +We mark each testcase with `#[drink::test]` attribute and declare return type as `Result` so that we can use the `?` operator: + +```rust +#[drink::test] +fn testcase() -> Result<(), Box> { + // ... +} ``` -### Setup test environment for your contract +Then, we can use the `Session` API to interact with both contracts and the whole runtime. +For details, check out testcases in [lib.rs](lib.rs). -Below is an example for the contract testing with `pop_drink` and `pop_sandbox` for `devnet` environment using `DevnetSandbox`. +### Writing tests for methods using [Pop API](https://github.com/r0gue-io/pop-node/tree/main/pop-api) + +Pop DRink! also provides [utilitiy methods](/crates/pop-drink/src/lib.rs) that you can use to test your contracts. This example interacts with a [PSP22 example contract](https://github.com/r0gue-io/pop-node/blob/main/pop-api/examples/fungibles/lib.rs) that uses [Pop API](https://github.com/r0gue-io/pop-node/tree/main/pop-api). The contract method returns [`PSP22Error`](https://github.com/r0gue-io/pop-node/blob/main/pop-api/src/v0/fungibles/errors.rs#L73C1-L73C22) custom error which is provided by Pop API library. ```rs -use pop_drink::session::Session; -use pop_sandbox::DevnetSandbox as Sandbox; +// Import required methods and types. +use drink::{call, session::Session}; +use pop_api::v0::fungibles::PSP22Error; -#[drink::contract_bundle_provider] -enum BundleProvider {} +// Interact with `transfer` method of the `Psp22` contract. +fn transfer(session: &mut Session, to: AccountId, amount: Balance) -> Result<(), PSP22Error> { + let empty_array = serde_json::to_string::<[u8; 0]>(&[]).unwrap(); + let input = vec![to.to_string(), amount.to_string(), empty_array]; -#[drink::test(sandbox = Sandbox)] -fn test(mut session: Session) { - // Your test case + call::(session, "Psp22::transfer", input, None) } ``` -## Examples +Asserts the returned error to an [`Error`](TODO) type using [`assert_err!`](TODO) to test errors of a runtime call. + +```rs +use drink::{assert_err, v0::Error, Assets, AssetsError::NoAccount}; + +#[drink::test(sandbox = Pop)] +fn test_transfer_to_no_account() { + // Test the contract call if a custom error is the runtime module error. + assert_err!( + transfer(&mut session, ALICE, AMOUNT), + Error::Module(Assets(NoAccount)) + ); +} +``` + +We need to specify the sandbox of Pop Network runtime for a testcase if the contract is using Pop API. + +```rs +#[drink::test(sandbox = Pop)] +``` + +## Development Guide + +To run the `examples` contracts for DRink! + +``` +cargo test --release +``` + +### Support -Please find more examples of `pop_drink` tests in the [`pop_drink/examples`](https://github.com/r0gue-io/pop-drink/tree/main/examples). +- Be part of our passionate community of Web3 pioneers. [Join our Telegram](https://t.me/onpopio)! +- Additionally, there are [GitHub issues](https://github.com/r0gue-io/pop-drink/issues) and + [Polkadot Stack Exchange](https://polkadot.stackexchange.com/).