Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion stellar-contracts/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![no_std]
use soroban_sdk::{contract, contractimpl, symbol_short, Address, BytesN, Env, String, Vec};
use soroban_sdk::{contract, contractimpl, contracttype, Address, BytesN, Env, Vec, symbol_short};use soroban_sdk::{contract, contractimpl, contracttype, Address, BytesN, Env, Vec, symbol_short};

mod types;
pub use types::*;
Expand All @@ -25,6 +25,49 @@ mod issuer_test;
#[cfg(test)]
mod status_test;

// 1. Define the input structure for the batch array
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CertBatchItem {
pub recipient: Address,
pub cert_hash: BytesN<32>, // The unique hash of the certificate data
}

#[contract]
pub struct StellarCertContract;

#[contractimpl]
impl StellarCertContract {

// Existing single issue function (for context)
// pub fn issue_certificate(env: Env, issuer: Address, recipient: Address, cert_hash: BytesN<32>) { ... }

// 2. Implement the Batch Function
pub fn batch_issue_certificates(env: Env, issuer: Address, certificates: Vec<CertBatchItem>) {
// Require the issuer to authorize the entire batch operation once
issuer.require_auth();

// 3. Iterate through the Vec and apply the issuance logic
for cert in certificates.into_iter() {
// NOTE: Replace this with your contract's actual storage key pattern
let storage_key = cert.cert_hash.clone();

// Ensure the certificate doesn't already exist to prevent overwriting
if env.storage().persistent().has(&storage_key) {
panic!("Certificate hash already exists in this batch");
}

// Store the certificate
env.storage().persistent().set(&storage_key, &cert.recipient);
}

// 4. Emit a single event for the batch to save on event emission costs
env.events().publish(
(symbol_short!("batch_iss"), issuer),
certificates.len(), // Log how many were issued
);
}

#[contract]
pub struct CertificateContract;

Expand Down
46 changes: 44 additions & 2 deletions stellar-contracts/src/test.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,51 @@
#![cfg(test)]

use super::*;
use soroban_sdk::{testutils::Address as _, Address, Bytes, BytesN, Env, Vec};
use soroban_sdk::{testutils::{Address as _, Events}, Vec, Address, Bytes, BytesN, Env, IntoVal};
use soroban_sdk::{Env, testutils::Address as _, Address, String};

#[test]
fn test_batch_issue_certificates() {
let env = Env::default();
env.mock_all_auths(); // Mock authorization for the test

let contract_id = env.register_contract(None, StellarCertContract);
let client = StellarCertContractClient::new(&env, &contract_id);

let issuer = Address::generate(&env);
let recipient_1 = Address::generate(&env);
let recipient_2 = Address::generate(&env);

// Create mock certificate hashes
let hash_1 = BytesN::from_array(&env, &[1; 32]);
let hash_2 = BytesN::from_array(&env, &[2; 32]);

// Construct the batch Vector
let batch = vec![
&env,
CertBatchItem { recipient: recipient_1.clone(), cert_hash: hash_1.clone() },
CertBatchItem { recipient: recipient_2.clone(), cert_hash: hash_2.clone() },
];

// Execute the batch issuance
client.batch_issue_certificates(&issuer, &batch);

// Verify storage state (Assuming you have a 'get_certificate' or similar read function)
// assert_eq!(client.get_certificate(&hash_1), recipient_1);
// assert_eq!(client.get_certificate(&hash_2), recipient_2);

// Verify the event was emitted correctly
let events = env.events().all();
let last_event = events.last().unwrap();
assert_eq!(
last_event.1, // Topics
(symbol_short!("batch_iss"), issuer).into_val(&env)
);
assert_eq!(
last_event.2, // Data (Length of batch)
2u32.into_val(&env)
);
}

// Helper function to create a certificate version
fn create_version(env: &Env, major: u32, minor: u32, patch: u32) -> CertificateVersion {
CertificateVersion {
Expand Down