MetaMask Snapsは、MetaMaskを世界で最も拡張性の高いウォレットにするためのロードマップです。開発者として、まったく新しい方法でMetaMaskに機能やAPIを追加することができます。Web3開発者はこの成長の中核を担っており、本シリーズでは現在開発中の革新的なMetaMask Snapsを紹介することを目的としています。
AA Snap
Snap リポジトリ: https://github.com/a42io/AAsnap
なぜ開発したのですか?
AA Snapは、すべての開発者とユーザーにAccount Abstraction(AA)を民主化するために開発されました。私たちはAAが将来的に広く普及すると考えています。しかし現状では、開発者がdappsにAAを統合したり、ユーザーが利用したりするには手間がかかります。
開発者の観点からは、EOAに加えてAAをサポートする追加コードを記述する必要があります。
ユーザーの観点からは、MetaMaskのような使い慣れたウォレットを使用できず、AAをサポートする別のウォレットをインストールする必要があり、UXが低下します。
そこで、MetaMask Snapsを活用することで、AAの統合と利用を簡単にしたいと考えました。
技術的な実装について説明していただけますか?
AA Snapは、サンプルフロントエンド、MetaMask snap、および一時的なサーバーの3つのコンポーネントで構成されています。このSnapにより、開発者とユーザーはAAウォレット(EIP-4337をサポートするコントラクトウォレット)を非常に簡単に利用できます。完全な実装についてはリポジトリをご覧ください。
サンプルフロントエンド
サンプルフロントエンドは、MetaMaskが提供するテンプレートをベースにしています。これにより、開発者がAA Snapを使ってdappsにAAを簡単に統合できることが示されています。
例えば、AAウォレットの残高は以下のシンプルなコードで取得できます。
const balance = (await window.ethereum.request({
method: 'wallet_invokeSnap',
params: [
defaultSnapOrigin,
{
method: 'balance',
},
],
})) as string;
AAウォレットからトランザクションを送信するには、受取人のアドレスと金額を渡すだけで、以下のコードを記述できます。
await window.ethereum.request({
method: 'wallet_invokeSnap',
params: [
defaultSnapOrigin,
{
method: 'transfer',
params: {
to,
value,
},
},
],
});
ユーザーの観点からAAウォレットはどれほど使いやすいでしょうか?こちらでお試しください: https://AAsn.app
Snap
Snapは以下のコードでAAのインスタンスを取得します。AAの実装には、@account-abstraction/sdk npmパッケージを使用しました。
AAウォレットのアドレスはユーザーのEOAから決定論的に導出できるため、ユーザーの入力は不要です。
export const getAbstractAccount = async (): Promise<SimpleAccountAPI> => {
const provider = new ethers.providers.Web3Provider(wallet as any);
await provider.send('eth_requestAccounts', []);
const owner = provider.getSigner();
const aa = new SimpleAccountAPI({
provider,
entryPointAddress,
owner,
factoryAddress,
});
return aa;
};
AAウォレットからトランザクションを送信するには、3つのステップがあります:
SnapはMetaMask内でSnapのsnap_confirmメソッドを使用して確認画面を表示します。このプロセスは必須ではありませんが、ユーザーが署名する内容の詳細を確認できないため、UX向上のために必要です。
コードはAAウォレットのユーザーオペレーションを作成し、そのハッシュへの署名をリクエストします。このプロセスは、EOAからトランザクションを作成して署名するプロセスとほぼ同じです。
署名済みのユーザーオペレーションをサーバー経由でバンドラーに送信します。
export const transfer = async (target: string, ethValue: string) => {
const value = ethers.utils.parseEther(ethValue);
const aa = await getAbstractAccount();
const address = await aa.getAccountAddress();
const result = await wallet.request({
method: 'snap_confirm',
params: [{
prompt: 'Transfer',
description: 'Transfer from your Abstraction Account',
textAreaContent: `from: ${address}\ntarget: ${target}\nvalue: ${ethValue}`,
}],
});
if (!result) {
return;
}
const op = await aa.createSignedUserOp({
target,
value,
data: '0x',
maxFeePerGas,
maxPriorityFeePerGas,
});
const printedOp = await printOp(op);
const body = JSON.stringify({
op: printedOp,
});
const response = await fetch(SERVER_END_POINT {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body,
});
};
一時的なサーバー
ハッカソン中に、Snap内でsendUserOpToBundlerメソッドを呼び出す際にエラーが発生しました。問題を深く調査する時間がなかったため、一時的にサーバーを作成して問題を解決することにしました。この一時的なサーバーは、署名済みのユーザーオペレーションを受け取り、バンドラーに渡すだけです。
このエラーはおそらく依存関係に起因するもので、MetaMask Snapsの実行環境にはいくつかの制限があります。以下のドキュメントに従うことで、一時的なサーバーを削除できると考えています: 依存関係のパッチ適用
app.post('/aa', async (req, res) => {
const provider = new ethers.providers.JsonRpcProvider(
process.env.RPC_ENDPOINT,
);
const client = await getHttpRpcClient(
provider,
process.env.BUNDLER_URL as string,
process.env.ENTRY_POINT_ADDRESS as string,
);
try {
const uoHash = await client.sendUserOpToBundler(JSON.parse(req.body.op));
return res.json({
uoHash,
});
} catch (e) {
console.log(e);
return res.status(400).send();
}
});
実装する場合の次のステップは何ですか?
不要なサーバーサイドのコードを削除し、Snap単独で動作させたいと考えています。また、現状では私たちのようなMetaMask Snapsの開発者が署名対象のトランザクションハッシュを悪意のあるものに置き換えることが可能なため、それを防ぐ仕組みの導入または提案を検討したいと思います。
あなたとチームについて少し教えていただけますか?
私たちのチームは、日本とシンガポールで小さなスタートアップ「a42」を運営しています。a42は、NFTやENSを含むスマートコントラクトによる認証を可能にするWeb3スマートロック「wΞlock」を開発しています: https://a42.io/w3lock 2022年には、MetaMask Snapsなどの新技術を学ぶために複数のハッカソンに参加しました。
守屋英義(piyo.eth):英義は2017年からEthereumベースのアプリの実験と開発を行っています。2017年にはコラボレーティブNFTアートプロジェクト「Pixereum」を開発しました。Googleでテクニカルプロダクトスペシャリストとして勤務した後、2019年に「a42」を設立しました。a42では、現実世界で機能するdappsを開発しています。現在は、2021年に開発したPoC(概念実証)をもとに、ENS/NFTで開錠できるWeb3スマートロック「wΞlock」を開発中です: https://twitter.com/hm0429/status/1465241679800111107
橘裕之(tachibana.eth):裕之はa42の共同創業者兼エンジニアです。IoTデバイス向けブロックチェーン認証モジュール「w3a.io」の開発プロジェクトを主導し、Ethereum Foundationからグラントを受けました。2022年を通じてETHGlobalハッカソンで複数の賞を受賞しています。現在はWeb3スマートロック製品向けのzkpプライバシーソリューションを開発中です。
守屋勇介(yskmyskm.eth):勇介はa42のデザイナーです。様々な映像制作でCG/VFXアーティストとして活動し、グローバルブランドから小規模なミュージックビデオまで幅広く携わってきました。映像業界で12年の経験を持ち、コンピューターグラフィックスを使った抽象表現を専門としています。また、撮影監督やドキュメンタリー監督としても活動しています。
MetaMask SnapsとWeb3空間に対してどのような可能性を感じていますか?
MetaMask Snapsは、複雑なWeb3技術を開発者とユーザーの双方にとって使いやすくし、従来のWebアプリケーションがWeb3と統合するうえで大きな助けになると確信しています。MetaMask Snapsの開発は、最初のモバイルアプリストアが登場したときと同じくらいの興奮を感じています。ぜひ試してみて、あなたのアイデアを実現してください!
MetaMask Snapsに挑戦したい開発者へのアドバイスはありますか?
まずMetaMask Snapsのテンプレート(https://github.com/MetaMask/template-snap-monorepo)から始めて、それを修正することをお勧めします。
ヒント:インジェクトされたethereumオブジェクトの取得方法に迷うかもしれませんが、walletオブジェクトがそれに相当します。
MetaMask Snapsで開発を始めよう
MetaMask Snapsを始めるには:
開発者ドキュメントをご確認ください
MetaMask Flaskをインストールしてください
MetaMask Snapsガイドをご覧ください
Twitter、GitHubディスカッション、Discordで私たちとつながり続けてください
次回のハッカソンでお近くの会場でお会いしましょう!Happy BUIDLing ⚒️
免責事項:MetaMask Snapsは一般的に、Consensys Software以外のサードパーティによって開発されています。サードパーティが開発したMetaMask Snapsの使用は、お客様自身の判断とリスクのもとで行われ、そのような活動から生じる損失や損害についてはお客様が単独で責任を負うことに同意したうえで使用するものとします。Consensysはサードパーティが開発したMetaMask Snapsについて、口頭または書面による明示的または黙示的な保証を一切行わず、サードパーティが開発したSnapsに関するすべての責任を否認します。ブロックチェーン関連ソフトウェアの使用にはリスクが伴い、MetaMask Snapsを使用する際にはそのリスクをすべて自己負担するものとします。