Skip to content

Commit

Permalink
feat: deserializable events, fixes #147
Browse files Browse the repository at this point in the history
  • Loading branch information
encody committed May 8, 2024
1 parent 3a74539 commit 69ec6fb
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 26 deletions.
8 changes: 4 additions & 4 deletions macros/src/standard/nep297.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,11 @@ pub fn expand(meta: Nep297Meta) -> Result<TokenStream, darling::Error> {
impl #imp #me::standard::nep297::ToEventLog for #ident #ty #wher {
type Data = #ident #ty;

fn to_event_log<'__el>(&'__el self) -> #me::standard::nep297::EventLog<&'__el Self> {
fn to_event_log<'__el>(&'__el self) -> #me::standard::nep297::EventLog<&'__el Self::Data> {
#me::standard::nep297::EventLog {
standard: #standard,
version: #version,
event: #event,
standard: #standard.into(),
version: #version.into(),
event: #event.into(),
data: self,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const NO_PROPOSED_OWNER_FAIL_MESSAGE: &str = "No proposed owner";
crate = "crate",
macros = "near_sdk_contract_tools_macros"
)]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum OwnerEvent {
/// Emitted when the current owner of the contract changes
Transfer {
Expand Down
2 changes: 1 addition & 1 deletion src/pause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const PAUSED_FAIL_MESSAGE: &str = "Disallowed while contract is paused";
crate = "crate",
macros = "near_sdk_contract_tools_macros"
)]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum PauseEvent {
/// Emitted when the contract is paused
Pause,
Expand Down
2 changes: 1 addition & 1 deletion src/standard/nep141/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use near_sdk_contract_tools_macros::event;
standard = "nep141",
version = "1.0.0"
)]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum Nep141Event<'a> {
/// Token mint event. Emitted when tokens are created and total_supply is
/// increased.
Expand Down
2 changes: 1 addition & 1 deletion src/standard/nep171/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use near_sdk_contract_tools_macros::event;
standard = "nep171",
version = "1.2.0"
)]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum Nep171Event<'a> {
/// Emitted when a token is newly minted.
NftMint(Vec<NftMintLog<'a>>),
Expand Down
105 changes: 87 additions & 18 deletions src/standard/nep297.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
//! Helpers for `#[derive(near_sdk_contract_tools::Nep297)]`

use near_sdk::{serde::Serialize, serde_json};
use std::borrow::Cow;

use near_sdk::{
serde::{self, Deserialize, Serialize},
serde_json,
};

/// Emit events according to the [NEP-297 event standard](https://nomicon.io/Standards/EventsFormat).
///
/// # Examples
///
/// ## Normal events
///
/// ```
/// use near_sdk_contract_tools::event;
///
Expand All @@ -27,10 +30,10 @@ use near_sdk::{serde::Serialize, serde_json};
/// e.emit();
/// ```
pub trait Event {
/// Converts the event into an NEP-297 event-formatted string
/// Converts the event into an NEP-297 event-formatted string.
fn to_event_string(&self) -> String;

/// Emits the event string to the blockchain
/// Emits the event string to the blockchain.
fn emit(&self);
}

Expand Down Expand Up @@ -60,26 +63,92 @@ where
}
}

/// This type can be converted into an [`EventLog`] struct
/// This type can be converted into an [`EventLog`] struct.
pub trait ToEventLog {
/// Metadata associated with the event
type Data: ?Sized;
/// Metadata associated with the event.
type Data;

/// Retrieves the event log before serialization
/// Retrieves the event log before serialization.
fn to_event_log(&self) -> EventLog<&Self::Data>;
}

/// NEP-297 Event Log Data
/// <https://github.com/near/NEPs/blob/master/neps/nep-0297.md#specification>
#[derive(Serialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(crate = "near_sdk::serde")]
pub struct EventLog<T> {
/// Name of the event standard, e.g. "nep171"
pub standard: &'static str,
/// Version of the standard, e.g. "1.0.0"
pub version: &'static str,
/// Name of the particular event, e.g. "nft_mint", "ft_transfer"
pub event: &'static str,
/// Data type of the event metadata
pub struct EventLog<'a, T> {
/// Name of the event standard, e.g. `"nep171"`.
pub standard: Cow<'a, str>,
/// Version of the standard, e.g. `"1.0.0"`.
pub version: Cow<'a, str>,
/// Name of the particular event, e.g. `"nft_mint"`, `"ft_transfer"`.
pub event: Cow<'a, str>,
/// Data type of the event metadata.
pub data: T,
}

impl<'de, T: Deserialize<'de>> EventLog<'de, T> {
/// Deserializes an event log from a string.
///
/// # Errors
///
/// Will return `Err` if the string is not a valid event log. A valid event
/// log begins with the string `"EVENT_JSON:"`, and is followed by a JSON
/// string.
pub fn from_event_log_string(s: &'de str) -> Result<Self, serde::de::value::Error> {
let data_str = s
.strip_prefix("EVENT_JSON:")
.ok_or(serde::de::Error::custom(serde::de::Unexpected::Str(
"EVENT_JSON:",
)))?;
let data =
serde_json::from_str::<EventLog<T>>(data_str).map_err(serde::de::Error::custom)?;
let x = Some(1);
x.as_ref();
Ok(data)
}

/// Converts the event log into a borrowed reference.
pub fn as_ref(&self) -> EventLog<&T> {
EventLog {
standard: Cow::Borrowed(&self.standard),
version: Cow::Borrowed(&self.version),
event: Cow::Borrowed(&self.event),
data: &self.data,
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn to_and_from_event_log() {
#[derive(Debug, PartialEq, Eq)]
struct MyEvent;

impl ToEventLog for MyEvent {
type Data = u32;

fn to_event_log(&self) -> EventLog<&u32> {
EventLog {
standard: "nep171".into(),
version: "1.0.0".into(),
event: "nft_mint".into(),
data: &1,
}
}
}

let event = MyEvent;

let string = event.to_event_string();

assert_eq!(string, "EVENT_JSON:{\"standard\":\"nep171\",\"version\":\"1.0.0\",\"event\":\"nft_mint\",\"data\":1}");

let from_event_log_str = EventLog::<u32>::from_event_log_string(&string).unwrap();

assert_eq!(from_event_log_str.as_ref(), event.to_event_log());
}
}

0 comments on commit 69ec6fb

Please sign in to comment.