This repository has been archived by the owner on Jan 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
state.go
131 lines (111 loc) · 3.36 KB
/
state.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
package token
import (
"crypto/ed25519"
"encoding/binary"
)
type AccountState byte
const (
AccountStateUninitialized AccountState = iota
AccountStateInitialized
AccountStateFrozen
)
// Reference: https://github.com/solana-labs/solana-program-library/blob/11b1e3eefdd4e523768d63f7c70a7aa391ea0d02/token/program/src/state.rs#L125
const AccountSize = 165
// Reference: https://github.com/solana-labs/solana-program-library/blob/8944f428fe693c3a4226bf766a79be9c75e8e520/token/program/src/state.rs#L214
const MultisigAccountSize = 355
type Account struct {
// The mint associated with this account
Mint ed25519.PublicKey
// The owner of this account.
Owner ed25519.PublicKey
// The amount of tokens this account holds.
Amount uint64
// If set, then the 'DelegatedAmount' represents the amount
// authorized by the delegate.
Delegate ed25519.PublicKey
/// The account's state
State AccountState
// If set, this is a native token, and the value logs the rent-exempt reserve. An Account
// is required to be rent-exempt, so the value is used by the Processor to ensure that wrapped
// SOL accounts do not drop below this threshold.
IsNative *uint64
// The amount delegated
DelegatedAmount uint64
// Optional authority to close the account.
CloseAuthority ed25519.PublicKey
}
func (a *Account) Marshal() []byte {
b := make([]byte, AccountSize)
var offset int
writeKey(b, a.Mint, &offset)
writeKey(b[offset:], a.Owner, &offset)
writeUint64(b[offset:], a.Amount, &offset)
writeOptionalKey(b[offset:], a.Delegate, &offset)
b[offset] = byte(a.State)
offset++
writeOptionalUint64(b[offset:], a.IsNative, &offset)
writeUint64(b[offset:], a.DelegatedAmount, &offset)
writeOptionalKey(b[offset:], a.CloseAuthority, &offset)
return b
}
func writeKey(dst []byte, src []byte, offset *int) {
copy(dst, src)
*offset += ed25519.PublicKeySize
}
func writeOptionalKey(dst []byte, src []byte, offset *int) {
if len(src) > 0 {
dst[0] = 1
copy(dst[4:], src)
}
*offset += 4 + ed25519.PublicKeySize
}
func writeUint64(dst []byte, v uint64, offset *int) {
binary.LittleEndian.PutUint64(dst, v)
*offset += 8
}
func writeOptionalUint64(dst []byte, v *uint64, offset *int) {
if v != nil {
dst[0] = 1
binary.LittleEndian.PutUint64(dst[4:], *v)
}
*offset += 4 + 8
}
func (a *Account) Unmarshal(b []byte) bool {
if len(b) != AccountSize {
return false
}
var offset int
loadKey(b, &a.Mint, &offset)
loadKey(b[offset:], &a.Owner, &offset)
loadUint64(b[offset:], &a.Amount, &offset)
loadOptionalKey(b[offset:], &a.Delegate, &offset)
a.State = AccountState(b[offset])
offset++
loadOptionalUint64(b[offset:], &a.IsNative, &offset)
loadUint64(b[offset:], &a.DelegatedAmount, &offset)
loadOptionalKey(b[offset:], &a.CloseAuthority, &offset)
return true
}
func loadKey(src []byte, dst *ed25519.PublicKey, offset *int) {
*dst = make([]byte, ed25519.PublicKeySize)
copy(*dst, src)
*offset += ed25519.PublicKeySize
}
func loadOptionalKey(src []byte, dst *ed25519.PublicKey, offset *int) {
if src[0] == 1 {
*dst = make([]byte, ed25519.PublicKeySize)
copy(*dst, src[4:])
}
*offset += 4 + ed25519.PublicKeySize
}
func loadUint64(src []byte, dst *uint64, offset *int) {
*dst = binary.LittleEndian.Uint64(src)
*offset += 8
}
func loadOptionalUint64(src []byte, dst **uint64, offset *int) {
if src[0] == 1 {
val := binary.LittleEndian.Uint64(src[4:])
*dst = &val
}
*offset += 4 + 8
}