aimo-core 0.1.1

AiMo Network core protocol Rust specs
Documentation
use solana_sdk::{signature::Keypair, signer::Signer};

use super::keys::*;

fn create_metadata() -> MetadataV1 {
    MetadataV1 {
        created_at: 1754401735372,
        valid_for: 5_000_000_000,
        usage_limit: 1234,
        scopes: vec![Scope::CompletionModel],
    }
}

fn create_sk() -> SecretKeyV1 {
    let keypair = Keypair::new();
    let metadata = create_metadata();
    // Use canonical JSON string for signature
    let canonical_metadata = metadata.to_canonical_json().unwrap();
    let signature = keypair
        .sign_message(canonical_metadata.as_bytes())
        .to_string();

    // FAKE SIGNATURE
    SecretKeyV1 {
        version: 1,
        wallet: Wallet::Solana,
        signer: keypair.pubkey().to_string(),
        signature,
        metadata: create_metadata(),
    }
}

fn sk_json() -> String {
    // FAKE SIGNER AND SIGNATURE
    serde_json::json!({
        "version": 1,
        "wallet": "solana",
        "signer": "8W7X1tGnWh9CXwnPD7wgke31Gdcqmex4LapJvQ2afBUq",
        "signature": "3HErCXKpy76bbu2rr1BpV79ue2N1StxaPwd4qRjQERMsY15JCpg4gDsN9jQ8cDNkmjeFxkc1GSEHzKULJA8mH6qL",
        "metadata": {
            "created_at": 1754401735372u64,
            "valid_for": 5000000000u64,
            "usage_limit": 1234,
            "scopes": ["completion_model"]
        }
    })
    .to_string()
}

#[test]
fn test_sk_encode_decode() {
    let sk = create_sk();
    let sk_encoded = sk.clone().into_string("test").unwrap();
    println!("{sk_encoded}");
    let (scope, sk_decoded) = SecretKeyV1::decode(&sk_encoded).unwrap();

    assert_eq!(scope, "test");
    assert_eq!(sk_decoded.signer, sk.signer);
    assert_eq!(sk_decoded.signature, sk.signature);
    assert_eq!(sk_decoded.metadata.created_at, sk.metadata.created_at);
}

#[test]
fn test_sk_parse() {
    let sk_json_str = sk_json();
    // println!("Parsing deserializing secret key from:\n{sk_json_str}");
    let sk_parsed = serde_json::from_str::<SecretKeyV1>(&sk_json_str).unwrap();

    assert_eq!(sk_parsed.metadata.scopes.len(), 1);
    assert_eq!(sk_parsed.metadata.scopes[0], Scope::CompletionModel);
}

#[test]
fn test_raw_key() {
    let sk = create_sk();
    let raw = SecretKeyRawV1::try_from(sk).unwrap();
    let bytes = raw.into_bytes();

    assert_eq!(bytes.len(), SecretKeyRawV1::BYTES);
}

#[test]
fn test_raw_metadata() {
    let sk = create_sk();
    let raw = MetadataRawV1::try_from(sk.metadata).unwrap();
    let bytes = raw.into_bytes();

    assert_eq!(bytes.len(), MetadataRawV1::BYTES);
}

#[test]
fn test_verify() {
    let sk = create_sk();
    assert!(sk.verify_signature().is_ok());

    // encode, decode and verify
    let sk = create_sk();
    let sk_string = sk.into_string("test").unwrap();
    let (_, sk) = SecretKeyV1::decode(&sk_string).unwrap();
    assert!(sk.verify_signature().is_ok());
}

#[test]
fn test_hash() {
    let sk = create_sk();
    assert!(sk.into_hash().is_ok());
}

#[test]
fn test_metadata_canonical_json() {
    let metadata = create_metadata();
    let canonical_json = metadata.to_canonical_json().unwrap();

    // The canonical JSON should be deterministic and parseable
    let parsed: serde_json::Value = serde_json::from_str(&canonical_json).unwrap();

    // Verify the parsed content matches our original metadata
    assert_eq!(parsed["created_at"], metadata.created_at);
    assert_eq!(parsed["valid_for"], metadata.valid_for);
    assert_eq!(parsed["usage_limit"], metadata.usage_limit);
    assert_eq!(parsed["scopes"][0], "completion_model");

    // Verify that calling the method multiple times produces the same result
    let canonical_json2 = metadata.to_canonical_json().unwrap();
    assert_eq!(canonical_json, canonical_json2);
}