-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adds zome for saving board defs, and validate board
- Loading branch information
Showing
22 changed files
with
1,112 additions
and
309 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
edition = "2021" | ||
name = "gamez" | ||
version = "0.0.1" | ||
|
||
[lib] | ||
crate-type = ["cdylib", "rlib"] | ||
name = "gamez" | ||
|
||
[dependencies] | ||
hdk = { workspace = true } | ||
|
||
serde = { workspace = true } | ||
|
||
gamez_integrity = { workspace = true } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use hdk::prelude::*; | ||
use gamez_integrity::*; | ||
|
||
#[hdk_extern] | ||
pub fn create_board_def(board_def: BoardDef) -> ExternResult<Record> { | ||
let board_def_hash = create_entry(&EntryTypes::BoardDef(board_def.clone()))?; | ||
let record = get(board_def_hash.clone(), GetOptions::default())? | ||
.ok_or( | ||
wasm_error!( | ||
WasmErrorInner::Guest(String::from("Could not find the newly created BoardDef")) | ||
), | ||
)?; | ||
let path = Path::from("all_board_defs"); | ||
create_link(path.path_entry_hash()?, board_def_hash.clone(), LinkTypes::AllBoardDefs, ())?; | ||
Ok(record) | ||
} | ||
#[hdk_extern] | ||
pub fn get_board_def(original_board_def_hash: ActionHash) -> ExternResult<Option<Record>> { | ||
let links = get_links(original_board_def_hash.clone(), LinkTypes::BoardDefUpdates, None)?; | ||
let latest_link = links | ||
.into_iter() | ||
.max_by(|link_a, link_b| link_a.timestamp.cmp(&link_b.timestamp)); | ||
let latest_board_def_hash = match latest_link { | ||
Some(link) => ActionHash::try_from(link.target.clone()).map_err(|err| wasm_error!(err))?, | ||
None => original_board_def_hash.clone(), | ||
}; | ||
get(latest_board_def_hash, GetOptions::default()) | ||
} | ||
#[derive(Serialize, Deserialize, Debug)] | ||
pub struct UpdateBoardDefInput { | ||
pub original_board_def_hash: ActionHash, | ||
pub previous_board_def_hash: ActionHash, | ||
pub updated_board_def: BoardDef, | ||
} | ||
#[hdk_extern] | ||
pub fn update_board_def(input: UpdateBoardDefInput) -> ExternResult<Record> { | ||
let updated_board_def_hash = update_entry( | ||
input.previous_board_def_hash.clone(), | ||
&input.updated_board_def, | ||
)?; | ||
create_link( | ||
input.original_board_def_hash.clone(), | ||
updated_board_def_hash.clone(), | ||
LinkTypes::BoardDefUpdates, | ||
(), | ||
)?; | ||
let record = get(updated_board_def_hash.clone(), GetOptions::default())? | ||
.ok_or( | ||
wasm_error!( | ||
WasmErrorInner::Guest(String::from("Could not find the newly updated BoardDef")) | ||
), | ||
)?; | ||
Ok(record) | ||
} | ||
|
||
#[hdk_extern] | ||
pub fn delete_board_def(original_board_def_hash: ActionHash) -> ExternResult<ActionHash> { | ||
delete_entry(original_board_def_hash) | ||
} | ||
|
||
#[hdk_extern] | ||
pub fn get_board_defs(_: ()) -> ExternResult<Vec<ActionHash>> { | ||
let path = Path::from("all_board_defs"); | ||
|
||
let links = get_links( | ||
path.path_entry_hash()?, | ||
LinkTypes::AllBoardDefs, | ||
None, | ||
)?; | ||
let action_hashes = links | ||
.into_iter() | ||
.filter_map(|link| link.target.into_action_hash()) | ||
.collect(); | ||
Ok(action_hashes) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
pub mod board_def; | ||
use gamez_integrity::*; | ||
|
||
use hdk::prelude::*; | ||
|
||
#[hdk_extern] | ||
pub fn init(_: ()) -> ExternResult<InitCallbackResult> { | ||
|
||
let mut fns = BTreeSet::new(); | ||
fns.insert((zome_info()?.name, "recv_remote_signal".into())); | ||
let functions = GrantedFunctions::Listed(fns); | ||
create_cap_grant(CapGrantEntry { | ||
tag: "".into(), | ||
access: CapAccess::Unrestricted, | ||
functions, | ||
})?; | ||
|
||
Ok(InitCallbackResult::Pass) | ||
} | ||
#[derive(Serialize, Deserialize, Debug)] | ||
#[serde(tag = "type")] | ||
pub enum Signal { | ||
LinkCreated { action: SignedActionHashed, link_type: LinkTypes }, | ||
LinkDeleted { action: SignedActionHashed, link_type: LinkTypes }, | ||
EntryCreated { action: SignedActionHashed, app_entry: EntryTypes }, | ||
EntryUpdated { | ||
action: SignedActionHashed, | ||
app_entry: EntryTypes, | ||
original_app_entry: EntryTypes, | ||
}, | ||
EntryDeleted { action: SignedActionHashed, original_app_entry: EntryTypes }, | ||
} | ||
#[hdk_extern(infallible)] | ||
pub fn post_commit(committed_actions: Vec<SignedActionHashed>) { | ||
for action in committed_actions { | ||
if let Err(err) = signal_action(action) { | ||
error!("Error signaling new action: {:?}", err); | ||
} | ||
} | ||
} | ||
fn signal_action(action: SignedActionHashed) -> ExternResult<()> { | ||
match action.hashed.content.clone() { | ||
Action::CreateLink(create_link) => { | ||
if let Ok(Some(link_type)) | ||
= LinkTypes::from_type(create_link.zome_index, create_link.link_type) { | ||
emit_signal(Signal::LinkCreated { | ||
action, | ||
link_type, | ||
})?; | ||
} | ||
Ok(()) | ||
} | ||
Action::DeleteLink(delete_link) => { | ||
let record = get( | ||
delete_link.link_add_address.clone(), | ||
GetOptions::default(), | ||
)? | ||
.ok_or( | ||
wasm_error!( | ||
WasmErrorInner::Guest("Failed to fetch CreateLink action" | ||
.to_string()) | ||
), | ||
)?; | ||
match record.action() { | ||
Action::CreateLink(create_link) => { | ||
if let Ok(Some(link_type)) | ||
= LinkTypes::from_type( | ||
create_link.zome_index, | ||
create_link.link_type, | ||
) { | ||
emit_signal(Signal::LinkDeleted { | ||
action, | ||
link_type, | ||
})?; | ||
} | ||
Ok(()) | ||
} | ||
_ => { | ||
return Err( | ||
wasm_error!( | ||
WasmErrorInner::Guest("Create Link should exist".to_string()) | ||
), | ||
); | ||
} | ||
} | ||
} | ||
Action::Create(_create) => { | ||
if let Ok(Some(app_entry)) = get_entry_for_action(&action.hashed.hash) { | ||
emit_signal(Signal::EntryCreated { | ||
action, | ||
app_entry, | ||
})?; | ||
} | ||
Ok(()) | ||
} | ||
Action::Update(update) => { | ||
if let Ok(Some(app_entry)) = get_entry_for_action(&action.hashed.hash) { | ||
if let Ok(Some(original_app_entry)) | ||
= get_entry_for_action(&update.original_action_address) { | ||
emit_signal(Signal::EntryUpdated { | ||
action, | ||
app_entry, | ||
original_app_entry, | ||
})?; | ||
} | ||
} | ||
Ok(()) | ||
} | ||
Action::Delete(delete) => { | ||
if let Ok(Some(original_app_entry)) | ||
= get_entry_for_action(&delete.deletes_address) { | ||
emit_signal(Signal::EntryDeleted { | ||
action, | ||
original_app_entry, | ||
})?; | ||
} | ||
Ok(()) | ||
} | ||
_ => Ok(()), | ||
} | ||
} | ||
fn get_entry_for_action(action_hash: &ActionHash) -> ExternResult<Option<EntryTypes>> { | ||
let record = match get_details(action_hash.clone(), GetOptions::default())? { | ||
Some(Details::Record(record_details)) => record_details.record, | ||
_ => { | ||
return Ok(None); | ||
} | ||
}; | ||
let entry = match record.entry().as_option() { | ||
Some(entry) => entry, | ||
None => { | ||
return Ok(None); | ||
} | ||
}; | ||
let (zome_index, entry_index) = match record.action().entry_type() { | ||
Some(EntryType::App(AppEntryDef { zome_index, entry_index, .. })) => { | ||
(zome_index, entry_index) | ||
} | ||
_ => { | ||
return Ok(None); | ||
} | ||
}; | ||
Ok( | ||
EntryTypes::deserialize_from_type( | ||
zome_index.clone(), | ||
entry_index.clone(), | ||
entry, | ||
)?, | ||
) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
edition = "2021" | ||
name = "gamez_integrity" | ||
version = "0.0.1" | ||
|
||
[lib] | ||
crate-type = ["cdylib", "rlib"] | ||
name = "gamez_integrity" | ||
|
||
[dependencies] | ||
hdi = { workspace = true } | ||
|
||
serde = { workspace = true } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use hdi::prelude::*; | ||
#[hdk_entry_helper] | ||
#[derive(Clone, PartialEq)] | ||
pub struct BoardDef { | ||
pub board: String, | ||
} | ||
pub fn validate_create_board_def( | ||
_action: EntryCreationAction, | ||
_board_def: BoardDef, | ||
) -> ExternResult<ValidateCallbackResult> { | ||
Ok(ValidateCallbackResult::Valid) | ||
} | ||
pub fn validate_update_board_def( | ||
_action: Update, | ||
_board_def: BoardDef, | ||
_original_action: EntryCreationAction, | ||
_original_board_def: BoardDef, | ||
) -> ExternResult<ValidateCallbackResult> { | ||
Ok(ValidateCallbackResult::Valid) | ||
} | ||
pub fn validate_delete_board_def( | ||
_action: Delete, | ||
_original_action: EntryCreationAction, | ||
_original_board_def: BoardDef, | ||
) -> ExternResult<ValidateCallbackResult> { | ||
Ok(ValidateCallbackResult::Valid) | ||
} | ||
pub fn validate_create_link_board_def_updates( | ||
_action: CreateLink, | ||
base_address: AnyLinkableHash, | ||
target_address: AnyLinkableHash, | ||
_tag: LinkTag, | ||
) -> ExternResult<ValidateCallbackResult> { | ||
let action_hash = ActionHash::try_from(base_address).map_err(|err| wasm_error!(err))?; | ||
let record = must_get_valid_record(action_hash)?; | ||
let _board_def: crate::BoardDef = record | ||
.entry() | ||
.to_app_option() | ||
.map_err(|e| wasm_error!(e))? | ||
.ok_or( | ||
wasm_error!( | ||
WasmErrorInner::Guest(String::from("Linked action must reference an entry")) | ||
), | ||
)?; | ||
let action_hash = ActionHash::try_from(target_address).map_err(|err| wasm_error!(err))?; | ||
let record = must_get_valid_record(action_hash)?; | ||
let _board_def: crate::BoardDef = record | ||
.entry() | ||
.to_app_option() | ||
.map_err(|e| wasm_error!(e))? | ||
.ok_or( | ||
wasm_error!( | ||
WasmErrorInner::Guest(String::from("Linked action must reference an entry")) | ||
), | ||
)?; | ||
Ok(ValidateCallbackResult::Valid) | ||
} | ||
pub fn validate_delete_link_board_def_updates( | ||
_action: DeleteLink, | ||
_original_action: CreateLink, | ||
_base: AnyLinkableHash, | ||
_target: AnyLinkableHash, | ||
_tag: LinkTag, | ||
) -> ExternResult<ValidateCallbackResult> { | ||
Ok( | ||
ValidateCallbackResult::Invalid( | ||
String::from("BoardDefUpdates links cannot be deleted"), | ||
), | ||
) | ||
} | ||
pub fn validate_create_link_all_board_defs( | ||
_action: CreateLink, | ||
_base_address: AnyLinkableHash, | ||
target_address: AnyLinkableHash, | ||
_tag: LinkTag, | ||
) -> ExternResult<ValidateCallbackResult> { | ||
// Check the entry type for the given action hash | ||
let action_hash = ActionHash::try_from(target_address).map_err(|err| wasm_error!(err))?; | ||
let record = must_get_valid_record(action_hash)?; | ||
let _board_def: crate::BoardDef = record | ||
.entry() | ||
.to_app_option() | ||
.map_err(|e| wasm_error!(e))? | ||
.ok_or( | ||
wasm_error!( | ||
WasmErrorInner::Guest(String::from("Linked action must reference an entry")) | ||
), | ||
)?; | ||
// TODO: add the appropriate validation rules | ||
Ok(ValidateCallbackResult::Valid) | ||
} | ||
pub fn validate_delete_link_all_board_defs( | ||
_action: DeleteLink, | ||
_original_action: CreateLink, | ||
_base: AnyLinkableHash, | ||
_target: AnyLinkableHash, | ||
_tag: LinkTag, | ||
) -> ExternResult<ValidateCallbackResult> { | ||
Ok( | ||
ValidateCallbackResult::Invalid( | ||
String::from("AllBoardDefs links cannot be deleted"), | ||
), | ||
) | ||
} |
Oops, something went wrong.