-
Notifications
You must be signed in to change notification settings - Fork 10
/
raw.go
215 lines (178 loc) · 5.56 KB
/
raw.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package pocketic
import (
"encoding/base64"
"encoding/json"
"fmt"
)
// Base64EncodedBlob is a byte slice that is base64 encoded when marshaled to JSON.
// The underlying byte slice is already decoded, so it can be used as is.
type Base64EncodedBlob []byte
func (b Base64EncodedBlob) MarshalJSON() ([]byte, error) {
encoded := base64.StdEncoding.EncodeToString(b)
return json.Marshal(encoded)
}
// String returns the base64 encoded string of the blob.
// NOTE: it will truncate the string if it is too long.
func (b Base64EncodedBlob) String() string {
str := base64.StdEncoding.EncodeToString(b)
if len(str) > 20 {
return str[:10] + "..." + str[len(str)-10:]
}
return str
}
func (b *Base64EncodedBlob) UnmarshalJSON(bytes []byte) error {
var encoded string
if err := json.Unmarshal(bytes, &encoded); err != nil {
return err
}
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
return err
}
*b = decoded
return nil
}
type EffectivePrincipal interface {
rawEffectivePrincipal()
}
func unmarshalRawEffectivePrincipal(bytes []byte) (EffectivePrincipal, error) {
var none EffectivePrincipalNone
if err := json.Unmarshal(bytes, &none); err == nil {
return none, nil
}
var m map[string]Base64EncodedBlob
if err := json.Unmarshal(bytes, &m); err != nil {
return nil, err
}
if canisterID, ok := m["CanisterId"]; ok {
return EffectivePrincipalCanisterID{CanisterID: canisterID}, nil
}
if subnetID, ok := m["SubnetId"]; ok {
return EffectivePrincipalSubnetID{SubnetID: subnetID}, nil
}
return nil, fmt.Errorf("unknown effective principal: %s", string(bytes))
}
type EffectivePrincipalCanisterID struct {
CanisterID Base64EncodedBlob `json:"CanisterId"`
}
func (EffectivePrincipalCanisterID) rawEffectivePrincipal() {}
type EffectivePrincipalNone struct{}
func (n EffectivePrincipalNone) MarshalJSON() ([]byte, error) {
return json.Marshal(new(None))
}
func (n EffectivePrincipalNone) UnmarshalJSON(bytes []byte) error {
var none None
return json.Unmarshal(bytes, &none)
}
func (EffectivePrincipalNone) rawEffectivePrincipal() {}
type EffectivePrincipalSubnetID struct {
SubnetID Base64EncodedBlob `json:"SubnetId"`
}
func (EffectivePrincipalSubnetID) rawEffectivePrincipal() {}
type MessageID struct {
EffectivePrincipal EffectivePrincipal `json:"effective_principal"`
MessageID Base64EncodedBlob `json:"message_id"`
}
func (r *MessageID) UnmarshalJSON(bytes []byte) error {
var raw struct {
EffectivePrincipal json.RawMessage `json:"effective_principal"`
MessageID Base64EncodedBlob `json:"message_id"`
}
if err := json.Unmarshal(bytes, &raw); err != nil {
return err
}
ep, err := unmarshalRawEffectivePrincipal(raw.EffectivePrincipal)
if err != nil {
return err
}
r.EffectivePrincipal = ep
r.MessageID = raw.MessageID
return nil
}
type RawCanisterID struct {
CanisterID Base64EncodedBlob `json:"canister_id"`
}
type Reject string
func (r Reject) Error() string {
return string(r)
}
type SubnetID struct {
SubnetID Base64EncodedBlob `json:"subnet_id"`
}
type UserError struct {
Code string `json:"code"`
Description string `json:"description"`
}
func (e UserError) Error() string {
return fmt.Sprintf("(%s) %s", e.Code, e.Description)
}
type VerifyCanisterSigArg struct {
Message Base64EncodedBlob `json:"msg"`
PublicKey Base64EncodedBlob `json:"pubkey"`
RootPubKey Base64EncodedBlob `json:"root_pubkey"`
Signature Base64EncodedBlob `json:"sig"`
}
type createResponse[T any] struct {
Created *T `json:"Created"`
Error *ErrorMessage `json:"Error"`
}
type rawAddCycles struct {
Amount int `json:"amount"`
CanisterID Base64EncodedBlob `json:"canister_id"`
}
type rawCanisterCall struct {
CanisterID Base64EncodedBlob `json:"canister_id"`
EffectivePrincipal EffectivePrincipal `json:"effective_principal"`
Method string `json:"method"`
Payload Base64EncodedBlob `json:"payload"`
Sender Base64EncodedBlob `json:"sender"`
}
func (r *rawCanisterCall) UnmarshalJSON(bytes []byte) error {
var raw struct {
CanisterID Base64EncodedBlob `json:"canister_id"`
EffectivePrincipal json.RawMessage `json:"effective_principal"`
Method string `json:"method"`
Payload Base64EncodedBlob `json:"payload"`
Sender Base64EncodedBlob `json:"sender"`
}
if err := json.Unmarshal(bytes, &raw); err != nil {
return err
}
ep, err := unmarshalRawEffectivePrincipal(raw.EffectivePrincipal)
if err != nil {
return err
}
r.CanisterID = raw.CanisterID
r.EffectivePrincipal = ep
r.Method = raw.Method
r.Payload = raw.Payload
r.Sender = raw.Sender
return nil
}
type rawCanisterResult result[rawWasmResult]
type rawCycles struct {
Cycles int `json:"cycles"`
}
type rawSetStableMemory struct {
BlobID Base64EncodedBlob `json:"blob_id"`
CanisterID Base64EncodedBlob `json:"canister_id"`
}
type rawStableMemory struct {
Blob Base64EncodedBlob `json:"blob"`
}
type rawSubmitIngressResult result[MessageID]
type rawTime struct {
NanosSinceEpoch int64 `json:"nanos_since_epoch"`
}
type rawWasmResult wasmResult[Base64EncodedBlob]
type result[R any] struct {
Ok *R `json:"Ok,omitempty"`
Err *UserError `json:"Err,omitempty"`
}
// wasmResult describes the different types that executing a WASM function in a canister can produce.
type wasmResult[Blob any] struct {
// Raw response, returned in a successful case.
Reply *Blob `json:"reply,omitempty"`
// Returned with an error message when the canister decides to reject the message.
Reject *Reject `json:"reject,omitempty"`
}