Introducción fácil con FMZ al desarrollo web3 basado en Ethereum

El autor:Un sueño pequeño., Creado: 2023-03-28 13:32:48, Actualizado: 2023-09-18 20:27:13

[TOC] ¿Qué quieres decir?

img

EtherEase con FMZ

Introducción fácil con FMZ al desarrollo web3 basado en Ethereum

Ethereum es una plataforma de contratos inteligentes basada en la tecnología blockchain que ofrece una forma descentralizada de escribir y implementar contratos inteligentes. Los contratos inteligentes son programas informáticos especiales que pueden ejecutarse automáticamente en la cadena de bloques y pueden implementar una variedad de lógicas de negocio sin la necesidad de confiar en terceros.

El inventor de la plataforma de intercambio cuantitativoFMZ.COMLa plataforma de intercambio digital (DEX) ofrece una API fácil de usar que permite a los desarrolladores interactuar con la cadena de bloques Ethereum y su ecosistema con mayor facilidad.

Los ejemplos de este tutorialJavaScriptEscribir lenguajes y usarlos en entornos de pruebaLa red de EthereumGoerli prueba la redTambién puede consultar la documentación API de la plataforma FMZ para ver las interfaces API utilizadas en el tutorial, así como sus descripciones y ejemplos de código.


FMZ utiliza el acceso

Antes de aprender a usar la plataforma de comercio cuantitativo FMZ, necesitamos familiarizarnos con algunos conceptos básicos:

1 FMZ, la arquitectura de la plataforma de intercambio cuantitativa

En la página oficial de la plataforma de cambio de FMZhttps://www.fmz.comEl sitio web de FMZ es el terminal administrativo de todo el sistema, y los programas escritos por el usuario se ejecutan en el host. El programa del host se puede implementar en varios dispositivos, como servidores, computadoras, etc. Cuando el usuario escribe un buen programa en el sitio web de FMZ para crear una instancia de ejecución, la plataforma de FMZ se comunica con el host para iniciar una instancia de programa en el host.

img

2 El administrador

Si se quiere ejecutar una instancia de programa, se debe implementar un administrador, que también es muy simple de implementar, con tutoriales de implementación en la plataforma. También se puede implementar automáticamente con el "administrador de implementación de un solo botón" que se ofrece en FMZ en lugar de un servidor de alquiler en FMZ.

  • Implementación de administradores en dispositivos personales

    Los programas administradores pueden ser implementados en servidores, ordenadores personales, etc., siempre y cuando se asegure que la red funcione correctamente. Los principales pasos para implementar son:

    1. iniciar sesión o abrir el dispositivo para implementar el programa administrador, por ejemplo:Ingresar al servidor¿Qué es esto?Abre el ordenador y entra en el sistema operativo¿Qué es esto? 2. Descargar la versión correspondiente del programa administrador (dependiendo del sistema operativo del dispositivo), descargar página:https://www.fmz.com/m/add-node img3, el descarga es un paquete de compresión que necesita descomprimir. 4. Para ejecutar este administrador, el administrador es un programa llamadorobotLa dirección de comunicación de un administrador de configuración, que es única para cada cuenta FMZ, se puede utilizar para iniciar sesión en FMZ.https://www.fmz.com/m/add-nodeLa página puede ver su dirección (es decir,./robot -s node.fmz.com/xxxxxEsta serie de direcciones, aquí.xxxxxEl contenido de la ubicación, cada cuenta de FMZ muestra diferente) ; por último, también es necesario introducir el código de la cuenta de FMZ, para configurarlos y luego ejecutar el programa de administrador.

  • Utilizando la función de "Un solo botón para implementar administradores" de la plataforma FMZ

    En la plataforma FMZ se ha añadido una página de administradores, con la dirección:https://www.fmz.com/m/add-node

    img

3, herramientas de depuración

La plataforma de comercio cuantitativo FMZ ofrece una herramienta de depuración gratuita, que es compatible con el uso de la plataforma de intercambio.JavaScriptTypeScriptLa página es:https://www.fmz.com/m/debug, ya que la creación de una instancia de ejecución es de pago. Durante la escuela primaria, se puede usar esta herramienta de depuración para probar, aprender. La herramienta de depuración no difiere en otros aspectos de la creación de una instancia de ejecución, excepto la limitación de tiempo de ejecución de hasta 3 minutos.

UsoTypeScriptEn el lenguaje, se requiere escribir en la primera línea del código.// @ts-checkSe utiliza para cambiarTypeScriptEl patrón, no cambiar por defecto esJavaScriptEl idioma también.

4o, las bolsas

En FMZ, "intercambio" es un concepto genérico que para el intercambio CEX se refiere a una configuración de cuenta de intercambio específica. Para web3, este intercambio se refiere a una información de configuración que contiene la dirección del nodo, la configuración de la clave privada.

En la plataforma FMZ, el usuario puede acceder a la información en la siguiente forma:https://www.fmz.com/m/add-platformEn la página, se puede configurar la información de los intercambios, donde los intercambios son conceptos generales.

img

SelecciónWeb3Para configurar la dirección de los nodos RPC y configurar la clave privada, puede hacer clic en la parte inferior derecha "Encriptar información sensible con una clave privada independiente" para ver el mecanismo de seguridad.

Los nodos pueden ser construidos por ellos mismos o por un servidor de nodos.InfuraDespués de registrarse, puede ver la dirección del nodo de su cuenta. La red principal, la red de prueba también están disponibles, es más conveniente configurar esta dirección en el gráfico anterior.Rpc AddressEn el control de la etiqueta, la etiqueta puede darse un nombre para distinguir los objetos de intercambio configurados.

img

En el dibujohttps://mainnet.infura.io/v3/xxxxxxxxxxxxxLa dirección de los nodos RPC de la red ETH de la empresa privada Infura.


Interacción con FMZ y Ethereum

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

Para empezar, vamos a poner algunos ejemplos sencillos. Hay diferentes maneras de acceder a web3 para diferentes lenguajes y herramientas:

img

En FMZ también se envuelven las llamadas de métodos RPC, que están envueltas en las funciones API de FMZ.exchange.IOEl modo de llamada es:exchange.IO("api", "eth", ...)El primer parámetro es el de entrada fija."api"El segundo parámetro es la entrada fija."eth"Los otros parámetros dependen del método de RPC que se está llamando.

En la actualidad, la plataforma FMZ es la única que puede exportar información.LogLa funciónLogLa función puede ingresar varios parámetros y luego exportarlos a la zona de registro en la página de "Herramientas de depuración" o "Disco real" de la plataforma FMZ, donde la página de "Herramientas de depuración" será la principal herramienta que probaremos.

el_getBalance

El dinero de Ethereumeth_getBalanceMétodo utilizado para consultar el saldo de ETH de una dirección en Ethereum que requiere la transmisión de dos parámetros.

  • En la página web de la organización, se puede consultar la dirección.
  • Las etiquetas, que generalmente usan "latest".

Vamos a preguntar al fundador de Ethereum.V神La dirección conocida de la cartera de ETH es:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

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

Ya se ha implementado un administrador (en el gráfico: linux/amd64...) y se ha configurado un objeto de intercambio (en el gráfico: Web3 test), se ha probado el código en la herramienta de depuración:

img

Haga clic en el botón "Executar" y ejecute este código, que muestra el resultado:

EthBalance: 0x117296558f185bbc4c6

LogLas funciones se imprimen.ethBalanceEl valor de la variable es:0x117296558f185bbc4c6, es el tipo de cadena. SíSaldo de ETH en el valor de los 16 dígitos¿Qué es esto?weiEn cuanto a las unidades,1e18 weiEs igual a 1.ETHPor lo tanto, también necesita ser convertido para convertirse en un saldo decimal de ETH legible.

¿Qué es esto?ethBalanceConvierte a datos legibles:

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 la parte superiorhttps://etherscan.io/Encuestas:

img

Sin embargo, esto se debe a que el problema de la precisión del lenguaje en sí mismo puede tener desviaciones, por lo que la plataforma FMZ tiene dos funciones integradas para procesar datos:

  • Big:Int convierte una cadena de 16 dígitos en un objeto BigInt.
  • BigDecimal: Convierte objetos de tipo numérico en objetos BigDecimal operables.

El código se ha modificado:

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

El saldo de la vida es de 5149,6244846875215.

Etiqueta de la cadena

eth_chainIdynet_versionLas dos funciones devuelven el Id de la cadena de bloques a la que el nodo RPC actual accede, con la diferencia de que el valor de la función RPC es el valor de la cadena de bloques.net_versionEl número de números que se devuelve es el número decimal Id.eth_chainIdDevolver el Id de los dieciséis dígitos

Nombre de la red correspondiente a la cadena 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

Utilizando una red de pruebas de Ethereum bien configuradagoerliLas pruebas en los nodos:

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

el precio de gas

Llamadoeth_gasPriceMétodos para consultar la cadena actualgas 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))
}

Aquí estamos escribiendo una función que convierte una cadena de 16 dígitos en una operación que puede ser leída:toAmountTambién hay que tener en cuenta que la unidad de gasPrice es:weiAsí que, por ejemplo,decimalsEl valor del parámetro real correspondiente es 0.

El número de bloqueo

eth_blockNumbePara consultar la altura de los bloques.

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

La herramienta de depuración funciona en:

img

https://etherscan.io/Encuestas:

img

eth_getBlockByNumber (El bloque por número)

Encuentra información sobre el bloque.

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

En la herramienta de depuración se puede obtener la siguiente información:

img


Leer la información del contrato

En la actualidad, Ethereum cuenta con una gran cantidad de aplicaciones de contratos inteligentes.ENSEl blogger de Twitter, que también es uno de ellos, escribió:ENSEl servicio de nombres de dominio Ethereum (Ethereum Name Service) es un servicio de resolución de nombres de dominio descentralizado basado en la cadena de bloques Ethereum. ¿Recuerdan que en el tutorial consultamos el ejemplo del saldo de la cartera de V, el fundador de Ethereum?0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045Entonces, ¿cómo sabemos la dirección?ENSLos contratos inteligentes, con un nombre intuitivovitalik.ethEl nombre del dios V (vitalik) para hacer una consulta.

En este capítulo, el siguiente contenido se utiliza en el entorno de la red Ethereum, basado en:ENSSe sabe que se requiere documentación para realizar la consulta de nombres de dominio de Ethereum.Hashing NamesPara hacer esto, utilice el siguiente código:vitalik.ethEl nombre está siendo procesado.

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

En el ejemplo de código anterior, vemos otra función extraña.EncodeEsta función es una función de la API de la plataforma FMZ, que se utiliza específicamente para realizar operaciones de codificación en la plataforma FMZ. La función admite múltiples métodos de codificación y soporta múltiples algoritmos de hash.

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

Según lo descrito en la documentación ENS, el usosha3.keccak256Los algoritmos procesan los datos.

LlamadonameHashFunciones, por ejemplo:Log(nameHash("vitalik.eth"))¿Qué es lo que está sucediendo?ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835, con el prefijo "0x".0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835Los contratos inteligentes de ENSresolverLos parámetros del método.

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

La dirección del contrato para la aplicación de contratos inteligentes de ENS se encuentra en:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e¿Qué es lo que está sucediendo?resolverAntes de abordar el tema, también necesitamos preparar el contrato.ABI

Registrado en ABI

Aprender a venir aquí no puede dejar de preguntarse, ¿qué es un contrato inteligente?ABI¿Qué es eso?

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

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

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

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

Se extrae de la ABI de la ENSresolverLa parte de los métodos, también puede utilizar el ABI completo, se puede encontrar enhttps://etherscan.io/Encuentra el ABI del contrato o obtén el ABI por otros medios (por ejemplo: documentación del proyecto).

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

En este caso, vamos a aprender una nueva forma de llamar en la plataforma FMZ.exchange.IO("abi", address, abiContent)En la actualidad, la mayoría de los usuarios de Twitter están registrados en el sitio web de ABI.addressLos parámetros son las direcciones de los contratos inteligentes.abiContentLos parámetros son los correspondientes contratos inteligentes 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智能合约的地址

Cómo llamar a los contratos inteligentes

Ahora podemos llamar a los contratos inteligentes ENS.resolverEl método es el método de regreso.ENS: Public ResolverLa dirección del contrato.

img

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

UsoENS: Public ResolverEl contratoaddrMétodos para obtener la dirección de la billetera de V.ENS: Public ResolverEl contrato aún requiere registrar el ABI.https://etherscan.io/¿Qué es lo que está pasando?

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

Última llamadaENS: Public ResolverEl contratoaddrEl método, los parámetros siguen siendoensNode

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

La función Log tiene una salida:

img

vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045

El código completo para llamar a 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)
}

Envío de ETH

En los capítulos anteriores del curso hemos aprendido cómo configurar la clave privada, ¿cómo sabemos que la clave privada corresponde a la dirección de la cartera para el objeto de intercambio que se ha configurado?exchange.IO("address")La función obtiene la dirección de la billetera correspondiente a la clave privada configurada.

Debido a lo siguiente:GoerliEn el caso de la red, la red es un entorno de prueba, así que el nodo que uso es:https://goerli.infura.io/v3/*******En el caso de los usuarios registrados, infura les asigna diferentes direcciones de los nodos.*******El contenido específico está oculto.

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

img

Una vez que se conoce la dirección de su billetera, se puede usar el método RPC de Ethereum.eth_getTransactionCountEl conteo de transacciones para consultar la dirección de la billetera. En Ethereum, este conteo es muy común, en realidad, es lo que se necesita para ingresar operaciones de transferencia.nonceParámetros, en Ethereum, el nonce se utiliza para asegurarse de que cada transacción es un número único. Es un número incremental que se incrementa automáticamente cada vez que se envía una nueva transacción. Por lo tanto, cuando envías transacciones a un contrato inteligente, es necesario proporcionar un nonce para asegurarse de que las transacciones son únicas y en el orden correcto.

https://goethereumbook.org/en/

img

Aquí está el archivo de Ethereum en Go.PendingNonceAtLa función es lo que se llama.eth_getTransactionCountMétodos. En las clases anteriores también aprendimos cómo llamar al método RPC, y lo volveremos a usar aquí.exchange.IO("api", "eth", ...)La función.

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

Antes de explicar cómo funciona la transferencia, simplemente entendemos algunos conceptos que consumen ciertos tokens de ETH en la transferencia en Ethereum (como gas).

  • Gas precio

    Sin embargo, la tarifa de gas en la red Ethereum siempre fluctúa según la demanda del mercado y lo que los usuarios están dispuestos a pagar, por lo que escribir una tarifa de gas fija en el código a veces no es una opción ideal.eth_gasPriceEl método que se utiliza para obtener el precio promedio del gas.

  • GasLimit

    El límite de gas para una transferencia estándar de Ethereum es de 21000 unidades.

Ya lo entiendo.noncegasPricegasLimitEstos conceptos pueden ser probados con transferencias.

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

En la actualidad, la mayoría de los usuarios de Twitter no tienen acceso a la red social.exchange.IOEl tercer parámetro de la función se escribe fijamente como "send".toAddressLos parámetros son la dirección de ETH que se recibe en el momento de la transferencia.toAmountLa cantidad de ETH para transferir.

noncegasPricegasLimitEstos parámetros se pueden usar en FMZ con valores que el sistema obtiene automáticamente por defecto. También se puede especificar:

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

A continuación, transferimos un cierto número de ETH a una dirección en el goerli de la web de pruebas:

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
}

La cantidad de transferencias en Ethereum esweiPara ello, se necesita una función de configuración.toInnerAmountTratamiento comoweiEl valor de la unidad.

En elhttps://etherscan.io/Encuentra el hash de transacción:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e

img

También puede escribir el código de búsqueda de transferencia de hash.0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e¿Cómo se usa?eth_getTransactionReceipt¿Cómo hacer una consulta?

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

Los resultados de la búsqueda:

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

Cada campo tiene una descripción correspondiente:

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 - 值的类型

El llamado contrato inteligente de Ethereum

Estamos enLeer la información del contratoEn este capítulo se obtiene la dirección de la billetera de V de Dios mediante un ejemplo completo de cómo llamar a un contrato ENS implementado en Ethereum.ReadNo hay necesidad de llamarlos.gasEn este capítulo vamos a llamar a algunos de los contratos inteligentes en Ethereum.WriteMétodos y pagosgasEstas operaciones serán validadas por cada nodo de la red y por los mineros, y cambiarán el estado de la cadena de bloques.

En el caso de las entidades financieras:

En el caso de los contratos ERC20 (los contratos de tokens ERC20), la plataforma FMZ incluye los contratos ERC20 como ABI de uso común directamente integrados en el sistema, omitiendo este paso de registro de ABI.

Para una mejor comprensión de los ABI, antes de usarlos, vea los siguientes ABI de los contratos 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"}]

El contenido de este capítulo:GoerliLos usuarios de Twitter también pueden usar el servicio de Facebook para probar sus redes.

Saldo de la actividad

Y luego volvemos a practicar una vez más cómo llamar a los contratos.ReadEl método para leer la información de los contratos y llamar a los contratos ERC20balanceOfEl método para consultar el saldo de los tokensbalanceOfEl método tiene un solo parámetro, pero no tiene nombre, y se puede ver por el tipo como una dirección (es decir, la dirección del token consultado). Dado que los datos devueltos no están en un solo token, también se requieren datos de precisión de los tokens para intercambiarlos, la precisión de los tokens se puede calcular con contratos ERC20.decimalsMétodo de obtención. Utilizamos la red de pruebas de Ethereum.goerliPara hacer una prueba, tenga en cuenta que las direcciones de los contratos de tokens en diferentes cadenas también pueden ser diferentes.

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

Más.