Tài nguyên đang được tải lên... tải...

Bắt đầu phát triển web3 dễ dàng dựa trên Ethereum sử dụng FMZ

Tác giả:FMZ~Lydia, Tạo: 2023-06-25 09:17:53, Cập nhật: 2023-09-18 20:28:19

[TOC]

img

Bắt đầu phát triển web3 dễ dàng dựa trên Ethereum sử dụng FMZ

EtherEaseWithFMZ hướng dẫn

Bắt đầu với phát triển web3 dựa trên Ethereum sử dụng FMZ dễ dàng

Ethereum là một nền tảng hợp đồng thông minh dựa trên công nghệ blockchain, cung cấp một cách phi tập trung để viết và triển khai các hợp đồng thông minh.

FMZ Quant Trading Platform (FMZ.COM) cung cấp một API dễ sử dụng, cho phép các nhà phát triển tương tác dễ dàng hơn với blockchain Ethereum và hệ sinh thái của nó. Nó đạt được quyền truy cập vào các sàn giao dịch phi tập trung (DEX), thu thập dữ liệu trên chuỗi, gửi giao dịch và các chức năng khác.

Trong hướng dẫn này, các ví dụ được viết bằngJavaScriptngôn ngữ, môi trường thử nghiệm sử dụng cả haiMạng chính EthereumMạng thử GoerliVà bạn cũng có thể xem các giao diện API và mô tả liên quan, ví dụ mã được sử dụng trong hướng dẫn trong tài liệu API nền tảng FMZ.


FMZ bắt đầu

Trước khi học cách sử dụng nền tảng giao dịch FMZ Quant, chúng ta cần làm quen với một vài khái niệm cơ bản:

1. FMZ Quant Trading Platform Architecture

Sau khi đăng ký và đăng nhập vào trang web chính thức của FMZ Quant Trading Platform (https://www.fmz.com), bạn có thể sử dụng các chức năng khác nhau của nền tảng. Trang web FMZ là cuối quản lý của toàn bộ hệ thống, và các chương trình được viết bởi người dùng thực sự chạy trên docker. Chương trình phần mềm docker có thể được triển khai trên các thiết bị khác nhau, chẳng hạn như máy chủ, máy tính, vv. Khi người dùng viết một chương trình và tạo một phiên bản chạy trên trang web FMZ, nền tảng FMZ sẽ liên lạc với docker và bắt đầu một phiên bản chương trình trên đó.

2. Docker

Nếu bạn muốn chạy một phiên bản chương trình, bạn phải triển khai một docker. Việc triển khai docker cũng rất đơn giản, và có các hướng dẫn triển khai trên nền tảng. Bạn cũng có thể sử dụng One-click Deployment do FMZ cung cấp để triển khai tự động trên các máy chủ thuê thay mặt FMZ.

  • triển khai Docker trên thiết bị cá nhân

Bạn có thể triển khai và chạy chương trình docker trên máy chủ, máy tính cá nhân và các thiết bị khác, miễn là mạng là bình thường (cần phải có thể truy cập vào mục tiêu tương ứng, chẳng hạn như một giao diện trao đổi nhất định, địa chỉ nút, v.v.).

  1. Đăng nhập hoặc mở thiết bị mà chương trình docker sẽ được triển khai, chẳng hạn nhưđăng nhập vào máy chủhoặcbật máy tính để vào hệ điều hành.
  2. Tải xuống phiên bản tương ứng của chương trình docker (tùy thuộc vào hệ điều hành thiết bị), trang tải xuống:https://www.fmz.com/m/add-node

img

  1. Những gì bạn tải về là một gói nén, cần phải giải nén.
  2. Chạy chương trình docker, chương trình docker là một tập tin thực thi được gọi làrobot. Thiết lập địa chỉ liên lạc docker, mà là duy nhất cho mỗi tài khoản FMZ, sau khi đăng nhập vào FMZ, bạn có thể xem địa chỉ của riêng bạn tạihttps://www.fmz.com/m/add-nodetrang (tức là,./robot -s node.fmz.com/xxxxxchuỗi địa chỉ này, nơi nội dung tạixxxxxvị trí là khác nhau cho mỗi tài khoản FMZ). Cuối cùng, bạn cần nhập mật khẩu của tài khoản FMZ của bạn. Sau khi cấu hình các thiết lập này, chạy chương trình docker.
  • Sử dụng One-Click Deployment của nền tảng FMZ

    Thêm một trang docker trên nền tảng FMZ, địa chỉ:https://www.fmz.com/m/add-node

    img

3. Công cụ gỡ lỗi

FMZ Quant Trading Platform cung cấp một công cụ gỡ lỗi miễn phí hỗ trợJavaScript, TypeScript, và trang là:https://www.fmz.com/m/debug. Bởi vì tạo các instance để chạy được tính phí. Trong giai đoạn học tập ban đầu, bạn có thể sử dụng công cụ gỡ lỗi này để kiểm tra và học. Ngoại trừ giới hạn thời gian chạy tối đa là 3 phút, không có sự khác biệt giữa sử dụng công cụ gỡ lỗi và tạo một instance để chạy.

Khi sử dụngTypeScriptngôn ngữ, bạn cần phải viết// @ts-checktrên dòng mã đầu tiên để chuyển sangTypeScriptchế độ; nếu không chuyển đổi, mặc định làJavaScript language.

4. Bàn giao thông

Trên FMZ, Platform là một khái niệm chung. Đối với các sàn giao dịch CEX, nó đề cập đến một cấu hình tài khoản giao dịch cụ thể. Đối với web3, giao dịch này đề cập đến thông tin cấu hình bao gồm địa chỉ nút và cấu hình khóa riêng.

Trong trạng thái đăng nhập của nền tảng FMZ, tạihttps://www.fmz.com/m/add-platformtrang, bạn có thể cấu hình thông tin trao đổi, nơi trao đổi là một khái niệm chung.

img

ChọnWeb3, cấu hình địa chỉ nút RPC, cấu hình khóa riêng, bạn có thể nhấp vào góc dưới bên phải Thông tin nhạy cảm sẽ được lưu trữ được mã hóa để xem cơ chế bảo mật.

Các nút có thể là các nút tự xây dựng hoặc các nút được cung cấp bởi các nhà cung cấp dịch vụ nút. Có nhiều nhà cung cấp dịch vụ nút, chẳng hạn như:Infura. Sau khi đăng ký, bạn có thể xem địa chỉ nút của tài khoản của riêng bạn. Cả mainnet và testnet đều có sẵn, điều này khá thuận tiện.Rpc AddressCác nhãn có thể được đặt tên bởi chính bạn để phân biệt giữa các đối tượng trao đổi được cấu hình.

img

Trong bức ảnh,https://mainnet.infura.io/v3/xxxxxxxxxxxxxlà địa chỉ nút RPC riêng của Infura ETH mainnet.


Tương tác với Ethereum bằng FMZ

Sau khi triển khai chương trình docker và cấu hình đối tượng trao đổi, bạn có thể sử dụngFMZ.COMs Debugging Tool để kiểm tra. Gọi phương pháp Ethereum RPC và tương tác với Ethereum, ngoài một số phương pháp RPC được liệt kê và giới thiệu trong chương này, các phương pháp RPC khác có thể được tìm thấy bằng cách tham khảo tài liệu, chẳng hạn như:https://www.quicknode.com/docs.

Chúng tôi liệt kê một vài ví dụ đơn giản, bắt đầu từ những điều cơ bản. Đối với các ngôn ngữ và công cụ khác nhau, có nhiều cách để truy cập web3, như được hiển thị trong hình:

img

Trên FMZ, các cuộc gọi phương thức RPC cũng được đóng gói và các hàm này được đóng gói trong hàm FMZ APIexchange.IOPhương pháp gọi làexchange.IO("api", "eth", ...). Các tham số đầu tiên được cố định để"api", các tham số thứ hai được cố định để"eth", và các tham số khác phụ thuộc vào phương pháp RPC cụ thể được gọi.

Đối với thông tin đầu ra, chúng tôi sẽ sử dụng cácLogPhương tiện truyền thông FMZLogfunction có thể chấp nhận nhiều tham số và sau đó xuất ra chúng trong khu vực nhật ký của trang Debug Tool hoặc Bot trên nền tảng FMZ. Trang Debug Tool sẽ là công cụ thử nghiệm chính của chúng tôi.

eth_getBalance

Cáceth_getBalancephương pháp của Ethereum được sử dụng để truy vấn số dư ETH của một địa chỉ trên Ethereum, và phương pháp này đòi hỏi hai tham số.

  • Địa chỉ cần truy vấn.
  • Nhãn hiệu, chúng tôi thường sử dụng latest. Hãy kiểm tra người sáng lập EthereumVitalik ButerinĐịa chỉ ví của ETH, địa chỉ được biết là:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045.
function main() {
    let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
    Log("ethBalance:", ethBalance)
}

Đã triển khai docker (trong hình: linux/amd64...) và cấu hình đối tượng trao đổi (trong hình: Web3 test), kiểm tra mã trong công cụ gỡ lỗi:

img

Nhấp vào nút Execute để chạy mã và hiển thị kết quả:

EthBalance: 0x117296558f185bbc4c6

Cáclogchức năng in raethBalancegiá trị biến thể như:0x117296558f185bbc4c6, đó là một kiểu chuỗi.giá trị mười sáu của số dư ETHtrongweiđơn vị, với1e18 weibằng 1ETHDo đó, nó cần phải được chuyển đổi để trở thành một số dư ETH thập phân có thể đọc được.

Chuyển đổiethBalancethành dữ liệu có thể đọc được:

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

Tìm kiếmhttps://etherscan.io/:

img

Tuy nhiên, do vấn đề độ chính xác của ngôn ngữ chính nó, sẽ có những sai lệch trong cách xử lý này. Do đó, nền tảng FMZ có hai chức năng tích hợp để xử lý dữ liệu:

  • BigInt: Chuyển đổi chuỗi hexadecimal thành đối tượng BigInt.
  • BigDecimal: Chuyển đổi các đối tượng kiểu số thành các đối tượng BigDecimal có thể tính toán được.

Điều chỉnh lại mã:

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

Đơn vị: 5149.6244846875215

eth_chainId

eth_chainIdnet_versionCả hai chức năng này trả về ID của blockchain mà nút RPC hiện tại được kết nối với, với sự khác biệt lànet_versiontrả về một Id thập phân vàeth_chainIdtrả về một ID hexadecimal.

Tên mạng tương ứng với 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

Kiểm tra với mạng thử nghiệm Ethereum được cấu hìnhgoerlinút:

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

Eth_gas Giá

Gọi choeth_gasPricephương pháp để truy vấn hiện tạigas pricetrên chuỗi.

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

Ở đây chúng ta viết một hàm để chuyển đổi chuỗi hexadecimal thành một giá trị số có thể đọc được:toAmountNgoài ra, lưu ý rằng đơn vịgasPricewei, vì vậy chuyển giá trị 0 đến tham số thực tương ứng với tham số chính thứcdecimals.

eth_blockNumber

"eth_blockNumberđược sử dụng để truy vấn chiều cao khối.

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

Chạy trong công cụ gỡ lỗi:

img

Tìm kiếmhttps://etherscan.io/:

img

eth_getBlockByNumber

Tìm kiếm thông tin khối.

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

Thực hiện trong Debugging Tool có thể lấy thông tin sau:

img

Đọc thông tin hợp đồng

Nhiều ứng dụng hợp đồng thông minh chạy trên Ethereum, vàENSlà một trong số đó.ENS, hoặc Dịch vụ Tên Ethereum, là một dịch vụ giải quyết tên miền phi tập trung dựa trên blockchain Ethereum. Bạn có nhớ ví dụ trong hướng dẫn nơi chúng tôi kiểm tra số dư của ví của người sáng lập Ethereum Vitalik Buterin?0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045Vậy làm thế nào chúng ta biết địa chỉ?ENShợp đồng thông minh sử dụng một tên trực quanvitalik.eth.

Nội dung sau trong chương này sử dụng môi trường mạng chính Ethereum, theoENStài liệu,Hashing Namesđược yêu cầu để truy vấn tên miền Ethereum. Sử dụng mã sau để xử lý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))
    }
}

Trong ví dụ mã ở trên, chúng tôi đã thấy một chức năng không quen thuộc khácEncodeChức năng này là một hàm API của nền tảng FMZ và được sử dụng đặc biệt để mã hóa các hoạt động trên nền tảng FMZ. Chức năng hỗ trợ nhiều phương pháp mã hóa và các thuật toán băm khác nhau.

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

Theo mô tả trong tài liệu ENS, sử dụngsha3.keccak256thuật toán để xử lý dữ liệu.

Gọi chonameHashchức năng, ví dụ:Log(nameHash("vitalik.eth")), bạn có thể nhận được:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835, và bạn cần thêm tiền tố 0x.0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835được sử dụng như là tham số củaresolverphương pháp trong ENS hợp đồng thông minh.

let ensNode = "0x" + nameHash("vitalik.eth")    // Prepare the parameters ensNode for calling the resolver method

Theo tài liệu ENS, địa chỉ hợp đồng cho các ứng dụng hợp đồng thông minh ENS là:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1eTrước khi gọi điện choresolverphương pháp hợp đồng thông minh, chúng ta cũng cần chuẩn bịABIcủa hợp đồng.

Đăng ký ABI

Khi biết điều này, bạn có thể hỏi:ABIcủa một hợp đồng thông minh?

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.

Xóa raresolverBạn có thể truy vấn ABI của hợp đồng trênhttps://etherscan.io/hoặc có được ABI thông qua các kênh khác (ví dụ: tài liệu dự án có liên quan).

img

let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`

Ở đây chúng ta sẽ học một phương pháp gọi mới trên nền tảng FMZ,exchange.IO("abi", address, abiContent), được sử dụng để đăng ký ABI.addressthông minh hợp đồng địa chỉ vàabiContenttham số là hợp đồng thông minh tương ứng ABI (dòng chuỗi).

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

Phương pháp gọi hợp đồng thông minh

Tiếp theo, bạn có thể gọi choresolverphương pháp của ENS hợp đồng thông minh, trả về địa chỉ củaENS: Public Resolver contract.

img

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

Sử dụngENS: Public Resolverhợp đồngaddrđể lấy địa chỉ ví của Vitalik Buterin.ENS: Public ResolverThông tin ABI cho hợp đồng thông minh này vẫn có thể được lấy từ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)

img

Cuối cùng, gọi choENS: Public Resolverhợp đồngaddrphương pháp, với các tham số vẫn làensNode.

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

Lượng đầu ra của hàm log:

vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045

Gọi mã đầy đủ của hệ thần kinh

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

Gửi ETH

Trong các chương khóa học trước, chúng ta đã học cách cấu hình khóa riêng. Làm thế nào chúng ta biết địa chỉ ví tương ứng với khóa riêng này cho đối tượng trao đổi được cấu hình? Trên FMZ, bạn có thể sử dụngexchange.IO("address")chức năng để lấy địa chỉ ví tương ứng với khóa riêng được cấu hình.

Nội dung sau trong chương này sử dụng môi trường testnet Goerli, vì vậy các nút tôi đang sử dụng là:https://goerli.infura.io/v3/*******, và Infura gán địa chỉ nút khác nhau cho mỗi người dùng đã đăng ký.*******ẩn nội dung cụ thể.

function main() {
    let walletAddress = exchange.IO("address")
    Log("Testnet goerli wallet address:", walletAddress)
}

Sau khi biết địa chỉ ví của bạn, bạn có thể sử dụng phương pháp RPC của Ethereumeth_getTransactionCountTrong Ethereum, số lượng này rất phổ biến, và nó thực sự lànoncetrong Ethereum, nonce là một số duy nhất được sử dụng để đảm bảo rằng mỗi giao dịch là duy nhất. nó là một số ngày càng tăng, và nó sẽ tự động tăng mỗi khi một giao dịch mới được gửi. do đó, khi bạn gửi giao dịch đến một hợp đồng thông minh, bạn cần cung cấp một nonce để đảm bảo rằng giao dịch là duy nhất và theo thứ tự chính xác. chúng ta có thể tìm thấy thông tin này trong một số tài liệu và tài liệu:

https://goethereumbook.org/en/

img

Ở đây,PendingNonceAtchức năng trong thư viện Ethereum của ngôn ngữ Go thực sự gọi cáceth_getTransactionCountTrong các bài học trước, chúng ta cũng đã học cách gọi các phương thức RPC.exchange.IO("api", "eth", ...)hoạt động trở lại.

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

Trước khi giải thích hoạt động chuyển tiền, chúng ta hãy hiểu một số khái niệm. Khi chuyển tiền trên Ethereum, một số lượng token ETH nhất định sẽ được tiêu thụ (như phí khí đốt). Phí khí đốt được xác định bởi hai thông số:

  • gas Giá

    Tuy nhiên, phí khí trên mạng Ethereum luôn dao động theo nhu cầu thị trường và phí người dùng sẵn sàng trả, vì vậy viết phí khí cố định trong mã đôi khi không phải là một lựa chọn lý tưởng.eth_gasPricephương pháp chúng tôi đã học trước đây, mà có thể có được giá trung bình của khí đốt.

  • gasLimit

    Một chuyển Ether tiêu chuẩn có giới hạn khí 21.000 đơn vị.

Sau khi hiểu các khái niệm củanonce, gasPrice, vàgasLimitFMZ cung cấp một chức năng chuyển giao rất đơn giản và dễ sử dụng.

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

Khi nó được sử dụng cho chuyển khoản, tham số thứ ba củaexchange.IOđược cố định là gửi ,toAddresstham số là địa chỉ nhận ETH trong quá trình chuyển tiền, vàtoAmountlà số tiền ETH được chuyển.

Các thông sốnonce, gasPrice, vàgasLimitTất cả có thể sử dụng các giá trị mặc định của hệ thống được lấy tự động trên FMZ. Chúng cũng có thể được chỉ định:

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

Tiếp theo, chúng ta sẽ chuyển một số lượng nhất định của ETH đến một địa chỉ cụ thể trên mạng lưới thử nghiệm 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
}

Bởi vì đơn vị của số tiền chuyển giao Ethereum làwei, một chức năng tùy chỉnhtoInnerAmountcần được sử dụng để xử lý giá trị trongwei units.

Query Transaction Hash:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734etrênhttps://etherscan.io/.

img

Bạn cũng có thể viết mã để truy vấn chuyển hash0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e, sử dụngeth_getTransactionReceiptphương pháp cho các truy vấn.

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

Kết quả truy vấn:

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

Mô tả tương ứng với mỗi trường:

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.

Gọi Ethereum Smart Contract

Trong chương về Đọc thông tin hợp đồng, chúng tôi đã sử dụng một ví dụ hoàn chỉnh để gọi phương pháp hợp đồng ENS được triển khai trên Ethereum để lấy địa chỉ ví của Vitalik Buterin.Readphương pháp, và gọi các phương pháp này không yêu cầugasTrong chương này, chúng ta sẽ gọi một sốWritephương pháp hợp đồng thông minh trên Ethereum và trả tiền chogasNhững hoạt động này sẽ được xác minh bởi mỗi nút và thợ mỏ trong toàn bộ mạng và thay đổi trạng thái blockchain.

ERC20

Đối với hợp đồng ERC20, nền tảng FMZ liệt kê ABI của hợp đồng ERC20 ABI như một ABI chung được tích hợp trực tiếp vào hệ thống, loại bỏ bước đăng ký ABI.

Để hiểu rõ hơn ABI, bạn có thể kiểm tra nó trước khi sử dụng nó.

[{"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

Có liên quan

Thêm nữa