このガイドでは Symbol Developer Documentation 開発サイクルについて説明します。
はじめに Symbol Developer Documentation で利用可能な組み込み機能の モザイク や アカウント を組み合わせてソリューションを設計します。このガイドを修了すれば、ブロックチェーンでトランザクションの発行および監視する方法を理解しているでしょう。
チケット二次市場は、再販市場としても知られており、最初の販売者からチケットを購入した後に個人間で行われるチケット交換です。最初の販売者は、イベントウェブサイト、オンラインチケット販売プラットフォーム、イベントの入口にあるショップまたは売店であったりします。
最初の販売者ではない人からチケットを購入しても、必ずしもそのチケットの追加料金を支払うという意味ではありません。これは最初の販売者が問題の解決に何もできず、偽造もしくは複製されたチケットを購入してしまう、被害者となる機会です。
チケット販売者はシステムのセットアップを望んでいます:
各チケットと購入者の識別。
チケット転売の防止。
未認証チケットとその複製の防止。
ブロックチェーンテクノロジーはこのようなケースに適用できます:
様々な参加者が関係します。
参加者はお互いに信頼する必要があります。
不変のイベントの集合を追跡し続ける必要があります。
Symbol は フレキシブルなブロックチェーン テクノロジーです。すべてのアプリケーションロジックをブロックチェーンにアップロードする代わりに、 API 呼び出し によってテスト済みの機能を使用して、価値、認可、トレーサビリティ、そして認証の移転と格納を行うことができます。
残りのコードは オフチェーン のままです。これにより必要に応じてプロセスを変更できるため、固有の不変性リスクが軽減されます。
まず、解決したいユースケースに関与するアクターを特定します:
チケット販売者
購入者
チケット販売者と顧客を別々の アカウント として表現することにしました。アカウントとは対応する秘密鍵で変更できる、ブロックチェーン上の預金金庫と考えてください。各アカウントは一意であり、アドレスによって識別されます。
テスト symbol.xym
をアカウントへ入金しましたか? 前のガイド では Symbol CLI を使用してアカウントの作り方を学習しました。このアカウントは チケット販売者 アカウントとして表現します。
次のコマンドを実行して、チケット販売者のアカウントに symbol.xym
単位があることを確認します。
symbol-cli account info --profile testnet
このような行がスクリーンに表示されているはずです:
Account Information
┌───────────────────┬────────────────────────────────────────────────┐
│ Property │ Value │
├───────────────────┼────────────────────────────────────────────────┤
│ Address │ TCWYXK-VYBMO4-NBCUF3-AXKJMX-CGVSYQ-OS7ZG2-TLI │
├───────────────────┼────────────────────────────────────────────────┤
│ Address Height │ 1 │
├───────────────────┼────────────────────────────────────────────────┤
│ Public Key │ 203...C0A │
├───────────────────┼────────────────────────────────────────────────┤
│ Public Key Height │ 3442 │
├───────────────────┼────────────────────────────────────────────────┤
│ Importance │ 0 │
├───────────────────┼────────────────────────────────────────────────┤
│ Importance Height │ 0 │
└───────────────────┴────────────────────────────────────────────────┘
Balance Information
┌──────────────────┬─────────────────┬─────────────────┬───────────────────┐
│ Mosaic Id │ Relative Amount │ Absolute Amount │ Expiration Height │
├──────────────────┼─────────────────┼─────────────────┼───────────────────┤
│ 5E62990DCAC5BE8A │ 750.0 │ 750000000 │ Never │
└──────────────────┴─────────────────┴─────────────────┴───────────────────┘
アカウントは 750 symbol.xym
相対単位を保有しています。もし "Balance Information" の次の行が空の場合は、テスト用通貨を手に入れるために 前のガイド に従ってください。
購入者 を識別するための2つ目のアカウントを CLI で作成します。
symbol-cli account generate --network TEST_NET --save \
--url <NODE_URL> --profile customer
New Account
┌─────────────┬────────────────────────────────────────────────┐
│ Property │ Value │
├─────────────┼────────────────────────────────────────────────┤
│ Address │ TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I │
├─────────────┼────────────────────────────────────────────────┤
│ Public Key │ E59...82F │
├─────────────┼────────────────────────────────────────────────┤
│ Private Key │ 111...111 │
└─────────────┴────────────────────────────────────────────────┘
アカウントはトランザクションを通じてブロックチェーンの状態を変更します。アカウントがトランザクションをアナウンスすると、正しく構成されている場合、サーバーは OK のレスポンスを返します。
ただし OK レスポンスを受信しても、トランザクションが有効であったり、ブロックに含まれるわけではありません。たとえば、発行者に十分な symbol.xym
がない、メッセージセットが大きすぎる、手数料の指定が少なすぎるなど、トランザクションが拒否される可能性があります。
ネットワークによって承認または拒否されるタイミングを検知するために、アナウンスする前に トランザクションを監視する ことを推奨します。
In a new terminal, monitor the transactions involving the ticket vendor's account to know if they are confirmed or rejected by the network.
symbol-cli monitor all --address TCWYXK-VYBMO4-NBCUF3-AXKJMX-CGVSYQ-OS7ZG2-TLI
Symbol モザイク でチケットを表現します。この機能は物体、チケット、クーポン、株式に相当するもの、あなたの暗号通貨さえも、いかなるアセットをブロックチェーン上に表現することができます。
モザイクは作成時に定義される変更可能なプロパティを持ちます。例えば 転送可能プロパティを false に設定します。これは、チケットの転売を防止するために、購入者がモザイク作成者だけに送り返すことしかできないことを意味します。
CLI を使用し、チケット販売者アカウントでチケットを表現する新しいモザイクを作成します。この新しいモザイクは次のように構成します:
プロパティ |
値 |
説明 |
---|---|---|
Divisibility |
0 |
“0.5 tickets” が送信できないように、モザイクは可分できないようにします。 |
Duration |
1000 |
モザイクは 1000 ブロック登録されます。 |
Amount |
99 |
作成するチケットの量 |
Supply mutable |
True |
モザイク供給量は後に変更可能です。 |
Transferable |
False |
モザイクはモザイク作成者だけに送り返すことしかできません。 |
symbol-cli transaction mosaic --amount 99 --supply-mutable \
--divisibility 0 --duration 1000 --max-fee 2000000 \
--sync --profile testnet
トランザクションをアナウンスしたら、ターミナルに表示された MosaicID コピーしてください。
The new mosaic id is: 7cdf3b117a3c40cc
トランザクションは最大30秒で承認済みとして現れてきます。ターミナルでエラーが起きた場合、エラーコードの意味は こちら を参照してください。
モザイクを定義したので、1 つのチケット単位を TransferTransaction をアナウンスして顧客に送信します。
新しいファイルを開き、次の値で TransferTransaction を定義してください。
プロパティ |
値 |
説明 |
---|---|---|
Deadline |
デフォルト (2 時間) |
トランザクションがブロックチェーンに取り込まれるまで待機できる最大時間。この時間を経過しても未確認の場合、トランザクションはドロップされます。パラメタは時間単位で定義され、 1 〜 6 の範囲です ( アグリゲートボンド トランザクションの場合は 1 〜 48) |
Recipient |
TCHBDE...32I |
受信のアカウントアドレス。このケースでは顧客のアドレスです。 |
Mosaics |
[1 |
送信するモザイクの配列 |
Message |
enjoy your ticket |
添付されたメッセージ |
Network |
TEST_NET |
ネットワークタイプ |
// replace with mosaic id
const mosaicIdHex = '7cdf3b117a3c40cc';
const mosaicId = new MosaicId(mosaicIdHex);
// replace with customer address
const rawAddress = 'TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I';
const recipientAddress = Address.createFromRawAddress(rawAddress);
// replace with network type
const networkType = NetworkType.TEST_NET;
const transferTransaction = TransferTransaction.create(
Deadline.create(epochAdjustment),
recipientAddress,
[new Mosaic(mosaicId, UInt64.fromUint(1))],
PlainMessage.create('enjoy your ticket'),
networkType,
UInt64.fromUint(2000000),
);
// replace with mosaic id
const mosaicIdHex = '7cdf3b117a3c40cc';
const mosaicId = new symbol_sdk_1.MosaicId(mosaicIdHex);
// replace with customer address
const rawAddress = 'TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I';
const recipientAddress = symbol_sdk_1.Address.createFromRawAddress(rawAddress);
// replace with network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
const transferTransaction = symbol_sdk_1.TransferTransaction.create(symbol_sdk_1.Deadline.create(epochAdjustment), recipientAddress, [new symbol_sdk_1.Mosaic(mosaicId, symbol_sdk_1.UInt64.fromUint(1))], symbol_sdk_1.PlainMessage.create('enjoy your ticket'), networkType, symbol_sdk_1.UInt64.fromUint(2000000));
// replace with node endpoint
try (final RepositoryFactory repositoryFactory = new RepositoryFactoryVertxImpl(
"NODE_URL")) {
// replace with mosaic id
final String mosaicIdHex = "7cdf3b117a3c40cc";
final MosaicId mosaicId = new MosaicId(mosaicIdHex);
// replace with customer address
final String rawAddress = "TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I";
final UnresolvedAddress recipientAddress = Address.createFromRawAddress(rawAddress);
final NetworkType networkType = repositoryFactory.getNetworkType().toFuture().get();
final Mosaic mosaic = new Mosaic(mosaicId, BigInteger.valueOf(1));
final TransferTransaction transferTransaction = TransferTransactionFactory
.create(
networkType,
recipientAddress,
Collections.singletonList(mosaic),
PlainMessage.create("Enjoy your ticket"))
.maxFee(BigInteger.valueOf(2000000)).build();
トランザクションは定義されましたが、まだネットワークへはアナウンスされていません。
ネットワークがトランザクションの信頼性を検証できるように チケット販売者のアカウント でトランザクションに署名をします。
注釈
Include the network generation hash to make the transaction only valid for your network. Open NODE_URL /node/info
in a new browser tab and copy the meta.networkGenerationHash
value.
// replace with ticket vendor private key
const privateKey =
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
const account = Account.createFromPrivateKey(privateKey, networkType);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
'1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = account.sign(
transferTransaction,
networkGenerationHash,
);
// replace with ticket vendor private key
const privateKey = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
const account = symbol_sdk_1.Account.createFromPrivateKey(privateKey, networkType);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash = '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = account.sign(transferTransaction, networkGenerationHash);
// replace with ticket vendor private key
final String privateKey = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
// replace with network generation hash
final String generationHash = repositoryFactory.getGenerationHash().toFuture().get();
final Account account = Account
.createFromPrivateKey(privateKey, networkType);
final SignedTransaction signedTransaction = account
.sign(transferTransaction, generationHash);
署名が終わったら、トランザクションをネットワークへアナウンスします。
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe(
(x) => console.log(x),
(err) => console.error(err),
);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp.announce(signedTransaction).subscribe((x) => console.log(x), (err) => console.error(err));
final TransactionRepository transactionRepository = repositoryFactory
.createTransactionRepository();
transactionRepository.announce(signedTransaction).toFuture().get();
}
symbol-cli transaction transfer --recipient-address TCHBDE-NCLKEB-ILBPWP-3JPB2X-NY64OE-7PYHHE-32I --mosaics 7cdf3b117a3c40cc::1 --message enjoy_your_ticket --max-fee 2000000 --sync
トランザクションを監視しているターミナルウィンドウを確認します。トランザクションが承認されたら、次のコマンドで顧客がチケットを受け取ったかどうかを確認できます。
symbol-cli account info --profile customer
✅ 各購入者の識別: 各購入者の Symbol アカウントの作成
✅ チケットの転売防止: 転送不可能なモザイクの作成
✅ 未認証なチケットとその複製: 一意なモザイクの作成
Symbol ビルドイン機能 の学習を続ける。