MetaMask Snapsは、MetaMaskを世界で最も拡張性の高いウォレットにするためのロードマップです。開発者として、まったく新しい方法でMetaMaskに機能やAPIを追加することができます。Web3開発者はこの成長の中核を担っており、本シリーズでは現在開発中の革新的なMetaMask Snapsを紹介することを目的としています。
スマートアカウントセッション
Snap リポジトリ: https://github.com/livingrockrises/snap-auto-approvals
なぜ開発したのですか?
ゲーミングDappにシームレスなユーザー体験を提供するため、安全な方法で自動承認を実現できる仕組みを作るために開発しました。
技術的な実装について説明していただけますか?
アプリ
このSnapは2つのパートで構成されています。1つ目はユーザーが操作するウェブサイト、2つ目は実際のSnapです。この2つの要素はクライアント・サーバーアーキテクチャに似た形で機能しており、Snapがサーバー、ウェブサイトがクライアントの役割を担います。
ウェブサイトのユーザーフローは以下の通りです:
EOAを接続し、Smart Account Session Snapをインストールします。
MetaMaskアドレスの上にスマートアカウントを有効化します。MetaMask EOAがこのスマートアカウントのコントローラーになります。
スマートアカウントでセッションモジュールを有効化します。モジュールはSmart Safeアカウントに追加のアクセス制御ロジックを提供します。基本的に、すべてのスマートアカウントは2つの手段によって制御されます。MetaMaskアカウントオーナーが署名鍵を使用する方法と、独自のカスタムアクセスロジックを持つオプションモジュールを使用する方法です。
セッションを作成します。
これにより、モジュールを通じてウォレット上でのトランザクションが承認された一時的なセッションキーがスマートアカウントに作成されます。セッションにはstartTime、endTime、DappコントラクトのカスタムアクションのPermissionsなどのパラメーターを設定できます。
上記のセッションキーを使用して、ガスや署名のためのMetaMaskポップアップなしに自動承認されたトランザクションを送信します。
MetaMask API
MetaMaskはAPIコールを提供しており、ユーザーが許可した場合にMetaMask Snapsで使用できます。
今回は以下を活用しました:
snap_manageState - MetaMask内に暗号化されたデータを保存できます。例えば、作成されたセッションキーペアの保存に使用しています。
export type SessionKeyStorage = {
owner: string;
sessionKey: string;
pk: string;
};
export const storeSessionInfo = async (data: SessionKeyStorage) => {
await wallet.request({
method: 'snap_manageState',
params: ['update', data],
});
};
export const clearSessionInfo = async () => {
const result = await wallet.request({
method: 'snap_manageState',
params: ['clear'],
});
return result;
};
export const getSessionInfo = async () => {
const result = await wallet.request({
method: 'snap_manageState',
params: ['get'],
});
return result;
};
snap_confirm - MetaMask内に暗号化されたデータを保存できます。例えば、作成されたアカウントの保存に使用しています。
export const promptUser = async (
prompt: string,
description: string,
content: string,
): Promise<boolean> => {
const response: any = await wallet.request({
method: 'snap_confirm',
params: [
{
prompt,
description,
textAreaContent: content,
},
],
});
console.log('Prompt user response', response);
if (response) {
return response;
}
return false;
};
promptUser(getMessage(origin),
'Do you want to use Smart Account',
`Your Smart Account Address is ${_smartAccount.address}`,
).then((approval) => {
if (approval) {
console.log('Sending smart acccount response ', _smartAccount);
resolve({
address: _smartAccount.address,
owner: _smartAccount.owner,
});
} else {
reject(new Error('EOA user'));
}
});
Snapはサイトからwallet_invokeSnapを通じて送信される受信JSON-RPCリクエストを処理します。
上記のアプリフローのために、connect、enable_session_module、create_session、interactなどのカスタムリクエストメソッドを作成しました。一例を以下に示します。コードはこちらでご確認いただけます。
export const useSmartAccount = async () => {
console.log('invoke Snap...');
const smartAccountResponse: any = await window.ethereum.request({
method: 'wallet_invokeSnap',
params: [
defaultSnapOrigin,
{
method: 'connect',
params: [],
},
],
});
return smartAccountResponse;
};
セッションキーモジュール
セッションキーによるアクセス制御を使用して、スマートコントラクトウォレットの機能を拡張するGnosis safeスタイルのモジュールを作成しました。
モジュールおよびウォレットコントラクトのコードはこちらでご確認いただけます。
struct Session {
address smartAccount;
address sessionKey;
uint256 startTimestamp;
uint256 nonce;
uint256 endTimestamp;
bool enable;
PermissionStorage permission;
}
struct PermissionStorage {
address[] whitelistDestinations;
mapping(address => bool) whitelistDestinationMap;
mapping(address => bytes4[]) whitelistMethods;
mapping(address => mapping(bytes4 => bool)) whitelistMethodsMap;
mapping(address => TokenApproval) tokenApprovals;
}
Snapを呼び出し、さらにスマートアカウントを呼び出すことでセッションが作成されると、リレイヤーを経由してスマートアカウントからセッションキーモジュール上で以下のメソッドが呼び出されます。
function createSession(
address sessionKey,
PermissionParam[] calldata permissions,
SessionParam calldata sessionParam
) external {
require(
!sessionMap[sessionKey].enable,
"Session for key is already enabled"
);
Session storage _session = sessionMap[sessionKey];
...
txHash: https://goerli.etherscan.io/tx/0x8b45f4cb0a7527bb7c44f6923eb9bb391faa656e212829ce0fd9c733ca71352b
セッションが作成されると、リレイヤーは有効なセッションキーと署名を使用してセッションキーモジュール上のトランザクションを呼び出すことができます。
function executeTransaction(
address _sessionKey,
address payable _to,
uint256 _value,
bytes calldata _data,
bytes calldata signature
) external returns (bool success) {
Session storage session = sessionMap[_sessionKey];
require(session.enable, "Session is not active");
require(
session.startTimestamp <= block.timestamp,
"Session has not yet started"
);
require(session.endTimestamp >= block.timestamp, "Session has expired");
...
txHash: https://goerli.etherscan.io/tx/0xf6d40bf9c74cff266f8bc26dabcf7a44ca1c0e85387f297f43fa5cb89bbea1a0
SDK
Biconomy SDKは、開発者がスマートアカウントを活用し、複雑なマルチステップのユーザージャーニーをシンプルなワンクリック体験に簡略化するための究極のWeb3スイートです。
各ユーザーは単純な暗号鍵ペアではなくスマートコントラクトウォレットを取得し、DAppはこのSCウォレットを通じたトランザクションバンドルを使用して、ユーザーのためにあらゆる種類のシームレスなインタラクションをカスタマイズできます。
以下の関数をSnapを呼び出すことで「connect」RPCコールに紐付けました。
import SmartAccount from '@biconomy-sdk/smart-account';
async function getsmartAccount(): Promise<SmartAccount> {
smartAccount = new SmartAccount(wallet, {
activeNetworkId: Number(wallet.chainId),
});
smartAccount = await smartAccount.init();
console.log('initialized');
console.log(smartAccount);
return smartAccount;
}
実装する場合の次のステップは何ですか?
keyrings機能と、MetaMask UIでEOAの代わりにスマートアカウント情報を表示する機能を楽しみにしています。
開発者が使用できるMetaMask Snaps対応のBiconomy SDKを公開する予定です。
ソーシャルリカバリーモジュールの追加、スマートアカウントを使用したワンクリッククロスチェーンバッチトランザクションの実装、そして送信先チェーンのトランザクションが実行され次第通知を表示する機能を追加します。
ご自身とチームについて少し教えていただけますか?
SachinはBiconomyのCTO兼共同創業者です。コンピューターサイエンスのバックグラウンドを持ち、Web2で6年、Web3で5年の経験があります。問題解決に対して体系的なアプローチを取ることを好み、アイデアを素早く実装してテストするためにハンズオンで取り組むことを大切にしています。
ChiragはBiconomyのブロックチェーンエンジニアです。プログラミングを愛し、研究開発を通じてWeb3のあらゆることを学ぶことに情熱を持っています。
MetaMask Snapsを最初に知ったのはいつで、どのような体験でしたか?
ETHBogotaハッカソンの少し前にMetaMask Snapsについて知りました。ドキュメントの充実度とSnapメソッドを通じた機能の豊富さに非常に感銘を受けました。
MetaMask Snapsが他のウォレットと異なる点は何ですか?
MetaMaskのコアチームに依存することなくMetaMaskウォレットの機能を拡張し、より速い成長を実現できる点です。開発者はJSON RPCコールインターフェースやストレージなど、MetaMaskの既存機能にアクセスできます。
MetaMaskでMetaMask Snapsを開発することはどのような体験ですか?
基本的な開発は非常に直感的でしたが、特定のメソッドに必要なパーミッション要件の把握に多くの時間を費やしました。例えば、EOAと同様にスマートコントラクトウォレットの残高を表示するためのカスタムUI要素を構築する機能は、現時点では難しい状況です。
MetaMask Snapsはあなたにとってどのような意味を持ちますか?
カスタムウィジェットをフロントエンドに構築したり、DAppに統合させたりすることなく、MetaMask内でERC4337スマートコントラクトウォレットをサポートできる秘密兵器です。
MetaMask SnapsがWeb3空間に解き放つ可能性についてどのような機会を見出していますか?
DApp固有のカスタマイズされたMetaMask Snapsは、より優れたユーザー体験を提供し、マルチチェーンインタラクションを可能にします。既存のWeb3ユーザーベースの上に、フィー抽象化、アカウント抽象化、ウォレットセキュリティ機能を導入することができます。
MetaMask Snapsを試したい開発者へのアドバイスはありますか?
GitHubディスカッションとDiscordをチェックしてください。開発中の多くの障壁を解消するのに役立ちます。JavaScriptとJSON RPCコールに慣れている方であれば誰でも開発できます。snap-monoreposとMetaMask Snapsのサンプルは開発を加速させるのに最適な出発点です。
データを保存する場合、保存できるのは単一のオブジェクトのみなので、1つのオブジェクト内に複数のキーバリューをネストすることができます。カスタム呼び出しSnapメソッドからレスポンスを返す必要がある場合は、プレーンなJSONオブジェクトを返すようにしてください。
MetaMask Snapsで開発を始める
MetaMask Snapsを始めるには:
開発者ドキュメントをご確認ください
MetaMask Flaskをインストールしてください
MetaMask Snapsガイドをご覧ください
Twitter、GitHubディスカッション、Discordでつながり続けましょう
お近くで開催される次のハッカソンでも私たちのチームにご注目ください!Happy BUIDLing ⚒️
免責事項:MetaMask Snapsは一般的にConsensys Software以外のサードパーティによって開発されています。サードパーティが開発したMetaMask Snapsの使用はご自身の判断とリスクのもとで行われ、そのような活動から生じる損失や損害についてはお客様が単独で責任を負うことに同意したものとみなされます。Consensysはサードパーティが開発したMetaMask Snapsについて、口頭または書面による明示的または黙示的な保証を行わず、サードパーティが開発したMetaMask Snapsに関するすべての責任を否認します。ブロックチェーン関連ソフトウェアの使用にはリスクが伴い、MetaMask Snapsを使用する際にはそのリスクをすべて自己負担するものとします。