KeyStoneとは
KeyStoneの名前は、日本語で「要石」や「楔石」と言い、橋やアーチの頂部にある楔形の石のことで、橋の中核となり安定性を高める役割をはたすもので、KeyStoneがユーザーとSymbolに橋をかけその中核として働くものを目指しています。また、Keyはブロックチェーン技術を支える公開鍵・秘密鍵といった技術を表し、Stoneは石のような硬さ・堅牢さのメタファーから来ています。
KeyStoneは単一のアプリケーションではなく、WalletやIDシステム、連携アプリケーションを開発するインフラとしての機能を提供する「あなたとSymbolエコシステムに橋を架ける」ものを目指しています。
KeyStoneWallet について
KeyStoneではiOS、Android、ブラウザ拡張機能でWalletアプリケーションの展開を予定しています。
機能としては、通常のウォレットアプリと同様な残高や所持しているモザイクの確認、トランザクション履歴の確認や、連絡先機能に加えて、連携アプリ機能があります。これは以前作ったSSS Extensionと同様な機能だと思っていただけるといいかと思います。
アプリ内ブラウザでKeyStoneに対応したSymbolアプリケーションを開き、Webアプリケーションからトランザクションを受け取るとトランザクションの内容が表示され、署名ボタンを押すとアクティブアカウントとして設定しているアカウントでトランザクションに署名し、署名済みトランザクションがアプリケーションへと返却されます。

また、この他にも任意のデータへの電子署名機能や、アクティブアカウントの公開鍵やアドレス、表示名を取得することができます。
実装のヒント
const signedPayload = window.catapult.requestSignTransaction(payload)
KeyStone Identities について
KeyStoneでは、ユーザーが管理する秘密鍵に加えて、システムで管理するKeyStoneID(公開鍵)とそれに紐づく秘密鍵が存在します。この秘密鍵は完全にKeyStoneシステムの中でのみ利用される鍵で内部的なIDとして利用されます。
また、KeyStoneで利用しているアカウントをKeyStoneIDに紐付けることで、KeyStoneIDの操作を自身のアカウントで行うことを実現します。また、ハーベスト通知などのホルダー向け機能の提供などを作ろうと思っています。
公式アプリについて
KeyStoneエコシステムに登場するアプリにはいくつかの種類があり、一つ目が公式アプリです。
これは、〇〇.key-st.one のURLで配信されるアプリ群を指し、まずは、先述したハーベスト関連のアプリなどホルダーが便利になるようなものから作っていきたいと思っています。SNSとかチャットアプリみたいなのも作りたい気持ちはある
連携アプリについて
〇〇.key-st.one以外でKeyStoneと連携することができるアプリケーションの総称。
以下の2種類に分かれる。
- KeyStoneIDを利用するアプリ
- KeyStoneで署名するアプリ
KeyStoneIDを利用するアプリ
KeyStoneにアプリケーションを登録すると、KeyStoneIDでログインを行うことができるようになる。ログインしているユーザーのKeyStoneIDを取得できるため、KeyStoneと連携したアプリで統一されたIDシステムを利用することができる。
KeyStoneで署名するアプリ
window.catapultを用いてアクティブアカウントの情報取得や、トランザクション、データへの署名を利用して秘密鍵に触れることなくSymbolアプリケーションを開発することができる。
開発者ポータルについて
KeyStoneIDを利用するアプリを開発する際に、アプリケーションの登録・管理をするためのポータルサイト、管理ポータルを経由してユーザーへのプッシュ通知機能などを提供できるようにしたいと思っています。
マネタイズについて
基本機能は全て無料で提供し、機能の上限の緩和などをプレミアムプランとして提供する形を考えています。現状作り始めているものとしては
- Walletのカラーテーマ
- KeyStoneIDへ連携するアカウント数の上限緩和 (3 -> 5, 10 みたいなイメージ)
- 通知系
- 開発支援系
などは作っていく予定です。
(開発や運用にそこそこお金がかかるのでぜひ課金して頂けると嬉しいです)
まとめ
Walletを含めた新しいエコシステムを作っていきますよって話、βテストもそろそろ始めます!
2026年、KeyStoneでSymbolを盛り上げていきたいので、よろしく!
おまけ サンプル実装
転送トランザクション作成サンプル
const txDes = new descriptors.TransferTransactionV1Descriptor(
new Address(params.recipientAddress),
[
new descriptors.UnresolvedMosaicDescriptor(
new models.UnresolvedMosaicId(networkCurrencyMosaicId),
new models.Amount(amount),
),
],
new Uint8Array([0x00, ...new TextEncoder().encode(msg)])
)
const transaction = facade.createTransactionFromTypedDescriptor(
txDes, new PublicKey(publicKey), 100, 7200
);
const transactionBytes = transaction.serialize()
const signedTransactionPayload = await window.catapult.requestSignTransaction(
utils.uint8ToHex(transactionBytes)
)
const response = await fetch(`${nodeUrl}/transactions`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payload: signedTransactionPayload })
})
