token program: Fix token account parsing
This commit is contained in:
parent
ca5e469dba
commit
ffe95d7199
25
README.md
25
README.md
|
@ -2266,7 +2266,9 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
bin "github.com/gagliardetto/binary"
|
||||
"github.com/gagliardetto/solana-go"
|
||||
"github.com/gagliardetto/solana-go/programs/token"
|
||||
"github.com/gagliardetto/solana-go/rpc"
|
||||
)
|
||||
|
||||
|
@ -2279,15 +2281,34 @@ func main() {
|
|||
context.TODO(),
|
||||
pubKey,
|
||||
&rpc.GetTokenAccountsConfig{
|
||||
Mint: solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112"),
|
||||
Mint: solana.WrappedSol.ToPointer(),
|
||||
},
|
||||
&rpc.GetTokenAccountsOpts{
|
||||
Encoding: solana.EncodingBase64Zstd,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
spew.Dump(out)
|
||||
|
||||
{
|
||||
tokenAccounts := make([]token.Account, 0)
|
||||
for _, rawAccount := range out.Value {
|
||||
var tokAcc token.Account
|
||||
|
||||
data := rawAccount.Account.Data.GetBinary()
|
||||
dec := bin.NewBinDecoder(data)
|
||||
err := dec.Decode(&tokAcc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tokenAccounts = append(tokenAccounts, tokAcc)
|
||||
}
|
||||
spew.Dump(tokenAccounts)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### [index](#contents) > [RPC](#rpc-methods) > GetTokenLargestAccounts
|
||||
|
|
|
@ -19,14 +19,13 @@ import (
|
|||
|
||||
bin "github.com/gagliardetto/binary"
|
||||
"github.com/gagliardetto/solana-go"
|
||||
ag_solanago "github.com/gagliardetto/solana-go"
|
||||
)
|
||||
|
||||
type Mint struct {
|
||||
// Optional authority used to mint new tokens. The mint authority may only be provided during
|
||||
// mint creation. If no mint authority is present then the mint has a fixed supply and no
|
||||
// further tokens may be minted.
|
||||
MintAuthority *ag_solanago.PublicKey `bin:"optional"`
|
||||
MintAuthority *solana.PublicKey `bin:"optional"`
|
||||
|
||||
// Total supply of tokens.
|
||||
Supply uint64
|
||||
|
@ -38,7 +37,7 @@ type Mint struct {
|
|||
IsInitialized bool
|
||||
|
||||
// Optional authority to freeze token accounts.
|
||||
FreezeAuthority *ag_solanago.PublicKey `bin:"optional"`
|
||||
FreezeAuthority *solana.PublicKey `bin:"optional"`
|
||||
}
|
||||
|
||||
func (mint *Mint) UnmarshalWithDecoder(dec *bin.Decoder) (err error) {
|
||||
|
@ -53,6 +52,9 @@ func (mint *Mint) UnmarshalWithDecoder(dec *bin.Decoder) (err error) {
|
|||
return err
|
||||
}
|
||||
mint.MintAuthority = solana.PublicKeyFromBytes(v).ToPointer()
|
||||
} else {
|
||||
// discard:
|
||||
dec.ReadNBytes(32)
|
||||
}
|
||||
}
|
||||
{
|
||||
|
@ -87,6 +89,9 @@ func (mint *Mint) UnmarshalWithDecoder(dec *bin.Decoder) (err error) {
|
|||
return err
|
||||
}
|
||||
mint.FreezeAuthority = solana.PublicKeyFromBytes(v).ToPointer()
|
||||
} else {
|
||||
// discard:
|
||||
dec.ReadNBytes(32)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -99,6 +104,11 @@ func (mint Mint) MarshalWithEncoder(encoder *bin.Encoder) (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
empty := solana.PublicKey{}
|
||||
err = encoder.WriteBytes(empty[:], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = encoder.WriteUint32(1, binary.LittleEndian)
|
||||
if err != nil {
|
||||
|
@ -128,6 +138,11 @@ func (mint Mint) MarshalWithEncoder(encoder *bin.Encoder) (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
empty := solana.PublicKey{}
|
||||
err = encoder.WriteBytes(empty[:], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = encoder.WriteUint32(1, binary.LittleEndian)
|
||||
if err != nil {
|
||||
|
@ -144,17 +159,17 @@ func (mint Mint) MarshalWithEncoder(encoder *bin.Encoder) (err error) {
|
|||
|
||||
type Account struct {
|
||||
// The mint associated with this account
|
||||
Mint ag_solanago.PublicKey
|
||||
Mint solana.PublicKey
|
||||
|
||||
// The owner of this account.
|
||||
Owner ag_solanago.PublicKey
|
||||
Owner solana.PublicKey
|
||||
|
||||
// The amount of tokens this account holds.
|
||||
Amount uint64
|
||||
|
||||
// If `delegate` is `Some` then `delegated_amount` represents
|
||||
// the amount authorized by the delegate
|
||||
Delegate *ag_solanago.PublicKey `bin:"optional"`
|
||||
Delegate *solana.PublicKey `bin:"optional"`
|
||||
|
||||
// The account's state
|
||||
State AccountState
|
||||
|
@ -168,5 +183,200 @@ type Account struct {
|
|||
DelegatedAmount uint64
|
||||
|
||||
// Optional authority to close the account.
|
||||
CloseAuthority *ag_solanago.PublicKey `bin:"optional"`
|
||||
CloseAuthority *solana.PublicKey `bin:"optional"`
|
||||
}
|
||||
|
||||
func (mint *Account) UnmarshalWithDecoder(dec *bin.Decoder) (err error) {
|
||||
{
|
||||
v, err := dec.ReadNBytes(32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mint.Mint = solana.PublicKeyFromBytes(v)
|
||||
}
|
||||
{
|
||||
v, err := dec.ReadNBytes(32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mint.Owner = solana.PublicKeyFromBytes(v)
|
||||
}
|
||||
{
|
||||
v, err := dec.ReadUint64(binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mint.Amount = v
|
||||
}
|
||||
{
|
||||
v, err := dec.ReadUint32(binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v == 1 {
|
||||
v, err := dec.ReadNBytes(32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mint.Delegate = solana.PublicKeyFromBytes(v).ToPointer()
|
||||
} else {
|
||||
// discard:
|
||||
dec.ReadNBytes(32)
|
||||
}
|
||||
}
|
||||
{
|
||||
v, err := dec.ReadUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mint.State = AccountState(v)
|
||||
}
|
||||
{
|
||||
v, err := dec.ReadUint32(binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v == 1 {
|
||||
v, err := dec.ReadUint64(bin.LE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mint.IsNative = &v
|
||||
} else {
|
||||
// discard:
|
||||
dec.ReadUint64(bin.LE)
|
||||
}
|
||||
}
|
||||
{
|
||||
v, err := dec.ReadUint64(binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mint.DelegatedAmount = v
|
||||
}
|
||||
{
|
||||
v, err := dec.ReadUint32(binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v == 1 {
|
||||
v, err := dec.ReadNBytes(32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mint.CloseAuthority = solana.PublicKeyFromBytes(v).ToPointer()
|
||||
} else {
|
||||
// discard:
|
||||
dec.ReadNBytes(32)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mint Account) MarshalWithEncoder(encoder *bin.Encoder) (err error) {
|
||||
{
|
||||
err = encoder.WriteBytes(mint.Mint[:], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
{
|
||||
err = encoder.WriteBytes(mint.Owner[:], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
{
|
||||
err = encoder.WriteUint64(mint.Amount, bin.LE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
{
|
||||
if mint.Delegate == nil {
|
||||
err = encoder.WriteUint32(0, binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
empty := solana.PublicKey{}
|
||||
err = encoder.WriteBytes(empty[:], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = encoder.WriteUint32(1, binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = encoder.WriteBytes(mint.Delegate[:], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
err = encoder.WriteUint8(uint8(mint.State))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{
|
||||
if mint.IsNative == nil {
|
||||
err = encoder.WriteUint32(0, binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = encoder.WriteUint64(0, bin.LE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = encoder.WriteUint32(1, binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = encoder.WriteUint64(*mint.IsNative, bin.LE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
err = encoder.WriteUint64(mint.DelegatedAmount, bin.LE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
{
|
||||
if mint.CloseAuthority == nil {
|
||||
err = encoder.WriteUint32(0, binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
empty := solana.PublicKey{}
|
||||
err = encoder.WriteBytes(empty[:], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = encoder.WriteUint32(1, binary.LittleEndian)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = encoder.WriteBytes(mint.CloseAuthority[:], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Multisig struct {
|
||||
// Number of signers required
|
||||
M uint8
|
||||
// Number of valid signers
|
||||
N uint8
|
||||
// Is `true` if this structure has been initialized
|
||||
IsInitialized bool
|
||||
// Signer public keys
|
||||
Signers [MAX_SIGNERS]solana.PublicKey
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func TestMint(t *testing.T) {
|
||||
account := []byte{
|
||||
accountBytes := []byte{
|
||||
1, 0, 0, 0,
|
||||
5, 234, 156, 241, 108, 228, 17, 152, 241, 164, 153, 55, 200, 140, 55, 10, 148, 212, 175, 255, 137, 181, 186, 203, 142, 244, 94, 99, 36, 187, 120, 247,
|
||||
9, 169, 49, 235, 241, 182, 6, 0,
|
||||
|
@ -21,7 +21,7 @@ func TestMint(t *testing.T) {
|
|||
5, 234, 156, 241, 108, 228, 17, 152, 241, 164, 153, 55, 200, 140, 55, 10, 148, 212, 175, 255, 137, 181, 186, 203, 142, 244, 94, 99, 36, 187, 120, 247,
|
||||
}
|
||||
{
|
||||
dec := bin.NewBinDecoder(account)
|
||||
dec := bin.NewBinDecoder(accountBytes)
|
||||
mint := Mint{}
|
||||
|
||||
err := dec.Decode(&mint)
|
||||
|
@ -42,7 +42,55 @@ func TestMint(t *testing.T) {
|
|||
buf := new(bytes.Buffer)
|
||||
err := bin.NewBinEncoder(buf).Encode(mint)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, account, buf.Bytes(), bin.FormatByteSlice(buf.Bytes()))
|
||||
require.Equal(t, accountBytes, buf.Bytes(), bin.FormatByteSlice(buf.Bytes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccount(t *testing.T) {
|
||||
accountBytes := []byte{
|
||||
6, 155, 136, 87, 254, 171, 129, 132, 251, 104, 127, 99, 70, 24, 192, 53, 218, 196, 57, 220, 26, 235, 59, 85, 152, 160, 240, 0, 0, 0, 0, 1,
|
||||
93, 100, 62, 133, 31, 102, 235, 161, 170, 152, 161, 7, 39, 223, 9, 180, 1, 224, 134, 204, 54, 241, 9, 195, 240, 147, 219, 146, 35, 92, 26, 224,
|
||||
42, 34, 176, 1, 0, 0, 0, 0,
|
||||
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
1,
|
||||
1, 0, 0, 0,
|
||||
240, 29, 31, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
{
|
||||
dec := bin.NewBinDecoder(accountBytes)
|
||||
account := Account{}
|
||||
|
||||
err := dec.Decode(&account)
|
||||
require.NoError(t, err, spew.Sdump(account))
|
||||
|
||||
balance := uint64(2039280)
|
||||
require.Equal(t,
|
||||
&Account{
|
||||
Mint: solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112"),
|
||||
Owner: solana.MustPublicKeyFromBase58("7HZaCWazgTuuFuajxaaxGYbGnyVKwxvsJKue1W4Nvyro"),
|
||||
Amount: (uint64)(28320298),
|
||||
Delegate: (*solana.PublicKey)(nil),
|
||||
State: (AccountState)(1),
|
||||
IsNative: (*uint64)(&balance),
|
||||
DelegatedAmount: (uint64)(0),
|
||||
CloseAuthority: (*solana.PublicKey)(nil),
|
||||
},
|
||||
&account,
|
||||
)
|
||||
|
||||
{
|
||||
buf := bin.NewWriteByWrite("")
|
||||
err := bin.NewBinEncoder(buf).Encode(account)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, accountBytes, buf.Bytes(), bin.FormatByteSlice(buf.Bytes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
ag_treeout "github.com/gagliardetto/treeout"
|
||||
)
|
||||
|
||||
// Maximum number of multisignature signers (max N)
|
||||
const MAX_SIGNERS = 11
|
||||
|
||||
var ProgramID ag_solanago.PublicKey = ag_solanago.TokenProgramID
|
||||
|
|
|
@ -16,7 +16,6 @@ package token
|
|||
|
||||
import (
|
||||
ag_binary "github.com/gagliardetto/binary"
|
||||
ag_solanago "github.com/gagliardetto/solana-go"
|
||||
)
|
||||
|
||||
type AuthorityType ag_binary.BorshEnum
|
||||
|
@ -49,17 +48,3 @@ const (
|
|||
// the delegate are able to perform operations on this account.
|
||||
Frozen
|
||||
)
|
||||
|
||||
type Multisig struct {
|
||||
// Number of signers required
|
||||
M uint8
|
||||
|
||||
// Number of valid signers
|
||||
N uint8
|
||||
|
||||
// Is `true` if this structure has been initialized
|
||||
IsInitialized bool
|
||||
|
||||
// Signer public keys
|
||||
Signers [11]ag_solanago.PublicKey
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
bin "github.com/gagliardetto/binary"
|
||||
"github.com/gagliardetto/solana-go"
|
||||
"github.com/gagliardetto/solana-go/programs/token"
|
||||
"github.com/gagliardetto/solana-go/rpc"
|
||||
)
|
||||
|
||||
|
@ -31,7 +33,7 @@ func main() {
|
|||
context.TODO(),
|
||||
pubKey,
|
||||
&rpc.GetTokenAccountsConfig{
|
||||
Mint: solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112").ToPointer(),
|
||||
Mint: solana.WrappedSol.ToPointer(),
|
||||
},
|
||||
&rpc.GetTokenAccountsOpts{
|
||||
Encoding: solana.EncodingBase64Zstd,
|
||||
|
@ -41,4 +43,20 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
spew.Dump(out)
|
||||
|
||||
{
|
||||
tokenAccounts := make([]token.Account, 0)
|
||||
for _, rawAccount := range out.Value {
|
||||
var tokAcc token.Account
|
||||
|
||||
data := rawAccount.Account.Data.GetBinary()
|
||||
dec := bin.NewBinDecoder(data)
|
||||
err := dec.Decode(&tokAcc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tokenAccounts = append(tokenAccounts, tokAcc)
|
||||
}
|
||||
spew.Dump(tokenAccounts)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue