狗哥区块链与AI精品内容集@NonceGeek

2025年03月28日更新 75 人订阅
原价: ¥ 20 限时优惠
专栏简介 「造」最关键的是什么?| Hackathon 漫游指南(贰) Why Hackathon?| Hackathon 漫游指南(壹) 设计「众人维护」的 BuidlerBoard | BeWater.xyz Movement 白皮书中文版 Rebuidl RSS 生产因素与反生产因素 | 独立黑客创业手册(陆) 组织 | 独立黑客创业手册(伍) 生产 | 独立黑客创业手册(肆) 销售 | 独立黑客创业手册(叄) 最优先的能力 | 独立黑客创业手册(贰) 为什么从独立黑客开始 | 独立黑客创业手册(壹) Aptos Token Object V2 | Move dApp 极速入门(贰拾肆) 可編程交易塊 | Move dApp 極速入門(貳拾叁) Aptos 密鑰輪換 | Move dApp 極速入門(貳拾貳) Aptos 对象模型 | Move dApp 极速入门(贰拾壹) Aptos Moveflow SDK使用指南 | Move dApp 极速入门(贰拾) Sui 上简单 Swap 的实现 | Move dApp 极速入门(拾玖) 用 Elixir 交互 Aptos | Move dApp 极速入门(拾捌) Sui 链上数据查询 | Move dApp 极速入门(拾柒) SUI 合约测试攻略 | Move dApp 极速入门(拾陆) Sui 数据类型详解 | Move dApp 极速入门(拾伍) Airdropper Contract in Aptos | Move dApp 极速入门(拾肆) Sandwich合约源码解析 | Move dApp 极速入门(拾叁) Sui 极速上手 | Move dApp 极速入门(拾贰) scaffold-aptos 脚手架 | Move dApp 极速入门(拾壹) 对 DID Document 的思考 | Move dApp 极速入门(九) DID中地址聚合器的实现 | Move dApp 极速入门(八) 值的存取应用3.0 | Web3.0 dApp 开发(五) 合约数据类型综述 | Move dApp 极速入门(四) 操作资源 | Move dApp 极速入门(三) 第一个 Move dApp | Move dApp 极速入门(二) Hello Move | Move dApp极速入门(一) Staker | Web3.0 dApp 开发(九) Token 自动售卖机 | Web3.0 dApp 开发(七) SVG NFT 全面实践 | Web3.0 dApp 开发(六) 值的存取应用2.0 | Web3.0 dApp 开发(四) 值的存取应用1.0 | Web3.0 dApp开发(三) Scaffold-eth 快速上手 | Web3.0 dApp 开发(二) eth.build 快速上手 | Web3.0 dApp 开发(一) 1 小时理解比特币系统 【NonceGeek Workshop 0x01总结】基于链上数据生成游戏地图 Remix 完全本地化部署 NFT:实体与虚拟载体的主与辅 | 狗哥的元宇宙思辨(一) Web3Camp 内容大全@NonceGeek 用 Python 创建一条 Pow 区块链(上) 区块链与共识机制演变史 基于 Etherscan 实现 Blockchain Syncer 【论文分享】去中心化社会:寻找 Web3 的灵魂(上) 【论文分享】去中心化社会:寻找 Web3 的灵魂(下) Ted Yin | 2021 年的区块链基础设施将是什么? 0. 公链、联盟链与分布式未来(全文) 基于 Infura 与 Web3py 部署调用 Hello 合约全过程 | 以太坊开发极速入门 太上中的基因设计与Binary | 函数式与区块链(一) 理解以太坊合约数据读取过程 | 函数式与区块链(二) Hello, Ink! | 用 Rust 写智能合约(一) Mapping 数据结构 | 用 Rust 写智能合约(二) 用 Rust 程序和 Webase 交互 | Rust 学习笔记(四) 用 Sqlite 存储 WeId | Rust 学习笔记(五) 链上注册WeId与错误处理 | Rust 学习笔记(六) WeId 链上创建与本地存储的完整闭环 | Rust 学习笔记(七) 以太坊上的核心开发者 Austin | 以太坊上的最佳开发实践 1. FISCO BCOS 开发环境节点搭建全攻略 伪代码简述 ECDSA 签名过程 | 联盟链开发 WeIdentity 源码分析 | 狗哥解码 WeIdentity 源码分析 | 狗哥解码 FISCO BCOS 介绍 | 联盟链开发 给Remix升个级 | 联盟链开发 2. 控制台的安装与使用 3. 【实验】补全一个区块链应用 4. 控制台的Web化 5. Web化控制台2.0:打造团队共用区块链学习平台 6. 使用脚手架快速搭建 Java DApp 【视频+文字】分布式思维 Rebuidl RSS (EN)

用 Elixir 交互 Aptos | Move dApp 极速入门(拾捌)

  • 李大狗
  • 发布于 2023-08-20 12:23
  • 阅读 3485

函数式语言 <> 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 已完成功能列表:

  • Acct Operations(账户相关操作)
  • Read Resource(读取资源)
  • Read Events(读取事件)
  • Call Func(调取函数)
  • Func Parser(解析字符串格式的函数,如0xdea79e568e00066f60fbfe6ac6d8a9ef2fabbeadc6aae1ec9158d50f6efe4ac8::addr_aggregator::create_addr_aggregator(u64,vector&lt;string>)

0x01 安装

创建一个新的示例项目:

$ 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

0x02 账户相关

我们可以通过随机种子来生成账户:

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&lt;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"
        }
      }
    }
  }
}

0x03 调取函数与读取事件

我们以 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: &lt;&lt;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")
# 这个函数生成的地址可以直接用浏览器访问.

640.png

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

在浏览器上查看,交易执行成功:

640 (1).png

我们也可以通过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"
   }
 ]}

0x04 查看资源

打开浏览器访问:

https\://explorer.aptoslabs.com/account/0xedf8dcb761e7ee7884e5a94d1f9b330f7a3ed09317bebe163738c31dc67e446f/resources

我们会发现增加了两个资源。

640 (2).png

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 极速入门(拾叁)\

Sui 极速上手 | Move dApp 极速入门(拾贰)

Move 高阶语法 | 共学课优秀笔记\

Move 基础语法 | 共学课优秀学习笔记

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 极速入门(五)\

合约数据类型综述 | Move dApp 极速入门(四)\

操作资源 | Move dApp极速入门(三)\

第一个 Move dApp | Move dApp极速入门(二)\

Hello Move | Move dApp极速入门(一)

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论