Skip to content

A Rust SDK for creating, signing, managing and posting ANS-104 dataitems.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

permaweb/bundles-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

About

A Rust SDK for creating, signing, managing and posting ANS-104 dataitems.

Warning: this repository is actively under development and could have breaking changes until reaching full API compatibility in v1.0.0.

Installation

Add to your Cargo.toml:

[dependencies]
# main library
bundles_rs = { git = "https://github.com/permaweb/bundles-rs", branch = "main" }

# use individual crates
# or use branch/tag/rev -- we recommend checking and using the last client version
ans104 = { git = "https://github.com/permaweb/bundles-rs", version = "x.x.x" } 
crypto = { git = "https://github.com/permaweb/bundles-rs", version = "x.x.x" }

Dev setup

git clone https://github.com/permaweb/bundles-rs.git
cd bundles-rs
cargo clippy --workspace --lib --examples --tests --benches --locked --all-features
cargo +nightly fmt
cargo check --all

Supported Signers

Blockchain Signature Type
Arweave RSA-PSS
Ethereum secp256k1
Solana Ed25519 (with base58 solana flavoring)
- Ed25519Core (raw Ed25519)

Regarding Tags

This ANS-104 dataitems client fully implements the ANS-104 specification as-is

Constraint bundles-rs Spec arbundles js HyperBEAM ar_bundles
Maximum tags per data item <= 128 tags <= 128 tags <= 128 tags No max tags
Tag name max size 1024 bytes 1024 bytes all keys + vals <= 4096 bytes Can have empty strings
Tag value max size 3072 bytes 3072 bytes Can have empty strings val <= 3072 bytes
Empty names/values non empty strings non empty strings Can have empty strings Can have empty strings

Special thanks for @nikooo777 for compiling this list. bundles-rs has been added to the compiled list.

Usage Examples

Quick start

use bundles_rs::{
    ans104::{data_item::DataItem, tags::Tag},
    crypto::ethereum::EthereumSigner,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // create a signer
    let signer = EthereumSigner::random()?;
    
    // create tags (metadata)
    let tags = vec![
        Tag::new("Content-Type", "text/plain"),
        Tag::new("App-Name", "Permaweb-Test-App"),
    ];
    
    // create and sign a dataitem
    let data = b"Hello World Arweave!".to_vec();
    // first None for Target and the second for Anchor
    // let target = [0u8; 32]; -- 32-byte target address
    // let anchor = b"unique-anchor".to_vec(); -- max 32 bytes
    let item = DataItem::build_and_sign(&signer, None, None, tags, data)?;
    
    // get the dataitem id
    let id = item.arweave_id();
    println!("dataitem id: {}", id);
    
    // serialize for upload
    let bytes = item.to_bytes()?;
    println!("Ready to upload {} bytes", bytes.len());
    
    Ok(())
}

Or for basic signed dataitem

use bundles_rs::ans104::{data_item::DataItem, tags::Tag};

// create unsigned data item
let tags = vec![Tag::new("Content-Type", "application/json")];
let data = br#"{"message": "Hello World"}"#.to_vec();
let mut item = DataItem::new(None, None, tags, data)?;

// sign dataitem
item.sign(&signer)?;

Working with signers

N.B: use random signer generation for testing purposes only

Arweave Signer

use bundles_rs::crypto::arweave::ArweaveSigner;

let signer = ArweaveSigner::from_jwk_file("wallet.json")?;

// from stringified JWK
let jwk_json = r#"{"kty":"RSA","n":"...","e":"AQAB","d":"..."}"#;
let signer = ArweaveSigner::from_jwk_str(jwk_json)?;

// random
let signer = ArweaveSigner::random()?;

// Arweave address
let address = signer.address();
println!("Arweave address: {}", address);

Ethereum Signer

use bundles_rs::crypto::ethereum::EthereumSigner;

// generate random key
let signer = EthereumSigner::random()?;

// or from private key bytes
let private_key = hex::decode("your_private_key_hex")?;
let signer = EthereumSigner::from_bytes(&private_key)?;

// EOA
let address = signer.address_string();
println!("Ethereum address: {}", address);

Solana Signer

use bundles_rs::crypto::solana::SolanaSigner;
// random
let signer = SolanaSigner::random();
// pk
let signer = SolanaSigner::from_base58("your_base58_private_key")?;
// from secret bytes
let secret = [0u8; 32]; // your secret bytes
let signer = SolanaSigner::from_secret_bytes(&secret)?;

// Get Solana address
let address = signer.address();
println!("Solana address: {}", address);

Ed25519Core Signer

use bundles_rs::crypto::ed25519::Ed25519Core;

// random
let signer = Ed25519Core::random();
// from seed bytes
let seed = [0u8; 32];
let signer = Ed25519Core::from_secret_bytes(&seed)?;

Verification

Manual

// verify signature and structure
item.verify()?;

// manual verification steps
assert_eq!(item.signature.len(), item.signature_type.signature_len());
assert_eq!(item.owner.len(), item.signature_type.owner_len());

With Signer

use bundles_rs::crypto::signer::Signer;

let message = item.signing_message();
let is_valid = signer.verify(&message, &item.signature)?;
assert!(is_valid);

Deep hash

use bundles_rs::ans104::deep_hash::{DeepHash, deep_hash_sync};

let data = b"custom data";
let hash_structure = DeepHash::List(vec![
    DeepHash::Blob(b"custom"),
    DeepHash::Blob(data),
]);

let hash = deep_hash_sync(&hash_structure);
println!("Deep hash hex: {}", hex::encode(hash));

Upload to Bundling services (e.g. Turbo)

use bundles_rs::bundler::BundlerClient;
use bundles_rs::ans104::{data_item::DataItem, tags::Tag};
use bundles_rs::crypto::solana::SolanaSigner;

let client = BundlerClient::turbo().build().unwrap();
let signer = SolanaSigner::random();
let tags = vec![Tag::new("content-type", "text/plain")];
let dataitem = DataItem::build_and_sign(&signer, None, None, tags, b"hello world turbo".to_vec()).unwrap();

let tx = client.send_transaction(dataitem).await.unwrap();
println!("tx: {:?}", tx);

For fully detailed examples, checkout the bundler crate

License

for releases up to v0.3.1

Licensed at your option under either of:

for releases after v0.3.1

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you will be licensed under the MIT License

Credits

This repository was initially developed by the Decent Land Labs team and is currently maintained and continuously developed by the Permaweb team.

About

A Rust SDK for creating, signing, managing and posting ANS-104 dataitems.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages