Skip to content
This repository has been archived by the owner on Sep 14, 2023. It is now read-only.

feat: smart contract with improved dx #462

Merged
merged 21 commits into from
Dec 22, 2022

Conversation

kratico
Copy link
Contributor

@kratico kratico commented Dec 14, 2022

Description

Add a smart contract deployment and call example.

The example showcase how to

  • send non-mutable messages
  • send mutable messages
  • encode message arguments and decode message return values using the contract metadata
  • decode message events

@kratico kratico changed the title Feat/ink smart contract example my contract dx feat: smart contract with improved dx Dec 14, 2022
@kratico kratico force-pushed the feat/ink-smart-contract-example-my-contract-dx branch from a21b5ee to 47145bb Compare December 14, 2022 18:50
}
}

const flipperContract = new SmartContract(contract.metadata, contractAddress)
Copy link
Contributor Author

@kratico kratico Dec 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following contract calls could be simplified without console.logs like

await flipperContract.call(T.alice.publicKey, "get", []).run()
await flipperContract.tx(T.alice.publicKey, "flip", [], T.alice.sign).run()
await flipperContract.call(T.alice.publicKey, "get", []).run()
await flipperContract.call(T.alice.publicKey, "get_count", []).run()
await flipperContract.tx(T.alice.publicKey, "inc", [], T.alice.sign).run()
await flipperContract.tx(T.alice.publicKey, "inc", [], T.alice.sign).run()
await flipperContract.call(T.alice.publicKey, "get_count", []).run()
await flipperContract.tx(T.alice.publicKey, "inc_by", [3], T.alice.sign).run()
await flipperContract.call(T.alice.publicKey, "get_count", []).run()
await flipperContract.call(T.alice.publicKey, "m1", [2, true]).run()
await flipperContract.call(T.alice.publicKey, "m1", [3, false]).run()

For messages that mutate the state, contract.tx(origin, message, args, sign) is used.
For other messages, contract.call(origin, message, args) is used.

The source code for this contract is

#[ink::contract]
mod flipper {

    /// Defines an event that is emitted
    /// every time inc is invoked.
    #[ink(event)]
    pub struct Incremented {
        from: Option<AccountId>,
        count: i32,
    }

    /// Defines the storage of your contract.
    /// Add new fields to the below struct in order
    /// to add new static storage fields to your contract.
    #[ink(storage)]
    pub struct Flipper {
        /// Stores a single `bool` value on the storage.
        value: bool,
        /// Stores count
        count: i32,
    }

    #[derive(Debug, scale::Encode, scale::Decode)]
    #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
    pub struct M2 {
        a: u32,
        b: bool,
    }

    impl Flipper {
        /// Constructor that initializes the `bool` value to the given `init_value`.
        #[ink(constructor)]
        pub fn new(init_value: bool) -> Self {
            Self {
                value: init_value,
                count: 0,
            }
        }

        /// Constructor that initializes the `bool` value to `false`.
        ///
        /// Constructors can delegate to other constructors.
        #[ink(constructor)]
        pub fn default() -> Self {
            Self::new(Default::default())
        }

        /// A message that can be called on instantiated contracts.
        /// This one flips the value of the stored `bool` from `true`
        /// to `false` and vice versa.
        #[ink(message)]
        pub fn flip(&mut self) {
            self.value = !self.value;
        }

        /// Simply returns the current value of our `bool`.
        #[ink(message)]
        pub fn get(&self) -> bool {
            self.value
        }

        /// multiple arg method returning a tuple.
        #[ink(message)]
        pub fn method_returning_tuple(&self, a: u32, b: bool) -> (u32, bool) {
            (a, b)
        }

        /// multiple arg method returning a struct.
        #[ink(message)]
        pub fn method_returning_struct(&self, a: u32, b: bool) -> M2 {
            M2 { a, b }
        }

        /// get the current count.
        #[ink(message)]
        pub fn get_count(&self) -> i32 {
            self.count
        }

        /// increment current count by 1
        #[ink(message)]
        pub fn inc(&mut self) {
            self.inc_by(1);
        }

        /// decrement current count by 1
        #[ink(message)]
        pub fn dec(&mut self) {
            self.inc_by(-1);
        }

        /// increment current count by n
        #[ink(message)]
        pub fn inc_by(&mut self, n: i32) {
            self.count += n;
        }

        /// increment current count by n and emit an event
        #[ink(message)]
        pub fn inc_by_with_event(&mut self, n: i32) {
            self.inc_by(n);
            self.env().emit_event(Incremented {
                from: self.env().caller().into(),
                count: self.count,
            });
        }
    }

examples/smart_contract.ts Outdated Show resolved Hide resolved
examples/smart_contract.ts Outdated Show resolved Hide resolved
examples/smart_contract.ts Outdated Show resolved Hide resolved
@@ -182,3 +183,164 @@ export namespace ContractMetadata {
return normalize(contractMetadata).V3.types
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following codecs can be removed once paritytech/substrate#11648 is implemented

harrysolovay
harrysolovay previously approved these changes Dec 22, 2022
@kratico kratico merged commit badc112 into main Dec 22, 2022
@kratico kratico deleted the feat/ink-smart-contract-example-my-contract-dx branch December 22, 2022 19:36
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants