MetaMask Snaps ist der Fahrplan, um MetaMask zum erweiterbarsten Wallet der Welt zu machen. Als Entwickler kannst du deine Features und APIs auf völlig neue Weise in MetaMask einbringen. Web3-Entwickler sind der Kern dieses Wachstums, und diese Serie soll die innovativen MetaMask Snaps vorstellen, die heute entwickelt werden.
Gaspreise auf der Ethereum-Blockchain sind schwer vorherzusagen und stellen ein Hindernis bei Zahlungen dar. Wenn ein Nutzer eine Zahlung durchführen möchte, kann es passieren, dass er deutlich mehr als nötig bezahlt. Kurzzeitig hoher Traffic auf der Blockchain kann zu erheblichen Schwankungen bei den Gaspreisen führen. Obwohl L2s entwickelt wurden, um Gaspreise zu senken, brauchen wir manchmal eine allgemeinere und einfachere Lösung, als für Transaktionszwecke ein L2 zu verwenden. Wir dachten, es wäre nützlich für Nutzer, eine App zu haben, die zukünftige Gaspreise auf Basis historischer Daten und aktueller Trends vorhersagen kann.
Kannst du uns durch die technische Umsetzung führen?
EtherEyes besteht aus vier Teilen: Gaspreisserver, dem Snap, SARIMA-Modell und Web-Frontend. Der Gaspreisserver liefert Daten zu historischen und aktuellen Gaspreisen. Die Website hostet den Snap und stellt eine Schnittstelle bereit, um den Snap zu installieren und durch den Aufruf von Snap-API-Methoden mit ihm zu interagieren. Wir haben das Seasonal Autoregressive Integrated Moving Average (SARIMA)-Modell verwendet, um Gaspreise vorherzusagen.
Gaspreisserver
Wir erfassen Live-Gaspreisdaten als Liste von etwa 200 Candlesticks (jeder Candlestick ist eine Aggregation der letzten 30 Minuten an Daten) mithilfe der Owlracle API. Dies liefert uns die Zeitreihendaten der Gaspreise der vergangenen 100 Stunden.
Der Snap
Für den Snap haben wir die Transaction Insights API verwendet, um Echtzeit-Gaspreisvorhersagen bereitzustellen. Der Ablauf des Snaps ist wie folgt:
Wenn der Nutzer zunächst eine Transaktion startet, erscheinen die Transaction Insights auf der Bestätigungsseite, die mithilfe des onTransactionHandler implementiert wird. Hier zeigen wir dem Nutzer die bevorstehende Vorhersage für die nächsten 30 und 60 Minuten. Eine vereinfachte Version unserer Implementierung ist hier dargestellt:
exportconstonTransaction:OnTransactionHandler=async({ transaction })=>{letstate:{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,};}letinsights: any ={type:'Gas Fee estimation',};if(!isObject(transaction)||!hasProperty(transaction,'data')||typeof transaction.data !=='string'){
console.warn('unknown transaction type');return{ insights };}const response =awaitfetch(`${MODEL_API_ENDPOINT}`,{method:'get',headers:{'Content-Type':'application/json',},});const currentData =awaitfetch(CURRENT_DATA_ENDPOINT,{method:'get',headers:{'Content-Type':'application/json',},});if(!response.ok){thrownewError('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 };};
Kopieren
Wenn der Nutzer warten möchte, kann er warten und ein Benachrichtigungssystem von der Website aus starten, das über den onCronjob-Handler mit dem Snap interagiert und alle drei Minuten Gaspreise als native Browser-Benachrichtigungen sendet. Wenn die Preise der Vorhersage sehr nahe kommen, wird der Nutzer aufgefordert, die Transaktion abzuschließen.
exportconstonCronjob:OnCronjobHandler=async({ request })=>{switch(request.method){case'exampleMethodOne':{// get data from state whenever snap is invoked as snaps executions are ephemeralletstate:{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 =awaitfetch(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`,},],});}return0;// basically do nothing}default:thrownewError('Method not found.');}};
Kopieren
Die entsprechenden Cronjob-Einstellungen sind (in snap.manifest.json):
Es gibt auch eine Dringlichkeitsfunktion, die die Dringlichkeit der Transaktion festlegt (technisch gesehen der Parameter, der bestimmt, wie groß die maximale Differenz zwischen Vorhersage und aktuellem Gaspreis sein darf, damit der Nutzer die Transaktion durchführen sollte). Durch Ändern der Dringlichkeit wird dieser Schwellenwert angepasst. Wir haben die Dringlichkeitseinstellung mithilfe der onRpcRequest-Methode des Snaps implementiert.
exportconstonRpcRequest: OnRpcRequestHandler =async({// eslint-disable-next-line @typescript-eslint/no-unused-vars
origin,
request,})=>{switch(request.method){// Other RPC methods herecase'set_urgency_35':{
urgency =35;letstate:{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;letstate:{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;letstate:{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;letstate:{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 ephemeralletstate:{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 =awaitfetch(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:{thrownewError('Method not found.');}}};
Kopieren
Zur Berechnung des Schwellenwerts haben wir die Dringlichkeitseinstellung durch 38 geteilt. Nach empirischen Tests mit verschiedenen Werten erwies sich 38 in den meisten Situationen als am besten geeignet. Es ist geplant, dies in naher Zukunft für eine dynamischere Performance weiter zu verfeinern und zu verbessern.
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`,},],});}
Kopieren
Da Snap-Zustände flüchtig sind, mussten wir Zustandsinformationen (wie Benachrichtigung ein/aus, vom Nutzer festgelegte Dringlichkeit) mithilfe der Snap Storage API im Speicher ablegen.
exportconstonRpcRequest: 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 });letstate:{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 });letstate:{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:{thrownewError('Method not found.');}}};
Kopieren
Das Modell
Wir verwenden dann ein bekanntes Zeitreihen-Prognosemodell namens SARIMA oder Seasonal ARIMA aus dem statsforecast-Paket auf den Zeitreihendaten, um den niedrigsten erwarteten Gaspreis in der nächsten Stunde vorherzusagen.
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():withopen('key.json')asf:
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 inhistory_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
Kopieren
Warum SARIMA?
Zahlreiche Publikationen zu SARIMA für die Zeitreihenprognose in verschiedenen Bereichen belegen, dass die Leistung von SARIMA gut ist. Wir haben uns auch auf eine Studie zu Ethereum-Gaspreisstatistiken bezogen, in der SARIMA verwendet wurde und vielversprechende Ergebnisse erzielt wurden.
Eine Alternative wären Deep-Learning-Techniken, die in der Regel größere Modelle umfassen, die auch mehr Zeit zum erneuten Training benötigen, was sie für Streaming-Daten weniger geeignet macht.
Einige der von uns herangezogenen Publikationen: 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
Carl, David and Ewerhart, Christian, Ethereum Gas Price Statistics (December 22, 2020). University of Zurich, Department of Economics, Working Paper No. 373, 2020, verfügbar unter: https://dx.doi.org/10.2139/ssrn.3754217
Web-Frontend
Wir haben eine einfache React-App als Web-Frontend-Schnittstelle verwendet. Sie enthält Schaltflächen für die Snap-Installation, das Senden einer Testtransaktion, das Festlegen der Nutzerdringlichkeit, das Umschalten von Gaspreisbenachrichtigungen und einen Dark-Mode-Umschalter. Sie ist sehr einfach und für jeden Nutzer leicht zu bedienen.
Was sind die nächsten Schritte, wenn ihr das umsetzen wollt?
Es gibt noch viel zu tun: Wir können damit beginnen, das Modell zuverlässiger zu machen, indem wir den Lernalgorithmus anpassen, um robustere Vorhersagen zu erzielen. Ein weiterer Verbesserungsbereich ist der Dringlichkeitsschwellenwert, bei dem wir einen dynamischeren Ausdruck entwickeln müssen, der gleichzeitig breite Variationen des Marktprofils, der Nutzerdringlichkeit und der Transaktions-Gaseinsparungen berücksichtigt und schnell einen nahezu optimalen Zeitpunkt für die Zahlung ermittelt. Außerdem müssen wir die Web-Oberfläche etwas benutzerfreundlicher gestalten und eine allgemeine Fehlerbehandlung für einige seltene Randfälle hinzufügen.
Könnt ihr uns ein wenig über euch und euer Team erzählen?
Wir sind ein Team aus acht BTech-Ingenieurstudenten am IIT Patna. Wir haben das Team gegründet, um am Inter IIT Tech Meet 11 (2023) teilzunehmen, bei dem Consensys eine MetaMask Snaps-Problemstellung eingebracht hat.
Vaishakh: Ich bin ein Student im letzten Jahr des Informatikstudiums am IIT Patna und liebe mein Fachgebiet. In letzter Zeit nehme ich an Hackathons teil und genieße die Erfahrung sehr. Ich freue mich darauf, die vielfältigen Möglichkeiten der Informatik weiter zu erkunden und zu sehen, wohin sie mich in der Zukunft führen wird.
Aritra B.: Aritra ist ein BTech-Student im zweiten Jahr im Bereich KI und Data Science am Indian Institute of Technology, Patna, und begeistert von Blockchain und ihren Anwendungen in der realen Welt. Er hat zuvor an einer Reihe kleinerer Blockchain-Projekte gearbeitet, die ihm die Grundlagen für das Lernen und Erkunden dieses Bereichs gelegt haben. Sein Ziel ist es, intelligente Blockchain-Lösungen zu entwickeln, die andere Bereiche der Informatik wie maschinelles Lernen nutzen, um neue Innovationen zu schaffen. Er wurde 2019 als KVPY-Fellow vom renommierten Indian Institute of Science (IISC) ausgewählt und beschäftigt sich derzeit mit ZK EVMs und deren einzigartigen Anwendungsbereichen in diesem Umfeld.
Padmaksh: Er studiert BTech in Informatik und Ingenieurwesen am Indian Institute of Technology Patna und hat ein ausgeprägtes Interesse an Cybersicherheit. Er interessiert sich auch sehr für Problemlösung und algorithmische Rätsel. Er vertieft sein Wissen über Blockchain-Architektur und erkundet weitere Fachgebiete.
Kartikay: Bachelorstudent am IIT Patna im Studiengang Maschinenbau, derzeit im dritten Studienjahr. Er hat ein ausgeprägtes Interesse an Webentwicklung und kompetitivem Programmieren. Er hat mehrere Websites für verschiedene Hochschulclubs und -veranstaltungen entworfen und entwickelt. Er verfügt über Grundkenntnisse in Data Science und Web3.
Harsh: Ich bin ein Student im zweiten Jahr am IIT Patna im Studiengang Chemieingenieurwesen. Ich beschäftige mich hauptsächlich mit Fallstudien und Problemlösung.
Dhushyanth: Ich bin ein Student im letzten Jahr des Elektrotechnikstudiums am IIT Patna und sehr begeistert von Technologie und Entwicklung. Ich habe mich in verschiedenen Bereichen ausprobiert, von der CRDT-Server-Implementierung in Rust bis hin zum Design von Perceptrons in Silicon Photonics. Ich führe gerne lebhafte Diskussionen über alles, wozu ich etwas beitragen kann, und genieße das sehr!
Vishwas S: Vishwas ist ein Informatikstudent im ersten Jahr am IIT Patna, der leidenschaftlich für sein Fachgebiet ist und nach Möglichkeiten sucht, es zu erkunden. In letzter Zeit hat er ein ausgeprägtes Interesse an der Blockchain-Technologie entwickelt und arbeitet in diesem Bereich.
Ankur: Ich bin ein Student im zweiten Jahr am IIT Patna im Studiengang Elektro- und Elektronikingenieurwesen. Ich habe kürzlich einige Websites für das IIT Patna entwickelt und genieße das Lösen von Problemen. In letzter Zeit begeistere ich mich für UI und UX mit einem Faible für Frontend. Ich beschäftige mich gerne mit menschlicher Psychologie und arbeite daran, Lösungen für verschiedene Probleme zu entwickeln.
Wann seid ihr zum ersten Mal mit MetaMask Snaps in Berührung gekommen und wie war eure Erfahrung?
Wir wurden zum ersten Mal beim Inter IIT Tech Meet 2023 mit MetaMask Snaps bekannt gemacht. Es ist eine wirklich einzigartige und interessante Erweiterung für MetaMask und kann genutzt werden, um endlose Anpassungen am Wallet vorzunehmen. Der Entwicklungsprozess ist ebenfalls recht unkompliziert, und wir hatten keine größeren Rückschläge bei der Entwicklung, obwohl weniger Dokumentation und Inhalte in Diskussionsforen verfügbar waren. Obwohl es sich noch in der Entwicklung befindet und derzeit einige wichtige Funktionen fehlen, können wir bereits das große Potenzial erkennen, das es in den kommenden Jahren haben wird.
Was unterscheidet MetaMask Snaps von anderen Wallets?
MetaMask Snaps ist vergleichbar mit einer Erweiterung in einem Webbrowser. Es wird verwendet, um die Funktionalitäten von MetaMask zu erweitern. Es ist sicher, da die Snaps in einer isolierten Umgebung ausgeführt werden, in der sie Zugang zu einem begrenzten Satz von Funktionen haben, der durch die vom Nutzer bei der Installation erteilten Berechtigungen bestimmt wird. Es ist eine großartige und sichere Möglichkeit, das Wallet-Erlebnis anzupassen.
Erzählt uns, wie es für euch und euer Team ist, MetaMask Snaps zu entwickeln.
Es ist eines der Projekte, das uns gezeigt hat, wie verschiedene Bereiche der Informatik zusammenarbeiten können, um eine Herausforderung zu lösen. Für mein Team und mich war die Entwicklung dieses Snaps eine fantastische Lerngelegenheit. Wir haben gelernt, wie wir unsere Idee effektiv umsetzen und wie wir maschinelles Lernen einsetzen können, um ein Problem auf der Blockchain zu lösen. Unterwegs haben wir auch einige neue Kontakte geknüpft. Auf der anderen Seite fühlen sich andere Wallets für Entwickler ziemlich einschränkend an.
Was bedeutet MetaMask Snaps für euch?
MetaMask Snaps fügt einem Krypto-Wallet die Funktionen von Erweiterungen hinzu. Es ist wirklich innovativ und kann für viele wichtige Anwendungsfälle genutzt werden, um die Massenadoption von Kryptowährungen zu fördern.
Welche Möglichkeiten seht ihr bei MetaMask Snaps und die Chancen, die es für den Web3-Bereich eröffnet?
MetaMask Snaps kann wirklich ein Durchbruch im Web3-Ökosystem sein, da es ein einfaches Ethereum-Wallet in ein umfassendes Web3-Management-Tool verwandelt, mit dem wir unser Web3-Erlebnis anpassen und verbessern können.
Habt ihr Ratschläge für Entwickler, die MetaMask Snaps ausprobieren möchten? Beginnt mit dem Lesen der Dokumentation. Sie ist sehr ausführlich und kann die meisten denkbaren Anwendungsfälle erklären. Bei Problemen, deren Lösung nicht offensichtlich ist, empfehlen wir, diese im Consensys Discord zu stellen, wo es ein eigenes Forum für diesen Zweck gibt.
Halte bei unserem Team Ausschau beim nächsten Hackathon in deiner Nähe! Happy BUIDLing ⚒️
Haftungsausschluss: MetaMask Snaps werden in der Regel von Drittanbietern entwickelt, die nicht zu Consensys Software gehören. Die Nutzung von MetaMask Snaps, die von Drittanbietern entwickelt wurden, erfolgt nach eigenem Ermessen und auf eigenes Risiko, und du stimmst zu, dass du allein für alle Verluste oder Schäden verantwortlich bist, die aus solchen Aktivitäten resultieren. Consensys gibt keine ausdrücklichen oder stillschweigenden Garantien, weder mündlich noch schriftlich, in Bezug auf von Drittanbietern entwickelte MetaMask Snaps und lehnt jegliche Haftung für von Drittanbietern entwickelte Snaps ab. Die Nutzung von Blockchain-bezogener Software birgt Risiken, die du bei der Verwendung von MetaMask Snaps vollständig übernimmst.
Abonnieren Sie Alpha und erhalten Sie Markt-Alpha direkt in Ihr Postfach
KI-übersetzt. Kann Fehler enthalten. Bitte überprüfen Sie die Informationen stets.
Bewerten Sie die Übersetzung
Dieser Artikel wurde verfasst von:
MetaMask
MetaMask, ehemals Consensys Software Inc, ist die weltweit größte Self-Custody-Finanzplattform und bietet Menschen einen zentralen Ort, um ihr Geld in Krypto- und traditionellen Vermögenswerten zu verwahren, auszugeben, zu sparen und zu vermehren. Das Unternehmen entwickelt die Verbraucherplattform, auf der all das stattfindet, und vereint Zahlungen, Sparen, Investieren und digitale Assets in einem nahtlosen Erlebnis. Ausgehend von der weltweit meistgenutzten Self-Custody-Wallet gibt MetaMask Nutzern die direkte Kontrolle über ihr Geld und ihre Vermögenswerte – mit einer Reichweite in rund 190 Ländern. MetaMask hat seit 2016 eine grundlegende Rolle beim Wachstum von Ethereum gespielt. Heute steht MetaMask im Mittelpunkt der Blockchain-Wirtschaft, entwickelt das Betriebssystem für Open Money und gibt Menschen die volle Kontrolle über ihr finanzielles Leben.