Aller au contenu

Ether Eyes Snap : Prédire les futurs prix du gas

Lauréat d'un Hackathon Inter IIT

13 min de lecture
Ether Eyes Snap : Prédire les futurs prix du gas

MetaMask Snaps est la feuille de route pour faire de MetaMask le wallet le plus extensible au monde. En tant que développeur, vous pouvez intégrer vos fonctionnalités et vos API à MetaMask de manières totalement nouvelles. Les développeurs Web3 sont au cœur de cette croissance, et cette série vise à mettre en lumière les MetaMask Snaps innovants en cours de développement aujourd'hui.

Ether Eyes Snap

Dépôt du Snap : https://github.com/aritroCoder/EtherEyes

Pourquoi l'avez-vous créé ?

Les prix du gas sur la blockchain Ethereum peuvent être très difficiles à prévoir, ce qui constitue un obstacle lors des paiements. Un utilisateur qui tente d'effectuer un paiement peut finir par payer bien plus que nécessaire. Un trafic élevé sur la blockchain pendant une courte période peut avoir un impact considérable sur les prix du gas. Bien que les L2 aient été conçus pour réduire les prix du gas, nous avons parfois besoin d'une solution plus générale et plus simple que le recours à un L2 pour les transactions. Nous avons pensé qu'il serait utile pour les utilisateurs de disposer d'une application capable de prédire les futurs prix du gas en se basant sur des données historiques et les tendances actuelles.

Pouvez-vous nous expliquer la mise en œuvre technique ?

EtherEyes se compose de quatre parties : le serveur de prix du gas, le snap, le modèle SARIMA et le frontend web. Le serveur de prix du gas fournit des données sur les prix du gas historiques et actuels. Le site web héberge le snap et propose une interface pour l'installer et interagir avec lui en appelant les méthodes de l'API du snap. Nous avons utilisé le modèle SARIMA (Seasonal Autoregressive Integrated Moving Average) pour prédire les prix du gas.

Serveur de prix du gas

Nous collectons des données en direct sur les prix du gas sous la forme d'une liste d'environ 200 chandeliers (chaque chandelier représente un agrégat des 30 dernières minutes de données) à l'aide de l'API Owlracle. Cela nous fournit les données de séries temporelles des prix du gas des 100 dernières heures.

Le Snap

Pour le snap, nous avons utilisé l'API transaction insights afin de fournir des prédictions de prix du gas en temps réel. Le fonctionnement du snap est le suivant :

Tout d'abord, lorsque l'utilisateur initie une transaction, les transaction insights s'affichent sur la page de confirmation, ce qui est implémenté via le onTransactionHandler. Nous y indiquons à l'utilisateur les prédictions à venir pour les 30 et 60 prochaines minutes. Une version simplifiée de ce que nous avons implémenté est présentée ici :

export const onTransaction: OnTransactionHandler = async ({ transaction }) => {
 let state: { notifToggle: boolean; urgency: number; lowEth: number };

 state = (await wallet.request({
   method: 'snap_manageState',
   params: ['get'],
 })) as { notifToggle: boolean; urgency: number; lowEth: number };

 if (!state) {
   state = {
     notifToggle,
     urgency,
     lowEth,
   };
 }

 let insights: any = {
   type: 'Gas Fee estimation',
 };

 if (
   !isObject(transaction) ||
   !hasProperty(transaction, 'data') ||
   typeof transaction.data !== 'string'
 ) {
   console.warn('unknown transaction type');
   return { insights };
 }

 const response = await fetch(`${MODEL_API_ENDPOINT}`, {
   method: 'get',
   headers: {
     'Content-Type': 'application/json',
   },
 });

 const currentData = await fetch(CURRENT_DATA_ENDPOINT, {
   method: 'get',
   headers: {
     'Content-Type': 'application/json',
   },
 });

 if (!response.ok) {
   throw new Error('API request failed');
 }

 const data = await response.json();
 const current = await currentData.json();

 state.lowEth = Math.min(data.low_30_minutes, data.low_60_minutes);

 await wallet.request({
   method: 'snap_manageState',
   params: ['update', state],
 });

 insights = {
   'Average Gas Limit': `Current value: ${current.avgGas}`,

   'Estimated current gas price': `Current value (Base + Priority): ${
     current.speeds[0].baseFee + current.speeds[0].maxPriorityFeePerGas
   } GWei; Base Fee: ${current.speeds[0].baseFee} GWei`,

   'Forecasted Avg Gas price (for the next 30 mins)': `
   Gas price within 30 minutes is expected to get as low as: ${data.low_30_minutes} GWei`,

   'Forecasted Avg Gas price (for the next 60 mins)': `Gas price within 60 minutes is expected to get as low as: ${Math.min(
     data.low_30_minutes,
     data.low_60_minutes,
   )} GWei`,

   'Expected savings in 30 mins (For average gas limit)': `
   ${
     current.avgGas *
     (current.speeds[0].baseFee +
       current.speeds[0].maxPriorityFeePerGas -
       data.low_30_minutes)
   } GWei`,

   'Expected savings in 60 mins (For average gas limit)': `${
     current.avgGas *
     (current.speeds[0].baseFee +
       current.speeds[0].maxPriorityFeePerGas -
       Math.min(data.low_30_minutes, data.low_60_minutes))
   } GWei
   `,
 };

 return { insights };
};
Copier

Si l'utilisateur décide d'attendre, il peut patienter et activer un système de notifications depuis le site web qui interagit avec le snap via le handler onCronjob et envoie les prix du gas toutes les trois minutes sous forme de notifications natives du navigateur. Lorsque les prix se rapprochent suffisamment de la prédiction, il invite l'utilisateur à finaliser la transaction.


export const onCronjob: OnCronjobHandler = async ({ request }) => {
 switch (request.method) {
   case 'exampleMethodOne': {
     // get data from state whenever snap is invoked as snaps executions are ephemeral
     let state: { notifToggle: boolean; urgency: number; lowEth: number };

     state = (await wallet.request({
       method: 'snap_manageState',
       params: ['get'],
     })) as { notifToggle: boolean; urgency: number; lowEth: number };

     if (!state) {
       state = {
         notifToggle,
         urgency,
         lowEth,
       };
     }
     notifToggle = state.notifToggle;
     urgency = state.urgency;
     lowEth = state.lowEth;

     await wallet.request({
       method: 'snap_manageState',
       params: ['update', state],
     });

     console.log({ notifToggle });
     if (notifToggle) {
       const currentData = await fetch(CURRENT_DATA_ENDPOINT, {
         method: 'get',
         headers: {
           'Content-Type': 'application/json',
         },
       });
       const current = await currentData.json();
       if (Math.abs(current.speeds[0].baseFee - lowEth) < urgency / 38) {
         return wallet.request({
           method: 'snap_notify',
           params: [
             {
               type: 'native',
               message: `Gasfee is low! Pay now at ${current.speeds[0].baseFee} Gwei`,
             },
           ],
         });
       }
       return wallet.request({
         method: 'snap_notify',
         params: [
           {
             type: 'native',
             message: `Current gasfee is ${current.speeds[0].baseFee} Gwei`,
           },
         ],
       });
     }
     return 0; // basically do nothing
   }

   default:
     throw new Error('Method not found.');
 }
};
Copier

Les paramètres du cronjob correspondant sont (dans snap.manifest.json) :

"endowment:cronjob": {
      "jobs": [
        {
          "expression": {
            "minute": "*/3",
            "hour": "*",
            "dayOfMonth": "*",
            "month": "*",
            "dayOfWeek": "*"
          },
          "request": {
            "method": "exampleMethodOne",
            "params": {}
          }
        }
      ]
    }
Copier

Il existe également une fonctionnalité d'urgence qui définit le niveau d'urgence de la transaction (techniquement, le paramètre qui détermine quelle doit être la différence maximale entre la prédiction et les prix du gas actuels pour que l'utilisateur procède à la transaction). Modifier l'urgence fait varier ce seuil. Nous avons implémenté le paramètre d'urgence à l'aide de la méthode onRpcRequest du snap.


 export const onRpcRequest: OnRpcRequestHandler = async ({
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  origin,
  request,
}) => {
  switch (request.method) {
    // Other RPC methods here
    case 'set_urgency_35': {
      urgency = 35;

      let state: { notifToggle: boolean; urgency: number; lowEth: number };

      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };

      if (!state) {
        state = {
          notifToggle,
          urgency: 35,
          lowEth,
        };
      }
      state.urgency = 35;

      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });

      return urgency;
    }

    case 'set_urgency_60': {
      urgency = 60;

      let state: { notifToggle: boolean; urgency: number; lowEth: number };

      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };

      if (!state) {
        state = {
          notifToggle,
          urgency: 60,
          lowEth,
        };
      }
      state.urgency = 60;

      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });

      return urgency;
    }

    case 'set_urgency_90': {
      urgency = 90;

      let state: { notifToggle: boolean; urgency: number; lowEth: number };

      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };

      if (!state) {
        state = {
          notifToggle,
          urgency: 90,
          lowEth,
        };
      }
      state.urgency = 90;

      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });

      return urgency;
    }

    case 'set_urgency_100': {
      urgency = 100;

      let state: { notifToggle: boolean; urgency: number; lowEth: number };

      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };

      if (!state) {
        state = {
          notifToggle,
          urgency: 100,
          lowEth,
        };
      }
      state.urgency = 100;

      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });

      return urgency;
    }

    case 'call_api': {
      // get data from state whenever snap is invoked as snaps executions are ephemeral
      let state: { notifToggle: boolean; urgency: number; lowEth: number };

      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };

      if (!state) {
        state = {
          notifToggle,
          urgency,
          lowEth,
        };
      }

      notifToggle = state.notifToggle;
      urgency = state.urgency;
      lowEth = state.lowEth;

      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });

      console.log(
        `Called inside custom api call: notifToggle = ${notifToggle} and urgency = ${urgency}`,
      );
      const currentData = await fetch(CURRENT_DATA_ENDPOINT, {
        method: 'get',
        headers: {
          'Content-Type': 'application/json',
        },
      });
      const current = await currentData.json();
      if (Math.abs(current.speeds[0].baseFee - lowEth) < urgency / 38) {
        return wallet.request({
          method: 'snap_notify',
          params: [
            {
              type: 'native',
              message: `Gasfee is low! Pay now at ${current.speeds[0].baseFee} Gwei`,
            },
          ],
        });
      }
      return wallet.request({
        method: 'snap_notify',
        params: [
          {
            type: 'native',
            message: `Current gasfee is ${current.speeds[0].baseFee} Gwei`,
          },
        ],
      });
    }

    default: {
      throw new Error('Method not found.');
    }
  }
};
Copier

Pour calculer le seuil, nous avons divisé le paramètre d'urgence par 38. Après des tests empiriques avec différentes valeurs, 38 s'est avéré le plus efficace dans la plupart des situations. Il est prévu d'affiner et d'améliorer ce paramètre dans un avenir proche pour des performances plus dynamiques.

if (Math.abs(current.speeds[0].baseFee - lowEth) < urgency / 38) {
          return wallet.request({
            method: 'snap_notify',
            params: [
              {
                type: 'native',
                message: `Gasfee is low! Pay now at ${current.speeds[0].baseFee} Gwei`,
              },
            ],
          });
        }
Copier

Les états du snap étant éphémères, nous avons dû stocker les informations d'état (comme l'activation/désactivation des notifications, le niveau d'urgence défini par l'utilisateur) dans le stockage à l'aide de l'API de stockage du snap.


export const onRpcRequest: OnRpcRequestHandler = async ({
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  origin,
  request,
}) => {
  switch (request.method) {
    case 'notif_toggle_true': {
      console.log('Notification toggled to true');
      notifToggle = true; // toggle the notification
      console.log({ notifToggle });

      let state: { notifToggle: boolean; urgency: number; lowEth: number };

      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };

      if (!state) {
        state = {
          notifToggle: true,
          urgency,
          lowEth,
        };
      }
      state.notifToggle = true;

      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });

      return notifToggle;
    }

    case 'notif_toggle_false': {
      console.log('Notification toggled to false');
      notifToggle = false; // toggle the notification
      console.log({ notifToggle });

      let state: { notifToggle: boolean; urgency: number; lowEth: number };

      state = (await wallet.request({
        method: 'snap_manageState',
        params: ['get'],
      })) as { notifToggle: boolean; urgency: number; lowEth: number };

      if (!state) {
        state = {
          notifToggle: false,
          urgency,
          lowEth,
        };
      }
      state.notifToggle = false;

      await wallet.request({
        method: 'snap_manageState',
        params: ['update', state],
      });

      return notifToggle;
    }

     default: {
      throw new Error('Method not found.');
    }
  }
}; 
Copier

Le Modèle

Nous utilisons ensuite un modèle populaire de prévision de séries temporelles appelé SARIMA ou ARIMA saisonnier, issu du package statsforecast, appliqué aux données de séries temporelles pour prédire le prix du gas le plus bas attendu dans l'heure suivante.


from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import requests
import numpy as np
from statsforecast.models import AutoARIMA
import json

def get_timeseries():
    with open('key.json') as f:
        data = json.load(f)
        print(data)

    key = data['key']

    history_data = requests.get(
        'https://api.owlracle.info/v3/eth/history?apikey={}&candles=100&txfee=true'
        .format(key))
    history_data = history_data.json()

    low = []

    for obj in history_data:
        low.append(obj['gasPrice']['low'])

    low.reverse()

    return np.array(low)

def get_prediction():
    values = get_timeseries()
    model = AutoARIMA()
    predictions = model.forecast(values, 2)
    print("Pred: ", predictions)
    prediction_json = {
        'low_30_minutes': predictions['mean'][0],
        'low_60_minutes': predictions['mean'][1]
    }

    return prediction_json

app = FastAPI()

origins = [
    "*",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/")
async def root():
    pred = get_prediction()

    return pred
Copier

Pourquoi SARIMA ?

  • De nombreuses publications sur SARIMA pour la prévision de séries temporelles dans divers domaines indiquent que ses performances sont bonnes. Nous avons également consulté une étude sur les statistiques des prix du gas Ethereum, dans laquelle SARIMA a été utilisé avec des résultats prometteurs.

  • Une alternative serait les techniques de deep learning, qui impliquent généralement des modèles plus volumineux nécessitant également plus de temps pour être réentraînés, ce qui les rend moins adaptés aux données en streaming.

  • Quelques publications consultées : A hybrid SARIMA and support vector machines in forecasting the production values of the machinery industry in Taiwan. Expert Systems with Applications, 32(1), 254-264. https://doi.org/10.1016/j.eswa.2005.11.027

  • Dynamic linear model and SARIMA: a comparison of their forecasting performance in epidemiology. https://doi.org/10.1002/sim.963

  • Long-term runoff study using SARIMA and ARIMA models in the United States. https://doi.org/10.1002/met.1491

  • Carl, David and Ewerhart, Christian, Ethereum Gas Price Statistics (December 22, 2020). University of Zurich, Department of Economics, Working Paper No. 373, 2020, Available at: https://dx.doi.org/10.2139/ssrn.3754217

Frontend Web

Nous avons utilisé une simple application React comme interface frontend web. Elle contient les boutons pour installer le snap, envoyer une transaction fictive, définir le niveau d'urgence de l'utilisateur, activer/désactiver les notifications de prix du gas et basculer en mode sombre. Elle est très simple et facile à utiliser pour n'importe quel utilisateur.

Quelles sont les prochaines étapes si vous souhaitez mettre cela en œuvre ?

Il y a beaucoup à faire : nous pouvons commencer par rendre le modèle plus fiable en ajustant l'algorithme d'apprentissage pour obtenir des prédictions plus robustes. Un autre axe d'amélioration concerne le seuil d'urgence, pour lequel nous devons trouver une expression plus dynamique capable de gérer simultanément de larges variations du profil de marché, du niveau d'urgence de l'utilisateur et des économies de gas sur les transactions, tout en convergeant rapidement vers un point quasi optimal où l'utilisateur devrait effectuer son paiement. Nous devons également rendre l'interface web un peu plus conviviale et ajouter une gestion globale des erreurs pour certains cas limites qui peuvent survenir rarement.

Pouvez-vous nous parler un peu de vous et de votre équipe ?

Nous sommes une équipe composée de huit étudiants en ingénierie BTech à l'IIT Patna. Nous avons formé cette équipe pour participer à l'Inter IIT Tech Meet 11 (2023), où Consensys a proposé un énoncé de problème autour de MetaMask Snaps.

  • Vaishakh : Je suis étudiant en dernière année d'informatique à l'IIT Patna et je suis passionné par mon domaine d'études. Ces derniers temps, je participe à des hackathons et j'apprécie énormément l'expérience. J'ai hâte d'explorer davantage les vastes possibilités de l'informatique et de voir où cela me mènera à l'avenir.

  • Aritra B. : Aritra est étudiant en deuxième année de BTech en IA et Science des données à l'Indian Institute of Technology de Patna. Il est passionné par la blockchain et ses applications dans le déploiement à grande échelle dans le monde réel. Il a travaillé sur plusieurs petits projets blockchain auparavant, ce qui lui a permis de construire les bases nécessaires pour apprendre et explorer ce domaine. Il vise à créer des solutions blockchain intelligentes en combinant d'autres domaines de l'informatique, comme le machine learning, pour générer de nouvelles innovations. Il a été sélectionné comme boursier KVPY par le prestigieux Indian Institute of Science (IISC) en 2019 et se consacre actuellement à l'apprentissage des ZK EVM et de leurs domaines d'application uniques dans cet espace.

  • Padmaksh : Étudiant en BTech en informatique et ingénierie à l'Indian Institute of Technology de Patna, il s'intéresse vivement à la cybersécurité. Il est également très attiré par la résolution de problèmes et les puzzles algorithmiques. Il approfondit actuellement ses connaissances en architecture blockchain et explore d'autres domaines.

  • Kartikay : Étudiant en licence à l'IIT Patna en génie mécanique, actuellement en 3e année de cursus. Il s'intéresse vivement au développement web et à la programmation compétitive. Il a conçu et développé plusieurs sites web pour de nombreux clubs et événements universitaires. Il possède des connaissances de base en Data Science et en Web3.

  • Harsh : Je suis étudiant en deuxième année de licence à l'IIT Patna en génie chimique. Je m'intéresse principalement aux études de cas et à la résolution de problèmes.

  • Dhushyanth : Je suis étudiant en dernière année de génie électrique à l'IIT Patna, très enthousiaste à l'égard de la technologie et du développement. Je me suis essayé à divers domaines, de l'implémentation de serveurs CRDT en Rust à la conception de Perceptrons en photonique sur silicium. J'aime les discussions animées sur tout sujet sur lequel j'ai mon mot à dire et j'en tire beaucoup de satisfaction !

  • Vishwas S : Vishwas est étudiant en première année d'informatique à l'IIT Patna. Passionné par son domaine d'études, il est à la recherche d'opportunités pour explorer de nouveaux horizons. Ces derniers temps, il a développé un vif intérêt pour la technologie blockchain et y travaille activement.

  • Ankur : Je suis étudiant en deuxième année de licence à l'IIT Patna en génie électrique et électronique. J'ai récemment développé quelques sites web pour l'IIT Patna et j'apprécie la résolution de problèmes. Ces derniers temps, je me passionne pour l'UI et l'UX avec un penchant pour le frontend. J'aime étudier la psychologie humaine et travailler à l'élaboration de solutions à divers problèmes.

Quand avez-vous découvert MetaMask Snaps pour la première fois et quelle a été votre expérience ?

Nous avons découvert MetaMask Snaps pour la première fois lors de l'Inter IIT Tech Meet 2023. C'est un complément vraiment unique et intéressant à MetaMask, qui peut être utilisé pour apporter des personnalisations infinies au wallet. Le processus de développement est également assez simple et nous n'avons pas rencontré de difficultés majeures lors du développement, même si la documentation et le contenu des forums de discussion disponibles étaient limités. Bien qu'il soit encore en développement et qu'il manque quelques fonctionnalités importantes pour l'instant, nous pouvons déjà percevoir le formidable potentiel qu'il pourra avoir dans les années à venir.

En quoi MetaMask Snaps se distingue-t-il des autres wallets ?

MetaMask Snaps est similaire à une extension dans un navigateur web. Il est utilisé pour étendre les fonctionnalités de MetaMask. Il est sécurisé car les snaps s'exécutent dans un environnement isolé où ils ont accès à un ensemble limité de capacités déterminées par les autorisations accordées par l'utilisateur lors de l'installation. C'est une excellente façon, à la fois sûre et pratique, de personnaliser votre expérience de wallet.

Parlez-nous de ce que représente la création de MetaMask Snaps pour vous et votre équipe.

C'est l'un des projets qui nous a permis de voir comment différents domaines de l'informatique peuvent collaborer pour relever un défi. Pour mon équipe et moi, la création de ce snap a été une fantastique opportunité d'apprentissage. Nous avons acquis des connaissances sur la manière de mettre en œuvre notre idée efficacement, ainsi que sur l'utilisation du machine learning pour résoudre un problème sur la blockchain. En chemin, nous avons également établi quelques nouvelles connexions. De l'autre côté, les autres wallets semblent assez restrictifs pour les développeurs.

Que représente MetaMask Snaps pour vous ?

MetaMask Snaps ajoute les fonctionnalités des extensions à un wallet crypto. C'est vraiment innovant et peut être utilisé pour de nombreux cas d'usage critiques afin de favoriser l'adoption massive des cryptomonnaies.

Quelles opportunités voyez-vous avec MetaMask Snaps et les possibilités qu'il ouvre pour l'espace Web3 ?

MetaMask Snaps pourrait véritablement représenter une avancée majeure dans l'écosystème Web3, car il transforme un simple wallet Ethereum en un outil complet de gestion Web3 permettant de personnaliser et d'enrichir notre expérience Web3.

Avez-vous des conseils à partager avec les développeurs désireux d'essayer MetaMask Snaps ? Commencez par lire la documentation. Elle est très détaillée et peut expliquer la plupart des cas d'usage envisageables. Pour tout problème dont la solution n'est pas évidente, nous vous suggérons de poser vos questions sur le Discord de Consensys, où un forum est dédié à cet effet.

Développer avec MetaMask Snaps

Pour démarrer avec MetaMask Snaps :

  1. Consultez la documentation développeur

  2. Installez MetaMask Flask

  3. Consultez un guide MetaMask Snaps

  4. Restez connecté avec nous sur Twitter, les discussions GitHub et Discord

Gardez un œil sur notre équipe lors du prochain hackathon près de chez vous ! Bonne construction ⚒️

Avertissement : Les MetaMask Snaps sont généralement développés par des tiers autres que Consensys Software. L'utilisation de MetaMask Snaps développés par des tiers se fait à votre propre discrétion et à vos propres risques, et implique votre accord selon lequel vous serez seul responsable de toute perte ou dommage résultant de ces activités. Consensys ne donne aucune garantie expresse ou implicite, qu'elle soit orale ou écrite, concernant les MetaMask Snaps développés par des tiers, et décline toute responsabilité pour les Snaps développés par des tiers. L'utilisation de logiciels liés à la blockchain comporte des risques que vous assumez pleinement lors de l'utilisation de MetaMask Snaps.

Traduit par IA. Peut contenir des erreurs. Veuillez toujours vérifier les informations.

Évaluer la traduction

Cet article a été rédigé par :

  • MetaMask

    MetaMask, anciennement Consensys Software Inc, est la plus grande plateforme financière self-custodial au monde, offrant aux utilisateurs un espace unique pour détenir, dépenser, épargner et faire fructifier leur argent, aussi bien en crypto qu'en actifs traditionnels. La société développe la plateforme grand public au sein de laquelle tout cela se concrétise, en réunissant paiements, épargne, investissement et actifs numériques dans une expérience fluide et unifiée. Issu du wallet self-custodial le plus utilisé au monde, MetaMask donne aux utilisateurs un contrôle direct sur leur argent et leurs actifs, avec une présence dans environ 190 pays. MetaMask joue un rôle fondateur dans la croissance d'Ethereum depuis 2016. Aujourd'hui, MetaMask occupe une place centrale dans l'économie blockchain, en construisant le système d'exploitation de l'Open Money et en donnant aux individus un contrôle total sur leur vie financière.

    Lire tous les articles