Skip to content

Interacting with ink! Smart Contracts

Interacting with ink! Smart Contracts Using Polkadart

This guide demonstrates how to interact with ink! smart contracts using Polkadart. In this example, we use the Flipper contract to walk through the entire process—from setting up your environment to deploying and interacting with your contract.

Table of Contents

Overview

In this guide you will:

  • Set up your ink! development environment.
  • Create, build, and deploy a smart contract.
  • Generate Dart bindings for your contract using the ink_cli package.
  • Interact with your deployed contract using Polkadart libraries.

By following these steps, you’ll gain a clear understanding of how to work with ink! smart contracts in a Dart environment.

Prerequisites

Before you begin, ensure you have completed the following:

  1. Set Up Your ink! Development Environment
    Install Rust and the necessary dependencies by following the ink! setup guide.

  2. Create an ink! Project
    Initialize and test a basic Flipper contract using the ink! project creation guide.

  3. Build Your Contract
    Compile your smart contract to Wasm as detailed in the building your contract guide.

  4. Run a Substrate Node
    Start a local development node by following the running Substrate guide.

For more detailed instructions, refer to the official ink! documentation.

Installation

To begin interacting with your smart contract using Polkadart, add the required dependencies to your pubspec.yaml file:

dependencies:
ink_abi: any
ink_cli: any
polkadart: any
polkadart_keyring: any

After updating the file, run the following command in your terminal to install the packages: This command installs all dependencies needed to proceed with generating contract bindings and interacting with your contract.

Terminal window
dart pub get

Generating Contract Bindings

To enable communication with your smart contract, you need to generate Dart bindings from your contract’s ABI.

Step 1: Create the Binding Generation Script

Create a Dart file named generate_contract.dart and add the following code:

import 'package:ink_cli/ink_cli.dart';
final fileOutput = FileOutput('generated_flipper.dart');
final generator =
TypeGenerator(abiFilePath: 'flipper.json', fileOutput: fileOutput);
generator.generate();
fileOutput.write();

This script reads the ABI from flipper.json and generates a Dart file (generated_flipper.dart) containing all necessary bindings.

Step 2: Run the Binding Generation Script

Execute the following command to generate the bindings:

Terminal window
dart run generate_contract.dart

Once the script completes, you will have a new file (generated_flipper.dart) ready for interacting with your contract.

Deploying the Contract

After generating the bindings, the next step is to deploy your contract to a local Substrate node and interact with it.

Necessary imports

import 'dart:io';
import 'dart:typed_data';
import 'package:polkadart/polkadart.dart';
import 'package:polkadart_keyring/polkadart_keyring.dart';
import 'generated_flipper.dart';

Create the connection and load account

Future<void> main() async {
// Connect to the local Substrate node
final provider = Provider.fromUri(Uri.parse('ws://127.0.0.1:9944'));
// Load the account (e.g., Alice) to sign transactions
final alice = await KeyPair.sr25519.fromUri('//Alice');
...
...
...

Create contract deployable object

// Create a deployer object to handle contract deployment
final contractDeployer = await ContractDeployer.from(provider: provider);

Deploy the contract with the help of generated constructors

// Deploy the contract using the Wasm file and initial parameter (init_value)
final InstantiateRequest result = await Contract.new_contract(
init_value: true,
keyPair: alice,
code: await File('flipper.wasm').readAsBytes(),
deployer: contractDeployer,
);
// Deployed Contract Address
final contractAddress = result.contractAddress;
print('Contract deployed at: $contractAddress');

Create a contract object from the returned contract - address

// Initialize the contract instance with the deployed contract address
final deployedContract = Contract(
provider: provider,
address: Uint8List.fromList(alice.publicKey.bytes.toList()),
contractAddress: Uint8List.fromList(result.contractAddress),
);

Interacting with the contract

Read the state of the contract - Get the value of the flipper contract

// Allow time for the deployment to process
await Future.delayed(Duration(seconds: 1));
// Query the initial value stored in the contract
final initialValue = await deployedContract.get();
print('Initial value: $initialValue');

Mutating the state

// Contract mutator object
final mutator = await ContractMutator.fromProvider(provider: provider);

Mutate the value of the contract

final executionResult = await deployedContract.flip(
keyPair: alice,
mutator: mutator,
);
// Wait for 20 seconds to let the changes be in the block
await Future.delayed(Duration(seconds: 20));
final flippedValue = await deployedContract.get();
print('Value after doing flip: $flippedValue');

Understanding the Script

  • Connecting to the Node:

    • The Provider.fromUri method connects to a local Substrate node running at ws://127.0.0.1:9944.
  • Account Management:

    • The script loads Alice’s key pair using KeyPair.sr25519.fromUri(‘//Alice’). This account is used to sign the transaction for deploying the contract.
  • Contract Deployment:

    • A deployer object is created and used with the Contract.new_contract method. This method takes the Wasm bytecode from flipper.wasm, an initial parameter (init_value), and the key pair to deploy the contract.
  • Contract Interaction:

    • After deployment, the script creates a contract instance with the generated address and queries the contract’s initial state using the get() method.

Conclusion

In this guide, we covered how to interact with ink! smart contracts using Polkadart by:

  • Getting up your development environment.
  • Installing the required Dart dependencies.
  • Generating Dart bindings from your contract’s ABI.
  • Deploying and interacting with your contract on a local Substrate node.

You can now experiment further by modifying the Flipper contract, exploring additional functionalities, or even deploying your contract on a testnet. For the latest updates and advanced features, always refer to the official ink! documentation.