Untitled
unknown
plain_text
a year ago
6.5 kB
8
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