Untitled
unknown
plain_text
5 months ago
6.5 kB
2
Indexable
use anchor_lang::prelude::*; use anchor_lang::solana_program::hash::hash; declare_id!("BiZguh7AWYWwvL8EykRT6YWCX1pge4NtVRkt3C9yUtKW"); #[program] pub mod smart_lading { use super::*; pub fn initialize(ctx: Context<Initialize>, max_documents: u32) -> Result<()> { let global_state = &mut ctx.accounts.global_state; global_state.document_count = 0; global_state.max_documents = max_documents; global_state.document_addresses = vec![Pubkey::default(); max_documents as usize]; Ok(()) } pub fn store_document( ctx: Context<StoreDocument>, bill_of_lading_number: String, ship_from: String, ship_to: String, ship_date: i64, carrier: String, cargo: String, value_usd: u64, doc_metadata: String, owner: Pubkey, ) -> Result<()> { let document = &mut ctx.accounts.document; let global_state = &mut ctx.accounts.global_state; require!( (global_state.document_count as usize) < global_state.document_addresses.len(), DocError::MaxDocumentsReached ); let clock: Clock = Clock::get().unwrap(); // Generate document hash let hash_input = format!( "{}{}{}{}{}{}{}", bill_of_lading_number, ship_from, ship_to, ship_date, carrier, cargo, value_usd ); let document_hash = hash(hash_input.as_bytes()); // Store document information document.document_hash = document_hash.to_bytes(); document.timestamp = clock.unix_timestamp; document.issuer = ctx.accounts.issuer.key(); document.doc_metadata = doc_metadata; document.bill_of_lading_number = bill_of_lading_number; document.owner = owner; // Store document address in global state let _index = global_state.document_count as usize; global_state.document_addresses[_index] = document.key(); global_state.document_count += 1; msg!( "document created BL num = {} at timestamp = {} with hash = {:?}, owner = {} ", document.bill_of_lading_number, document.timestamp, document.document_hash, document.owner ); Ok(()) } pub fn verify_document(ctx: Context<VerifyDocument>, input_hash: [u8; 32]) -> Result<bool> { let document = &ctx.accounts.document; let stored_hash = document.document_hash; let is_valid = input_hash == stored_hash; msg!("verifyDocument = {} ", is_valid); Ok(is_valid) } pub fn get_document_count(ctx: Context<GetDocumentCount>) -> Result<u64> { msg!( "get_document_count = {} ", ctx.accounts.global_state.document_count ); Ok(ctx.accounts.global_state.document_count) } pub fn get_document_addresses( ctx: Context<GetDocumentAddresses>, start_index: u32, limit: u32, ) -> Result<Vec<Pubkey>> { let global_state = &ctx.accounts.global_state; let end_index = (start_index + limit).min(global_state.document_count as u32); Ok(global_state.document_addresses[start_index as usize..end_index as usize].to_vec()) } pub fn get_document_owner( ctx: Context<GetDocumentOwner>, bill_of_lading_number: String, ) -> Result<Pubkey> { msg!("get_document_owner = {}", ctx.accounts.document.owner); let doc = &mut ctx.accounts.document; Ok(doc.owner) } pub fn change_document_owner( ctx: Context<ChangeDocumentOwner>, bill_of_lading_number: String, new_owner: Pubkey, ) -> Result<()> { let doc = &mut ctx.accounts.document; msg!( "get_document_owner = old {} vs new {} ", doc.owner, new_owner ); doc.owner = new_owner.key(); msg!("Owner change successful."); Ok(()) } } #[derive(Accounts)] #[instruction(max_documents: u32)] pub struct Initialize<'info> { #[account( init, payer = authority, space = 8 + 8 + 4 + 4 + (32 * max_documents as usize), // Discriminator + document_count + max_documents + vec length + document addresses seeds = [b"global_state"], bump )] pub global_state: Account<'info, GlobalState>, #[account(mut)] pub authority: Signer<'info>, pub system_program: Program<'info, System>, } #[derive(Accounts)] #[instruction(bill_of_lading_number: String)] pub struct StoreDocument<'info> { #[account( init, payer = issuer, space = 8 + 32 + 8 + 32 + 300 + 500, // Increased space for strings seeds = [b"document", bill_of_lading_number.as_bytes()], bump )] pub document: Account<'info, Document>, #[account(mut)] pub global_state: Account<'info, GlobalState>, #[account(mut)] pub issuer: Signer<'info>, pub system_program: Program<'info, System>, } #[derive(Accounts)] pub struct VerifyDocument<'info> { pub document: Account<'info, Document>, } #[derive(Accounts)] pub struct GetDocumentCount<'info> { pub global_state: Account<'info, GlobalState>, } #[derive(Accounts)] pub struct GetDocumentAddresses<'info> { pub global_state: Account<'info, GlobalState>, } #[derive(Accounts)] #[instruction(bill_of_lading_number: String)] pub struct GetDocumentOwner<'info> { #[account( seeds = [b"document", bill_of_lading_number.as_bytes()], bump )] pub document: Account<'info, Document>, } #[derive(Accounts)] #[instruction(bill_of_lading_number: String)] pub struct ChangeDocumentOwner<'info> { #[account( seeds = [b"document", bill_of_lading_number.as_bytes()], bump, )] pub document: Account<'info, Document>, } #[account] pub struct GlobalState { pub document_count: u64, pub max_documents: u32, pub document_addresses: Vec<Pubkey>, } #[account] pub struct Document { pub document_hash: [u8; 32], pub timestamp: i64, pub issuer: Pubkey, pub doc_metadata: String, pub bill_of_lading_number: String, pub owner: Pubkey, } #[error_code] pub enum DocError { #[msg("Not valid authentication")] NotValidAuth, #[msg("Bill of Lading does not exist")] BlNotExisting, #[msg("Maximum number of documents reached")] MaxDocumentsReached, #[msg("Not authorized to perform this action")] NotAuthorized, #[msg("Default error")] DefaultErr, }
Editor is loading...
Leave a Comment