[TOC]
Tutorial EtherEaseWithFMZ
Mulakan dengan pembangunan web3 berdasarkan Ethereum menggunakan FMZ dengan mudah
Ethereum adalah platform kontrak pintar berdasarkan teknologi blockchain, yang menyediakan cara yang terdesentralisasi untuk menulis dan menggunakan kontrak pintar. Kontrak pintar adalah jenis program komputer khas yang dapat dijalankan secara automatik di blockchain dan melaksanakan pelbagai logika perniagaan tanpa perlu mempercayai pihak ketiga.
Platform Perdagangan Kuantum FMZ (FMZ.COM) menyediakan API yang mudah digunakan, yang membolehkan pemaju berinteraksi dengan lebih mudah dengan blockchain Ethereum dan ekosistemnya.
Dalam tutorial ini, contoh-contoh yang ditulis dalamJavaScript
bahasa, persekitaran ujian menggunakan kedua-duaEthereum mainnetdanRangkaian ujian Goerli. Dan anda juga boleh melihat antara muka API dan penerangan yang berkaitan, contoh kod yang digunakan dalam tutorial dalam dokumentasi API platform FMZ.
Sebelum belajar menggunakan Platform Dagangan Kuantum FMZ, kita perlu membiasakan diri dengan beberapa konsep asas:
Selepas mendaftar dan log masuk ke laman web rasmi Platform Dagangan Kuantum FMZ (https://www.fmz.com), anda boleh menggunakan pelbagai fungsi platform. Laman web FMZ adalah akhir pengurusan keseluruhan sistem, dan program yang ditulis oleh pengguna berjalan di docker sebenarnya. Program perisian docker boleh digunakan di pelbagai peranti, seperti pelayan, komputer, dll. Apabila pengguna menulis program dan membuat contoh yang berjalan di laman web FMZ, platform FMZ akan berkomunikasi dengan docker dan memulakan contoh program di atasnya.
Jika anda ingin menjalankan contoh program, anda mesti menyebarkan docker. Penyebaran docker juga sangat mudah, dan terdapat tutorial penyebaran di platform. Anda juga boleh menggunakan
Anda boleh menyebarkan dan menjalankan program docker pada pelayan, komputer peribadi dan peranti lain, selagi rangkaian adalah normal (perlu dapat mengakses sasaran yang sesuai, seperti antara muka pertukaran tertentu, alamat nod, dll.).
robot
. Mengatur alamat komunikasi docker, yang unik untuk setiap akaun FMZ, selepas log masuk ke FMZ, anda boleh melihat alamat anda sendiri dihttps://www.fmz.com/m/add-node
halaman (iaitu,./robot -s node.fmz.com/xxxxx
rentetan alamat ini, di mana kandungan dixxxxx
kedudukan adalah berbeza untuk setiap akaun FMZ). Akhirnya, anda perlu memasukkan kata laluan akaun FMZ anda. Selepas mengkonfigurasi tetapan ini, jalankan program docker.Gunakan fungsi
Tambah halaman dok pada platform FMZ, alamat:https://www.fmz.com/m/add-node
Platform Perdagangan Kuantum FMZ menyediakan alat penyempurnaan percuma yang menyokongJavaScript
, TypeScript
, dan halaman adalah:https://www.fmz.com/m/debug. Kerana mencipta contoh untuk dijalankan akan dikenakan bayaran. Semasa tempoh pembelajaran awal, anda boleh menggunakan alat debugging ini untuk ujian dan pembelajaran. Kecuali had masa berjalan maksimum 3 minit, tidak ada perbezaan antara menggunakan alat debugging dan membuat contoh untuk dijalankan.
Apabila menggunakanTypeScript
Bahasa, anda perlu menulis// @ts-check
pada baris pertama kod untuk beralih keTypeScript
mod; jika tidak ditukar, lalai adalahJavaScript
language.
Pada FMZ,
Dalam keadaan log masuk platform FMZ, dihttps://www.fmz.com/m/add-platform
halaman, anda boleh mengkonfigurasi pertukaran maklumat, di mana pertukaran adalah konsep umum.
PilihWeb3
, mengkonfigurasi alamat nod RPC, mengkonfigurasi kunci peribadi, anda boleh klik sudut kanan bawah
Nod boleh menjadi nod yang dibina sendiri atau nod yang disediakan oleh penyedia perkhidmatan nod.Infura. Selepas pendaftaran, anda boleh melihat alamat nod akaun anda sendiri. Kedua-dua mainnet dan testnet tersedia, yang agak mudah.Rpc Address
label boleh dinamakan oleh anda sendiri untuk membezakan antara objek pertukaran yang dikonfigurasikan.
Dalam gambar itu,https://mainnet.infura.io/v3/xxxxxxxxxxxxx
adalah alamat nod RPC infura ETH utama peribadi.
Selepas menyebarkan program docker dan mengkonfigurasi objek pertukaran, anda boleh menggunakanFMZ.COM
Kami menyenaraikan beberapa contoh mudah, bermula dari asas. untuk pelbagai bahasa dan alat, terdapat cara untuk mengakses web3, seperti yang ditunjukkan dalam gambar:
Pada FMZ, panggilan kaedah RPC juga dikapsul, dan fungsi ini dikapsul dalam fungsi FMZ APIexchange.IO
Cara panggilan adalahexchange.IO("api", "eth", ...)
. Parameter pertama ditetapkan kepada"api"
, parameter kedua ditetapkan kepada"eth"
, dan parameter lain bergantung kepada kaedah RPC tertentu yang dipanggil.
Untuk maklumat output, kita akan menggunakanLog
fungsi platform FMZ.Log
fungsi boleh menerima pelbagai parameter dan kemudian mengeluarkan mereka di kawasan log
Peraturaneth_getBalance
kaedah Ethereum digunakan untuk menanyakan baki ETH alamat di Ethereum, dan kaedah ini memerlukan dua parameter.
Vitalik Buterin
alamat dompet ETH, alamat yang diketahui adalah:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
.function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
}
Sudah digunakan docker (dalam gambar: linux/amd64...) dan dikonfigurasikan objek pertukaran (dalam gambar: Web3 ujian), menguji kod dalam alat debugging:
Klik butang
EthBalanse: 0x117296558f185bbc4c6
Peraturanlog
fungsi mencetak keluarethBalance
Nilai pembolehubah sebagai:0x117296558f185bbc4c6
, yang merupakan jenis rentetan.nilai heksadesimal baki ETHdalamwei
unit, dengan1e18 wei
sama dengan 1ETH
Oleh itu, ia perlu ditukar untuk menjadi baki ETH perpuluhan yang boleh dibaca.
PengubahsuaianethBalance
ke dalam data yang boleh dibaca:
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
Log("ethBalance:", ethBalance)
// Converting ethBalance into readable data
let vitalikEthBalance = parseInt(ethBalance.substring(2), 16) / 1e18
Log("vitalikEthBalance:", vitalikEthBalance)
}
Cari terushttps://etherscan.io/
:
Walau bagaimanapun, kerana masalah ketepatan bahasa itu sendiri, akan ada penyimpangan dalam cara pemprosesan ini.
Sesuaikan kod lagi:
function main() {
let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
// The precision unit of ETH is 1e18
let ethDecimal = 18
Log("vitalikEthBalance:", Number((BigDecimal(BigInt(ethBalance)) / BigDecimal(Math.pow(10, ethDecimal))).toString()))
}
VitalikEthBalanse: 5149.6244846875215
eth_chainId
dannet_version
Kedua-dua fungsi ini mengembalikan ID blockchain yang simpul RPC semasa disambungkan ke, dengan perbezaan adalah bahawanet_version
mengembalikan Id perpuluhan daneth_chainId
Mengembalikan ID hexadecimal.
Nama rangkaian yang sepadan dengan 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
Ujian dengan Ethereum testnet yang dikonfigurasigoerli
simpul:
function main() {
let netVersionId = exchange.IO("api", "eth", "net_version")
let ethChainId = exchange.IO("api", "eth", "eth_chainId")
Log("netVersionId:", netVersionId)
Log("ethChainId:", ethChainId, " , conversion:", parseInt(ethChainId.substring(2), 16))
}
Panggileth_gasPrice
kaedah untuk menyoal arusgas price
di rantai.
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
Log("gasPrice:", gasPrice, " , conversion:", toAmount(gasPrice, 0))
}
Di sini kita menulis fungsi untuk menukar rentetan hexadecimal ke dalam nilai nombor yang boleh dibaca:toAmount
Di samping itu, perhatikan bahawa unitgasPrice
adalahwei
, jadi lulus nilai 0 kepada parameter sebenar yang sepadan dengan parameter formaldecimals
.
"eth_blockNumber
digunakan untuk menyoal ketinggian blok.
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))
}
Jalankan dalam alat debugging:
Cari terushttps://etherscan.io/
:
Soalan maklumat blok.
function main() {
let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
Log(blockNumber)
let blockMsg = exchange.IO("api", "eth", "eth_getBlockByNumber", blockNumber, true)
Log(typeof(blockMsg), blockMsg)
// Due to the excessive content of Log output, it will be truncated automatically, so traverse each field of the returned block information and print them one by one
for (let key in blockMsg) {
Log("key:", key, ", val:", blockMsg[key])
}
}
Melakukan dalam
Banyak aplikasi kontrak pintar berjalan di Ethereum, danENS
adalah salah seorang daripada mereka.ENS
, atau Perkhidmatan Nama Ethereum, adalah perkhidmatan resolusi nama domain terdesentralisasi berdasarkan blockchain Ethereum.
Adakah anda ingat contoh dalam tutorial di mana kita memeriksa baki dompet pengasas Ethereum Vitalik Buterin0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
Jadi bagaimana kita tahu alamat? Malah, ia boleh ditanyakan melaluiENS
kontrak pintar menggunakan nama intuitifvitalik.eth
.
Kandungan berikut dalam bab ini menggunakan persekitaran Ethereum mainnet, mengikutENS
dokumentasi,Hashing Names
diperlukan untuk menyoal nama domain Ethereum. Gunakan kod berikut untuk memprosesvitalik.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))
}
}
Dalam contoh kod di atas, kita melihat satu lagi fungsi yang tidak biasaEncode
. Fungsi ini adalah fungsi API platform FMZ dan secara khusus digunakan untuk pengekodan operasi pada platform FMZ. Fungsi ini menyokong pelbagai kaedah pengekodan dan pelbagai algoritma hash.
Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)
Sesuai dengan penerangan dalam dokumen ENS, gunakansha3.keccak256
Algoritma untuk memproses data.
PanggilnameHash
fungsi, contohnya:Log(nameHash("vitalik.eth"))
, anda boleh mendapatkan:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835
, dan anda perlu menambah 0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835
digunakan sebagai parameterresolver
kaedah dalam kontrak pintar ENS.
let ensNode = "0x" + nameHash("vitalik.eth") // Prepare the parameters ensNode for calling the resolver method
Menurut dokumentasi ENS, alamat kontrak untuk aplikasi kontrak pintar ENS adalah:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
. Sebelum memanggilresolver
kaedah kontrak pintar, kita juga perlu menyediakanABI
daripada kontrak.
Setelah mengetahui ini, anda mungkin bertanya: apa yangABI
kontrak pintar?
ABI, or Application Binary Interface, is the interface standard for smart contracts to communicate with the external world.
The ABI of a smart contract defines the contract's function interfaces, parameter types, return values, and other information, as well as specifications for calling the contract and passing parameters.
The ABI of a smart contract is usually stored in JSON format and contains the following information:
Contract function interfaces: function names, parameter lists, return values, etc.
Function parameter types: such as uint256, bool, string etc.
Encoding methods for input and output parameters of functions: Smart contracts use an encoding method called Solidity ABI to encode input and output parameters of functions so that they can interact with Ethereum network.
In Ethereum network ,the ABI of a smart contract is used to call its functions. When you need to call a contract function, you need to provide the name of the function, its parameters, and bytecode encoded according to ABI encoding method.
Ethereum nodes will package this information into transactions and send them out on Ethereum network for execution.
In Solidity language,the keyword 'interface' can be used define ABIs for smart contracts. Ethereum development tools like Remix IDE ,Truffle also provide editing & generation tools making it easier developers create & use ABIs.
Keluarkanresolver
anda boleh menggunakan ABI lengkap. anda boleh menyoal ABI kontrak padahttps://etherscan.io/
atau mendapatkan ABI melalui saluran lain (contohnya, dokumentasi projek yang relevan).
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"}]`
Di sini kita akan belajar kaedah panggilan baru pada platform FMZ,exchange.IO("abi", address, abiContent)
, yang digunakan untuk mendaftarkan ABI.address
parameter adalah alamat kontrak pintar danabiContent
Parameter adalah kontrak pintar yang sepadan ABI (string).
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver) // 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e is the address of the ENS smart contract deployed on the Ethereum mainnet
Seterusnya, anda boleh memanggilresolver
kaedah kontrak pintar ENS, yang mengembalikan alamatENS: Public Resolver
contract.
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
GunakanENS: Public Resolver
kontrakaddr
Cara untuk mendapatkan alamat dompet Vitalik Buterin.ENS: Public Resolver
maklumat ABI untuk kontrak pintar ini masih boleh diperolehi darihttps://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)
Akhirnya, hubungiENS: Public Resolver
kontrakaddr
kaedah, dengan parameter masih menjadiensNode
.
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
Keluaran fungsi 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() {
// Calculate the name
let ensNode = "0x" + nameHash("vitalik.eth")
// Register ENS contract
let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver)
let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
// Register ENS Public Resolver contract
let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)
let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)
}
Dalam bab kursus sebelumnya, kita telah belajar bagaimana untuk mengkonfigurasi kunci peribadi. Bagaimana kita tahu alamat dompet yang sepadan dengan kunci peribadi ini untuk objek pertukaran yang dikonfigurasi? Pada FMZ, anda boleh menggunakanexchange.IO("address")
fungsi untuk mendapatkan alamat dompet yang sepadan dengan kunci peribadi yang dikonfigurasikan.
Kandungan berikut dalam bab ini menggunakan persekitaran Goerli testnet, jadi nod yang saya gunakan adalah:https://goerli.infura.io/v3/*******
, dan Infura menetapkan alamat nod yang berbeza untuk setiap pengguna berdaftar.*******
menyembunyikan kandungan tertentu.
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
}
Selepas mengetahui alamat dompet anda, anda boleh menggunakan kaedah RPC Ethereumeth_getTransactionCount
Dalam Ethereum, jumlah ini sangat biasa, dan ia sebenarnyanonce
parameter yang perlu diteruskan semasa operasi pemindahan. Dalam Ethereum, nonce adalah nombor unik yang digunakan untuk memastikan bahawa setiap transaksi adalah unik. Ia adalah nombor yang semakin meningkat, dan ia akan meningkat secara automatik setiap kali transaksi baru dihantar. Oleh itu, apabila anda menghantar transaksi ke kontrak pintar, anda perlu memberikan nonce untuk memastikan bahawa transaksi itu unik dan dalam urutan yang betul.
Di sini,PendingNonceAt
fungsi dalam perpustakaan Ethereum bahasa Go sebenarnya memanggileth_getTransactionCount
Dalam kursus sebelumnya, kita juga telah belajar bagaimana untuk memanggil kaedah RPC.exchange.IO("api", "eth", ...)
berfungsi lagi.
function toAmount(s, decimals) {
return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
/**
* eth_getTransactionCount
* @param address - string - The address from which the transaction count to be checked.
* @param blockNumber - string - The block number as a string in hexadecimal format or tags.
* @returns The integer of the number of transactions sent from an address encoded as hexadecimal.
*/
let nonce: string = exchange.IO("api", "eth", "eth_getTransactionCount", walletAddress, "pending")
Log("wallet address:", walletAddress, "current nonceļ¼", nonce, ", convert to decimal:", toAmount(nonce, 0))
}
Sebelum menerangkan operasi pemindahan, mari kita memahami beberapa konsep secara ringkas. Semasa memindahkan pada Ethereum, sejumlah token ETH akan dimakan (sebagai yuran gas). Yuran gas ditentukan oleh dua parameter:
gasPrice
Walau bagaimanapun, yuran gas pada rangkaian Ethereum sentiasa berfluktuasi mengikut permintaan pasaran dan yuran pengguna bersedia membayar, jadi menulis yuran gas tetap dalam kod kadang-kadang bukan pilihan yang ideal.eth_gasPrice
kaedah yang kita belajar sebelum ini, yang boleh mendapatkan harga gas purata.
gasLimit
Pemindahan Ether standard mempunyai had gas 21,000 unit.
Setelah memahami konsep-konsepnonce
, gasPrice
, dangasLimit
, anda boleh menguji pemindahan. FMZ menyediakan fungsi pemindahan yang sangat mudah dan mudah digunakan.
exchange.IO("api", "eth", "send", toAddress, toAmount)
Apabila ia digunakan untuk pemindahan, parameter ketigaexchange.IO
ditetapkan sebagai toAddress
parameter ialah alamat yang menerima ETH semasa pemindahan, dantoAmount
adalah jumlah ETH yang dipindahkan.
Parameternonce
, gasPrice
, dangasLimit
semua boleh menggunakan nilai lalai sistem yang diperoleh secara automatik di FMZ. Mereka juga boleh ditentukan:
exchange.IO("api", "eth", "send", toAddress, toAmount, {gasPrice: 5000000000, gasLimit: 21000, nonce: 100})
Seterusnya, kita akan memindahkan sejumlah ETH ke alamat tertentu di rangkaian ujian goerli:
function toInnerAmount(s, decimals) {
return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}
function main() {
let walletAddress = exchange.IO("address")
Log("Testnet goerli wallet address:", walletAddress)
let ret = exchange.IO("api", "eth", "send", "0x4D75a08E870674E68cAE611f329A27f446A66813", toInnerAmount(0.01, 18))
return ret // return Transaction Hash : 0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
}
Kerana unit jumlah pemindahan Ethereum adalahwei
, fungsi tersuaitoInnerAmount
perlu digunakan untuk memproses nilai dalamwei
units.
Hash Transaksi pertanyaan:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
padahttps://etherscan.io/
.
Anda juga boleh menulis kod untuk query transfer hash0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
, menggunakaneth_getTransactionReceipt
kaedah untuk pertanyaan.
function main() {
let transHash = "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e"
let info = exchange.IO("api", "eth", "eth_getTransactionReceipt", transHash)
return info
}
Hasil pertanyaan:
{
"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": []
}
Penerangan yang sepadan dengan setiap bidang:
blockHash - The hash value of the block where the transaction is located.
blockNumber - The block number of the block where the transaction is located, encoded in hexadecimal.
contractAddress - If it's a contract creation, the address of the contract; otherwise null.
cumulativeGasUsed - The total gas used when executing this transaction in the block.
effectiveGasPrice - Total base fee plus tip per unit of gas.
from - Sender's address.
gasUsed - Gas used by this specific transaction.
logs - Array of log objects generated by this transaction.
address - Address that generated this log.
topics - Data array with 0 to 4 indexed log parameters, each with 32 bytes. In Solidity, first topic is event signature hash (e.g., Deposit(address,bytes32,uint256)), unless you declare an event using anonymous specifier.
data - Non-indexed parameters for logs with length of 32 bytes.
blockNumber - The block number of the block where this log is located.
transactionHash - Transaction hash at time when log was created. Null if pending state.
transactionIndex - Index position during creation. Null if pending state.
blockHash - The hash value for containing block.
logIndex - Hexadecimal-encoded integer index position within containing block. Null if pending state.
removed - True if deleted due to chain reorganization; false for valid logs.
logsBloom - Bloom filter for retrieving related logs.
status - Hexadecimal-encoded value either being '1' (success) or '0' (failure).
to - Receiving party's address; null for contract creation transactions.
transactionHash - The hash value associated with given transaction.
transactionIndex - Hexadecimal-encoded index position within its respective containing-block.
type - Type value.
Dalam bab mengenai Read
kaedah, dan memanggil kaedah ini tidak memerlukangas
(ingat apa yang kita bercakap tentang gas sebelum ini?). Dalam bab ini, kita akan memanggil beberapaWrite
kaedah kontrak pintar pada Ethereum dan membayar untukgas
Operasi ini akan disahkan oleh setiap nod dan pelombong di seluruh rangkaian dan mengubah keadaan blockchain.
Untuk kontrak ERC20 (kontrak token ERC20), platform FMZ menyenaraikan ABI kontrak ERC20 ABI sebagai ABI biasa yang dibina terus ke dalam sistem, menghapuskan langkah pendaftaran ABI.
Untuk lebih memahami ABI, anda boleh memeriksanya sebelum menggunakannya.
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"tran