MetaMask Snaps 是讓 MetaMask 成為全球最具擴展性錢包的發展藍圖。身為開發者,您可以透過全新方式將您的功能與 API 帶入 MetaMask。Web3 開發者是這項成長的核心,本系列旨在展示當今正在建構的創新 MetaMask Snaps。
智能帳戶工作階段
Snap 程式庫:https://github.com/livingrockrises/snap-auto-approvals
您為什麼要建構它?
為了替遊戲 dapp 打造流暢的使用者體驗,以安全的方式提供自動核准功能。
能否帶我們了解技術實作的細節?
應用程式
我們的 Snap 由兩個部分組成。第一部分是使用者互動的網站,第二部分是實際的 Snap。這兩個元素的運作方式類似於主從式架構,其中 Snap 是伺服器,網站是客戶端。
網站的使用者流程如下:
連接您的 EOA 並安裝智能帳戶工作階段 Snap。
在 MetaMask 地址之上啟用智能帳戶。MetaMask EOA 將成為此智能帳戶的控制者。
在您的智能帳戶上啟用工作階段模組。模組可為您的 Smart Safe 帳戶啟用額外的存取控制邏輯。基本上,每個智能帳戶由兩種方式控制:一是 MetaMask 帳戶擁有者使用其簽名金鑰,二是具有自訂存取邏輯的選用模組。
建立工作階段。
這將在您的智能帳戶上建立臨時工作階段金鑰,授權透過模組在您的錢包上執行交易。工作階段可設定參數,例如開始時間、結束時間,以及針對 Dapp 合約自訂操作的權限。
使用上述工作階段金鑰發送自動核准的交易,無需 MetaMask 彈出視窗確認 gas 費用或簽名。
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 可透過此智能合約錢包,使用交易捆綁包為使用者自訂各種流暢的互動。
我們已將以下函式與透過呼叫 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 的技術長暨共同創辦人。擁有電腦科學背景,他具備 6 年的 Web2 和 5 年的 Web3 經驗。他熱愛以結構化的方式解決問題,並喜歡親身實踐,快速實現並測試自己的想法。
Chirag 是 Biconomy 的區塊鏈工程師。他熱愛程式設計,並透過研究與開發學習所有 Web3 相關知識。
您是什麼時候第一次接觸到 MetaMask Snaps 的?體驗如何?
我們在 ETHBogota 黑客松前不久得知了 MetaMask Snaps。我們對其文件說明及透過 Snap 方法所展現的功能印象深刻。
MetaMask Snaps 與其他錢包有何不同?
它能夠在不依賴 MetaMask 核心團隊的情況下擴展 MetaMask 錢包的功能,並實現更快速的成長。開發者可以存取 MetaMask 的現有功能,例如 JSON RPC 呼叫介面和儲存空間。
請告訴我們您和您的團隊使用 MetaMask 建構 MetaMask Snaps 的體驗?
基礎開發非常直觀,但我們花了很多時間釐清特定方法的權限需求。目前,建構自訂 UI 元素(例如像顯示 EOA 一樣顯示智能合約錢包餘額)仍有一定難度。
MetaMask Snaps 對您意味著什麼?
它是一項秘密武器,讓我們能夠在 MetaMask 中支援 ERC4337 智能合約錢包,而無需建構或要求 dapp 在其前端整合自訂小工具。
您認為 MetaMask Snaps 為 Web3 領域帶來了哪些機遇與可能性?
針對特定 dapp 客製化的 MetaMask Snaps 可提供更好的使用者體驗,並實現多鏈互動。在現有 Web3 使用者基礎上引入費用抽象、帳戶抽象和錢包安全功能。
對於有意嘗試 MetaMask Snaps 的開發者,您有什麼建議?
查看 GitHub 討論區和 Discord,這些資源可以幫助解決開發過程中的許多障礙。任何熟悉 JavaScript 和 JSON RPC 呼叫的人都可以進行建構。snap-monorepos 和範例 MetaMask Snaps 是加速開發的好起點。
如果您需要儲存資料,只能儲存單一物件,因此您可以在一個物件中嵌套多個鍵值。當您需要從自訂呼叫的 Snap 方法返回回應時,請確保它返回純 JSON 物件。
使用 MetaMask Snaps 進行建構
開始使用 MetaMask Snaps:
查看開發者文件
安裝 MetaMask Flask
查看 MetaMask Snaps 指南
在 Twitter、GitHub 討論區和 Discord 上與我們保持聯繫
請留意我們的團隊將出現在您附近的下一場黑客松!祝 BUIDL 愉快 ⚒️
免責聲明:MetaMask Snaps 通常由 Consensys Software 以外的第三方開發。使用第三方開發的 MetaMask Snaps 須由您自行決定並承擔風險,且您同意對因此類活動造成的任何損失或損害負全部責任。Consensys 對第三方開發的 MetaMask Snaps 不作任何明示或暗示的保證,並對第三方開發的 MetaMask Snaps 免除一切責任。使用區塊鏈相關軟體存在風險,使用 MetaMask Snaps 即表示您完全承擔這些風險。