Substrateで文字列データを保存する

## Substrateでは"String"、"str"は使えない
- 使えません。※2020/8/4現在

## 使えないならどうするか
- 結論から言うと "Vec"を使います。

```
Vec<u8>
```

## ここまではネットでも確認出来る、で？
- 独自パレットを作成し、外部関数のパラメータの文字列項目を"Vec<u8>"で実装する。
- そしてその関数を**[Polkadot/Substrate Portal](https://polkadot.js.org/apps/#/extrinsics)**から呼び出そうと試みる・・・
- 「そんな型は知らん」的なエラーが出る・・・

# 本日お伝えしたい事
- Substrateに文字列データを保存するための一連の工程
- 即ち、(1)独自Palletの実装。(2)外部関数の実装。(3)ビルド。(4)Polkdatod/Substrate Portalで確認

# (1)独自Palletの実装
- **[substrate developer hub](https://substrate.dev/docs/en/tutorials/create-a-pallet/)**の当該チュートリアルを参考に実施して下さい。

# (2)外部関数の実装
- "pallets/test-pallet/src/lib.rs"に変更を加えていきます。
- **※※rust未熟＆substrate未熟のため、間違いや無駄が多くあると自戒しておりますので、ご了承下さい。**
- "Vec"を使うための宣言をします。

```
use sp_std::vec::Vec;
```
- 保存するための構造体を定義します。

```
pub struct TestData {
    pub my_name: Vec<u8>,
    pub my_address: Vec<u8>
}
```
- ブロックチェーンに保存する領域を定義します。

```
decl_storage! {
    trait Store for Module<T: Trait> as TemplateModule {
        pub TestDatas: map hasher(blake2_128_concat) T::AccountId => TestData;
    }
}
```
- 外部関数を定義します。

```
        #[weight = 10_000]
        pub fn save_testdata(origin, testdata:TestData) -> dispatch::DispatchResult {
            let registerer = ensure_signed(origin)?;
            let regist_data = TestData {
                my_name:testdata.my_name,
                my_address:testdata.my_address,
            };
            TestDatas::<T>::insert(&registerer, regist_data);
            Ok(())
        }
```
# (3)ビルド
- test-palletをビルドします。

```
cd pallets/test-pallet/
cargo build --release
```
- 無事ビルドが成功したら、全体をビルドします。

```
cd ../../
cargo build --release
```

#(4)Polkdatod/Substrate Portalで確認
- まず実行します。
- その前に、一度実行している場合は一度データをクリアします。

```
./target/release/node-template purge-chain --dev 
./target/release/node-template --dev
```

- Polkadot/Substrate Portalにアクセスします。
- 実装した関数を"Extrinsics"から呼ぼうとすると・・・
- "TestData"が指定できない・・・
<img width="780" alt="1.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628255/dfe269f1-e1be-fed3-cfa7-d29d8e50d2ad.jpeg">
- "設定"-"ディベロッパー"からTestDataの定義をJSON形式で追加します。

```
{
  "TestData": {
    "my_name": "Text",
    "my_address": "Text"
  }
}
```
<img width="780" alt="2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628255/4adebb28-eaa7-019b-dba6-53b4716db16a.jpeg">
- もう一度関数コール画面を確認すると・・・
- おお！入力出来る
<img width="780" alt="3.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628255/041a577d-76c5-f4e5-b506-c5f4690d9632.jpeg">

- 入力してトランザクションを発行します。
<img width="780" alt="4.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628255/8dea0ee5-43cd-c159-f6fd-331c2ca28c8f.jpeg">

- "チェーン状態"からデータの登録をします。
- 確かに登録されていることが確認出来ます。
<img width="780" alt="5.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628255/1a6f618b-b131-f58e-64fa-83a9d9832be1.jpeg">

# まとめ
- 途中をだいぶ端折っていますので同じ悩みをお持ちの方でご不明点がある方は、TelegramのSubstrate日本語チャネルで"stakahashi"までご連絡下さい。
- これでやっと自分の独自チェーンの実装が進められそうなのでやっていきたいです。
- Plasm Networkも引き続き応援していきます。
- いつも質問に回答頂くSubstrate日本語チャネルの方に感謝申し上げます。

# 見せられたものではありませんが全体ソースも公開しておきます。
- ★★余分なコード、冗長なコードが多くある可能性があります。
- "pallets/test-pallet/src/lib.rs"

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

use codec::{Decode, Encode};

/// A FRAME pallet template with necessary imports

/// Feel free to remove or edit this file as needed.
/// If you change the name of this file, make sure to update its references in runtime/src/lib.rs
/// If you remove this file, you can remove those references

/// For more guidance on Substrate FRAME, see the example pallet
/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs
use frame_support::{decl_error, decl_event, decl_module, decl_storage, dispatch};
use frame_system::{self as system, ensure_signed};
use sp_std::vec::Vec;

#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};

#[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 {
    pub my_name: Vec<u8>,
    pub my_address: Vec<u8>
}

impl core::fmt::Debug for TestData {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        write!(f, "Hi")
    }
}

/// The pallet's configuration trait.
pub trait Trait: system::Trait {
    // Add other types and constants required to configure this pallet.

    /// The overarching event type.
    type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}

// 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 {
        // Just a dummy storage item.
        // Here we are declaring a StorageValue, `Something` as a Option<u32>
        // `get(fn something)` is the default getter which returns either the stored `u32` or `None` if nothing stored
        Something get(fn something): Option<u32>;
        pub TestDatas: map hasher(blake2_128_concat) T::AccountId => TestData;
    }
}

// The pallet's events
decl_event!(
    pub enum Event<T>
    where
        AccountId = <T as system::Trait>::AccountId,
    {
        /// Just a dummy event.
        /// Event `Something` is declared with a parameter of the type `u32` and `AccountId`
        /// To emit this event, we call the deposit function, from our runtime functions
        SomethingStored(u32, AccountId),
    }
);

// The pallet's errors
decl_error! {
    pub enum Error for Module<T: Trait> {
        /// Value was None
        NoneValue,
        /// Value reached maximum and cannot be incremented further
        StorageOverflow,
        //test
        TestErrorErrorError,
    }
}

// The pallet's dispatchable functions.
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;

        /// Just a dummy entry point.
        /// function that can be called by the external world as an extrinsics call
        /// takes a parameter of the type `AccountId`, stores it, and emits an event
        #[weight = 10_000]
        pub fn do_something(origin, something: u32) -> dispatch::DispatchResult {
            // Check it was signed and get the signer. See also: ensure_root and ensure_none
            let who = ensure_signed(origin)?;

            // Code to execute when something calls this.
            // For example: the following line stores the passed in u32 in the storage
            Something::put(something);

            // Here we are raising the Something event
            Self::deposit_event(RawEvent::SomethingStored(something, who));
            Ok(())
        }

        /// Another dummy entry point.
        /// takes no parameters, attempts to increment storage value, and possibly throws an error
        #[weight = 10_000]
        pub fn cause_error(origin) -> dispatch::DispatchResult {
            // Check it was signed and get the signer. See also: ensure_root and ensure_none
            let _who = ensure_signed(origin)?;

            match Something::get() {
                None => Err(Error::<T>::NoneValue)?,
                Some(old) => {
                    let new = old.checked_add(1).ok_or(Error::<T>::StorageOverflow)?;
                    Something::put(new);
                    Ok(())
                },
            }
        }
        #[weight = 10_000]
        pub fn intentinaly_error(orign,value:u16) -> dispatch::DispatchResult {
            if value > 5{
                Ok(())
            }
            else{
                Err(Error::<T>::TestErrorErrorError)?
            }
        }
        #[weight = 10_000]
        pub fn save_testdata(origin, testdata:TestData) -> dispatch::DispatchResult {
            let registerer = ensure_signed(origin)?;
            let regist_data = TestData {
                my_name:testdata.my_name,
                my_address:testdata.my_address,
            };

            TestDatas::<T>::insert(&registerer, regist_data);
            Ok(())
        }
    }
}

```
- "pallets/test-pallet/Cargo.toml"

```
[package]
authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
description = 'FRAME pallet template'
edition = '2018'
homepage = 'https://substrate.dev'
license = 'Unlicense'
name = 'test-pallet'
repository = 'https://github.com/substrate-developer-hub/substrate-pallet-template/'
version = '2.0.0-rc4'

[package.metadata.docs.rs]
targets = ['x86_64-unknown-linux-gnu']
[dependencies.codec]
default-features = false
features = ['derive']
package = 'parity-scale-codec'
version = '1.3.1'

[dependencies.frame-support]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'v2.0.0-rc4'
version = '2.0.0-rc4'

[dependencies.frame-system]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'v2.0.0-rc4'
version = '2.0.0-rc4'
[dev-dependencies.sp-core]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'v2.0.0-rc4'
version = '2.0.0-rc4'

[dev-dependencies.sp-io]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'v2.0.0-rc4'
version = '2.0.0-rc4'

[dev-dependencies.sp-runtime]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'v2.0.0-rc4'
version = '2.0.0-rc4'

[dependencies.serde]
default-features = false
# git = 'https://github.com/paritytech/substrate.git'
# tag = 'v2.0.0-rc4'
version = '1.0.106'

[dependencies.sp-std]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
tag = 'v2.0.0-rc4'
version = '2.0.0-rc4'


[features]
default = ['std']
std = [
    'codec/std',
    'frame-support/std',
    'frame-system/std',
]

```