Introduction facile au développement web3 basé sur Ethereum avec FMZ

Auteur:Le petit rêve, Créé à: 2023-03-28 13:32:48, Mis à jour à: 2023-09-18 20:27:13

[TOC] Je vous en prie.

img

Le tutoriel EtherEase avec FMZ

Introduction facile au développement web3 basé sur Ethereum avec FMZ

Ethereum est une plateforme de contrats intelligents basée sur la technologie blockchain qui offre une façon décentralisée d'écrire et de déployer des contrats intelligents. Les contrats intelligents sont des programmes informatiques spéciaux qui peuvent être exécutés automatiquement sur la blockchain et peuvent réaliser toutes sortes de logiques commerciales sans avoir besoin de faire confiance à un tiers.

Les inventeurs de la plateforme de négociation quantitativeFMZ.COMLa plate-forme offre une API facile à utiliser qui permet aux développeurs d'interagir plus facilement avec la blockchain Ethereum et son écosystème.

Utiliser les exemples de ce tutorielJavaScriptÉcrire des langues, tester des environnementsLe réseau EthereumRéseau de test de GoerliVous pouvez également consulter la documentation API de la plateforme FMZ pour voir les interfaces API utilisées dans le tutoriel, ainsi que les descriptions et les exemples de code.


FMZ est utilisé pour l'entrée

Avant d'apprendre à utiliser la plateforme de trading quantitative FMZ, nous devons nous familiariser avec quelques concepts de base:

L'architecture de la plateforme de négociation quantitative FMZ

Le site officiel de la plateforme de trading quantitative FMZhttps://www.fmz.comUne fois enregistré, vous pouvez utiliser toutes les fonctionnalités de la plate-forme. Le site FMZ est l'administrateur du système entier, les programmes écrits par l'utilisateur sont en fait exécutés sur l'hôte. L'hôte peut déployer ce logiciel sur divers appareils, tels que serveurs, ordinateurs, etc. Lorsque l'utilisateur écrit un bon programme sur le site FMZ pour créer un exemple d'exécution, la plate-forme FMZ communique avec l'hôte et lance un exemple de programme sur l'hôte.

img

2 - Le gestionnaire

Si vous voulez exécuter une instance de programme, vous devez déployer un hôte, qui est également très simple à déployer, avec des tutoriels de déploiement sur la plate-forme. Vous pouvez également déployer automatiquement un serveur loué au nom de FMZ à l'aide du "hôte de déploiement en un clic" fourni sur FMZ.

  • Déployer un hôte sur un appareil personnel

    Les programmes administrateurs peuvent être déployés sur des appareils tels que des serveurs, des ordinateurs personnels, etc. Les principales étapes du déploiement sont les suivantes:

    1° Connectez-vous ou ouvrez le périphérique sur lequel vous souhaitez déployer un programme hôte, par exempleConnectez-vous au serveurOu alorsOuvrez l'ordinateur et accédez au système d'exploitationJe ne sais pas. 2, télécharger la version correspondante du programme d'administration (selon le système d'exploitation de l'appareil), télécharger la page:https://www.fmz.com/m/add-node img3° Le téléchargement est un paquet de compression qui doit être décompressé. 4° exécutez ce programme administrateur, un programme administrateur appelérobotLe fichier exécutable de l'application. Configure l'adresse de communication de l'administrateur, qui est unique pour chaque compte FMZ.https://www.fmz.com/m/add-nodeLa page peut voir son adresse (c'est-à-dire./robot -s node.fmz.com/xxxxxCette chaîne d'adresses, ici.xxxxxLe contenu de l'emplacement est différent pour chaque compte FMZ). Enfin, vous devez entrer le mot de passe de votre compte FMZ, le configurer et exécuter le programme d'administration.

  • Utilisation de la fonctionnalité de déploiement d'hôtes en un clic de la plateforme FMZ

    Une page d'administrateur a été ajoutée à la plateforme FMZ, à l'adresse:https://www.fmz.com/m/add-node

    img

Les outils de débogage

La plateforme de trading quantitative FMZ offre un outil de débogage gratuit, qui prend en charge les opérations de débogage.JavaScriptTypeScriptLe site est le suivant:https://www.fmz.com/m/debugLe débogage peut être utilisé pour tester, apprendre et apprendre pendant l'école primaire. Le débogage n'est pas différent de la création d'exemplaires, sauf qu'il est limité à 3 minutes.

UtilisationTypeScriptDans les langues, il faut écrire la première ligne du code.// @ts-checkPour passer àTypeScriptLe mode, ne pas basculer par défautJavaScriptLa langue.

Les échanges

Sur FMZ, "échange" est un concept générique qui, pour l'échange CEX, désigne une configuration de compte d'échange spécifique. Pour le web3, l'échange désigne une information de configuration contenant l'adresse des nœuds, la configuration de la clé privée.

Il y a aussi des sites de téléchargement de vidéos sur les réseaux sociaux.https://www.fmz.com/m/add-platformLe site Web de l'échange est une page qui permet de configurer l'information de l'échange, où l'échange est un concept général.

img

SélectionWeb3Vous pouvez configurer l'adresse des nœuds RPC ou la configuration de la clé privée en cliquant sur "Enregistrer des informations sensibles en utilisant une clé privée indépendante" en bas à droite.

Les nœuds peuvent être construits eux-mêmes ou fournis par des serveurs de nœuds.InfureAprès l'enregistrement, vous pouvez voir l'adresse du nœud de votre compte.Rpc AddressDans le cadre de la configuration de l'échange, les étiquettes peuvent se nommer pour distinguer les objets de l'échange.

img

Dans le dessinhttps://mainnet.infura.io/v3/xxxxxxxxxxxxxIl s'agit de l'adresse du nœud RPC de l'ETH du réseau principal privé d'Infura.


Interagir avec FMZ et Ethereum

在部署好托管者程序、配置好交易所对象的前提下,就可以使用FMZ.COM的「调试工具」进行测试了。调用以太坊RPC方法和以太坊交互,除了本章节列举介绍的几个RPC方法,其它RPC方法可以查询资料了解,例如https://www.quicknode.com/docs

Voici quelques exemples simples pour commencer par les bases. Il existe différentes manières d'accéder au web3 pour les langages et les outils:

img

Les appels aux méthodes RPC sur FMZ sont également enveloppés, ces fonctionnalités sont enveloppées dans les fonctions API de FMZ.exchange.IOLe mode d'appel est:exchange.IO("api", "eth", ...)Le premier paramètre est le flux fixe."api"Le deuxième paramètre est le flux fixe."eth"Les autres paramètres dépendent de la méthode RPC utilisée.

Nous avons utilisé la plateforme FMZ pour exporter des informations.LogLa fonctionLogLes fonctions peuvent entrer plusieurs paramètres et les exécuter dans la zone des journaux de la page "Outils de débogage" ou "Disque dur" de la plate-forme FMZ, où la page "Outils de débogage" sera le principal outil de test.

eth_getBalance

Pour Ethereumeth_getBalanceUne méthode utilisée pour rechercher le solde d'ETH d'une adresse sur Ethereum nécessite la transmission de deux paramètres.

  • L'adresse à consulter.
  • Les étiquettes utilisent généralement "latest".

Nous allons consulter le fondateur d'Ethereum.V神L'adresse du portefeuille ETH, connue pour être:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

function main() {
    let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
    Log("ethBalance:", ethBalance)
}

Vous avez déployé un hôte (figure: linux/amd64...) et configuré un objet d'échange (figure: Web3 test), et vous avez testé le code dans le débogage:

img

Cliquez sur le bouton "Exécuter" pour exécuter ce code et vous obtiendrez le résultat:

Le bilan est le suivant: 0x117296558f185bbc4c6

LogLa fonction est imprimée.ethBalanceLa valeur de la variable est:0x117296558f185bbc4c6, est le type de chaîne ─ ouiLe solde de l'ETH à 16 chiffresJe vous en prie.weiLe nombre d'unités1e18 weiest égal à 1.ETHAinsi, il est nécessaire de les convertir pour qu'ils deviennent des équilibres décimaux d'ETH.

Je vaisethBalanceLes données sont converties en données lisibles:

function main() {
    let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
    Log("ethBalance:", ethBalance)
    
    // 将ethBalance转换为可读的数据
    let vitalikEthBalance = parseInt(ethBalance.substring(2), 16) / 1e18
    Log("vitalikEthBalance:", vitalikEthBalance)
}

img

En hauthttps://etherscan.io/Il y a une question:

img

Cependant, la raison en est que les problèmes de précision de la langue elle-même peuvent être déformés, et la plateforme FMZ a donc deux fonctions intégrées pour traiter les données:

  • Big:Int convertit une chaîne à 16 chiffres en un objet BigInt.
  • BigDecimal: convertissez les objets de type numérique en objets BigDecimal qui peuvent être utilisés.

Le code a été modifié:

function main() {
    let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")

    // ETH的精度单位为1e18
    let ethDecimal = 18
    Log("vitalikEthBalance:", Number((BigDecimal(BigInt(ethBalance)) / BigDecimal(Math.pow(10, ethDecimal))).toString()))
}

Le bilan est de 5149,6244846875215.

eth_chainId

eth_chainIdetnet_versionLes deux fonctions renvoient l'id de la chaîne de blocs à laquelle le nœud RPC actuel a accès, la différence étant:net_versionIl est possible de modifier l'id de l'image en utilisant des paramètres.eth_chainIdIl est possible de modifier l'id d'un système à 16 chiffres.

Nom du réseau correspondant à la chaîne Id

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

img

Utiliser le réseau de test Ethereum bien configurégoerliLes tests de nœuds:

function main() {
    let netVersionId = exchange.IO("api", "eth", "net_version")
    let ethChainId = exchange.IO("api", "eth", "eth_chainId")

    Log("netVersionId:", netVersionId)
    Log("ethChainId:", ethChainId, " ,转换:", parseInt(ethChainId.substring(2), 16))
}

img

prix du gaz eth_gas

Appeléeeth_gasPriceMétode qui demande à la chaîne actuellegas price

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, " ,转换:", toAmount(gasPrice, 0))
}

Ici, nous écrivons une fonction qui convertit une chaîne de 16 chiffres en une opération qui permet de lire une valeur numérique:toAmountIl faut aussi noter que l'unité de prix du gaz est:weiDonc, on peut faire une figure de semence.decimalsLa valeur du paramètre réel correspondant est 0.

Le nombre de blocs

eth_blockNumbePour demander la hauteur d'un bloc.

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))
}

Les outils de débogage fonctionnent:

img

https://etherscan.io/Les requêtes:

img

eth_getBlockByNumber

Vous pouvez consulter les informations sur les blocs.

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)
    
    // 由于Log输出的内容过多,会自动截断,所以遍历返回的区块信息各个字段,逐个打印
    for (let key in blockMsg) {
        Log("key:", key, ", val:", blockMsg[key])
    }
}

Les informations suivantes peuvent être obtenues en les exécutant dans les outils de débogage:

img


Lire les informations du contrat

Il existe de nombreuses applications de contrats intelligents sur Ethereum.ENSIl y a aussi des gens qui se disent que c'est une bonne chose.ENSL'Ethereum Name Service est un service décentralisé de résolution de noms de domaine basé sur la blockchain Ethereum. Souvenez-vous que dans le tutoriel, nous avons consulté l'exemple du solde du portefeuille de Dieu V, le fondateur d'Ethereum?0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045Mais comment pouvons-nous connaître cette adresse?ENSLes contrats intelligents, avec un nom intuitifvitalik.ethIl y a aussi des gens qui ont besoin d'aide pour se renseigner sur le nom de Dieu.

Les éléments suivants sont utilisés dans l'environnement d'Ethereum selon les termes suivants:ENSLa documentation est connue pour nécessiter des recherches sur les noms de domaine Ethereum.Hashing NamesPour le faire, utilisez le code suivant:vitalik.ethLe nom est en cours de traitement.

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))
    }
}

Dans l'exemple de code ci-dessus, nous voyons une autre fonction étrange.EncodeCette fonction est une fonction API de la plateforme FMZ, spécialement conçue pour effectuer des opérations d'encodage sur la plateforme FMZ.

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)

Utilisation selon la description dans la documentation ENSsha3.keccak256L'algorithme traite les données.

AppeléenameHashLes fonctions, par exemple:Log(nameHash("vitalik.eth"))Vous pouvez:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835Il faut ajouter le préfixe "0x".0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835Il s'agit d'un contrat intelligent créé par l'ENSresolverParamètres de la méthode.

let ensNode = "0x" + nameHash("vitalik.eth")    // 准备好调用resolver方法的参数ensNode

En consultant les documents d'ENS, vous pouvez voir que l'adresse du contrat de l'application ENS Smart Contract est:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1eLe gouvernement a décidé d'utiliser les contrats intelligents.resolverNous avons besoin d'un contrat pour préparer notre approche.ABI

Enregistré ABI

Il y a des gens qui apprennent à venir ici et qui demandent ce qu'est un contrat intelligent.ABIJe ne sais pas.

ABI,即应用程序二进制接口(Application Binary Interface),是智能合约与外部世界进行通信的接口标准。
智能合约的 ABI 定义了合约的函数接口、参数类型、返回值等信息,以及调用合约的方式和参数传递方式等规范。

智能合约的 ABI 通常以 JSON 格式存储,包含以下信息:

合约的函数接口:函数名、参数列表、返回值等信息。
函数参数类型:如 uint256、bool、string 等。
函数的输入参数和输出参数的编码方式:智能合约使用一种称为 Solidity ABI 的编码方式来编码函数的输入参数和输出参数,
以便与以太坊网络进行交互。
在以太坊网络中,使用智能合约的 ABI 来调用合约的函数。当需要调用合约函数时,需要提供函数名和函数参数,以及将函数参数按照 ABI 编码方式编码后的字节码。
以太坊节点会将这些信息打包成一笔交易,并将交易发送到以太坊网络中执行。

智能合约的 ABI 在 Solidity 语言中可以通过 interface 关键字来定义。以太坊开发工具如 Remix IDE、Truffle 等也提供了 ABI 编辑和生成工具,
使得开发者可以方便地创建和使用智能合约的 ABI。

On peut extraire l'ABI de l'ENS.resolverUne partie de la méthode peut également être utilisée avec une ABI complète.https://etherscan.io/Vous pouvez consulter l'ABI du contrat ou l'obtenir par d'autres moyens (par exemple: documentation relative au projet).

img

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"}]`

Nous allons apprendre une nouvelle façon d'appeler sur la plateforme FMZ.exchange.IO("abi", address, abiContent)Il y a aussi des sites de rencontres en ligne qui permettent de s'inscrire à l'ABI.addressLes paramètres sont l'adresse du contrat intelligent.abiContentLes paramètres sont les contrats intelligents correspondants 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 是在以太坊主网上部署的ENS智能合约的地址

Comment appeler un contrat intelligent

Vous pouvez ensuite appeler le contrat intelligent ENS.resolverLa méthode est là, la méthode est de retourENS: Public ResolverL'adresse du contrat est la suivante:

img

let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)

UtilisationENS: Public ResolverLe contrataddrComment obtenir l'adresse du portefeuille de V?ENS: Public ResolverLes contrats doivent toujours être enregistrés ABI.https://etherscan.io/Je suis désolée.

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)

img

Dernier appelENS: Public ResolverLe contrataddrLa méthode, les paramètres sont toujoursensNode

let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)

La fonction log est produite par:

img

vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045

Le code complet pour appeler l'ENS

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() {
    // 计算名称
    let ensNode = "0x" + nameHash("vitalik.eth")

    // 注册ENS合约
    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)
    
    // 注册ENS Public Resolver合约
    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)
}

Envoyer de l'ETH

Dans les chapitres précédents, nous avons appris comment configurer une clé privée, et comment savoir si cette clé privée correspond à une adresse de portefeuille pour un objet d'échange configuré?exchange.IO("address")La fonction obtient la clé privée de la configuration correspondant à l'adresse du portefeuille.

En raison de l'utilisation des éléments suivants dans ce chapitre:GoerliJe vais essayer d'utiliser un environnement Web, donc le nœud que j'utilise est le suivant:https://goerli.infura.io/v3/*******Les adresses des nœuds que l'infura attribue à chaque utilisateur enregistré sont différentes.*******Le contenu est masqué.

function main() {
    let walletAddress = exchange.IO("address")
    Log("测试网 goerli 钱包地址:", walletAddress)
}

img

Une fois que vous connaissez votre adresse de portefeuille, vous pouvez utiliser la méthode RPC d'Ethereum.eth_getTransactionCountLe nombre de transactions pour l'adresse de votre portefeuille. Dans Ethereum, ce nombre est très courant, car il est nécessaire de le saisir pour effectuer un virement.nonceParamètres, dans Ethereum, nonce est utilisé pour s'assurer que chaque transaction est unique. C'est un nombre croissant qui s'ajoute automatiquement à chaque fois qu'une nouvelle transaction est envoyée. Par conséquent, lorsque vous envoyez une transaction à un contrat intelligent, vous devez fournir un nonce pour vous assurer que la transaction est unique et dans le bon ordre.

https://goethereumbook.org/en/

img

Il y a une version de Go dans le référentiel Ethereum.PendingNonceAtLa fonction est en fait appelée.eth_getTransactionCountLes méthodes. Dans les cours précédents, nous avons également appris comment appeler la méthode RPC, et nous l'utilisons à nouveau ici.exchange.IO("api", "eth", ...)Les fonctions.

function toAmount(s, decimals) {
    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}

function main() {
    let walletAddress = exchange.IO("address")
    Log("测试网 goerli 钱包地址:", 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 = exchange.IO("api", "eth", "eth_getTransactionCount", walletAddress, "pending")
    Log("钱包地址:", walletAddress, "当前的 nonce:", nonce, ",转换为10进制:", toAmount(nonce, 0))
}

Avant d'expliquer les opérations de transfert, nous avons simplement compris quelques concepts qui consomment un certain nombre de jetons d'ETH lors d'un transfert sur Ethereum (en tant que frais de gaz). Ce coût de gaz est déterminé par deux paramètres:

  • prix du gaz

    Cependant, le prix du carburant sur le réseau Ethereum fluctue toujours en fonction de la demande du marché et de ce que les utilisateurs sont prêts à payer, de sorte qu'écrire un prix fixe du carburant dans le code n'est parfois pas une option idéale.eth_gasPriceLa méthode qui permet d'obtenir le prix moyen du gaz.

  • Limite de gaz

    La limite de gaz d'un transfert standard d'Ethereum est de 21000 unités.

Je comprends.noncegasPricegasLimitCes concepts peuvent être testés. Une fonction de transfert enveloppée dans FMZ est très simple et facile à utiliser.

exchange.IO("api", "eth", "send", toAddress, toAmount)

Les utilisateurs de Twitter ont été informés de la disparition de leur compte.exchange.IOLe troisième paramètre est écrit comme "send".toAddressLe paramètre est l'adresse à laquelle l'ETH est reçu lors du transfert.toAmountLa quantité d'ETH transférée.

noncegasPricegasLimitCes paramètres peuvent être utilisés sur FMZ avec les valeurs que le système obtient automatiquement par défaut.

exchange.IO("api", "eth", "send", toAddress, toAmount, {gasPrice: 5000000000, gasLimit: 21000, nonce: 100})

Ensuite, nous transférons une certaine quantité d'ETH vers une adresse sur le goerli du test:

function toInnerAmount(s, decimals) {
    return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}

function main() {
    let walletAddress = exchange.IO("address")
    Log("测试网 goerli 钱包地址:", walletAddress)

    let ret = exchange.IO("api", "eth", "send", "0x4D75a08E870674E68cAE611f329A27f446A66813", toInnerAmount(0.01, 18))
    return ret    // 返回Transaction Hash : 0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
}

C'est parce que l'unité de la quantité de virements sur Ethereum estweiVous devez utiliser une fonction personnalisée.toInnerAmountTraiter commeweiLe nombre d'unités.

Danshttps://etherscan.io/Pour consulter le transaction hash ci-dessus:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e

img

Vous pouvez également écrire des requêtes de code pour transférer des hachages.0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e, utilisationeth_getTransactionReceiptComment faire une requête?.

function main() {
    let transHash = "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e"
    let info = exchange.IO("api", "eth", "eth_getTransactionReceipt", transHash)
    return info
}

Résultats de recherche:

{
	"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": []
}

Chaque champ est décrit comme suit:

blockHash - 该交易所在区块的哈希值
blockNumber - 以十六进制编码的该交易所在区块的块号
contractAddress - 如果是合约创建,该合约的地址;否则为null
cumulativeGasUsed - 该交易在区块中执行时使用的总燃气量
effectiveGasPrice - 每单位燃气的总基础费用加小费
from - 发送者的地址
gasUsed - 该特定交易使用的燃气量
logs - 生成该交易的日志对象数组
  address - 生成该日志的地址
  topics - 0到4个32字节索引日志参数的数据数组。在Solidity中,第一个主题是事件签名的哈希值(例如Deposit(address,bytes32,uint256)),除非你使用匿名说明符声明该事件
  data - 日志的32字节非索引参数
  blockNumber - 该日志所在区块的块号
  transactionHash - 该日志创建时的交易哈希值。如果该日志处于待定状态,则为null
  transactionIndex - 该日志创建时的交易索引位置。如果该日志处于待定状态,则为null
  blockHash - 该日志所在区块的哈希值
  logIndex - 该日志在区块中的索引位置,以十六进制编码的整数。如果该日志处于待定状态,则为null
  removed - 如果该日志已被删除,则为true,由于链重组而被删除;如果是有效的日志,则为false
logsBloom - 用于检索相关日志的布隆过滤器
status - 以十六进制编码的值,它要么是1(成功),要么是0(失败)
to - 接收者的地址。如果是合约创建交易,则为null
transactionHash - 该交易的哈希值
transactionIndex - 以十六进制编码的该交易在区块中的索引位置
type - 值的类型

Appeler les contrats intelligents Ethereum

Nous sommes dansLire les informations du contratDans ce chapitre, une méthode appelant les contrats ENS déployés sur Ethereum est utilisée pour obtenir l'adresse du portefeuille de V.ReadIl n'est pas nécessaire d'appeler ces méthodes.gasDans ce chapitre, nous allons parler de l'utilisation de certains des contrats intelligents d'Ethereum.WriteComment et comment payergasCes opérations seront validées par chaque nœud de l'ensemble du réseau ainsi que par les mineurs et changeront l'état de la blockchain.

Résultats de l'enquête

Pour les contrats ERC20, la plate-forme FMZ classe les ABI des contrats ERC20 comme étant des ABI couramment utilisés directement intégrés dans le système, en omettant cette étape de l'enregistrement des ABI.

Pour une meilleure compréhension de l'ABI, avant de l'utiliser, vous pouvez consulter l'ABI suivant pour les contrats ERC20:

[{"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":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]

Les articles suivants sont utilisés dans ce chapitre:GoerliLe site Web de l'équipe de test a été mis à jour.

Bilan de

Nous avons ensuite répété une fois de plus comment appeler les contrats.ReadLa méthode pour lire les informations sur les contrats et appeler les contrats ERC20balanceOfLes méthodes pour vérifier le solde des jetonsbalanceOfLa méthode n'a qu'un paramètre, mais n'est pas nommée, et est vue par le type comme une adresse (c'est-à-dire l'adresse du jeton interrogé). Puisque les données retournées ne sont pas en unité de jeton, des données de précision de jeton sont nécessaires pour les convertir.decimalsNous utilisons le réseau de test Ethereum.goerliLe test a été effectué en tenant compte du fait que les adresses des contrats de jetons sur différentes chaînes peuvent également être différentes.

function toAmount(s, decimals) {
    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}

function main() {
    let walletAddress = exchange.IO("address")
    
    // goerli WETH address 
    let wethAddress = "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
    // goerli LINK address 
    let linkAddress = "0x326C977E6efc84E512bB9C30f76E30c160eD06FB"

    // 由于是ERC20合约,FMZ已经内置ABI注册,所以这里不用注册ERC20 ABI
    let wethDecimals = exchange.IO("api", wethAddress, "decimals")
    let linkDecimals = exchange.IO("api", linkAddress, "decimals")

    let wethBalance = exchange.IO("api", wethAddress, "balanceOf", walletAddress)
    let linkBalance = exchange.IO("api", linkAddre

Plus de