1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! Events emitted by the position token contract
use cosmwasm_std::{Addr, Event};
use cw_utils::Expiration;
use shared::prelude::*;

/// New NFT was minted
#[derive(Debug)]
pub struct MintEvent {
    /// Position token ID
    pub token_id: String,
    /// Owner of the position
    pub owner: Addr,
}

impl From<MintEvent> for Event {
    fn from(src: MintEvent) -> Self {
        Event::new("mint").add_attributes(vec![
            ("token_id", src.token_id.to_string()),
            ("owner", src.owner.to_string()),
        ])
    }
}

impl TryFrom<Event> for MintEvent {
    type Error = anyhow::Error;

    fn try_from(evt: Event) -> anyhow::Result<Self> {
        Ok(MintEvent {
            token_id: evt.string_attr("token_id")?,
            owner: evt.unchecked_addr_attr("owner")?,
        })
    }
}

/// NFT was burned, aka a position was closed
#[derive(Debug)]
pub struct BurnEvent {
    /// Position that was closed
    pub token_id: String,
}

impl From<BurnEvent> for Event {
    fn from(src: BurnEvent) -> Self {
        Event::new("burn").add_attributes(vec![("token_id", src.token_id)])
    }
}

impl TryFrom<Event> for BurnEvent {
    type Error = anyhow::Error;

    fn try_from(evt: Event) -> anyhow::Result<Self> {
        Ok(BurnEvent {
            token_id: evt.string_attr("token_id")?,
        })
    }
}

// converting expiration back into an event is painful
// so these are just unidirectional for now

/// Approval was granted
#[derive(Debug)]
pub struct ApprovalEvent {
    /// Position
    pub token_id: String,
    /// Who can spend it
    pub spender: Addr,
    /// When it expires
    pub expires: Expiration,
}

impl From<ApprovalEvent> for Event {
    fn from(src: ApprovalEvent) -> Self {
        Event::new("approval").add_attributes(vec![
            ("token_id", src.token_id.to_string()),
            ("spender", src.spender.to_string()),
            ("expires", src.expires.to_string()),
        ])
    }
}

/// Approval was revoked
#[derive(Debug)]
pub struct RevokeEvent {
    /// Position ID
    pub token_id: String,
    /// Whose spend permissions were revoked
    pub spender: Addr,
}

impl From<RevokeEvent> for Event {
    fn from(src: RevokeEvent) -> Self {
        Event::new("revoke").add_attributes(vec![
            ("token_id", src.token_id.to_string()),
            ("spender", src.spender.to_string()),
        ])
    }
}

/// An operator was granted spend permissions on all positions for a wallet
#[derive(Debug)]
pub struct ApproveAllEvent {
    /// Who is the operator
    pub operator: Addr,
    /// When does the permission expire
    pub expires: Expiration,
}

impl From<ApproveAllEvent> for Event {
    fn from(src: ApproveAllEvent) -> Self {
        Event::new("approve-all").add_attributes(vec![
            ("operator", src.operator.to_string()),
            ("expires", src.expires.to_string()),
        ])
    }
}

/// Revoke all permissions for an operator
#[derive(Debug)]
pub struct RevokeAllEvent {
    /// Operator to revoke
    pub operator: Addr,
}

impl From<RevokeAllEvent> for Event {
    fn from(src: RevokeAllEvent) -> Self {
        Event::new("revoke-all").add_attributes(vec![("operator", src.operator.to_string())])
    }
}

/// NFT was transferred
#[derive(Debug)]
pub struct TransferEvent {
    /// New owner
    pub recipient: Addr,
    /// Position ID
    pub token_id: String,
}

impl From<TransferEvent> for Event {
    fn from(src: TransferEvent) -> Self {
        Event::new("transfer").add_attributes(vec![
            ("recipient", src.recipient.to_string()),
            ("token_id", src.token_id),
        ])
    }
}