Skip to content

Commit da3fad7

Browse files
committed
Implement Asset
1 parent dd444c6 commit da3fad7

9 files changed

Lines changed: 1015 additions & 2 deletions

File tree

contracts/assetsup/src/asset.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use soroban_sdk::{contracttype, Address, BytesN, String};
2+
3+
use crate::types::{AssetStatus, AssetType};
4+
5+
#[contracttype]
6+
#[derive(Clone, Debug, Eq, PartialEq)]
7+
pub enum DataKey {
8+
Asset(BytesN<32>),
9+
}
10+
11+
#[contracttype]
12+
#[derive(Clone, Debug, Eq, PartialEq)]
13+
pub struct Asset {
14+
pub id: BytesN<32>,
15+
pub name: String,
16+
pub asset_type: AssetType,
17+
pub category: String,
18+
pub branch_id: u64,
19+
pub department_id: u64,
20+
pub status: AssetStatus,
21+
pub purchase_date: u64,
22+
pub purchase_cost: i128,
23+
pub current_value: i128,
24+
pub warranty_expiry: u64,
25+
pub stellar_token_id: BytesN<32>,
26+
pub owner: Address,
27+
}
28+
29+
// Note: Contract methods implemented in lib.rs

contracts/assetsup/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use soroban_sdk::contracterror;
2+
3+
#[contracterror]
4+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
5+
pub enum ContractError {
6+
AssetAlreadyExists = 1,
7+
AssetNotFound = 2,
8+
}

contracts/assetsup/src/lib.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#![no_std]
2-
use soroban_sdk::{Address, Env, contract, contractimpl, contracttype};
2+
use soroban_sdk::{Address, Env, contract, contractimpl, contracttype, BytesN};
3+
4+
pub(crate) mod types;
5+
pub(crate) mod errors;
6+
pub(crate) mod asset;
37

48
#[contracttype]
59
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -24,6 +28,33 @@ impl AssetUpContract {
2428
pub fn get_admin(env: Env) -> Address {
2529
env.storage().persistent().get(&DataKey::Admin).unwrap()
2630
}
31+
32+
// Asset functions
33+
pub fn register_asset(env: Env, asset: asset::Asset) -> Result<(), errors::ContractError> {
34+
// Access control
35+
asset.owner.require_auth();
36+
37+
if asset.name.len() == 0 {
38+
panic!("Name cannot be empty");
39+
}
40+
41+
let key = asset::DataKey::Asset(asset.id.clone());
42+
let store = env.storage().persistent();
43+
if store.has(&key) {
44+
return Err(errors::ContractError::AssetAlreadyExists);
45+
}
46+
store.set(&key, &asset);
47+
Ok(())
48+
}
49+
50+
pub fn get_asset(env: Env, asset_id: BytesN<32>) -> Result<asset::Asset, errors::ContractError> {
51+
let key = asset::DataKey::Asset(asset_id);
52+
let store = env.storage().persistent();
53+
match store.get::<_, asset::Asset>(&key) {
54+
Some(a) => Ok(a),
55+
None => Err(errors::ContractError::AssetNotFound),
56+
}
57+
}
2758
}
2859

2960
mod tests;
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#![cfg(test)]
2+
3+
extern crate std;
4+
5+
use soroban_sdk::{testutils::Address as _, Address, BytesN, Env, String};
6+
7+
use crate::{asset::Asset, types::{AssetStatus, AssetType}, errors::ContractError};
8+
9+
use super::initialize::setup_test_environment;
10+
11+
fn make_bytes32(env: &Env, seed: u32) -> BytesN<32> {
12+
let mut arr = [0u8; 32];
13+
// Simple deterministic fill
14+
for i in 0..32 {
15+
arr[i] = ((seed as usize + i) % 256) as u8;
16+
}
17+
BytesN::from_array(env, &arr)
18+
}
19+
20+
#[test]
21+
fn test_register_and_get_asset_success() {
22+
let (env, client, _admin) = setup_test_environment();
23+
let owner = Address::generate(&env);
24+
25+
let id = make_bytes32(&env, 1);
26+
let token = make_bytes32(&env, 2);
27+
28+
let name = String::from_str(&env, "Laptop A");
29+
let category = String::from_str(&env, "Electronics");
30+
31+
let asset = Asset {
32+
id: id.clone(),
33+
name: name.clone(),
34+
asset_type: AssetType::IT,
35+
category: category.clone(),
36+
branch_id: 10,
37+
department_id: 20,
38+
status: AssetStatus::Active,
39+
purchase_date: 1_725_000_000,
40+
purchase_cost: 120_000,
41+
current_value: 100_000,
42+
warranty_expiry: 1_800_000_000,
43+
stellar_token_id: token.clone(),
44+
owner: owner.clone(),
45+
};
46+
47+
let res = client.try_register_asset(&asset);
48+
assert!(res.is_ok());
49+
50+
let got = client.try_get_asset(&id).unwrap().unwrap();
51+
52+
assert_eq!(got.id, id);
53+
assert_eq!(got.name, name);
54+
assert_eq!(got.asset_type, AssetType::IT);
55+
assert_eq!(got.category, category);
56+
assert_eq!(got.branch_id, 10);
57+
assert_eq!(got.department_id, 20);
58+
assert_eq!(got.status, AssetStatus::Active);
59+
assert_eq!(got.purchase_date, 1_725_000_000);
60+
assert_eq!(got.purchase_cost, 120_000);
61+
assert_eq!(got.current_value, 100_000);
62+
assert_eq!(got.warranty_expiry, 1_800_000_000);
63+
assert_eq!(got.stellar_token_id, token);
64+
assert_eq!(got.owner, owner);
65+
}
66+
67+
#[test]
68+
#[should_panic]
69+
fn test_register_asset_duplicate() {
70+
let (env, client, _admin) = setup_test_environment();
71+
let owner = Address::generate(&env);
72+
73+
let id = make_bytes32(&env, 3);
74+
let token = make_bytes32(&env, 4);
75+
76+
let name = String::from_str(&env, "Office Chair");
77+
let category = String::from_str(&env, "Furniture");
78+
79+
let asset = Asset {
80+
id: id.clone(),
81+
name: name.clone(),
82+
asset_type: AssetType::Furniture,
83+
category: category.clone(),
84+
branch_id: 1,
85+
department_id: 2,
86+
status: AssetStatus::Active,
87+
purchase_date: 1_700_000_000,
88+
purchase_cost: 15_000,
89+
current_value: 12_000,
90+
warranty_expiry: 1_750_000_000,
91+
stellar_token_id: token.clone(),
92+
owner: owner.clone(),
93+
};
94+
95+
// First registration should succeed
96+
client.register_asset(&asset);
97+
98+
// Second registration with same ID should panic (Err propagated)
99+
client.register_asset(&asset);
100+
}

contracts/assetsup/src/tests/initialize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn test_initialize() {
2828
}
2929

3030
#[test]
31-
#[should_panic()]
31+
#[should_panic]
3232
fn test_initialize_panic() {
3333
let (_env, client, admin) = setup_test_environment();
3434
client.initialize(&admin);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
mod initialize;
2+
mod asset;

contracts/assetsup/src/types.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![allow(clippy::upper_case_acronyms)]
2+
use soroban_sdk::{contracttype};
3+
4+
#[contracttype]
5+
#[derive(Clone, Debug, Eq, PartialEq)]
6+
pub enum AssetType {
7+
IT,
8+
Furniture,
9+
Vehicle,
10+
RealEstate,
11+
Machinery,
12+
Other,
13+
}
14+
15+
#[contracttype]
16+
#[derive(Clone, Debug, Eq, PartialEq)]
17+
pub enum AssetStatus {
18+
Active,
19+
Maintenance,
20+
Retired,
21+
Disposed,
22+
}

0 commit comments

Comments
 (0)