Loans spec

Priorities

Book zome

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct Book {
    name: String,
    author: String,
    genre: String,
    blurb: String,
    isbn: String,
    book_owner: Address
}

create_book: {
    inputs: |book: Book|,
    outputs: |result: ZomeApiResult<Address>|,
    handler: handle_create_book
}
get_book: {
    inputs: |address: Address|,
    outputs: |result: ZomeApiResult<GetEntryResult>|, // Another change request from guillem, this GetEntryResult type can be returned by using https://developer.holochain.org/api/latest/hdk/api/fn.get_entry_result.html
    handler: handle_get_book
}

get_my_books: {
    inputs: | |,
    outputs: |result: ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>>|,
    handler: handle_get_books
}

get_owner: {
    inputs: |address: Address|,
    outputs: |result: ZomeApiResult<Address>|,
    handler: handle_get_owner
}

Loans zome

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct LoanRequest {
    item_address: Address,
    borrower_address: Address,
    created_at: i64,
}

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct Loan {
    item_address: Address,
    borrower_address: Option<Address>,
    started_at: Option<i64>
    finished_at: Option<i64>
    comment: Option<String>
    return_by: Option<i64>
}

// Create a loan request entry
// Called by the person who wants to borrow
request_to_borrow(item_address: Address, created_at: i64): -> ZomeApiResult<Address>


get_my_loan_requests() -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>>

// This assumes that the books zome has a way of getting all the items of an owner
get_item_loan_requests(item_address: Address) -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>>

// Create a loan entry
// Called by the person who owns the item
// Steps
// 1. Get the loan request
// 2. Get the loan entry
// 3. If the loan entry does not exist, create it only with item_address
// 4. Update the loan entry with the new information
// 5. Create a link from the borrower agent address to the address of the updated entry (not the original entry address)
// 6. Delete the loan request
create_loan(loan_request_address: Address, started_at: i64, return_by: i64) -> ZomeApiResult<Address>

// Remove a loan request
// Called by the person who owns the item
decline_loan(loan_request_address: Address) -> ZomeApiResult<()>

get_loan_history(item_address: Address) -> ZomeApiResult<Option<EntryHistory>>

get_loan_status(item_address: Address) -> ZomeApiResult<Option<Entry>>

// Has to be called by the borrower first and the by the lender
// If double signature, remove link between borrower agent address and loan
finish_loan(item_address: Address, finished_at: i64, comment: Option<String>) -> ZomeApiResult<()>

// Retrieve the loans throught the borrower->loans links
get_my_active_loans() -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>>

Further implementations

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct Collection {
    name: String,
}

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct User {
    name: String,
    street: String,
    zip: String,
    city: String,
    country: String,
}



get_my_address: {
                inputs: | |,
                outputs: |result: JsonString|,
                handler: handle_get_my_address
            }
            
            create_collection: {
                inputs: |name: String|,
                outputs: |result: JsonString|,
                handler: handle_create_collection
            }
            create_user: {
                inputs: |name: String, street: String, zip: String, city: String, country: String|,
                outputs: |result: JsonString|,
                handler: handle_create_user
            }
            get_user_data: {
                inputs: |address: Address|,
                outputs: |result: JsonString|,
                handler: handle_get_user_data
            }
            add_book_to_collection: {
                inputs: |book_address: Address, collection_address: Address|,
                outputs: |result: JsonString|,
                handler: handle_add_book_to_collection
            }
            get_books_in_collection: {
                inputs: |collection_address: Address, tag: String|,
                outputs: |result: JsonString|,
                handler: handle_get_books_in_collection
            }
            get_collections_book_is_in: {
                inputs: |book_address: Address, tag: String|,
                outputs: |result: JsonString|,
                handler: handle_get_collections_book_is_in
            }
            //retrieve all books linked to the anchor shelf
            get_books: {
                inputs: |shelf_address: Address, tag: String|,
                outputs: |result: JsonString|,
                handler: handle_get_books
            }
            get_owners: {
                inputs: |book_address: Address, tag: String|,
                outputs: |result: JsonString|,
                handler: handle_get_owners
            }
            request_to_borrow: {
                inputs: |borrower_address: Address, book_address: Address|,
                outputs: |result: JsonString|,
                handler: handle_request_to_borrow
            }
            get_requests_by_user: {
                inputs: |borrower_address: Address|,
                outputs: |result: JsonString|,
                handler: handle_get_requests_by_user
            }
            get_book_requests: {
                inputs: |book_address: Address|,
                outputs: |result: JsonString|,
                handler: handle_get_book_requests
            }
            create_loan: {
                inputs: |book_address: Address, borrower_address: Address, return_by: String|,
                outputs: |result: JsonString|,
                handler: handle_create_loan
            }

paste code here: zomes/books./lib.rs

Books zome from Hedayat


use std::convert::TryFrom;
use hdk::{
    utils,
    entry_definition::ValidatingEntryType,
    error::{ZomeApiResult, ZomeApiError},
    holochain_persistence_api::{
        cas::content::{AddressableContent, Address},
    },
    holochain_json_api::{
        error::JsonError, json::JsonString,
    },
    holochain_core_types::{
        dna::entry_types::Sharing,
        validation::EntryValidationData,
        entry::Entry,
        link::LinkMatch,
    }
};

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
pub struct Book {
    name: String,
    author: String,
    genre: String,
    blurb: String,
    isbn: String,
    book_owner: Address
}

pub fn definition() -> ValidatingEntryType {
    entry!(
        name: "book",
        description: "Represents a book as an item source of loan system",
        sharing: Sharing::Public,
        validation_package: || {
            hdk::ValidationPackageDefinition::Entry
        },
// link 
        validation: | validation_data: hdk::EntryValidationData<Book>| {
            match validation_data {
                EntryValidationData::Create{entry, validation_data: _} => {
                    let book = entry as Book;
                    if book.name.trim().is_empty() {
                        return Err("Name of the book can not be empty".into())
                    }
                    if book.author.trim().is_empty() {
                        return Err("Author of the book can not be empty".into())
                    }
                    
                    if book.genre.trim().is_empty() {
                        return Err("Genre of the book can not be empty".into())
                    }
                    
                    if book.name.trim().is_empty() {
                        return Err("ISBN of the book can not be empty".into())
                    }
                    // how to check Address
                    Ok(())
                },
                _ => {
                    Err("the entry is not the type of Book".into())
                }
            }
        },
          links: [
            from!(
                "%agent_id",
                link_type: "owner_book",
                validation_package: || {
                    hdk::ValidationPackageDefinition::ChainFull
                },
                validation: | validation_data: hdk::LinkValidationData | {                    
                    if let hdk::LinkValidationData::LinkAdd{link, ..} = validation_data {
                        if link.link.tag() == "muffins" {
                            Err("This is the one tag that is not allowed!".into())
                        } else {
                            Ok(())
                        }
                    } else {
                        Ok(())
                    }
                }
            )
        ]
    )
}



/*************** lib/ 

#![feature(proc_macro_hygiene)]
#[macro_use]
extern crate hdk;
extern crate hdk_proc_macros;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate holochain_json_derive;
use std::convert::TryFrom;
//holochain_wasm_utils::api_serialization::get_entry::GetEntryOptions
use holochain_wasm_utils::*;

use hdk::{
    entry_definition::ValidatingEntryType,
    error::ZomeApiResult,
    AGENT_ADDRESS

};
use hdk::holochain_core_types::{
    entry::Entry,
    dna::entry_types::Sharing,
};

use hdk::holochain_json_api::{
    json::JsonString,
    error::JsonError
};

use hdk::holochain_persistence_api::{
    cas::content::Address
};

use hdk_proc_macros::zome;

mod book;

#[zome]
mod book_zome {

    #[init]
    fn init() {
        Ok(())
    }

    #[validate_agent]
    pub fn validate_agent(validation_data: EntryValidationData<AgentId>) {
        Ok(())
    }

    #[entry_def]
     fn book_entry_def() -> ValidatingEntryType {
        book::definition();
    }

    
 #[zome_fn("hc_public")]
 fn create_book(book:Book) -> ZomeApiResult<Address>{
     let entry = Entry::App("book".into(),book.into());
     let address = hdk::commit_entry(&entry)?;
     Ok(address)     
 }

    #[zome_fn("hc_public")]
    fn get_book(address:Address) -> ZomeApiResult<GetEntryResult> {
       hdk::get_entry_result(address, GetEntryOptions::default())
    }

    #[zome_fn("hc_public")]
    fn get_my_books() -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>> {
   hdk::get_links_result(AgentId, LinkMatch::Exactly("owner_book"), LinkMatch::Any, GetLinksOptions::default(), GetEntryOptions::default())
    }
    
    #[zome_fn("hc_public")]
fn get_owner(address:Address) -> ZomeApiResult<Address> {
 Ok(hdk::get_entry_result(address, GetEntryOptions::default()).Address)
}

}

Scaffolding of Loans zome from Viktor

#![feature(proc_macro_hygiene)]
#[macro_use]
extern crate hdk;
extern crate hdk_proc_macros;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate holochain_json_derive;

use hdk::{
    entry_definition::ValidatingEntryType,
    error::ZomeApiResult,
};
use hdk::holochain_core_types::{
    entry::Entry,
    dna::entry_types::Sharing,
};

use hdk::holochain_json_api::{
    json::JsonString,
    error::JsonError
};

use hdk::holochain_persistence_api::{
    cas::content::Address
};

use hdk_proc_macros::zome;

// see https://developer.holochain.org/api/latest/hdk/ for info on using the hdk library

// This is a sample zome that defines an entry type "MyEntry" that can be committed to the
// agent's chain via the exposed function create_my_entry

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct LoanRequest {
    item_address: Address,
    borrower_address: Address,
}

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct Loan {
    item_address: Address,
    borrower_address: Address,
    return_by: i64
}

#[zome]
mod loans {

    #[init]
    fn init() {
        Ok(())
    }

    #[validate_agent]
    pub fn validate_agent(validation_data: EntryValidationData<AgentId>) {
        Ok(())
    }

    #[entry_def]
     fn loan_request_def() -> ValidatingEntryType {
        entry!(
            name: "loan_request",
            description: "a request that a user has created when wanting to borrow someones item",
            sharing: Sharing::Public,
            validation_package: || {
                hdk::ValidationPackageDefinition::Entry
            },
            validation: | _validation_data: hdk::EntryValidationData<MyEntry>| {
                Ok(())
            },
            links: [
            to!(
                "loan_request",
                link_type: "owner_of_item_requested",
                validation_package: || {
                    hdk::ValidationPackageDefinition::ChainFull
                },
                validation: | _validation_data: hdk::LinkValidationData | {
                    Ok(())
                }
            )]
        )
    }

    #[entry_def]
     fn loan_def() -> ValidatingEntryType {
        entry!(
            name: "loan",
            description: "a loan entry created when a request to borrow is accepted by the owner",
            sharing: Sharing::Public,
            validation_package: || {
                hdk::ValidationPackageDefinition::Entry
            },
            validation: | _validation_data: hdk::EntryValidationData<MyEntry>| {
                Ok(())
            }
        ),
        to!(
                "loan",
                link_type: "owner_of_item_loaned",
                validation_package: || {
                    hdk::ValidationPackageDefinition::ChainFull
                },
                validation: | _validation_data: hdk::LinkValidationData | {
                    Ok(())
                }
            )]
    }


    #[zome_fn("hc_public")]
    fn request_to_borrow(loan_request: LoanRequest) -> ZomeApiResult<Address> {
        //creating the request entry
        let entry = Entry::App("loan_request".into(), entry.into());
        let address = hdk::commit_entry(&entry)?;
        // call get_owner function from book zome

        // create a link from owner_of_item to loan_request

        Ok(address)
    }

    #[zome_fn("hc_public")]
    fn get_loan_requests() -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>> {
        //get all loan requests for the user
        //hdk::get_entry(&address)

    }
    
    #[zome_fn("hc_public")]
    fn create_loan(loan_request_address: Address, return_by: i64) -> ZomeApiResult<Address> {
        //create a loan entry
        let entry = Entry::App("loan".into(), entry.into());
        let address = hdk::commit_entry(&entry)?;
        //create a link to the owner of the loan (and also one to the borrower?)

        Ok(address)

    }
    #[zome_fn("hc_public")]
    fn decline_loan(loan_request_address: Address) -> ZomeApiResult<Address> {
        //mark request as deleted?
        ok()

    }
    #[zome_fn("hc_public")]
    fn get_my_loans() -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>> {
        //get a vector of my loans based on my agent address and links
        ok()

    }

}



Select a repo