37 个版本 (12 个破坏性版本)

0.17.4 2024年8月16日
0.17.0 2024年7月11日
0.13.1 2024年2月19日
0.12.1 2023年12月18日
0.6.1 2023年7月19日

#284 in 神奇豆子

Download history 185/week @ 2024-04-28 529/week @ 2024-05-05 132/week @ 2024-05-12 15/week @ 2024-05-19 138/week @ 2024-05-26 53/week @ 2024-06-02 325/week @ 2024-06-09 18/week @ 2024-06-16 155/week @ 2024-06-23 69/week @ 2024-06-30 320/week @ 2024-07-07 104/week @ 2024-07-14 123/week @ 2024-07-21 429/week @ 2024-07-28 206/week @ 2024-08-04 432/week @ 2024-08-11

每月1,198次下载
用于 tonapi

MITLGPL-3.0+

445KB
11K SLoC

Open Network 的 Rust SDK

Open Network 的 Rust SDK

功能

  • Open Network 的 Rust SDK
  • 使用 tonlibjson 作为数据提供者
  • 支持解析和生成单元方法,以便更方便地与数据结构交互
  • 支持钱包版本(3, 3修订版2, 4修订版2)
  • 推导钱包地址
  • 支持 TON 助记符
  • 交易 NaCL 兼容的 Ed25519 签名
  • 支持代币功能:获取代币数据和代币钱包地址
  • 支持内部和外部代币元数据加载
  • 连接池和重试支持,以改善服务器级交互
  • 支持 IPFS 代币元数据

依赖项

tonlib-sys - https://github.com/ston-fi/tonlib-sys

先决条件

对于 Linux

sudo apt install build-essential cmake libsodium-dev libsecp256k1-dev lz4 liblz4-dev

对于 macOS

brew install --cask mactex
brew install readline secp256k1 ccache pkgconfig cmake libsodium

构建库

您可以使用以下命令构建库

cargo build

用法

要在您的 Rust 应用程序中使用此库,请将以下内容添加到您的 Cargo.toml 文件中

[dependencies]
tonlib = "0.15"

然后,在您的 Rust 代码中,您可以导入库

use tonlib;

单元

创建一个 Cell 并向其中写入数据

use anyhow::anyhow;
use tonlib::address::TonAddress;
use tonlib::cell::CellBuilder;

fn write_cell() -> anyhow::Result<()> {
let mut writer = CellBuilder::new();
let addr = TonAddress::from_base64_url("EQDk2VTvn04SUKJrW7rXahzdF8_Qi6utb0wj43InCu9vdjrR")?;
let cell = writer
    .store_u32(32, 0xFAD45AADu32)?
    .store_bit(true)?
    .store_u8(8, 234u8)?
    .store_slice(&[0xFA, 0xD4, 0x5A, 0xAD, 0xAA, 0x12, 0xFF, 0x45])?
    .store_address(&addr)?
    .store_string("Hello, TON")?
    .build()?;
    # Ok(())
}

Cell 读取数据

use tonlib::cell::Cell;
fn read_cell(cell: Cell) -> anyhow::Result<()> {
    let mut reader = cell.parser();
    let u32_value = reader.load_u32(32)?;
    let bit_value = reader.load_bit()?;
    let u8_value = reader.load_u8(8)?;
    let bytes_value = reader.load_bytes(8)?;
    let address_value = reader.load_address()?;
    let str_value = reader.ensure_empty()?;
    Ok(())
}

TON 区块链客户端

要调用方法,请创建一个客户端


use tonlib::client::TonClient;
use tonlib::client::TonClientBuilder;
async fn create_client()-> anyhow::Result<()>{
    TonClient::set_log_verbosity_level(2); //setup of logging level
    let client = TonClientBuilder::new()
    .with_pool_size(10)
    .with_keystore_dir(String::from("/tmp"))
    .build()
    .await?;
Ok(())
}

TonClient::set_log_verbosity_level(2); 设置日志级别。

默认情况下,连接到主网。但在创建客户端时也可以指定测试网络

use tonlib::config::TESTNET_CONFIG;
use tonlib::client::TonConnectionParams;
use tonlib::client::TonClientBuilder;
async fn create_client_with_conn_params()-> anyhow::Result<()>{
    let client = TonClientBuilder::new()
        .with_connection_params(&TonConnectionParams {
            config: TESTNET_CONFIG.to_string(),
            blockchain_name: None,
            use_callbacks_for_network: false,
            ignore_cache: false,
            keystore_dir: None,
        })
        .with_pool_size(10)
        .build()
        .await?;
    Ok(())
}

创建客户端后,您可以在 TON 区块链上调用方法

use tonlib::address::TonAddress;
use tonlib::tl::InternalTransactionId;
use tonlib::tl::NULL_BLOCKS_ACCOUNT_TRANSACTION_ID;
use tonlib::tl::BlocksTransactions;
use tonlib::tl::BlocksShards;
use tonlib::tl::BlockId;
use tonlib::tl::BlocksMasterchainInfo;
use tonlib::client::TonClient;
use tonlib::client::TonClientInterface;

async fn call_blockchain_methods()-> anyhow::Result<()>{
    let client = TonClient::builder().build().await?;
    let (_, info) = client.get_masterchain_info().await?;
    println!("MasterchainInfo: {:?}", &info);
    let block_id = BlockId {
        workchain: info.last.workchain,
        shard: info.last.shard,
        seqno: info.last.seqno,
    };
    let block_id_ext = client.lookup_block(1, &block_id, 0, 0).await?;
    println!("BlockIdExt: {:?}", &block_id_ext);
    let block_shards: BlocksShards = client.get_block_shards(&info.last).await?;
    let mut shards = block_shards.shards.clone();
    println!("Shards: {:?}", &block_shards);
    shards.insert(0, info.last.clone());
    for shard in &shards {
        println!("Processing shard: {:?}", shard);
        let workchain = shard.workchain;
        let txs: BlocksTransactions = client
            .get_block_transactions(&shard, 7, 1024, &NULL_BLOCKS_ACCOUNT_TRANSACTION_ID)
            .await?;
        println!(
            "Number of transactions: {}, incomplete: {}",
            txs.transactions.len(),
            txs.incomplete
        );
        for tx_id in txs.transactions {
            let mut t: [u8; 32] = [0; 32];
            t.clone_from_slice(tx_id.account.as_slice());
            let addr = TonAddress::new(workchain, &t);
            let id = InternalTransactionId {
                hash: tx_id.hash.clone(),
                lt: tx_id.lt,
            };
            let tx = client
                .get_raw_transactions_v2(&addr, &id, 1, false)
                .await?;
            println!("Tx: {:?}", tx.transactions[0])
        }
    }
    Ok(())
}

您可以获取任何合约的账户状态

use tonlib::address::TonAddress;
use tonlib::client::TonClient;
use crate::tonlib::client::TonClientInterface;

async fn get_state()-> anyhow::Result<()>{  
    let client = TonClient::builder().build().await?;
    let address = TonAddress::from_base64_url(
        "EQB3ncyBUTjZUA5EnFKR5_EnOMI9V1tTEAAPaiU71gc4TiUt-",
    )?;
    let r = client
            .get_account_state(&address)
            .await;
    Ok(())
}

与合约和代币操作

与代币和钱包操作的方法

use tonlib::client::TonClient;
use tonlib::contract::TonContractFactory;
use crate::tonlib::contract::JettonMasterContract;
use crate::tonlib::contract::JettonWalletContract;

async fn method_call() -> anyhow::Result<()> { 
    let client = TonClient::builder().build().await?;
    let contract_factory = TonContractFactory::builder(&client).build().await?;
    let master_contract = contract_factory.get_contract(
        &"EQDk2VTvn04SUKJrW7rXahzdF8_Qi6utb0wj43InCu9vdjrR".parse()?,
    );
    let jetton_data = master_contract.get_jetton_data().await?;

    let wallet_contract = contract_factory.get_contract(
        &"EQCGY3OVLtD9KRcOsP2ldQDtuY0FMzV7wPoxjrFbayBXc23c".parse()?,
    );
    let wallet_data = wallet_contract.get_wallet_data().await?;
    Ok(())
}

要加载代币的元数据,可以使用通用的 MetaLoader 和它的类型别名: JettonMetaLoader, NftItemMetaLoader, NftCollectionMetaLoader

use tonlib::client::TonClient;
use tonlib::contract::TonContractFactory;
use tonlib::contract::JettonMasterContract;
use tonlib::meta::JettonMetaLoader;
use tonlib::meta::LoadMeta;

async fn load_meta() -> anyhow::Result<()> { 
    let client = TonClient::builder().build().await?;
    let contract_factory = TonContractFactory::builder(&client).build().await?;
    let contract =
        contract_factory.get_contract(&"EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728".parse()?); 
    let jetton_data = contract.get_jetton_data().await?;
    let loader = JettonMetaLoader::default()?;
    let content_res = loader.load(&jetton_data.content).await?;

Ok(())
}

获取代币的钱包地址

use tonlib::address::TonAddress;
use tonlib::client::TonClient;
use tonlib::contract::TonContractFactory;
use tonlib::contract::JettonMasterContract; 

async fn get_wallet_address() -> anyhow::Result<()> {

    let client = TonClient::default().await?;
    let contract_factory = TonContractFactory::builder(&client).build().await?;
    let contract =
        contract_factory.get_contract(&"EQDk2VTvn04SUKJrW7rXahzdF8_Qi6utb0wj43InCu9vdjrR".parse()?,
    );
    let owner_address = TonAddress::from_base64_url(
        "EQB2BtXDXaQuIcMYW7JEWhHmwHfPPwa-eoCdefiAxOhU3pQg",
    )?;
    let wallet_address = contract.get_wallet_address(&owner_address).await?;
    Ok(())
}

向 TON 发送消息

从密语创建密钥对( )

use tonlib::mnemonic::Mnemonic;
use tonlib::mnemonic::KeyPair;
async fn create_key_pair() -> anyhow::Result<()> {
    let mnemonic = Mnemonic::new(
        vec![
            "dose", "ice", "enrich", "trigger", "test", "dove", "century", "still", "betray",
            "gas", "diet", "dune",
        ],
        &None,
        )?;
    let key_pair = mnemonic.to_key_pair();
    Ok(())
}

现在您可以为 TON 区块链发送转账消息做好了准备。

创建代币转账



use num_bigint::BigUint;
use std::time::SystemTime;

use tonlib::address::TonAddress;
use tonlib::cell::BagOfCells;
use tonlib::client::TonClient;
use tonlib::client::TonClientInterface;
use tonlib::contract::TonContractFactory;
use tonlib::contract::JettonMasterContract;
use tonlib::message::JettonTransferMessage;

use tonlib::message::TransferMessage;
use tonlib::mnemonic::KeyPair;
use tonlib::mnemonic::Mnemonic;
use tonlib::wallet::TonWallet;
use tonlib::wallet::WalletVersion;

async fn create_jetton_transfer() -> anyhow::Result<()> {

    let seqno:i32 = 30000000;

    let self_address: TonAddress = "EQB2BtXDXaQuIcMYW7JEWhHmwHfPPwa-eoCdefiAxOhU3pQg "
        .parse()
        .unwrap();
    let mnemonic_str = "mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic mnemonic";
    let mnemonic: Mnemonic = Mnemonic::from_str(mnemonic_str, &None).unwrap();
    let key_pair: KeyPair = mnemonic.to_key_pair().unwrap();
    let jetton_master_address: TonAddress = "EQDCJL0iQHofcBBvFBHdVG233Ri2V4kCNFgfRT-gqAd3Oc86"
        .parse()
        .unwrap();

    let client = TonClient::default().await?;
        let contract_factory = TonContractFactory::builder(&client).build().await?;
    let jetton_master =
        contract_factory.get_contract(&jetton_master_address);
    let self_jetton_wallet_addr = jetton_master.get_wallet_address(&self_address).await?;
    let wallet = TonWallet::derive_default(WalletVersion::V4R2, &key_pair)?;
    let dest: TonAddress = "<destination wallet address>".parse()?;
    let src: TonAddress = "<source wallet address>".parse()?;
    let jetton_amount = BigUint::from(1000000u64);
    let jetton_transfer = JettonTransferMessage::new(&dest, &jetton_amount)
        .with_query_id(100500)
        .with_response_destination(&self_address)
        .build()?;
    let ton_amount = BigUint::from(200000000u64); // 0.2 TON
    let transfer = TransferMessage::new(&src, &ton_amount)
        .with_data(jetton_transfer)
        .build()?;
    let now = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)?
        .as_secs() as u32;
    let body = wallet.create_external_body(now + 60, seqno.try_into().unwrap(), vec![transfer])?;
    let signed = wallet.sign_external_body(&body)?;
    let wrapped = wallet.wrap_signed_body(signed)?;
    let boc = BagOfCells::from_root(wrapped);
    let tx = boc.serialize(true)?;

    let hash = client.send_raw_message_return_hash(tx.as_slice()).await?;

    Ok(())
}

创建简单转账


use anyhow::anyhow;
use num_bigint::BigUint;
use std::time::SystemTime;

use tonlib::address::TonAddress;
use tonlib::cell::BagOfCells;
use tonlib::message::TransferMessage;
use tonlib::wallet::TonWallet;
use tonlib::client::TonClient;
use tonlib::client::TonClientInterface;
use tonlib::mnemonic::KeyPair;
use tonlib::mnemonic::Mnemonic;
use tonlib::wallet::WalletVersion;


async fn create_simple_transfer() -> anyhow::Result<()> {
    let mnemonic = Mnemonic::new(
        vec![
            "dose", "ice", "enrich", "trigger", "test", "dove", "century", "still", "betray",
            "gas", "diet", "dune",
        ],
        &None,
        )?;
    let key_pair = mnemonic.to_key_pair()?;
    let seqno =  30000000;
    

    let client = TonClient::default().await?;
    let wallet = TonWallet::derive_default(WalletVersion::V4R2, &key_pair)?;
    let dest: TonAddress = "<destination wallet address>".parse()?;
    let value = BigUint::from(10000000u64); // 0.01 TON
    let transfer = TransferMessage::new(&dest, &value).build()?;
    let now = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)?
        .as_secs() as u32;
    let body = wallet.create_external_body(now + 60, seqno, vec![transfer])?;
    let signed = wallet.sign_external_body(&body)?;
    let wrapped = wallet.wrap_signed_body(signed)?;
    let boc = BagOfCells::from_root(wrapped);
    let tx = boc.serialize(true)?;
    let hash = client.send_raw_message_return_hash(tx.as_slice()).await?;

    Ok(())
}

交叉编译

为了针对特定的 CPU 微架构进行交叉编译,将环境变量 TARGET_CPU_MARCH 设置为所需的值。支持的值可以在 https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html 中查看

贡献

如果您想为此库做出贡献,请随时在 GitHub 上提交拉取请求。

许可

此库采用 MIT 许可证。有关详细信息,请参阅 LICENSE 文件。-->

依赖项

~13–26MB
~381K SLoC