函数式语言 <> Move
NonceGeekDAO 长期聚焦于 Move 生态与 Elixir 函数式编程语言。
https\://github.com/NonceGeek/
web3_move_ex
是 NonceGeekDAO 开发的,泛 Move 生态的 Elixir SDK,目前已完成对Aptos
的基础支持。本篇文章案例可见:
https\://github.com/NonceGeek/web3_move_ex_example
Aptos 已完成功能列表:
0xdea79e568e00066f60fbfe6ac6d8a9ef2fabbeadc6aae1ec9158d50f6efe4ac8::addr_aggregator::create_addr_aggregator(u64,vector<string>)
)创建一个新的示例项目:
$ mix new web3_move_ex_example
$ # 或者 clone 现成的 github repo:
$ git clone https://github.com/NonceGeek/web3_move_ex_example.git
在mix.exs
中添加最新版本的web3_move_ex
:
defp deps do
[
{:web3_move_ex, "~> 0.4.0"}
]
end
打开交互式界面:
$ iex -S mix
我们可以通过随机种子来生成账户:
alias Web3MoveEx.Aptos
{:ok, acct} = Aptos.generate_keys()
也可以通过私钥来生成:
{:ok, acct} = Aptos.generate_keys("0xffc207d0666ca82eac4e2238d0cf15f963a03ec6a9daa617dc035b7228de1f28")
创建连接节点的 client
:
{:ok, client} = Aptos.connect(:testnet)
给账户注入一些 faucet
:
Aptos.get_faucet(client, acct)
获取余额:
Aptos.get_balance(client, acct)
可以看到获取 faucet 成功了:
iex(10)> Aptos.get_balance(client, acct)
%{
coin: %{value: "100000000"},
deposit_events: %{
counter: "1",
guid: %{
id: %{
addr: "0xe59f44953723d5a8e26df9d3d4a613a2da3ff9f7dc4214dc281e10a244f39e3f",
creation_num: "2"
}
}
},
frozen: false,
withdraw_events: %{
counter: "0",
guid: %{
id: %{
addr: "0xe59f44953723d5a8e26df9d3d4a613a2da3ff9f7dc4214dc281e10a244f39e3f",
creation_num: "3"
}
}
}
}
我们可以把刚才的一系列步骤打包成一个函数:
def gen_acct_and_get_faucet(network_type) do
{:ok, acct} = Aptos.generate_keys()
{:ok, client} = Aptos.connect(network_type)
{:ok, _res} = Aptos.get_faucet(client, acct)
Process.sleep(2000) # 用 2 秒等待交易成功
%{res: Aptos.get_balance(client, acct), acct: acct}
end
函数执行结果:
iex(7)> %{acct: acct} = Web3MoveExExample.gen_acct_and_get_faucet(:testnet)
%{
acct: #Account<0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f>,
res: %{
coin: %{value: "100000000"},
deposit_events: %{
counter: "1",
guid: %{
id: %{
addr: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
creation_num: "2"
}
}
},
frozen: false,
withdraw_events: %{
counter: "0",
guid: %{
id: %{
addr: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
creation_num: "3"
}
}
}
}
}
我们以 MoveDID
在测试网络上的合约为例,演示如何通过web3_move_ex
来进行合约调用。
MoveDID Repo:https\://github.com/NonceGeek/MoveDID
Smart Contract on Testnet:
0x06195d43edde4b1cd3a96f7838686b9b12b51023cd388dfb21f123b350f4ec46
我们可以通过 func_string 来生成 func:
import Web3MoveEx.Aptos
addr= "0x06195d43edde4b1cd3a96f7838686b9b12b51023cd388dfb21f123b350f4ec46" # 合约地址
init_func_str = "#{addr}::init::init(u64, string)"
{:ok, init_func} = ~a"#{init_func_str}"
结果如下:
iex(5)> {:ok, init_func} = ~a"#{init_func_str}"
{:ok,
%Web3MoveEx.Aptos.Types.Function{
address: <<6, 25, 93, 67, 237, 222, 75, 28, 211, 169, 111, 120, 56,
104, 107, 155, 18, 181, 16, 35, 205, 56, 141, 251, 33, 241, 35,
179, 80, 244, 236, 70>>,
address_encoded: "0x06195d43edde4b1cd3a96f7838686b9b12b51023cd388dfb21f123b350f4ec46",
is_entry: true,
module: "init",
name: "init",
param_names: [],
params: [:u64, :string],
return: [],
type_params: [],
visibility: :public
}}
可以顺便检查一下events
的功能,按照合约逻辑,新添加一个DID
,会在contract_owner
下生成相应的事件。
Aptos.build_event_path(client, addr, "#{addr}::addr_aggregator::CreateAddrAggregatorEventSet", "create_addr_aggregator_events")
# 这个函数生成的地址可以直接用浏览器访问.
Aptos.get_events(client, addr, "#{addr}::addr_aggregator::CreateAddrAggregatorEventSet", "create_addr_aggregator_events")
# 这个函数可以拿到 Event 结果.
Result:
iex(13)> Aptos.get_events(client, addr, "#{addr}::addr_aggregator::CreateAddrAggregatorEventSet", "create_addr_aggregator_events")
{:ok, []}
生成 payload
:
payload = Aptos.call_function(f, [], [1, "testAcct"])
提交交易:
Aptos.submit_txn_with_auto_acct_updating(client, acct, payload)
# 方法 0x01:自动更新 acct 的信息
# Aptos.submit_txn(client, acct, payload)
# 方法 0x02:不自动更新 acct 的信息
执行结果:
iex(15)> Aptos.submit_txn_with_auto_acct_updating(client, acct, payload)
{:ok,
%{
expiration_timestamp_secs: "1679451173",
gas_unit_price: "1000",
hash: "0x931c2821df3e6c9c40bf00d5ed7e20aa1172a053d3c3d658a9f7bd31f17d91f6",
max_gas_amount: "2000",
payload: %{
arguments: ["1", "testAcct"],
function: "0x6195d43edde4b1cd3a96f7838686b9b12b51023cd388dfb21f123b350f4ec46::init::init",
type: "entry_function_payload",
type_arguments: []
},
sender: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
sequence_number: "0",
signature: %{
public_key: "0x361c4395cc87cf951dc5f879bdf2c2f91df3078c9a2ee4b5bf9892243a24a5fb",
signature: "0x94f9cbf17c5095e76ea30a88d6683c9951fbfa3b1e261ca6b4722fac985946dcc0f5e7a8c03e6b322f39b102874484b620cf0943c672eadd4fd9b3505e65f804",
type: "ed25519_signature"
}
}}
在浏览器上查看,交易执行成功:
我们也可以通过check_tx_res_by_hash
查看:
Aptos.check_tx_res_by_hash(client, hash) # return true or false
我们同样可以将call_fun_init
的过程封装为一个函数:
def call_func_init(client, acct, contract_addr, did_type, description) do
{:ok, f} = gen_func_init(contract_addr)
payload = Aptos.call_function(f, [], [did_type, description])
{:ok, %{hash: hash} = tx} = Aptos.submit_txn_with_auto_acct_updating(client, acct, payload)
Process.sleep(2000) # 用 2 秒等待交易成功
res = Aptos.check_tx_res_by_hash(client, hash)
%{res: res, tx: tx}
end
def gen_func_init(contract_addr) do
init_func_str = "#{contract_addr}::init::init(u64, string)"
~a"#{init_func_str}"
end
执行结果:
iex(22)> Web3MoveExExample.call_func_init(client, acct, addr, 1, "test Acct")
%{
res: true,
tx: %{
expiration_timestamp_secs: "1679475296",
gas_unit_price: "1000",
hash: "0x73687a7e4c953f3cf13a768fe03560a61c06615fa8c089888f23cd3ccd8dc6e8",
max_gas_amount: "2000",
payload: %{
arguments: ["1", "test Acct"],
function: "0x6195d43edde4b1cd3a96f7838686b9b12b51023cd388dfb21f123b350f4ec46::init::init",
type: "entry_function_payload",
type_arguments: []
},
sender: "0xc193cd62bab00790d40265505ce894552c14a3693aca9bc2310ee0ecdc53780b",
sequence_number: "0",
signature: %{
public_key: "0x6bfa0d62dd63ea8a4291ffec10fc448ab554188d7765a9faf1b0992dbb199c38",
signature: "0xc8a9d4368a0cc2daff3add7162745990d3bd9c33ec6f1112b5dfe45cdd25d4fdf5d19a361048b67081e3ce9c242c93266af4736d8c86541906e08c2ef387ef05",
type: "ed25519_signature"
}
}
}
此时再次执行 get_events
,会发现 events 成功生成:
iex(16)> Aptos.get_events(client, addr, "#{addr}::addr_aggregator::CreateAddrAggregatorEventSet", "create_addr_aggregator_events")
{:ok,
[
%{
data: %{
description: "testAcct",
key_addr: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
type: "1"
},
guid: %{
account_address: "0x6195d43edde4b1cd3a96f7838686b9b12b51023cd388dfb21f123b350f4ec46",
creation_number: "4"
},
sequence_number: "0",
type: "0x6195d43edde4b1cd3a96f7838686b9b12b51023cd388dfb21f123b350f4ec46::addr_aggregator::CreateAddrAggregatorEvent",
version: "473098605"
}
]}
打开浏览器访问:
https\://explorer.aptoslabs.com/account/0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f/resources
我们会发现增加了两个资源。
image-20230322101914974
这个资源我们同样可以通过 web3_move_ex
获取到:
Aptos.get_resource(client, account.address_hex, "#{addr}::addr_aggregator::AddrAggregator")
结果:
iex(20)> Aptos.get_resource(client, "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f", "#{addr}::addr_aggregator::AddrAggregator")
{:ok,
%{
data: %{
add_addr_events: %{
counter: "0",
guid: %{
id: %{
addr: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
creation_num: "4"
}
}
},
addr_infos_map: %{
handle: "0xbae0b5ae8c373db15ca2f71a18f92ed3ed363e5730cf3f8a90791c04ff6908da"
},
addrs: [],
delete_addr_events: %{
counter: "0",
guid: %{
id: %{
addr: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
creation_num: "7"
}
}
},
description: "testAcct",
key_addr: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
max_id: "0",
modified_counter: "0",
type: "1",
update_addr_events: %{
counter: "0",
guid: %{
id: %{
addr: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
creation_num: "6"
}
}
},
update_addr_signature_events: %{
counter: "0",
guid: %{
id: %{
addr: "0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f",
creation_num: "5"
}
}
}
},
type: "0x6195d43edde4b1cd3a96f7838686b9b12b51023cd388dfb21f123b350f4ec46::addr_aggregator::AddrAggregator"
}}
前文链接:
Sui 链上数据查询 | Move dApp 极速入门(拾柒)\
SUI 合约测试攻略 | Move dApp 极速入门(拾陆)\
Sui 数据类型详解 | Move dApp 极速入门(十五)\
Airdropper Contract in Aptos | Move dApp 极速入门(拾肆)\
Sandwich合约案例实践 | Move dApp 极速入门(拾叁)\
scaffold-aptos 脚手架 | Move dApp 极速入门(拾壹)
Aptos NFT 发行指南 | Move dApp 极速入门(十)
对 DID Document 的思考 | Move dApp 极速入门(九)\
DID中地址聚合器的实现 | Move dApp 极速入门(八)
Aptos 中的智能合约形式化验证 | Move dApp 极速入门(七)
Aptos CLI使用指南与REPL设计建议 | Move dApp 极速入门(六)\
实现一套 DID 之总体设计 | Move dApp 极速入门(五)\
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!