#abi #abigen #enums #contract #macro #starknet #struct

sb-starknet-abigen-macros

由 gilhm 开发的 StarkNet ABI 生成器宏

3 个版本

0.1.2 2023 年 12 月 9 日
0.1.1 2023 年 12 月 9 日
0.1.0 2023 年 12 月 6 日

#54#starknet


switchboard-starknet-sdk 中使用

Apache-2.0

43KB
821

starknet-abigen-rs 的过程宏

abigen

abigen 宏旨在从智能合约的 ABI 生成 Rust 绑定。生成的绑定包含 ABI 文件中存在的所有函数、事件、结构和枚举。

一些类型直接映射到 Rust 原生类型(如整数、ResultOption、布尔值等),其他特定类型如 ContractAddressClassHashEthAddressstarknet-rs 管理,而 ABI 中找到的所有其他类型都根据需要生成为 structenum

abigen 将生成所有必要的序列化/反序列化代码,以便与纯 Rust 类型一起使用。

例如

// Cairo function like fn view_1(self: @ContractState, v: felt252, s: Span<felt252>)
// is generated in rust like:

fn view_1(v: FieldElement, s: Vec<FieldElement>);

要为您的合约生成绑定,您可以执行以下操作

use starknet::macros::abigen;

abigen!(MyContract, "/path/to/abi.json");

这将生成所有类型和两个 struct,用于合约

  1. MyContractReader,用于调用仅读取区块链状态的 view 函数。要初始化一个读取器,您需要一个合约地址和一个提供者

    let rpc_url = Url::parse("http://0.0.0.0:5050").unwrap();
    let provider = JsonRpcClient::new(HttpTransport::new(rpc_url.clone()));
    let contract_address = FieldElement::from_hex_be("0x123...").unwrap();
    
    let reader = MyContractReader::new(contract_address, &provider);
    let result = reader.my_view_1().await;
    
  2. MyContract,它反过来用于调用 external 函数,其中实际上会将事务发送到区块链。这需要一个账户来签署这些事务

    let rpc_url = Url::parse("http://0.0.0.0:5050").unwrap();
    let provider = JsonRpcClient::new(HttpTransport::new(rpc_url.clone()));
    
    let signer = LocalWallet::from(SigningKey::from_secret_scalar(
         FieldElement::from_hex_be("<PRIVATE_KEY_HEX>").unwrap(),
    ));
    
    let account_address = FieldElement::from_hex_be("<ACCOUNT_ADDRESS_HEX>").unwrap();
    let account = SingleOwnerAccount::new(
         provider.clone(),
         signer,
         address,
         felt!("0x4b4154414e41"), // KATANA
         ExecutionEncoding::Legacy,
     );
    
    let contract_address = FieldElement::from_hex_be("0x123...").unwrap();
    
    let reader = MyContract::new(contract_address, &account);
    let result = reader.my_external_1().await;
    

abigen 宏提供的另一个功能是反序列化事件的能力。在 ABI 中,始终有一个包含在您的合约中声明的所有事件的 Event 枚举。

然后您可以执行以下操作

let even_page = provider.fetch_events(...);
for e in event_page.events {
  let my_event: Event = match e.try_into() {
    Ok(ev) => ev,
    Err(_) => continue; // This is an event from an other contract or you may use an out-dated ABI.
  };

  match my_event {
    Event::MyEventA(a) => // work with a, already typed and deserialized,
    Event::MyEventB(b) => // work with b, already typed and deserialized,
    ...
  };
}

依赖项

~12–27MB
~409K SLoC