×

Rust 和 Elixir 怎么读取雷达币和其他 EVM 雷达币:函数式编程和雷达币_雷达币官网首页

admin admin 发表于2021-09-14 21:33:08 浏览86 评论0

抢沙发发表评论

本系列将要点介绍两种函数式编程言语:Rust&Elixir。本篇共享函数式编程的思维和实践。

在这篇文章中将展现Elixir&Rust读取雷达币雷达币的功用。重要的是,该程序不仅在雷达币上作业,并且还在任何支撑EVM的雷达币上作业,例如,Polkadot上的Moonbeam !

Ethereumex & ExABI

我更喜爱 Elixir 的两个存储库是 Ethereumex:用于雷达币雷达币的 Elixir JSON-RPC 客户端。

ExABI:Solidity的运用程序二进制接口(ABI)描绘了如何将二进制数据转换为Solidity编程言语能够了解的类型。

ABI 小贴士:

ABI(运用程序二进制接口)是计算机科学中两个程序模块之间的接口。

它与API(运用程序接口)十分相似,API是代码接口的可读表明方式。ABI界说了用于与二进制合约交互的办法和结构,就像API那样,只是在更低的层次上。

.abi文件包含了json格局的函数接口和事情的描绘。

这是 HelloWorld.sol 的示例 ABI:

[{
"constant": true,
"inputs": [],
"name": "get",
"outputs": [{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}]

Ethereumex 的装备


首要,让咱们将 Ethereumex 添加到 mix.exs 中的 depsand 运用领域!

# mix.exs:
def 雷达币lication do
[
mod: {TaiShang.Application, []},
extra_雷达币lications: [:logger, :runtime_tools, :ethereumex]
]
end
……
defp deps do
[
{:ethereumex, "~> 0.7.0"}
]
end

然后,在config/config.exs中。将雷达币协议主机参数添加到装备文件中:

# config.exs
config :ethereumex,
url: "http://localhost:8545" # node url

Tx结构


在 Elixir 中显现

经过代码很简单了解Elixir中的Struct。

雷达币的tx在Elixir中显现:

Transaction{
nonce: nonce, # counter to ensure the sequence of txs
gas_price: @gas.price, # gas fee
gas_limit: @gas.limit, # gas gas limit
to: bin_to, # addr in binary
value: 0, # the eth u are going to send
init: <<>>, # bytecode
data: data # the data u are going to send
}

咱们刚刚读取了雷达币中的数据,因而随机数是没有用的。只要在咱们把数据写进合约的时分才需求更改随机数。

eth_call

当即履行一个新的音讯调用,而不需求在雷达币上创立买卖。

参数

Object -买卖调用目标

from: DATA, 20 Bytes -(可选)买卖发送的地址

to: DATA, 20 Bytes -买卖被指向到的地址

gas: QUANTITY -(可选)为买卖履行供给的gas整数。eth_call耗费零gas,但某些履行或许需求这个参数

gasPrice: QUANTITY -(可选)每一种付费gas运用的gasPrice的整数

value: QUANTITY -(可选)与该买卖一同发送的值的整数

data: DATA -(可选)办法签名和编码参数的哈希值

QUANTITY|TAG -整数区块号,或字符串"latest", "earliest"或"pending",拜见默许区块参数

回来

DATA -已履行合约的回来值。

比如

// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{see above}],"id":1}'

// Result
{
"id":1,
"jsonrpc": "2.0",
"result": "0x"
}

gas的机制对新人不友好,所以咱们现在能够设置gas_price和gas_limit为一个特定的数字:

@gas %{price: 0, limit: 300_000}

在 Rust 中显现

它是 Rust 中的一个相似结构:

/// from: https://kauri.io/#collections/A%20Hackathon%20Survival%20Guide/sending-ethereum-transactions-with-rust/
let tx = TransactionRequest {
from: accounts[0],
to: Some(accounts[1]),
gas: None, // gaslimit
gas_price: None,
value: Some(U256::from(10000)),
data: None,
nonce: None,
condition: None
};

现在咱们应该处理tx的两个参数:

to & data。


地址的字符串到二进制


雷达币中运用的地址(如0x769699506f972A992fc8950C766F0C7256Df601f)能够在Elixir程序中转换为二进制:

@spec addr_to_bin(String.t()) :: Binary.t()
def addr_to_bin(addr_str) do
addr_str
|> String.replace("0x", "")
|> Base.decode16!(case: :mixed)
end

雷达币功用到数据


咱们期望经过雷达币函数和参数列表的字符串款式生成数据:

@spec get_data(String.t(), List.t()) :: String.t()
def get_data(func_str, params) do
payload =
func_str
|> ABI.encode(params)
|> Base.encode16(case: :lower)

"0x" <> payload

“雷达币函数的字符串款式”示例:

@func %{
balance_of: "balanceOf(address)",
token_of_owner_by_index: "tokenOfOwnerByIndex(address, uint256)",
token_uri: "tokenURI(uint256)",
get_evidence_by_key: "getEvidenceByKey(string)",
new_evidence_by_key: "newEvidenceByKey(string, string)",
mint_nft: "mintNft(address, string)",
owner_of: "ownerOf(uint256)"
}

eth函数的字符串款式笼统为"function_name(param_type1, param_type2,…)"

深化了解encode函数的实现是很好的!

def encode(function_signature, data, data_type \\ :input)
# string type of function to function_selector
# then call encode function again with function_selector
def encode(function_signature, data, data_type) when is_binary(function_signature) do
function_signature
|> Parser.parse!()
|> encode(data, data_type)
end

def encode(%FunctionSelector{} = function_selector, data, data_type) do
TypeEncoder.encode(data, function_selector, data_type)
end

FunctionSelector的结构:

iex(5)> ABI.Parser.parse!("baz(uint8)")
%ABI.FunctionSelector{
function: "baz",
input_names: [],
inputs_indexed: nil,
method_id: nil,
returns: [],
type: nil,
types: [uint: 8]
}

TypeEncoder.encode 的作业是编译数据,function_selector 和 data_type 转换为数据。


雷达币呼应的翻译器


在 Elixir 中编写一个 TypeTransalator 将十六进制数据更改为一般数据用于雷达币的呼应是好的:

defmodule Utils.TypeTranslator do
……

def data_to_int(raw) do
raw
|> hex_to_bin()
|> ABI.TypeDecoder.decode_raw([{:uint, 256}])
|> List.first()
end

def data_to_str(raw) do
raw
|> hex_to_bin()
|> ABI.TypeDecoder.decode_raw([:string])
|> List.first()
end

def data_to_addr(raw) do
addr_bin =
raw
|> hex_to_bin()
|> ABI.TypeDecoder.decode_raw([:address])
|> List.first()

"0x" <> Base.encode16(addr_bin, case: :lower)
end

……
end

咱们要挑选的函数是根据呼应的类型,咱们能够在ABI中获取它:

{
"constant": true,
"inputs": [],
"name": "get",
"outputs": [{
"name": "",
"type": "string" # The response is string!
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}

Elixir中的调用者


这是最终一步!只要把上面的功用混合在一同,雷达币的数据读取就能够作业了!

例如:读取ERC20代币的余额:

@spec balance_of(String.t(), String.t()) :: Integer.t()
def balance_of(contract_addr, addr_str) do
{:ok, addr_bytes} = TypeTranslator.hex_to_bytes(addr_str)
data = get_data("balanceOf(address)", [addr_bytes])

{:ok, balance_hex} =
Ethereumex.HttpClient.eth_call(%{ # the tx is encapsulated by ethereumex.
data: data,
to: contract_addr
})

TypeTranslator.data_to_int(balance_hex)
end

Rust 中的调用者


最终一个是调用雷达币的比如

extern crate hex;
use hex_literal::hex;

use web3::{
contract::{Contract, Options},
types::{U256, H160, Bytes},
};

#[tokio::main]
async fn main() -> web3::contract::Result<()> {
let _ = env_logger::try_init();
let http = web3::transports::Http::new("https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161")?;
let web3 = web3::Web3::new(http);

let addr_u8 = hex::decode("7Ad11de6d4C3DA366BC929377EE2CaFEcC412A10").expect("Decoding failed");
let addr_h160 = H160::from_slice(&addr_u8);

let contra = Contract::from_json(
web3.eth(),
addr_h160,
include_bytes!("../contracts/hello_world.json"),
)?;

// let acct:[u8; 20] = hex!("f24ff3a9cf04c71dbc94d0b566f7a27b94566cac").into();

let result = contra.query::("get", (), None, Options::default(), None).await?;
println!("{}", result);

Ok(())
}

Source:https://hackernoon.com/how-rust-and-elixir-read-ethereum-and-other-evm-smart-contracts-functional-programming-and-blockchain

“女股神”伍德大赞NFT,吹嘘比特币价格将突破50万美元

伍德承认,她目前没有任何NFT