はじめてのブロックチェーン実践講座その２

# はじめに
本講座では、金融庁認定の暗号資産：**Symbol** ブロックチェーンを利用し、
**プログラム知識ゼロ**でブロックチェーンを自由に利用、体験していただきます。

また、本講座はTaka Nobu(@nem_takanobu）様の「[速習Symbolブロックチェーン](https://github.com/xembook/quick_learning_symbol/blob/main/01_introduction.md)」を元に作成しております。

本講座では、「[はじめてのブロックチェーン実践講座その１](https://qiita.com/nembear/items/7e17b143945eb8eb41f6)」を実施した方向けに書かれております。まだ実施していない方は、そちらから実施してください。また、本講座では、**複数トランザクションの同時送信。あなたのオリジナルトークン作成**が出来るようになります。

# 準備するもの
・インターネット接続環境
・Google Chromeブラウザ
・PC環境
・「[はじめてのブロックチェーン実践講座その１](https://qiita.com/nembear/items/7e17b143945eb8eb41f6)」の知識

# １．複数トランザクションの同時送信
### １－１．アグリゲートトランザクションとは？
「[はじめてのブロックチェーン実践講座その１](https://qiita.com/nembear/items/7e17b143945eb8eb41f6)」では、aliceからbobへの送金トランザクションを作成し、署名⇒アナウンスしました。今の皆さんの知識で、aliceからcarolへの送金も可能だと思います。ですが、１００人に送信する場合に、１つ１つトランザクションを送信するのは大変ですよね。そこで活躍するのが、***アグリゲートトランザクション***となります。簡単に説明すると、**１つのトランザクション内に複数の送信データを格納して一括で送るトランザクション**になります。

◆前回のトランザクションの流れ
１．bobへ１XYMをメッセージ付きで送るトランザクション作成
２．aliceの秘密鍵で署名
３．ノードへアナウンス⇒送金

◆今回のアグリゲートトランザクションの流れ
１．**bobとcarol**へ１XYMをメッセージ付きで送るトランザクション作成
２．aliceの秘密鍵で署名
３．ノードへアナウンス⇒送金

このようになります。

### １－２．事前準備
・[Symbol利用環境の構築](https://qiita.com/nembear/items/7e17b143945eb8eb41f6#%EF%BC%92%EF%BC%92symbol%E5%88%A9%E7%94%A8%E7%92%B0%E5%A2%83%E3%81%AE%E6%A7%8B%E7%AF%89)
・[alice、bob、carolのアカウントの呼び出し](https://qiita.com/nembear/items/7e17b143945eb8eb41f6#%EF%BC%94%EF%BC%91%E4%BA%8B%E5%89%8D%E7%A2%BA%E8%AA%8D)
※方法を忘れた際は、上記のリンク先にて実施してください。
・Symbolデスクトップウォレットの起動

### １－３．アグリゲートトランザクション作成
ここでは、アグリゲートトランザクションを作成します。ここで用意するトランザクションとは、
***１．送信先（bob,carol）***
***２．トークンとその枚数の指定(XYM１枚)***
***３．メッセージの有無（hello bob,hello carol）***
***４．ネットワークタイプ（Testnet）***
こちらを**bob,carolでそれぞれ先に作成**し、アグリゲートトランザクションとしてまとめたものとなります。

では早速、アグリゲートトランザクション生成のコマンドを観ていきましょう。
```js
//bobへの送金トランザクション 
innerTx1 = sym.TransferTransaction.create(
    undefined,
    bob.address, 
    [new sym.Mosaic(new sym.NamespaceId("symbol.xym"),sym.UInt64.fromUint(1000000))],
    sym.PlainMessage.create('hello bob'),
    networkType,
);
//carolへの送金トランザクション
innerTx2 = sym.TransferTransaction.create(
    undefined,
    carol.address, 
    [new sym.Mosaic(new sym.NamespaceId("symbol.xym"),sym.UInt64.fromUint(1000000))],
    sym.PlainMessage.create('hello carol'),
    networkType,
);
//上記をまとめたアグリゲートトランザクション宣言
aggregateTx = sym.AggregateTransaction.createComplete(
    sym.Deadline.create(epochAdjustment,6),
    [
//bobとcarolへの上記の送金トランザクションをそれぞれ呼び出し１つにまとめる
      innerTx1.toAggregate(alice.publicAccount), //aliceアカウントの公開鍵
      innerTx2.toAggregate(alice.publicAccount)  //aliceアカウントの公開鍵
    ],
    networkType,
    [],
    sym.UInt64.fromUint(1000000)//手数料
);
```
では、早速アグリゲートトランザクションをコンソール画面にコピーして貼り付けてみましょう。
![Capt_51.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/bd775eae-8af9-6403-5b03-d639319d77b5.jpeg)

エンターキーを押下し、以下の状態になればOKです。

![Capt_52.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/864b9b59-8b5e-0fc2-98e9-463d02085c0a.jpeg)

### １－４．署名
トランザクションは「誰に何をどう送るか？のセット」だとお伝えしたと思います。ですがそれだけでは、「***誰が送るのか？***」が足りていません。そこで、***送信元のサインを秘密鍵を利用して実施***いたします。以下のコマンドをご覧ください。
```js
signedTx = alice.sign(aggregateTx,generationHash);
console.log(signedTx);
```
ここでは、**aliceの秘密鍵を利用して、サイン**を行っています。前項目ではbob,carolへの送信アグリゲートトランザクションを作成したため、***aliceからbob,carolへ同時送信を行う***ことになります。早速、コマンドをconsole画面に入力→エンターキーを押下してください。
![Capt_53.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/4a12ea06-dd26-12f3-1f45-b000d0479792.jpeg)

### １－５．アナウンス
ここまで、アグリゲートトランザクション（bobとcarolに何を何枚送るか）を作成し、そこに署名（aliceから送信）をいたしました。では、いよいよこれを ***Symbolブロックチェーンノードにアナウンス***（送信)しましょう。以下のコマンドを入力してください。
***※エンターキーは押下しないこと***
```js
await txRepo.announce(signedTx).toPromise();
```
![Capt_60.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/7b53638f-443d-2566-46a5-b6882009d96a.jpeg)
上記の状態になればOKです。それではアナウンスをする前に、Symbolウォレットでaliceのホーム画面を表示させてください。
では、Symbolウォレットを起動したまま、console画面にてエンターキーを押下しノードへアナウンスをしてください。
![Capt_60.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/fd80b647-9ff8-0967-81a0-d3ee500122e3.jpeg)
上記と同時に、Symbolウォレットから「チャリン」と音が鳴ると思います。Symbolウォレットを確認してください。あなたのコマンド入力で、Symbolウォレットに反映されました。名称が前回と異なり、**アグリゲートコンプリート**と表示されています。
![Capt_56.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/d720a4dc-e841-c062-d4de-6e478261b1be.jpeg)
続いて、Symbolウォレットのアグリゲートコンプリートをクリックして、詳細を観てみましょう。
![Capt_57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/7bd50791-6594-da7b-1286-efc64fcc9773.jpeg)
前回の講座での通常トランザクションとは異なり、アグリゲートコンプリートと表示されています。更に、トランザクション詳細として、**alice⇒bob、alice⇒carolへ同時に送金**されていることが分かります。

bobとcarolのアカウントを確認してみましょう。指定した「***１XYM、メッセージ：hallo bob/hallo carol***」がそれぞれ入金されていることが確認できます。
◆bob詳細
![Capt_58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/79b655ac-b375-fef0-c307-6641739089ec.jpeg)
◆carol詳細
![Capt_59.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/014c9812-7a93-af95-c60e-a2c6a1ab46a5.jpeg)

おめでとうございます。***これであなたはブロックチェーンでのアグリゲートトランザクション送金を自身で可能となりました***。複数のトランザクションを一括して送るときにとても便利な機能です。ユースケースとしては、**オリジナルトークンをチケットとして作成し、購入者に一括して送信する**等、様々な利用方法が考えられます。

次の章からは、**あなたのオリジナルトークン**を作成していきましょう。

# ２．オリジナルトークン作成
### ２－１．オリジナルトークンとは？
Symbolでは、簡単に**あなただけのユニークなトークン（SymbolではMosaicと呼びます）を作成する**ことが出来ます。例えば、いままで送金していたXYMをトークンとして分解すると以下の通りとなります。

**◆XYMの詳細**
・ネームスペース：Symbol
・サブネームスペース：XYM
・モザイクID：72C0212E67A08BCE(ユニークなIDとなります。)
・表示：Symbol.XYM（実際にウォレットでは以下のように表示されています）
![Capt_61.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/b8fc0446-0498-594e-1658-730158261575.jpeg)
本章では「Symbol.XYM」のように、**あなただけのトークン**を作成しましょう。今回、私は「nembear.coin」というオリジナルトークンを作成していきます。

### ２－２．モザイクID作成
前章で説明した、**モザイクID**の部分から作成いたします。まずは、**carolアカウント**に３００XYMを送金しましょう。（やり方を忘れた方は[こちら](https://qiita.com/nembear/items/7e17b143945eb8eb41f6#%EF%BC%93%EF%BC%92symbol%E3%82%A6%E3%82%A9%E3%83%AC%E3%83%83%E3%83%88%E3%81%A8%E3%81%AE%E9%80%A3%E5%8B%95)ラストから）

では早速、モザイクから作成しましょう。
```js
//モザイクトランザクション定義１
supplyMutable = true; //供給量変更の可否(初期設定から枚数の変更が可能)
transferable = true; //第三者への譲渡可否(carol⇒alice⇒bobへの譲渡可能)
restrictable = true; //制限設定の可否(モザイク制限可能)
revokable = false; //発行者からの還収可否(carolからの還収不可)

nonce = sym.MosaicNonce.createRandom();
mosaicDefTx = sym.MosaicDefinitionTransaction.create(
    undefined, 
    nonce,
    sym.MosaicId.createFromNonce(nonce, carol.address), //モザイクID生成
    sym.MosaicFlags.create(supplyMutable, transferable, restrictable, revokable),
    0,//divisibility:可分性(1)
    sym.UInt64.fromUint(0), //duration:有効期限(0=無制限) 
    networkType
);
```
これで、carolのアカウントで作成されるモザイク定義１が登録されます。
console画面にて、コマンド全文をコピーして入力してください。その後、エンターキーを押下してください。
![Capt_62.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/31466f76-e25c-6556-c481-68d1f68e0871.jpeg)
続いて、モザイクの枚数を定義します。１００枚のモザイクを作成します。
```js
//モザイクトランザクション定義２
mosaicChangeTx = sym.MosaicSupplyChangeTransaction.create(
    undefined,
    mosaicDefTx.mosaicId,
    sym.MosaicSupplyChangeAction.Increase,
    sym.UInt64.fromUint(100), //モザイク枚数１００枚
    networkType
);
```
console画面にて、コマンド全文をコピーして入力してください。その後、エンターキーを押下してください。
![Capt_63.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/247a0748-d9d0-8e1d-0d6f-e9ba3cb36088.jpeg)
これで、あなたの**オリジナルトークン（モザイク）がすべてトランザクションとして定義**されました。２つのトランザクションですので、第１章で実施した**アグリゲートトランザクション**で、署名⇒アナウンスしましょう。
```js
//アグリゲートトランザクションを使用
aggregateTx = sym.AggregateTransaction.createComplete(
    sym.Deadline.create(epochAdjustment),
    [
      mosaicDefTx.toAggregate(carol.publicAccount),//carolの公開鍵を使用
      mosaicChangeTx.toAggregate(carol.publicAccount),//carolの公開鍵を使用
    ],
    networkType,[],
).setMaxFeeForAggregate(100, 0);

signedTx = carol.sign(aggregateTx,generationHash);//carolの秘密鍵で署名
await txRepo.announce(signedTx).toPromise();//ノードへアナウンス
```
console画面にて、コマンド全文をコピーして入力してください。その後、エンターキーを押下してください。
![Capt_64.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/a3a55ba8-46c3-be73-d744-145509f80cc2.jpeg)
それでは早速、carolのアカウントをSymboウォレットで確認しましょう。以下の通り、新規のオリジナルトークン（モザイク）がアグリゲートトランザクションで作成されました。
![Capt_65.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/6155217a-765e-8c98-32cb-81cb9f4f35f3.jpeg)
続いて、アグリゲートトランザクションの中身を確認しましょう。**ユニークなモザイクIDが発行されています**（ここでは「0B84D717C9DA3F82」）更に設定が、指定した通りになっていることを確認してください。さらに、１００枚発行されていることが確認できます。また、**トークン発行には手数料として５０XYMがかかる**ことをご承知おきください。
![Capt_66.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/0ad4701a-8f1e-fa1a-40cf-186e46c2c489.jpeg)
おめでとうございます！これで、**あなたのオリジナルトークンが作成されました**。早速このトークン（モザイク）をAliceに送信してみましょう。console画面にて、コマンド全文をコピーして入力してください。その後、エンターキーを押下してください。
```js
//モザイクIDを指定しトランザクションを作成
 tx = sym.TransferTransaction.create(
                sym.Deadline.create(epochAdjustment, 6),
                sym.Address.createFromRawAddress("あなたのaliceのアドレスを入力してください。"),
                [new sym.Mosaic(new sym.MosaicId('あなたのモザイクIDを入力してください'), sym.UInt64.fromUint(1))],//モザイクIDと枚数を指定(１枚）
                sym.PlainMessage.create('オリジナルモザイク'),
                sym.NetworkType.TEST_NET,
            ).setMaxFee(100);

signedTx = carol.sign(tx,generationHash);//carolの秘密鍵で署名
console.log(signedTx);
res = await txRepo.announce(signedTx).toPromise();//ノードへアナウンス
console.log(res);
```
下記のように表示されればOKです。続いてSymbolウォレットのaliceアカウントを開いてみましょう。
![Capt_67.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/bec588c6-7911-e20d-955c-497899bf83c4.jpeg)
このように、あなたのオリジナルトークンの送金が完了しました。**送信トランザクション内の【MosaicId】を変更する**と自由に送金が出来ます。**XYMも皆さんが作ったオリジナルトークンの１つ**ということですね。
![Capt_68.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/5e7aa2c4-35a5-8714-33dd-6fea7d396c9a.jpeg)
### ２－３．ネームスペース、サブネームスペース作成
前章で、オリジナルトークン（モザイクIDの発行）作成を行いました。ですが、見た目が文字列になっております。これだと、受け取った方も誰のトークンか認識するのが難しいと思います。そこで、ここでは、**モザイクIDにネームスペースを紐づけたい**と思います。意味合いとしては以下の通りです。
**◆ネームスペース例（XYMの場合）
・ネームスペース「Symbol」を取得
　⇒サブネームスペース「XYM」を取得
　　⇒モザイクID「72C0212E67A08BCE」をサブネームスペースに紐づける**
その結果、**モザイクID「72C0212E67A08BCE」を「Symbol.XYM」と認識させる**ことが出来ます。今回の講座では、私は作成したモザイクIDを「nembear.coin」として認識させたいと思います。**皆さんもオリジナルの名称を考えてください**。

では早速、carolのアカウントで、ネームスペース、サブネームスペースを取得しましょう。まずは、***ネームスペースをレンタルします***。console画面にて、コマンド全文をコピーして入力後に**指定通り編集**してください。その後、エンターキーを押下してください。
**※注意：ネームスペースはユニークな文字列(英数字)のみ有効となります。既に誰かが取得しているネームスペースはレンタルすることが出来ません。**
```js
tx = sym.NamespaceRegistrationTransaction.createRootNamespace(
    sym.Deadline.create(epochAdjustment),
    "あなたがレンタルしたいネームスペース名を入力してください。",
    sym.UInt64.fromUint(86400),
    networkType
).setMaxFee(100);
signedTx = carol.sign(tx,generationHash);//carolの秘密鍵で署名
await txRepo.announce(signedTx).toPromise();
```
下記の通り、表示されればOKです。（私は「nembear」という名前のネームスペースを入力しています。）
![Capt_71.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/e6599f57-6ecb-5446-f7ea-23ad9b8b1121.jpeg)
早速、carolのアカウントをSymbolウォレットで確認してみましょう。予定通り、**ネームスペースの登録**がトランザクションとして表示されています。
![Capt_72.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/5d77533d-68e7-a3b9-43f6-2653cc56a7d9.jpeg)
さらに詳細を観てみましょう。スペース名として**あなたが指定したネームスペース名**、レンタル期間が３０日（延長可能です）、そしてレンタル料（レンタル期間によって金額が変更されます）が表示されています。
![Capt_73.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/2fb30f98-b09f-90f3-b8a1-228311c05d34.jpeg)
続いて、carolのアカウントで、***サブネームスペースをレンタルします***。console画面にて、コマンド全文をコピーして入力してください。その後、エンターキーを押下してください。
```js
subNamespaceTx = sym.NamespaceRegistrationTransaction.createSubNamespace(
    sym.Deadline.create(epochAdjustment),
    "coin",  //あなたが作成したいサブネームスペースを入力してください。
    "nembear", //先ほど作成したネームスペースを入力してください。
    networkType,
).setMaxFee(100);
signedTx = carol.sign(subNamespaceTx,generationHash);
await txRepo.announce(signedTx).toPromise();
```
下記の通り、表示されればOKです。
![Capt_74.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/b05748f5-4ddd-547c-d400-95f583ba15e2.jpeg)
早速、carolのアカウントをSymbolウォレットで確認してみましょう。予定通り、ネームスペースの登録がトランザクションとして表示されています。
![Capt_75.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/c885a071-fa1a-4b09-f259-bb99501c0eec.jpeg)
さらに詳細を観てみましょう。サブスペース名として**あなたが指定したサブネームスペース名**、紐づけたネームスペース名、そしてレンタル料が表示されています。
![Capt_76.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/d6ba5d44-36cb-9760-46f5-fb3e73a6617e.jpeg)
これで、ネームスペース、サブネームスペースを取得することが出来ました。次章では、このネームスペースをアカウントに紐づけましょう。
### ２－４．オリジナルトークン作成
前章で、ネームスペースの作成を行いました。ここでは、それを**アカウント、モザイクIDと紐づけて、オリジナルのトークンを作成**しましょう。まずは**アカウントへのリンク**を実施いたします。
console画面にて、コマンド全文をコピーして入力してください。その後、エンターキーを押下してください。
```js
namespaceId = new sym.NamespaceId("あなたのネームスペース入力してください");
address = sym.Address.createFromRawAddress("carolのアドレスを入力してください");
tx = sym.AliasTransaction.createForAddress(
    sym.Deadline.create(epochAdjustment),
    sym.AliasAction.Link,
    namespaceId,
    address,
    networkType
).setMaxFee(100);
signedTx = carol.sign(tx,generationHash);
await txRepo.announce(signedTx).toPromise();
```
下記の通り、表示されればOKです。
![Capt_77.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/74a32dbd-b310-c443-800b-56513024155b.jpeg)
早速、carolのアカウントをSymbolウォレットで確認してみましょう。予定通り、アドレスエイリヤスの登録がトランザクションとして表示されています。
![Capt_78.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/9215a94f-493e-8ff3-15fe-a9cc562642a8.jpeg)
さらに詳細を観てみましょう。**ネームスペースID、LINK、carolアドレス**が設定されているのが確認できます。
![Capt_79.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/abf1725c-bbee-788d-8d4b-b14f3b42cf5e.jpeg)
さらに、ネームスペースを確認すると、**ネームスペースがcarolのアドレスに紐づいている**ことが確認できます。
![Capt_80.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/af94d3d4-88b6-2cf5-2d7c-797c5edff5bb.jpeg)
それではいよいよ、**モザイクIDと紐づけて、オリジナルトークンを作成**しましょう。
console画面にて、コマンド全文をコピーして入力してください。その後、エンターキーを押下してください。
```js
namespaceId = new sym.NamespaceId("あなたのネームスペース、サブネームスペースを入力してください");//例：nembear.coin
mosaicId = new sym.MosaicId("あなたのモザイクIDを入力してください");
tx = sym.AliasTransaction.createForMosaic(
    sym.Deadline.create(epochAdjustment),
    sym.AliasAction.Link,
    namespaceId,
    mosaicId,
    networkType
).setMaxFee(100);
signedTx = carol.sign(tx,generationHash);
await txRepo.announce(signedTx).toPromise();
```
下記の通り、表示されればOKです。
![Capt_81.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/211fb55e-1541-13fb-a104-561a72f2ebbd.jpeg)
早速、carolのアカウントをSymbolウォレットで確認してみましょう。予定通り、モザイクエイリヤスの登録がトランザクションとして表示されています。更に、アセット欄のモザイク名称が、**ネームスペース.サブネームスペース**として表示されています。
![Capt_82.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/b03f6822-8b4d-4ebc-6891-839bec4a796d.jpeg)
さらに詳細を観てみましょう。**ネームスペースID、LINK、モザイクID**が設定されているのが確認できます。
![Capt_83.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/3f1fed44-4340-d904-9d1a-f823fa066198.jpeg)
さらに、ネームスペースを確認すると、**ネームスペースがモザイクIDに紐づいている**ことが確認できます。
![Capt_84.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/c37e9ef9-df13-be68-0fe9-7c73b7b2cd27.jpeg)
続いて、モザイクを見てみましょう。**モザイクIDに指定した名前（ネームスペース、サブネームスペース）が付きました**。これで、あなたのオリジナルトークンの完成です。
![Capt_85.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/34dfae1b-bba1-33c0-4448-34aa373542b0.jpeg)
aliceのアカウントにも、モザイクIDだったトークンが、名前入り変更されています。
![Capt_87.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/9baef38d-964d-44f8-8487-ee3391e8fe20.jpeg)
# ３．回収可能トークンの発行と回収
### ３－１．回収可能トークンとは？？
前章までで作成したトークンは、**１度送ってしまうと送信先アカウントが送り返さない限り元に戻すことは出来ません**。ですが、回収可能トークンは、**自身で送ったトークンを回収することが可能です**。
◆**ユースケース**
・サブスク：あなたの作ったトークンの所持者のみ閲覧出来るサイトや記事を作成し、月々の支払いがない場合、トークンを回収することでサブスクリプションが成立。
・チケット：あなたの作ったトークンの所持者のみ参加できるイベントを開催し、イベント終了後回収することで、チケットとして成立。
◆**特記事項**
・手数料が作成者払い：Symbolブロックチェーンでは送信時に手数料がかかります。その結果、XYMを持っていない方は受信は出来ますが、送信が出来ません。ですが、回収可能トークンは回収手数料がトークン作成者が持つので、どんなユーザーにも送ることが出来ます。

### ３－２．回収トークンの作成
早速作成していきましょう。前章とやり方は同じです。モザイクトランザクション定義１の**revokable**のみ**true**に設定してください。そこからは、前章と同様の操作となります。（便宜上、**carolのアカウント**で作成してください）
```
//モザイクトランザクション定義１
supplyMutable = true; //供給量変更の可否(初期設定から枚数の変更が可能)
transferable = false; //第三者への譲渡可否(carol⇒alice⇒bobへの譲渡可能)
restrictable = true; //制限設定の可否(モザイク制限不可)
revokable = true; //発行者からの還収可否(carolからの還収不可)

nonce = sym.MosaicNonce.createRandom();
mosaicDefTx = sym.MosaicDefinitionTransaction.create(
    undefined, 
    nonce,
    sym.MosaicId.createFromNonce(nonce, carol.address), //モザイクID生成
    sym.MosaicFlags.create(supplyMutable, transferable, restrictable, revokable),
    0,//divisibility:可分性(1)
    sym.UInt64.fromUint(0), //duration:有効期限(0=無制限) 
    networkType
);
```
### ３－３．回収トークンの回収方法
回収可能トークンを回収するトランザクションを説明いたします。準備として、回収可能トークンをbobに送信してください。
![Capt_88.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/722864d3-8f3f-6986-5525-8bfa46b5b2c5.jpeg)
回収トランザクションは以下の通りとなります。入力後にエンターキーを押下してください。（エンターキーを押下後に自動回収される為、bobのアカウントを開いておきましょう）
```
 revTx = sym.MosaicSupplyRevocationTransaction.create(
                sym.Deadline.create(epochAdjustment),
                sym.Address.createFromRawAddress("bobのアドレスを入力"),
                new sym.Mosaic(new sym.MosaicId("回収可能トークンのモザイクIDを入力"), sym.UInt64.fromUint(1)),
                sym.NetworkType.TEST_NET,
                sym.UInt64.fromUint(100000)
            );
            
            signedTx = carol.sign(revTx, generationHash);
            new sym.TransactionHttp(NODE)
                .announce(signedTx)
                .subscribe((x) => console.log(x), (err) => console.error(err));
```
未承認の場合はまだ、回収可能トークンが存在しています。
![Capt_89.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/d994ec0f-497a-91a4-2dd3-d5956e27e1d9.jpeg)
承認済みになると、回収可能トークンが消え、carolのアカウントへ戻ります。
![Capt_90.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217292/7a38a843-abcc-6593-2ba2-a83b59cb3611.jpeg)

おめでとうございます。これで回収可能トークンまで作成することが出来るようになりました。「はじめてのブロックチェーン実践講座その１」に比べ、**Symbolブロックチェーンの見識がさらに高まったことと思います**。Symbolブロックチェーンを利用してのアイデアや想像も広がったのではないでしょうか？そこで、皆さんに是非実施して欲しいことがあります。「[速習Symbolブロックチェーン](https://github.com/xembook/quick_learning_symbol/blob/main/01_introduction.md)」を是非実施してください。今のあなたの知識では**すんなり、そして深くSymbolブロックチェーンを学ぶことが出来ます**。ここまでお付き合いいただきありがとうございました。感謝申し上げます。