[TOC]
Легкое введение в разработку web3 на базе Ethereum с FMZ
Ethereum - это платформа умных контрактов, основанная на технологии блокчейн, которая предоставляет децентрализованный способ написания и развертывания умных контрактов; умные контракты - это специальные компьютерные программы, которые могут автоматически выполняться на блокчейне и реализовывать различные бизнес-логики без необходимости доверять третьим лицам.
Изобретатели количественной платформы для торговлиFMZ.COMЭто позволяет разработчикам более легко взаимодействовать с блокчейном Ethereum и его экосистемой. Это позволяет получить доступ к централизованной бирже (DEX), получить данные о цепочке, отправить транзакции и т. д.
Использование примеров в этом урокеJavaScript
Написание языков, использование тестовых средЭфириум、Гёрли тестирует сетьВ API-документации FMZ-платформы также можно посмотреть API-интерфейсы, используемые в учебниках, а также их описания и примеры кода.
Перед тем, как научиться использовать квантовую торговую платформу FMZ, нам необходимо ознакомиться с несколькими основными концепциями:
На официальном сайте FMZhttps://www.fmz.comПосле регистрации, после входа в систему, можно использовать различные функции платформы. FMZ является администратором всей системы, и программы, написанные пользователем, фактически работают на хостере. Хостера могут быть развернуты на различных устройствах, таких как серверы, компьютеры и т. д. Когда пользователь создает рабочий экземпляр на сайте FMZ, платформа FMZ общается с хостером и запускает экземпляр программы на хостере.
Если вы хотите запустить экземпляр программы, вам нужно будет развернуть хостера, развертывание хостера также очень простое, есть инструкции по развертыванию на платформе.
Развернуть хост на персональных устройствах
Программа может быть развернута на серверах, персональных компьютерах и других устройствах, при условии, что сеть функционирует. Основные шаги в развертывании:
1. Зарегистрироваться или открыть устройство, на котором вы хотите развернуть программу администратора, например:Вход на серверИлиОткрыть компьютер и войти в операционную системуЯ не знаю.
2, загрузить соответствующую версию хостпрограммы (в зависимости от операционной системы устройства), загрузить страницу:https://www.fmz.com/m/add-node
3, загружается пакет сжатия, который требует разжатия.
4, чтобы запустить этот хост, хост - это программа под названиемrobot
Используемый файл. Конфигурируйте адрес обмена сообщениями администратора, который является уникальным для каждой учетной записи FMZ, после входа в FMZhttps://www.fmz.com/m/add-node
На странице можно посмотреть свой адрес (т.е../robot -s node.fmz.com/xxxxx
Это адресная строка, здесь.xxxxx
Содержимое местоположения, показываемое каждой учетной записью FMZ, отличается). Наконец, необходимо ввести пароль учетной записи FMZ, который необходимо настроить, после чего можно запустить администраторную программу.
Использование FMZ-платформы с функцией "Одна кнопка развертывания хостера"
Добавить страницу хозяина на платформе FMZ, адрес:https://www.fmz.com/m/add-node
FMZ Quantitative Trading Platform предоставляет бесплатный инструмент для декомпенсации, поддерживающий:JavaScript
,TypeScript
На странице написано:https://www.fmz.com/m/debug, поскольку создание экземпляров платного действия. В начальном классе можно использовать этот инструмент для тестирования, обучения. Кроме ограничения времени выполнения на 3 минуты, другие аспекты не отличаются от создания экземпляров.
ИспользованиеTypeScript
В языке, который требует написания в первой строке кода// @ts-check
Для переключения наTypeScript
По умолчанию, не переключаетсяJavaScript
Язык.
В FMZ "биржа" является общей концепцией, которая для биржи CEX означает конкретную конфигурацию учетной записи биржи. Для web3 эта биржа означает конфигурационную информацию, содержащую адрес узла, конфигурацию частного ключа.
На сайте FMZ можно посмотреть видео, сделанное в режиме онлайн.https://www.fmz.com/m/add-platform
На странице, на которой можно настроить информацию об биржах, где биржа является общей концепцией.
ВыборWeb3
Для того, чтобы установить адрес RPC-нота или установить частный ключ, нажмите в нижнем правом углу "Сохранение конфиденциальной информации с использованием независимого частного ключа" для просмотра механизма безопасности.
Нод может быть создан самостоятельно или предоставлен сервером. Нод-серверов много, например:ИнфураПосле регистрации можно посмотреть адрес своего аккаунта. Главная сеть, тестовая сеть доступны, более удобно, чтобы настроить этот адрес в графике выше.Rpc Address
В контроле.tag можно дать себе название, чтобы отличить объекты биржи, на которых они настраиваются.
На рисункеhttps://mainnet.infura.io/v3/xxxxxxxxxxxxx
Это адрес RPC-нота частной сети ETH Infura.
在部署好托管者程序、配置好交易所对象的前提下,就可以使用FMZ.COM的「调试工具」进行测试了。调用以太坊RPC方法和以太坊交互,除了本章节列举介绍的几个RPC方法,其它RPC方法可以查询资料了解,例如https://www.quicknode.com/docs。
Мы перечислим несколько простых примеров, чтобы начать с основ.
В FMZ также были завернуты вызовы методов RPC, которые были завернуты в функции API FMZ.exchange.IO
В среднем.exchange.IO("api", "eth", ...)
Первый параметр - фиксированный поток."api"
Второй параметр - фиксированный поток."eth"
Другие параметры определяются в зависимости от конкретного метода RPC.
Мы использовали платформу FMZ для вывода информации.Log
ФункцияLog
Функция может вводить несколько параметров, а затем выводить их в регионе журналов на странице FMZ "Дебютные инструменты" или "Физический диск", где страница "Дебютные инструменты" будет основным инструментом для нашего тестирования.
Эфириумeth_getBalance
Метод, используемый для запроса баланса ETH на адрес на Ethereum, требует передачи 2 параметров.
Давайте спросим у основателя Ethereum.V神
На данный момент существует только один ETH-кошелек.0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
。
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
}
Уже развернуты хостеры (изображение: linux/amd64...) и настроены объекты биржи (изображение: Web3 test), в дебаторе тестируется код:
Нажмите кнопку "Выполнить", чтобы запустить этот код, и вы увидите результат:
EthБалканс: 0x117296558f185bbc4c6
Log
Функции печатаются.ethBalance
Значение переменных:0x117296558f185bbc4c6
, это тип строки ─ даБаланс ETH с шестнадцатизначной стоимостью,wei
В частности,1e18 wei
Равно 1.ETH
Поэтому необходимо преобразование, чтобы превратиться в читаемый десятичный баланс ETH.
Это будетethBalance
Перевод данных в читаемый:
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)
}
Вверхhttps://etherscan.io/
Запрос:
Однако это объясняется тем, что в вопросах точности языка могут быть отклонения, поэтому платформа FMZ встроена в две функции для обработки данных:
Новый код:
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()))
}
ВиталикЭтБалкан: 5149.6244846875215
eth_chainId
иnet_version
Применение почти одинаковое, поэтому проверим вместе. Обе функции возвращают ID блокчейна, к которому в данный момент присоединился узел RPC, разница в том, чтоnet_version
И мы возвращаем ID десятичного порядка.eth_chainId
Возвращается шестнадцатизначный Ид.
Имя сети, соответствующее идентификатору цепи
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
Использование хорошо настроенной тестовой сети Ethereumgoerli
Ноты тестирования:
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))
}
Звонокeth_gasPrice
Метод, запрос на текущую цепочкуgas 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))
}
Здесь мы записываем функцию, которая преобразует шестнадцатизначную строку в читаемую числовую величину:toAmount
Также стоит отметить, что единицей цены на газ являетсяwei
И поэтому мы используем фигуруdecimals
Соответствующее значение реального параметра передачи может быть равно нулю.
eth_blockNumbe
Для запроса высоты блока.
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))
}
Дебютные инструменты:
https://etherscan.io/
Запрос:
Например, вы можете получить информацию о блоке.
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])
}
}
В инструменте "Дебют" вы можете получить следующую информацию:
На эфире работает множество приложений для умных контрактов.ENS
Он был одним из них.ENS
Ethereum Name Service - это децентрализованная служба анализа доменных имен, основанная на блокчейне Ethereum.
Помните, что в нашем уроке мы спрашивали примеры с балансом кошелька основателя Ethereum, Бога V?0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
Но как мы узнаем этот адрес?ENS
Умные контракты, использующие интуитивно понятные названияvitalik.eth
Например, в одном из интервью, который я читал в своем блоге, я написал, что я хочу узнать больше о жизни человека.
В этой главе мы рассмотрим следующее:ENS
Документы, которые требуются для запроса доменного имени EthereumHashing Names
Используйте следующий кодvitalik.eth
Название обрабатывается.
function nameHash(name) {
if (name == "") {
return "0000000000000000000000000000000000000000000000000000000000000000"
} else {
let arr = name.split(".")
let label = arr[0]
arr.shift()
let remainder = arr.join(".")
return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
}
}
В этом примере мы увидели еще одну необычную функцию.Encode
Функция, API-функция для платформы FMZ, предназначена для кодирования операций на платформе FMZ. Функция поддерживает множество методов кодирования и поддерживает множество хэширующих алгоритмов.
Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)
Использование в соответствии с описанием в документации ENSsha3.keccak256
Алгоритмы обрабатывают данные.
ЗвонокnameHash
Функции, например:Log(nameHash("vitalik.eth"))
В этом случае:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835
, необходимо добавить префикс "0x".0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835
В качестве интеллектуального контракта ENSresolver
Параметры метода.
let ensNode = "0x" + nameHash("vitalik.eth") // 准备好调用resolver方法的参数ensNode
В документе ENS указано, что адрес контракта на приложение ENS Smart Contract:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
‒ В связи с этим, я не могу сказать, что я не знаю, что делать.resolver
Мы должны подготовить контракт, прежде чем приступить к работе.ABI
。
Именно поэтому мы пришли сюда, чтобы узнать, что такое умные контракты.ABI
Что это?
ABI,即应用程序二进制接口(Application Binary Interface),是智能合约与外部世界进行通信的接口标准。
智能合约的 ABI 定义了合约的函数接口、参数类型、返回值等信息,以及调用合约的方式和参数传递方式等规范。
智能合约的 ABI 通常以 JSON 格式存储,包含以下信息:
合约的函数接口:函数名、参数列表、返回值等信息。
函数参数类型:如 uint256、bool、string 等。
函数的输入参数和输出参数的编码方式:智能合约使用一种称为 Solidity ABI 的编码方式来编码函数的输入参数和输出参数,
以便与以太坊网络进行交互。
在以太坊网络中,使用智能合约的 ABI 来调用合约的函数。当需要调用合约函数时,需要提供函数名和函数参数,以及将函数参数按照 ABI 编码方式编码后的字节码。
以太坊节点会将这些信息打包成一笔交易,并将交易发送到以太坊网络中执行。
智能合约的 ABI 在 Solidity 语言中可以通过 interface 关键字来定义。以太坊开发工具如 Remix IDE、Truffle 等也提供了 ABI 编辑和生成工具,
使得开发者可以方便地创建和使用智能合约的 ABI。
Вытащить ABI из ENSresolver
Часть методов, также можно использовать с полным ABI, можно использовать вhttps://etherscan.io/
Вы можете запросить ABI по контракту или получить ABI другими способами (например, документация по проекту).
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"}]`
В этой статье мы узнаем о новом способе вызова на платформе FMZ.exchange.IO("abi", address, abiContent)
В этом случае, если вы хотите зарегистрироваться в ABI, используйте этот метод.address
Параметры - это адреса смарт-контрактов.abiContent
Параметры - это соответствующие умные контракты ABI (строки).
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智能合约的地址
В следующий раз мы сможем настроить систему, которая будет называться ENS Smart Contract.resolver
Сделано. Сделано.ENS: Public Resolver
Адрес контракта.
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
ИспользованиеENS: Public Resolver
Контрактaddr
Способы получения адреса кошелька бога V.ENS: Public Resolver
Контракт по-прежнему требует регистрации ABI.https://etherscan.io/
Доступ к материалам.
let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)
Последний звонокENS: Public Resolver
Контрактaddr
Метод, параметры остаютсяensNode
。
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
Вывод функции Log:
vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045
function nameHash(name) {
if (name == "") {
return "0000000000000000000000000000000000000000000000000000000000000000"
} else {
let arr = name.split(".")
let label = arr[0]
arr.shift()
let remainder = arr.join(".")
return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
}
}
function main() {
// 计算名称
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)
}
В предыдущих главах мы уже говорили о том, как настроить частный ключ, и как мы узнаем, что этот частный ключ соответствует адресу кошелька для конфигурированного объекта биржи?exchange.IO("address")
Функция получает конфигурированный частный ключ, соответствующий адресу кошелька.
В связи с использованиемGoerli
Я использую следующие узлы для тестирования веб-среды:https://goerli.infura.io/v3/*******
Инфура распределяет различные адреса узлов для каждого зарегистрированного пользователя.*******
В частности, в Twitter появилась статья, в которой говорится, что в ней скрыто определенное содержание.
function main() {
let walletAddress = exchange.IO("address")
Log("测试网 goerli 钱包地址:", walletAddress)
}
После того, как вы узнаете свой адрес кошелька, вы можете использовать метод RPC на Эфириуме.eth_getTransactionCount
Счет транзакций для запроса адреса кошелька. В Эфириуме этот счет очень часто используется, на самом деле, это то, что нужно передать при операции по переводу.nonce
Параметры, в Ethereum nonce используется для обеспечения того, чтобы каждая сделка была уникальной цифрой. Это увеличивающееся число, которое автоматически увеличивается при каждом отправлении новой сделки. Поэтому, когда вы отправляете сделки в умные контракты, необходимо предоставить nonce, чтобы убедиться, что сделка уникальна и в правильном порядке.
Здесь вы можете увидеть, что происходит в репозитории Ethereum на языке GoPendingNonceAt
Функция, на самом деле, называетсяeth_getTransactionCount
Метод. В предыдущих уроках мы также изучали, как использовать метод RPC, и мы используем его снова.exchange.IO("api", "eth", ...)
Функция.
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))
}
Перед тем, как рассказать о том, как происходит транзакция, мы просто познакомимся с некоторыми понятиями, которые потребляют определенные токены ETH при транзакции на Ethereum (как расходы на газ).
Газовый
Тем не менее, стоимость газа в сети Ethereum всегда колеблется в зависимости от потребностей рынка и того, что пользователи готовы заплатить, поэтому фиксированная стоимость газа, записанная в коде, иногда не является идеальным вариантом.eth_gasPrice
В этом случае, если вы хотите получить среднюю цену на газ, используйте один из следующих методов:
Газовой лимит
Газовый лимит на стандартную транзакцию эфиримов составляет 21000 единиц.
Понимаю.nonce
,gasPrice
,gasLimit
Эти концепции можно протестировать. В FMZ упакованы очень простые и удобные функции перевода.
exchange.IO("api", "eth", "send", toAddress, toAmount)
Поскольку они используются в качестве перевода денег, они могут быть использованы в качестве платежных средств.exchange.IO
Третий параметр фиксируется как "send".toAddress
Параметры - это адрес, на котором получается ETH при переводе.toAmount
Количество ETH для перевода.
nonce
,gasPrice
,gasLimit
Эти параметры могут быть использованы в FMZ с помощью системного автоматического получения по умолчанию.
exchange.IO("api", "eth", "send", toAddress, toAmount, {gasPrice: 5000000000, gasLimit: 21000, nonce: 100})
Далее мы переводим определенную сумму ETH в адрес на тестовом сайте goerli:
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
}
Потому что единицей количества транзакций в Эфириуме являетсяwei
Для этого нужно использовать специальную функцию.toInnerAmount
Обработкаwei
Число в единице.
Вhttps://etherscan.io/
Например:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
。
Вы также можете написать код для запроса, передачи хештегов.0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
Использованиеeth_getTransactionReceipt
Как сделать запрос?
function main() {
let transHash = "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e"
let info = exchange.IO("api", "eth", "eth_getTransactionReceipt", transHash)
return info
}
Результаты поиска:
{
"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": []
}
Описание каждого поля:
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 - 值的类型
Мы находимсяЧитать информацию о контрактеВ этой главе приведен полный пример того, как методы вызова ENS-контрактов, развернутых на Эфириуме, получают адрес кошелька Бога V. Эти методы относятся кRead
В этом случае вы не должны использовать эти методы.gas
В этой главе мы будем называть некоторые из этих умных контрактов на Эфириуме.Write
Способы и оплатаgas
Эти операции будут проверены каждым нотом по всей сети, а также майнером, и изменят состояние блокчейна.
Для ERC20 контрактов (ERC20 token contracts) платформа FMZ включает ABI ERC20 контрактов как обычный ABI прямо в систему, без регистрации ABI.
Для более полного понимания ABI, перед тем как использовать его, вы можете посмотреть следующий ABI для 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"}]
Использование:Goerli
Проверка сетевой среды.
И затем мы повторяем еще раз, как вызвать контракт.Read
Метод чтения контрактной информации и вызова контракта ERC20balanceOf
Как узнать баланс токенов?balanceOf
Метод имеет только один параметр, но не имеет названия, который можно увидеть по типу как адрес (т. е. адрес запрошенного токона). Так как возвращенные данные не являются единицами в виде токенов, для их расчета также требуются данные о точности токенов, то точность токенов может быть определена по контракту ERC20.decimals
Метод получения. Мы используем тестовую сеть Ethereumgoerli
Проведите тестирование и обратите внимание, что в разных цепочках могут быть разные адреса контрактов на токены.
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", linkAddres