Skip to content

Commit

Permalink
token program: Fix token account parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
gagliardetto committed Feb 15, 2022
1 parent ca5e469 commit ffe95d7
Show file tree
Hide file tree
Showing 6 changed files with 311 additions and 28 deletions.
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -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
Expand Down
224 changes: 217 additions & 7 deletions programs/token/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -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)
}
}
{
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand All @@ -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
}
Loading

0 comments on commit ffe95d7

Please sign in to comment.