MetaMask Snaps es la hoja de ruta para convertir a MetaMask en la wallet más extensible del mundo. Como desarrollador, puedes incorporar tus funcionalidades y APIs a MetaMask de formas completamente nuevas. Los desarrolladores de Web3 son el núcleo de este crecimiento, y esta serie tiene como objetivo destacar los innovadores MetaMask Snaps que se están construyendo hoy en día.
Smart Account Sessions
Repositorio del Snap: https://github.com/livingrockrises/snap-auto-approvals
¿Por qué lo construiste?
Para crear una experiencia de usuario fluida en dapps de gaming, ofreciéndoles una forma de realizar aprobaciones automáticas de manera segura.
¿Puedes explicarnos la implementación técnica?
La App
Nuestro Snap está compuesto por dos partes. La primera es un sitio web con el que los usuarios interactúan. La segunda es el Snap en sí. Estos dos elementos funcionan de manera similar a una arquitectura cliente-servidor, donde el Snap actúa como servidor y el sitio web como cliente.
El sitio web tiene el siguiente flujo de usuario:
Conecta tu EOA e instala el Snap de Smart Account Session.
Activa la Smart Account sobre la dirección de MetaMask. La EOA de MetaMask será el controlador de esta Smart Account.
Activa el Módulo de Sesión en tu Smart Account. Los módulos habilitan lógica adicional de control de acceso para tu cuenta Smart Safe. En esencia, cada Smart Account está controlada por dos medios: por el propietario de la cuenta MetaMask mediante sus claves de firma, y por módulos opcionales que tienen su propia lógica de acceso personalizada.
Crea una sesión.
Esto creará claves de sesión temporales en tu smart account, autorizadas para realizar transacciones en tu wallet a través del módulo. La sesión puede tener parámetros como startTime, endTime y permisos para acciones personalizadas en los contratos de la Dapp.
Envía transacciones aprobadas automáticamente usando la clave de sesión anterior, sin que aparezca el pop-up de MetaMask para gas o firmas.
La API de MetaMask
MetaMask proporciona llamadas a la API, que pueden ser utilizadas por los MetaMask Snaps si el usuario lo permite.
En este caso, hemos aprovechado las siguientes:
snap_manageState - que nos permite almacenar datos cifrados dentro de MetaMask. Por ejemplo, la usamos para guardar el par de claves de sesión creado.
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 - que nos permite almacenar datos cifrados dentro de MetaMask. Por ejemplo, la usamos para guardar las cuentas creadas.
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'));
}
});
El Snap gestionará las solicitudes JSON-RPC entrantes, enviadas a través de wallet_invokeSnap desde el sitio.
Para el flujo de la app anterior, hemos creado métodos de solicitud personalizados como connect, enable_session_module, create_session e interact. A continuación se muestra un ejemplo, y el código está disponible aquí.
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;
};
Módulo de Clave de Sesión
Desarrollamos un módulo al estilo de Gnosis Safe para ampliar la funcionalidad de la wallet de contrato inteligente mediante control de acceso con claves de sesión.
El código se puede encontrar aquí para los contratos del módulo y de la wallet.
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;
}
Cuando se crea una sesión invocando el snap y, a su vez, invocando la smart account, el siguiente método es llamado en el módulo de clave de sesión desde la Smart Account a través de un relayer.
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
Una vez creada la sesión, un relayer puede invocar una transacción en el módulo de clave de sesión con una clave de sesión y firma válidas.
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
El SDK
El SDK de Biconomy es la suite Web3 definitiva para que los desarrolladores aprovechen las smart accounts y simplifiquen los recorridos de usuario, transformando flujos complejos de múltiples pasos en una experiencia de un solo clic.
Cada usuario obtiene una wallet de contrato inteligente, en lugar de un simple par de claves criptográficas, y las dApps pueden personalizar todo tipo de interacciones fluidas mediante paquetes de transacciones a través de esta wallet SC para el usuario.
Hemos vinculado la siguiente función con la llamada RPC 'connect' al invocar el snap.
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;
}
¿Cuáles son los próximos pasos si implementaras esto?
Estamos muy entusiasmados con la función de keyrings y la posibilidad de mostrar información de smart accounts en lugar de EOAs en la interfaz de MetaMask.
Publicaremos el SDK de Biconomy compatible con MetaMask Snaps para que los desarrolladores lo utilicen.
Añadiremos un módulo de recuperación social y transacciones agrupadas cross-chain en un solo clic usando Smart Accounts, además de mostrar notificaciones en cuanto se ejecute la transacción en la cadena de destino.
¿Puedes contarnos un poco sobre ti y tu equipo?
Sachin es el CTO y cofundador de Biconomy. Con formación en ciencias de la computación, cuenta con 6 años de experiencia en web2 y 5 años en web3. Le encanta adoptar un enfoque estructurado para la resolución de problemas y disfruta involucrarse directamente para implementar y probar sus ideas rápidamente.
Chirag es ingeniero blockchain en Biconomy. Le apasiona la programación y aprender todo lo relacionado con web3 a través de la investigación y el desarrollo.
¿Cuándo conociste MetaMask Snaps por primera vez y cómo fue tu experiencia?
Conocimos MetaMask Snaps poco antes del hackathon ETHBogota. Quedamos muy impresionados por la documentación y las capacidades que ofrecen los métodos de snap.
¿Qué diferencia a MetaMask Snaps de otras wallets?
La capacidad de ampliar las funcionalidades de la wallet MetaMask sin depender del equipo central de MetaMask, lo que permite un crecimiento más ágil. Los desarrolladores pueden acceder a las funcionalidades existentes de MetaMask, como la interfaz de llamadas JSON RPC y el almacenamiento.
¿Cómo es para ti y tu equipo la experiencia de construir MetaMask Snaps con MetaMask?
El desarrollo básico fue muy intuitivo, pero dedicamos bastante tiempo a entender los requisitos de permisos para ciertos métodos. La posibilidad de crear elementos de UI personalizados, por ejemplo para mostrar el saldo de wallets de contratos inteligentes al igual que las EOAs, resulta complicada por el momento.
¿Qué significa MetaMask Snaps para ti?
Es un arma secreta que nos permite dar soporte a las wallets de contratos inteligentes ERC4337 dentro de MetaMask, sin necesidad de construir ni de que las dapps integren un widget personalizado en su frontend.
¿Qué oportunidades ves en MetaMask Snaps y las posibilidades que abre para el espacio Web3?
Los MetaMask Snaps personalizados para cada dapp pueden ofrecer una mejor experiencia de usuario y habilitar interacciones multichain. Además, permiten introducir abstracción de comisiones, abstracción de cuentas y capacidades de seguridad de wallets sobre la base de usuarios Web3 existente.
¿Algún consejo que quieras compartir con los desarrolladores interesados en probar MetaMask Snaps?
Consulta las discusiones en GitHub y el Discord, que pueden ayudarte a superar muchos bloqueos durante el desarrollo. Cualquier persona familiarizada con JavaScript y las llamadas JSON RPC puede construir. Los snap-monorepos y los MetaMask Snaps de ejemplo son un buen punto de partida para acelerar tu desarrollo.
Si necesitas almacenar algo, solo se puede guardar un único objeto, por lo que puedes anidar múltiples pares clave-valor dentro de ese único objeto. Cuando necesites devolver respuestas desde métodos de snap invocados de forma personalizada, asegúrate de que retornen un objeto JSON plano.
Construyendo con MetaMask Snaps
Para comenzar con MetaMask Snaps:
Consulta la documentación para desarrolladores
Instala MetaMask Flask
Revisa una guía de MetaMask Snaps
Mantente conectado con nosotros en Twitter, discusiones de GitHub y Discord
¡Estáte atento a nuestro equipo en el próximo hackathon cerca de ti! ¡Feliz BUIDLing! ⚒️
Aviso legal: Los MetaMask Snaps son desarrollados en general por terceros distintos a Consensys Software. El uso de MetaMask Snaps desarrollados por terceros se realiza a tu propia discreción y riesgo, y con el acuerdo de que serás el único responsable de cualquier pérdida o daño que resulte de dichas actividades. Consensys no ofrece ninguna garantía expresa ni implícita, ya sea oral o escrita, con respecto a los MetaMask Snaps desarrollados por terceros, y declina toda responsabilidad por los MetaMask Snaps desarrollados por terceros. El uso de software relacionado con blockchain conlleva riesgos, que asumes en su totalidad al utilizar MetaMask Snaps.