I'm building an application that allows anyone to deploy PSP34 using Openbrush contract.

I want to allow users to deploy a new contract from the UI and upload an image to mint the NFT.

I have successfully called the function to mint from the UI, but I am stumped by the code for each user to deploy the contract from the UI.

Specifically, I want users to be able to call new to create a new contract from the UI. (total supply at this point is 0)

I guess I would use CodePromise, but I am having trouble understanding what the argument wasm is. Can someone please tell me what it is? https://polkadot.js.org/docs/api-contract/start/code

#![cfg_attr(not(feature = "std"), no_std)]

use ink_lang as ink;

mod psp34_contract {
    use openbrush::contracts::psp34::extensions::metadata::*;
    use openbrush::contracts::psp34::extensions::burnable::*;
    use openbrush::contracts::psp34::extensions::enumerable::*;
    use openbrush::contracts::psp34::*;
    use ink_prelude::string::String;
    use ink_prelude::vec::Vec;
    use ink_storage::Mapping;
    use ink_storage::traits::SpreadAllocate;

    /// Defines the storage of your contract.
    /// Add new fields to the below struct in order
    /// to add new static storage fields to your contract.
    #[derive(Default, SpreadAllocate, PSP34Storage, PSP34MetadataStorage)]
    pub struct Psp34Contract {
        psp34: PSP34Data<EnumerableBalances>,
        last_token_id: u8,
        cid_list: Mapping<String, Vec<String>>,
        metadata: PSP34MetadataData,

    impl PSP34 for Psp34Contract {}
    impl PSP34Metadata for Psp34Contract {}
    // Optionally you can add more default implementations
    impl PSP34Internal for Psp34Contract {}
    impl PSP34MetadataInternal for Psp34Contract {}
    impl PSP34Burnable for Psp34Contract {}
    impl PSP34Enumerable for Psp34Contract {}

    impl Psp34Contract {
        pub fn new(id: Id, name: String, symbol: String) -> Self {
            ink_lang::codegen::initialize_contract(|instance: &mut Self| {
                instance._set_attribute(id.clone(), String::from("name").into_bytes(), name.into_bytes());
                instance._set_attribute(id, String::from("symbol").into_bytes(), symbol.into_bytes());

        pub fn mint_token(&mut self) -> Result<(), PSP34Error> {
            self._mint_to(Self::env().caller(), Id::U8(self.last_token_id))?;
            self.last_token_id += 1;

        pub fn mint_with_attribute(&mut self, title: String, author: String, date: String, cid: String) -> Result<(), PSP34Error> {
            self._mint_to(Self::env().caller(), Id::U8(self.last_token_id))?;
            self.last_token_id += 1;
            let mut attributes = Vec::new();
            self.cid_list.insert(cid, &attributes);

1 Answer 1


The wasm argument represents the actual contract code that will run on-chain.

After building your contract you get 3 files:

  • metadata.json
  • a wasm file
  • a .contract file that contains both the metadata and Wasm blob

The .contract file is valid JSON and can be parsed as such. You would then access the wasm code like so: json.source.wasm

Check Contracts UI for a possible implementation https://github.com/paritytech/contracts-ui

  • Thank you @Andreea. const code = new CodePromise(api, metadata, wasm); the official doc show above sample code. In this situation, api is instance, metadata is metadata.json, right? The third argument 'wasm' you said is in the .contract file? Also I can access like this 'json.info.source.wasm'?
    – Steve
    Nov 2, 2022 at 1:38
  • Sorry for the my poor understanding and for asking such a rudimentary question!
    – Steve
    Nov 2, 2022 at 1:39
  • if you want to let users deploy contracts from your app you need to display an instantiation form with a file input where they can upload the .contract file which is valid JSON. the contents of the file input should then be parsed into an object and the wasm blob can be found at yourJsonObject.info.source.wasm Nov 2, 2022 at 10:27
  • sorry it's yourJsonObject.source.wasm. the metadata structure is subject to change, but you can preview the .contract file in any online json formatter and you can see where the wasm field is. Nov 2, 2022 at 10:36
  • like this ?, I set contractWASM as compiled .contract file. Then I define wasm as bellow const wasm = contractWasm.source.wasm;
    – Steve
    Nov 4, 2022 at 2:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.