[TOC]
EtherEaseWithFMZ Tutorial
Starten Sie mit der Entwicklung von Web3 auf Basis von Ethereum mit FMZ einfach
Ethereum ist eine Smart-Contract-Plattform, die auf Blockchain-Technologie basiert und eine dezentrale Möglichkeit zum Schreiben und Bereitstellen von Smart Contracts bietet.
FMZ Quant Handelsplattform (FMZ.COM) bietet eine einfach zu bedienende API, die es Entwicklern ermöglicht, einfacher mit der Ethereum-Blockchain und ihrem Ökosystem zu interagieren.
In diesem Tutorial sind die Beispiele inJavaScript
Sprache, die Testumgebung verwendet beideEthereum-MainnetundGoerli-Testnetz. Und Sie können auch die API-Schnittstellen und zugehörigen Beschreibungen, Codebeispiele im Tutorial in FMZ Plattform
Bevor wir lernen, die FMZ Quant Trading Plattform zu nutzen, müssen wir uns mit einigen Grundkonzepten vertraut machen:
Nach der Registrierung und Anmeldung auf der offiziellen Website der FMZ Quant Trading Platform (https://www.fmz.comDie FMZ-Website ist das Management-End des gesamten Systems, und benutzergeschriebene Programme laufen tatsächlich auf dem Docker. Das Docker-Softwareprogramm kann auf verschiedenen Geräten wie Servern, Computern usw. bereitgestellt werden. Wenn ein Benutzer ein Programm schreibt und eine laufende Instanz auf der FMZ-Website erstellt, wird die FMZ-Plattform mit dem Docker kommunizieren und eine Programminstanz darauf starten.
Wenn Sie eine Programminstanz ausführen möchten, müssen Sie einen Docker bereitstellen. Die Bereitstellung des Dockers ist auch sehr einfach, und es gibt Bereitstellungsleitfäden auf der Plattform. Sie können auch die
Sie können das Docker-Programm auf Servern, PCs und anderen Geräten bereitstellen und ausführen, solange das Netzwerk normal ist (es muss auf das entsprechende Ziel zugreifen können, z. B. eine bestimmte Austauschoberfläche, Knotenadresse usw.).
robot
. Konfigurieren Sie die Docker-Kommunikationsadresse, die für jedes FMZ-Konto einzigartig ist, nach dem Anmelden bei FMZ, können Sie Ihre eigene Adresse anhttps://www.fmz.com/m/add-node
Seite (d. h../robot -s node.fmz.com/xxxxx
Diese Adresskette, wo der Inhaltxxxxx
Die Position ist für jedes FMZ-Konto unterschiedlich). Schließlich müssen Sie das Passwort Ihres FMZ-Kontos eingeben. Nachdem Sie diese Einstellungen konfiguriert haben, führen Sie das Docker-Programm aus.Verwenden Sie die Funktion
Hinzufügen einer Docker-Seite auf der FMZ-Plattform, Adresse:https://www.fmz.com/m/add-node
FMZ Quant Trading Platform bietet ein kostenloses Debugging-Tool, dasJavaScript
, TypeScript
, und die Seite lautet:https://www.fmz.com/m/debug. Weil das Erstellen von Instanzen zum Ausführen berechnet wird. Während der ersten Lernphase können Sie dieses Debug-Tool für Tests und Lernen verwenden. Außer der maximalen Laufzeit von 3 Minuten gibt es keinen Unterschied zwischen der Verwendung des Debug-Tools und dem Erstellen einer Instanz zum Ausführen.
Bei der Anwendung derTypeScript
Sprache, du musst schreiben// @ts-check
in der ersten Codezeile aufTypeScript
Modus; wenn nicht eingeschaltet, ist der StandardJavaScript
language.
Bei FMZ ist
Im eingeloggten Zustand der FMZ-Plattformhttps://www.fmz.com/m/add-platform
Seite, können Sie Austauschinformationen konfigurieren, wo der Austausch ein allgemeines Konzept ist.
AuswählenWeb3
, die RPC-Knotenadresse konfigurieren, den privaten Schlüssel konfigurieren, können Sie auf die untere rechte Ecke klicken
Knoten können selbst gebaute Knoten oder Knoten sein, die von Knotendienstleistern bereitgestellt werden.Infura. Nach der Registrierung können Sie die Knotenadresse Ihres eigenen Kontos anzeigen. Sowohl das Mainnet als auch das Testnet sind verfügbar, was sehr praktisch ist.Rpc Address
Das Etikett kann selbst benannt werden, um zwischen konfigurierten Austauschobjekten zu unterscheiden.
Auf dem Bild,https://mainnet.infura.io/v3/xxxxxxxxxxxxx
ist die private Infura ETH-Mainnet-RPC-Knotenadresse.
Nach der Bereitstellung des Docker-Programms und der Konfiguration des Exchange-Objekts können SieFMZ.COM
Für verschiedene Sprachen und Tools gibt es Möglichkeiten, auf Web3 zuzugreifen, wie auf dem Bild gezeigt:
Auf FMZ werden auch RPC-Methodenanrufe verkapselt, und diese Funktionen werden in der FMZ-API-Funktion verkapseltexchange.IO
Die Anrufmethode ist:exchange.IO("api", "eth", ...)
. Der erste Parameter ist auf"api"
, ist der zweite Parameter auf"eth"
, und andere Parameter hängen von der spezifischen aufgerufenen RPC-Methode ab.
Für Ausgabeinformationen werden wir dieLog
Die Funktion der FMZ-PlattformLog
Die Funktion kann mehrere Parameter akzeptieren und sie dann im Protokollbereich der Seite
Dieeth_getBalance
Methode von Ethereum wird verwendet, um den ETH-Guthaben einer Adresse auf Ethereum abzufragen, und diese Methode erfordert zwei Parameter.
Vitalik Buterin
Die bekannte Adresse ist:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
.function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
}
Bereits eingesetzt Docker (im Bild: linux/amd64...) und konfiguriert das Austauschobjekt (im Bild: Web3 Test), Testcode in Debugging-Tool:
Klicken Sie auf die Schaltfläche
EthBalance: 0x117296558f185bbc4c6
Dielog
Funktion druckt dieethBalance
Variablenwert:0x117296558f185bbc4c6
, was ein Zeichenfolge ist. Es istden hexadezimalen Wert des ETH-Saldosinwei
Einheiten mit1e18 wei
ist gleich 1ETH
Daher muss es in eine lesbare Dezimal-ETH-Balance umgewandelt werden.
UmwandlungethBalance
in lesbare Daten:
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
// Converting ethBalance into readable data
let vitalikEthBalance = parseInt(ethBalance.substring(2), 16) / 1e18
Log("vitalikEthBalance:", vitalikEthBalance)
}
Suche weiterhttps://etherscan.io/
:
Aufgrund des Präzisionsproblems der Sprache selbst werden jedoch Abweichungen bei dieser Art der Verarbeitung auftreten. Daher verfügt die FMZ-Plattform über zwei integrierte Funktionen für die Datenverarbeitung:
Passen Sie den Code noch einmal an:
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
// The precision unit of ETH is 1e18
let ethDecimal = 18
Log("vitalikEthBalance:", Number((BigDecimal(BigInt(ethBalance)) / BigDecimal(Math.pow(10, ethDecimal))).toString()))
}
LebensmittelhilfeBilanz: 5149,6244846875215
eth_chainId
undnet_version
Beide Funktionen geben die Id der Blockchain zurück, mit der der aktuelle RPC-Knoten verbunden ist, wobei der Unterschied darin besteht, dassnet_version
Gibt eine Dezimalnummer zurück undeth_chainId
Gibt eine hexadezimal-Id zurück.
Name des Netzes, der der Kette entspricht
1 - ethereum mainnet
2 - morden testnet (deprecated)
3 - ropsten testnet
4 - rinkeby testnet
5 - goerli testnet
11155111 - sepolia testnet
10 - optimism mainnet
69 - optimism kovan testnet
42 - kovan testnet
137 - matic/polygon mainnet
80001 - matic/polygon mumbai testnet
250 - fantom mainnet
100 - xdai mainnet
56 - bsc mainnet
Test mit dem konfigurierten Ethereum Testnetzgoerli
Knotenpunkt:
function main() {
let netVersionId = exchange.IO("api", "eth", "net_version")
let ethChainId = exchange.IO("api", "eth", "eth_chainId")
Log("netVersionId:", netVersionId)
Log("ethChainId:", ethChainId, " , conversion:", parseInt(ethChainId.substring(2), 16))
}
Rufen Sie dieeth_gasPrice
Methode zur Abfrage der aktuellengas price
auf der Kette.
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
Log("gasPrice:", gasPrice, " , conversion:", toAmount(gasPrice, 0))
}
Hier schreiben wir eine Funktion, um die Hexadezimalzeile in einen lesbaren Zahlenwert umzuwandeln:toAmount
Außerdem ist zu beachten, daß die EinheitgasPrice
istwei
, also geben Sie den Wert 0 an den realen Parameter, der dem formalen Parameter entsprichtdecimals
.
"eth_blockNumber
wird zur Abfrage der Blockhöhe verwendet.
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log(toAmount(blockNumber, 0))
}
Führen Sie das Debugging-Tool aus:
Suche weiterhttps://etherscan.io/
:
Abfrage-Blockinformationen.
function main() {
let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log(blockNumber)
let blockMsg = exchange.IO("api", "eth", "eth_getBlockByNumber", blockNumber, true)
Log(typeof(blockMsg), blockMsg)
// Due to the excessive content of Log output, it will be truncated automatically, so traverse each field of the returned block information and print them one by one
for (let key in blockMsg) {
Log("key:", key, ", val:", blockMsg[key])
}
}
Durch die Ausführung im
Viele Smart-Contract-Anwendungen laufen auf Ethereum undENS
ist einer von ihnen.ENS
, oder Ethereum Name Service, ist ein dezentraler Domain-Namen-Resolution-Dienst auf Basis der Ethereum-Blockchain.
Erinnern Sie sich an das Beispiel im Tutorial, wo wir den Saldo der Brieftasche des Ethereum-Gründers Vitalik Buterin0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
Wie können wir die Adresse wissen?ENS
Smart Contract mit einem intuitiven Namenvitalik.eth
.
Die folgenden Inhalte in diesem Kapitel verwenden die Ethereum-Mainnet-Umgebung.ENS
Unterlagen,Hashing Names
sind für die Abfrage von Ethereum-Domainnamen erforderlich. Verwenden Sie den folgenden Code, umvitalik.eth
.
function nameHash(name) {
if (name == "") {
return "0000000000000000000000000000000000000000000000000000000000000000"
} else {
let arr = name.split(".")
let label = arr[0]
arr.shift()
let remainder = arr.join(".")
return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
}
}
In dem obigen Codebeispiel sahen wir eine andere unbekannte FunktionEncode
. Diese Funktion ist eine API-Funktion der FMZ-Plattform und wird speziell für die Kodierung von Operationen auf der FMZ-Plattform verwendet.
Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)
Nach der Beschreibung im ENS-Dokument verwenden Sie diesha3.keccak256
Algorithmus zur Verarbeitung von Daten.
Rufen Sie dienameHash
Funktion, zum Beispiel:Log(nameHash("vitalik.eth"))
, können Sie:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835
, und Sie müssen das Präfix 0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835
wird als Parameter derresolver
Methode im ENS-Smart-Vertrag.
let ensNode = "0x" + nameHash("vitalik.eth") // Prepare the parameters ensNode for calling the resolver method
Nach der ENS-Dokumentation lautet die Vertragsadresse für ENS-Smart Contract-Anwendungen:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
Bevor Sie dieresolver
Wir müssen auch dieABI
des Vertrages.
Das ist eine sehr wichtige Frage.ABI
von einem intelligenten Vertrag?
ABI, or Application Binary Interface, is the interface standard for smart contracts to communicate with the external world.
The ABI of a smart contract defines the contract's function interfaces, parameter types, return values, and other information, as well as specifications for calling the contract and passing parameters.
The ABI of a smart contract is usually stored in JSON format and contains the following information:
Contract function interfaces: function names, parameter lists, return values, etc.
Function parameter types: such as uint256, bool, string etc.
Encoding methods for input and output parameters of functions: Smart contracts use an encoding method called Solidity ABI to encode input and output parameters of functions so that they can interact with Ethereum network.
In Ethereum network ,the ABI of a smart contract is used to call its functions. When you need to call a contract function, you need to provide the name of the function, its parameters, and bytecode encoded according to ABI encoding method.
Ethereum nodes will package this information into transactions and send them out on Ethereum network for execution.
In Solidity language,the keyword 'interface' can be used define ABIs for smart contracts. Ethereum development tools like Remix IDE ,Truffle also provide editing & generation tools making it easier developers create & use ABIs.
Entfernen Sieresolver
Sie können die ABI des Vertrags aufhttps://etherscan.io/
oder die ABI über andere Kanäle erhalten (z. B. relevante Projektdokumentation).
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
Hier werden wir eine neue Anrufmethode auf der FMZ-Plattform lernen,exchange.IO("abi", address, abiContent)
, die zur Registrierung von ABI verwendet wird.address
Der Parameter ist die Adresse des Smart Contracts und dieabiContent
Parameter ist der entsprechende Smart Contract ABI (String).
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver) // 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e is the address of the ENS smart contract deployed on the Ethereum mainnet
Als nächstes können Sie dieresolver
Das ENS-Smart-Contract, das die Adresse desENS: Public Resolver
contract.
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
VerwendenENS: Public Resolver
Verträgeaddr
Sie haben die Möglichkeit, die Geldbörsenadresse von Vitalik Buterin zu erhalten.ENS: Public Resolver
Die ABI-Informationen für diesen Smart Contract können immer noch vonhttps://etherscan.io/
.
let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)
Schließlich rufen Sie dieENS: Public Resolver
Verträgeaddr
Methode, wobei der Parameter immer nochensNode
.
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
Ausgabe der Log-Funktion:
vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045
function nameHash(name) {
if (name == "") {
return "0000000000000000000000000000000000000000000000000000000000000000"
} else {
let arr = name.split(".")
let label = arr[0]
arr.shift()
let remainder = arr.join(".")
return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
}
}
function main() {
// Calculate the name
let ensNode = "0x" + nameHash("vitalik.eth")
// Register ENS contract
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver)
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
// Register ENS Public Resolver contract
let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
}
In den vorherigen Kapiteln des Kurses haben wir gelernt, wie man private Schlüssel konfiguriert. Wie wissen wir, welche Wallet-Adresse diesem privaten Schlüssel für das konfigurierte Exchange-Objekt entspricht?exchange.IO("address")
Funktion, um die Wallet-Adresse zu erhalten, die dem konfigurierten privaten Schlüssel entspricht.
Die folgenden Inhalte in diesem Kapitel verwenden die Goerli-Testnet-Umgebung, also ist der Knoten, den ich verwende:https://goerli.infura.io/v3/*******
, und Infura weist für jeden registrierten Benutzer verschiedene Knotenadressen zu.*******
versteckt bestimmte Inhalte.
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
}
Nachdem Sie Ihre Wallet-Adresse kennen, können Sie Ethereumeth_getTransactionCount
In Ethereum ist diese Anzahl sehr verbreitet, und es ist eigentlich die Anzahl der Transaktionen der Wallet-Adresse.nonce
In Ethereum ist Nonce eine eindeutige Zahl, die verwendet wird, um sicherzustellen, dass jede Transaktion einzigartig ist. Es ist eine zunehmende Zahl, und sie wird automatisch jedes Mal, wenn eine neue Transaktion gesendet wird, steigen. Wenn Sie daher eine Transaktion an einen Smart Contract senden, müssen Sie eine Nonce bereitstellen, um sicherzustellen, dass die Transaktion einzigartig und in der richtigen Reihenfolge ist.
Hier, diePendingNonceAt
Die Funktion in der Ethereum-Bibliothek der Go-Sprache ruft tatsächlich dieeth_getTransactionCount
In den vorherigen Kursen haben wir auch gelernt, wie man RPC-Methoden anruft.exchange.IO("api", "eth", ...)
wieder funktionieren.
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
/**
* eth_getTransactionCount
* @param address - string - The address from which the transaction count to be checked.
* @param blockNumber - string - The block number as a string in hexadecimal format or tags.
* @returns The integer of the number of transactions sent from an address encoded as hexadecimal.
*/
let nonce: string = exchange.IO("api", "eth", "eth_getTransactionCount", walletAddress, "pending")
Log("wallet address:", walletAddress, "current nonce:", nonce, ", convert to decimal:", toAmount(nonce, 0))
}
Bevor wir den Transfervorgang erklären, verstehen wir einige Konzepte kurz. Beim Transfer auf Ethereum wird eine bestimmte Menge an ETH-Token verbraucht (als Gasgebühren). Die Gasgebühr wird durch zwei Parameter bestimmt:
Gaspreis
Allerdings schwanken die Gasgebühren im Ethereum-Netzwerk immer je nach Marktnachfrage und den Gebühren, die Benutzer bereit sind zu zahlen, so dass das Schreiben einer festen Gasgebühr im Code manchmal keine ideale Wahl ist.eth_gasPrice
Dies ist eine Methode, die wir bereits gelernt haben, um den durchschnittlichen Gaspreis zu ermitteln.
Gasgrenze
Ein Standard-Ether-Transfer hat ein Gaslimit von 21.000 Einheiten.
Nach dem Verständnis der Begriffenonce
, gasPrice
, undgasLimit
FMZ bietet eine sehr einfache und benutzerfreundliche Übertragungsfunktion.
exchange.IO("api", "eth", "send", toAddress, toAmount)
Wenn es für Übertragungen verwendet wird, ist der dritte Parameter derexchange.IO
ist als toAddress
Parameter ist die Adresse, die während der Übertragung ETH empfängt, undtoAmount
ist der übertragene ETH-Betrag.
Die Parameternonce
, gasPrice
, undgasLimit
können alle System-Standardwerte verwenden, die automatisch auf der FMZ ermittelt werden.
exchange.IO("api", "eth", "send", toAddress, toAmount, {gasPrice: 5000000000, gasLimit: 21000, nonce: 100})
Als nächstes werden wir eine bestimmte Menge ETH an eine bestimmte Adresse im Goerli-Testnetzwerk überweisen:
function toInnerAmount(s, decimals) {
return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
let ret = exchange.IO("api", "eth", "send", "0x4D75a08E870674E68cAE611f329A27f446A66813", toInnerAmount(0.01, 18))
return ret // return Transaction Hash : 0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
}
Weil die Einheit des Ethereum-Übertragungsbetrags istwei
, eine benutzerdefinierte FunktiontoInnerAmount
Der Wert inwei
units.
Hash der Abfrage:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
aufhttps://etherscan.io/
.
Sie können auch Code schreiben, um Abfrage-Transfer-Hash0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
, unter Verwendung dereth_getTransactionReceipt
Methode für Abfragen.
function main() {
let transHash = "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e"
let info = exchange.IO("api", "eth", "eth_getTransactionReceipt", transHash)
return info
}
Abfrageergebnis:
{
"cumulativeGasUsed": "0x200850",
"effectiveGasPrice": "0x1748774421",
"transactionHash": "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e",
"type": "0x0",
"blockHash": "0x6bdde8b0f0453ecd24eecf7c634d65306f05511e0e8f09f9ed3f59eee2d06ac7",
"contractAddress": null,
"blockNumber": "0x868a50",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasUsed": "0x5208",
"to": "0x4d75a08e870674e68cae611f329a27f446a66813",
"status": "0x1",
"transactionIndex": "0x23",
"from": "0x6b3f11d807809b0b1e5e3243df04a280d9f94bf4",
"logs": []
}
Beschreibung für jedes Feld:
blockHash - The hash value of the block where the transaction is located.
blockNumber - The block number of the block where the transaction is located, encoded in hexadecimal.
contractAddress - If it's a contract creation, the address of the contract; otherwise null.
cumulativeGasUsed - The total gas used when executing this transaction in the block.
effectiveGasPrice - Total base fee plus tip per unit of gas.
from - Sender's address.
gasUsed - Gas used by this specific transaction.
logs - Array of log objects generated by this transaction.
address - Address that generated this log.
topics - Data array with 0 to 4 indexed log parameters, each with 32 bytes. In Solidity, first topic is event signature hash (e.g., Deposit(address,bytes32,uint256)), unless you declare an event using anonymous specifier.
data - Non-indexed parameters for logs with length of 32 bytes.
blockNumber - The block number of the block where this log is located.
transactionHash - Transaction hash at time when log was created. Null if pending state.
transactionIndex - Index position during creation. Null if pending state.
blockHash - The hash value for containing block.
logIndex - Hexadecimal-encoded integer index position within containing block. Null if pending state.
removed - True if deleted due to chain reorganization; false for valid logs.
logsBloom - Bloom filter for retrieving related logs.
status - Hexadecimal-encoded value either being '1' (success) or '0' (failure).
to - Receiving party's address; null for contract creation transactions.
transactionHash - The hash value associated with given transaction.
transactionIndex - Hexadecimal-encoded index position within its respective containing-block.
type - Type value.
In dem Kapitel über Read
Methoden, und das Aufrufen dieser Methoden erfordert keinegas
(Erinnern Sie sich an das, was wir zuvor über Gas gesprochen haben?).Write
Methoden von intelligenten Verträgen auf Ethereum und bezahlen fürgas
Diese Operationen werden von jedem Knoten und Miner im gesamten Netzwerk verifiziert und verändern den Blockchain-Zustand.
Für den ERC20-Vertrag (ERC20-Token-Vertrag) listet die FMZ-Plattform die ABI des ERC20-Vertrags ABI als eine gemeinsame ABI direkt in das System integriert, wodurch der Schritt der Registrierung der ABI eliminiert wird.
Um ABI besser zu verstehen, können Sie es überprüfen, bevor Sie es verwenden.
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"tran