-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathaction.go
169 lines (127 loc) · 3.65 KB
/
action.go
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package action
import (
"errors"
"time"
"github.com/code-payments/code-server/pkg/pointer"
"github.com/code-payments/code-server/pkg/code/data/intent"
)
type Type uint8
const (
UnknownType Type = iota
OpenAccount
CloseEmptyAccount
CloseDormantAccount
NoPrivacyTransfer
NoPrivacyWithdraw
PrivateTransfer // Incorprorates all client-side private movement of funds. Backend processes don't care about the distinction, yet.
SaveRecentRoot
)
type State uint8
const (
StateUnknown State = iota
StatePending
StateRevoked
StateConfirmed
StateFailed
)
type ByActionId []*Record
func (a ByActionId) Len() int { return len(a) }
func (a ByActionId) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByActionId) Less(i, j int) bool { return a[i].ActionId < a[j].ActionId }
type Record struct {
Id uint64
Intent string
IntentType intent.Type
ActionId uint32
ActionType Type
Source string // Source token account involved
Destination *string // Destination token account involved, when it makes sense
// Kin quark amount involved, when it makes sense. This must be set for actions
// that make balance changes across Code accounts! For deferred actions that are
// initially in the unknown state, the balance may be nil and updated at a later
// time. Store implementations will enforce which actions will allow quantity updates.
//
// todo: We have some options of how to handle balance calculations for actions in
// the unknown state. For now, remain in the most flexible state (ie. set quantity
// as needed and include everything in the calculation). We'll wait for more
// use cases before forming a firm opinion.
Quantity *uint64
InitiatorPhoneNumber *string
State State
CreatedAt time.Time
}
func (r *Record) Validate() error {
if len(r.Intent) == 0 {
return errors.New("intent is required")
}
if r.IntentType == intent.UnknownType {
return errors.New("intent type is required")
}
if r.ActionType == UnknownType {
return errors.New("action type is required")
}
// todo: validate intent and action type align
if len(r.Source) == 0 {
return errors.New("source is required")
}
if r.Destination != nil && len(*r.Destination) == 0 {
return errors.New("destination is required when set")
}
if r.Quantity != nil && *r.Quantity == 0 {
return errors.New("quantity is required when set")
}
if r.InitiatorPhoneNumber != nil && len(*r.InitiatorPhoneNumber) == 0 {
return errors.New("initiator phone number is required when set")
}
return nil
}
func (r *Record) Clone() Record {
return Record{
Id: r.Id,
Intent: r.Intent,
IntentType: r.IntentType,
ActionId: r.ActionId,
ActionType: r.ActionType,
Source: r.Source,
Destination: pointer.StringCopy(r.Destination),
Quantity: pointer.Uint64Copy(r.Quantity),
InitiatorPhoneNumber: pointer.StringCopy(r.InitiatorPhoneNumber),
State: r.State,
CreatedAt: r.CreatedAt,
}
}
func (r *Record) CopyTo(dst *Record) {
dst.Id = r.Id
dst.Intent = r.Intent
dst.IntentType = r.IntentType
dst.ActionId = r.ActionId
dst.ActionType = r.ActionType
dst.Source = r.Source
dst.Destination = r.Destination
dst.Quantity = r.Quantity
dst.InitiatorPhoneNumber = r.InitiatorPhoneNumber
dst.State = r.State
dst.CreatedAt = r.CreatedAt
}
func (s State) IsTerminal() bool {
switch s {
case StateConfirmed, StateFailed, StateRevoked:
return true
}
return false
}
func (s State) String() string {
switch s {
case StateUnknown:
return "unknown"
case StatePending:
return "pending"
case StateConfirmed:
return "confirmed"
case StateFailed:
return "failed"
case StateRevoked:
return "revoked"
}
return "unknown"
}