| Crates.io | rust_pact |
| lib.rs | rust_pact |
| version | 0.1.8 |
| created_at | 2025-09-05 07:03:21.158331+00 |
| updated_at | 2025-12-15 08:10:15.042904+00 |
| description | Pact smart contract client for kadena blockchain |
| homepage | https://github.com/cyberfly-io/rust-pact |
| repository | https://github.com/cyberfly-io/rust-pact |
| max_upload_size | |
| id | 1825172 |
| size | 132,173 |
A Rust library for interacting with Kadena Pact smart contracts and blockchain operations.
use rust_pact::crypto;
use rust_pact::utils::KeyPair;
use rust_pact::api;
use rust_pact::lang;
use rust_pact::simple;
use rust_pact::fetch;
fn main() {
// Generate a key pair
let (public_key, secret_key) = crypto::gen_key_pair();
let kp = KeyPair { public_key, secret_key, clist: None };
// Prepare meta and cap
let meta = lang::mk_meta("sender", "0", 0.00001, 1000, 1234567890, 600);
let cap = lang::mk_cap("role", "desc", "cap.name", vec![json!("arg1"), json!("arg2")]);
// Prepare exec command
let pact_code = "(free.my-module.my-func arg1 arg2)";
let env_data = json!({"key": "value"});
let key_pairs = vec![kp.clone()];
let exec_cmd = simple::exec::prepare_exec_cmd(
pact_code,
env_data,
meta.clone(),
Some("testnet04".to_string()),
None,
key_pairs.clone()
);
println!("Exec Command: {}", exec_cmd);
}
For more examples, see the examples/ directory.
use rust_pact::{tools, gen_key_pair};
use rust_pact::utils::KeyPair;
// Run with: cargo run --example tools
// To perform real network calls set env var RUN_LIVE=1 (these hit public Chainweb endpoints)
fn main() {
// WARNING: Hard‑coding real secret keys is unsafe. Use env vars or a secure store in production.
let key_pair = KeyPair {
public_key: "10375651f1ca0110468152bb8f47b7b8a469e36dfab1c83adf60cab84b5726d3".into(),
secret_key: "18d3a823139cf60cab0b738e7605bb9e4a2f3ff245c270fa55d197f9b3c4c004".into(),
clist: None
};
let token_address = "coin"; // same as Python call
let sender_account = "k:10375651f1ca0110468152bb8f47b7b8a469e36dfab1c83adf60cab84b5726d3";
let receiver_account = "k:03df480e0b300c52901fdff265f0460913fea495f39972321698740536cc38e3";
let receiver_public_key = "03df480e0b300c52901fdff265f0460913fea495f39972321698740536cc38e3";
let amount = 2.0_f64;
let chain_id = "1";
let network_id = "testnet04"; // matches your Python call
let res = tools::token_transfer(
token_address,
sender_account,
receiver_account,
receiver_public_key,
amount,
key_pair,
chain_id,
network_id
);
println!("Transfer result: {}", res);
}
use rust_pact::{tools, fetch};
use rust_pact::utils::KeyPair;
use serde_json::json;
fn main() {
// Cross-chain transfer from chain 1 to chain 2
let sender_keypair = KeyPair {
public_key: "10375651f1ca0110468152bb8f47b7b8a469e36dfab1c83adf60cab84b5726d3".into(),
secret_key: "18d3a823139cf60cab0b738e7605bb9e4a2f3ff245c270fa55d197f9b3c4c004".into(),
clist: None
};
let receiver_keypair = KeyPair {
public_key: "03df480e0b300c52901fdff265f0460913fea495f39972321698740536cc38e3".into(),
secret_key: "".into(), // Only public key needed for completion
clist: None
};
let token_address = "coin";
let sender_account = "k:10375651f1ca0110468152bb8f47b7b8a469e36dfab1c83adf60cab84b5726d3";
let receiver_account = "k:03df480e0b300c52901fdff265f0460913fea495f39972321698740536cc38e3";
let receiver_public_key = "03df480e0b300c52901fdff265f0460913fea495f39972321698740536cc38e3";
let amount = 1.0_f64;
let source_chain_id = "1";
let target_chain_id = "2";
let network_id = "testnet04";
// Step 1: Initiate cross-chain transfer on source chain
let transfer_result = tools::crosschain_transfer(
token_address,
sender_account,
receiver_account,
receiver_public_key,
amount,
sender_keypair.clone(),
source_chain_id,
target_chain_id,
network_id
);
println!("Transfer initiated: {}", transfer_result);
// Step 2: Poll for completion and get pact ID
let request_key = "transaction-hash-from-step-1";
let api_host = tools::get_api_host(network_id, source_chain_id);
let poll_cmd = json!({"requestKeys": [request_key]});
let poll_result = fetch::poll(&poll_cmd, &api_host);
// Step 3: Get SPV proof
let spv_cmd = json!({
"requestKey": request_key,
"targetChainId": target_chain_id
});
let spv_result = fetch::spv(&spv_cmd, &api_host);
// Step 4: Complete cross-chain transfer on target chain
let pact_id = "extracted-from-poll-result";
let proof = "extracted-from-spv-result";
let complete_result = tools::crosschain_complete(
pact_id,
proof,
receiver_account,
receiver_public_key,
amount,
receiver_keypair.clone(),
target_chain_id,
network_id
);
println!("Cross-chain transfer completed: {}", complete_result);
}
For a simplified, single-call cross-chain transfer that handles all the polling and SPV proof retrieval automatically:
use rust_pact::{tools, CrossChainConfig};
use rust_pact::utils::KeyPair;
fn main() {
let sender_keypair = KeyPair {
public_key: "10375651f1ca0110468152bb8f47b7b8a469e36dfab1c83adf60cab84b5726d3".into(),
secret_key: "18d3a823139cf60cab0b738e7605bb9e4a2f3ff245c270fa55d197f9b3c4c004".into(),
clist: None
};
let receiver_keypair = KeyPair {
public_key: "03df480e0b300c52901fdff265f0460913fea495f39972321698740536cc38e3".into(),
secret_key: "".into(),
clist: None
};
let token_address = "coin";
let sender_account = "k:10375651f1ca0110468152bb8f47b7b8a469e36dfab1c83adf60cab84b5726d3";
let receiver_account = "k:03df480e0b300c52901fdff265f0460913fea495f39972321698740536cc38e3";
let receiver_public_key = "03df480e0b300c52901fdff265f0460913fea495f39972321698740536cc38e3";
let amount = 1.0_f64;
let source_chain_id = "1";
let target_chain_id = "2";
let network_id = "testnet04";
// Use default config (configurable via env vars) or customize
let config = CrossChainConfig::default(); // Or CrossChainConfig { attempts_tx: 20, ... }
let result = tools::crosschain_transfer_full(
token_address,
sender_account,
receiver_account,
receiver_public_key,
amount,
sender_keypair,
source_chain_id,
target_chain_id,
network_id,
Some(config)
);
println!("Full cross-chain result: {}", result);
// Check status
if result.get("status").and_then(|s| s.as_str()) == Some("success") {
println!("✅ Transfer completed successfully!");
} else {
println!("❌ Transfer failed: {}", result.get("error").unwrap_or(&serde_json::Value::Null));
}
}
The CrossChainConfig struct allows tuning of polling behavior:
attempts_tx: Max attempts for initial transaction polling (default: 30, 0 = infinite)interval_tx_ms: Interval between tx polls in ms (default: 5000)post_confirm_wait_ms: Delay after tx success before SPV fetch (default: 10000)attempts_spv: Max attempts for SPV proof polling (default: 0 = infinite, >0 = use limit)interval_spv_ms: Interval between SPV polls in ms (default: 5000)attempts_final: Max attempts for final completion polling (default: 30, 0 = infinite)interval_final_ms: Interval between final polls in ms (default: 5000)verbose: Enable diagnostic logging (default: false)max_total_time_ms: Max total time for all polling combined (default: 360000ms = 6min, 0 = no limit)All values can be overridden via environment variables prefixed with XCHAIN_, e.g., XCHAIN_ATTEMPTS=0 for infinite polling.
Note: SPV proof polling defaults to infinite attempts since SPV proofs can take significant time to become available after cross-chain transactions.
{
"status": "success",
"request_key_init": "KnTrT06r4gLKuA56fRMZOCBjS1MiSNoCGDO8g8VxYVI",
"init_result": {"requestKeys": ["KnTrT06r4gLKuA56fRMZOCBjS1MiSNoCGDO8g8VxYVI"]},
"init_poll_result": {"KnTrT06r4gLKuA56fRMZOCBjS1MiSNoCGDO8g8VxYVI": {"continuation": {"pactId": "pact-id-123", "step": 0}}},
"pact_id": "pact-id-123",
"spv_proof": "spv-proof-data",
"complete_result": {"requestKeys": ["completion-hash-456"]},
"request_key_complete": "completion-hash-456",
"final_poll_result": {"completion-hash-456": {"result": {"status": "success"}}}
}
Run the example: cargo run --example crosschain_full
crosschain_transfer_full)XCHAIN_MAX_TOTAL_TIME_MS for testnetConfigure cross-chain behavior via environment variables:
# Polling attempts (0 = infinite)
export XCHAIN_ATTEMPTS=10 # Transaction polling attempts
export XCHAIN_SPV_ATTEMPTS=0 # SPV polling attempts (0 = infinite - DEFAULT)
export XCHAIN_FINAL_ATTEMPTS=30 # Final completion polling attempts
# Timing (milliseconds)
export XCHAIN_INTERVAL_MS=10000 # Transaction poll interval
export XCHAIN_SPV_INTERVAL_MS=5000 # SPV poll interval
export XCHAIN_POST_CONFIRM_WAIT_MS=10000 # Wait after tx confirmation
export XCHAIN_MAX_TOTAL_TIME_MS=360000 # Total timeout (6 minutes)
# Other options
export XCHAIN_VERBOSE=1 # Enable verbose logging
export RUN_LIVE=1 # Enable live network calls
For testing cross-chain operations:
testnet04) for developmentXCHAIN_SPV_ATTEMPTS=0 for infinite SPV pollingcargo build
cargo run --example basic
Enable verbose logs and adjust timing via environment variables:
# Enable live network calls (testnet/mainnet based on your params)
export RUN_LIVE=1
# Verbose logging
export XCHAIN_VERBOSE=1
# Polling attempts (0 = infinite)
export XCHAIN_ATTEMPTS=30
export XCHAIN_SPV_ATTEMPTS=0
export XCHAIN_FINAL_ATTEMPTS=30
# Intervals & timeouts (ms)
export XCHAIN_INTERVAL_MS=5000
export XCHAIN_SPV_INTERVAL_MS=5000
export XCHAIN_FINAL_INTERVAL_MS=5000
export XCHAIN_POST_CONFIRM_WAIT_MS=10000
export XCHAIN_MAX_TOTAL_TIME_MS=1200000 # 20 minutes recommended for testnet
# Run the example
cargo run --example crosschain_full
Tips:
XCHAIN_SPV_ATTEMPTS=0 by default for unlimited SPV attemptssudo xcodebuild -license