5
  1. I want to save "String" Value on Substrate
  2. At First, I use "Vec" But It's not recognized by Polkadot JS
  3. I use "Bytes",So I get the below error
  4. How can I solve this problem?

Please help me.

  • Is it correct to use "Bytes" as a way to store strings?
  • If correct, how can I fix the error below?
  • If not, what is correct to use?
  • Please let me know if you have sample code
#[cfg(test)]
mod mock;

#[cfg(test)]
mod tests;

#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, Hash)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct TestData<BlockNumber,Bytes> {
    pub name: Bytes,                                                                                                                                                                    
    pub address: Bytes,
}
pub type TestDataOf<T> = TestData<primitives::Bytes>;
--snip--
// This pallet's storage items.
decl_storage! {
    // It is important to update your storage name so that your pallet's
    // storage items are isolated from other pallets.
    // ---------------------------------vvvvvvvvvvvvvv
    trait Store for Module<T: Trait> as TemplateModule {
        pub TestDatas: map hasher(blake2_128_concat) T::AccountId => Option<TestDataOf<T>>;
    }
}
--snip--
decl_module! {
    /// The module declaration.
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        // Initializing errors
        // this includes information about your errors in the node's metadata.
        // it is needed only if you are using errors in your pallet
        type Error = Error<T>;

        // Initializing events
        // this is needed only if you are using events in your pallet
        fn deposit_event() = default;


        /// regist public data
        #[weight = 10_000]
        pub fn register_test_data(origin, name:Bytes, address:Bytes) -> dispatch::DispatchResult {
            let registerer = ensure_signed(origin)?;
            let test_data = TestDataOf::<T> {
                name,
                address,
            };
            <TestDatas<T>>::insert(&registerer, test_data);
            Ok(())
        }
    }
}
--snip--

Error is...

the trait `_::_parity_scale_codec::Encode` is not implemented for `TestData<substrate_primitives::Bytes>`
the trait `_::_parity_scale_codec::Decode` is not implemented for `TestData<substrate_primitives::Bytes>`
the trait `_::_parity_scale_codec::WrapperTypeEncode` is not implemented for `substrate_primitives::Bytes`
s.Takahashi
  • 469
  • 4
  • 15
  • Hi @s.Takahashi, can you please support our Substrate StackExchange proposal: https://area51.stackexchange.com/proposals/126136 – Shawn Tabrizi Dec 16 '21 at 13:08

1 Answers1

7

You should use a Vec<u8> to store arbitrary bytes in runtime storage like a string.

When accessing a Vec<u8> that is a string in Polkadot JS, you should use the type Text, which automatically handles parsing and converting this type to regular UTF-8 text.

Example:

Rust:

pub struct TestData {
    pub name: Vec<u8>,                                                                                                                                                                    
    pub address: Vec<u8>,
}

Polkadot JS Type Definition:

TestData: {
    name: 'Text',
    address: 'Text'
}

Let me know if this helps or if you have further issues.

Shawn Tabrizi
  • 12,206
  • 1
  • 38
  • 69
  • Thank you for your answer. I want to call my function by " Extrinsics " on Polkadot/Substrate Portal(https://polkadot.js.org/apps/#/extrinsics). How can I define Polkadot JS Type Definition? – s.Takahashi Aug 03 '20 at 12:16
  • 1
    @Shin go to `Settings` > `Developer` and you will see a JSON input where you can define your JS types. Note there are helpful informational guides on how to use it. – Shawn Tabrizi Aug 03 '20 at 13:49
  • Thank you for your answer again. I can call my function how you told me. Thank you so much! This question is solved. – s.Takahashi Aug 04 '20 at 03:42
  • After `scale_info::TypeInfo` was introduced, It does not need to config JS type, if a field contain no-ASCII, it can't interpreted as string, just a hex string. How to fix it? – gfan Dec 18 '21 at 10:18
  • @gfan, yes, you are correct in the latest version we don't need to explicitly define any type, and in the case of strings, after using Vec in your pallet you can directly pass the string(text) format in polkadot.js portal, and you will be getting the same values back when you fetch from storage. – Pawan Bisht Jan 12 '22 at 09:10
  • Yes, you are right. Further more what my wondering is : when config `name: 'Text'` in polkadot.js portal, the vec data can be represented as a utf-8 readable string, but after use `scale_info::TypeInfo`, polkadot.js portal only represents it as hex string. How to let the polkadot display a human-readable string? – gfan Jan 13 '22 at 02:07
  • I am importing both FRAME support and system preludes but I am getting a type not found for `Vec` when adding it to a field in a storage map struct. – lovelikelando Jul 26 '22 at 01:06