Pular para o conteúdo

CoinChoice Snap: Abasteça Gas com Qualquer Moeda

Vencedor do Hackathon ETHDenver

11 min de leitura
CoinChoice Snap: Abasteça Gas com Qualquer Moeda

MetaMask Snaps é o roteiro para tornar a MetaMask a carteira mais extensível do mundo. Como desenvolvedor, você pode trazer seus recursos e APIs para a MetaMask de formas totalmente novas. Os desenvolvedores Web3 são o núcleo desse crescimento, e esta série tem como objetivo destacar os MetaMask Snaps inovadores que estão sendo criados hoje.

CoinChoice Snap

Snap Repo: https://github.com/coinchoice/coinchoice/

Por que você o criou?

O CoinChoice foi desenvolvido a partir de um problema pequeno e tedioso, mas amplamente comum: um usuário Web3 pode ter uma carteira com tokens de valor, mas sem a moeda de gas para realizar transações.

Esse problema é ainda mais evidente para usuários com liquidez fracionada. Um usuário que gerencia múltiplas carteiras e aproveita oportunidades em diferentes ecossistemas de blockchain acaba dividindo seus tokens de gas entre cada uma de suas carteiras, reservando capital que, de outra forma, seria destinado a investimentos, apenas para viabilizar seus ativos digitais e transações. Além do gerenciamento de gas, tokens transferidos para uma rede onde o gas não está disponível exigem que o usuário obtenha gas antes de realizar qualquer ação. Normalmente, isso envolve o acesso a uma Exchange Centralizada para obter e sacar gas — sujeitando o usuário às taxas de saque da CEX.

No fundo, a experiência é falha. Não deveria haver dependência de exchanges centralizadas para que os usuários acessem a Web3. Os usuários não deveriam precisar se preocupar com o gerenciamento de gas e, em vez disso, deveriam poder simplesmente interagir com sistemas descentralizados. Isso não significa que o gas não deva ser necessário. O gas cumpre um propósito fantástico ao recompensar os operadores de uma rede, além de prevenir spam/ddos. O gas simplesmente deveria ser mais flexível. Se um dApp ou desenvolvedor de jogos tiver um token nativo, esse token deveria ser suficiente como moeda para pagar o gas.

Com essa filosofia em mente, o CoinChoice foi desenvolvido.

O CoinChoice reside no navegador do usuário, complementando cada transação com a capacidade de gerenciar o gas na moeda que o usuário desejar. Se o usuário preferir manter USDC em vez de ETH, o gas pode ser pago em USDC.

O MetaMask Snap do CoinChoice complementa ainda mais a experiência. Diretamente na Extensão de Navegador da MetaMask, os usuários podem recarregar seu ETH em troca da moeda de gas escolhida. Isso transforma a MetaMask em uma solução que substitui a visita a uma Exchange Centralizada, consolidando e simplificando a experiência Web3, e permitindo que novos usuários Web3 se familiarizem com um subconjunto de sistemas sem se sentirem sobrecarregados pela crescente abundância de serviços e plataformas.

Nos explique a implementação técnica?

O CoinChoice é uma Extensão de Navegador para MetaMask que oferece a você a escolha de quais moedas são usadas para pagar o gas.

Pacotes

  • backend: Um servidor web NestJS responsável por — simular transações contra a API Tenderly e a API 0x Quote para gerar estimativas de gas na moeda escolhida

  • receber e distribuir mensagens entre o MetaMask Snap e a Extensão de Navegador do cliente

  • receber meta-tx para encaminhar aos contratos relayer

  • browser-extension: Uma Extensão de Navegador desenvolvida com o Plasmo Framework — intercepta requisições RPC para a MetaMask a fim de injetar swaps para ETH para financiamento de gas

  • oferece um popup onde a Moeda de Gas pode ser selecionada

  • oferece um popup para gerenciamento de Token desenvolvido com o Cypher Onboarding SDK

  • todos os dados são enviados ao serviço de backend onde as Interações e Simulações com a Blockchain são gerenciadas

  • contracts: Smart Contracts que viabilizam o relay de meta-transações para facilitar swaps no Protocolo 0x.

  • frpc: Um pacote para aproveitar o fRPC Gateway da Rede Fluence

  • meta-mask: Um pacote que contém um Site React.js e o MetaMask Snap associado. — O Snap é responsável por oferecer Swaps de ETH diretamente na interface da MetaMask, exibindo a mensagem "Need ETH?"

  • O Snap funciona fazendo uma requisição ao backend para que uma mensagem seja encaminhada à extensão de navegador do cliente, possibilitando uma experiência em que o MetaMask Snap pode iniciar a Extensão de Navegador

  • O Site associado é usado para habilitar a Instalação do MetaMask Snap

Configuração Técnica

O CoinChoice é uma extensão de navegador que complementa as transações com a oportunidade de recarregar gas com uma moeda escolhida.

A extensão de navegador é projetada para solicitar ao usuário que pague o gas na moeda selecionada antes de cada transação.

Se o usuário aceitar, uma meta-transação é capturada para converter uma quantidade estimada do token escolhido em ETH.

Essa meta-transação é encaminhada ao serviço de backend, que a repassa ao Smart Contract relayer, onde é executada.

Após a liquidação da meta-transação, a transação original do usuário é solicitada e acessível graças ao depósito da quantidade adequada de gas.

O MetaMask Snap é projetado para encaminhar uma transação que, de outra forma, ficaria isolada dentro da extensão MetaMask para a Extensão CoinChoice. Ele faz isso:

  1. enviando uma requisição com os detalhes da transação ao serviço de backend

  2. o backend então encaminha os dados da transação para a extensão de navegador via conexão websocket

  3. assim que a extensão de navegador recebe essa mensagem websocket, ela inicia seu fluxo de recarga de uma quantidade automaticamente estimada de gas em troca de uma moeda selecionada.

Backend como Message Bus

O CoinChoice adotou a abordagem de usar um backend como message bus entre os dois componentes frontend devido à natureza isolada (sandboxed) do MetaMask Snap.

O isolamento do código do Snap impede a comunicação com componentes frontend que residem em contextos fora da extensão MetaMask.

No entanto, os Snaps podem facilitar requisições server-side e, portanto, um serviço de backend capaz de gerenciar sessões de usuário pode ser usado para passar mensagens entre os contextos frontend.

Um exemplo disso pode ser demonstrado por meio do nosso código-fonte.

Dentro do MetaMask Snap, enviamos uma requisição ao servidor.

Veja https://github.com/Coinchoice/coinchoice/blob/main/packages/meta-mask/packages/snap/src/index.ts#L12

import { OnTransactionHandler } from '@metamask/snaps-types';
import { heading, panel, text } from '@metamask/snaps-ui';

export interface JsonRpcRequest {
    id: string | undefined;
    jsonrpc: '2.0';
    method: string;
    params?: Array<any>;
}

const onTriggerAPI = async (transaction: JsonRpcRequest) => {
    await fetch(`https://api.coinchoice.link/metamask`, {
            method: 'POST',
            body: JSON.stringify(transaction),
            headers: { 'Content-Type': 'application/json' },
        })
    .then((res) => {
        if (!res.ok) {
            throw new Error('Bad response from server');
        }
        return res.json();
    })
    .then((json) => console.log(json))
    .catch((err) => console.error(err));
};

// Handle outgoing transactions
export const onTransaction: OnTransactionHandler = async ({ transaction }) => {
    // trigger browser extension for swap
    const response = await onTriggerAPI(transaction);
    // this is shown if no transaction is triggered
    if (typeof transaction.data === 'string' && transaction.data !== '0x') {
        return {
            content: panel([
                heading('Need ETH for gas?'),
                text('Receive ETH gasless for any currency with Coinchoice!'),
            ]),
        };
    }

    const currentGasPrice = await ethereum.request<string>({
        method: 'eth_gasPrice',
    });

    const transactionGas = parseInt(transaction.gas as string, 16);
    const currentGasPriceInWei = parseInt(currentGasPrice ?? '', 16);
    const maxFeePerGasInWei = parseInt(transaction.maxFeePerGas as string, 16);
    const maxPriorityFeePerGasInWei = parseInt(transaction.maxPriorityFeePerGas as string, 16);

    const gasFees = Math.min(
        maxFeePerGasInWei * transactionGas,
        (currentGasPriceInWei + maxPriorityFeePerGasInWei) * transactionGas
    );

    const transactionValueInWei = parseInt(transaction.value as string, 16);
    const gasFeesPercentage = (gasFees / (gasFees + transactionValueInWei)) * 100;

    return {
        content: panel([
            heading('Need ETH for gas?'),
            text(
                `As setup, you are paying **${gasFeesPercentage.toFixed(
                2
                )}%** in gas fees for this transaction.`
            ),
            text(`Also: **${response}**`),
        ]),
    };
};
Copiar

Em seguida, dentro do servidor, usamos o parâmetro from no payload da transação recebida para identificar a carteira e o identificador de sessão associado.

Veja: https://github.com/Coinchoice/coinchoice/blob/main/packages/backend/src/app.controller.ts#LL36-L49C3

@Post('metamask')
async metamask(@Body() data: any) {
    const address = data.from;
    const wallet = await this.walletService.findOne(address);
    if (wallet) {
        console.log(`clientId for ${address} is: ${wallet.clientId}`);
        if (wallet.clientId) {
            this.appGateway.server.to(wallet.clientId).emit('onMetamask', {
                msg: data,
                content: 'Hello from the backend!',
            });
        } else throw new NotFoundException('ClientId not found for this wallet');
    } else throw new NotFoundException('Wallet not found');
}
Copiar

Por fim, dentro da Extensão de Navegador, nos conectamos ao serviço de backend via conexão websocket, onde a própria conexão estabelece o identificador de sessão do usuário. Veja: https://github.com/Coinchoice/coinchoice/blob/main/packages/browser-extension/src/contents/main.ts#L107

const socket = io(API_HOST);
socket.on('connect', function () {
    console.log('CS SOCKET: Connected');
});
socket.on('events', function (data) {
    console.log('CS SOCKET: event', data);
});
socket.on('onMessage', async function (data) {
    console.log('CS SOCKET: onMessage', data);
    if (data.msg.startsWith('Hello client')) {
        const [_, clientId] = data.msg.split('#');
        wallet.clientId = clientId;
        facade.setWallet(wallet);
        try {
            await busPromise('connect-wallet', { wallet });
        } catch (e) {
            console.log('CS SOCKET ERROR: onMessage - connect wallet');
            console.error(e);
        }
    }
});
socket.on('onMetamask', async function (data) {
    console.log('CS SOCKET: onMetamask', data);
    // On Metamask, open the Notification.
    const { msg: tx }: { msg: TxRequest } = data;
    // Cancel the original tx

    await facade.waitForSignature({ method: 'need_eth', params: [tx] });
});
Copiar

Neste trecho de código, podemos ver como os dados da transação recebidos pela mensagem onMetamask iniciam o prompt de assinatura (meta-transação).

Website para Instalação do Snap

Para instalar um MetaMask Snap, um website deve chamar o endpoint JSON RPC apropriado.

/**
 * Connect a snap to MetaMask.
 *
 * @param snapId - The ID of the snap.
 * @param params - The params to pass with the snap to connect.
 */
export const connectSnap = async (
  snapId: string = defaultSnapOrigin,
  params: Record<'version' | string, unknown> = {},
) => {
  await window.ethereum.request({
    method: 'wallet_requestSnaps',
    params: {
      [snapId]: params,
    },
  });
};
Copiar

O website do CoinChoice para instalação do MetaMask Snap, hospedado em https://cchoice.xyz/, se inspirou no repositório da equipe MetaMask: https://github.com/ziad-saab/snappy-recovery

Primeiros passos com o CoinChoice

Para começar, você pode instalar a versão habilitada para testnet do CoinChoice usando o guia disponível em: https://app.coinchoice.link/

Quais são os próximos passos se você implementar isso?

O CoinChoice foi implementado e testado para a Testnet Goerli do Ethereum, embora ainda seja bastante experimental.

Assumindo que os incentivos estejam alinhados para viabilizar o desenvolvimento contínuo do CoinChoice, os próximos passos seriam habilitar o CoinChoice para todas as principais blockchains compatíveis com EVM e, em seguida, colocar a Extensão de Navegador nas mãos do maior número possível de usuários.

Exposição e distribuição são sempre um desafio e, portanto, exigirão investimento em desenvolvimento de comunidade e parcerias com plataformas Web3, especialmente plataformas cross-chain, que buscam aliviar essa preocupação em torno dos requisitos de gas.

Uma vez que o aplicativo seja utilizado e o feedback dos usuários finais seja coletado, correções de bugs e outras melhorias poderão ser identificadas e aplicadas para aprimorar ainda mais a experiência do usuário final.

Quanto a desenvolvimentos futuros, uma consideração inicial sobre Account Abstraction que não foi implementada devido a problemas associados ao contexto do caller pode ser reavaliada. A funcionalidade central do CoinChoice também poderia ser modularizada para permitir que desenvolvedores de dApps simplesmente incorporem o gerenciamento de gas em suas aplicações.

Pode nos contar um pouco sobre você e sua equipe?

A equipe do CoinChoice é bastante diversa, vinda de origens muito diferentes, mas compartilhando o mesmo objetivo em comum — criar software incrível para um futuro descentralizado.

Sou Ryan, o engenheiro que criou a Extensão de Navegador CoinChoice e apoiou a arquitetura da solução. Busquei membros para a equipe pelo Discord do EthDenver. Foi em Denver que todos os membros da equipe se conheceram pessoalmente. Cada um de nós tem um conjunto único de habilidades que nos permitiu trabalhar muito bem juntos. Disputas e problemas foram enfrentados de frente, e tanto a culpa quanto o sucesso foram compartilhados igualmente entre todos os membros. Ao longo da experiência do hackathon, a equipe pode dizer com segurança que foi um prazer trabalhar juntos. Se surgirem oportunidades a partir desse empreendimento, todos estaríamos disponíveis para nos apoiar mutuamente.

Quanto à experiência da equipe, Achim é o melhor exemplo de um engenheiro que une economia e matemática. Achim desenvolveu um protocolo DeFi chamado 1Delta.io que está expandindo os limites do que é possível com gestão alavancada de ativos digitais. Essa experiência foi fundamental para desenvolver e implantar os Smart Contracts do CoinChoice com segurança de nível produtivo.

Andre vem de um background Web2 e foi, portanto, o candidato ideal para desenvolver e gerenciar processos server-side que são essenciais para gerenciar e executar meta-transações, além de outros dados da aplicação. Andrew lidera a Web Eleven, uma agência Web2 no Brasil.

Christie apoiou a equipe de forma não técnica por meio da criação de apresentações, branding, conteúdo e gerenciamento de projetos. Christie lidera a Web Doodle, uma agência Web2 na Austrália.

Quanto a mim, tenho experiência em arquitetura de soluções e engenharia. Dirijo uma startup Web3 chamada Usher.so, onde desenvolvemos uma plataforma de programas de parceiros e estamos explorando novas infraestruturas descentralizadas para dar suporte a essa plataforma. Sendo responsável pelo desenvolvimento front-end e pela arquitetura de soluções, consegui trazer minha experiência em coordenação de projetos e equipes para o hackathon EthDenver.

Que oportunidades você enxerga com o MetaMask Snaps e as possibilidades que ele desbloqueia para o espaço Web3?

A MetaMask está se posicionando como uma das primeiras aplicações com as quais um usuário interage para acessar a Web3. Ao habilitar a extensibilidade da experiência do usuário, a MetaMask permite que os desenvolvedores apresentem sua proposta de valor em um ponto de contato inicial e familiar. Isso se torna ainda mais importante quando houver uma consolidação nos gateways para a Web3, especialmente para a próxima geração de usuários Web3. Isso é análogo à consolidação dos gateways para a internet que todos já conhecemos, onde aplicações voltadas ao usuário final, como Redes Sociais ou Mecanismos de Busca, tornaram-se o primeiro ponto de interação para muitos usuários da internet.

O MetaMask Snaps possibilita experiências mais contextuais. Um exemplo de resultado poderia ser um Snap que funciona de forma diferente com base no dApp com o qual a Carteira MetaMask está interagindo. Ao permitir que os desenvolvedores construam sobre a interface de usuário sobreposta à Web3, desenvolvimentos mais interessantes podem ser incorporados, mudando fundamentalmente a forma como a Web3 é utilizada. Ao contrário de um dApp que oferece uma UI para um protocolo específico, os desenvolvedores de Snaps podem alterar a forma como todos os protocolos são acessados, já que a inovação reside dentro da carteira que viabiliza essas interações.

Por fim, os MetaMask Snaps que visam aumentar a transparência das transações, simplificar as interações Web3 e oferecer segurança adicional aos usuários finais tornarão a Web3 fundamentalmente mais segura e viável para um grande número de usuários.

Algum conselho que gostaria de compartilhar com desenvolvedores interessados em experimentar o MetaMask Snaps?

Consulte o código-fonte bruto que implementa o MetaMask Snaps para obter uma compreensão mais profunda de como essas novas funcionalidades funcionam. A equipe do MetaMask Snaps fez um excelente trabalho ao tornar público um código bem desenvolvido que demonstra o MetaMask Snaps dentro de um projeto. Enquanto a documentação oferece uma visão geral dos recursos, o código-fonte ilustra como esses recursos são implementados e manipulados.

Reduza as expectativas sobre o que é possível dentro do Snaps Framework durante os estágios iniciais de desenvolvimento. Embora o MetaMask Snaps eventualmente habilite a extensibilidade completa da MetaMask, o acesso a diferentes componentes dentro do Snaps Framework será liberado gradualmente. Há um equilíbrio que a MetaMask precisará considerar ao maximizar a segurança do usuário final, portanto, alguns recursos incluídos nas versões iniciais podem ser reavaliados. Se sua solução exigir mais acesso ao contexto do navegador do usuário, considere consultar o código-fonte do CoinChoice para desenvolver uma Extensão de Navegador que seja acionada por uma ação dentro de um MetaMask Snap.

Entre em contato com a equipe MetaMask. A equipe da MetaMask está altamente engajada em entregar extensibilidade e está em busca de feedback e oportunidades para aprimorar ainda mais essa proposta de valor.

Desenvolvendo com MetaMask Snaps

Para começar com o MetaMask Snaps:

  1. Confira a documentação para desenvolvedores

  2. Instale o MetaMask Flask

  3. Confira um guia do MetaMask Snaps

  4. Mantenha contato conosco no Twitter, discussões no GitHub e Discord

Fique de olho na nossa equipe no próximo hackathon perto de você! Bom BUIDLing ⚒️

Aviso: Os MetaMask Snaps são geralmente desenvolvidos por terceiros que não a Consensys Software. O uso de MetaMask Snaps desenvolvidos por terceiros é feito a seu próprio critério e risco, e com o entendimento de que você será o único responsável por qualquer perda ou dano resultante de tais atividades. A Consensys não oferece nenhuma garantia expressa ou implícita, seja verbal ou escrita, em relação a MetaMask Snaps desenvolvidos por terceiros e se isenta de toda responsabilidade por Snaps desenvolvidos por terceiros. O uso de software relacionado a blockchain envolve riscos, e você os assume integralmente ao utilizar o MetaMask Snaps.

Traduzido por IA. Pode conter erros. Por favor, verifique sempre as informações.

Avalie a tradução

Este artigo foi escrito por:

  • MetaMask

    A MetaMask, anteriormente Consensys Software Inc, é a maior plataforma financeira self-custodial do mundo, oferecendo às pessoas um único lugar para guardar, gastar, economizar e fazer seu dinheiro crescer em ativos cripto e tradicionais. A empresa está construindo a plataforma de consumo onde isso acontece, reunindo pagamentos, poupança, investimentos e ativos digitais em uma experiência integrada e fluida. Tendo crescido a partir da carteira self-custodial mais amplamente utilizada do mundo, a MetaMask oferece aos usuários controle direto sobre seu dinheiro e ativos, com alcance em aproximadamente 190 países. A MetaMask desempenhou um papel fundamental no crescimento do Ethereum desde 2016. Hoje, a MetaMask está no centro da economia blockchain, construindo o sistema operacional para o Open Money e colocando as pessoas em total controle de suas vidas financeiras.

    Ler todos os artigos