Skip to content

Commit

Permalink
feat: endpoint to update buyers
Browse files Browse the repository at this point in the history
  • Loading branch information
veeso committed Nov 10, 2023
1 parent dc1b043 commit b1312af
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/declarations/dilazionato/dilazionato.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export type TokenError = { 'ContractValueIsNotMultipleOfInstallments' : null } |
{ 'ContractAlreadyExists' : bigint } |
{ 'TokenDoesNotBelongToContract' : bigint } |
{ 'TokenNotFound' : bigint } |
{ 'ContractNotFound' : bigint } |
{ 'ContractHasNoTokens' : null } |
{ 'TokenIsBurned' : bigint } |
{ 'InvalidExpirationDate' : null } |
Expand Down Expand Up @@ -180,4 +181,5 @@ export interface _SERVICE {
'transaction' : ActorMethod<[bigint], Result_7>,
'transfer' : ActorMethod<[Principal, bigint], Result_1>,
'transfer_from' : ActorMethod<[Principal, Principal, bigint], Result_1>,
'update_contract_buyers' : ActorMethod<[bigint, Array<Principal>], Result>,
}
6 changes: 6 additions & 0 deletions src/declarations/dilazionato/dilazionato.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const idlFactory = ({ IDL }) => {
'ContractAlreadyExists' : IDL.Nat,
'TokenDoesNotBelongToContract' : IDL.Nat,
'TokenNotFound' : IDL.Nat,
'ContractNotFound' : IDL.Nat,
'ContractHasNoTokens' : IDL.Null,
'TokenIsBurned' : IDL.Nat,
'InvalidExpirationDate' : IDL.Null,
Expand Down Expand Up @@ -231,6 +232,11 @@ export const idlFactory = ({ IDL }) => {
[Result_1],
[],
),
'update_contract_buyers' : IDL.Func(
[IDL.Nat, IDL.Vec(IDL.Principal)],
[Result],
[],
),
});
};
export const init = ({ IDL }) => {
Expand Down
2 changes: 2 additions & 0 deletions src/did/src/dilazionato.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ pub enum SellContractError {
pub enum TokenError {
#[error("the provided contract ID ({0}) already exists in the canister storage")]
ContractAlreadyExists(ID),
#[error("the provided contract ID ({0}) doesn't exist in the canister storage")]
ContractNotFound(ID),
#[error("the provided token ID ({0}) already exists in the canister storage")]
TokenAlreadyExists(TokenIdentifier),
#[error("the provided token ({0}) doesn't belong to the provided contract")]
Expand Down
2 changes: 1 addition & 1 deletion src/did/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
mod common;

pub mod fly;
pub mod dilazionato;
pub mod fly;
pub use common::{StorableNat, StorablePrincipal, ID};
2 changes: 2 additions & 0 deletions src/dilazionato/dilazionato.did
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type TokenError = variant {
ContractAlreadyExists : nat;
TokenDoesNotBelongToContract : nat;
TokenNotFound : nat;
ContractNotFound : nat;
ContractHasNoTokens;
TokenIsBurned : nat;
InvalidExpirationDate;
Expand Down Expand Up @@ -175,4 +176,5 @@ service : (SellContractInitData) -> {
transaction : (nat) -> (Result_7) query;
transfer : (principal, nat) -> (Result_1);
transfer_from : (principal, principal, nat) -> (Result_1);
update_contract_buyers : (nat, vec principal) -> (Result);
}
26 changes: 26 additions & 0 deletions src/dilazionato/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,23 @@ impl SellContract {
Ok(())
}

pub fn inspect_is_buyer(contract: ID) -> SellContractResult<()> {
let contract = match Storage::get_contract(&contract) {
Some(contract) => contract,
None => {
return Err(SellContractError::Token(TokenError::ContractNotFound(
contract,
)))
}
};

if contract.buyers.contains(&caller()) {
Ok(())
} else {
Err(SellContractError::Unauthorized)
}
}

/// get contract by id
pub fn get_contract(id: &ID) -> Option<Contract> {
Storage::get_contract(id)
Expand Down Expand Up @@ -229,6 +246,15 @@ impl SellContract {
ic_cdk::trap(&err.to_string());
}
}

/// Update contract buyers. Only the buyer can call this method.
pub fn update_contract_buyers(
contract_id: ID,
buyers: Vec<Principal>,
) -> SellContractResult<()> {
Self::inspect_is_buyer(contract_id.clone())?;
Storage::update_contract_buyers(&contract_id, buyers)
}
}

#[async_trait]
Expand Down
69 changes: 69 additions & 0 deletions src/dilazionato/src/app/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,26 @@ impl Storage {
})
}

/// Update the contract buyers
pub fn update_contract_buyers(
contract_id: &ID,
buyers: Vec<Principal>,
) -> SellContractResult<()> {
CONTRACTS.with_borrow_mut(|contracts| {
for (id, contract) in contracts.iter() {
if contract.id == *contract_id {
let mut contract = contract.clone();
contract.buyers = buyers;
contracts.insert(id, contract);
return Ok(());
}
}
Err(SellContractError::Token(TokenError::ContractNotFound(
contract_id.clone(),
)))
})
}

/// Update the operator for all token to the new operator canister
pub fn update_tokens_operator(operator: Principal) -> SellContractResult<()> {
TOKENS.with_borrow_mut(|tokens| {
Expand Down Expand Up @@ -837,4 +857,53 @@ mod test {
Some(Principal::anonymous())
);
}

#[test]
fn test_should_update_contract_buyers() {
let seller =
Principal::from_text("zrrb4-gyxmq-nx67d-wmbky-k6xyt-byhmw-tr5ct-vsxu4-nuv2g-6rr65-aae")
.unwrap();
let contract_id = ID::from(1);
let next_token_id = Storage::total_supply();
assert_eq!(next_token_id, Nat::from(0));
let token_1 = Token {
id: next_token_id.into(),
contract_id: contract_id.clone(),
owner: Some(seller),
value: 100,
is_burned: false,
transferred_at: None,
transferred_by: None,
approved_at: None,
approved_by: None,
burned_at: None,
burned_by: None,
minted_at: 0,
minted_by: Principal::anonymous(),
operator: Some(seller),
};
let contract = Contract {
id: contract_id.clone(),
seller,
buyers: vec![Principal::anonymous()],
tokens: vec![token_1.id.clone()],
expiration: "2040-06-01".to_string(),
mfly_reward: 4_000,
value: 250_000,
building: BuildingData {
city: "Rome".to_string(),
},
};

assert!(Storage::insert_contract(contract.clone(), vec![token_1.clone()]).is_ok());
let buyer = seller.clone();
assert!(
Storage::update_contract_buyers(&contract_id, vec![Principal::anonymous(), buyer])
.is_ok()
);
assert_eq!(
Storage::get_contract(&contract_id).unwrap().buyers,
vec![Principal::anonymous(), buyer]
);
}
}
6 changes: 6 additions & 0 deletions src/dilazionato/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ pub fn get_contracts() -> Vec<ID> {
SellContract::get_contracts()
}

#[update]
#[candid_method(update)]
pub fn update_contract_buyers(contract_id: ID, buyers: Vec<Principal>) -> SellContractResult<()> {
SellContract::update_contract_buyers(contract_id, buyers)
}

#[update]
#[candid_method(update)]
pub fn admin_set_fly_canister(canister_id: Principal) {
Expand Down

0 comments on commit b1312af

Please sign in to comment.