avatar of 发明者量化-小小梦 发明者量化-小小梦
tập trung vào tin nhắn riêng tư
4
tập trung vào
1271
Người theo dõi

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

Được tạo ra trong: 2023-03-28 13:32:48, cập nhật trên: 2024-11-11 22:28:24
comments   0
hits   3837

[TOC]

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

Hướng dẫn EtherEaseWithFMZ

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

Ethereum là nền tảng hợp đồng thông minh dựa trên công nghệ blockchain, cung cấp phương pháp phi tập trung để viết và triển khai hợp đồng thông minh. Hợp đồng thông minh là một chương trình máy tính đặc biệt có thể tự động thực thi trên blockchain và có thể triển khai nhiều logic kinh doanh khác nhau mà không cần phải tin tưởng bên thứ ba.

Nền tảng giao dịch định lượng Inventor (FMZ.COM) cung cấp API dễ sử dụng giúp các nhà phát triển dễ dàng tương tác với chuỗi khối Ethereum và hệ sinh thái của nó. Thực hiện các chức năng như 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 và gửi giao dịch.

Các ví dụ trong hướng dẫn này sử dụngJavaScriptViết ngôn ngữ, sử dụng môi trường thử nghiệmMạng chính EthereumMạng thử nghiệm Goerli. Bạn cũng có thể xem các giao diện API được sử dụng trong hướng dẫn cũng như các mô tả liên quan và ví dụ mã trong tài liệu API của nền tảng FMZ.


Bắt đầu với FMZ

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

1. Kiến trúc nền tảng giao dịch định lượng FMZ

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

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

2. Chủ nhà

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 máy chủ. Việc triển khai máy chủ cũng rất đơn giản và có hướng dẫn triển khai trên nền tảng. Bạn cũng có thể sử dụng “máy chủ triển khai một cú nhấp chuột” được cung cấp trên FMZ để tự động triển khai bằng máy chủ do FMZ thuê.

  • Triển khai máy chủ trên thiết bị cá nhân

Chương trình giám sát có thể được triển khai và chạy 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 hoạt động bình thường (mục tiêu tương ứng cần có thể truy cập được, chẳng hạn như giao diện trao đổi, địa chỉ nút, v.v.). Các bước triển khai chính là:

  1. Đăng nhập hoặc mở thiết bị mà bạn muốn triển khai chương trình lưu trữ, chẳng hạn nhưĐăng nhập vào máy chủhoặcBật máy tính và nhập hệ điều hành
  2. Tải xuống phiên bản tương ứng của chương trình lưu trữ (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 Sử dụng FMZ để dễ dàng bắt đầu phát triển web3 dựa trên Ethereum
  3. Tệp đã tải xuống là một gói nén, cần phải giải nén.
  4. Chạy chương trình chủ. Chương trình chủ là một chương trình được gọi làrobottập tin thực thi. Cấu hình địa chỉ giao tiếp của người giám hộ. Địa chỉ giao tiếp này là duy nhất cho mỗi tài khoản FMZ. Sau khi đăng nhập vào FMZ,https://www.fmz.com/m/add-nodeTrang có thể xem địa chỉ của chính nó (tức là./robot -s node.fmz.com/xxxxxChuỗi địa chỉ này, ở đâyxxxxxNội dung của vị trí được hiển thị khác nhau đối với 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. Sau khi cấu hình xong, hãy chạy chương trình máy chủ.
  • Sử dụng chức năng “triển khai người giám hộ chỉ bằng một cú nhấp chuột” của nền tảng FMZ

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

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

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

Nền tảng giao dịch định lượng FMZ cung cấp một công cụ gỡ lỗi miễn phí hỗ trợJavaScriptTypeScriptTrang này là: https://www.fmz.com/m/debug, vì việc tạo phiên bản và chạy phiên bản đó sẽ mất phí. Công cụ gỡ lỗi này có thể được sử dụng để thử nghiệm và học tập trong giai đoạn học tập ban đầu. Công cụ gỡ lỗi không khác gì việc tạo một phiên bản, ngoại trừ thời gian chạy bị giới hạn trong 3 phút.

sử dụngTypeScriptKhi sử dụng ngôn ngữ, bạn cần phải viết nó ở dòng mã đầu tiên// @ts-checkĐể chuyển sangTypeScriptChế độ, nếu không được chuyển đổi, mặc định làJavaScriptngôn ngữ.

4. Trao đổi

Trên FMZ, “exchange” là một khái niệm chung. Đối với sàn giao dịch CEX, nó đề cập đến cấu hình tài khoản sàn giao dịch cụ thể. Đối với web3, trao đổi 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.

Khi đăng nhập vào nền tảng FMZ,https://www.fmz.com/m/add-platformTrang này cho phép bạn cấu hình thông tin trao đổi, trong đó trao đổi là một khái niệm chung.

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

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

Các nút có thể được tự xây dựng hoặc được cung cấp bởi 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 mình. Có cả mainnet và testnet, tiện lợi hơn. Cấu hình địa chỉ node này trong hình trên.Rpc Addresstrong các điều khiển. Thẻ có thể được đặt tên riêng để phân biệt các đối tượng trao đổi được cấu hình.

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

Trong hìnhhttps://mainnet.infura.io/v3/xxxxxxxxxxxxxĐây là địa chỉ nút RPC mainnet ETH riêng tư của Infura.


Sử dụng FMZ để tương tác với Ethereum

Sau khi triển khai chương trình giám sát và cấu hình đối tượng trao đổi, bạn có thể sử dụng “công cụ gỡ lỗi” của FMZ.COM để thử nghiệm. Gọi các phương thức RPC của Ethereum để tương tác với Ethereum. Ngoài một số phương thức RPC được liệt kê trong chương này, bạn có thể tham khảo tài liệu về các phương thức RPC khác, chẳng hạn nhưhttps://www.quicknode.com/docs

Chúng ta hãy lấy một vài ví dụ đơn giản và bắt đầu với những điều cơ bản. Có nhiều cách để truy cập web3 cho nhiều ngôn ngữ và công cụ khác nhau, như thể hiện trong hình:

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

Các lệnh gọi phương thức RPC cũng được đóng gói trên FMZ. Các hàm này được đóng gói trong hàm API FMZexchange.IOở giữa. Phương pháp gọi làexchange.IO("api", "eth", ...). Tham số đầu tiên là cố định."api", tham số thứ hai được cố định"eth", các tham số khác phụ thuộc vào phương thức RPC cụ thể được gọi.

Để xuất thông tin, chúng tôi sử dụng nền tảng FMZLogchức năng,LogChức năng này có thể truyền nhiều tham số và sau đó xuất chúng ra vùng nhật ký của trang “Debug Tool” hoặc “Real Trading” của nền tảng FMZ. Trang “Debug Tool” sẽ là công cụ chính để chúng tôi thử nghiệm.

eth_getBalance

Ethereumeth_getBalancePhương pháp này được sử dụng để truy vấn số dư ETH của một địa chỉ trên Ethereum. Phương pháp này yêu cầu phải truyền vào hai tham số.

  • Địa chỉ cần truy vấn.
  • Thẻ, thường là “mới nhất”.

Hãy cùng kiểm tra người sáng lập EthereumV神Địa chỉ ví ETH, các địa chỉ đã biết là:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

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

Người giám hộ đã được triển khai (trong hình: linux/amd64 …) và đối tượng trao đổi đã được cấu hình (trong hình: Web3 test). Kiểm tra mã trong công cụ gỡ lỗi:

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

Nhấp vào nút “Thực thi” để chạy mã này và hiển thị kết quả:

ethBalance: 0x117296558f185bbc4c6

LogChức năng inethBalanceCác giá trị biến là:0x117296558f185bbc4c6, là kiểu chuỗi. ĐúngSố dư ETH theo giá trị thập lục phân,quaweiLà một đơn vị,1e18 weilà 1ETH. Do đó, cần phải chuyển đổi số dư ETH thành số thập phân dễ đọc.

SẽethBalanceChuyển đổi thành dữ liệu có thể đọc được:

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

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

Trên cùnghttps://etherscan.io/Truy vấn:

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

Tuy nhiên, quá trình xử lý này sẽ có sai lệch do tính chính xác của ngôn ngữ, do đó nền tảng FMZ có hai hàm tích hợp để xử lý dữ liệu:

  • BigInt: Chuyển đổi chuỗi thập lục phân thành đối tượng BigInt.
  • BigDecimal: Chuyển đổi một đối tượng kiểu số thành một đối tượng BigDecimal có thể thao tác được.

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

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

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

vitalikEthBalance: 5149.6244846875215

eth_chainId

eth_chainIdnet_versionCông dụng của chúng tương tự nhau nên chúng tôi đã thử nghiệm chúng cùng nhau. Cả hai hàm đều trả về ID của blockchain mà nút RPC hiện tại được kết nối tới. Sự khác biệt lànet_versionTrả về ID thập phân.eth_chainIdTrả về ID thập lục phân.

Tên mạng tương ứng với ID chuỗi

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

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

Sử dụng mạng thử nghiệm Ethereum đã cấu hìnhgoerliKiểm tra nú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, " ,转换:", parseInt(ethChainId.substring(2), 16))
}

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

eth_gasPrice

Gọieth_gasPricePhương pháp truy vấn chuỗi hiện tạigas price

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

function main() {
    let gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
    Log("gasPrice:", gasPrice, " ,转换:", toAmount(gasPrice, 0))
}

Ở đây chúng ta viết một hàm để chuyển đổi một chuỗi thập lục phân thành giá trị có thể đọc được:toAmount. Một điều nữa cần lưu ý là đơn vị của gasPrice làwei, vì vậy tham sốdecimalsTham số thực tế tương ứng có thể được truyền là 0.

eth_blockNumbe

eth_blockNumbeĐượ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 trình gỡ lỗi:

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

https://etherscan.io/Khi truy vấn:

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

eth_getBlockByNumber

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

Có thể thu thập được thông tin sau bằng cách thực hiện trong “Công cụ gỡ lỗi”:

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


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

Có rất nhiều ứng dụng hợp đồng thông minh chạy trên Ethereum.ENSlà một trong số đó.ENS, cụ thể là Dịch vụ tên miền Ethereum, là dịch vụ phân giải tên miền phi tập trung dựa trên chuỗi khối Ethereum. Bạn còn nhớ ví dụ trong hướng dẫn khi chúng ta truy vấn số dư ví của người sáng lập Ethereum Vitalik Buterin không? Một trong những địa chỉ ví của Vitalik là:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045. Vậy làm sao chúng ta biết được địa chỉ này? Trên thực tế, thông quaENSHợp đồng thông minh, sử dụng tên trực quanvitalik.eth(vitalik là tên của Vitalik) để thực hiện truy vấn.

Nội dung sau trong chương này sử dụng môi trường mạng chính Ethereum.ENSTài liệu cho thấy tên miền Ethereum cần được truy vấn cần phải làHashing Names, sử dụng mã sau đểvitalik.ethTên đã được xử lý.

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 ta thấy một hàm lạ khácEncodeHàm này là hàm API của nền tảng FMZ, được sử dụng cụ thể để thực hiện các hoạt động mã hóa trên nền tảng FMZ. Hàm này hỗ trợ nhiều phương pháp mã hóa và nhiều thuật toán băm.

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

Theo tài liệu ENS, sử dụngsha3.keccak256Thuật toán xử lý dữ liệu.

GọinameHashCác chức năng, ví dụ:Log(nameHash("vitalik.eth")), chúng ta có thể nhận được:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835, bạn cần thêm tiền tố “0x”.0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835Là một hợp đồng thông minh ENSresolverCác tham số của phương pháp.

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

Theo tài liệu ENS, địa chỉ hợp đồng của ứng dụng hợp đồng thông minh ENS là:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e. Khi gọi hợp đồng thông minhresolverTrước khi tiến hành, chúng ta cần chuẩn bị hợp đồngABI

Đăng ký ABI

Sau khi tìm hiểu điều này, tôi không khỏi thắc mắc, hợp đồng thông minh là gì?ABIVải len?

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

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

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

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

Trích xuất nội dung sau từ ENS ABI:resolverABI đầy đủ cũng có thể được sử dụng tronghttps://etherscan.io/Bạn có thể truy vấn ABI của hợp đồng trên GitHub hoặc lấy ABI thông qua các phương tiện khác (ví dụ: tài liệu dự án có liên quan).

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

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 phải tìm hiểu phương thức gọi mới trên nền tảng FMZ.exchange.IO("abi", address, abiContent), sử dụng phương pháp này để đăng ký ABI,addressTham số này là địa chỉ của hợp đồng thông minh.abiContentTham số này là ABI của hợp đồng thông minh tương ứ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 是在以太坊主网上部署的ENS智能合约的地址

Gọi phương thức hợp đồng thông minh

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

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

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

sử dụngENS: Public ResolverHợp đồngaddrPhương pháp lấy địa chỉ ví của Vitalik. Để gọiENS: Public ResolverHợp đồng vẫn cần phải đăng ký ABI trước. Thông tin ABI của hợp đồng thông minh này vẫn có thể được tìm thấy tạihttps://etherscan.io/Lấy.

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)

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

Cuộc gọi cuối cùngENS: Public ResolverHợp đồngaddrPhương pháp, các tham số vẫn cònensNode

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

Đầu ra của hàm log:

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

vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045

Mã hoàn chỉnh để gọi ENS

function nameHash(name) {
    if (name == "") {
        return "0000000000000000000000000000000000000000000000000000000000000000"
    } else {
        let arr = name.split(".")
        let label = arr[0]
        
        arr.shift()
        let remainder = arr.join(".")
        return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
    }
}

function main() {
    // 计算名称
    let ensNode = "0x" + nameHash("vitalik.eth")

    // 注册ENS合约
    let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
    exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver)
    let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
    
    // 注册ENS Public Resolver合约
    let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
    exchange.IO("abi", resolverAddress, abiENSPublicResolver)
    let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
    Log("vitalikAddress:", vitalikAddress)
}

Gửi ETH

Trong các chương trước của khóa học, chúng ta đã học cách cấu hình khóa riêng. Đối với đối tượng trao đổi được cấu hình, làm thế nào để chúng ta biết địa chỉ ví tương ứng với khóa riêng này? Có sẵn trên FMZexchange.IO("address")Chức năng này sẽ lấy địa chỉ ví tương ứng với khóa riêng đã cấu hình.

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

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

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

Khi bạn đã biết địa chỉ ví của mình, bạn có thể sử dụng phương pháp RPC của Ethereumeth_getTransactionCountTruy vấn số lượng giao dịch của một địa chỉ ví. Số đếm này được sử dụng rất phổ biến trong Ethereum. Trên thực tế, đây là số đếm cần phải truyền vào khi chuyển tiền.nonceTham số, Trong Ethereum, nonce là một con số được sử dụng để đảm bảo rằng mỗi giao dịch là duy nhất. Đây là một con số ngày càng tăng và tự động tăng lên mỗi khi có một giao dịch mới được gửi đi. Do đó, khi bạn gửi giao dịch đến hợp đồng thông minh, bạn cần cung cấp nonce để đảm bảo giao dịch là duy nhất và theo đúng thứ tự. Trong một số dữ liệu và tài liệu chúng ta có thể tìm thấy:

https://goethereumbook.org/en/

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

Đây là thư viện Ethereum bằng ngôn ngữ GoPendingNonceAtChức năng thực sự gọieth_getTransactionCountphương pháp. Trong khóa học trước, chúng ta cũng đã học cách gọi các phương thức RPC. Chúng ta sẽ sử dụng lại ở đây.exchange.IO("api", "eth", ...)chức năng.

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

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

    /**
    * eth_getTransactionCount
    * @param address - string - The address from which the transaction count to be checked.
    * @param blockNumber - string - The block number as a string in hexadecimal format or tags.
    * @returns The integer of the number of transactions sent from an address encoded as hexadecimal.
    */
    let nonce = exchange.IO("api", "eth", "eth_getTransactionCount", walletAddress, "pending")
    Log("钱包地址:", walletAddress, "当前的 nonce:", nonce, ",转换为10进制:", toAmount(nonce, 0))
}

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

  • gasPrice

Tuy nhiên, phí gas trên mạng Ethereum luôn biến động dựa trên nhu cầu thị trường và mức giá mà người dùng sẵn sàng trả, do đó, việc ghi một mức phí gas cố định vào mã đôi khi không lý tưởng. Chúng ta có thể sử dụng những gì chúng ta đã học trước đâyeth_gasPricePhương pháp có thể tính được giá khí đốt trung bình.

  • gasLimit

Giới hạn khí cho một lần chuyển ete tiêu chuẩn là 21.000 đơn vị.

Hiểu rồinoncegasPricegasLimitVới những khái niệm này, bạn có thể kiểm tra việc chuyển giao. Một hàm truyền rất đơn giản và dễ sử dụng được đóng gói trên FMZ.

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

Khi được sử dụng để chuyển giao,exchange.IOTham số thứ ba luôn là “gửi”.toAddressTham số là địa chỉ nhận ETH trong quá trình chuyển tiền.toAmountSố lượng ETH được chuyển.

noncegasPricegasLimitCác tham số này có thể sử dụng các giá trị được hệ thống tự động lấy theo mặc định trên FMZ. Bạn cũng có thể chỉ định:

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

Tiếp theo, chúng tôi chuyển một số lượng ETH nhất định đến một địa chỉ nhất định trên mạng 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("测试网 goerli 钱包地址:", walletAddress)

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

Bởi vì đơn vị chuyển tiền Ethereum làwei, bạn cần sử dụng một hàm tùy chỉnhtoInnerAmountĐược xử lý nhưweiGiá trị của đơn vị.

hiện hữuhttps://etherscan.io/Truy vấn băm giao dịch:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e

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

Bạn cũng có thể viết mã để truy vấn băm chuyển giao0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e,sử dụngeth_getTransactionReceiptPhương pháp 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ả của từng trường:

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