From 54f848ef5a49aece7ff8fdc7bbbc7e6b111af4a9 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 00:43:43 +0200 Subject: [PATCH 01/24] Stub token program --- cmd/slnc/cmd/token_get_mint.go | 4 +- cmd/slnc/cmd/token_list_mints.go | 5 +- programs/token/Approve.go | 186 +++++++ programs/token/ApproveChecked.go | 234 +++++++++ programs/token/ApproveChecked_test.go | 31 ++ programs/token/Approve_test.go | 31 ++ programs/token/Burn.go | 186 +++++++ programs/token/BurnChecked.go | 216 ++++++++ programs/token/BurnChecked_test.go | 31 ++ programs/token/Burn_test.go | 31 ++ programs/token/CloseAccount.go | 155 ++++++ programs/token/CloseAccount_test.go | 31 ++ programs/token/FreezeAccount.go | 154 ++++++ programs/token/FreezeAccount_test.go | 31 ++ programs/token/InitializeAccount.go | 165 ++++++ programs/token/InitializeAccount2.go | 170 +++++++ programs/token/InitializeAccount2_test.go | 31 ++ programs/token/InitializeAccount3.go | 147 ++++++ programs/token/InitializeAccount3_test.go | 31 ++ programs/token/InitializeAccount_test.go | 31 ++ programs/token/InitializeMint.go | 223 +++++++++ programs/token/InitializeMint2.go | 196 ++++++++ programs/token/InitializeMint2_test.go | 31 ++ programs/token/InitializeMint_test.go | 31 ++ programs/token/InitializeMultisig.go | 186 +++++++ programs/token/InitializeMultisig2.go | 147 ++++++ programs/token/InitializeMultisig2_test.go | 31 ++ programs/token/InitializeMultisig_test.go | 31 ++ programs/token/MintTo.go | 186 +++++++ programs/token/MintToChecked.go | 214 ++++++++ programs/token/MintToChecked_test.go | 31 ++ programs/token/MintTo_test.go | 31 ++ programs/token/Revoke.go | 135 +++++ programs/token/Revoke_test.go | 31 ++ programs/token/SetAuthority.go | 209 ++++++++ programs/token/SetAuthority_test.go | 31 ++ programs/token/SyncNative.go | 101 ++++ programs/token/SyncNative_test.go | 31 ++ programs/token/ThawAccount.go | 154 ++++++ programs/token/ThawAccount_test.go | 31 ++ programs/token/Transfer.go | 188 +++++++ programs/token/TransferChecked.go | 236 +++++++++ programs/token/TransferChecked_test.go | 31 ++ programs/token/Transfer_test.go | 31 ++ programs/token/accounts.go | 51 ++ programs/token/instructions.go | 468 ++++++++++++------ programs/token/mints-data/mainnet-tokens.json | 148 ------ programs/token/rice-box.go | 44 -- programs/token/rpc.go | 16 +- programs/token/testing_utils.go | 18 + programs/token/types.go | 87 ++-- programs/token/types_test.go | 106 ---- 52 files changed, 4865 insertions(+), 521 deletions(-) create mode 100644 programs/token/Approve.go create mode 100644 programs/token/ApproveChecked.go create mode 100644 programs/token/ApproveChecked_test.go create mode 100644 programs/token/Approve_test.go create mode 100644 programs/token/Burn.go create mode 100644 programs/token/BurnChecked.go create mode 100644 programs/token/BurnChecked_test.go create mode 100644 programs/token/Burn_test.go create mode 100644 programs/token/CloseAccount.go create mode 100644 programs/token/CloseAccount_test.go create mode 100644 programs/token/FreezeAccount.go create mode 100644 programs/token/FreezeAccount_test.go create mode 100644 programs/token/InitializeAccount.go create mode 100644 programs/token/InitializeAccount2.go create mode 100644 programs/token/InitializeAccount2_test.go create mode 100644 programs/token/InitializeAccount3.go create mode 100644 programs/token/InitializeAccount3_test.go create mode 100644 programs/token/InitializeAccount_test.go create mode 100644 programs/token/InitializeMint.go create mode 100644 programs/token/InitializeMint2.go create mode 100644 programs/token/InitializeMint2_test.go create mode 100644 programs/token/InitializeMint_test.go create mode 100644 programs/token/InitializeMultisig.go create mode 100644 programs/token/InitializeMultisig2.go create mode 100644 programs/token/InitializeMultisig2_test.go create mode 100644 programs/token/InitializeMultisig_test.go create mode 100644 programs/token/MintTo.go create mode 100644 programs/token/MintToChecked.go create mode 100644 programs/token/MintToChecked_test.go create mode 100644 programs/token/MintTo_test.go create mode 100644 programs/token/Revoke.go create mode 100644 programs/token/Revoke_test.go create mode 100644 programs/token/SetAuthority.go create mode 100644 programs/token/SetAuthority_test.go create mode 100644 programs/token/SyncNative.go create mode 100644 programs/token/SyncNative_test.go create mode 100644 programs/token/ThawAccount.go create mode 100644 programs/token/ThawAccount_test.go create mode 100644 programs/token/Transfer.go create mode 100644 programs/token/TransferChecked.go create mode 100644 programs/token/TransferChecked_test.go create mode 100644 programs/token/Transfer_test.go create mode 100644 programs/token/accounts.go delete mode 100644 programs/token/mints-data/mainnet-tokens.json delete mode 100644 programs/token/rice-box.go create mode 100644 programs/token/testing_utils.go delete mode 100644 programs/token/types_test.go diff --git a/cmd/slnc/cmd/token_get_mint.go b/cmd/slnc/cmd/token_get_mint.go index 2e65488a..18e1555a 100644 --- a/cmd/slnc/cmd/token_get_mint.go +++ b/cmd/slnc/cmd/token_get_mint.go @@ -57,13 +57,13 @@ var tokenGetMintCmd = &cobra.Command{ out = append(out, fmt.Sprintf("Supply | %d", mint.Supply)) out = append(out, fmt.Sprintf("Decimals | %d", mint.Decimals)) - if mint.MintAuthorityOption != 0 { + if mint.MintAuthority != nil { out = append(out, fmt.Sprintf("Token Authority | %s", mint.MintAuthority)) } else { out = append(out, "No mint authority") } - if mint.FreezeAuthorityOption != 0 { + if mint.FreezeAuthority != nil { out = append(out, fmt.Sprintf("Freeze Authority | %s", mint.FreezeAuthority)) } else { out = append(out, "No freeze authority") diff --git a/cmd/slnc/cmd/token_list_mints.go b/cmd/slnc/cmd/token_list_mints.go index 246f23e6..a4281d78 100644 --- a/cmd/slnc/cmd/token_list_mints.go +++ b/cmd/slnc/cmd/token_list_mints.go @@ -36,16 +36,15 @@ var tokenListMintsCmd = &cobra.Command{ out := []string{"Mint | Decimals | Supply | Token Authority | Freeze Authority"} for _, m := range mints { line := []string{ - fmt.Sprintf("%d", m.MintAuthorityOption), fmt.Sprintf("%d", m.Supply), fmt.Sprintf("%d", m.Decimals), } - if m.MintAuthorityOption != 0 { + if m.MintAuthority != nil { line = append(line, fmt.Sprintf("%s", m.MintAuthority)) } else { line = append(line, "No mint authority") } - if m.FreezeAuthorityOption != 0 { + if m.FreezeAuthority != nil { line = append(line, fmt.Sprintf("%s", m.FreezeAuthority)) } else { line = append(line, "No freeze authority") diff --git a/programs/token/Approve.go b/programs/token/Approve.go new file mode 100644 index 00000000..c9c4944a --- /dev/null +++ b/programs/token/Approve.go @@ -0,0 +1,186 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Approves a delegate. A delegate is given the authority over tokens on +// behalf of the source account's owner. +type Approve struct { + // The amount of tokens the delegate is approved for. + Amount *uint64 + + // [0] = [WRITE] source + // ··········· The source account. + // + // [1] = [] delegate + // ··········· The delegate. + // + // [2] = [] owner + // ··········· The source account owner. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewApproveInstructionBuilder creates a new `Approve` instruction builder. +func NewApproveInstructionBuilder() *Approve { + nd := &Approve{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The amount of tokens the delegate is approved for. +func (inst *Approve) SetAmount(amount uint64) *Approve { + inst.Amount = &amount + return inst +} + +// The source account. +func (inst *Approve) SetSourceAccount(source ag_solanago.PublicKey) *Approve { + inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + return inst +} + +func (inst *Approve) GetSourceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The delegate. +func (inst *Approve) SetDelegateAccount(delegate ag_solanago.PublicKey) *Approve { + inst.AccountMetaSlice[1] = ag_solanago.Meta(delegate) + return inst +} + +func (inst *Approve) GetDelegateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The source account owner. +func (inst *Approve) SetOwnerAccount(owner ag_solanago.PublicKey) *Approve { + inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) + return inst +} + +func (inst *Approve) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *Approve) SetSignersAccount(signers ag_solanago.PublicKey) *Approve { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *Approve) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst Approve) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_Approve, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Approve) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Approve) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Amount == nil { + return errors.New("Amount parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Source is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Delegate is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *Approve) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Approve")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("delegate", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj Approve) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + return nil +} +func (obj *Approve) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + return nil +} + +// NewApproveInstruction declares a new Approve instruction with the provided parameters and accounts. +func NewApproveInstruction( + // Parameters: + amount uint64, + // Accounts: + source ag_solanago.PublicKey, + delegate ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *Approve { + return NewApproveInstructionBuilder(). + SetAmount(amount). + SetSourceAccount(source). + SetDelegateAccount(delegate). + SetOwnerAccount(owner). + SetSignersAccount(signers) +} diff --git a/programs/token/ApproveChecked.go b/programs/token/ApproveChecked.go new file mode 100644 index 00000000..da47f29f --- /dev/null +++ b/programs/token/ApproveChecked.go @@ -0,0 +1,234 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Approves a delegate. A delegate is given the authority over tokens on +// behalf of the source account's owner. +// +// This instruction differs from Approve in that the token mint and +// decimals value is checked by the caller. This may be useful when +// creating transactions offline or within a hardware wallet. +type ApproveChecked struct { + // The amount of tokens the delegate is approved for. + Amount *uint64 + + // Expected number of base 10 digits to the right of the decimal place. + Decimals *uint8 + + // [0] = [WRITE] source + // ··········· The source account. + // + // [1] = [] mint + // ··········· The token mint. + // + // [2] = [] delegate + // ··········· The delegate. + // + // [3] = [] owner + // ··········· The source account owner. + // + // [4] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewApproveCheckedInstructionBuilder creates a new `ApproveChecked` instruction builder. +func NewApproveCheckedInstructionBuilder() *ApproveChecked { + nd := &ApproveChecked{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 5), + } + return nd +} + +// The amount of tokens the delegate is approved for. +func (inst *ApproveChecked) SetAmount(amount uint64) *ApproveChecked { + inst.Amount = &amount + return inst +} + +// Expected number of base 10 digits to the right of the decimal place. +func (inst *ApproveChecked) SetDecimals(decimals uint8) *ApproveChecked { + inst.Decimals = &decimals + return inst +} + +// The source account. +func (inst *ApproveChecked) SetSourceAccount(source ag_solanago.PublicKey) *ApproveChecked { + inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + return inst +} + +func (inst *ApproveChecked) GetSourceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The token mint. +func (inst *ApproveChecked) SetMintAccount(mint ag_solanago.PublicKey) *ApproveChecked { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + return inst +} + +func (inst *ApproveChecked) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The delegate. +func (inst *ApproveChecked) SetDelegateAccount(delegate ag_solanago.PublicKey) *ApproveChecked { + inst.AccountMetaSlice[2] = ag_solanago.Meta(delegate) + return inst +} + +func (inst *ApproveChecked) GetDelegateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// The source account owner. +func (inst *ApproveChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *ApproveChecked { + inst.AccountMetaSlice[3] = ag_solanago.Meta(owner) + return inst +} + +func (inst *ApproveChecked) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// M signer accounts. +func (inst *ApproveChecked) SetSignersAccount(signers ag_solanago.PublicKey) *ApproveChecked { + inst.AccountMetaSlice[4] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *ApproveChecked) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +func (inst ApproveChecked) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_ApproveChecked, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst ApproveChecked) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *ApproveChecked) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Amount == nil { + return errors.New("Amount parameter is not set") + } + if inst.Decimals == nil { + return errors.New("Decimals parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Source is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Delegate is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[4] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *ApproveChecked) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("ApproveChecked")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("delegate", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[4])) + }) + }) + }) +} + +func (obj ApproveChecked) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `Decimals` param: + err = encoder.Encode(obj.Decimals) + if err != nil { + return err + } + return nil +} +func (obj *ApproveChecked) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `Decimals`: + err = decoder.Decode(&obj.Decimals) + if err != nil { + return err + } + return nil +} + +// NewApproveCheckedInstruction declares a new ApproveChecked instruction with the provided parameters and accounts. +func NewApproveCheckedInstruction( + // Parameters: + amount uint64, + decimals uint8, + // Accounts: + source ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + delegate ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *ApproveChecked { + return NewApproveCheckedInstructionBuilder(). + SetAmount(amount). + SetDecimals(decimals). + SetSourceAccount(source). + SetMintAccount(mint). + SetDelegateAccount(delegate). + SetOwnerAccount(owner). + SetSignersAccount(signers) +} diff --git a/programs/token/ApproveChecked_test.go b/programs/token/ApproveChecked_test.go new file mode 100644 index 00000000..c4fa7b0c --- /dev/null +++ b/programs/token/ApproveChecked_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_ApproveChecked(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("ApproveChecked"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(ApproveChecked) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(ApproveChecked) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/Approve_test.go b/programs/token/Approve_test.go new file mode 100644 index 00000000..ba656e82 --- /dev/null +++ b/programs/token/Approve_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Approve(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Approve"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Approve) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(Approve) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/Burn.go b/programs/token/Burn.go new file mode 100644 index 00000000..c6701824 --- /dev/null +++ b/programs/token/Burn.go @@ -0,0 +1,186 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Burns tokens by removing them from an account. `Burn` does not support +// accounts associated with the native mint, use `CloseAccount` instead. +type Burn struct { + // The amount of tokens to burn. + Amount *uint64 + + // [0] = [WRITE] source + // ··········· The account to burn from. + // + // [1] = [WRITE] mint + // ··········· The token mint. + // + // [2] = [] owner + // ··········· The account's owner/delegate. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewBurnInstructionBuilder creates a new `Burn` instruction builder. +func NewBurnInstructionBuilder() *Burn { + nd := &Burn{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The amount of tokens to burn. +func (inst *Burn) SetAmount(amount uint64) *Burn { + inst.Amount = &amount + return inst +} + +// The account to burn from. +func (inst *Burn) SetSourceAccount(source ag_solanago.PublicKey) *Burn { + inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + return inst +} + +func (inst *Burn) GetSourceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The token mint. +func (inst *Burn) SetMintAccount(mint ag_solanago.PublicKey) *Burn { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() + return inst +} + +func (inst *Burn) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The account's owner/delegate. +func (inst *Burn) SetOwnerAccount(owner ag_solanago.PublicKey) *Burn { + inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) + return inst +} + +func (inst *Burn) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *Burn) SetSignersAccount(signers ag_solanago.PublicKey) *Burn { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *Burn) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst Burn) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_Burn, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Burn) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Burn) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Amount == nil { + return errors.New("Amount parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Source is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *Burn) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Burn")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj Burn) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + return nil +} +func (obj *Burn) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + return nil +} + +// NewBurnInstruction declares a new Burn instruction with the provided parameters and accounts. +func NewBurnInstruction( + // Parameters: + amount uint64, + // Accounts: + source ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *Burn { + return NewBurnInstructionBuilder(). + SetAmount(amount). + SetSourceAccount(source). + SetMintAccount(mint). + SetOwnerAccount(owner). + SetSignersAccount(signers) +} diff --git a/programs/token/BurnChecked.go b/programs/token/BurnChecked.go new file mode 100644 index 00000000..e17829b0 --- /dev/null +++ b/programs/token/BurnChecked.go @@ -0,0 +1,216 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Burns tokens by removing them from an account. `BurnChecked` does not +// support accounts associated with the native mint, use `CloseAccount` +// instead. +// +// This instruction differs from Burn in that the decimals value is checked +// by the caller. This may be useful when creating transactions offline or +// within a hardware wallet. +type BurnChecked struct { + // The amount of tokens to burn. + Amount *uint64 + + // Expected number of base 10 digits to the right of the decimal place. + Decimals *uint8 + + // [0] = [WRITE] source + // ··········· The account to burn from. + // + // [1] = [WRITE] mint + // ··········· The token mint. + // + // [2] = [] owner + // ··········· The account's owner/delegate. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewBurnCheckedInstructionBuilder creates a new `BurnChecked` instruction builder. +func NewBurnCheckedInstructionBuilder() *BurnChecked { + nd := &BurnChecked{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The amount of tokens to burn. +func (inst *BurnChecked) SetAmount(amount uint64) *BurnChecked { + inst.Amount = &amount + return inst +} + +// Expected number of base 10 digits to the right of the decimal place. +func (inst *BurnChecked) SetDecimals(decimals uint8) *BurnChecked { + inst.Decimals = &decimals + return inst +} + +// The account to burn from. +func (inst *BurnChecked) SetSourceAccount(source ag_solanago.PublicKey) *BurnChecked { + inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + return inst +} + +func (inst *BurnChecked) GetSourceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The token mint. +func (inst *BurnChecked) SetMintAccount(mint ag_solanago.PublicKey) *BurnChecked { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() + return inst +} + +func (inst *BurnChecked) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The account's owner/delegate. +func (inst *BurnChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *BurnChecked { + inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) + return inst +} + +func (inst *BurnChecked) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *BurnChecked) SetSignersAccount(signers ag_solanago.PublicKey) *BurnChecked { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *BurnChecked) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst BurnChecked) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_BurnChecked, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst BurnChecked) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *BurnChecked) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Amount == nil { + return errors.New("Amount parameter is not set") + } + if inst.Decimals == nil { + return errors.New("Decimals parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Source is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *BurnChecked) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("BurnChecked")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj BurnChecked) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `Decimals` param: + err = encoder.Encode(obj.Decimals) + if err != nil { + return err + } + return nil +} +func (obj *BurnChecked) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `Decimals`: + err = decoder.Decode(&obj.Decimals) + if err != nil { + return err + } + return nil +} + +// NewBurnCheckedInstruction declares a new BurnChecked instruction with the provided parameters and accounts. +func NewBurnCheckedInstruction( + // Parameters: + amount uint64, + decimals uint8, + // Accounts: + source ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *BurnChecked { + return NewBurnCheckedInstructionBuilder(). + SetAmount(amount). + SetDecimals(decimals). + SetSourceAccount(source). + SetMintAccount(mint). + SetOwnerAccount(owner). + SetSignersAccount(signers) +} diff --git a/programs/token/BurnChecked_test.go b/programs/token/BurnChecked_test.go new file mode 100644 index 00000000..9b80eea0 --- /dev/null +++ b/programs/token/BurnChecked_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_BurnChecked(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("BurnChecked"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(BurnChecked) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(BurnChecked) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/Burn_test.go b/programs/token/Burn_test.go new file mode 100644 index 00000000..14aaba03 --- /dev/null +++ b/programs/token/Burn_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Burn(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Burn"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Burn) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(Burn) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/CloseAccount.go b/programs/token/CloseAccount.go new file mode 100644 index 00000000..c5b34086 --- /dev/null +++ b/programs/token/CloseAccount.go @@ -0,0 +1,155 @@ +package token + +import ( + "encoding/binary" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Close an account by transferring all its SOL to the destination account. +// Non-native accounts may only be closed if its token amount is zero. +type CloseAccount struct { + + // [0] = [WRITE] account + // ··········· The account to close. + // + // [1] = [WRITE] destination + // ··········· The destination account. + // + // [2] = [] owner + // ··········· The account's owner. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewCloseAccountInstructionBuilder creates a new `CloseAccount` instruction builder. +func NewCloseAccountInstructionBuilder() *CloseAccount { + nd := &CloseAccount{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The account to close. +func (inst *CloseAccount) SetAccount(account ag_solanago.PublicKey) *CloseAccount { + inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + return inst +} + +func (inst *CloseAccount) GetAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The destination account. +func (inst *CloseAccount) SetDestinationAccount(destination ag_solanago.PublicKey) *CloseAccount { + inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() + return inst +} + +func (inst *CloseAccount) GetDestinationAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The account's owner. +func (inst *CloseAccount) SetOwnerAccount(owner ag_solanago.PublicKey) *CloseAccount { + inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) + return inst +} + +func (inst *CloseAccount) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *CloseAccount) SetSignersAccount(signers ag_solanago.PublicKey) *CloseAccount { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *CloseAccount) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst CloseAccount) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_CloseAccount, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst CloseAccount) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *CloseAccount) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Account is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Destination is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *CloseAccount) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("CloseAccount")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj CloseAccount) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *CloseAccount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewCloseAccountInstruction declares a new CloseAccount instruction with the provided parameters and accounts. +func NewCloseAccountInstruction( + // Accounts: + account ag_solanago.PublicKey, + destination ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *CloseAccount { + return NewCloseAccountInstructionBuilder(). + SetAccount(account). + SetDestinationAccount(destination). + SetOwnerAccount(owner). + SetSignersAccount(signers) +} diff --git a/programs/token/CloseAccount_test.go b/programs/token/CloseAccount_test.go new file mode 100644 index 00000000..164058e9 --- /dev/null +++ b/programs/token/CloseAccount_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_CloseAccount(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("CloseAccount"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(CloseAccount) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(CloseAccount) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/FreezeAccount.go b/programs/token/FreezeAccount.go new file mode 100644 index 00000000..982cbe9b --- /dev/null +++ b/programs/token/FreezeAccount.go @@ -0,0 +1,154 @@ +package token + +import ( + "encoding/binary" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Freeze an Initialized account using the Mint's freeze_authority (if set). +type FreezeAccount struct { + + // [0] = [WRITE] account + // ··········· The account to freeze. + // + // [1] = [] mint + // ··········· The token mint. + // + // [2] = [] authority + // ··········· The mint freeze authority. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewFreezeAccountInstructionBuilder creates a new `FreezeAccount` instruction builder. +func NewFreezeAccountInstructionBuilder() *FreezeAccount { + nd := &FreezeAccount{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The account to freeze. +func (inst *FreezeAccount) SetAccount(account ag_solanago.PublicKey) *FreezeAccount { + inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + return inst +} + +func (inst *FreezeAccount) GetAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The token mint. +func (inst *FreezeAccount) SetMintAccount(mint ag_solanago.PublicKey) *FreezeAccount { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + return inst +} + +func (inst *FreezeAccount) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The mint freeze authority. +func (inst *FreezeAccount) SetAuthorityAccount(authority ag_solanago.PublicKey) *FreezeAccount { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) + return inst +} + +func (inst *FreezeAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *FreezeAccount) SetSignersAccount(signers ag_solanago.PublicKey) *FreezeAccount { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *FreezeAccount) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst FreezeAccount) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_FreezeAccount, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst FreezeAccount) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *FreezeAccount) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Account is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *FreezeAccount) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("FreezeAccount")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj FreezeAccount) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *FreezeAccount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewFreezeAccountInstruction declares a new FreezeAccount instruction with the provided parameters and accounts. +func NewFreezeAccountInstruction( + // Accounts: + account ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *FreezeAccount { + return NewFreezeAccountInstructionBuilder(). + SetAccount(account). + SetMintAccount(mint). + SetAuthorityAccount(authority). + SetSignersAccount(signers) +} diff --git a/programs/token/FreezeAccount_test.go b/programs/token/FreezeAccount_test.go new file mode 100644 index 00000000..d611f82e --- /dev/null +++ b/programs/token/FreezeAccount_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_FreezeAccount(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("FreezeAccount"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(FreezeAccount) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(FreezeAccount) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/InitializeAccount.go b/programs/token/InitializeAccount.go new file mode 100644 index 00000000..b02e06e9 --- /dev/null +++ b/programs/token/InitializeAccount.go @@ -0,0 +1,165 @@ +package token + +import ( + "encoding/binary" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Initializes a new account to hold tokens. If this account is associated +// with the native mint then the token balance of the initialized account +// will be equal to the amount of SOL in the account. If this account is +// associated with another mint, that mint must be initialized before this +// command can succeed. +// +// The `InitializeAccount` instruction requires no signers and MUST be +// included within the same Transaction as the system program's +// `CreateAccount` instruction that creates the account being initialized. +// Otherwise another party can acquire ownership of the uninitialized +// account. +type InitializeAccount struct { + + // [0] = [WRITE] account + // ··········· The account to initialize. + // + // [1] = [] mint + // ··········· The mint this account will be associated with. + // + // [2] = [] owner + // ··········· The new account's owner/multisignature. + // + // [3] = [] $(SysVarRentPubkey) + // ··········· Rent sysvar. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeAccountInstructionBuilder creates a new `InitializeAccount` instruction builder. +func NewInitializeAccountInstructionBuilder() *InitializeAccount { + nd := &InitializeAccount{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + nd.AccountMetaSlice[3] = ag_solanago.Meta(ag_solanago.SysVarRentPubkey) + return nd +} + +// The account to initialize. +func (inst *InitializeAccount) SetAccount(account ag_solanago.PublicKey) *InitializeAccount { + inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + return inst +} + +func (inst *InitializeAccount) GetAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The mint this account will be associated with. +func (inst *InitializeAccount) SetMintAccount(mint ag_solanago.PublicKey) *InitializeAccount { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + return inst +} + +func (inst *InitializeAccount) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The new account's owner/multisignature. +func (inst *InitializeAccount) SetOwnerAccount(owner ag_solanago.PublicKey) *InitializeAccount { + inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) + return inst +} + +func (inst *InitializeAccount) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// Rent sysvar. +func (inst *InitializeAccount) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeAccount { + inst.AccountMetaSlice[3] = ag_solanago.Meta(SysVarRentPubkey) + return inst +} + +func (inst *InitializeAccount) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst InitializeAccount) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeAccount, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst InitializeAccount) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *InitializeAccount) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Account is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.SysVarRentPubkey is not set") + } + } + return nil +} + +func (inst *InitializeAccount) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("InitializeAccount")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj InitializeAccount) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *InitializeAccount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewInitializeAccountInstruction declares a new InitializeAccount instruction with the provided parameters and accounts. +func NewInitializeAccountInstruction( + // Accounts: + account ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + SysVarRentPubkey ag_solanago.PublicKey) *InitializeAccount { + return NewInitializeAccountInstructionBuilder(). + SetAccount(account). + SetMintAccount(mint). + SetOwnerAccount(owner). + SetSysVarRentPubkeyAccount(SysVarRentPubkey) +} diff --git a/programs/token/InitializeAccount2.go b/programs/token/InitializeAccount2.go new file mode 100644 index 00000000..57fd0ab7 --- /dev/null +++ b/programs/token/InitializeAccount2.go @@ -0,0 +1,170 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Like InitializeAccount, but the owner pubkey is passed via instruction data +// rather than the accounts list. This variant may be preferable when using +// Cross Program Invocation from an instruction that does not need the owner's +// `AccountInfo` otherwise. +type InitializeAccount2 struct { + // The new account's owner/multisignature. + Owner *ag_solanago.PublicKey + + // [0] = [WRITE] account + // ··········· The account to initialize. + // + // [1] = [] mint + // ··········· The mint this account will be associated with. + // + // [2] = [] $(SysVarRentPubkey) + // ··········· Rent sysvar. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeAccount2InstructionBuilder creates a new `InitializeAccount2` instruction builder. +func NewInitializeAccount2InstructionBuilder() *InitializeAccount2 { + nd := &InitializeAccount2{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + nd.AccountMetaSlice[2] = ag_solanago.Meta(ag_solanago.SysVarRentPubkey) + return nd +} + +// The new account's owner/multisignature. +func (inst *InitializeAccount2) SetOwner(owner ag_solanago.PublicKey) *InitializeAccount2 { + inst.Owner = &owner + return inst +} + +// The account to initialize. +func (inst *InitializeAccount2) SetAccount(account ag_solanago.PublicKey) *InitializeAccount2 { + inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + return inst +} + +func (inst *InitializeAccount2) GetAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The mint this account will be associated with. +func (inst *InitializeAccount2) SetMintAccount(mint ag_solanago.PublicKey) *InitializeAccount2 { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + return inst +} + +func (inst *InitializeAccount2) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// Rent sysvar. +func (inst *InitializeAccount2) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeAccount2 { + inst.AccountMetaSlice[2] = ag_solanago.Meta(SysVarRentPubkey) + return inst +} + +func (inst *InitializeAccount2) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst InitializeAccount2) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeAccount2, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst InitializeAccount2) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *InitializeAccount2) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Owner == nil { + return errors.New("Owner parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Account is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.SysVarRentPubkey is not set") + } + } + return nil +} + +func (inst *InitializeAccount2) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("InitializeAccount2")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Owner", *inst.Owner)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj InitializeAccount2) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Owner` param: + err = encoder.Encode(obj.Owner) + if err != nil { + return err + } + return nil +} +func (obj *InitializeAccount2) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Owner`: + err = decoder.Decode(&obj.Owner) + if err != nil { + return err + } + return nil +} + +// NewInitializeAccount2Instruction declares a new InitializeAccount2 instruction with the provided parameters and accounts. +func NewInitializeAccount2Instruction( + // Parameters: + owner ag_solanago.PublicKey, + // Accounts: + account ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + SysVarRentPubkey ag_solanago.PublicKey) *InitializeAccount2 { + return NewInitializeAccount2InstructionBuilder(). + SetOwner(owner). + SetAccount(account). + SetMintAccount(mint). + SetSysVarRentPubkeyAccount(SysVarRentPubkey) +} diff --git a/programs/token/InitializeAccount2_test.go b/programs/token/InitializeAccount2_test.go new file mode 100644 index 00000000..40934a73 --- /dev/null +++ b/programs/token/InitializeAccount2_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_InitializeAccount2(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("InitializeAccount2"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(InitializeAccount2) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(InitializeAccount2) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/InitializeAccount3.go b/programs/token/InitializeAccount3.go new file mode 100644 index 00000000..96ab3af6 --- /dev/null +++ b/programs/token/InitializeAccount3.go @@ -0,0 +1,147 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Like InitializeAccount2, but does not require the Rent sysvar to be provided. +type InitializeAccount3 struct { + // The new account's owner/multisignature. + Owner *ag_solanago.PublicKey + + // [0] = [WRITE] account + // ··········· The account to initialize. + // + // [1] = [] mint + // ··········· The mint this account will be associated with. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeAccount3InstructionBuilder creates a new `InitializeAccount3` instruction builder. +func NewInitializeAccount3InstructionBuilder() *InitializeAccount3 { + nd := &InitializeAccount3{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// The new account's owner/multisignature. +func (inst *InitializeAccount3) SetOwner(owner ag_solanago.PublicKey) *InitializeAccount3 { + inst.Owner = &owner + return inst +} + +// The account to initialize. +func (inst *InitializeAccount3) SetAccount(account ag_solanago.PublicKey) *InitializeAccount3 { + inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + return inst +} + +func (inst *InitializeAccount3) GetAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The mint this account will be associated with. +func (inst *InitializeAccount3) SetMintAccount(mint ag_solanago.PublicKey) *InitializeAccount3 { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + return inst +} + +func (inst *InitializeAccount3) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst InitializeAccount3) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeAccount3, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst InitializeAccount3) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *InitializeAccount3) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Owner == nil { + return errors.New("Owner parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Account is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + } + return nil +} + +func (inst *InitializeAccount3) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("InitializeAccount3")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Owner", *inst.Owner)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj InitializeAccount3) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Owner` param: + err = encoder.Encode(obj.Owner) + if err != nil { + return err + } + return nil +} +func (obj *InitializeAccount3) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Owner`: + err = decoder.Decode(&obj.Owner) + if err != nil { + return err + } + return nil +} + +// NewInitializeAccount3Instruction declares a new InitializeAccount3 instruction with the provided parameters and accounts. +func NewInitializeAccount3Instruction( + // Parameters: + owner ag_solanago.PublicKey, + // Accounts: + account ag_solanago.PublicKey, + mint ag_solanago.PublicKey) *InitializeAccount3 { + return NewInitializeAccount3InstructionBuilder(). + SetOwner(owner). + SetAccount(account). + SetMintAccount(mint) +} diff --git a/programs/token/InitializeAccount3_test.go b/programs/token/InitializeAccount3_test.go new file mode 100644 index 00000000..2425a09b --- /dev/null +++ b/programs/token/InitializeAccount3_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_InitializeAccount3(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("InitializeAccount3"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(InitializeAccount3) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(InitializeAccount3) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/InitializeAccount_test.go b/programs/token/InitializeAccount_test.go new file mode 100644 index 00000000..3da3ac27 --- /dev/null +++ b/programs/token/InitializeAccount_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_InitializeAccount(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("InitializeAccount"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(InitializeAccount) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(InitializeAccount) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/InitializeMint.go b/programs/token/InitializeMint.go new file mode 100644 index 00000000..d9033811 --- /dev/null +++ b/programs/token/InitializeMint.go @@ -0,0 +1,223 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Initializes a new mint and optionally deposits all the newly minted +// tokens in an account. +// +// The `InitializeMint` instruction requires no signers and MUST be +// included within the same Transaction as the system program's +// `CreateAccount` instruction that creates the account being initialized. +// Otherwise another party can acquire ownership of the uninitialized +// account. +type InitializeMint struct { + // Number of base 10 digits to the right of the decimal place. + Decimals *uint8 + + // The authority/multisignature to mint tokens. + MintAuthority *ag_solanago.PublicKey + + // The freeze authority/multisignature of the mint. + FreezeAuthority *ag_solanago.PublicKey `bin:"optional"` + + // [0] = [WRITE] mint + // ··········· The mint to initialize. + // + // [1] = [] $(SysVarRentPubkey) + // ··········· Rent sysvar. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeMintInstructionBuilder creates a new `InitializeMint` instruction builder. +func NewInitializeMintInstructionBuilder() *InitializeMint { + nd := &InitializeMint{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + nd.AccountMetaSlice[1] = ag_solanago.Meta(ag_solanago.SysVarRentPubkey) + return nd +} + +// Number of base 10 digits to the right of the decimal place. +func (inst *InitializeMint) SetDecimals(decimals uint8) *InitializeMint { + inst.Decimals = &decimals + return inst +} + +// The authority/multisignature to mint tokens. +func (inst *InitializeMint) SetMintAuthority(mint_authority ag_solanago.PublicKey) *InitializeMint { + inst.MintAuthority = &mint_authority + return inst +} + +// The freeze authority/multisignature of the mint. +func (inst *InitializeMint) SetFreezeAuthority(freeze_authority ag_solanago.PublicKey) *InitializeMint { + inst.FreezeAuthority = &freeze_authority + return inst +} + +// The mint to initialize. +func (inst *InitializeMint) SetMintAccount(mint ag_solanago.PublicKey) *InitializeMint { + inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() + return inst +} + +func (inst *InitializeMint) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// Rent sysvar. +func (inst *InitializeMint) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeMint { + inst.AccountMetaSlice[1] = ag_solanago.Meta(SysVarRentPubkey) + return inst +} + +func (inst *InitializeMint) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst InitializeMint) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeMint, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst InitializeMint) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *InitializeMint) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Decimals == nil { + return errors.New("Decimals parameter is not set") + } + if inst.MintAuthority == nil { + return errors.New("MintAuthority parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.SysVarRentPubkey is not set") + } + } + return nil +} + +func (inst *InitializeMint) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("InitializeMint")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) + paramsBranch.Child(ag_format.Param("MintAuthority", *inst.MintAuthority)) + paramsBranch.Child(ag_format.Param("FreezeAuthority (OPTIONAL)", inst.FreezeAuthority)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj InitializeMint) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Decimals` param: + err = encoder.Encode(obj.Decimals) + if err != nil { + return err + } + // Serialize `MintAuthority` param: + err = encoder.Encode(obj.MintAuthority) + if err != nil { + return err + } + // Serialize `FreezeAuthority` param (optional): + { + if obj.FreezeAuthority == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.FreezeAuthority) + if err != nil { + return err + } + } + } + return nil +} +func (obj *InitializeMint) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Decimals`: + err = decoder.Decode(&obj.Decimals) + if err != nil { + return err + } + // Deserialize `MintAuthority`: + err = decoder.Decode(&obj.MintAuthority) + if err != nil { + return err + } + // Deserialize `FreezeAuthority` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.FreezeAuthority) + if err != nil { + return err + } + } + } + return nil +} + +// NewInitializeMintInstruction declares a new InitializeMint instruction with the provided parameters and accounts. +func NewInitializeMintInstruction( + // Parameters: + decimals uint8, + mint_authority ag_solanago.PublicKey, + freeze_authority ag_solanago.PublicKey, + // Accounts: + mint ag_solanago.PublicKey, + SysVarRentPubkey ag_solanago.PublicKey) *InitializeMint { + return NewInitializeMintInstructionBuilder(). + SetDecimals(decimals). + SetMintAuthority(mint_authority). + SetFreezeAuthority(freeze_authority). + SetMintAccount(mint). + SetSysVarRentPubkeyAccount(SysVarRentPubkey) +} diff --git a/programs/token/InitializeMint2.go b/programs/token/InitializeMint2.go new file mode 100644 index 00000000..ca28ba20 --- /dev/null +++ b/programs/token/InitializeMint2.go @@ -0,0 +1,196 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Like InitializeMint, but does not require the Rent sysvar to be provided. +type InitializeMint2 struct { + // Number of base 10 digits to the right of the decimal place. + Decimals *uint8 + + // The authority/multisignature to mint tokens. + MintAuthority *ag_solanago.PublicKey + + // The freeze authority/multisignature of the mint. + FreezeAuthority *ag_solanago.PublicKey `bin:"optional"` + + // [0] = [WRITE] mint + // ··········· The mint to initialize. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeMint2InstructionBuilder creates a new `InitializeMint2` instruction builder. +func NewInitializeMint2InstructionBuilder() *InitializeMint2 { + nd := &InitializeMint2{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 1), + } + return nd +} + +// Number of base 10 digits to the right of the decimal place. +func (inst *InitializeMint2) SetDecimals(decimals uint8) *InitializeMint2 { + inst.Decimals = &decimals + return inst +} + +// The authority/multisignature to mint tokens. +func (inst *InitializeMint2) SetMintAuthority(mint_authority ag_solanago.PublicKey) *InitializeMint2 { + inst.MintAuthority = &mint_authority + return inst +} + +// The freeze authority/multisignature of the mint. +func (inst *InitializeMint2) SetFreezeAuthority(freeze_authority ag_solanago.PublicKey) *InitializeMint2 { + inst.FreezeAuthority = &freeze_authority + return inst +} + +// The mint to initialize. +func (inst *InitializeMint2) SetMintAccount(mint ag_solanago.PublicKey) *InitializeMint2 { + inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() + return inst +} + +func (inst *InitializeMint2) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +func (inst InitializeMint2) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeMint2, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst InitializeMint2) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *InitializeMint2) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Decimals == nil { + return errors.New("Decimals parameter is not set") + } + if inst.MintAuthority == nil { + return errors.New("MintAuthority parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + } + return nil +} + +func (inst *InitializeMint2) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("InitializeMint2")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) + paramsBranch.Child(ag_format.Param("MintAuthority", *inst.MintAuthority)) + paramsBranch.Child(ag_format.Param("FreezeAuthority (OPTIONAL)", inst.FreezeAuthority)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) + }) + }) + }) +} + +func (obj InitializeMint2) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Decimals` param: + err = encoder.Encode(obj.Decimals) + if err != nil { + return err + } + // Serialize `MintAuthority` param: + err = encoder.Encode(obj.MintAuthority) + if err != nil { + return err + } + // Serialize `FreezeAuthority` param (optional): + { + if obj.FreezeAuthority == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.FreezeAuthority) + if err != nil { + return err + } + } + } + return nil +} +func (obj *InitializeMint2) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Decimals`: + err = decoder.Decode(&obj.Decimals) + if err != nil { + return err + } + // Deserialize `MintAuthority`: + err = decoder.Decode(&obj.MintAuthority) + if err != nil { + return err + } + // Deserialize `FreezeAuthority` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.FreezeAuthority) + if err != nil { + return err + } + } + } + return nil +} + +// NewInitializeMint2Instruction declares a new InitializeMint2 instruction with the provided parameters and accounts. +func NewInitializeMint2Instruction( + // Parameters: + decimals uint8, + mint_authority ag_solanago.PublicKey, + freeze_authority ag_solanago.PublicKey, + // Accounts: + mint ag_solanago.PublicKey) *InitializeMint2 { + return NewInitializeMint2InstructionBuilder(). + SetDecimals(decimals). + SetMintAuthority(mint_authority). + SetFreezeAuthority(freeze_authority). + SetMintAccount(mint) +} diff --git a/programs/token/InitializeMint2_test.go b/programs/token/InitializeMint2_test.go new file mode 100644 index 00000000..67646192 --- /dev/null +++ b/programs/token/InitializeMint2_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_InitializeMint2(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("InitializeMint2"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(InitializeMint2) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(InitializeMint2) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/InitializeMint_test.go b/programs/token/InitializeMint_test.go new file mode 100644 index 00000000..cf08cef3 --- /dev/null +++ b/programs/token/InitializeMint_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_InitializeMint(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("InitializeMint"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(InitializeMint) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(InitializeMint) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/InitializeMultisig.go b/programs/token/InitializeMultisig.go new file mode 100644 index 00000000..b0ff2cda --- /dev/null +++ b/programs/token/InitializeMultisig.go @@ -0,0 +1,186 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Initializes a multisignature account with N provided signers. +// +// Multisignature accounts can used in place of any single owner/delegate +// accounts in any token instruction that require an owner/delegate to be +// present. The variant field represents the number of signers (M) +// required to validate this multisignature account. +// +// The `InitializeMultisig` instruction requires no signers and MUST be +// included within the same Transaction as the system program's +// `CreateAccount` instruction that creates the account being initialized. +// Otherwise another party can acquire ownership of the uninitialized +// account. +type InitializeMultisig struct { + // The number of signers (M) required to validate this multisignature + // account. + M *uint8 + + // [0] = [WRITE] account + // ··········· The multisignature account to initialize. + // + // [1] = [] $(SysVarRentPubkey) + // ··········· Rent sysvar. + // + // [2...] = [SIGNER] signers + // ··········· ..2+N The signer accounts, must equal to N where 1 <= N <=11 + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeMultisigInstructionBuilder creates a new `InitializeMultisig` instruction builder. +func NewInitializeMultisigInstructionBuilder() *InitializeMultisig { + nd := &InitializeMultisig{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + nd.AccountMetaSlice[1] = ag_solanago.Meta(ag_solanago.SysVarRentPubkey) + return nd +} + +// The number of signers (M) required to validate this multisignature +// account. +func (inst *InitializeMultisig) SetM(m uint8) *InitializeMultisig { + inst.M = &m + return inst +} + +// The multisignature account to initialize. +func (inst *InitializeMultisig) SetAccount(account ag_solanago.PublicKey) *InitializeMultisig { + inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + return inst +} + +func (inst *InitializeMultisig) GetAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// Rent sysvar. +func (inst *InitializeMultisig) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeMultisig { + inst.AccountMetaSlice[1] = ag_solanago.Meta(SysVarRentPubkey) + return inst +} + +func (inst *InitializeMultisig) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// ..2+N The signer accounts, must equal to N where 1 <= N <=11 +func (inst *InitializeMultisig) SetSigners(signers ...ag_solanago.PublicKey) *InitializeMultisig { + for _, signer := range signers { + inst.AccountMetaSlice = append(inst.AccountMetaSlice, ag_solanago.Meta(signer).SIGNER()) + } + return inst +} + +func (inst *InitializeMultisig) GetSigners() []*ag_solanago.AccountMeta { + if len(inst.AccountMetaSlice) == 2 { + return nil + } + return inst.AccountMetaSlice[2:] +} + +func (inst InitializeMultisig) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeMultisig, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst InitializeMultisig) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *InitializeMultisig) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.M == nil { + return errors.New("M parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Account is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.SysVarRentPubkey is not set") + } + if len(inst.AccountMetaSlice) == 2 { + return fmt.Errorf("Signers are not set") + } + } + return nil +} + +func (inst *InitializeMultisig) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("InitializeMultisig")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("M", *inst.M)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj InitializeMultisig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `M` param: + err = encoder.Encode(obj.M) + if err != nil { + return err + } + return nil +} +func (obj *InitializeMultisig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `M`: + err = decoder.Decode(&obj.M) + if err != nil { + return err + } + return nil +} + +// NewInitializeMultisigInstruction declares a new InitializeMultisig instruction with the provided parameters and accounts. +func NewInitializeMultisigInstruction( + // Parameters: + m uint8, + // Accounts: + account ag_solanago.PublicKey, + SysVarRentPubkey ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *InitializeMultisig { + return NewInitializeMultisigInstructionBuilder(). + SetM(m). + SetAccount(account). + SetSysVarRentPubkeyAccount(SysVarRentPubkey). + SetSignersAccount(signers) +} diff --git a/programs/token/InitializeMultisig2.go b/programs/token/InitializeMultisig2.go new file mode 100644 index 00000000..469ad8ec --- /dev/null +++ b/programs/token/InitializeMultisig2.go @@ -0,0 +1,147 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Like InitializeMultisig, but does not require the Rent sysvar to be provided. +type InitializeMultisig2 struct { + // The number of signers (M) required to validate this multisignature account. + M *uint8 + + // [0] = [WRITE] account + // ··········· The multisignature account to initialize. + // + // [1] = [SIGNER] signers + // ··········· The signer accounts, must equal to N where 1 <= N <= 11. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeMultisig2InstructionBuilder creates a new `InitializeMultisig2` instruction builder. +func NewInitializeMultisig2InstructionBuilder() *InitializeMultisig2 { + nd := &InitializeMultisig2{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// The number of signers (M) required to validate this multisignature account. +func (inst *InitializeMultisig2) SetM(m uint8) *InitializeMultisig2 { + inst.M = &m + return inst +} + +// The multisignature account to initialize. +func (inst *InitializeMultisig2) SetAccount(account ag_solanago.PublicKey) *InitializeMultisig2 { + inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + return inst +} + +func (inst *InitializeMultisig2) GetAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The signer accounts, must equal to N where 1 <= N <= 11. +func (inst *InitializeMultisig2) SetSignersAccount(signers ag_solanago.PublicKey) *InitializeMultisig2 { + inst.AccountMetaSlice[1] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *InitializeMultisig2) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst InitializeMultisig2) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeMultisig2, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst InitializeMultisig2) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *InitializeMultisig2) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.M == nil { + return errors.New("M parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Account is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *InitializeMultisig2) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("InitializeMultisig2")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("M", *inst.M)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj InitializeMultisig2) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `M` param: + err = encoder.Encode(obj.M) + if err != nil { + return err + } + return nil +} +func (obj *InitializeMultisig2) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `M`: + err = decoder.Decode(&obj.M) + if err != nil { + return err + } + return nil +} + +// NewInitializeMultisig2Instruction declares a new InitializeMultisig2 instruction with the provided parameters and accounts. +func NewInitializeMultisig2Instruction( + // Parameters: + m uint8, + // Accounts: + account ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *InitializeMultisig2 { + return NewInitializeMultisig2InstructionBuilder(). + SetM(m). + SetAccount(account). + SetSignersAccount(signers) +} diff --git a/programs/token/InitializeMultisig2_test.go b/programs/token/InitializeMultisig2_test.go new file mode 100644 index 00000000..a0280612 --- /dev/null +++ b/programs/token/InitializeMultisig2_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_InitializeMultisig2(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("InitializeMultisig2"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(InitializeMultisig2) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(InitializeMultisig2) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/InitializeMultisig_test.go b/programs/token/InitializeMultisig_test.go new file mode 100644 index 00000000..90ae0184 --- /dev/null +++ b/programs/token/InitializeMultisig_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_InitializeMultisig(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("InitializeMultisig"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(InitializeMultisig) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(InitializeMultisig) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/MintTo.go b/programs/token/MintTo.go new file mode 100644 index 00000000..01156ef0 --- /dev/null +++ b/programs/token/MintTo.go @@ -0,0 +1,186 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Mints new tokens to an account. The native mint does not support +// minting. +type MintTo struct { + // The amount of new tokens to mint. + Amount *uint64 + + // [0] = [WRITE] mint + // ··········· The mint. + // + // [1] = [WRITE] destination + // ··········· The account to mint tokens to. + // + // [2] = [] authority + // ··········· The mint's minting authority. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewMintToInstructionBuilder creates a new `MintTo` instruction builder. +func NewMintToInstructionBuilder() *MintTo { + nd := &MintTo{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The amount of new tokens to mint. +func (inst *MintTo) SetAmount(amount uint64) *MintTo { + inst.Amount = &amount + return inst +} + +// The mint. +func (inst *MintTo) SetMintAccount(mint ag_solanago.PublicKey) *MintTo { + inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() + return inst +} + +func (inst *MintTo) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The account to mint tokens to. +func (inst *MintTo) SetDestinationAccount(destination ag_solanago.PublicKey) *MintTo { + inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() + return inst +} + +func (inst *MintTo) GetDestinationAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The mint's minting authority. +func (inst *MintTo) SetAuthorityAccount(authority ag_solanago.PublicKey) *MintTo { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) + return inst +} + +func (inst *MintTo) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *MintTo) SetSignersAccount(signers ag_solanago.PublicKey) *MintTo { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *MintTo) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst MintTo) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_MintTo, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst MintTo) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *MintTo) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Amount == nil { + return errors.New("Amount parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Destination is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *MintTo) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("MintTo")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj MintTo) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + return nil +} +func (obj *MintTo) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + return nil +} + +// NewMintToInstruction declares a new MintTo instruction with the provided parameters and accounts. +func NewMintToInstruction( + // Parameters: + amount uint64, + // Accounts: + mint ag_solanago.PublicKey, + destination ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *MintTo { + return NewMintToInstructionBuilder(). + SetAmount(amount). + SetMintAccount(mint). + SetDestinationAccount(destination). + SetAuthorityAccount(authority). + SetSignersAccount(signers) +} diff --git a/programs/token/MintToChecked.go b/programs/token/MintToChecked.go new file mode 100644 index 00000000..e7d4b580 --- /dev/null +++ b/programs/token/MintToChecked.go @@ -0,0 +1,214 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Mints new tokens to an account. The native mint does not support minting. +// +// This instruction differs from MintTo in that the decimals value is +// checked by the caller. This may be useful when creating transactions +// offline or within a hardware wallet. +type MintToChecked struct { + // The amount of new tokens to mint. + Amount *uint64 + + // Expected number of base 10 digits to the right of the decimal place. + Decimals *uint8 + + // [0] = [WRITE] mint + // ··········· The mint. + // + // [1] = [WRITE] destination + // ··········· The account to mint tokens to. + // + // [2] = [] authority + // ··········· The mint's minting authority. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewMintToCheckedInstructionBuilder creates a new `MintToChecked` instruction builder. +func NewMintToCheckedInstructionBuilder() *MintToChecked { + nd := &MintToChecked{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The amount of new tokens to mint. +func (inst *MintToChecked) SetAmount(amount uint64) *MintToChecked { + inst.Amount = &amount + return inst +} + +// Expected number of base 10 digits to the right of the decimal place. +func (inst *MintToChecked) SetDecimals(decimals uint8) *MintToChecked { + inst.Decimals = &decimals + return inst +} + +// The mint. +func (inst *MintToChecked) SetMintAccount(mint ag_solanago.PublicKey) *MintToChecked { + inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() + return inst +} + +func (inst *MintToChecked) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The account to mint tokens to. +func (inst *MintToChecked) SetDestinationAccount(destination ag_solanago.PublicKey) *MintToChecked { + inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() + return inst +} + +func (inst *MintToChecked) GetDestinationAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The mint's minting authority. +func (inst *MintToChecked) SetAuthorityAccount(authority ag_solanago.PublicKey) *MintToChecked { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) + return inst +} + +func (inst *MintToChecked) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *MintToChecked) SetSignersAccount(signers ag_solanago.PublicKey) *MintToChecked { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *MintToChecked) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst MintToChecked) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_MintToChecked, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst MintToChecked) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *MintToChecked) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Amount == nil { + return errors.New("Amount parameter is not set") + } + if inst.Decimals == nil { + return errors.New("Decimals parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Destination is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *MintToChecked) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("MintToChecked")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj MintToChecked) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `Decimals` param: + err = encoder.Encode(obj.Decimals) + if err != nil { + return err + } + return nil +} +func (obj *MintToChecked) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `Decimals`: + err = decoder.Decode(&obj.Decimals) + if err != nil { + return err + } + return nil +} + +// NewMintToCheckedInstruction declares a new MintToChecked instruction with the provided parameters and accounts. +func NewMintToCheckedInstruction( + // Parameters: + amount uint64, + decimals uint8, + // Accounts: + mint ag_solanago.PublicKey, + destination ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *MintToChecked { + return NewMintToCheckedInstructionBuilder(). + SetAmount(amount). + SetDecimals(decimals). + SetMintAccount(mint). + SetDestinationAccount(destination). + SetAuthorityAccount(authority). + SetSignersAccount(signers) +} diff --git a/programs/token/MintToChecked_test.go b/programs/token/MintToChecked_test.go new file mode 100644 index 00000000..ceee3ec3 --- /dev/null +++ b/programs/token/MintToChecked_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_MintToChecked(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("MintToChecked"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(MintToChecked) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(MintToChecked) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/MintTo_test.go b/programs/token/MintTo_test.go new file mode 100644 index 00000000..e63e2e23 --- /dev/null +++ b/programs/token/MintTo_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_MintTo(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("MintTo"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(MintTo) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(MintTo) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/Revoke.go b/programs/token/Revoke.go new file mode 100644 index 00000000..13a33c28 --- /dev/null +++ b/programs/token/Revoke.go @@ -0,0 +1,135 @@ +package token + +import ( + "encoding/binary" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Revokes the delegate's authority. +type Revoke struct { + + // [0] = [WRITE] source + // ··········· The source account. + // + // [1] = [] owner + // ··········· The source account's owner. + // + // [2] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewRevokeInstructionBuilder creates a new `Revoke` instruction builder. +func NewRevokeInstructionBuilder() *Revoke { + nd := &Revoke{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// The source account. +func (inst *Revoke) SetSourceAccount(source ag_solanago.PublicKey) *Revoke { + inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + return inst +} + +func (inst *Revoke) GetSourceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The source account's owner. +func (inst *Revoke) SetOwnerAccount(owner ag_solanago.PublicKey) *Revoke { + inst.AccountMetaSlice[1] = ag_solanago.Meta(owner) + return inst +} + +func (inst *Revoke) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// M signer accounts. +func (inst *Revoke) SetSignersAccount(signers ag_solanago.PublicKey) *Revoke { + inst.AccountMetaSlice[2] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *Revoke) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst Revoke) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_Revoke, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Revoke) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Revoke) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Source is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *Revoke) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Revoke")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj Revoke) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *Revoke) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewRevokeInstruction declares a new Revoke instruction with the provided parameters and accounts. +func NewRevokeInstruction( + // Accounts: + source ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *Revoke { + return NewRevokeInstructionBuilder(). + SetSourceAccount(source). + SetOwnerAccount(owner). + SetSignersAccount(signers) +} diff --git a/programs/token/Revoke_test.go b/programs/token/Revoke_test.go new file mode 100644 index 00000000..99cc150f --- /dev/null +++ b/programs/token/Revoke_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Revoke(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Revoke"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Revoke) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(Revoke) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/SetAuthority.go b/programs/token/SetAuthority.go new file mode 100644 index 00000000..939fc8cb --- /dev/null +++ b/programs/token/SetAuthority.go @@ -0,0 +1,209 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Sets a new authority of a mint or account. +type SetAuthority struct { + // The type of authority to update. + AuthorityType *AuthorityType + + // The new authority. + NewAuthority *ag_solanago.PublicKey `bin:"optional"` + + // [0] = [WRITE] subject + // ··········· The mint or account to change the authority of. + // + // [1] = [] authority + // ··········· The current authority of the mint or account. + // + // [2] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewSetAuthorityInstructionBuilder creates a new `SetAuthority` instruction builder. +func NewSetAuthorityInstructionBuilder() *SetAuthority { + nd := &SetAuthority{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// The type of authority to update. +func (inst *SetAuthority) SetAuthorityType(authority_type AuthorityType) *SetAuthority { + inst.AuthorityType = &authority_type + return inst +} + +// The new authority. +func (inst *SetAuthority) SetNewAuthority(new_authority ag_solanago.PublicKey) *SetAuthority { + inst.NewAuthority = &new_authority + return inst +} + +// The mint or account to change the authority of. +func (inst *SetAuthority) SetSubjectAccount(subject ag_solanago.PublicKey) *SetAuthority { + inst.AccountMetaSlice[0] = ag_solanago.Meta(subject).WRITE() + return inst +} + +func (inst *SetAuthority) GetSubjectAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The current authority of the mint or account. +func (inst *SetAuthority) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetAuthority { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority) + return inst +} + +func (inst *SetAuthority) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// M signer accounts. +func (inst *SetAuthority) SetSignersAccount(signers ag_solanago.PublicKey) *SetAuthority { + inst.AccountMetaSlice[2] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *SetAuthority) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst SetAuthority) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_SetAuthority, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst SetAuthority) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *SetAuthority) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.AuthorityType == nil { + return errors.New("AuthorityType parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Subject is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *SetAuthority) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("SetAuthority")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("AuthorityType", *inst.AuthorityType)) + paramsBranch.Child(ag_format.Param("NewAuthority (OPTIONAL)", inst.NewAuthority)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("subject", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj SetAuthority) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `AuthorityType` param: + err = encoder.Encode(obj.AuthorityType) + if err != nil { + return err + } + // Serialize `NewAuthority` param (optional): + { + if obj.NewAuthority == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.NewAuthority) + if err != nil { + return err + } + } + } + return nil +} +func (obj *SetAuthority) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `AuthorityType`: + err = decoder.Decode(&obj.AuthorityType) + if err != nil { + return err + } + // Deserialize `NewAuthority` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.NewAuthority) + if err != nil { + return err + } + } + } + return nil +} + +// NewSetAuthorityInstruction declares a new SetAuthority instruction with the provided parameters and accounts. +func NewSetAuthorityInstruction( + // Parameters: + authority_type AuthorityType, + new_authority ag_solanago.PublicKey, + // Accounts: + subject ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *SetAuthority { + return NewSetAuthorityInstructionBuilder(). + SetAuthorityType(authority_type). + SetNewAuthority(new_authority). + SetSubjectAccount(subject). + SetAuthorityAccount(authority). + SetSignersAccount(signers) +} diff --git a/programs/token/SetAuthority_test.go b/programs/token/SetAuthority_test.go new file mode 100644 index 00000000..833766a3 --- /dev/null +++ b/programs/token/SetAuthority_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_SetAuthority(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("SetAuthority"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(SetAuthority) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(SetAuthority) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/SyncNative.go b/programs/token/SyncNative.go new file mode 100644 index 00000000..b4edebb1 --- /dev/null +++ b/programs/token/SyncNative.go @@ -0,0 +1,101 @@ +package token + +import ( + "encoding/binary" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Given a wrapped / native token account (a token account containing SOL) +// updates its amount field based on the account's underlying `lamports`. +// This is useful if a non-wrapped SOL account uses `system_instruction::transfer` +// to move lamports to a wrapped token account, and needs to have its token +// `amount` field updated. +type SyncNative struct { + + // [0] = [WRITE] tokenAccount + // ··········· The native token account to sync with its underlying lamports. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewSyncNativeInstructionBuilder creates a new `SyncNative` instruction builder. +func NewSyncNativeInstructionBuilder() *SyncNative { + nd := &SyncNative{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 1), + } + return nd +} + +// The native token account to sync with its underlying lamports. +func (inst *SyncNative) SetTokenAccount(tokenAccount ag_solanago.PublicKey) *SyncNative { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAccount).WRITE() + return inst +} + +func (inst *SyncNative) GetTokenAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +func (inst SyncNative) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_SyncNative, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst SyncNative) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *SyncNative) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.TokenAccount is not set") + } + } + return nil +} + +func (inst *SyncNative) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("SyncNative")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAccount", inst.AccountMetaSlice[0])) + }) + }) + }) +} + +func (obj SyncNative) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *SyncNative) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewSyncNativeInstruction declares a new SyncNative instruction with the provided parameters and accounts. +func NewSyncNativeInstruction( + // Accounts: + tokenAccount ag_solanago.PublicKey) *SyncNative { + return NewSyncNativeInstructionBuilder(). + SetTokenAccount(tokenAccount) +} diff --git a/programs/token/SyncNative_test.go b/programs/token/SyncNative_test.go new file mode 100644 index 00000000..01dc127c --- /dev/null +++ b/programs/token/SyncNative_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_SyncNative(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("SyncNative"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(SyncNative) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(SyncNative) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/ThawAccount.go b/programs/token/ThawAccount.go new file mode 100644 index 00000000..b32c72d7 --- /dev/null +++ b/programs/token/ThawAccount.go @@ -0,0 +1,154 @@ +package token + +import ( + "encoding/binary" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Thaw a Frozen account using the Mint's freeze_authority (if set). +type ThawAccount struct { + + // [0] = [WRITE] account + // ··········· The account to thaw. + // + // [1] = [] mint + // ··········· The token mint. + // + // [2] = [] authority + // ··········· The mint freeze authority. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewThawAccountInstructionBuilder creates a new `ThawAccount` instruction builder. +func NewThawAccountInstructionBuilder() *ThawAccount { + nd := &ThawAccount{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The account to thaw. +func (inst *ThawAccount) SetAccount(account ag_solanago.PublicKey) *ThawAccount { + inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + return inst +} + +func (inst *ThawAccount) GetAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The token mint. +func (inst *ThawAccount) SetMintAccount(mint ag_solanago.PublicKey) *ThawAccount { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + return inst +} + +func (inst *ThawAccount) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The mint freeze authority. +func (inst *ThawAccount) SetAuthorityAccount(authority ag_solanago.PublicKey) *ThawAccount { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) + return inst +} + +func (inst *ThawAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *ThawAccount) SetSignersAccount(signers ag_solanago.PublicKey) *ThawAccount { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *ThawAccount) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst ThawAccount) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_ThawAccount, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst ThawAccount) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *ThawAccount) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Account is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *ThawAccount) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("ThawAccount")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj ThawAccount) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *ThawAccount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewThawAccountInstruction declares a new ThawAccount instruction with the provided parameters and accounts. +func NewThawAccountInstruction( + // Accounts: + account ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *ThawAccount { + return NewThawAccountInstructionBuilder(). + SetAccount(account). + SetMintAccount(mint). + SetAuthorityAccount(authority). + SetSignersAccount(signers) +} diff --git a/programs/token/ThawAccount_test.go b/programs/token/ThawAccount_test.go new file mode 100644 index 00000000..1ab8c410 --- /dev/null +++ b/programs/token/ThawAccount_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_ThawAccount(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("ThawAccount"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(ThawAccount) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(ThawAccount) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/Transfer.go b/programs/token/Transfer.go new file mode 100644 index 00000000..a5512b56 --- /dev/null +++ b/programs/token/Transfer.go @@ -0,0 +1,188 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Transfers tokens from one account to another either directly or via a +// delegate. If this account is associated with the native mint then equal +// amounts of SOL and Tokens will be transferred to the destination +// account. +type Transfer struct { + // The amount of tokens to transfer. + Amount *uint64 + + // [0] = [WRITE] source + // ··········· The source account. + // + // [1] = [WRITE] destination + // ··········· The destination account. + // + // [2] = [] owner + // ··········· The source account owner/delegate. + // + // [3] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewTransferInstructionBuilder creates a new `Transfer` instruction builder. +func NewTransferInstructionBuilder() *Transfer { + nd := &Transfer{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// The amount of tokens to transfer. +func (inst *Transfer) SetAmount(amount uint64) *Transfer { + inst.Amount = &amount + return inst +} + +// The source account. +func (inst *Transfer) SetSourceAccount(source ag_solanago.PublicKey) *Transfer { + inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + return inst +} + +func (inst *Transfer) GetSourceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The destination account. +func (inst *Transfer) SetDestinationAccount(destination ag_solanago.PublicKey) *Transfer { + inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() + return inst +} + +func (inst *Transfer) GetDestinationAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The source account owner/delegate. +func (inst *Transfer) SetOwnerAccount(owner ag_solanago.PublicKey) *Transfer { + inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) + return inst +} + +func (inst *Transfer) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// M signer accounts. +func (inst *Transfer) SetSignersAccount(signers ag_solanago.PublicKey) *Transfer { + inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *Transfer) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst Transfer) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_Transfer, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Transfer) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Transfer) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Amount == nil { + return errors.New("Amount parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Source is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Destination is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *Transfer) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Transfer")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj Transfer) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + return nil +} +func (obj *Transfer) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + return nil +} + +// NewTransferInstruction declares a new Transfer instruction with the provided parameters and accounts. +func NewTransferInstruction( + // Parameters: + amount uint64, + // Accounts: + source ag_solanago.PublicKey, + destination ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *Transfer { + return NewTransferInstructionBuilder(). + SetAmount(amount). + SetSourceAccount(source). + SetDestinationAccount(destination). + SetOwnerAccount(owner). + SetSignersAccount(signers) +} diff --git a/programs/token/TransferChecked.go b/programs/token/TransferChecked.go new file mode 100644 index 00000000..526840b3 --- /dev/null +++ b/programs/token/TransferChecked.go @@ -0,0 +1,236 @@ +package token + +import ( + "encoding/binary" + "errors" + "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// Transfers tokens from one account to another either directly or via a +// delegate. If this account is associated with the native mint then equal +// amounts of SOL and Tokens will be transferred to the destination +// account. +// +// This instruction differs from Transfer in that the token mint and +// decimals value is checked by the caller. This may be useful when +// creating transactions offline or within a hardware wallet. +type TransferChecked struct { + // The amount of tokens to transfer. + Amount *uint64 + + // Expected number of base 10 digits to the right of the decimal place. + Decimals *uint8 + + // [0] = [WRITE] source + // ··········· The source account. + // + // [1] = [] mint + // ··········· The token mint. + // + // [2] = [WRITE] destination + // ··········· The destination account. + // + // [3] = [] owner + // ··········· The source account's owner/delegate. + // + // [4] = [SIGNER] signers + // ··········· M signer accounts. + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewTransferCheckedInstructionBuilder creates a new `TransferChecked` instruction builder. +func NewTransferCheckedInstructionBuilder() *TransferChecked { + nd := &TransferChecked{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 5), + } + return nd +} + +// The amount of tokens to transfer. +func (inst *TransferChecked) SetAmount(amount uint64) *TransferChecked { + inst.Amount = &amount + return inst +} + +// Expected number of base 10 digits to the right of the decimal place. +func (inst *TransferChecked) SetDecimals(decimals uint8) *TransferChecked { + inst.Decimals = &decimals + return inst +} + +// The source account. +func (inst *TransferChecked) SetSourceAccount(source ag_solanago.PublicKey) *TransferChecked { + inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + return inst +} + +func (inst *TransferChecked) GetSourceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// The token mint. +func (inst *TransferChecked) SetMintAccount(mint ag_solanago.PublicKey) *TransferChecked { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + return inst +} + +func (inst *TransferChecked) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// The destination account. +func (inst *TransferChecked) SetDestinationAccount(destination ag_solanago.PublicKey) *TransferChecked { + inst.AccountMetaSlice[2] = ag_solanago.Meta(destination).WRITE() + return inst +} + +func (inst *TransferChecked) GetDestinationAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// The source account's owner/delegate. +func (inst *TransferChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *TransferChecked { + inst.AccountMetaSlice[3] = ag_solanago.Meta(owner) + return inst +} + +func (inst *TransferChecked) GetOwnerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// M signer accounts. +func (inst *TransferChecked) SetSignersAccount(signers ag_solanago.PublicKey) *TransferChecked { + inst.AccountMetaSlice[4] = ag_solanago.Meta(signers).SIGNER() + return inst +} + +func (inst *TransferChecked) GetSignersAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +func (inst TransferChecked) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: ag_binary.TypeIDFromUint32(Instruction_TransferChecked, binary.LittleEndian), + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst TransferChecked) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *TransferChecked) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Amount == nil { + return errors.New("Amount parameter is not set") + } + if inst.Decimals == nil { + return errors.New("Decimals parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return fmt.Errorf("accounts.Source is not set") + } + if inst.AccountMetaSlice[1] == nil { + return fmt.Errorf("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return fmt.Errorf("accounts.Destination is not set") + } + if inst.AccountMetaSlice[3] == nil { + return fmt.Errorf("accounts.Owner is not set") + } + if inst.AccountMetaSlice[4] == nil { + return fmt.Errorf("accounts.Signers is not set") + } + } + return nil +} + +func (inst *TransferChecked) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("TransferChecked")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[4])) + }) + }) + }) +} + +func (obj TransferChecked) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `Decimals` param: + err = encoder.Encode(obj.Decimals) + if err != nil { + return err + } + return nil +} +func (obj *TransferChecked) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `Decimals`: + err = decoder.Decode(&obj.Decimals) + if err != nil { + return err + } + return nil +} + +// NewTransferCheckedInstruction declares a new TransferChecked instruction with the provided parameters and accounts. +func NewTransferCheckedInstruction( + // Parameters: + amount uint64, + decimals uint8, + // Accounts: + source ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + destination ag_solanago.PublicKey, + owner ag_solanago.PublicKey, + signers ag_solanago.PublicKey) *TransferChecked { + return NewTransferCheckedInstructionBuilder(). + SetAmount(amount). + SetDecimals(decimals). + SetSourceAccount(source). + SetMintAccount(mint). + SetDestinationAccount(destination). + SetOwnerAccount(owner). + SetSignersAccount(signers) +} diff --git a/programs/token/TransferChecked_test.go b/programs/token/TransferChecked_test.go new file mode 100644 index 00000000..1b281d62 --- /dev/null +++ b/programs/token/TransferChecked_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_TransferChecked(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("TransferChecked"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(TransferChecked) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(TransferChecked) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/Transfer_test.go b/programs/token/Transfer_test.go new file mode 100644 index 00000000..959962c9 --- /dev/null +++ b/programs/token/Transfer_test.go @@ -0,0 +1,31 @@ +package token + +import ( + "bytes" + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Transfer(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Transfer"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Transfer) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + // + got := new(Transfer) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/programs/token/accounts.go b/programs/token/accounts.go new file mode 100644 index 00000000..7265b780 --- /dev/null +++ b/programs/token/accounts.go @@ -0,0 +1,51 @@ +package token + +import 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"` + + // Total supply of tokens. + Supply uint64 + + // Number of base 10 digits to the right of the decimal place. + Decimals uint8 + + // Is `true` if this structure has been initialized + IsInitialized bool + + // Optional authority to freeze token accounts. + FreezeAuthority *ag_solanago.PublicKey `bin:"optional"` +} + +type Account struct { + // The mint associated with this account + Mint ag_solanago.PublicKey + + // The owner of this account. + Owner ag_solanago.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"` + + // The account's state + State AccountState + + // If is_some, 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 `bin:"optional"` + + // The amount delegated + DelegatedAmount uint64 + + // Optional authority to close the account. + CloseAuthority *ag_solanago.PublicKey `bin:"optional"` +} diff --git a/programs/token/instructions.go b/programs/token/instructions.go index ae34e5f5..8e7f3746 100644 --- a/programs/token/instructions.go +++ b/programs/token/instructions.go @@ -1,205 +1,345 @@ -// Copyright 2020 dfuse Platform Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// A Token program on the Solana blockchain. +// This program defines a common implementation for Fungible and Non Fungible tokens. package token import ( + "bytes" + "encoding/binary" "fmt" - "github.com/gagliardetto/solana-go/text" - - bin "github.com/dfuse-io/binary" - "github.com/gagliardetto/solana-go" + ag_spew "github.com/davecgh/go-spew/spew" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_text "github.com/gagliardetto/solana-go/text" + ag_treeout "github.com/gagliardetto/treeout" ) -var TOKEN_PROGRAM_ID = solana.MustPublicKeyFromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") +var ProgramID ag_solanago.PublicKey = ag_solanago.SPLTokenProgramID -func init() { - solana.RegisterInstructionDecoder(TOKEN_PROGRAM_ID, registryDecodeInstruction) +func SetProgramID(pubkey ag_solanago.PublicKey) { + ProgramID = pubkey + ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) } -func registryDecodeInstruction(accounts []*solana.AccountMeta, data []byte) (interface{}, error) { - inst, err := DecodeInstruction(accounts, data) - if err != nil { - return nil, err +const ProgramName = "Token" + +func init() { + if !ProgramID.IsZero() { + ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) } - return inst, nil } -func DecodeInstruction(accounts []*solana.AccountMeta, data []byte) (*Instruction, error) { - var inst Instruction - if err := bin.NewBinDecoder(data).Decode(&inst); err != nil { - return nil, fmt.Errorf("unable to decode instruction for serum program: %w", err) - } +const ( + // Initializes a new mint and optionally deposits all the newly minted + // tokens in an account. + // + // The `InitializeMint` instruction requires no signers and MUST be + // included within the same Transaction as the system program's + // `CreateAccount` instruction that creates the account being initialized. + // Otherwise another party can acquire ownership of the uninitialized + // account. + Instruction_InitializeMint uint32 = iota + + // Initializes a new account to hold tokens. If this account is associated + // with the native mint then the token balance of the initialized account + // will be equal to the amount of SOL in the account. If this account is + // associated with another mint, that mint must be initialized before this + // command can succeed. + // + // The `InitializeAccount` instruction requires no signers and MUST be + // included within the same Transaction as the system program's + // `CreateAccount` instruction that creates the account being initialized. + // Otherwise another party can acquire ownership of the uninitialized + // account. + Instruction_InitializeAccount + + // Initializes a multisignature account with N provided signers. + // + // Multisignature accounts can used in place of any single owner/delegate + // accounts in any token instruction that require an owner/delegate to be + // present. The variant field represents the number of signers (M) + // required to validate this multisignature account. + // + // The `InitializeMultisig` instruction requires no signers and MUST be + // included within the same Transaction as the system program's + // `CreateAccount` instruction that creates the account being initialized. + // Otherwise another party can acquire ownership of the uninitialized + // account. + Instruction_InitializeMultisig + + // Transfers tokens from one account to another either directly or via a + // delegate. If this account is associated with the native mint then equal + // amounts of SOL and Tokens will be transferred to the destination + // account. + Instruction_Transfer + + // Approves a delegate. A delegate is given the authority over tokens on + // behalf of the source account's owner. + Instruction_Approve + + // Revokes the delegate's authority. + Instruction_Revoke + + // Sets a new authority of a mint or account. + Instruction_SetAuthority + + // Mints new tokens to an account. The native mint does not support + // minting. + Instruction_MintTo + + // Burns tokens by removing them from an account. `Burn` does not support + // accounts associated with the native mint, use `CloseAccount` instead. + Instruction_Burn + + // Close an account by transferring all its SOL to the destination account. + // Non-native accounts may only be closed if its token amount is zero. + Instruction_CloseAccount + + // Freeze an Initialized account using the Mint's freeze_authority (if set). + Instruction_FreezeAccount + + // Thaw a Frozen account using the Mint's freeze_authority (if set). + Instruction_ThawAccount + + // Transfers tokens from one account to another either directly or via a + // delegate. If this account is associated with the native mint then equal + // amounts of SOL and Tokens will be transferred to the destination + // account. + // + // This instruction differs from Transfer in that the token mint and + // decimals value is checked by the caller. This may be useful when + // creating transactions offline or within a hardware wallet. + Instruction_TransferChecked + + // Approves a delegate. A delegate is given the authority over tokens on + // behalf of the source account's owner. + // + // This instruction differs from Approve in that the token mint and + // decimals value is checked by the caller. This may be useful when + // creating transactions offline or within a hardware wallet. + Instruction_ApproveChecked + + // Mints new tokens to an account. The native mint does not support minting. + // + // This instruction differs from MintTo in that the decimals value is + // checked by the caller. This may be useful when creating transactions + // offline or within a hardware wallet. + Instruction_MintToChecked + + // Burns tokens by removing them from an account. `BurnChecked` does not + // support accounts associated with the native mint, use `CloseAccount` + // instead. + // + // This instruction differs from Burn in that the decimals value is checked + // by the caller. This may be useful when creating transactions offline or + // within a hardware wallet. + Instruction_BurnChecked + + // Like InitializeAccount, but the owner pubkey is passed via instruction data + // rather than the accounts list. This variant may be preferable when using + // Cross Program Invocation from an instruction that does not need the owner's + // `AccountInfo` otherwise. + Instruction_InitializeAccount2 + + // Given a wrapped / native token account (a token account containing SOL) + // updates its amount field based on the account's underlying `lamports`. + // This is useful if a non-wrapped SOL account uses `system_instruction::transfer` + // to move lamports to a wrapped token account, and needs to have its token + // `amount` field updated. + Instruction_SyncNative + + // Like InitializeAccount2, but does not require the Rent sysvar to be provided. + Instruction_InitializeAccount3 + + // Like InitializeMultisig, but does not require the Rent sysvar to be provided. + Instruction_InitializeMultisig2 + + // Like InitializeMint, but does not require the Rent sysvar to be provided. + Instruction_InitializeMint2 +) - if v, ok := inst.Impl.(solana.AccountsSettable); ok { - err := v.SetAccounts(accounts) - if err != nil { - return nil, fmt.Errorf("unable to set accounts for instruction: %w", err) - } +// InstructionIDToName returns the name of the instruction given its ID. +func InstructionIDToName(id uint32) string { + switch id { + case Instruction_InitializeMint: + return "InitializeMint" + case Instruction_InitializeAccount: + return "InitializeAccount" + case Instruction_InitializeMultisig: + return "InitializeMultisig" + case Instruction_Transfer: + return "Transfer" + case Instruction_Approve: + return "Approve" + case Instruction_Revoke: + return "Revoke" + case Instruction_SetAuthority: + return "SetAuthority" + case Instruction_MintTo: + return "MintTo" + case Instruction_Burn: + return "Burn" + case Instruction_CloseAccount: + return "CloseAccount" + case Instruction_FreezeAccount: + return "FreezeAccount" + case Instruction_ThawAccount: + return "ThawAccount" + case Instruction_TransferChecked: + return "TransferChecked" + case Instruction_ApproveChecked: + return "ApproveChecked" + case Instruction_MintToChecked: + return "MintToChecked" + case Instruction_BurnChecked: + return "BurnChecked" + case Instruction_InitializeAccount2: + return "InitializeAccount2" + case Instruction_SyncNative: + return "SyncNative" + case Instruction_InitializeAccount3: + return "InitializeAccount3" + case Instruction_InitializeMultisig2: + return "InitializeMultisig2" + case Instruction_InitializeMint2: + return "InitializeMint2" + default: + return "" } - - return &inst, nil } -var InstructionDefVariant = bin.NewVariantDefinition(bin.Uint8TypeIDEncoding, []bin.VariantType{ - {"initialize_mint", (*InitializeMint)(nil)}, - {"initialize_account", (*InitializeAccount)(nil)}, - {"InitializeMultisig", (*InitializeMultisig)(nil)}, - {"Transfer", (*Transfer)(nil)}, - {"Approve", (*Approve)(nil)}, - {"Revoke", (*Revoke)(nil)}, - {"SetAuthority", (*SetAuthority)(nil)}, - {"MintTo", (*MintTo)(nil)}, - {"Burn", (*Burn)(nil)}, - {"CloseAccount", (*CloseAccount)(nil)}, - {"FreezeAccount", (*FreezeAccount)(nil)}, - {"ThawAccount", (*ThawAccount)(nil)}, - {"TransferChecked", (*TransferChecked)(nil)}, - {"ApproveChecked", (*ApproveChecked)(nil)}, - {"MintToChecked", (*MintToChecked)(nil)}, - {"BurnChecked", (*BurnChecked)(nil)}, -}) - type Instruction struct { - bin.BaseVariant -} - -var _ bin.EncoderDecoder = &Instruction{} - -func (i *Instruction) UnmarshalWithDecoder(decoder *bin.Decoder) (err error) { - return i.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionDefVariant) + ag_binary.BaseVariant } -func (i *Instruction) MarshalWithEncoder(encoder *bin.Encoder) error { - err := encoder.WriteUint8(i.TypeID.Uint8()) - if err != nil { - return fmt.Errorf("unable to write variant type: %w", err) +func (inst *Instruction) EncodeToTree(parent ag_treeout.Branches) { + if enToTree, ok := inst.Impl.(ag_text.EncodableToTree); ok { + enToTree.EncodeToTree(parent) + } else { + parent.Child(ag_spew.Sdump(inst)) } - return encoder.Encode(i.Impl) -} -func (i *Instruction) TextEncode(encoder *text.Encoder, option *text.Option) error { - return encoder.Encode(i.Impl, option) -} - -type InitializeMultisigAccounts struct { -} -type InitializeMultisig struct { - Accounts *InitializeMultisigAccounts -} - -type InitializeMintAccounts struct { -} -type InitializeMint struct { - Accounts *InitializeMintAccounts -} - -type TransferAccounts struct { -} -type Transfer struct { - Accounts *TransferAccounts -} - -type ApproveAccounts struct { -} -type Approve struct { - Accounts *ApproveAccounts -} - -type RevokeAccounts struct { -} -type Revoke struct { - Accounts *RevokeAccounts -} - -type SetAuthorityAccounts struct { -} -type SetAuthority struct { - Accounts *SetAuthorityAccounts -} - -type MintToAccounts struct { -} -type MintTo struct { - Accounts *MintToAccounts -} - -type BurnAccounts struct { -} -type Burn struct { - Accounts *BurnAccounts } -type CloseAccountAccounts struct { -} -type CloseAccount struct { - Accounts *CloseAccountAccounts -} - -type FreezeAccountAccounts struct { -} -type FreezeAccount struct { - Accounts *FreezeAccountAccounts -} +var InstructionImplDef = ag_binary.NewVariantDefinition( + ag_binary.Uint32TypeIDEncoding, + []ag_binary.VariantType{ + { + "InitializeMint", (*InitializeMint)(nil), + }, + { + "InitializeAccount", (*InitializeAccount)(nil), + }, + { + "InitializeMultisig", (*InitializeMultisig)(nil), + }, + { + "Transfer", (*Transfer)(nil), + }, + { + "Approve", (*Approve)(nil), + }, + { + "Revoke", (*Revoke)(nil), + }, + { + "SetAuthority", (*SetAuthority)(nil), + }, + { + "MintTo", (*MintTo)(nil), + }, + { + "Burn", (*Burn)(nil), + }, + { + "CloseAccount", (*CloseAccount)(nil), + }, + { + "FreezeAccount", (*FreezeAccount)(nil), + }, + { + "ThawAccount", (*ThawAccount)(nil), + }, + { + "TransferChecked", (*TransferChecked)(nil), + }, + { + "ApproveChecked", (*ApproveChecked)(nil), + }, + { + "MintToChecked", (*MintToChecked)(nil), + }, + { + "BurnChecked", (*BurnChecked)(nil), + }, + { + "InitializeAccount2", (*InitializeAccount2)(nil), + }, + { + "SyncNative", (*SyncNative)(nil), + }, + { + "InitializeAccount3", (*InitializeAccount3)(nil), + }, + { + "InitializeMultisig2", (*InitializeMultisig2)(nil), + }, + { + "InitializeMint2", (*InitializeMint2)(nil), + }, + }, +) -type ThawAccountAccounts struct { -} -type ThawAccount struct { - Accounts *ThawAccountAccounts +func (inst *Instruction) ProgramID() ag_solanago.PublicKey { + return ProgramID } -type TransferCheckedAccounts struct { -} -type TransferChecked struct { - Accounts *TransferCheckedAccounts +func (inst *Instruction) Accounts() (out []*ag_solanago.AccountMeta) { + return inst.Impl.(ag_solanago.AccountsGettable).GetAccounts() } -type ApproveCheckedAccounts struct { -} -type ApproveChecked struct { - Accounts *ApproveCheckedAccounts +func (inst *Instruction) Data() ([]byte, error) { + buf := new(bytes.Buffer) + if err := ag_binary.NewBinEncoder(buf).Encode(inst); err != nil { + return nil, fmt.Errorf("unable to encode instruction: %w", err) + } + return buf.Bytes(), nil } -type MintToCheckedAccounts struct { -} -type MintToChecked struct { - Accounts *MintToCheckedAccounts +func (inst *Instruction) TextEncode(encoder *ag_text.Encoder, option *ag_text.Option) error { + return encoder.Encode(inst.Impl, option) } -type BurnCheckedAccounts struct { -} -type BurnChecked struct { - Accounts *BurnCheckedAccounts +func (inst *Instruction) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error { + return inst.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionImplDef) } -type InitializeAccountAccounts struct { - Account *solana.AccountMeta `text:"linear,notype"` - Mint *solana.AccountMeta `text:"linear,notype"` - Owner *solana.AccountMeta `text:"linear,notype"` - RentSysvar *solana.AccountMeta `text:"linear,notype"` +func (inst *Instruction) MarshalWithEncoder(encoder *ag_binary.Encoder) error { + err := encoder.WriteUint32(inst.TypeID.Uint32(), binary.LittleEndian) + if err != nil { + return fmt.Errorf("unable to write variant type: %w", err) + } + return encoder.Encode(inst.Impl) } -type InitializeAccount struct { - Accounts *InitializeAccountAccounts `bin:"-"` +func registryDecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (interface{}, error) { + inst, err := DecodeInstruction(accounts, data) + if err != nil { + return nil, err + } + return inst, nil } -func (i *InitializeAccount) SetAccounts(accounts []*solana.AccountMeta) error { - i.Accounts = &InitializeAccountAccounts{ - Account: accounts[0], - Mint: accounts[1], - Owner: accounts[2], - RentSysvar: accounts[3], +func DecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (*Instruction, error) { + inst := new(Instruction) + if err := ag_binary.NewBinDecoder(data).Decode(inst); err != nil { + return nil, fmt.Errorf("unable to decode instruction: %w", err) } - return nil + if v, ok := inst.Impl.(ag_solanago.AccountsSettable); ok { + err := v.SetAccounts(accounts) + if err != nil { + return nil, fmt.Errorf("unable to set accounts for instruction: %w", err) + } + } + return inst, nil } diff --git a/programs/token/mints-data/mainnet-tokens.json b/programs/token/mints-data/mainnet-tokens.json deleted file mode 100644 index 479a040d..00000000 --- a/programs/token/mints-data/mainnet-tokens.json +++ /dev/null @@ -1,148 +0,0 @@ -[ - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x476c5E26a75bd202a9683ffD34359C0CC15be0fF/logo.png", - "mintAddress": "SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt", - "tokenName": "Serum", - "tokenSymbol": "SRM" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x476c5E26a75bd202a9683ffD34359C0CC15be0fF/logo.png", - "mintAddress": "MSRMcoVyrFxnSgo5uXwone5SKcGhT1KEJMFEkMEWf9L", - "tokenName": "MegaSerum", - "tokenSymbol": "MSRM" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/bitcoin/info/logo.png", - "mintAddress": "9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E", - "tokenName": "Wrapped Bitcoin", - "tokenSymbol": "BTC" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png", - "mintAddress": "2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk", - "tokenName": "Wrapped Ethereum", - "tokenSymbol": "ETH" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/f3ffd0b9ae2165336279ce2f8db1981a55ce30f8/blockchains/ethereum/assets/0x50D1c9771902476076eCFc8B2A83Ad6b9355a4c9/logo.png", - "mintAddress": "AGFEad2et2ZJif9jaGpdMixQqvW5i81aBdvKe7PHNfz3", - "tokenName": "Wrapped FTT", - "tokenSymbol": "FTT" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e/logo.png", - "mintAddress": "3JSf5tPeuscJGtaCp5giEiDhv51gQ4v3zWg8DGgyLfAB", - "tokenName": "Wrapped YFI", - "tokenSymbol": "YFI" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png", - "mintAddress": "CWE8jPTUYhdCTZYWPTe1o5DFqfdjzWKc9WKz6rSjQUdG", - "tokenName": "Wrapped Chainlink", - "tokenSymbol": "LINK" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ripple/info/logo.png", - "mintAddress": "Ga2AXHpfAF6mv2ekZwcsJFqu7wB4NV331qNH7fW9Nst8", - "tokenName": "Wrapped XRP", - "tokenSymbol": "XRP" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/f3ffd0b9ae2165336279ce2f8db1981a55ce30f8/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png", - "mintAddress": "BQcdHdAQW1hczDbBi9hiegXAR7A98Q9jx3X3iBBBDiq4", - "tokenName": "Wrapped USDT", - "tokenSymbol": "USDT" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/f3ffd0b9ae2165336279ce2f8db1981a55ce30f8/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", - "mintAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - "tokenName": "USD Coin", - "tokenSymbol": "USDC" - }, - { - "deprecated": true, - "icon": "https://raw.githubusercontent.com/trustwallet/assets/f3ffd0b9ae2165336279ce2f8db1981a55ce30f8/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png", - "mintAddress": "BXXkv6z8ykpG1yuvUDPgh732wzVHB69RnB9YgSYh3itW", - "tokenName": "Wrapped USDC", - "tokenSymbol": "WUSDC" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B3595068778DD592e39A122f4f5a5cF09C90fE2/logo.png", - "mintAddress": "AR1Mtgh7zAtxuxGd2XPovXPVjcSdY3i4rQYisNadjfKy", - "tokenName": "Wrapped SUSHI", - "tokenSymbol": "SUSHI" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/6996a371cd02f516506a8f092eeb29888501447c/blockchains/nuls/assets/NULSd6HgyZkiqLnBzTaeSQfx1TNg2cqbzq51h/logo.png", - "mintAddress": "CsZ5LZkDS7h9TDKjrbL7VAwQZ9nsRu8vJLhRYfmGaN8K", - "tokenName": "Wrapped ALEPH", - "tokenSymbol": "ALEPH" - }, - { - "icon": "https://github.com/trustwallet/assets/raw/b0ab88654fe64848da80d982945e4db06e197d4f/blockchains/ethereum/assets/0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9/logo.png", - "mintAddress": "SF3oTvfWzEP3DTwGSvUXRrGTvr75pdZNnBLAH9bzMuX", - "tokenName": "Wrapped SXP", - "tokenSymbol": "SXP" - }, - { - "mintAddress": "BtZQfWqDGbk9Wf2rXEiWyQBdBY1etnUUn6zEphvVS7yN", - "tokenName": "Wrapped HGET", - "tokenSymbol": "HGET" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/4c82c2a409f18a4dd96a504f967a55a8fe47026d/blockchains/smartchain/assets/0xd4CB328A82bDf5f03eB737f37Fa6B370aef3e888/logo.png", - "mintAddress": "5Fu5UUgbjpUvdBveb3a1JTNirL8rXtiYeSMWvKjtUNQv", - "tokenName": "Wrapped CREAM", - "tokenSymbol": "CREAM" - }, - { - "mintAddress": "873KLxCbz7s9Kc4ZzgYRtNmhfkQrhfyWGZJBmyCbC3ei", - "tokenName": "Wrapped UBXT", - "tokenSymbol": "UBXT" - }, - { - "mintAddress": "HqB7uswoVg4suaQiDP3wjxob1G5WdZ144zhdStwMCq7e", - "tokenName": "Wrapped HNT", - "tokenSymbol": "HNT" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/6e375e4e5fb0ffe09ed001bae1ef8ca1d6c86034/blockchains/ethereum/assets/0xf8C3527CC04340b208C854E985240c02F7B7793f/logo.png", - "mintAddress": "9S4t2NEAiJVMvPdRYKVrfJpBafPBLtvbvyS3DecojQHw", - "tokenName": "Wrapped FRONT", - "tokenSymbol": "FRONT" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/878dcab0fab90e6593bcb9b7d941be4915f287dc/blockchains/ethereum/assets/0xb2734a4Cec32C81FDE26B0024Ad3ceB8C9b34037/logo.png", - "mintAddress": "6WNVCuxCGJzNjmMZoKyhZJwvJ5tYpsLyAtagzYASqBoF", - "tokenName": "Wrapped AKRO", - "tokenSymbol": "AKRO" - }, - { - "mintAddress": "DJafV9qemGp7mLMEn5wrfqaFwxsbLgUsGVS16zKRk9kc", - "tokenName": "Wrapped HXRO", - "tokenSymbol": "HXRO" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/08d734b5e6ec95227dc50efef3a9cdfea4c398a1/blockchains/ethereum/assets/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984/logo.png", - "mintAddress": "DEhAasscXF4kEGxFgJ3bq4PpVGp5wyUxMRvn6TzGVHaw", - "tokenName": "Wrapped UNI", - "tokenSymbol": "UNI" - }, - { - "mintAddress": "GeDS162t9yGJuLEHPWXXGrb1zwkzinCgRwnT8vHYjKza", - "tokenName": "Wrapped MATH", - "tokenSymbol": "MATH" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/08d734b5e6ec95227dc50efef3a9cdfea4c398a1/blockchains/tomochain/info/logo.png", - "mintAddress": "GXMvfY2jpQctDqZ9RoU3oWPhufKiCcFEfchvYumtX7jd", - "tokenName": "Wrapped TOMO", - "tokenSymbol": "TOMO" - }, - { - "icon": "https://raw.githubusercontent.com/trustwallet/assets/2d2491130e6beda208ba4fc6df028a82a0106ab6/blockchains/ethereum/assets/0xB1f66997A5760428D3a87D68b90BfE0aE64121cC/logo.png", - "mintAddress": "EqWCKXfs3x47uVosDpTRgFniThL9Y8iCztJaapxbEaVX", - "tokenName": "Wrapped LUA", - "tokenSymbol": "LUA" - } -] diff --git a/programs/token/rice-box.go b/programs/token/rice-box.go deleted file mode 100644 index 9370608d..00000000 --- a/programs/token/rice-box.go +++ /dev/null @@ -1,44 +0,0 @@ -// Code generated by rice embed-go; DO NOT EDIT. -package token - -import ( - "time" - - "github.com/GeertJohan/go.rice/embedded" -) - -func init() { - - // define files - file2 := &embedded.EmbeddedFile{ - Filename: "mainnet-tokens.json", - FileModTime: time.Unix(1606332268, 0), - - Content: string("[\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x476c5E26a75bd202a9683ffD34359C0CC15be0fF/logo.png\",\n \"mintAddress\": \"SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt\",\n \"tokenName\": \"Serum\",\n \"tokenSymbol\": \"SRM\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x476c5E26a75bd202a9683ffD34359C0CC15be0fF/logo.png\",\n \"mintAddress\": \"MSRMcoVyrFxnSgo5uXwone5SKcGhT1KEJMFEkMEWf9L\",\n \"tokenName\": \"MegaSerum\",\n \"tokenSymbol\": \"MSRM\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/bitcoin/info/logo.png\",\n \"mintAddress\": \"9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E\",\n \"tokenName\": \"Wrapped Bitcoin\",\n \"tokenSymbol\": \"BTC\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png\",\n \"mintAddress\": \"2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk\",\n \"tokenName\": \"Wrapped Ethereum\",\n \"tokenSymbol\": \"ETH\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/f3ffd0b9ae2165336279ce2f8db1981a55ce30f8/blockchains/ethereum/assets/0x50D1c9771902476076eCFc8B2A83Ad6b9355a4c9/logo.png\",\n \"mintAddress\": \"AGFEad2et2ZJif9jaGpdMixQqvW5i81aBdvKe7PHNfz3\",\n \"tokenName\": \"Wrapped FTT\",\n \"tokenSymbol\": \"FTT\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e/logo.png\",\n \"mintAddress\": \"3JSf5tPeuscJGtaCp5giEiDhv51gQ4v3zWg8DGgyLfAB\",\n \"tokenName\": \"Wrapped YFI\",\n \"tokenSymbol\": \"YFI\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png\",\n \"mintAddress\": \"CWE8jPTUYhdCTZYWPTe1o5DFqfdjzWKc9WKz6rSjQUdG\",\n \"tokenName\": \"Wrapped Chainlink\",\n \"tokenSymbol\": \"LINK\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ripple/info/logo.png\",\n \"mintAddress\": \"Ga2AXHpfAF6mv2ekZwcsJFqu7wB4NV331qNH7fW9Nst8\",\n \"tokenName\": \"Wrapped XRP\",\n \"tokenSymbol\": \"XRP\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/f3ffd0b9ae2165336279ce2f8db1981a55ce30f8/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png\",\n \"mintAddress\": \"BQcdHdAQW1hczDbBi9hiegXAR7A98Q9jx3X3iBBBDiq4\",\n \"tokenName\": \"Wrapped USDT\",\n \"tokenSymbol\": \"USDT\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/f3ffd0b9ae2165336279ce2f8db1981a55ce30f8/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png\",\n \"mintAddress\": \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n \"tokenName\": \"USD Coin\",\n \"tokenSymbol\": \"USDC\"\n },\n {\n \"deprecated\": true,\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/f3ffd0b9ae2165336279ce2f8db1981a55ce30f8/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png\",\n \"mintAddress\": \"BXXkv6z8ykpG1yuvUDPgh732wzVHB69RnB9YgSYh3itW\",\n \"tokenName\": \"Wrapped USDC\",\n \"tokenSymbol\": \"WUSDC\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B3595068778DD592e39A122f4f5a5cF09C90fE2/logo.png\",\n \"mintAddress\": \"AR1Mtgh7zAtxuxGd2XPovXPVjcSdY3i4rQYisNadjfKy\",\n \"tokenName\": \"Wrapped SUSHI\",\n \"tokenSymbol\": \"SUSHI\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/6996a371cd02f516506a8f092eeb29888501447c/blockchains/nuls/assets/NULSd6HgyZkiqLnBzTaeSQfx1TNg2cqbzq51h/logo.png\",\n \"mintAddress\": \"CsZ5LZkDS7h9TDKjrbL7VAwQZ9nsRu8vJLhRYfmGaN8K\",\n \"tokenName\": \"Wrapped ALEPH\",\n \"tokenSymbol\": \"ALEPH\"\n },\n {\n \"icon\": \"https://github.com/trustwallet/assets/raw/b0ab88654fe64848da80d982945e4db06e197d4f/blockchains/ethereum/assets/0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9/logo.png\",\n \"mintAddress\": \"SF3oTvfWzEP3DTwGSvUXRrGTvr75pdZNnBLAH9bzMuX\",\n \"tokenName\": \"Wrapped SXP\",\n \"tokenSymbol\": \"SXP\"\n },\n {\n \"mintAddress\": \"BtZQfWqDGbk9Wf2rXEiWyQBdBY1etnUUn6zEphvVS7yN\",\n \"tokenName\": \"Wrapped HGET\",\n \"tokenSymbol\": \"HGET\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/4c82c2a409f18a4dd96a504f967a55a8fe47026d/blockchains/smartchain/assets/0xd4CB328A82bDf5f03eB737f37Fa6B370aef3e888/logo.png\",\n \"mintAddress\": \"5Fu5UUgbjpUvdBveb3a1JTNirL8rXtiYeSMWvKjtUNQv\",\n \"tokenName\": \"Wrapped CREAM\",\n \"tokenSymbol\": \"CREAM\"\n },\n {\n \"mintAddress\": \"873KLxCbz7s9Kc4ZzgYRtNmhfkQrhfyWGZJBmyCbC3ei\",\n \"tokenName\": \"Wrapped UBXT\",\n \"tokenSymbol\": \"UBXT\"\n },\n {\n \"mintAddress\": \"HqB7uswoVg4suaQiDP3wjxob1G5WdZ144zhdStwMCq7e\",\n \"tokenName\": \"Wrapped HNT\",\n \"tokenSymbol\": \"HNT\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/6e375e4e5fb0ffe09ed001bae1ef8ca1d6c86034/blockchains/ethereum/assets/0xf8C3527CC04340b208C854E985240c02F7B7793f/logo.png\",\n \"mintAddress\": \"9S4t2NEAiJVMvPdRYKVrfJpBafPBLtvbvyS3DecojQHw\",\n \"tokenName\": \"Wrapped FRONT\",\n \"tokenSymbol\": \"FRONT\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/878dcab0fab90e6593bcb9b7d941be4915f287dc/blockchains/ethereum/assets/0xb2734a4Cec32C81FDE26B0024Ad3ceB8C9b34037/logo.png\",\n \"mintAddress\": \"6WNVCuxCGJzNjmMZoKyhZJwvJ5tYpsLyAtagzYASqBoF\",\n \"tokenName\": \"Wrapped AKRO\",\n \"tokenSymbol\": \"AKRO\"\n },\n {\n \"mintAddress\": \"DJafV9qemGp7mLMEn5wrfqaFwxsbLgUsGVS16zKRk9kc\",\n \"tokenName\": \"Wrapped HXRO\",\n \"tokenSymbol\": \"HXRO\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/08d734b5e6ec95227dc50efef3a9cdfea4c398a1/blockchains/ethereum/assets/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984/logo.png\",\n \"mintAddress\": \"DEhAasscXF4kEGxFgJ3bq4PpVGp5wyUxMRvn6TzGVHaw\",\n \"tokenName\": \"Wrapped UNI\",\n \"tokenSymbol\": \"UNI\"\n },\n {\n \"mintAddress\": \"GeDS162t9yGJuLEHPWXXGrb1zwkzinCgRwnT8vHYjKza\",\n \"tokenName\": \"Wrapped MATH\",\n \"tokenSymbol\": \"MATH\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/08d734b5e6ec95227dc50efef3a9cdfea4c398a1/blockchains/tomochain/info/logo.png\",\n \"mintAddress\": \"GXMvfY2jpQctDqZ9RoU3oWPhufKiCcFEfchvYumtX7jd\",\n \"tokenName\": \"Wrapped TOMO\",\n \"tokenSymbol\": \"TOMO\"\n },\n {\n \"icon\": \"https://raw.githubusercontent.com/trustwallet/assets/2d2491130e6beda208ba4fc6df028a82a0106ab6/blockchains/ethereum/assets/0xB1f66997A5760428D3a87D68b90BfE0aE64121cC/logo.png\",\n \"mintAddress\": \"EqWCKXfs3x47uVosDpTRgFniThL9Y8iCztJaapxbEaVX\",\n \"tokenName\": \"Wrapped LUA\",\n \"tokenSymbol\": \"LUA\"\n }\n]\n"), - } - - // define dirs - dir1 := &embedded.EmbeddedDir{ - Filename: "", - DirModTime: time.Unix(1606332268, 0), - ChildFiles: []*embedded.EmbeddedFile{ - file2, // "mainnet-tokens.json" - - }, - } - - // link ChildDirs - dir1.ChildDirs = []*embedded.EmbeddedDir{} - - // register embeddedBox - embedded.RegisterEmbeddedBox(`mints-data`, &embedded.EmbeddedBox{ - Name: `mints-data`, - Time: time.Unix(1606332268, 0), - Dirs: map[string]*embedded.EmbeddedDir{ - "": dir1, - }, - Files: map[string]*embedded.EmbeddedFile{ - "mainnet-tokens.json": file2, - }, - }) -} diff --git a/programs/token/rpc.go b/programs/token/rpc.go index 83accef2..1755bb43 100644 --- a/programs/token/rpc.go +++ b/programs/token/rpc.go @@ -18,15 +18,25 @@ import ( "context" "fmt" + bin "github.com/dfuse-io/binary" "github.com/gagliardetto/solana-go/rpc" ) -//go:generate rice embed-go +const MINT_SIZE = 82 + +func (mint *Mint) Decode(data []byte) error { + mint = new(Mint) + dec := bin.NewBinDecoder(data) + if err := dec.Decode(&mint); err != nil { + return fmt.Errorf("unable to decode mint: %w", err) + } + return nil +} func FetchMints(ctx context.Context, rpcCli *rpc.Client) (out []*Mint, err error) { resp, err := rpcCli.GetProgramAccountsWithOpts( ctx, - TOKEN_PROGRAM_ID, + ProgramID, &rpc.GetProgramAccountsOpts{ Filters: []rpc.RPCFilter{ { @@ -45,7 +55,7 @@ func FetchMints(ctx context.Context, rpcCli *rpc.Client) (out []*Mint, err error for _, keyedAcct := range resp { acct := keyedAcct.Account - m := &Mint{} + m := new(Mint) if err := m.Decode(acct.Data.GetBinary()); err != nil { return nil, fmt.Errorf("unable to decode mint %q: %w", acct.Owner.String(), err) } diff --git a/programs/token/testing_utils.go b/programs/token/testing_utils.go new file mode 100644 index 00000000..a0ce07a2 --- /dev/null +++ b/programs/token/testing_utils.go @@ -0,0 +1,18 @@ +package token + +import ( + "bytes" + "fmt" + ag_binary "github.com/dfuse-io/binary" +) + +func encodeT(data interface{}, buf *bytes.Buffer) error { + if err := ag_binary.NewBinEncoder(buf).Encode(data); err != nil { + return fmt.Errorf("unable to encode instruction: %w", err) + } + return nil +} + +func decodeT(dst interface{}, data []byte) error { + return ag_binary.NewBinDecoder(data).Decode(dst) +} diff --git a/programs/token/types.go b/programs/token/types.go index 81e2d57e..a5cf0fa0 100644 --- a/programs/token/types.go +++ b/programs/token/types.go @@ -1,66 +1,51 @@ package token import ( - "fmt" + ag_binary "github.com/dfuse-io/binary" + ag_solanago "github.com/gagliardetto/solana-go" +) + +type AuthorityType ag_binary.BorshEnum + +const ( + // Authority to mint new tokens + AuthorityMintTokens AuthorityType = iota + + // Authority to freeze any account associated with the Mint + AuthorityFreezeAccount - bin "github.com/dfuse-io/binary" - "github.com/gagliardetto/solana-go" + // Owner of a given token account + AuthorityAccountOwner + + // Authority to close a token account + AuthorityCloseAccount ) -// Token contract interface +type AccountState ag_binary.BorshEnum -type Token struct { - ProgramID string - Mint string -} +const ( + // Account is not yet initialized + Uninitialized AccountState = iota -func New(programID string, mint string) *Token { - return &Token{ProgramID: programID, Mint: mint} -} + // Account is initialized; the account owner and/or delegate may perform permitted operations + // on this account + Initialized -type Account struct { - Mint solana.PublicKey - Owner solana.PublicKey - Amount bin.Uint64 - IsDelegateSet uint32 - Delegate solana.PublicKey - IsInitialized bool - IsNative bool - Padding [2]byte `json:"-"` - DelegatedAmount bin.Uint64 -} + // Account has been frozen by the mint freeze authority. Neither the account owner nor + // the delegate are able to perform operations on this account. + Frozen +) type Multisig struct { - M byte - N byte - IsInitialized bool - Signers [11]solana.PublicKey -} + // Number of signers required + M uint8 -const MINT_SIZE = 82 + // Number of valid signers + N uint8 -type Mint struct { - MintAuthorityOption uint32 - MintAuthority solana.PublicKey - Supply bin.Uint64 - Decimals uint8 - IsInitialized bool - FreezeAuthorityOption uint32 - FreezeAuthority solana.PublicKey -} - -func (m *Mint) Decode(in []byte) error { - decoder := bin.NewBinDecoder(in) - err := decoder.Decode(&m) - if err != nil { - return fmt.Errorf("unpack: %w", err) - } - return nil -} + // Is `true` if this structure has been initialized + IsInitialized bool -type MintMeta struct { - TokenSymbol string - MintAddress solana.PublicKey - TokenName string - IconURL string `json:"icon"` + // Signer public keys + Signers [11]ag_solanago.PublicKey } diff --git a/programs/token/types_test.go b/programs/token/types_test.go deleted file mode 100644 index 159e08fd..00000000 --- a/programs/token/types_test.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2020 dfuse Platform Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package token - -import ( - "bytes" - "context" - "os" - "testing" - - bin "github.com/dfuse-io/binary" - "github.com/gagliardetto/solana-go" - "github.com/gagliardetto/solana-go/rpc" - "github.com/mr-tron/base58" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestAccount(t *testing.T) { - b58data := "SqtzmJArwV2556pK7AdHbHNPVP2L2WaR6zfcFeot94TzGRUyUMEWew558UxnYEGrmm9b9VZY7MS6TCHT5wqtzaA5Vy8ghoFyGmbRNC58CttRf5GzH9wfjCkncyrmKjfevyjrJ2W9XKLgYGth46ctFWzJJXCeHsYwDx1d" - data, _ := base58.Decode(b58data) - - //fmt.Println("HEX:", hex.EncodeToString(data)) - // ba71eb12868584549b86f75620e7bb3ac5ef49df3fef0d48ad08e48dfa0fc786 // mint - // d7a1d0a56e355f17cedd5733e36a0cc9e2caf7a435e3256e4c9bff755f682b5a // owner - // 5ece000000000000 // amount - // 00000000 // is delegate set - // 0000000000000000000000000000000000000000000000000000000000000000 // delegate - // 01000000 // is initialized, is native + padding - // 0000000000000000 // delegate amount - var out Account - err := bin.NewBinDecoder(data).Decode(&out) - require.NoError(t, err) - - expect := Account{ - Mint: solana.MustPublicKeyFromBase58("DYoajiN32pjK8zMAa67ScNn2E7EmXrZ6doABRqfSZ63F"), - Owner: solana.MustPublicKeyFromBase58("FWjmNcjufwC3QFdcHrAK1yAQkCwJSUAxvVFFgvQ1nAJM"), - Amount: bin.Uint64(52830), - IsInitialized: true, - } - expectJSON, err := json.MarshalIndent(expect, "", " ") - require.NoError(t, err) - - outJSON, err := json.MarshalIndent(out, "", " ") - require.NoError(t, err) - - assert.JSONEq(t, string(expectJSON), string(outJSON)) - - buf := &bytes.Buffer{} - assert.NoError(t, bin.NewBinEncoder(buf).Encode(out)) - - assert.Equal(t, b58data, base58.Encode(buf.Bytes())) -} - -func TestMint(t *testing.T) { - rpcURL := os.Getenv("RPC_URL") - if rpcURL == "" { - t.Skip("Setup 'RPC_URL' to run test i.e. 'wss://api.mainnet-beta.solana.com'") - return - } - addr := solana.MustPublicKeyFromBase58("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v") - cli := rpc.New(rpcURL) - - var m Mint - err := cli.GetAccountDataIn(context.Background(), addr, &m) - // handle `err` - require.NoError(t, err) - - json.NewEncoder(os.Stdout).Encode(m) - // {"OwnerOption":1, - // "Owner":"2wmVCSfPxGPjrnMMn7rchp4uaeoTqN39mXFC2zhPdri9", - // "Decimals":128, - // "IsInitialized":true} -} - -func TestRawMint(t *testing.T) { - rpcURL := os.Getenv("RPC_URL") - if rpcURL == "" { - t.Skip("Setup 'RPC_URL' to run test i.e. 'wss://api.mainnet-beta.solana.com'") - return - } - addr := solana.MustPublicKeyFromBase58("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v") - cli := rpc.New(rpcURL) - - resp, err := cli.GetAccountInfo(context.Background(), addr) - // handle `err` - require.NoError(t, err) - - json.NewEncoder(os.Stdout).Encode(resp) - // {"OwnerOption":1, - // "Owner":"2wmVCSfPxGPjrnMMn7rchp4uaeoTqN39mXFC2zhPdri9", - // "Decimals":128, - // "IsInitialized":true} -} From 5550ac122c5b314409905efd31d8404d348891a9 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 01:50:30 +0200 Subject: [PATCH 02/24] Update README --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5042fcef..7d5e85d8 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,17 @@ More contracts to come. - [x] Full WebSocket JSON streaming API - [ ] Wallet, account, and keys management - [ ] Clients for native programs -- [ ] Clients for Solana Program Library + - [x] system + - [ ] config + - [ ] stake + - [ ] vote + - [ ] BPF Loader + - [ ] Secp256k1 +- [ ] Clients for Solana Program Library (SPL) + - [ ] token: WIP + - [ ] memo + - [ ] name-service + - [ ] ... - [ ] Client for Serum - [ ] More programs From c860699d3238f87ff96c0b2f848fa72a85a21267 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 01:55:23 +0200 Subject: [PATCH 03/24] token: regenerate with new comments --- programs/token/Approve.go | 13 +++++++++++++ programs/token/ApproveChecked.go | 17 +++++++++++++++++ programs/token/Burn.go | 13 +++++++++++++ programs/token/BurnChecked.go | 14 ++++++++++++++ programs/token/CloseAccount.go | 12 ++++++++++++ programs/token/FreezeAccount.go | 12 ++++++++++++ programs/token/InitializeAccount.go | 12 ++++++++++++ programs/token/InitializeAccount2.go | 10 ++++++++++ programs/token/InitializeAccount3.go | 7 +++++++ programs/token/InitializeMint.go | 9 +++++++++ programs/token/InitializeMint2.go | 6 ++++++ programs/token/InitializeMultisig2.go | 7 +++++++ programs/token/MintTo.go | 13 +++++++++++++ programs/token/MintToChecked.go | 14 ++++++++++++++ programs/token/Revoke.go | 9 +++++++++ programs/token/SetAuthority.go | 11 +++++++++++ programs/token/SyncNative.go | 3 +++ programs/token/ThawAccount.go | 12 ++++++++++++ programs/token/TransferChecked.go | 17 +++++++++++++++++ 19 files changed, 211 insertions(+) diff --git a/programs/token/Approve.go b/programs/token/Approve.go index c9c4944a..889302a4 100644 --- a/programs/token/Approve.go +++ b/programs/token/Approve.go @@ -38,48 +38,61 @@ func NewApproveInstructionBuilder() *Approve { return nd } +// SetAmount sets the "amount" parameter. // The amount of tokens the delegate is approved for. func (inst *Approve) SetAmount(amount uint64) *Approve { inst.Amount = &amount return inst } +// SetSourceAccount sets the "source" account. // The source account. func (inst *Approve) SetSourceAccount(source ag_solanago.PublicKey) *Approve { inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() return inst } +// GetSourceAccount gets the "source" account. +// The source account. func (inst *Approve) GetSourceAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetDelegateAccount sets the "delegate" account. // The delegate. func (inst *Approve) SetDelegateAccount(delegate ag_solanago.PublicKey) *Approve { inst.AccountMetaSlice[1] = ag_solanago.Meta(delegate) return inst } +// GetDelegateAccount gets the "delegate" account. +// The delegate. func (inst *Approve) GetDelegateAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetOwnerAccount sets the "owner" account. // The source account owner. func (inst *Approve) SetOwnerAccount(owner ag_solanago.PublicKey) *Approve { inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) return inst } +// GetOwnerAccount gets the "owner" account. +// The source account owner. func (inst *Approve) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *Approve) SetSignersAccount(signers ag_solanago.PublicKey) *Approve { inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *Approve) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/ApproveChecked.go b/programs/token/ApproveChecked.go index da47f29f..7cb136a1 100644 --- a/programs/token/ApproveChecked.go +++ b/programs/token/ApproveChecked.go @@ -48,64 +48,81 @@ func NewApproveCheckedInstructionBuilder() *ApproveChecked { return nd } +// SetAmount sets the "amount" parameter. // The amount of tokens the delegate is approved for. func (inst *ApproveChecked) SetAmount(amount uint64) *ApproveChecked { inst.Amount = &amount return inst } +// SetDecimals sets the "decimals" parameter. // Expected number of base 10 digits to the right of the decimal place. func (inst *ApproveChecked) SetDecimals(decimals uint8) *ApproveChecked { inst.Decimals = &decimals return inst } +// SetSourceAccount sets the "source" account. // The source account. func (inst *ApproveChecked) SetSourceAccount(source ag_solanago.PublicKey) *ApproveChecked { inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() return inst } +// GetSourceAccount gets the "source" account. +// The source account. func (inst *ApproveChecked) GetSourceAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The token mint. func (inst *ApproveChecked) SetMintAccount(mint ag_solanago.PublicKey) *ApproveChecked { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) return inst } +// GetMintAccount gets the "mint" account. +// The token mint. func (inst *ApproveChecked) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetDelegateAccount sets the "delegate" account. // The delegate. func (inst *ApproveChecked) SetDelegateAccount(delegate ag_solanago.PublicKey) *ApproveChecked { inst.AccountMetaSlice[2] = ag_solanago.Meta(delegate) return inst } +// GetDelegateAccount gets the "delegate" account. +// The delegate. func (inst *ApproveChecked) GetDelegateAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetOwnerAccount sets the "owner" account. // The source account owner. func (inst *ApproveChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *ApproveChecked { inst.AccountMetaSlice[3] = ag_solanago.Meta(owner) return inst } +// GetOwnerAccount gets the "owner" account. +// The source account owner. func (inst *ApproveChecked) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *ApproveChecked) SetSignersAccount(signers ag_solanago.PublicKey) *ApproveChecked { inst.AccountMetaSlice[4] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *ApproveChecked) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[4] } diff --git a/programs/token/Burn.go b/programs/token/Burn.go index c6701824..590f2af2 100644 --- a/programs/token/Burn.go +++ b/programs/token/Burn.go @@ -38,48 +38,61 @@ func NewBurnInstructionBuilder() *Burn { return nd } +// SetAmount sets the "amount" parameter. // The amount of tokens to burn. func (inst *Burn) SetAmount(amount uint64) *Burn { inst.Amount = &amount return inst } +// SetSourceAccount sets the "source" account. // The account to burn from. func (inst *Burn) SetSourceAccount(source ag_solanago.PublicKey) *Burn { inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() return inst } +// GetSourceAccount gets the "source" account. +// The account to burn from. func (inst *Burn) GetSourceAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The token mint. func (inst *Burn) SetMintAccount(mint ag_solanago.PublicKey) *Burn { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() return inst } +// GetMintAccount gets the "mint" account. +// The token mint. func (inst *Burn) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetOwnerAccount sets the "owner" account. // The account's owner/delegate. func (inst *Burn) SetOwnerAccount(owner ag_solanago.PublicKey) *Burn { inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) return inst } +// GetOwnerAccount gets the "owner" account. +// The account's owner/delegate. func (inst *Burn) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *Burn) SetSignersAccount(signers ag_solanago.PublicKey) *Burn { inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *Burn) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/BurnChecked.go b/programs/token/BurnChecked.go index e17829b0..c56f20eb 100644 --- a/programs/token/BurnChecked.go +++ b/programs/token/BurnChecked.go @@ -46,54 +46,68 @@ func NewBurnCheckedInstructionBuilder() *BurnChecked { return nd } +// SetAmount sets the "amount" parameter. // The amount of tokens to burn. func (inst *BurnChecked) SetAmount(amount uint64) *BurnChecked { inst.Amount = &amount return inst } +// SetDecimals sets the "decimals" parameter. // Expected number of base 10 digits to the right of the decimal place. func (inst *BurnChecked) SetDecimals(decimals uint8) *BurnChecked { inst.Decimals = &decimals return inst } +// SetSourceAccount sets the "source" account. // The account to burn from. func (inst *BurnChecked) SetSourceAccount(source ag_solanago.PublicKey) *BurnChecked { inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() return inst } +// GetSourceAccount gets the "source" account. +// The account to burn from. func (inst *BurnChecked) GetSourceAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The token mint. func (inst *BurnChecked) SetMintAccount(mint ag_solanago.PublicKey) *BurnChecked { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() return inst } +// GetMintAccount gets the "mint" account. +// The token mint. func (inst *BurnChecked) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetOwnerAccount sets the "owner" account. // The account's owner/delegate. func (inst *BurnChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *BurnChecked { inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) return inst } +// GetOwnerAccount gets the "owner" account. +// The account's owner/delegate. func (inst *BurnChecked) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *BurnChecked) SetSignersAccount(signers ag_solanago.PublicKey) *BurnChecked { inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *BurnChecked) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/CloseAccount.go b/programs/token/CloseAccount.go index c5b34086..46c595a2 100644 --- a/programs/token/CloseAccount.go +++ b/programs/token/CloseAccount.go @@ -35,42 +35,54 @@ func NewCloseAccountInstructionBuilder() *CloseAccount { return nd } +// SetAccount sets the "account" account. // The account to close. func (inst *CloseAccount) SetAccount(account ag_solanago.PublicKey) *CloseAccount { inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() return inst } +// GetAccount gets the "account" account. +// The account to close. func (inst *CloseAccount) GetAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetDestinationAccount sets the "destination" account. // The destination account. func (inst *CloseAccount) SetDestinationAccount(destination ag_solanago.PublicKey) *CloseAccount { inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() return inst } +// GetDestinationAccount gets the "destination" account. +// The destination account. func (inst *CloseAccount) GetDestinationAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetOwnerAccount sets the "owner" account. // The account's owner. func (inst *CloseAccount) SetOwnerAccount(owner ag_solanago.PublicKey) *CloseAccount { inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) return inst } +// GetOwnerAccount gets the "owner" account. +// The account's owner. func (inst *CloseAccount) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *CloseAccount) SetSignersAccount(signers ag_solanago.PublicKey) *CloseAccount { inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *CloseAccount) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/FreezeAccount.go b/programs/token/FreezeAccount.go index 982cbe9b..824e592b 100644 --- a/programs/token/FreezeAccount.go +++ b/programs/token/FreezeAccount.go @@ -34,42 +34,54 @@ func NewFreezeAccountInstructionBuilder() *FreezeAccount { return nd } +// SetAccount sets the "account" account. // The account to freeze. func (inst *FreezeAccount) SetAccount(account ag_solanago.PublicKey) *FreezeAccount { inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() return inst } +// GetAccount gets the "account" account. +// The account to freeze. func (inst *FreezeAccount) GetAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The token mint. func (inst *FreezeAccount) SetMintAccount(mint ag_solanago.PublicKey) *FreezeAccount { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) return inst } +// GetMintAccount gets the "mint" account. +// The token mint. func (inst *FreezeAccount) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetAuthorityAccount sets the "authority" account. // The mint freeze authority. func (inst *FreezeAccount) SetAuthorityAccount(authority ag_solanago.PublicKey) *FreezeAccount { inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) return inst } +// GetAuthorityAccount gets the "authority" account. +// The mint freeze authority. func (inst *FreezeAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *FreezeAccount) SetSignersAccount(signers ag_solanago.PublicKey) *FreezeAccount { inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *FreezeAccount) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/InitializeAccount.go b/programs/token/InitializeAccount.go index b02e06e9..e22aa201 100644 --- a/programs/token/InitializeAccount.go +++ b/programs/token/InitializeAccount.go @@ -45,42 +45,54 @@ func NewInitializeAccountInstructionBuilder() *InitializeAccount { return nd } +// SetAccount sets the "account" account. // The account to initialize. func (inst *InitializeAccount) SetAccount(account ag_solanago.PublicKey) *InitializeAccount { inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() return inst } +// GetAccount gets the "account" account. +// The account to initialize. func (inst *InitializeAccount) GetAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The mint this account will be associated with. func (inst *InitializeAccount) SetMintAccount(mint ag_solanago.PublicKey) *InitializeAccount { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) return inst } +// GetMintAccount gets the "mint" account. +// The mint this account will be associated with. func (inst *InitializeAccount) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetOwnerAccount sets the "owner" account. // The new account's owner/multisignature. func (inst *InitializeAccount) SetOwnerAccount(owner ag_solanago.PublicKey) *InitializeAccount { inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) return inst } +// GetOwnerAccount gets the "owner" account. +// The new account's owner/multisignature. func (inst *InitializeAccount) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSysVarRentPubkeyAccount sets the "$(SysVarRentPubkey)" account. // Rent sysvar. func (inst *InitializeAccount) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeAccount { inst.AccountMetaSlice[3] = ag_solanago.Meta(SysVarRentPubkey) return inst } +// GetSysVarRentPubkeyAccount gets the "$(SysVarRentPubkey)" account. +// Rent sysvar. func (inst *InitializeAccount) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/InitializeAccount2.go b/programs/token/InitializeAccount2.go index 57fd0ab7..6e1fcb72 100644 --- a/programs/token/InitializeAccount2.go +++ b/programs/token/InitializeAccount2.go @@ -38,38 +38,48 @@ func NewInitializeAccount2InstructionBuilder() *InitializeAccount2 { return nd } +// SetOwner sets the "owner" parameter. // The new account's owner/multisignature. func (inst *InitializeAccount2) SetOwner(owner ag_solanago.PublicKey) *InitializeAccount2 { inst.Owner = &owner return inst } +// SetAccount sets the "account" account. // The account to initialize. func (inst *InitializeAccount2) SetAccount(account ag_solanago.PublicKey) *InitializeAccount2 { inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() return inst } +// GetAccount gets the "account" account. +// The account to initialize. func (inst *InitializeAccount2) GetAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The mint this account will be associated with. func (inst *InitializeAccount2) SetMintAccount(mint ag_solanago.PublicKey) *InitializeAccount2 { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) return inst } +// GetMintAccount gets the "mint" account. +// The mint this account will be associated with. func (inst *InitializeAccount2) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetSysVarRentPubkeyAccount sets the "$(SysVarRentPubkey)" account. // Rent sysvar. func (inst *InitializeAccount2) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeAccount2 { inst.AccountMetaSlice[2] = ag_solanago.Meta(SysVarRentPubkey) return inst } +// GetSysVarRentPubkeyAccount gets the "$(SysVarRentPubkey)" account. +// Rent sysvar. func (inst *InitializeAccount2) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } diff --git a/programs/token/InitializeAccount3.go b/programs/token/InitializeAccount3.go index 96ab3af6..4f55e41b 100644 --- a/programs/token/InitializeAccount3.go +++ b/programs/token/InitializeAccount3.go @@ -31,28 +31,35 @@ func NewInitializeAccount3InstructionBuilder() *InitializeAccount3 { return nd } +// SetOwner sets the "owner" parameter. // The new account's owner/multisignature. func (inst *InitializeAccount3) SetOwner(owner ag_solanago.PublicKey) *InitializeAccount3 { inst.Owner = &owner return inst } +// SetAccount sets the "account" account. // The account to initialize. func (inst *InitializeAccount3) SetAccount(account ag_solanago.PublicKey) *InitializeAccount3 { inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() return inst } +// GetAccount gets the "account" account. +// The account to initialize. func (inst *InitializeAccount3) GetAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The mint this account will be associated with. func (inst *InitializeAccount3) SetMintAccount(mint ag_solanago.PublicKey) *InitializeAccount3 { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) return inst } +// GetMintAccount gets the "mint" account. +// The mint this account will be associated with. func (inst *InitializeAccount3) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } diff --git a/programs/token/InitializeMint.go b/programs/token/InitializeMint.go index d9033811..a9b210f1 100644 --- a/programs/token/InitializeMint.go +++ b/programs/token/InitializeMint.go @@ -45,40 +45,49 @@ func NewInitializeMintInstructionBuilder() *InitializeMint { return nd } +// SetDecimals sets the "decimals" parameter. // Number of base 10 digits to the right of the decimal place. func (inst *InitializeMint) SetDecimals(decimals uint8) *InitializeMint { inst.Decimals = &decimals return inst } +// SetMintAuthority sets the "mint_authority" parameter. // The authority/multisignature to mint tokens. func (inst *InitializeMint) SetMintAuthority(mint_authority ag_solanago.PublicKey) *InitializeMint { inst.MintAuthority = &mint_authority return inst } +// SetFreezeAuthority sets the "freeze_authority" parameter. // The freeze authority/multisignature of the mint. func (inst *InitializeMint) SetFreezeAuthority(freeze_authority ag_solanago.PublicKey) *InitializeMint { inst.FreezeAuthority = &freeze_authority return inst } +// SetMintAccount sets the "mint" account. // The mint to initialize. func (inst *InitializeMint) SetMintAccount(mint ag_solanago.PublicKey) *InitializeMint { inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() return inst } +// GetMintAccount gets the "mint" account. +// The mint to initialize. func (inst *InitializeMint) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetSysVarRentPubkeyAccount sets the "$(SysVarRentPubkey)" account. // Rent sysvar. func (inst *InitializeMint) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeMint { inst.AccountMetaSlice[1] = ag_solanago.Meta(SysVarRentPubkey) return inst } +// GetSysVarRentPubkeyAccount gets the "$(SysVarRentPubkey)" account. +// Rent sysvar. func (inst *InitializeMint) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } diff --git a/programs/token/InitializeMint2.go b/programs/token/InitializeMint2.go index ca28ba20..4181cd09 100644 --- a/programs/token/InitializeMint2.go +++ b/programs/token/InitializeMint2.go @@ -34,30 +34,36 @@ func NewInitializeMint2InstructionBuilder() *InitializeMint2 { return nd } +// SetDecimals sets the "decimals" parameter. // Number of base 10 digits to the right of the decimal place. func (inst *InitializeMint2) SetDecimals(decimals uint8) *InitializeMint2 { inst.Decimals = &decimals return inst } +// SetMintAuthority sets the "mint_authority" parameter. // The authority/multisignature to mint tokens. func (inst *InitializeMint2) SetMintAuthority(mint_authority ag_solanago.PublicKey) *InitializeMint2 { inst.MintAuthority = &mint_authority return inst } +// SetFreezeAuthority sets the "freeze_authority" parameter. // The freeze authority/multisignature of the mint. func (inst *InitializeMint2) SetFreezeAuthority(freeze_authority ag_solanago.PublicKey) *InitializeMint2 { inst.FreezeAuthority = &freeze_authority return inst } +// SetMintAccount sets the "mint" account. // The mint to initialize. func (inst *InitializeMint2) SetMintAccount(mint ag_solanago.PublicKey) *InitializeMint2 { inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() return inst } +// GetMintAccount gets the "mint" account. +// The mint to initialize. func (inst *InitializeMint2) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } diff --git a/programs/token/InitializeMultisig2.go b/programs/token/InitializeMultisig2.go index 469ad8ec..03db2138 100644 --- a/programs/token/InitializeMultisig2.go +++ b/programs/token/InitializeMultisig2.go @@ -31,28 +31,35 @@ func NewInitializeMultisig2InstructionBuilder() *InitializeMultisig2 { return nd } +// SetM sets the "m" parameter. // The number of signers (M) required to validate this multisignature account. func (inst *InitializeMultisig2) SetM(m uint8) *InitializeMultisig2 { inst.M = &m return inst } +// SetAccount sets the "account" account. // The multisignature account to initialize. func (inst *InitializeMultisig2) SetAccount(account ag_solanago.PublicKey) *InitializeMultisig2 { inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() return inst } +// GetAccount gets the "account" account. +// The multisignature account to initialize. func (inst *InitializeMultisig2) GetAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetSignersAccount sets the "signers" account. // The signer accounts, must equal to N where 1 <= N <= 11. func (inst *InitializeMultisig2) SetSignersAccount(signers ag_solanago.PublicKey) *InitializeMultisig2 { inst.AccountMetaSlice[1] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// The signer accounts, must equal to N where 1 <= N <= 11. func (inst *InitializeMultisig2) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } diff --git a/programs/token/MintTo.go b/programs/token/MintTo.go index 01156ef0..627c5e44 100644 --- a/programs/token/MintTo.go +++ b/programs/token/MintTo.go @@ -38,48 +38,61 @@ func NewMintToInstructionBuilder() *MintTo { return nd } +// SetAmount sets the "amount" parameter. // The amount of new tokens to mint. func (inst *MintTo) SetAmount(amount uint64) *MintTo { inst.Amount = &amount return inst } +// SetMintAccount sets the "mint" account. // The mint. func (inst *MintTo) SetMintAccount(mint ag_solanago.PublicKey) *MintTo { inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() return inst } +// GetMintAccount gets the "mint" account. +// The mint. func (inst *MintTo) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetDestinationAccount sets the "destination" account. // The account to mint tokens to. func (inst *MintTo) SetDestinationAccount(destination ag_solanago.PublicKey) *MintTo { inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() return inst } +// GetDestinationAccount gets the "destination" account. +// The account to mint tokens to. func (inst *MintTo) GetDestinationAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetAuthorityAccount sets the "authority" account. // The mint's minting authority. func (inst *MintTo) SetAuthorityAccount(authority ag_solanago.PublicKey) *MintTo { inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) return inst } +// GetAuthorityAccount gets the "authority" account. +// The mint's minting authority. func (inst *MintTo) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *MintTo) SetSignersAccount(signers ag_solanago.PublicKey) *MintTo { inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *MintTo) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/MintToChecked.go b/programs/token/MintToChecked.go index e7d4b580..0d8e4ce0 100644 --- a/programs/token/MintToChecked.go +++ b/programs/token/MintToChecked.go @@ -44,54 +44,68 @@ func NewMintToCheckedInstructionBuilder() *MintToChecked { return nd } +// SetAmount sets the "amount" parameter. // The amount of new tokens to mint. func (inst *MintToChecked) SetAmount(amount uint64) *MintToChecked { inst.Amount = &amount return inst } +// SetDecimals sets the "decimals" parameter. // Expected number of base 10 digits to the right of the decimal place. func (inst *MintToChecked) SetDecimals(decimals uint8) *MintToChecked { inst.Decimals = &decimals return inst } +// SetMintAccount sets the "mint" account. // The mint. func (inst *MintToChecked) SetMintAccount(mint ag_solanago.PublicKey) *MintToChecked { inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() return inst } +// GetMintAccount gets the "mint" account. +// The mint. func (inst *MintToChecked) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetDestinationAccount sets the "destination" account. // The account to mint tokens to. func (inst *MintToChecked) SetDestinationAccount(destination ag_solanago.PublicKey) *MintToChecked { inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() return inst } +// GetDestinationAccount gets the "destination" account. +// The account to mint tokens to. func (inst *MintToChecked) GetDestinationAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetAuthorityAccount sets the "authority" account. // The mint's minting authority. func (inst *MintToChecked) SetAuthorityAccount(authority ag_solanago.PublicKey) *MintToChecked { inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) return inst } +// GetAuthorityAccount gets the "authority" account. +// The mint's minting authority. func (inst *MintToChecked) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *MintToChecked) SetSignersAccount(signers ag_solanago.PublicKey) *MintToChecked { inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *MintToChecked) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/Revoke.go b/programs/token/Revoke.go index 13a33c28..088677fe 100644 --- a/programs/token/Revoke.go +++ b/programs/token/Revoke.go @@ -31,32 +31,41 @@ func NewRevokeInstructionBuilder() *Revoke { return nd } +// SetSourceAccount sets the "source" account. // The source account. func (inst *Revoke) SetSourceAccount(source ag_solanago.PublicKey) *Revoke { inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() return inst } +// GetSourceAccount gets the "source" account. +// The source account. func (inst *Revoke) GetSourceAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetOwnerAccount sets the "owner" account. // The source account's owner. func (inst *Revoke) SetOwnerAccount(owner ag_solanago.PublicKey) *Revoke { inst.AccountMetaSlice[1] = ag_solanago.Meta(owner) return inst } +// GetOwnerAccount gets the "owner" account. +// The source account's owner. func (inst *Revoke) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *Revoke) SetSignersAccount(signers ag_solanago.PublicKey) *Revoke { inst.AccountMetaSlice[2] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *Revoke) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } diff --git a/programs/token/SetAuthority.go b/programs/token/SetAuthority.go index 939fc8cb..58fccbe8 100644 --- a/programs/token/SetAuthority.go +++ b/programs/token/SetAuthority.go @@ -37,44 +37,55 @@ func NewSetAuthorityInstructionBuilder() *SetAuthority { return nd } +// SetAuthorityType sets the "authority_type" parameter. // The type of authority to update. func (inst *SetAuthority) SetAuthorityType(authority_type AuthorityType) *SetAuthority { inst.AuthorityType = &authority_type return inst } +// SetNewAuthority sets the "new_authority" parameter. // The new authority. func (inst *SetAuthority) SetNewAuthority(new_authority ag_solanago.PublicKey) *SetAuthority { inst.NewAuthority = &new_authority return inst } +// SetSubjectAccount sets the "subject" account. // The mint or account to change the authority of. func (inst *SetAuthority) SetSubjectAccount(subject ag_solanago.PublicKey) *SetAuthority { inst.AccountMetaSlice[0] = ag_solanago.Meta(subject).WRITE() return inst } +// GetSubjectAccount gets the "subject" account. +// The mint or account to change the authority of. func (inst *SetAuthority) GetSubjectAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetAuthorityAccount sets the "authority" account. // The current authority of the mint or account. func (inst *SetAuthority) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetAuthority { inst.AccountMetaSlice[1] = ag_solanago.Meta(authority) return inst } +// GetAuthorityAccount gets the "authority" account. +// The current authority of the mint or account. func (inst *SetAuthority) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *SetAuthority) SetSignersAccount(signers ag_solanago.PublicKey) *SetAuthority { inst.AccountMetaSlice[2] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *SetAuthority) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } diff --git a/programs/token/SyncNative.go b/programs/token/SyncNative.go index b4edebb1..c7c91205 100644 --- a/programs/token/SyncNative.go +++ b/programs/token/SyncNative.go @@ -29,12 +29,15 @@ func NewSyncNativeInstructionBuilder() *SyncNative { return nd } +// SetTokenAccount sets the "tokenAccount" account. // The native token account to sync with its underlying lamports. func (inst *SyncNative) SetTokenAccount(tokenAccount ag_solanago.PublicKey) *SyncNative { inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAccount).WRITE() return inst } +// GetTokenAccount gets the "tokenAccount" account. +// The native token account to sync with its underlying lamports. func (inst *SyncNative) GetTokenAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } diff --git a/programs/token/ThawAccount.go b/programs/token/ThawAccount.go index b32c72d7..f5534fee 100644 --- a/programs/token/ThawAccount.go +++ b/programs/token/ThawAccount.go @@ -34,42 +34,54 @@ func NewThawAccountInstructionBuilder() *ThawAccount { return nd } +// SetAccount sets the "account" account. // The account to thaw. func (inst *ThawAccount) SetAccount(account ag_solanago.PublicKey) *ThawAccount { inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() return inst } +// GetAccount gets the "account" account. +// The account to thaw. func (inst *ThawAccount) GetAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The token mint. func (inst *ThawAccount) SetMintAccount(mint ag_solanago.PublicKey) *ThawAccount { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) return inst } +// GetMintAccount gets the "mint" account. +// The token mint. func (inst *ThawAccount) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetAuthorityAccount sets the "authority" account. // The mint freeze authority. func (inst *ThawAccount) SetAuthorityAccount(authority ag_solanago.PublicKey) *ThawAccount { inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) return inst } +// GetAuthorityAccount gets the "authority" account. +// The mint freeze authority. func (inst *ThawAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *ThawAccount) SetSignersAccount(signers ag_solanago.PublicKey) *ThawAccount { inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *ThawAccount) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } diff --git a/programs/token/TransferChecked.go b/programs/token/TransferChecked.go index 526840b3..b0bccb72 100644 --- a/programs/token/TransferChecked.go +++ b/programs/token/TransferChecked.go @@ -50,64 +50,81 @@ func NewTransferCheckedInstructionBuilder() *TransferChecked { return nd } +// SetAmount sets the "amount" parameter. // The amount of tokens to transfer. func (inst *TransferChecked) SetAmount(amount uint64) *TransferChecked { inst.Amount = &amount return inst } +// SetDecimals sets the "decimals" parameter. // Expected number of base 10 digits to the right of the decimal place. func (inst *TransferChecked) SetDecimals(decimals uint8) *TransferChecked { inst.Decimals = &decimals return inst } +// SetSourceAccount sets the "source" account. // The source account. func (inst *TransferChecked) SetSourceAccount(source ag_solanago.PublicKey) *TransferChecked { inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() return inst } +// GetSourceAccount gets the "source" account. +// The source account. func (inst *TransferChecked) GetSourceAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetMintAccount sets the "mint" account. // The token mint. func (inst *TransferChecked) SetMintAccount(mint ag_solanago.PublicKey) *TransferChecked { inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) return inst } +// GetMintAccount gets the "mint" account. +// The token mint. func (inst *TransferChecked) GetMintAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetDestinationAccount sets the "destination" account. // The destination account. func (inst *TransferChecked) SetDestinationAccount(destination ag_solanago.PublicKey) *TransferChecked { inst.AccountMetaSlice[2] = ag_solanago.Meta(destination).WRITE() return inst } +// GetDestinationAccount gets the "destination" account. +// The destination account. func (inst *TransferChecked) GetDestinationAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// SetOwnerAccount sets the "owner" account. // The source account's owner/delegate. func (inst *TransferChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *TransferChecked { inst.AccountMetaSlice[3] = ag_solanago.Meta(owner) return inst } +// GetOwnerAccount gets the "owner" account. +// The source account's owner/delegate. func (inst *TransferChecked) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } +// SetSignersAccount sets the "signers" account. // M signer accounts. func (inst *TransferChecked) SetSignersAccount(signers ag_solanago.PublicKey) *TransferChecked { inst.AccountMetaSlice[4] = ag_solanago.Meta(signers).SIGNER() return inst } +// GetSignersAccount gets the "signers" account. +// M signer accounts. func (inst *TransferChecked) GetSignersAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[4] } From d7fb81af0855ce30af314664011ed58062600ebc Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 13:51:24 +0200 Subject: [PATCH 04/24] Handle signers --- programs/token/InitializeMultisig.go | 22 +++++++++-- programs/token/Transfer.go | 55 ++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/programs/token/InitializeMultisig.go b/programs/token/InitializeMultisig.go index b0ff2cda..f4c1276e 100644 --- a/programs/token/InitializeMultisig.go +++ b/programs/token/InitializeMultisig.go @@ -48,6 +48,7 @@ func NewInitializeMultisigInstructionBuilder() *InitializeMultisig { return nd } +// SetM sets the "m" parameter. // The number of signers (M) required to validate this multisignature // account. func (inst *InitializeMultisig) SetM(m uint8) *InitializeMultisig { @@ -55,34 +56,44 @@ func (inst *InitializeMultisig) SetM(m uint8) *InitializeMultisig { return inst } +// SetAccount sets the "account" account. // The multisignature account to initialize. func (inst *InitializeMultisig) SetAccount(account ag_solanago.PublicKey) *InitializeMultisig { inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() return inst } +// GetAccount gets the "account" account. +// The multisignature account to initialize. func (inst *InitializeMultisig) GetAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetSysVarRentPubkeyAccount sets the "$(SysVarRentPubkey)" account. // Rent sysvar. func (inst *InitializeMultisig) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeMultisig { inst.AccountMetaSlice[1] = ag_solanago.Meta(SysVarRentPubkey) return inst } +// GetSysVarRentPubkeyAccount gets the "$(SysVarRentPubkey)" account. +// Rent sysvar. func (inst *InitializeMultisig) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetSigners sets the "signers" accounts. // ..2+N The signer accounts, must equal to N where 1 <= N <=11 func (inst *InitializeMultisig) SetSigners(signers ...ag_solanago.PublicKey) *InitializeMultisig { + inst.AccountMetaSlice = inst.AccountMetaSlice[:2] for _, signer := range signers { inst.AccountMetaSlice = append(inst.AccountMetaSlice, ag_solanago.Meta(signer).SIGNER()) } return inst } +// GetSignersAccount gets the "signers" account. +// ..2+N The signer accounts, must equal to N where 1 <= N <=11 func (inst *InitializeMultisig) GetSigners() []*ag_solanago.AccountMeta { if len(inst.AccountMetaSlice) == 2 { return nil @@ -124,7 +135,7 @@ func (inst *InitializeMultisig) Validate() error { return fmt.Errorf("accounts.SysVarRentPubkey is not set") } if len(inst.AccountMetaSlice) == 2 { - return fmt.Errorf("Signers are not set") + return fmt.Errorf("accounts.Signers is not set") } } return nil @@ -147,7 +158,10 @@ func (inst *InitializeMultisig) EncodeToTree(parent ag_treeout.Branches) { instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[2])) + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.AccountMetaSlice[2:]))) + for i, v := range inst.AccountMetaSlice[2:] { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -177,10 +191,10 @@ func NewInitializeMultisigInstruction( // Accounts: account ag_solanago.PublicKey, SysVarRentPubkey ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *InitializeMultisig { + signers []ag_solanago.PublicKey) *InitializeMultisig { return NewInitializeMultisigInstructionBuilder(). SetM(m). SetAccount(account). SetSysVarRentPubkeyAccount(SysVarRentPubkey). - SetSignersAccount(signers) + SetSigners(signers...) } diff --git a/programs/token/Transfer.go b/programs/token/Transfer.go index a5512b56..cf1a3572 100644 --- a/programs/token/Transfer.go +++ b/programs/token/Transfer.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "errors" "fmt" + ag_binary "github.com/dfuse-io/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -27,7 +28,7 @@ type Transfer struct { // [2] = [] owner // ··········· The source account owner/delegate. // - // [3] = [SIGNER] signers + // [3...] = [SIGNER] signers // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } @@ -35,55 +36,75 @@ type Transfer struct { // NewTransferInstructionBuilder creates a new `Transfer` instruction builder. func NewTransferInstructionBuilder() *Transfer { nd := &Transfer{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } +// SetAmount sets the "amount" parameter. // The amount of tokens to transfer. func (inst *Transfer) SetAmount(amount uint64) *Transfer { inst.Amount = &amount return inst } +// SetSourceAccount sets the "source" account. // The source account. func (inst *Transfer) SetSourceAccount(source ag_solanago.PublicKey) *Transfer { inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() return inst } +// GetSourceAccount gets the "source" account. +// The source account. func (inst *Transfer) GetSourceAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[0] } +// SetDestinationAccount sets the "destination" account. // The destination account. func (inst *Transfer) SetDestinationAccount(destination ag_solanago.PublicKey) *Transfer { inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() return inst } +// GetDestinationAccount gets the "destination" account. +// The destination account. func (inst *Transfer) GetDestinationAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } +// SetOwnerAccount sets the "owner" account. // The source account owner/delegate. -func (inst *Transfer) SetOwnerAccount(owner ag_solanago.PublicKey) *Transfer { - inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) +func (inst *Transfer) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *Transfer { + if len(multisigSigners) > 0 { + // Set owner; + inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) + // Reset signers: + inst.AccountMetaSlice = inst.AccountMetaSlice[:3] + // Add signers: + for _, signer := range multisigSigners { + inst.AccountMetaSlice = append(inst.AccountMetaSlice, ag_solanago.Meta(signer).SIGNER()) + } + } else { + inst.AccountMetaSlice[2] = ag_solanago.Meta(owner).SIGNER() + } return inst } +// GetOwnerAccount gets the "owner" account. +// The source account owner/delegate. func (inst *Transfer) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } +// GetSigners gets the "signers" accounts. // M signer accounts. -func (inst *Transfer) SetSignersAccount(signers ag_solanago.PublicKey) *Transfer { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -func (inst *Transfer) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] +func (inst *Transfer) GetSigners() []*ag_solanago.AccountMeta { + if len(inst.AccountMetaSlice) == 3 { + return nil + } + return inst.AccountMetaSlice[3:] } func (inst Transfer) Build() *Instruction { @@ -122,7 +143,7 @@ func (inst *Transfer) Validate() error { if inst.AccountMetaSlice[2] == nil { return fmt.Errorf("accounts.Owner is not set") } - if inst.AccountMetaSlice[3] == nil { + if !inst.AccountMetaSlice[2].IsSigner && len(inst.AccountMetaSlice) == 3 { return fmt.Errorf("accounts.Signers is not set") } } @@ -147,7 +168,10 @@ func (inst *Transfer) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.AccountMetaSlice[3:]))) + for i, v := range inst.AccountMetaSlice[3:] { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -178,11 +202,10 @@ func NewTransferInstruction( source ag_solanago.PublicKey, destination ag_solanago.PublicKey, owner ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *Transfer { + signers []ag_solanago.PublicKey) *Transfer { return NewTransferInstructionBuilder(). SetAmount(amount). SetSourceAccount(source). SetDestinationAccount(destination). - SetOwnerAccount(owner). - SetSignersAccount(signers) + SetOwnerAccount(owner, signers...) } From 587f1e6894af2f1d03463da19d20a7ae8142e518 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 15:11:00 +0200 Subject: [PATCH 05/24] Add utility methods to AccountMetaSlice --- account.go | 36 +++++++++++++++++++++++++++++++ account_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/account.go b/account.go index fdb8485c..a37ddf24 100644 --- a/account.go +++ b/account.go @@ -110,3 +110,39 @@ func (slice AccountMetaSlice) GetSigners() []*AccountMeta { } return signers } + +func (slice AccountMetaSlice) Len() int { + return len(slice) +} + +func (slice AccountMetaSlice) SplitFrom(index int) (AccountMetaSlice, AccountMetaSlice) { + if index < 0 { + panic("negative index") + } + if index == 0 { + return AccountMetaSlice{}, slice + } + if index > len(slice)-1 { + return slice, AccountMetaSlice{} + } + + firstLen, secondLen := calcSplitAtLengths(len(slice), index) + + first := make(AccountMetaSlice, firstLen) + copy(first, slice[:index]) + + second := make(AccountMetaSlice, secondLen) + copy(second, slice[index:]) + + return first, second +} + +func calcSplitAtLengths(total int, index int) (int, int) { + if index == 0 { + return 0, total + } + if index > total-1 { + return total, 0 + } + return index, total - index +} diff --git a/account_test.go b/account_test.go index 1b4361a4..726a4571 100644 --- a/account_test.go +++ b/account_test.go @@ -140,3 +140,59 @@ func TestMeta(t *testing.T) { require.True(t, meta.IsSigner) require.True(t, meta.IsWritable) } + +func TestSplitFrom(t *testing.T) { + slice := make(AccountMetaSlice, 0) + slice = append(slice, Meta(BPFLoaderDeprecatedProgramID)) + slice = append(slice, Meta(SPLTokenProgramID)) + slice = append(slice, Meta(SPLTokenLendingProgramID)) + slice = append(slice, Meta(SPLAssociatedTokenAccountProgramID)) + slice = append(slice, Meta(SPLMemoProgramID)) + + require.Len(t, slice, 5) + + { + part1, part2 := slice.SplitFrom(0) + require.Len(t, part1, 0) + require.Len(t, part2, 5) + } + { + part1, part2 := slice.SplitFrom(1) + require.Len(t, part1, 1) + require.Len(t, part2, 4) + } + { + part1, part2 := slice.SplitFrom(2) + require.Len(t, part1, 2) + require.Len(t, part2, 3) + } + { + part1, part2 := slice.SplitFrom(3) + require.Len(t, part1, 3) + require.Len(t, part2, 2) + } + { + part1, part2 := slice.SplitFrom(4) + require.Len(t, part1, 4) + require.Len(t, part2, 1) + } + { + part1, part2 := slice.SplitFrom(5) + require.Len(t, part1, 5) + require.Len(t, part2, 0) + } + { + part1, part2 := slice.SplitFrom(6) + require.Len(t, part1, 5) + require.Len(t, part2, 0) + } + { + part1, part2 := slice.SplitFrom(10000) + require.Len(t, part1, 5) + require.Len(t, part2, 0) + } + require.Panics(t, + func() { + slice.SplitFrom(-1) + }) +} From c366000bd7ac3085baa6789db03f2c4144aa5fe4 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 15:22:42 +0200 Subject: [PATCH 06/24] Add more tests for AccountMetaSlice.SplitFrom --- account_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/account_test.go b/account_test.go index 726a4571..0379daf8 100644 --- a/account_test.go +++ b/account_test.go @@ -160,6 +160,11 @@ func TestSplitFrom(t *testing.T) { part1, part2 := slice.SplitFrom(1) require.Len(t, part1, 1) require.Len(t, part2, 4) + require.Equal(t, Meta(BPFLoaderDeprecatedProgramID), part1[0]) + require.Equal(t, Meta(SPLTokenProgramID), part2[0]) + require.Equal(t, Meta(SPLTokenLendingProgramID), part2[1]) + require.Equal(t, Meta(SPLAssociatedTokenAccountProgramID), part2[2]) + require.Equal(t, Meta(SPLMemoProgramID), part2[3]) } { part1, part2 := slice.SplitFrom(2) From e3feb5237cbea8835f2ccddd51852939eccd1a6e Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 16:13:57 +0200 Subject: [PATCH 07/24] token: refactor InitializeMultisig, Transfer instructions --- programs/token/InitializeMultisig.go | 63 ++++++++++-------- programs/token/InitializeMultisig_test.go | 11 ++-- programs/token/Transfer.go | 79 ++++++++++++----------- programs/token/Transfer_test.go | 11 ++-- programs/token/instructions.go | 2 + 5 files changed, 92 insertions(+), 74 deletions(-) diff --git a/programs/token/InitializeMultisig.go b/programs/token/InitializeMultisig.go index f4c1276e..bc422197 100644 --- a/programs/token/InitializeMultisig.go +++ b/programs/token/InitializeMultisig.go @@ -36,15 +36,28 @@ type InitializeMultisig struct { // // [2...] = [SIGNER] signers // ··········· ..2+N The signer accounts, must equal to N where 1 <= N <=11 - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *InitializeMultisig) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(2) + return nil +} + +func (slice InitializeMultisig) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewInitializeMultisigInstructionBuilder creates a new `InitializeMultisig` instruction builder. func NewInitializeMultisigInstructionBuilder() *InitializeMultisig { nd := &InitializeMultisig{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + Accounts: make(ag_solanago.AccountMetaSlice, 2), + Signers: make(ag_solanago.AccountMetaSlice, 0), } - nd.AccountMetaSlice[1] = ag_solanago.Meta(ag_solanago.SysVarRentPubkey) + nd.Accounts[1] = ag_solanago.Meta(ag_solanago.SysVarRentPubkey) return nd } @@ -59,48 +72,38 @@ func (inst *InitializeMultisig) SetM(m uint8) *InitializeMultisig { // SetAccount sets the "account" account. // The multisignature account to initialize. func (inst *InitializeMultisig) SetAccount(account ag_solanago.PublicKey) *InitializeMultisig { - inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + inst.Accounts[0] = ag_solanago.Meta(account).WRITE() return inst } // GetAccount gets the "account" account. // The multisignature account to initialize. func (inst *InitializeMultisig) GetAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetSysVarRentPubkeyAccount sets the "$(SysVarRentPubkey)" account. // Rent sysvar. func (inst *InitializeMultisig) SetSysVarRentPubkeyAccount(SysVarRentPubkey ag_solanago.PublicKey) *InitializeMultisig { - inst.AccountMetaSlice[1] = ag_solanago.Meta(SysVarRentPubkey) + inst.Accounts[1] = ag_solanago.Meta(SysVarRentPubkey) return inst } // GetSysVarRentPubkeyAccount gets the "$(SysVarRentPubkey)" account. // Rent sysvar. func (inst *InitializeMultisig) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } -// SetSigners sets the "signers" accounts. +// AddSigners adds the "signers" accounts. // ..2+N The signer accounts, must equal to N where 1 <= N <=11 -func (inst *InitializeMultisig) SetSigners(signers ...ag_solanago.PublicKey) *InitializeMultisig { - inst.AccountMetaSlice = inst.AccountMetaSlice[:2] +func (inst *InitializeMultisig) AddSigners(signers ...ag_solanago.PublicKey) *InitializeMultisig { for _, signer := range signers { - inst.AccountMetaSlice = append(inst.AccountMetaSlice, ag_solanago.Meta(signer).SIGNER()) + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) } return inst } -// GetSignersAccount gets the "signers" account. -// ..2+N The signer accounts, must equal to N where 1 <= N <=11 -func (inst *InitializeMultisig) GetSigners() []*ag_solanago.AccountMeta { - if len(inst.AccountMetaSlice) == 2 { - return nil - } - return inst.AccountMetaSlice[2:] -} - func (inst InitializeMultisig) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -128,15 +131,18 @@ func (inst *InitializeMultisig) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return fmt.Errorf("accounts.Account is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return fmt.Errorf("accounts.SysVarRentPubkey is not set") } - if len(inst.AccountMetaSlice) == 2 { + if len(inst.Signers) == 0 { return fmt.Errorf("accounts.Signers is not set") } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -156,10 +162,11 @@ func (inst *InitializeMultisig) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[1])) - signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.AccountMetaSlice[2:]))) - for i, v := range inst.AccountMetaSlice[2:] { + accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.Accounts[1])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) } }) @@ -196,5 +203,5 @@ func NewInitializeMultisigInstruction( SetM(m). SetAccount(account). SetSysVarRentPubkeyAccount(SysVarRentPubkey). - SetSigners(signers...) + AddSigners(signers...) } diff --git a/programs/token/InitializeMultisig_test.go b/programs/token/InitializeMultisig_test.go index 90ae0184..de6fce44 100644 --- a/programs/token/InitializeMultisig_test.go +++ b/programs/token/InitializeMultisig_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_InitializeMultisig(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_InitializeMultisig(t *testing.T) { { params := new(InitializeMultisig) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(InitializeMultisig) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + got.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/Transfer.go b/programs/token/Transfer.go index cf1a3572..7fa1e7d1 100644 --- a/programs/token/Transfer.go +++ b/programs/token/Transfer.go @@ -30,13 +30,26 @@ type Transfer struct { // // [3...] = [SIGNER] signers // ··········· M signer accounts. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *Transfer) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice Transfer) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewTransferInstructionBuilder creates a new `Transfer` instruction builder. func NewTransferInstructionBuilder() *Transfer { nd := &Transfer{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -51,43 +64,38 @@ func (inst *Transfer) SetAmount(amount uint64) *Transfer { // SetSourceAccount sets the "source" account. // The source account. func (inst *Transfer) SetSourceAccount(source ag_solanago.PublicKey) *Transfer { - inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + inst.Accounts[0] = ag_solanago.Meta(source).WRITE() return inst } // GetSourceAccount gets the "source" account. // The source account. func (inst *Transfer) GetSourceAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetDestinationAccount sets the "destination" account. // The destination account. func (inst *Transfer) SetDestinationAccount(destination ag_solanago.PublicKey) *Transfer { - inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() + inst.Accounts[1] = ag_solanago.Meta(destination).WRITE() return inst } // GetDestinationAccount gets the "destination" account. // The destination account. func (inst *Transfer) GetDestinationAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetOwnerAccount sets the "owner" account. // The source account owner/delegate. func (inst *Transfer) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *Transfer { - if len(multisigSigners) > 0 { - // Set owner; - inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) - // Reset signers: - inst.AccountMetaSlice = inst.AccountMetaSlice[:3] - // Add signers: - for _, signer := range multisigSigners { - inst.AccountMetaSlice = append(inst.AccountMetaSlice, ag_solanago.Meta(signer).SIGNER()) - } - } else { - inst.AccountMetaSlice[2] = ag_solanago.Meta(owner).SIGNER() + inst.Accounts[2] = ag_solanago.Meta(owner) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) } return inst } @@ -95,16 +103,7 @@ func (inst *Transfer) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigne // GetOwnerAccount gets the "owner" account. // The source account owner/delegate. func (inst *Transfer) GetOwnerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// GetSigners gets the "signers" accounts. -// M signer accounts. -func (inst *Transfer) GetSigners() []*ag_solanago.AccountMeta { - if len(inst.AccountMetaSlice) == 3 { - return nil - } - return inst.AccountMetaSlice[3:] + return inst.Accounts[2] } func (inst Transfer) Build() *Instruction { @@ -134,18 +133,21 @@ func (inst *Transfer) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return fmt.Errorf("accounts.Source is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return fmt.Errorf("accounts.Destination is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return fmt.Errorf("accounts.Owner is not set") } - if !inst.AccountMetaSlice[2].IsSigner && len(inst.AccountMetaSlice) == 3 { + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { return fmt.Errorf("accounts.Signers is not set") } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -165,11 +167,12 @@ func (inst *Transfer) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) - signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.AccountMetaSlice[3:]))) - for i, v := range inst.AccountMetaSlice[3:] { + accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) } }) @@ -202,10 +205,10 @@ func NewTransferInstruction( source ag_solanago.PublicKey, destination ag_solanago.PublicKey, owner ag_solanago.PublicKey, - signers []ag_solanago.PublicKey) *Transfer { + multisigSigners []ag_solanago.PublicKey) *Transfer { return NewTransferInstructionBuilder(). SetAmount(amount). SetSourceAccount(source). SetDestinationAccount(destination). - SetOwnerAccount(owner, signers...) + SetOwnerAccount(owner, multisigSigners...) } diff --git a/programs/token/Transfer_test.go b/programs/token/Transfer_test.go index 959962c9..db226013 100644 --- a/programs/token/Transfer_test.go +++ b/programs/token/Transfer_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/google/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_Transfer(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_Transfer(t *testing.T) { { params := new(Transfer) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(Transfer) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + got.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/instructions.go b/programs/token/instructions.go index 8e7f3746..da805b86 100644 --- a/programs/token/instructions.go +++ b/programs/token/instructions.go @@ -15,6 +15,8 @@ import ( ag_treeout "github.com/gagliardetto/treeout" ) +const MAX_SIGNERS = 11 + var ProgramID ag_solanago.PublicKey = ag_solanago.SPLTokenProgramID func SetProgramID(pubkey ag_solanago.PublicKey) { From ee20853c742343b0d4646fd4f7fcb4eba837f612 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 16:51:19 +0200 Subject: [PATCH 08/24] Upgrade token prog code --- go.mod | 2 ++ go.sum | 4 +++ programs/token/Approve.go | 37 ++++---------------- programs/token/ApproveChecked.go | 39 +++++----------------- programs/token/ApproveChecked_test.go | 2 +- programs/token/Approve_test.go | 2 +- programs/token/Burn.go | 37 ++++---------------- programs/token/BurnChecked.go | 37 ++++---------------- programs/token/BurnChecked_test.go | 2 +- programs/token/Burn_test.go | 2 +- programs/token/CloseAccount.go | 38 +++++---------------- programs/token/CloseAccount_test.go | 2 +- programs/token/FreezeAccount.go | 38 +++++---------------- programs/token/FreezeAccount_test.go | 2 +- programs/token/InitializeAccount.go | 12 +++---- programs/token/InitializeAccount2.go | 9 +++-- programs/token/InitializeAccount2_test.go | 2 +- programs/token/InitializeAccount3.go | 7 ++-- programs/token/InitializeAccount3_test.go | 2 +- programs/token/InitializeAccount_test.go | 2 +- programs/token/InitializeMint.go | 7 ++-- programs/token/InitializeMint2.go | 5 ++- programs/token/InitializeMint2_test.go | 2 +- programs/token/InitializeMint_test.go | 2 +- programs/token/InitializeMultisig.go | 2 +- programs/token/InitializeMultisig2.go | 7 ++-- programs/token/InitializeMultisig2_test.go | 2 +- programs/token/InitializeMultisig_test.go | 2 +- programs/token/MintTo.go | 37 ++++---------------- programs/token/MintToChecked.go | 37 ++++---------------- programs/token/MintToChecked_test.go | 2 +- programs/token/MintTo_test.go | 2 +- programs/token/Revoke.go | 36 ++++---------------- programs/token/Revoke_test.go | 2 +- programs/token/SetAuthority.go | 35 ++++--------------- programs/token/SetAuthority_test.go | 2 +- programs/token/SyncNative.go | 6 ++-- programs/token/SyncNative_test.go | 2 +- programs/token/ThawAccount.go | 38 +++++---------------- programs/token/ThawAccount_test.go | 2 +- programs/token/Transfer.go | 2 +- programs/token/TransferChecked.go | 39 +++++----------------- programs/token/TransferChecked_test.go | 2 +- programs/token/Transfer_test.go | 2 +- programs/token/instructions.go | 2 +- programs/token/testing_utils.go | 2 +- programs/token/types.go | 2 +- 47 files changed, 144 insertions(+), 415 deletions(-) diff --git a/go.mod b/go.mod index a93b60d0..c80fc1bc 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,8 @@ require ( github.com/dfuse-io/binary v0.0.0-20210216024852-4ae6830a495d github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 github.com/fatih/color v1.7.0 + github.com/gagliardetto/binary v0.4.1 // indirect + github.com/gagliardetto/gofuzz v1.2.2 // indirect github.com/gagliardetto/treeout v0.1.2 github.com/google/go-cmp v0.5.1 github.com/google/gofuzz v1.0.0 diff --git a/go.sum b/go.sum index 803f1ae7..224dbd1a 100644 --- a/go.sum +++ b/go.sum @@ -91,8 +91,12 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gagliardetto/binary v0.4.0 h1:dxLndYArHtdZYbLYwnpLY86mlAa9gWgxG2zSDPFINjM= github.com/gagliardetto/binary v0.4.0/go.mod h1:55fxN6CKhVnsBhSr3Hmyn7i2igseIzN9/NC+gHvv42k= +github.com/gagliardetto/binary v0.4.1 h1:3HXeBOfmR2HHIrF1YBnoqgFKQBtN8+rWA770KyXmU0U= +github.com/gagliardetto/binary v0.4.1/go.mod h1:peJR9PvwamL4YOh1nHWCPLry2VEfeeD1ADvewka7HnQ= github.com/gagliardetto/gofuzz v1.2.1 h1:fHBiDgCYYb8kBRqyI+bhU59/IKATHArFUAY3iVUrdPA= github.com/gagliardetto/gofuzz v1.2.1/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= +github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= github.com/gagliardetto/treeout v0.1.2 h1:WXO7LDJTwINO37OQfNlf7s095Z1bAiwN2ACaZQic33Q= github.com/gagliardetto/treeout v0.1.2/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= diff --git a/programs/token/Approve.go b/programs/token/Approve.go index 889302a4..e42804fc 100644 --- a/programs/token/Approve.go +++ b/programs/token/Approve.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -24,16 +23,13 @@ type Approve struct { // // [2] = [] owner // ··········· The source account owner. - // - // [3] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewApproveInstructionBuilder creates a new `Approve` instruction builder. func NewApproveInstructionBuilder() *Approve { nd := &Approve{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } @@ -84,19 +80,6 @@ func (inst *Approve) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *Approve) SetSignersAccount(signers ag_solanago.PublicKey) *Approve { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *Approve) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - func (inst Approve) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -125,16 +108,13 @@ func (inst *Approve) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Source is not set") + return errors.New("accounts.Source is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Delegate is not set") + return errors.New("accounts.Delegate is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Owner is not set") - } - if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Owner is not set") } } return nil @@ -158,7 +138,6 @@ func (inst *Approve) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("delegate", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) }) }) }) @@ -188,12 +167,10 @@ func NewApproveInstruction( // Accounts: source ag_solanago.PublicKey, delegate ag_solanago.PublicKey, - owner ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *Approve { + owner ag_solanago.PublicKey) *Approve { return NewApproveInstructionBuilder(). SetAmount(amount). SetSourceAccount(source). SetDelegateAccount(delegate). - SetOwnerAccount(owner). - SetSignersAccount(signers) + SetOwnerAccount(owner) } diff --git a/programs/token/ApproveChecked.go b/programs/token/ApproveChecked.go index 7cb136a1..1fc65af6 100644 --- a/programs/token/ApproveChecked.go +++ b/programs/token/ApproveChecked.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -34,16 +33,13 @@ type ApproveChecked struct { // // [3] = [] owner // ··········· The source account owner. - // - // [4] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewApproveCheckedInstructionBuilder creates a new `ApproveChecked` instruction builder. func NewApproveCheckedInstructionBuilder() *ApproveChecked { nd := &ApproveChecked{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 5), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), } return nd } @@ -114,19 +110,6 @@ func (inst *ApproveChecked) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *ApproveChecked) SetSignersAccount(signers ag_solanago.PublicKey) *ApproveChecked { - inst.AccountMetaSlice[4] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *ApproveChecked) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[4] -} - func (inst ApproveChecked) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -158,19 +141,16 @@ func (inst *ApproveChecked) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Source is not set") + return errors.New("accounts.Source is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Delegate is not set") + return errors.New("accounts.Delegate is not set") } if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Owner is not set") - } - if inst.AccountMetaSlice[4] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Owner is not set") } } return nil @@ -196,7 +176,6 @@ func (inst *ApproveChecked) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("delegate", inst.AccountMetaSlice[2])) accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[3])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[4])) }) }) }) @@ -238,14 +217,12 @@ func NewApproveCheckedInstruction( source ag_solanago.PublicKey, mint ag_solanago.PublicKey, delegate ag_solanago.PublicKey, - owner ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *ApproveChecked { + owner ag_solanago.PublicKey) *ApproveChecked { return NewApproveCheckedInstructionBuilder(). SetAmount(amount). SetDecimals(decimals). SetSourceAccount(source). SetMintAccount(mint). SetDelegateAccount(delegate). - SetOwnerAccount(owner). - SetSignersAccount(signers) + SetOwnerAccount(owner) } diff --git a/programs/token/ApproveChecked_test.go b/programs/token/ApproveChecked_test.go index c4fa7b0c..4b0b061d 100644 --- a/programs/token/ApproveChecked_test.go +++ b/programs/token/ApproveChecked_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/Approve_test.go b/programs/token/Approve_test.go index ba656e82..90e483f4 100644 --- a/programs/token/Approve_test.go +++ b/programs/token/Approve_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/Burn.go b/programs/token/Burn.go index 590f2af2..987360dd 100644 --- a/programs/token/Burn.go +++ b/programs/token/Burn.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -24,16 +23,13 @@ type Burn struct { // // [2] = [] owner // ··········· The account's owner/delegate. - // - // [3] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewBurnInstructionBuilder creates a new `Burn` instruction builder. func NewBurnInstructionBuilder() *Burn { nd := &Burn{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } @@ -84,19 +80,6 @@ func (inst *Burn) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *Burn) SetSignersAccount(signers ag_solanago.PublicKey) *Burn { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *Burn) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - func (inst Burn) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -125,16 +108,13 @@ func (inst *Burn) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Source is not set") + return errors.New("accounts.Source is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Owner is not set") - } - if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Owner is not set") } } return nil @@ -158,7 +138,6 @@ func (inst *Burn) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) }) }) }) @@ -188,12 +167,10 @@ func NewBurnInstruction( // Accounts: source ag_solanago.PublicKey, mint ag_solanago.PublicKey, - owner ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *Burn { + owner ag_solanago.PublicKey) *Burn { return NewBurnInstructionBuilder(). SetAmount(amount). SetSourceAccount(source). SetMintAccount(mint). - SetOwnerAccount(owner). - SetSignersAccount(signers) + SetOwnerAccount(owner) } diff --git a/programs/token/BurnChecked.go b/programs/token/BurnChecked.go index c56f20eb..8ca9d4d5 100644 --- a/programs/token/BurnChecked.go +++ b/programs/token/BurnChecked.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -32,16 +31,13 @@ type BurnChecked struct { // // [2] = [] owner // ··········· The account's owner/delegate. - // - // [3] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewBurnCheckedInstructionBuilder creates a new `BurnChecked` instruction builder. func NewBurnCheckedInstructionBuilder() *BurnChecked { nd := &BurnChecked{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } @@ -99,19 +95,6 @@ func (inst *BurnChecked) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *BurnChecked) SetSignersAccount(signers ag_solanago.PublicKey) *BurnChecked { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *BurnChecked) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - func (inst BurnChecked) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -143,16 +126,13 @@ func (inst *BurnChecked) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Source is not set") + return errors.New("accounts.Source is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Owner is not set") - } - if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Owner is not set") } } return nil @@ -177,7 +157,6 @@ func (inst *BurnChecked) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) }) }) }) @@ -218,13 +197,11 @@ func NewBurnCheckedInstruction( // Accounts: source ag_solanago.PublicKey, mint ag_solanago.PublicKey, - owner ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *BurnChecked { + owner ag_solanago.PublicKey) *BurnChecked { return NewBurnCheckedInstructionBuilder(). SetAmount(amount). SetDecimals(decimals). SetSourceAccount(source). SetMintAccount(mint). - SetOwnerAccount(owner). - SetSignersAccount(signers) + SetOwnerAccount(owner) } diff --git a/programs/token/BurnChecked_test.go b/programs/token/BurnChecked_test.go index 9b80eea0..7a3b8a3f 100644 --- a/programs/token/BurnChecked_test.go +++ b/programs/token/BurnChecked_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/Burn_test.go b/programs/token/Burn_test.go index 14aaba03..0116d0fd 100644 --- a/programs/token/Burn_test.go +++ b/programs/token/Burn_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/CloseAccount.go b/programs/token/CloseAccount.go index 46c595a2..d5bbd970 100644 --- a/programs/token/CloseAccount.go +++ b/programs/token/CloseAccount.go @@ -2,8 +2,8 @@ package token import ( "encoding/binary" - "fmt" - ag_binary "github.com/dfuse-io/binary" + "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -21,16 +21,13 @@ type CloseAccount struct { // // [2] = [] owner // ··········· The account's owner. - // - // [3] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewCloseAccountInstructionBuilder creates a new `CloseAccount` instruction builder. func NewCloseAccountInstructionBuilder() *CloseAccount { nd := &CloseAccount{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } @@ -74,19 +71,6 @@ func (inst *CloseAccount) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *CloseAccount) SetSignersAccount(signers ag_solanago.PublicKey) *CloseAccount { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *CloseAccount) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - func (inst CloseAccount) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -108,16 +92,13 @@ func (inst *CloseAccount) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Account is not set") + return errors.New("accounts.Account is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Destination is not set") + return errors.New("accounts.Destination is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Owner is not set") - } - if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Owner is not set") } } return nil @@ -139,7 +120,6 @@ func (inst *CloseAccount) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) }) }) }) @@ -157,11 +137,9 @@ func NewCloseAccountInstruction( // Accounts: account ag_solanago.PublicKey, destination ag_solanago.PublicKey, - owner ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *CloseAccount { + owner ag_solanago.PublicKey) *CloseAccount { return NewCloseAccountInstructionBuilder(). SetAccount(account). SetDestinationAccount(destination). - SetOwnerAccount(owner). - SetSignersAccount(signers) + SetOwnerAccount(owner) } diff --git a/programs/token/CloseAccount_test.go b/programs/token/CloseAccount_test.go index 164058e9..726ca8c7 100644 --- a/programs/token/CloseAccount_test.go +++ b/programs/token/CloseAccount_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/FreezeAccount.go b/programs/token/FreezeAccount.go index 824e592b..4dd43c38 100644 --- a/programs/token/FreezeAccount.go +++ b/programs/token/FreezeAccount.go @@ -2,8 +2,8 @@ package token import ( "encoding/binary" - "fmt" - ag_binary "github.com/dfuse-io/binary" + "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -20,16 +20,13 @@ type FreezeAccount struct { // // [2] = [] authority // ··········· The mint freeze authority. - // - // [3] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewFreezeAccountInstructionBuilder creates a new `FreezeAccount` instruction builder. func NewFreezeAccountInstructionBuilder() *FreezeAccount { nd := &FreezeAccount{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } @@ -73,19 +70,6 @@ func (inst *FreezeAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *FreezeAccount) SetSignersAccount(signers ag_solanago.PublicKey) *FreezeAccount { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *FreezeAccount) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - func (inst FreezeAccount) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -107,16 +91,13 @@ func (inst *FreezeAccount) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Account is not set") + return errors.New("accounts.Account is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Authority is not set") } } return nil @@ -138,7 +119,6 @@ func (inst *FreezeAccount) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) }) }) }) @@ -156,11 +136,9 @@ func NewFreezeAccountInstruction( // Accounts: account ag_solanago.PublicKey, mint ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *FreezeAccount { + authority ag_solanago.PublicKey) *FreezeAccount { return NewFreezeAccountInstructionBuilder(). SetAccount(account). SetMintAccount(mint). - SetAuthorityAccount(authority). - SetSignersAccount(signers) + SetAuthorityAccount(authority) } diff --git a/programs/token/FreezeAccount_test.go b/programs/token/FreezeAccount_test.go index d611f82e..42b7b212 100644 --- a/programs/token/FreezeAccount_test.go +++ b/programs/token/FreezeAccount_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/InitializeAccount.go b/programs/token/InitializeAccount.go index e22aa201..d5a04159 100644 --- a/programs/token/InitializeAccount.go +++ b/programs/token/InitializeAccount.go @@ -2,8 +2,8 @@ package token import ( "encoding/binary" - "fmt" - ag_binary "github.com/dfuse-io/binary" + "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -118,16 +118,16 @@ func (inst *InitializeAccount) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Account is not set") + return errors.New("accounts.Account is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Owner is not set") + return errors.New("accounts.Owner is not set") } if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.SysVarRentPubkey is not set") + return errors.New("accounts.SysVarRentPubkey is not set") } } return nil diff --git a/programs/token/InitializeAccount2.go b/programs/token/InitializeAccount2.go index 6e1fcb72..1d860a59 100644 --- a/programs/token/InitializeAccount2.go +++ b/programs/token/InitializeAccount2.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -112,13 +111,13 @@ func (inst *InitializeAccount2) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Account is not set") + return errors.New("accounts.Account is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.SysVarRentPubkey is not set") + return errors.New("accounts.SysVarRentPubkey is not set") } } return nil diff --git a/programs/token/InitializeAccount2_test.go b/programs/token/InitializeAccount2_test.go index 40934a73..4b132e9d 100644 --- a/programs/token/InitializeAccount2_test.go +++ b/programs/token/InitializeAccount2_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/InitializeAccount3.go b/programs/token/InitializeAccount3.go index 4f55e41b..2529fbbe 100644 --- a/programs/token/InitializeAccount3.go +++ b/programs/token/InitializeAccount3.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -92,10 +91,10 @@ func (inst *InitializeAccount3) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Account is not set") + return errors.New("accounts.Account is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } } return nil diff --git a/programs/token/InitializeAccount3_test.go b/programs/token/InitializeAccount3_test.go index 2425a09b..443fc879 100644 --- a/programs/token/InitializeAccount3_test.go +++ b/programs/token/InitializeAccount3_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/InitializeAccount_test.go b/programs/token/InitializeAccount_test.go index 3da3ac27..01b41201 100644 --- a/programs/token/InitializeAccount_test.go +++ b/programs/token/InitializeAccount_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/InitializeMint.go b/programs/token/InitializeMint.go index a9b210f1..354d03ca 100644 --- a/programs/token/InitializeMint.go +++ b/programs/token/InitializeMint.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -123,10 +122,10 @@ func (inst *InitializeMint) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.SysVarRentPubkey is not set") + return errors.New("accounts.SysVarRentPubkey is not set") } } return nil diff --git a/programs/token/InitializeMint2.go b/programs/token/InitializeMint2.go index 4181cd09..8a3cd80e 100644 --- a/programs/token/InitializeMint2.go +++ b/programs/token/InitializeMint2.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -99,7 +98,7 @@ func (inst *InitializeMint2) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } } return nil diff --git a/programs/token/InitializeMint2_test.go b/programs/token/InitializeMint2_test.go index 67646192..eb617f26 100644 --- a/programs/token/InitializeMint2_test.go +++ b/programs/token/InitializeMint2_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/InitializeMint_test.go b/programs/token/InitializeMint_test.go index cf08cef3..4a5b096d 100644 --- a/programs/token/InitializeMint_test.go +++ b/programs/token/InitializeMint_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/InitializeMultisig.go b/programs/token/InitializeMultisig.go index bc422197..29a4545c 100644 --- a/programs/token/InitializeMultisig.go +++ b/programs/token/InitializeMultisig.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" diff --git a/programs/token/InitializeMultisig2.go b/programs/token/InitializeMultisig2.go index 03db2138..715be740 100644 --- a/programs/token/InitializeMultisig2.go +++ b/programs/token/InitializeMultisig2.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -92,10 +91,10 @@ func (inst *InitializeMultisig2) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Account is not set") + return errors.New("accounts.Account is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Signers is not set") } } return nil diff --git a/programs/token/InitializeMultisig2_test.go b/programs/token/InitializeMultisig2_test.go index a0280612..a411d09a 100644 --- a/programs/token/InitializeMultisig2_test.go +++ b/programs/token/InitializeMultisig2_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/InitializeMultisig_test.go b/programs/token/InitializeMultisig_test.go index de6fce44..93dd5512 100644 --- a/programs/token/InitializeMultisig_test.go +++ b/programs/token/InitializeMultisig_test.go @@ -5,7 +5,7 @@ import ( "strconv" "testing" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" ) diff --git a/programs/token/MintTo.go b/programs/token/MintTo.go index 627c5e44..cca89c62 100644 --- a/programs/token/MintTo.go +++ b/programs/token/MintTo.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -24,16 +23,13 @@ type MintTo struct { // // [2] = [] authority // ··········· The mint's minting authority. - // - // [3] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewMintToInstructionBuilder creates a new `MintTo` instruction builder. func NewMintToInstructionBuilder() *MintTo { nd := &MintTo{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } @@ -84,19 +80,6 @@ func (inst *MintTo) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *MintTo) SetSignersAccount(signers ag_solanago.PublicKey) *MintTo { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *MintTo) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - func (inst MintTo) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -125,16 +108,13 @@ func (inst *MintTo) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Destination is not set") + return errors.New("accounts.Destination is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Authority is not set") } } return nil @@ -158,7 +138,6 @@ func (inst *MintTo) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) }) }) }) @@ -188,12 +167,10 @@ func NewMintToInstruction( // Accounts: mint ag_solanago.PublicKey, destination ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *MintTo { + authority ag_solanago.PublicKey) *MintTo { return NewMintToInstructionBuilder(). SetAmount(amount). SetMintAccount(mint). SetDestinationAccount(destination). - SetAuthorityAccount(authority). - SetSignersAccount(signers) + SetAuthorityAccount(authority) } diff --git a/programs/token/MintToChecked.go b/programs/token/MintToChecked.go index 0d8e4ce0..115651dc 100644 --- a/programs/token/MintToChecked.go +++ b/programs/token/MintToChecked.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -30,16 +29,13 @@ type MintToChecked struct { // // [2] = [] authority // ··········· The mint's minting authority. - // - // [3] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewMintToCheckedInstructionBuilder creates a new `MintToChecked` instruction builder. func NewMintToCheckedInstructionBuilder() *MintToChecked { nd := &MintToChecked{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } @@ -97,19 +93,6 @@ func (inst *MintToChecked) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *MintToChecked) SetSignersAccount(signers ag_solanago.PublicKey) *MintToChecked { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *MintToChecked) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - func (inst MintToChecked) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -141,16 +124,13 @@ func (inst *MintToChecked) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Destination is not set") + return errors.New("accounts.Destination is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Authority is not set") } } return nil @@ -175,7 +155,6 @@ func (inst *MintToChecked) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) }) }) }) @@ -216,13 +195,11 @@ func NewMintToCheckedInstruction( // Accounts: mint ag_solanago.PublicKey, destination ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *MintToChecked { + authority ag_solanago.PublicKey) *MintToChecked { return NewMintToCheckedInstructionBuilder(). SetAmount(amount). SetDecimals(decimals). SetMintAccount(mint). SetDestinationAccount(destination). - SetAuthorityAccount(authority). - SetSignersAccount(signers) + SetAuthorityAccount(authority) } diff --git a/programs/token/MintToChecked_test.go b/programs/token/MintToChecked_test.go index ceee3ec3..aafffb77 100644 --- a/programs/token/MintToChecked_test.go +++ b/programs/token/MintToChecked_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/MintTo_test.go b/programs/token/MintTo_test.go index e63e2e23..7baabf68 100644 --- a/programs/token/MintTo_test.go +++ b/programs/token/MintTo_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/Revoke.go b/programs/token/Revoke.go index 088677fe..101ea6b6 100644 --- a/programs/token/Revoke.go +++ b/programs/token/Revoke.go @@ -2,8 +2,8 @@ package token import ( "encoding/binary" - "fmt" - ag_binary "github.com/dfuse-io/binary" + "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -17,16 +17,13 @@ type Revoke struct { // // [1] = [] owner // ··········· The source account's owner. - // - // [2] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewRevokeInstructionBuilder creates a new `Revoke` instruction builder. func NewRevokeInstructionBuilder() *Revoke { nd := &Revoke{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), } return nd } @@ -57,19 +54,6 @@ func (inst *Revoke) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *Revoke) SetSignersAccount(signers ag_solanago.PublicKey) *Revoke { - inst.AccountMetaSlice[2] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *Revoke) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - func (inst Revoke) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -91,13 +75,10 @@ func (inst *Revoke) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Source is not set") + return errors.New("accounts.Source is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Owner is not set") - } - if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Owner is not set") } } return nil @@ -118,7 +99,6 @@ func (inst *Revoke) EncodeToTree(parent ag_treeout.Branches) { instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[2])) }) }) }) @@ -135,10 +115,8 @@ func (obj *Revoke) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) func NewRevokeInstruction( // Accounts: source ag_solanago.PublicKey, - owner ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *Revoke { + owner ag_solanago.PublicKey) *Revoke { return NewRevokeInstructionBuilder(). SetSourceAccount(source). - SetOwnerAccount(owner). - SetSignersAccount(signers) + SetOwnerAccount(owner) } diff --git a/programs/token/Revoke_test.go b/programs/token/Revoke_test.go index 99cc150f..198cda88 100644 --- a/programs/token/Revoke_test.go +++ b/programs/token/Revoke_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/SetAuthority.go b/programs/token/SetAuthority.go index 58fccbe8..87c5da8f 100644 --- a/programs/token/SetAuthority.go +++ b/programs/token/SetAuthority.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -23,16 +22,13 @@ type SetAuthority struct { // // [1] = [] authority // ··········· The current authority of the mint or account. - // - // [2] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewSetAuthorityInstructionBuilder creates a new `SetAuthority` instruction builder. func NewSetAuthorityInstructionBuilder() *SetAuthority { nd := &SetAuthority{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), } return nd } @@ -77,19 +73,6 @@ func (inst *SetAuthority) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[1] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *SetAuthority) SetSignersAccount(signers ag_solanago.PublicKey) *SetAuthority { - inst.AccountMetaSlice[2] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *SetAuthority) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - func (inst SetAuthority) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -118,13 +101,10 @@ func (inst *SetAuthority) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Subject is not set") + return errors.New("accounts.Subject is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Authority is not set") - } - if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Authority is not set") } } return nil @@ -148,7 +128,6 @@ func (inst *SetAuthority) EncodeToTree(parent ag_treeout.Branches) { instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("subject", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[2])) }) }) }) @@ -209,12 +188,10 @@ func NewSetAuthorityInstruction( new_authority ag_solanago.PublicKey, // Accounts: subject ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *SetAuthority { + authority ag_solanago.PublicKey) *SetAuthority { return NewSetAuthorityInstructionBuilder(). SetAuthorityType(authority_type). SetNewAuthority(new_authority). SetSubjectAccount(subject). - SetAuthorityAccount(authority). - SetSignersAccount(signers) + SetAuthorityAccount(authority) } diff --git a/programs/token/SetAuthority_test.go b/programs/token/SetAuthority_test.go index 833766a3..5ce0ca2a 100644 --- a/programs/token/SetAuthority_test.go +++ b/programs/token/SetAuthority_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/SyncNative.go b/programs/token/SyncNative.go index c7c91205..1e70f9a9 100644 --- a/programs/token/SyncNative.go +++ b/programs/token/SyncNative.go @@ -2,8 +2,8 @@ package token import ( "encoding/binary" - "fmt" - ag_binary "github.com/dfuse-io/binary" + "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -63,7 +63,7 @@ func (inst *SyncNative) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.TokenAccount is not set") + return errors.New("accounts.TokenAccount is not set") } } return nil diff --git a/programs/token/SyncNative_test.go b/programs/token/SyncNative_test.go index 01dc127c..b3238aca 100644 --- a/programs/token/SyncNative_test.go +++ b/programs/token/SyncNative_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/ThawAccount.go b/programs/token/ThawAccount.go index f5534fee..1724c45d 100644 --- a/programs/token/ThawAccount.go +++ b/programs/token/ThawAccount.go @@ -2,8 +2,8 @@ package token import ( "encoding/binary" - "fmt" - ag_binary "github.com/dfuse-io/binary" + "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -20,16 +20,13 @@ type ThawAccount struct { // // [2] = [] authority // ··········· The mint freeze authority. - // - // [3] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewThawAccountInstructionBuilder creates a new `ThawAccount` instruction builder. func NewThawAccountInstructionBuilder() *ThawAccount { nd := &ThawAccount{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), } return nd } @@ -73,19 +70,6 @@ func (inst *ThawAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[2] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *ThawAccount) SetSignersAccount(signers ag_solanago.PublicKey) *ThawAccount { - inst.AccountMetaSlice[3] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *ThawAccount) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - func (inst ThawAccount) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -107,16 +91,13 @@ func (inst *ThawAccount) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Account is not set") + return errors.New("accounts.Account is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Authority is not set") } } return nil @@ -138,7 +119,6 @@ func (inst *ThawAccount) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[3])) }) }) }) @@ -156,11 +136,9 @@ func NewThawAccountInstruction( // Accounts: account ag_solanago.PublicKey, mint ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *ThawAccount { + authority ag_solanago.PublicKey) *ThawAccount { return NewThawAccountInstructionBuilder(). SetAccount(account). SetMintAccount(mint). - SetAuthorityAccount(authority). - SetSignersAccount(signers) + SetAuthorityAccount(authority) } diff --git a/programs/token/ThawAccount_test.go b/programs/token/ThawAccount_test.go index 1ab8c410..089c088e 100644 --- a/programs/token/ThawAccount_test.go +++ b/programs/token/ThawAccount_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/Transfer.go b/programs/token/Transfer.go index 7fa1e7d1..bf49c834 100644 --- a/programs/token/Transfer.go +++ b/programs/token/Transfer.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" diff --git a/programs/token/TransferChecked.go b/programs/token/TransferChecked.go index b0bccb72..70e2d09d 100644 --- a/programs/token/TransferChecked.go +++ b/programs/token/TransferChecked.go @@ -3,8 +3,7 @@ package token import ( "encoding/binary" "errors" - "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" ag_treeout "github.com/gagliardetto/treeout" @@ -36,16 +35,13 @@ type TransferChecked struct { // // [3] = [] owner // ··········· The source account's owner/delegate. - // - // [4] = [SIGNER] signers - // ··········· M signer accounts. ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` } // NewTransferCheckedInstructionBuilder creates a new `TransferChecked` instruction builder. func NewTransferCheckedInstructionBuilder() *TransferChecked { nd := &TransferChecked{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 5), + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), } return nd } @@ -116,19 +112,6 @@ func (inst *TransferChecked) GetOwnerAccount() *ag_solanago.AccountMeta { return inst.AccountMetaSlice[3] } -// SetSignersAccount sets the "signers" account. -// M signer accounts. -func (inst *TransferChecked) SetSignersAccount(signers ag_solanago.PublicKey) *TransferChecked { - inst.AccountMetaSlice[4] = ag_solanago.Meta(signers).SIGNER() - return inst -} - -// GetSignersAccount gets the "signers" account. -// M signer accounts. -func (inst *TransferChecked) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[4] -} - func (inst TransferChecked) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -160,19 +143,16 @@ func (inst *TransferChecked) Validate() error { // Check whether all (required) accounts are set: { if inst.AccountMetaSlice[0] == nil { - return fmt.Errorf("accounts.Source is not set") + return errors.New("accounts.Source is not set") } if inst.AccountMetaSlice[1] == nil { - return fmt.Errorf("accounts.Mint is not set") + return errors.New("accounts.Mint is not set") } if inst.AccountMetaSlice[2] == nil { - return fmt.Errorf("accounts.Destination is not set") + return errors.New("accounts.Destination is not set") } if inst.AccountMetaSlice[3] == nil { - return fmt.Errorf("accounts.Owner is not set") - } - if inst.AccountMetaSlice[4] == nil { - return fmt.Errorf("accounts.Signers is not set") + return errors.New("accounts.Owner is not set") } } return nil @@ -198,7 +178,6 @@ func (inst *TransferChecked) EncodeToTree(parent ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[2])) accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[3])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[4])) }) }) }) @@ -240,14 +219,12 @@ func NewTransferCheckedInstruction( source ag_solanago.PublicKey, mint ag_solanago.PublicKey, destination ag_solanago.PublicKey, - owner ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *TransferChecked { + owner ag_solanago.PublicKey) *TransferChecked { return NewTransferCheckedInstructionBuilder(). SetAmount(amount). SetDecimals(decimals). SetSourceAccount(source). SetMintAccount(mint). SetDestinationAccount(destination). - SetOwnerAccount(owner). - SetSignersAccount(signers) + SetOwnerAccount(owner) } diff --git a/programs/token/TransferChecked_test.go b/programs/token/TransferChecked_test.go index 1b281d62..fc7c5e87 100644 --- a/programs/token/TransferChecked_test.go +++ b/programs/token/TransferChecked_test.go @@ -2,7 +2,7 @@ package token import ( "bytes" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" "strconv" "testing" diff --git a/programs/token/Transfer_test.go b/programs/token/Transfer_test.go index db226013..2ab64bdd 100644 --- a/programs/token/Transfer_test.go +++ b/programs/token/Transfer_test.go @@ -5,7 +5,7 @@ import ( "strconv" "testing" - ag_gofuzz "github.com/google/gofuzz" + ag_gofuzz "github.com/gagliardetto/gofuzz" ag_require "github.com/stretchr/testify/require" ) diff --git a/programs/token/instructions.go b/programs/token/instructions.go index da805b86..217cbdf8 100644 --- a/programs/token/instructions.go +++ b/programs/token/instructions.go @@ -9,7 +9,7 @@ import ( "fmt" ag_spew "github.com/davecgh/go-spew/spew" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_text "github.com/gagliardetto/solana-go/text" ag_treeout "github.com/gagliardetto/treeout" diff --git a/programs/token/testing_utils.go b/programs/token/testing_utils.go index a0ce07a2..20ddafd1 100644 --- a/programs/token/testing_utils.go +++ b/programs/token/testing_utils.go @@ -3,7 +3,7 @@ package token import ( "bytes" "fmt" - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ) func encodeT(data interface{}, buf *bytes.Buffer) error { diff --git a/programs/token/types.go b/programs/token/types.go index a5cf0fa0..def5ca0f 100644 --- a/programs/token/types.go +++ b/programs/token/types.go @@ -1,7 +1,7 @@ package token import ( - ag_binary "github.com/dfuse-io/binary" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ) From 34ec1cb535773782eec20b148ea70ed14484e0f1 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 17:41:00 +0200 Subject: [PATCH 09/24] token: add multisign signers handling --- programs/token/Approve.go | 71 ++++++++++++++----- programs/token/ApproveChecked.go | 79 ++++++++++++++++------ programs/token/ApproveChecked_test.go | 11 +-- programs/token/Approve_test.go | 11 +-- programs/token/Burn.go | 71 ++++++++++++++----- programs/token/BurnChecked.go | 71 ++++++++++++++----- programs/token/BurnChecked_test.go | 11 +-- programs/token/Burn_test.go | 11 +-- programs/token/CloseAccount.go | 71 ++++++++++++++----- programs/token/CloseAccount_test.go | 11 +-- programs/token/FreezeAccount.go | 71 ++++++++++++++----- programs/token/FreezeAccount_test.go | 11 +-- programs/token/InitializeMultisig.go | 3 +- programs/token/InitializeMultisig2.go | 59 ++++++++++------ programs/token/InitializeMultisig2_test.go | 11 +-- programs/token/MintTo.go | 72 +++++++++++++++----- programs/token/MintToChecked.go | 71 ++++++++++++++----- programs/token/MintToChecked_test.go | 11 +-- programs/token/MintTo_test.go | 11 +-- programs/token/Revoke.go | 63 +++++++++++++---- programs/token/Revoke_test.go | 11 +-- programs/token/SetAuthority.go | 63 +++++++++++++---- programs/token/SetAuthority_test.go | 11 +-- programs/token/ThawAccount.go | 71 ++++++++++++++----- programs/token/ThawAccount_test.go | 11 +-- programs/token/TransferChecked.go | 79 ++++++++++++++++------ programs/token/TransferChecked_test.go | 11 +-- 27 files changed, 781 insertions(+), 277 deletions(-) diff --git a/programs/token/Approve.go b/programs/token/Approve.go index e42804fc..15cb00dc 100644 --- a/programs/token/Approve.go +++ b/programs/token/Approve.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -23,13 +25,29 @@ type Approve struct { // // [2] = [] owner // ··········· The source account owner. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [3...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *Approve) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice Approve) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewApproveInstructionBuilder creates a new `Approve` instruction builder. func NewApproveInstructionBuilder() *Approve { nd := &Approve{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -44,40 +62,46 @@ func (inst *Approve) SetAmount(amount uint64) *Approve { // SetSourceAccount sets the "source" account. // The source account. func (inst *Approve) SetSourceAccount(source ag_solanago.PublicKey) *Approve { - inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + inst.Accounts[0] = ag_solanago.Meta(source).WRITE() return inst } // GetSourceAccount gets the "source" account. // The source account. func (inst *Approve) GetSourceAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetDelegateAccount sets the "delegate" account. // The delegate. func (inst *Approve) SetDelegateAccount(delegate ag_solanago.PublicKey) *Approve { - inst.AccountMetaSlice[1] = ag_solanago.Meta(delegate) + inst.Accounts[1] = ag_solanago.Meta(delegate) return inst } // GetDelegateAccount gets the "delegate" account. // The delegate. func (inst *Approve) GetDelegateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetOwnerAccount sets the "owner" account. // The source account owner. -func (inst *Approve) SetOwnerAccount(owner ag_solanago.PublicKey) *Approve { - inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) +func (inst *Approve) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *Approve { + inst.Accounts[2] = ag_solanago.Meta(owner) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetOwnerAccount gets the "owner" account. // The source account owner. func (inst *Approve) GetOwnerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } func (inst Approve) Build() *Instruction { @@ -107,15 +131,21 @@ func (inst *Approve) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Source is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Delegate is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Owner is not set") } + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -135,9 +165,14 @@ func (inst *Approve) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("delegate", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("delegate", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -167,10 +202,12 @@ func NewApproveInstruction( // Accounts: source ag_solanago.PublicKey, delegate ag_solanago.PublicKey, - owner ag_solanago.PublicKey) *Approve { + owner ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *Approve { return NewApproveInstructionBuilder(). SetAmount(amount). SetSourceAccount(source). SetDelegateAccount(delegate). - SetOwnerAccount(owner) + SetOwnerAccount(owner, multisigSigners...) } diff --git a/programs/token/ApproveChecked.go b/programs/token/ApproveChecked.go index 1fc65af6..e6323a70 100644 --- a/programs/token/ApproveChecked.go +++ b/programs/token/ApproveChecked.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -33,13 +35,29 @@ type ApproveChecked struct { // // [3] = [] owner // ··········· The source account owner. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [4...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *ApproveChecked) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(4) + return nil +} + +func (slice ApproveChecked) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewApproveCheckedInstructionBuilder creates a new `ApproveChecked` instruction builder. func NewApproveCheckedInstructionBuilder() *ApproveChecked { nd := &ApproveChecked{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + Accounts: make(ag_solanago.AccountMetaSlice, 4), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -61,53 +79,59 @@ func (inst *ApproveChecked) SetDecimals(decimals uint8) *ApproveChecked { // SetSourceAccount sets the "source" account. // The source account. func (inst *ApproveChecked) SetSourceAccount(source ag_solanago.PublicKey) *ApproveChecked { - inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + inst.Accounts[0] = ag_solanago.Meta(source).WRITE() return inst } // GetSourceAccount gets the "source" account. // The source account. func (inst *ApproveChecked) GetSourceAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetMintAccount sets the "mint" account. // The token mint. func (inst *ApproveChecked) SetMintAccount(mint ag_solanago.PublicKey) *ApproveChecked { - inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + inst.Accounts[1] = ag_solanago.Meta(mint) return inst } // GetMintAccount gets the "mint" account. // The token mint. func (inst *ApproveChecked) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetDelegateAccount sets the "delegate" account. // The delegate. func (inst *ApproveChecked) SetDelegateAccount(delegate ag_solanago.PublicKey) *ApproveChecked { - inst.AccountMetaSlice[2] = ag_solanago.Meta(delegate) + inst.Accounts[2] = ag_solanago.Meta(delegate) return inst } // GetDelegateAccount gets the "delegate" account. // The delegate. func (inst *ApproveChecked) GetDelegateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } // SetOwnerAccount sets the "owner" account. // The source account owner. -func (inst *ApproveChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *ApproveChecked { - inst.AccountMetaSlice[3] = ag_solanago.Meta(owner) +func (inst *ApproveChecked) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *ApproveChecked { + inst.Accounts[3] = ag_solanago.Meta(owner) + if len(multisigSigners) == 0 { + inst.Accounts[3].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetOwnerAccount gets the "owner" account. // The source account owner. func (inst *ApproveChecked) GetOwnerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] + return inst.Accounts[3] } func (inst ApproveChecked) Build() *Instruction { @@ -140,18 +164,24 @@ func (inst *ApproveChecked) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Source is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Mint is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Delegate is not set") } - if inst.AccountMetaSlice[3] == nil { + if inst.Accounts[3] == nil { return errors.New("accounts.Owner is not set") } + if !inst.Accounts[3].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -172,10 +202,15 @@ func (inst *ApproveChecked) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("delegate", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("delegate", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[3])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -217,12 +252,14 @@ func NewApproveCheckedInstruction( source ag_solanago.PublicKey, mint ag_solanago.PublicKey, delegate ag_solanago.PublicKey, - owner ag_solanago.PublicKey) *ApproveChecked { + owner ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *ApproveChecked { return NewApproveCheckedInstructionBuilder(). SetAmount(amount). SetDecimals(decimals). SetSourceAccount(source). SetMintAccount(mint). SetDelegateAccount(delegate). - SetOwnerAccount(owner) + SetOwnerAccount(owner, multisigSigners...) } diff --git a/programs/token/ApproveChecked_test.go b/programs/token/ApproveChecked_test.go index 4b0b061d..69de9f78 100644 --- a/programs/token/ApproveChecked_test.go +++ b/programs/token/ApproveChecked_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_ApproveChecked(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_ApproveChecked(t *testing.T) { { params := new(ApproveChecked) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(ApproveChecked) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/Approve_test.go b/programs/token/Approve_test.go index 90e483f4..048955fe 100644 --- a/programs/token/Approve_test.go +++ b/programs/token/Approve_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_Approve(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_Approve(t *testing.T) { { params := new(Approve) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(Approve) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + got.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/Burn.go b/programs/token/Burn.go index 987360dd..b59e4c3c 100644 --- a/programs/token/Burn.go +++ b/programs/token/Burn.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -23,13 +25,29 @@ type Burn struct { // // [2] = [] owner // ··········· The account's owner/delegate. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [3...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *Burn) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice Burn) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewBurnInstructionBuilder creates a new `Burn` instruction builder. func NewBurnInstructionBuilder() *Burn { nd := &Burn{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -44,40 +62,46 @@ func (inst *Burn) SetAmount(amount uint64) *Burn { // SetSourceAccount sets the "source" account. // The account to burn from. func (inst *Burn) SetSourceAccount(source ag_solanago.PublicKey) *Burn { - inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + inst.Accounts[0] = ag_solanago.Meta(source).WRITE() return inst } // GetSourceAccount gets the "source" account. // The account to burn from. func (inst *Burn) GetSourceAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetMintAccount sets the "mint" account. // The token mint. func (inst *Burn) SetMintAccount(mint ag_solanago.PublicKey) *Burn { - inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() + inst.Accounts[1] = ag_solanago.Meta(mint).WRITE() return inst } // GetMintAccount gets the "mint" account. // The token mint. func (inst *Burn) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetOwnerAccount sets the "owner" account. // The account's owner/delegate. -func (inst *Burn) SetOwnerAccount(owner ag_solanago.PublicKey) *Burn { - inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) +func (inst *Burn) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *Burn { + inst.Accounts[2] = ag_solanago.Meta(owner) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetOwnerAccount gets the "owner" account. // The account's owner/delegate. func (inst *Burn) GetOwnerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } func (inst Burn) Build() *Instruction { @@ -107,15 +131,21 @@ func (inst *Burn) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Source is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Mint is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Owner is not set") } + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -135,9 +165,14 @@ func (inst *Burn) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -167,10 +202,12 @@ func NewBurnInstruction( // Accounts: source ag_solanago.PublicKey, mint ag_solanago.PublicKey, - owner ag_solanago.PublicKey) *Burn { + owner ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *Burn { return NewBurnInstructionBuilder(). SetAmount(amount). SetSourceAccount(source). SetMintAccount(mint). - SetOwnerAccount(owner) + SetOwnerAccount(owner, multisigSigners...) } diff --git a/programs/token/BurnChecked.go b/programs/token/BurnChecked.go index 8ca9d4d5..6f7c14bb 100644 --- a/programs/token/BurnChecked.go +++ b/programs/token/BurnChecked.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -31,13 +33,29 @@ type BurnChecked struct { // // [2] = [] owner // ··········· The account's owner/delegate. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [3...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *BurnChecked) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice BurnChecked) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewBurnCheckedInstructionBuilder creates a new `BurnChecked` instruction builder. func NewBurnCheckedInstructionBuilder() *BurnChecked { nd := &BurnChecked{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -59,40 +77,46 @@ func (inst *BurnChecked) SetDecimals(decimals uint8) *BurnChecked { // SetSourceAccount sets the "source" account. // The account to burn from. func (inst *BurnChecked) SetSourceAccount(source ag_solanago.PublicKey) *BurnChecked { - inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + inst.Accounts[0] = ag_solanago.Meta(source).WRITE() return inst } // GetSourceAccount gets the "source" account. // The account to burn from. func (inst *BurnChecked) GetSourceAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetMintAccount sets the "mint" account. // The token mint. func (inst *BurnChecked) SetMintAccount(mint ag_solanago.PublicKey) *BurnChecked { - inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() + inst.Accounts[1] = ag_solanago.Meta(mint).WRITE() return inst } // GetMintAccount gets the "mint" account. // The token mint. func (inst *BurnChecked) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetOwnerAccount sets the "owner" account. // The account's owner/delegate. -func (inst *BurnChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *BurnChecked { - inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) +func (inst *BurnChecked) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *BurnChecked { + inst.Accounts[2] = ag_solanago.Meta(owner) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetOwnerAccount gets the "owner" account. // The account's owner/delegate. func (inst *BurnChecked) GetOwnerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } func (inst BurnChecked) Build() *Instruction { @@ -125,15 +149,21 @@ func (inst *BurnChecked) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Source is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Mint is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Owner is not set") } + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -154,9 +184,14 @@ func (inst *BurnChecked) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -197,11 +232,13 @@ func NewBurnCheckedInstruction( // Accounts: source ag_solanago.PublicKey, mint ag_solanago.PublicKey, - owner ag_solanago.PublicKey) *BurnChecked { + owner ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *BurnChecked { return NewBurnCheckedInstructionBuilder(). SetAmount(amount). SetDecimals(decimals). SetSourceAccount(source). SetMintAccount(mint). - SetOwnerAccount(owner) + SetOwnerAccount(owner, multisigSigners...) } diff --git a/programs/token/BurnChecked_test.go b/programs/token/BurnChecked_test.go index 7a3b8a3f..3f116c08 100644 --- a/programs/token/BurnChecked_test.go +++ b/programs/token/BurnChecked_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_BurnChecked(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_BurnChecked(t *testing.T) { { params := new(BurnChecked) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(BurnChecked) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/Burn_test.go b/programs/token/Burn_test.go index 0116d0fd..10d6ad37 100644 --- a/programs/token/Burn_test.go +++ b/programs/token/Burn_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_Burn(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_Burn(t *testing.T) { { params := new(Burn) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(Burn) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/CloseAccount.go b/programs/token/CloseAccount.go index d5bbd970..c6091393 100644 --- a/programs/token/CloseAccount.go +++ b/programs/token/CloseAccount.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -21,13 +23,29 @@ type CloseAccount struct { // // [2] = [] owner // ··········· The account's owner. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [3...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *CloseAccount) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice CloseAccount) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewCloseAccountInstructionBuilder creates a new `CloseAccount` instruction builder. func NewCloseAccountInstructionBuilder() *CloseAccount { nd := &CloseAccount{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -35,40 +53,46 @@ func NewCloseAccountInstructionBuilder() *CloseAccount { // SetAccount sets the "account" account. // The account to close. func (inst *CloseAccount) SetAccount(account ag_solanago.PublicKey) *CloseAccount { - inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + inst.Accounts[0] = ag_solanago.Meta(account).WRITE() return inst } // GetAccount gets the "account" account. // The account to close. func (inst *CloseAccount) GetAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetDestinationAccount sets the "destination" account. // The destination account. func (inst *CloseAccount) SetDestinationAccount(destination ag_solanago.PublicKey) *CloseAccount { - inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() + inst.Accounts[1] = ag_solanago.Meta(destination).WRITE() return inst } // GetDestinationAccount gets the "destination" account. // The destination account. func (inst *CloseAccount) GetDestinationAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetOwnerAccount sets the "owner" account. // The account's owner. -func (inst *CloseAccount) SetOwnerAccount(owner ag_solanago.PublicKey) *CloseAccount { - inst.AccountMetaSlice[2] = ag_solanago.Meta(owner) +func (inst *CloseAccount) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *CloseAccount { + inst.Accounts[2] = ag_solanago.Meta(owner) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetOwnerAccount gets the "owner" account. // The account's owner. func (inst *CloseAccount) GetOwnerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } func (inst CloseAccount) Build() *Instruction { @@ -91,15 +115,21 @@ func (inst CloseAccount) ValidateAndBuild() (*Instruction, error) { func (inst *CloseAccount) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Account is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Destination is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Owner is not set") } + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -117,9 +147,14 @@ func (inst *CloseAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -137,9 +172,11 @@ func NewCloseAccountInstruction( // Accounts: account ag_solanago.PublicKey, destination ag_solanago.PublicKey, - owner ag_solanago.PublicKey) *CloseAccount { + owner ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *CloseAccount { return NewCloseAccountInstructionBuilder(). SetAccount(account). SetDestinationAccount(destination). - SetOwnerAccount(owner) + SetOwnerAccount(owner, multisigSigners...) } diff --git a/programs/token/CloseAccount_test.go b/programs/token/CloseAccount_test.go index 726ca8c7..db8beda8 100644 --- a/programs/token/CloseAccount_test.go +++ b/programs/token/CloseAccount_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_CloseAccount(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_CloseAccount(t *testing.T) { { params := new(CloseAccount) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(CloseAccount) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/FreezeAccount.go b/programs/token/FreezeAccount.go index 4dd43c38..001912c2 100644 --- a/programs/token/FreezeAccount.go +++ b/programs/token/FreezeAccount.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -20,13 +22,29 @@ type FreezeAccount struct { // // [2] = [] authority // ··········· The mint freeze authority. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [3...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *FreezeAccount) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice FreezeAccount) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewFreezeAccountInstructionBuilder creates a new `FreezeAccount` instruction builder. func NewFreezeAccountInstructionBuilder() *FreezeAccount { nd := &FreezeAccount{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -34,40 +52,46 @@ func NewFreezeAccountInstructionBuilder() *FreezeAccount { // SetAccount sets the "account" account. // The account to freeze. func (inst *FreezeAccount) SetAccount(account ag_solanago.PublicKey) *FreezeAccount { - inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + inst.Accounts[0] = ag_solanago.Meta(account).WRITE() return inst } // GetAccount gets the "account" account. // The account to freeze. func (inst *FreezeAccount) GetAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetMintAccount sets the "mint" account. // The token mint. func (inst *FreezeAccount) SetMintAccount(mint ag_solanago.PublicKey) *FreezeAccount { - inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + inst.Accounts[1] = ag_solanago.Meta(mint) return inst } // GetMintAccount gets the "mint" account. // The token mint. func (inst *FreezeAccount) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetAuthorityAccount sets the "authority" account. // The mint freeze authority. -func (inst *FreezeAccount) SetAuthorityAccount(authority ag_solanago.PublicKey) *FreezeAccount { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) +func (inst *FreezeAccount) SetAuthorityAccount(authority ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *FreezeAccount { + inst.Accounts[2] = ag_solanago.Meta(authority) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetAuthorityAccount gets the "authority" account. // The mint freeze authority. func (inst *FreezeAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } func (inst FreezeAccount) Build() *Instruction { @@ -90,15 +114,21 @@ func (inst FreezeAccount) ValidateAndBuild() (*Instruction, error) { func (inst *FreezeAccount) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Account is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Mint is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Authority is not set") } + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -116,9 +146,14 @@ func (inst *FreezeAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -136,9 +171,11 @@ func NewFreezeAccountInstruction( // Accounts: account ag_solanago.PublicKey, mint ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *FreezeAccount { + authority ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *FreezeAccount { return NewFreezeAccountInstructionBuilder(). SetAccount(account). SetMintAccount(mint). - SetAuthorityAccount(authority) + SetAuthorityAccount(authority, multisigSigners...) } diff --git a/programs/token/FreezeAccount_test.go b/programs/token/FreezeAccount_test.go index 42b7b212..3aae0e50 100644 --- a/programs/token/FreezeAccount_test.go +++ b/programs/token/FreezeAccount_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_FreezeAccount(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_FreezeAccount(t *testing.T) { { params := new(FreezeAccount) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(FreezeAccount) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/InitializeMultisig.go b/programs/token/InitializeMultisig.go index 29a4545c..c75db159 100644 --- a/programs/token/InitializeMultisig.go +++ b/programs/token/InitializeMultisig.go @@ -198,7 +198,8 @@ func NewInitializeMultisigInstruction( // Accounts: account ag_solanago.PublicKey, SysVarRentPubkey ag_solanago.PublicKey, - signers []ag_solanago.PublicKey) *InitializeMultisig { + signers []ag_solanago.PublicKey, +) *InitializeMultisig { return NewInitializeMultisigInstructionBuilder(). SetM(m). SetAccount(account). diff --git a/programs/token/InitializeMultisig2.go b/programs/token/InitializeMultisig2.go index 715be740..43a4cdc2 100644 --- a/programs/token/InitializeMultisig2.go +++ b/programs/token/InitializeMultisig2.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -19,13 +21,26 @@ type InitializeMultisig2 struct { // // [1] = [SIGNER] signers // ··········· The signer accounts, must equal to N where 1 <= N <= 11. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *InitializeMultisig2) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(1) + return nil +} + +func (slice InitializeMultisig2) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewInitializeMultisig2InstructionBuilder creates a new `InitializeMultisig2` instruction builder. func NewInitializeMultisig2InstructionBuilder() *InitializeMultisig2 { nd := &InitializeMultisig2{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + Accounts: make(ag_solanago.AccountMetaSlice, 1), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -40,29 +55,25 @@ func (inst *InitializeMultisig2) SetM(m uint8) *InitializeMultisig2 { // SetAccount sets the "account" account. // The multisignature account to initialize. func (inst *InitializeMultisig2) SetAccount(account ag_solanago.PublicKey) *InitializeMultisig2 { - inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + inst.Accounts[0] = ag_solanago.Meta(account).WRITE() return inst } // GetAccount gets the "account" account. // The multisignature account to initialize. func (inst *InitializeMultisig2) GetAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } -// SetSignersAccount sets the "signers" account. +// AddSigners adds the "signers" accounts. // The signer accounts, must equal to N where 1 <= N <= 11. -func (inst *InitializeMultisig2) SetSignersAccount(signers ag_solanago.PublicKey) *InitializeMultisig2 { - inst.AccountMetaSlice[1] = ag_solanago.Meta(signers).SIGNER() +func (inst *InitializeMultisig2) AddSigners(signers ...ag_solanago.PublicKey) *InitializeMultisig2 { + for _, signer := range signers { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } -// GetSignersAccount gets the "signers" account. -// The signer accounts, must equal to N where 1 <= N <= 11. -func (inst *InitializeMultisig2) GetSignersAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - func (inst InitializeMultisig2) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, @@ -90,11 +101,14 @@ func (inst *InitializeMultisig2) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Account is not set") } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Signers is not set") + if len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) } } return nil @@ -115,8 +129,12 @@ func (inst *InitializeMultisig2) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("signers", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -145,9 +163,10 @@ func NewInitializeMultisig2Instruction( m uint8, // Accounts: account ag_solanago.PublicKey, - signers ag_solanago.PublicKey) *InitializeMultisig2 { + signers []ag_solanago.PublicKey, +) *InitializeMultisig2 { return NewInitializeMultisig2InstructionBuilder(). SetM(m). SetAccount(account). - SetSignersAccount(signers) + AddSigners(signers...) } diff --git a/programs/token/InitializeMultisig2_test.go b/programs/token/InitializeMultisig2_test.go index a411d09a..78896de8 100644 --- a/programs/token/InitializeMultisig2_test.go +++ b/programs/token/InitializeMultisig2_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_InitializeMultisig2(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_InitializeMultisig2(t *testing.T) { { params := new(InitializeMultisig2) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(InitializeMultisig2) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/MintTo.go b/programs/token/MintTo.go index cca89c62..b2ca83cb 100644 --- a/programs/token/MintTo.go +++ b/programs/token/MintTo.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -23,13 +25,29 @@ type MintTo struct { // // [2] = [] authority // ··········· The mint's minting authority. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [3...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *MintTo) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice MintTo) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewMintToInstructionBuilder creates a new `MintTo` instruction builder. func NewMintToInstructionBuilder() *MintTo { nd := &MintTo{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -44,40 +62,46 @@ func (inst *MintTo) SetAmount(amount uint64) *MintTo { // SetMintAccount sets the "mint" account. // The mint. func (inst *MintTo) SetMintAccount(mint ag_solanago.PublicKey) *MintTo { - inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() + inst.Accounts[0] = ag_solanago.Meta(mint).WRITE() return inst } // GetMintAccount gets the "mint" account. // The mint. func (inst *MintTo) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetDestinationAccount sets the "destination" account. // The account to mint tokens to. func (inst *MintTo) SetDestinationAccount(destination ag_solanago.PublicKey) *MintTo { - inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() + inst.Accounts[1] = ag_solanago.Meta(destination).WRITE() return inst } // GetDestinationAccount gets the "destination" account. // The account to mint tokens to. func (inst *MintTo) GetDestinationAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetAuthorityAccount sets the "authority" account. // The mint's minting authority. -func (inst *MintTo) SetAuthorityAccount(authority ag_solanago.PublicKey) *MintTo { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) +func (inst *MintTo) SetAuthorityAccount(authority ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *MintTo { + inst.Accounts[2] = ag_solanago.Meta(authority) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetAuthorityAccount gets the "authority" account. // The mint's minting authority. func (inst *MintTo) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } func (inst MintTo) Build() *Instruction { @@ -107,15 +131,21 @@ func (inst *MintTo) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Mint is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Destination is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Authority is not set") } + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -135,9 +165,15 @@ func (inst *MintTo) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } + }) }) }) @@ -167,10 +203,12 @@ func NewMintToInstruction( // Accounts: mint ag_solanago.PublicKey, destination ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *MintTo { + authority ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *MintTo { return NewMintToInstructionBuilder(). SetAmount(amount). SetMintAccount(mint). SetDestinationAccount(destination). - SetAuthorityAccount(authority) + SetAuthorityAccount(authority, multisigSigners...) } diff --git a/programs/token/MintToChecked.go b/programs/token/MintToChecked.go index 115651dc..36edc18d 100644 --- a/programs/token/MintToChecked.go +++ b/programs/token/MintToChecked.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -29,13 +31,29 @@ type MintToChecked struct { // // [2] = [] authority // ··········· The mint's minting authority. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [3...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *MintToChecked) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice MintToChecked) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewMintToCheckedInstructionBuilder creates a new `MintToChecked` instruction builder. func NewMintToCheckedInstructionBuilder() *MintToChecked { nd := &MintToChecked{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -57,40 +75,46 @@ func (inst *MintToChecked) SetDecimals(decimals uint8) *MintToChecked { // SetMintAccount sets the "mint" account. // The mint. func (inst *MintToChecked) SetMintAccount(mint ag_solanago.PublicKey) *MintToChecked { - inst.AccountMetaSlice[0] = ag_solanago.Meta(mint).WRITE() + inst.Accounts[0] = ag_solanago.Meta(mint).WRITE() return inst } // GetMintAccount gets the "mint" account. // The mint. func (inst *MintToChecked) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetDestinationAccount sets the "destination" account. // The account to mint tokens to. func (inst *MintToChecked) SetDestinationAccount(destination ag_solanago.PublicKey) *MintToChecked { - inst.AccountMetaSlice[1] = ag_solanago.Meta(destination).WRITE() + inst.Accounts[1] = ag_solanago.Meta(destination).WRITE() return inst } // GetDestinationAccount gets the "destination" account. // The account to mint tokens to. func (inst *MintToChecked) GetDestinationAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetAuthorityAccount sets the "authority" account. // The mint's minting authority. -func (inst *MintToChecked) SetAuthorityAccount(authority ag_solanago.PublicKey) *MintToChecked { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) +func (inst *MintToChecked) SetAuthorityAccount(authority ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *MintToChecked { + inst.Accounts[2] = ag_solanago.Meta(authority) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetAuthorityAccount gets the "authority" account. // The mint's minting authority. func (inst *MintToChecked) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } func (inst MintToChecked) Build() *Instruction { @@ -123,15 +147,21 @@ func (inst *MintToChecked) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Mint is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Destination is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Authority is not set") } + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -152,9 +182,14 @@ func (inst *MintToChecked) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -195,11 +230,13 @@ func NewMintToCheckedInstruction( // Accounts: mint ag_solanago.PublicKey, destination ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *MintToChecked { + authority ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *MintToChecked { return NewMintToCheckedInstructionBuilder(). SetAmount(amount). SetDecimals(decimals). SetMintAccount(mint). SetDestinationAccount(destination). - SetAuthorityAccount(authority) + SetAuthorityAccount(authority, multisigSigners...) } diff --git a/programs/token/MintToChecked_test.go b/programs/token/MintToChecked_test.go index aafffb77..95b83da6 100644 --- a/programs/token/MintToChecked_test.go +++ b/programs/token/MintToChecked_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_MintToChecked(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_MintToChecked(t *testing.T) { { params := new(MintToChecked) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(MintToChecked) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/MintTo_test.go b/programs/token/MintTo_test.go index 7baabf68..1afe5711 100644 --- a/programs/token/MintTo_test.go +++ b/programs/token/MintTo_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_MintTo(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_MintTo(t *testing.T) { { params := new(MintTo) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(MintTo) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/Revoke.go b/programs/token/Revoke.go index 101ea6b6..448f7bb8 100644 --- a/programs/token/Revoke.go +++ b/programs/token/Revoke.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -17,13 +19,29 @@ type Revoke struct { // // [1] = [] owner // ··········· The source account's owner. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [2...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *Revoke) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(2) + return nil +} + +func (slice Revoke) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewRevokeInstructionBuilder creates a new `Revoke` instruction builder. func NewRevokeInstructionBuilder() *Revoke { nd := &Revoke{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + Accounts: make(ag_solanago.AccountMetaSlice, 2), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -31,27 +49,33 @@ func NewRevokeInstructionBuilder() *Revoke { // SetSourceAccount sets the "source" account. // The source account. func (inst *Revoke) SetSourceAccount(source ag_solanago.PublicKey) *Revoke { - inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + inst.Accounts[0] = ag_solanago.Meta(source).WRITE() return inst } // GetSourceAccount gets the "source" account. // The source account. func (inst *Revoke) GetSourceAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetOwnerAccount sets the "owner" account. // The source account's owner. -func (inst *Revoke) SetOwnerAccount(owner ag_solanago.PublicKey) *Revoke { - inst.AccountMetaSlice[1] = ag_solanago.Meta(owner) +func (inst *Revoke) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *Revoke { + inst.Accounts[1] = ag_solanago.Meta(owner) + if len(multisigSigners) == 0 { + inst.Accounts[1].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetOwnerAccount gets the "owner" account. // The source account's owner. func (inst *Revoke) GetOwnerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } func (inst Revoke) Build() *Instruction { @@ -74,12 +98,18 @@ func (inst Revoke) ValidateAndBuild() (*Instruction, error) { func (inst *Revoke) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Source is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Owner is not set") } + if !inst.Accounts[1].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -97,8 +127,13 @@ func (inst *Revoke) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[1])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -115,8 +150,10 @@ func (obj *Revoke) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) func NewRevokeInstruction( // Accounts: source ag_solanago.PublicKey, - owner ag_solanago.PublicKey) *Revoke { + owner ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *Revoke { return NewRevokeInstructionBuilder(). SetSourceAccount(source). - SetOwnerAccount(owner) + SetOwnerAccount(owner, multisigSigners...) } diff --git a/programs/token/Revoke_test.go b/programs/token/Revoke_test.go index 198cda88..680138c7 100644 --- a/programs/token/Revoke_test.go +++ b/programs/token/Revoke_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_Revoke(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_Revoke(t *testing.T) { { params := new(Revoke) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(Revoke) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/SetAuthority.go b/programs/token/SetAuthority.go index 87c5da8f..5cac55c2 100644 --- a/programs/token/SetAuthority.go +++ b/programs/token/SetAuthority.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -22,13 +24,29 @@ type SetAuthority struct { // // [1] = [] authority // ··········· The current authority of the mint or account. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [2...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *SetAuthority) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(2) + return nil +} + +func (slice SetAuthority) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewSetAuthorityInstructionBuilder creates a new `SetAuthority` instruction builder. func NewSetAuthorityInstructionBuilder() *SetAuthority { nd := &SetAuthority{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + Accounts: make(ag_solanago.AccountMetaSlice, 2), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -50,27 +68,33 @@ func (inst *SetAuthority) SetNewAuthority(new_authority ag_solanago.PublicKey) * // SetSubjectAccount sets the "subject" account. // The mint or account to change the authority of. func (inst *SetAuthority) SetSubjectAccount(subject ag_solanago.PublicKey) *SetAuthority { - inst.AccountMetaSlice[0] = ag_solanago.Meta(subject).WRITE() + inst.Accounts[0] = ag_solanago.Meta(subject).WRITE() return inst } // GetSubjectAccount gets the "subject" account. // The mint or account to change the authority of. func (inst *SetAuthority) GetSubjectAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetAuthorityAccount sets the "authority" account. // The current authority of the mint or account. -func (inst *SetAuthority) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetAuthority { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority) +func (inst *SetAuthority) SetAuthorityAccount(authority ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *SetAuthority { + inst.Accounts[1] = ag_solanago.Meta(authority) + if len(multisigSigners) == 0 { + inst.Accounts[1].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetAuthorityAccount gets the "authority" account. // The current authority of the mint or account. func (inst *SetAuthority) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } func (inst SetAuthority) Build() *Instruction { @@ -100,12 +124,18 @@ func (inst *SetAuthority) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Subject is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Authority is not set") } + if !inst.Accounts[1].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -126,8 +156,13 @@ func (inst *SetAuthority) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("subject", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("subject", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[1])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -188,10 +223,12 @@ func NewSetAuthorityInstruction( new_authority ag_solanago.PublicKey, // Accounts: subject ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *SetAuthority { + authority ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *SetAuthority { return NewSetAuthorityInstructionBuilder(). SetAuthorityType(authority_type). SetNewAuthority(new_authority). SetSubjectAccount(subject). - SetAuthorityAccount(authority) + SetAuthorityAccount(authority, multisigSigners...) } diff --git a/programs/token/SetAuthority_test.go b/programs/token/SetAuthority_test.go index 5ce0ca2a..b4ec4006 100644 --- a/programs/token/SetAuthority_test.go +++ b/programs/token/SetAuthority_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_SetAuthority(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_SetAuthority(t *testing.T) { { params := new(SetAuthority) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(SetAuthority) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/ThawAccount.go b/programs/token/ThawAccount.go index 1724c45d..cc4ad4f2 100644 --- a/programs/token/ThawAccount.go +++ b/programs/token/ThawAccount.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -20,13 +22,29 @@ type ThawAccount struct { // // [2] = [] authority // ··········· The mint freeze authority. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [3...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *ThawAccount) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(3) + return nil +} + +func (slice ThawAccount) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewThawAccountInstructionBuilder creates a new `ThawAccount` instruction builder. func NewThawAccountInstructionBuilder() *ThawAccount { nd := &ThawAccount{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + Accounts: make(ag_solanago.AccountMetaSlice, 3), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -34,40 +52,46 @@ func NewThawAccountInstructionBuilder() *ThawAccount { // SetAccount sets the "account" account. // The account to thaw. func (inst *ThawAccount) SetAccount(account ag_solanago.PublicKey) *ThawAccount { - inst.AccountMetaSlice[0] = ag_solanago.Meta(account).WRITE() + inst.Accounts[0] = ag_solanago.Meta(account).WRITE() return inst } // GetAccount gets the "account" account. // The account to thaw. func (inst *ThawAccount) GetAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetMintAccount sets the "mint" account. // The token mint. func (inst *ThawAccount) SetMintAccount(mint ag_solanago.PublicKey) *ThawAccount { - inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + inst.Accounts[1] = ag_solanago.Meta(mint) return inst } // GetMintAccount gets the "mint" account. // The token mint. func (inst *ThawAccount) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetAuthorityAccount sets the "authority" account. // The mint freeze authority. -func (inst *ThawAccount) SetAuthorityAccount(authority ag_solanago.PublicKey) *ThawAccount { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority) +func (inst *ThawAccount) SetAuthorityAccount(authority ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *ThawAccount { + inst.Accounts[2] = ag_solanago.Meta(authority) + if len(multisigSigners) == 0 { + inst.Accounts[2].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetAuthorityAccount gets the "authority" account. // The mint freeze authority. func (inst *ThawAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } func (inst ThawAccount) Build() *Instruction { @@ -90,15 +114,21 @@ func (inst ThawAccount) ValidateAndBuild() (*Instruction, error) { func (inst *ThawAccount) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Account is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Mint is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Authority is not set") } + if !inst.Accounts[2].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -116,9 +146,14 @@ func (inst *ThawAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[2])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -136,9 +171,11 @@ func NewThawAccountInstruction( // Accounts: account ag_solanago.PublicKey, mint ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *ThawAccount { + authority ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *ThawAccount { return NewThawAccountInstructionBuilder(). SetAccount(account). SetMintAccount(mint). - SetAuthorityAccount(authority) + SetAuthorityAccount(authority, multisigSigners...) } diff --git a/programs/token/ThawAccount_test.go b/programs/token/ThawAccount_test.go index 089c088e..338074f8 100644 --- a/programs/token/ThawAccount_test.go +++ b/programs/token/ThawAccount_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_ThawAccount(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_ThawAccount(t *testing.T) { { params := new(ThawAccount) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(ThawAccount) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } diff --git a/programs/token/TransferChecked.go b/programs/token/TransferChecked.go index 70e2d09d..e534e71c 100644 --- a/programs/token/TransferChecked.go +++ b/programs/token/TransferChecked.go @@ -3,6 +3,8 @@ package token import ( "encoding/binary" "errors" + "fmt" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -35,13 +37,29 @@ type TransferChecked struct { // // [3] = [] owner // ··········· The source account's owner/delegate. - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + // + // [4...] = [SIGNER] signers + // ··········· M signer accounts. + Accounts ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` + Signers ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +func (obj *TransferChecked) SetAccounts(accounts []*ag_solanago.AccountMeta) error { + obj.Accounts, obj.Signers = ag_solanago.AccountMetaSlice(accounts).SplitFrom(4) + return nil +} + +func (slice TransferChecked) GetAccounts() (accounts []*ag_solanago.AccountMeta) { + accounts = append(accounts, slice.Accounts...) + accounts = append(accounts, slice.Signers...) + return } // NewTransferCheckedInstructionBuilder creates a new `TransferChecked` instruction builder. func NewTransferCheckedInstructionBuilder() *TransferChecked { nd := &TransferChecked{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + Accounts: make(ag_solanago.AccountMetaSlice, 4), + Signers: make(ag_solanago.AccountMetaSlice, 0), } return nd } @@ -63,53 +81,59 @@ func (inst *TransferChecked) SetDecimals(decimals uint8) *TransferChecked { // SetSourceAccount sets the "source" account. // The source account. func (inst *TransferChecked) SetSourceAccount(source ag_solanago.PublicKey) *TransferChecked { - inst.AccountMetaSlice[0] = ag_solanago.Meta(source).WRITE() + inst.Accounts[0] = ag_solanago.Meta(source).WRITE() return inst } // GetSourceAccount gets the "source" account. // The source account. func (inst *TransferChecked) GetSourceAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] + return inst.Accounts[0] } // SetMintAccount sets the "mint" account. // The token mint. func (inst *TransferChecked) SetMintAccount(mint ag_solanago.PublicKey) *TransferChecked { - inst.AccountMetaSlice[1] = ag_solanago.Meta(mint) + inst.Accounts[1] = ag_solanago.Meta(mint) return inst } // GetMintAccount gets the "mint" account. // The token mint. func (inst *TransferChecked) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] + return inst.Accounts[1] } // SetDestinationAccount sets the "destination" account. // The destination account. func (inst *TransferChecked) SetDestinationAccount(destination ag_solanago.PublicKey) *TransferChecked { - inst.AccountMetaSlice[2] = ag_solanago.Meta(destination).WRITE() + inst.Accounts[2] = ag_solanago.Meta(destination).WRITE() return inst } // GetDestinationAccount gets the "destination" account. // The destination account. func (inst *TransferChecked) GetDestinationAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] + return inst.Accounts[2] } // SetOwnerAccount sets the "owner" account. // The source account's owner/delegate. -func (inst *TransferChecked) SetOwnerAccount(owner ag_solanago.PublicKey) *TransferChecked { - inst.AccountMetaSlice[3] = ag_solanago.Meta(owner) +func (inst *TransferChecked) SetOwnerAccount(owner ag_solanago.PublicKey, multisigSigners ...ag_solanago.PublicKey) *TransferChecked { + inst.Accounts[3] = ag_solanago.Meta(owner) + if len(multisigSigners) == 0 { + inst.Accounts[3].SIGNER() + } + for _, signer := range multisigSigners { + inst.Signers = append(inst.Signers, ag_solanago.Meta(signer).SIGNER()) + } return inst } // GetOwnerAccount gets the "owner" account. // The source account's owner/delegate. func (inst *TransferChecked) GetOwnerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] + return inst.Accounts[3] } func (inst TransferChecked) Build() *Instruction { @@ -142,18 +166,24 @@ func (inst *TransferChecked) Validate() error { // Check whether all (required) accounts are set: { - if inst.AccountMetaSlice[0] == nil { + if inst.Accounts[0] == nil { return errors.New("accounts.Source is not set") } - if inst.AccountMetaSlice[1] == nil { + if inst.Accounts[1] == nil { return errors.New("accounts.Mint is not set") } - if inst.AccountMetaSlice[2] == nil { + if inst.Accounts[2] == nil { return errors.New("accounts.Destination is not set") } - if inst.AccountMetaSlice[3] == nil { + if inst.Accounts[3] == nil { return errors.New("accounts.Owner is not set") } + if !inst.Accounts[3].IsSigner && len(inst.Signers) == 0 { + return fmt.Errorf("accounts.Signers is not set") + } + if len(inst.Signers) > MAX_SIGNERS { + return fmt.Errorf("too many signers; got %v, but max is 11", len(inst.Signers)) + } } return nil } @@ -174,10 +204,15 @@ func (inst *TransferChecked) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("destination", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[3])) + + signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) + for i, v := range inst.Signers { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + } }) }) }) @@ -219,12 +254,14 @@ func NewTransferCheckedInstruction( source ag_solanago.PublicKey, mint ag_solanago.PublicKey, destination ag_solanago.PublicKey, - owner ag_solanago.PublicKey) *TransferChecked { + owner ag_solanago.PublicKey, + multisigSigners []ag_solanago.PublicKey, +) *TransferChecked { return NewTransferCheckedInstructionBuilder(). SetAmount(amount). SetDecimals(decimals). SetSourceAccount(source). SetMintAccount(mint). SetDestinationAccount(destination). - SetOwnerAccount(owner) + SetOwnerAccount(owner, multisigSigners...) } diff --git a/programs/token/TransferChecked_test.go b/programs/token/TransferChecked_test.go index fc7c5e87..393464b7 100644 --- a/programs/token/TransferChecked_test.go +++ b/programs/token/TransferChecked_test.go @@ -2,10 +2,11 @@ package token import ( "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" "strconv" "testing" + + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" ) func TestEncodeDecode_TransferChecked(t *testing.T) { @@ -15,14 +16,16 @@ func TestEncodeDecode_TransferChecked(t *testing.T) { { params := new(TransferChecked) fu.Fuzz(params) - params.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil buf := new(bytes.Buffer) err := encodeT(*params, buf) ag_require.NoError(t, err) // got := new(TransferChecked) err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil + params.Accounts = nil + params.Signers = nil ag_require.NoError(t, err) ag_require.Equal(t, params, got) } From 6f8c2e3c1b6e1cb38f385ad43288aa6534be47d9 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sat, 4 Sep 2021 19:01:32 +0200 Subject: [PATCH 10/24] Simplify program ID names --- account_test.go | 12 ++++++------ keys.go | 2 +- program_ids.go | 19 ++++++++++++++----- programs/token/instructions.go | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/account_test.go b/account_test.go index 0379daf8..95de56dc 100644 --- a/account_test.go +++ b/account_test.go @@ -144,10 +144,10 @@ func TestMeta(t *testing.T) { func TestSplitFrom(t *testing.T) { slice := make(AccountMetaSlice, 0) slice = append(slice, Meta(BPFLoaderDeprecatedProgramID)) - slice = append(slice, Meta(SPLTokenProgramID)) - slice = append(slice, Meta(SPLTokenLendingProgramID)) + slice = append(slice, Meta(TokenProgramID)) + slice = append(slice, Meta(TokenLendingProgramID)) slice = append(slice, Meta(SPLAssociatedTokenAccountProgramID)) - slice = append(slice, Meta(SPLMemoProgramID)) + slice = append(slice, Meta(MemoProgramID)) require.Len(t, slice, 5) @@ -161,10 +161,10 @@ func TestSplitFrom(t *testing.T) { require.Len(t, part1, 1) require.Len(t, part2, 4) require.Equal(t, Meta(BPFLoaderDeprecatedProgramID), part1[0]) - require.Equal(t, Meta(SPLTokenProgramID), part2[0]) - require.Equal(t, Meta(SPLTokenLendingProgramID), part2[1]) + require.Equal(t, Meta(TokenProgramID), part2[0]) + require.Equal(t, Meta(TokenLendingProgramID), part2[1]) require.Equal(t, Meta(SPLAssociatedTokenAccountProgramID), part2[2]) - require.Equal(t, Meta(SPLMemoProgramID), part2[3]) + require.Equal(t, Meta(MemoProgramID), part2[3]) } { part1, part2 := slice.SplitFrom(2) diff --git a/keys.go b/keys.go index dcc5351e..4b1e58f4 100644 --- a/keys.go +++ b/keys.go @@ -332,7 +332,7 @@ func findAssociatedTokenAddressAndBumpSeed( ) (PublicKey, uint8, error) { return FindProgramAddress([][]byte{ walletAddress[:], - SPLTokenProgramID[:], + TokenProgramID[:], splTokenMintAddress[:], }, programID, diff --git a/program_ids.go b/program_ids.go index a37a62fd..13aaaf97 100644 --- a/program_ids.go +++ b/program_ids.go @@ -29,15 +29,15 @@ var ( var ( // A Token program on the Solana blockchain. // This program defines a common implementation for Fungible and Non Fungible tokens. - SPLTokenProgramID = MustPublicKeyFromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") + TokenProgramID = MustPublicKeyFromBase58("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") // A Uniswap-like exchange for the Token program on the Solana blockchain, // implementing multiple automated market maker (AMM) curves. - SPLTokenSwapProgramID = MustPublicKeyFromBase58("SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8") - SPLTokenSwapFeeOwner = MustPublicKeyFromBase58("HfoTxFR1Tm6kGmWgYWD6J7YHVy1UwqSULUGVLXkJqaKN") + TokenSwapProgramID = MustPublicKeyFromBase58("SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8") + TokenSwapFeeOwner = MustPublicKeyFromBase58("HfoTxFR1Tm6kGmWgYWD6J7YHVy1UwqSULUGVLXkJqaKN") // A lending protocol for the Token program on the Solana blockchain inspired by Aave and Compound. - SPLTokenLendingProgramID = MustPublicKeyFromBase58("LendZqTs8gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi") + TokenLendingProgramID = MustPublicKeyFromBase58("LendZqTs8gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi") // This program defines the convention and provides the mechanism for mapping // the user's wallet address to the associated token accounts they hold. @@ -49,5 +49,14 @@ var ( // to the transaction log, so that anyone can easily observe memos // and know they were approved by zero or more addresses // by inspecting the transaction log from a trusted provider. - SPLMemoProgramID = MustPublicKeyFromBase58("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr") + MemoProgramID = MustPublicKeyFromBase58("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr") +) + +var ( + // The Mint for native SOL Token accounts + SolMint = MustPublicKeyFromBase58("So11111111111111111111111111111111111111112") +) + +var ( + TokenMetadataProgramID = MustPublicKeyFromBase58("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s") ) diff --git a/programs/token/instructions.go b/programs/token/instructions.go index 217cbdf8..3f319893 100644 --- a/programs/token/instructions.go +++ b/programs/token/instructions.go @@ -17,7 +17,7 @@ import ( const MAX_SIGNERS = 11 -var ProgramID ag_solanago.PublicKey = ag_solanago.SPLTokenProgramID +var ProgramID ag_solanago.PublicKey = ag_solanago.TokenProgramID func SetProgramID(pubkey ag_solanago.PublicKey) { ProgramID = pubkey From 143da1bc655246fe7d9b728fab6fe4472a8913ce Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sun, 5 Sep 2021 00:25:15 +0200 Subject: [PATCH 11/24] token: instruction ID type is uint8 --- programs/token/Approve.go | 3 +-- programs/token/ApproveChecked.go | 3 +-- programs/token/Burn.go | 3 +-- programs/token/BurnChecked.go | 3 +-- programs/token/CloseAccount.go | 3 +-- programs/token/FreezeAccount.go | 3 +-- programs/token/InitializeAccount.go | 4 ++-- programs/token/InitializeAccount2.go | 4 ++-- programs/token/InitializeAccount3.go | 4 ++-- programs/token/InitializeMint.go | 4 ++-- programs/token/InitializeMint2.go | 4 ++-- programs/token/InitializeMultisig.go | 3 +-- programs/token/InitializeMultisig2.go | 3 +-- programs/token/MintTo.go | 3 +-- programs/token/MintToChecked.go | 3 +-- programs/token/Revoke.go | 3 +-- programs/token/SetAuthority.go | 3 +-- programs/token/SyncNative.go | 4 ++-- programs/token/ThawAccount.go | 3 +-- programs/token/Transfer.go | 3 +-- programs/token/TransferChecked.go | 3 +-- programs/token/instructions.go | 9 ++++----- 22 files changed, 31 insertions(+), 47 deletions(-) diff --git a/programs/token/Approve.go b/programs/token/Approve.go index 15cb00dc..d5687ef8 100644 --- a/programs/token/Approve.go +++ b/programs/token/Approve.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -107,7 +106,7 @@ func (inst *Approve) GetOwnerAccount() *ag_solanago.AccountMeta { func (inst Approve) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_Approve, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_Approve), }} } diff --git a/programs/token/ApproveChecked.go b/programs/token/ApproveChecked.go index e6323a70..86ab1796 100644 --- a/programs/token/ApproveChecked.go +++ b/programs/token/ApproveChecked.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -137,7 +136,7 @@ func (inst *ApproveChecked) GetOwnerAccount() *ag_solanago.AccountMeta { func (inst ApproveChecked) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_ApproveChecked, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_ApproveChecked), }} } diff --git a/programs/token/Burn.go b/programs/token/Burn.go index b59e4c3c..78f565e2 100644 --- a/programs/token/Burn.go +++ b/programs/token/Burn.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -107,7 +106,7 @@ func (inst *Burn) GetOwnerAccount() *ag_solanago.AccountMeta { func (inst Burn) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_Burn, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_Burn), }} } diff --git a/programs/token/BurnChecked.go b/programs/token/BurnChecked.go index 6f7c14bb..b3c70759 100644 --- a/programs/token/BurnChecked.go +++ b/programs/token/BurnChecked.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -122,7 +121,7 @@ func (inst *BurnChecked) GetOwnerAccount() *ag_solanago.AccountMeta { func (inst BurnChecked) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_BurnChecked, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_BurnChecked), }} } diff --git a/programs/token/CloseAccount.go b/programs/token/CloseAccount.go index c6091393..42f19891 100644 --- a/programs/token/CloseAccount.go +++ b/programs/token/CloseAccount.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -98,7 +97,7 @@ func (inst *CloseAccount) GetOwnerAccount() *ag_solanago.AccountMeta { func (inst CloseAccount) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_CloseAccount, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_CloseAccount), }} } diff --git a/programs/token/FreezeAccount.go b/programs/token/FreezeAccount.go index 001912c2..9082a117 100644 --- a/programs/token/FreezeAccount.go +++ b/programs/token/FreezeAccount.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -97,7 +96,7 @@ func (inst *FreezeAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { func (inst FreezeAccount) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_FreezeAccount, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_FreezeAccount), }} } diff --git a/programs/token/InitializeAccount.go b/programs/token/InitializeAccount.go index d5a04159..88700499 100644 --- a/programs/token/InitializeAccount.go +++ b/programs/token/InitializeAccount.go @@ -1,8 +1,8 @@ package token import ( - "encoding/binary" "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -100,7 +100,7 @@ func (inst *InitializeAccount) GetSysVarRentPubkeyAccount() *ag_solanago.Account func (inst InitializeAccount) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeAccount, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_InitializeAccount), }} } diff --git a/programs/token/InitializeAccount2.go b/programs/token/InitializeAccount2.go index 1d860a59..28ad5793 100644 --- a/programs/token/InitializeAccount2.go +++ b/programs/token/InitializeAccount2.go @@ -1,8 +1,8 @@ package token import ( - "encoding/binary" "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -86,7 +86,7 @@ func (inst *InitializeAccount2) GetSysVarRentPubkeyAccount() *ag_solanago.Accoun func (inst InitializeAccount2) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeAccount2, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_InitializeAccount2), }} } diff --git a/programs/token/InitializeAccount3.go b/programs/token/InitializeAccount3.go index 2529fbbe..243df14b 100644 --- a/programs/token/InitializeAccount3.go +++ b/programs/token/InitializeAccount3.go @@ -1,8 +1,8 @@ package token import ( - "encoding/binary" "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -66,7 +66,7 @@ func (inst *InitializeAccount3) GetMintAccount() *ag_solanago.AccountMeta { func (inst InitializeAccount3) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeAccount3, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_InitializeAccount3), }} } diff --git a/programs/token/InitializeMint.go b/programs/token/InitializeMint.go index 354d03ca..b4f1b034 100644 --- a/programs/token/InitializeMint.go +++ b/programs/token/InitializeMint.go @@ -1,8 +1,8 @@ package token import ( - "encoding/binary" "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -94,7 +94,7 @@ func (inst *InitializeMint) GetSysVarRentPubkeyAccount() *ag_solanago.AccountMet func (inst InitializeMint) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeMint, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_InitializeMint), }} } diff --git a/programs/token/InitializeMint2.go b/programs/token/InitializeMint2.go index 8a3cd80e..a8486a90 100644 --- a/programs/token/InitializeMint2.go +++ b/programs/token/InitializeMint2.go @@ -1,8 +1,8 @@ package token import ( - "encoding/binary" "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -70,7 +70,7 @@ func (inst *InitializeMint2) GetMintAccount() *ag_solanago.AccountMeta { func (inst InitializeMint2) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeMint2, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_InitializeMint2), }} } diff --git a/programs/token/InitializeMultisig.go b/programs/token/InitializeMultisig.go index c75db159..025295da 100644 --- a/programs/token/InitializeMultisig.go +++ b/programs/token/InitializeMultisig.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -107,7 +106,7 @@ func (inst *InitializeMultisig) AddSigners(signers ...ag_solanago.PublicKey) *In func (inst InitializeMultisig) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeMultisig, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_InitializeMultisig), }} } diff --git a/programs/token/InitializeMultisig2.go b/programs/token/InitializeMultisig2.go index 43a4cdc2..29edf4ad 100644 --- a/programs/token/InitializeMultisig2.go +++ b/programs/token/InitializeMultisig2.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -77,7 +76,7 @@ func (inst *InitializeMultisig2) AddSigners(signers ...ag_solanago.PublicKey) *I func (inst InitializeMultisig2) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_InitializeMultisig2, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_InitializeMultisig2), }} } diff --git a/programs/token/MintTo.go b/programs/token/MintTo.go index b2ca83cb..f5f9a609 100644 --- a/programs/token/MintTo.go +++ b/programs/token/MintTo.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -107,7 +106,7 @@ func (inst *MintTo) GetAuthorityAccount() *ag_solanago.AccountMeta { func (inst MintTo) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_MintTo, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_MintTo), }} } diff --git a/programs/token/MintToChecked.go b/programs/token/MintToChecked.go index 36edc18d..45c0d44f 100644 --- a/programs/token/MintToChecked.go +++ b/programs/token/MintToChecked.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -120,7 +119,7 @@ func (inst *MintToChecked) GetAuthorityAccount() *ag_solanago.AccountMeta { func (inst MintToChecked) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_MintToChecked, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_MintToChecked), }} } diff --git a/programs/token/Revoke.go b/programs/token/Revoke.go index 448f7bb8..97fcc426 100644 --- a/programs/token/Revoke.go +++ b/programs/token/Revoke.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -81,7 +80,7 @@ func (inst *Revoke) GetOwnerAccount() *ag_solanago.AccountMeta { func (inst Revoke) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_Revoke, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_Revoke), }} } diff --git a/programs/token/SetAuthority.go b/programs/token/SetAuthority.go index 5cac55c2..ef7f4452 100644 --- a/programs/token/SetAuthority.go +++ b/programs/token/SetAuthority.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -100,7 +99,7 @@ func (inst *SetAuthority) GetAuthorityAccount() *ag_solanago.AccountMeta { func (inst SetAuthority) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_SetAuthority, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_SetAuthority), }} } diff --git a/programs/token/SyncNative.go b/programs/token/SyncNative.go index 1e70f9a9..b753e740 100644 --- a/programs/token/SyncNative.go +++ b/programs/token/SyncNative.go @@ -1,8 +1,8 @@ package token import ( - "encoding/binary" "errors" + ag_binary "github.com/gagliardetto/binary" ag_solanago "github.com/gagliardetto/solana-go" ag_format "github.com/gagliardetto/solana-go/text/format" @@ -45,7 +45,7 @@ func (inst *SyncNative) GetTokenAccount() *ag_solanago.AccountMeta { func (inst SyncNative) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_SyncNative, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_SyncNative), }} } diff --git a/programs/token/ThawAccount.go b/programs/token/ThawAccount.go index cc4ad4f2..e8a5ddd1 100644 --- a/programs/token/ThawAccount.go +++ b/programs/token/ThawAccount.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -97,7 +96,7 @@ func (inst *ThawAccount) GetAuthorityAccount() *ag_solanago.AccountMeta { func (inst ThawAccount) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_ThawAccount, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_ThawAccount), }} } diff --git a/programs/token/Transfer.go b/programs/token/Transfer.go index bf49c834..45aea2a9 100644 --- a/programs/token/Transfer.go +++ b/programs/token/Transfer.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -109,7 +108,7 @@ func (inst *Transfer) GetOwnerAccount() *ag_solanago.AccountMeta { func (inst Transfer) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_Transfer, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_Transfer), }} } diff --git a/programs/token/TransferChecked.go b/programs/token/TransferChecked.go index e534e71c..dbfd2fd1 100644 --- a/programs/token/TransferChecked.go +++ b/programs/token/TransferChecked.go @@ -1,7 +1,6 @@ package token import ( - "encoding/binary" "errors" "fmt" @@ -139,7 +138,7 @@ func (inst *TransferChecked) GetOwnerAccount() *ag_solanago.AccountMeta { func (inst TransferChecked) Build() *Instruction { return &Instruction{BaseVariant: ag_binary.BaseVariant{ Impl: inst, - TypeID: ag_binary.TypeIDFromUint32(Instruction_TransferChecked, binary.LittleEndian), + TypeID: ag_binary.TypeIDFromUint8(Instruction_TransferChecked), }} } diff --git a/programs/token/instructions.go b/programs/token/instructions.go index 3f319893..a7b13372 100644 --- a/programs/token/instructions.go +++ b/programs/token/instructions.go @@ -5,7 +5,6 @@ package token import ( "bytes" - "encoding/binary" "fmt" ag_spew "github.com/davecgh/go-spew/spew" @@ -41,7 +40,7 @@ const ( // `CreateAccount` instruction that creates the account being initialized. // Otherwise another party can acquire ownership of the uninitialized // account. - Instruction_InitializeMint uint32 = iota + Instruction_InitializeMint uint8 = iota // Initializes a new account to hold tokens. If this account is associated // with the native mint then the token balance of the initialized account @@ -162,7 +161,7 @@ const ( ) // InstructionIDToName returns the name of the instruction given its ID. -func InstructionIDToName(id uint32) string { +func InstructionIDToName(id uint8) string { switch id { case Instruction_InitializeMint: return "InitializeMint" @@ -224,7 +223,7 @@ func (inst *Instruction) EncodeToTree(parent ag_treeout.Branches) { } var InstructionImplDef = ag_binary.NewVariantDefinition( - ag_binary.Uint32TypeIDEncoding, + ag_binary.Uint8TypeIDEncoding, []ag_binary.VariantType{ { "InitializeMint", (*InitializeMint)(nil), @@ -317,7 +316,7 @@ func (inst *Instruction) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error } func (inst *Instruction) MarshalWithEncoder(encoder *ag_binary.Encoder) error { - err := encoder.WriteUint32(inst.TypeID.Uint32(), binary.LittleEndian) + err := encoder.WriteUint8(inst.TypeID.Uint8()) if err != nil { return fmt.Errorf("unable to write variant type: %w", err) } From d7eb94b123f49218743b5c99e50e1fcca68252c8 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Sun, 5 Sep 2021 01:13:45 +0200 Subject: [PATCH 12/24] Fix display panics and errors --- text/format/format.go | 4 ++-- transaction.go | 24 +++++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/text/format/format.go b/text/format/format.go index d92ace1e..1e8a3fac 100644 --- a/text/format/format.go +++ b/text/format/format.go @@ -31,8 +31,8 @@ func Meta(name string, meta *solana.AccountMeta) string { if meta.IsWritable { out += "WRITE" } - if meta.IsWritable { - if meta.IsWritable { + if meta.IsSigner { + if meta.IsSigner { out += ", " } out += "SIGN" diff --git a/transaction.go b/transaction.go index 5c5b57b9..484f2d98 100644 --- a/transaction.go +++ b/transaction.go @@ -352,18 +352,20 @@ func (tx *Transaction) EncodeToTree(parent treeout.Branches) { for _, inst := range tx.Message.Instructions { progKey, err := tx.ResolveProgramIDIndex(inst.ProgramIDIndex) - if err != nil { - panic(err) - } - - decodedInstruction, err := DecodeInstruction(progKey, inst.ResolveInstructionAccounts(&tx.Message), inst.Data) - if err != nil { - panic(err) - } - if enToTree, ok := decodedInstruction.(text.EncodableToTree); ok { - enToTree.EncodeToTree(message) + if err == nil { + decodedInstruction, err := DecodeInstruction(progKey, inst.ResolveInstructionAccounts(&tx.Message), inst.Data) + if err == nil { + if enToTree, ok := decodedInstruction.(text.EncodableToTree); ok { + enToTree.EncodeToTree(message) + } else { + message.Child(spew.Sdump(decodedInstruction)) + } + } else { + // TODO: log error? + message.Child(fmt.Sprintf(text.RedBG("cannot decode instruction for %s program: %s"), progKey, err)) + } } else { - message.Child(spew.Sdump(decodedInstruction)) + message.Child(fmt.Sprintf(text.RedBG("cannot ResolveProgramIDIndex: %s"), err)) } } }) From 10ca07c7a5d8e8694693f41ef222a3f43f9acf4f Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 13:22:17 +0200 Subject: [PATCH 13/24] system: improve tree visualization formatting --- programs/system/AdvanceNonceAccount.go | 6 +++--- programs/system/Allocate.go | 2 +- programs/system/AllocateWithSeed.go | 8 ++++---- programs/system/Assign.go | 2 +- programs/system/AssignWithSeed.go | 8 ++++---- programs/system/AuthorizeNonceAccount.go | 4 ++-- programs/system/CreateAccount.go | 8 ++++---- programs/system/CreateAccountWithSeed.go | 14 +++++++------- programs/system/InitializeNonceAccount.go | 6 +++--- programs/system/Transfer.go | 4 ++-- programs/system/TransferWithSeed.go | 10 +++++----- programs/system/WithdrawNonceAccount.go | 10 +++++----- 12 files changed, 41 insertions(+), 41 deletions(-) diff --git a/programs/system/AdvanceNonceAccount.go b/programs/system/AdvanceNonceAccount.go index 7830fd73..de7133c9 100644 --- a/programs/system/AdvanceNonceAccount.go +++ b/programs/system/AdvanceNonceAccount.go @@ -103,9 +103,9 @@ func (inst *AdvanceNonceAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("NonceAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("$(SysVarRecentBlockHashesPubkey)", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("NonceAuthorityAccount", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" Nonce", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("SysVarRecentBlockHashes", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" NonceAuthority", inst.AccountMetaSlice[2])) }) }) }) diff --git a/programs/system/Allocate.go b/programs/system/Allocate.go index 2d06becf..8bba028b 100644 --- a/programs/system/Allocate.go +++ b/programs/system/Allocate.go @@ -94,7 +94,7 @@ func (inst *Allocate) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("NewAccount", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("New", inst.AccountMetaSlice[0])) }) }) }) diff --git a/programs/system/AllocateWithSeed.go b/programs/system/AllocateWithSeed.go index 64490601..71a0d341 100644 --- a/programs/system/AllocateWithSeed.go +++ b/programs/system/AllocateWithSeed.go @@ -138,16 +138,16 @@ func (inst *AllocateWithSeed) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Base", *inst.Base)) - paramsBranch.Child(ag_format.Param("Seed", *inst.Seed)) + paramsBranch.Child(ag_format.Param(" Base", *inst.Base)) + paramsBranch.Child(ag_format.Param(" Seed", *inst.Seed)) paramsBranch.Child(ag_format.Param("Space", *inst.Space)) paramsBranch.Child(ag_format.Param("Owner", *inst.Owner)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("AllocatedAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("BaseAccount", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("Allocated", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" Base", inst.AccountMetaSlice[1])) }) }) }) diff --git a/programs/system/Assign.go b/programs/system/Assign.go index 67b183c8..18e78a1b 100644 --- a/programs/system/Assign.go +++ b/programs/system/Assign.go @@ -94,7 +94,7 @@ func (inst *Assign) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("AssignedAccount", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("Assigned", inst.AccountMetaSlice[0])) }) }) }) diff --git a/programs/system/AssignWithSeed.go b/programs/system/AssignWithSeed.go index ba4ec998..1ffc3239 100644 --- a/programs/system/AssignWithSeed.go +++ b/programs/system/AssignWithSeed.go @@ -126,15 +126,15 @@ func (inst *AssignWithSeed) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Base", *inst.Base)) - paramsBranch.Child(ag_format.Param("Seed", *inst.Seed)) + paramsBranch.Child(ag_format.Param(" Base", *inst.Base)) + paramsBranch.Child(ag_format.Param(" Seed", *inst.Seed)) paramsBranch.Child(ag_format.Param("Owner", *inst.Owner)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("AssignedAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("BaseAccount", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("Assigned", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" Base", inst.AccountMetaSlice[1])) }) }) }) diff --git a/programs/system/AuthorizeNonceAccount.go b/programs/system/AuthorizeNonceAccount.go index 3025b8e1..45be7345 100644 --- a/programs/system/AuthorizeNonceAccount.go +++ b/programs/system/AuthorizeNonceAccount.go @@ -107,8 +107,8 @@ func (inst *AuthorizeNonceAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("NonceAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("NonceAuthorityAccount", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" Nonce", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("NonceAuthority", inst.AccountMetaSlice[1])) }) }) }) diff --git a/programs/system/CreateAccount.go b/programs/system/CreateAccount.go index 0ba84047..921626b3 100644 --- a/programs/system/CreateAccount.go +++ b/programs/system/CreateAccount.go @@ -127,14 +127,14 @@ func (inst *CreateAccount) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { paramsBranch.Child(ag_format.Param("Lamports", *inst.Lamports)) - paramsBranch.Child(ag_format.Param("Space", *inst.Space)) - paramsBranch.Child(ag_format.Param("Owner", *inst.Owner)) + paramsBranch.Child(ag_format.Param(" Space", *inst.Space)) + paramsBranch.Child(ag_format.Param(" Owner", *inst.Owner)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("FundingAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("NewAccount", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("Funding", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" New", inst.AccountMetaSlice[1])) }) }) }) diff --git a/programs/system/CreateAccountWithSeed.go b/programs/system/CreateAccountWithSeed.go index 56c466c1..c1751031 100644 --- a/programs/system/CreateAccountWithSeed.go +++ b/programs/system/CreateAccountWithSeed.go @@ -171,18 +171,18 @@ func (inst *CreateAccountWithSeed) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Base", *inst.Base)) - paramsBranch.Child(ag_format.Param("Seed", *inst.Seed)) + paramsBranch.Child(ag_format.Param(" Base", *inst.Base)) + paramsBranch.Child(ag_format.Param(" Seed", *inst.Seed)) paramsBranch.Child(ag_format.Param("Lamports", *inst.Lamports)) - paramsBranch.Child(ag_format.Param("Space", *inst.Space)) - paramsBranch.Child(ag_format.Param("Owner", *inst.Owner)) + paramsBranch.Child(ag_format.Param(" Space", *inst.Space)) + paramsBranch.Child(ag_format.Param(" Owner", *inst.Owner)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("FundingAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("CreatedAccount", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("BaseAccount", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("Funding", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("Created", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" Base", inst.AccountMetaSlice[2])) }) }) }) diff --git a/programs/system/InitializeNonceAccount.go b/programs/system/InitializeNonceAccount.go index 3d21c05e..eb7f71b3 100644 --- a/programs/system/InitializeNonceAccount.go +++ b/programs/system/InitializeNonceAccount.go @@ -124,9 +124,9 @@ func (inst *InitializeNonceAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("NonceAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("$(SysVarRecentBlockHashesPubkey)", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" Nonce", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("SysVarRecentBlockHashes", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" SysVarRent", inst.AccountMetaSlice[2])) }) }) }) diff --git a/programs/system/Transfer.go b/programs/system/Transfer.go index 78f96df9..868c51c5 100644 --- a/programs/system/Transfer.go +++ b/programs/system/Transfer.go @@ -107,8 +107,8 @@ func (inst *Transfer) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("FundingAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("RecipientAccount", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" Funding", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("Recipient", inst.AccountMetaSlice[1])) }) }) }) diff --git a/programs/system/TransferWithSeed.go b/programs/system/TransferWithSeed.go index ac12f6a4..d24b7876 100644 --- a/programs/system/TransferWithSeed.go +++ b/programs/system/TransferWithSeed.go @@ -139,16 +139,16 @@ func (inst *TransferWithSeed) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Lamports", *inst.Lamports)) - paramsBranch.Child(ag_format.Param("FromSeed", *inst.FromSeed)) + paramsBranch.Child(ag_format.Param(" Lamports", *inst.Lamports)) + paramsBranch.Child(ag_format.Param(" FromSeed", *inst.FromSeed)) paramsBranch.Child(ag_format.Param("FromOwner", *inst.FromOwner)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("FundingAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("BaseForFundingAccount", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("RecipientAccount", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" Funding", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("BaseForFunding", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" Recipient", inst.AccountMetaSlice[2])) }) }) }) diff --git a/programs/system/WithdrawNonceAccount.go b/programs/system/WithdrawNonceAccount.go index b023da10..f6846d53 100644 --- a/programs/system/WithdrawNonceAccount.go +++ b/programs/system/WithdrawNonceAccount.go @@ -148,11 +148,11 @@ func (inst *WithdrawNonceAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("NonceAccount", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("RecipientAccount", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("$(SysVarRecentBlockHashesPubkey)", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[3])) - accountsBranch.Child(ag_format.Meta("NonceAuthorityAccount", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta(" Nonce", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" Recipient", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("SysVarRecentBlockHashes", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" SysVarRent", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" NonceAuthority", inst.AccountMetaSlice[4])) }) }) }) From 2ac6e1b03ffa22f2f32752803d0dd5c138ce2b5d Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 13:24:02 +0200 Subject: [PATCH 14/24] EncodeToTree on Transaction, Message: include lengths --- transaction.go | 4 ++-- types.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/transaction.go b/transaction.go index 484f2d98..c99f1e4a 100644 --- a/transaction.go +++ b/transaction.go @@ -337,7 +337,7 @@ func (tx *Transaction) EncodeTree(encoder *text.TreeEncoder) (int, error) { func (tx *Transaction) EncodeToTree(parent treeout.Branches) { parent.ParentFunc(func(txTree treeout.Branches) { - txTree.Child("Signatures[]").ParentFunc(func(signaturesBranch treeout.Branches) { + txTree.Child(fmt.Sprintf("Signatures[len=%v]", len(tx.Signatures))).ParentFunc(func(signaturesBranch treeout.Branches) { for _, sig := range tx.Signatures { signaturesBranch.Child(sig.String()) } @@ -348,7 +348,7 @@ func (tx *Transaction) EncodeToTree(parent treeout.Branches) { }) }) - parent.Child("Instructions[]").ParentFunc(func(message treeout.Branches) { + parent.Child(fmt.Sprintf("Instructions[len=%v]", len(tx.Message.Instructions))).ParentFunc(func(message treeout.Branches) { for _, inst := range tx.Message.Instructions { progKey, err := tx.ResolveProgramIDIndex(inst.ProgramIDIndex) diff --git a/types.go b/types.go index 7ab1cffa..f01167ff 100644 --- a/types.go +++ b/types.go @@ -66,7 +66,7 @@ var _ bin.EncoderDecoder = &Message{} func (mx *Message) EncodeToTree(txTree treeout.Branches) { txTree.Child(text.Sf("RecentBlockhash: %s", mx.RecentBlockhash)) - txTree.Child("AccountKeys[]").ParentFunc(func(accountKeysBranch treeout.Branches) { + txTree.Child(fmt.Sprintf("AccountKeys[len=%v]", len(mx.AccountKeys))).ParentFunc(func(accountKeysBranch treeout.Branches) { for _, key := range mx.AccountKeys { accountKeysBranch.Child(text.ColorizeBG(key.String())) } From d20a34fd6dea6de337a1ce5432b3f9eb8c688d91 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 14:00:09 +0200 Subject: [PATCH 15/24] Tree formatter: align params and accounts --- programs/token/Approve.go | 10 +++++++--- programs/token/ApproveChecked.go | 14 +++++++++----- programs/token/Burn.go | 10 +++++++--- programs/token/BurnChecked.go | 12 ++++++++---- programs/token/CloseAccount.go | 10 +++++++--- programs/token/FreezeAccount.go | 10 +++++++--- programs/token/InitializeAccount.go | 8 ++++---- programs/token/InitializeAccount2.go | 6 +++--- programs/token/InitializeAccount3.go | 2 +- programs/token/InitializeMint.go | 10 +++++----- programs/token/InitializeMint2.go | 6 +++--- programs/token/InitializeMultisig.go | 10 +++++++--- programs/token/InitializeMultisig2.go | 6 +++++- programs/token/MintTo.go | 11 +++++++---- programs/token/MintToChecked.go | 12 ++++++++---- programs/token/Revoke.go | 8 ++++++-- programs/token/SetAuthority.go | 12 ++++++++---- programs/token/ThawAccount.go | 10 +++++++--- programs/token/Transfer.go | 10 +++++++--- programs/token/TransferChecked.go | 14 +++++++++----- 20 files changed, 125 insertions(+), 66 deletions(-) diff --git a/programs/token/Approve.go b/programs/token/Approve.go index d5687ef8..1d8c555d 100644 --- a/programs/token/Approve.go +++ b/programs/token/Approve.go @@ -164,13 +164,17 @@ func (inst *Approve) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" source", inst.Accounts[0])) accountsBranch.Child(ag_format.Meta("delegate", inst.Accounts[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/ApproveChecked.go b/programs/token/ApproveChecked.go index 86ab1796..2dbb05e0 100644 --- a/programs/token/ApproveChecked.go +++ b/programs/token/ApproveChecked.go @@ -195,20 +195,24 @@ func (inst *ApproveChecked) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + paramsBranch.Child(ag_format.Param(" Amount", *inst.Amount)) paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta(" source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[1])) accountsBranch.Child(ag_format.Meta("delegate", inst.Accounts[2])) - accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[3])) + accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[3])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/Burn.go b/programs/token/Burn.go index 78f565e2..d0a6946a 100644 --- a/programs/token/Burn.go +++ b/programs/token/Burn.go @@ -165,12 +165,16 @@ func (inst *Burn) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/BurnChecked.go b/programs/token/BurnChecked.go index b3c70759..19dbf366 100644 --- a/programs/token/BurnChecked.go +++ b/programs/token/BurnChecked.go @@ -177,19 +177,23 @@ func (inst *BurnChecked) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + paramsBranch.Child(ag_format.Param(" Amount", *inst.Amount)) paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/CloseAccount.go b/programs/token/CloseAccount.go index 42f19891..a9e4a448 100644 --- a/programs/token/CloseAccount.go +++ b/programs/token/CloseAccount.go @@ -146,13 +146,17 @@ func (inst *CloseAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" account", inst.Accounts[0])) accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/FreezeAccount.go b/programs/token/FreezeAccount.go index 9082a117..679287e0 100644 --- a/programs/token/FreezeAccount.go +++ b/programs/token/FreezeAccount.go @@ -145,13 +145,17 @@ func (inst *FreezeAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta(" account", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[1])) accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/InitializeAccount.go b/programs/token/InitializeAccount.go index 88700499..24706b0f 100644 --- a/programs/token/InitializeAccount.go +++ b/programs/token/InitializeAccount.go @@ -146,10 +146,10 @@ func (inst *InitializeAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" owner", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("SysVarRent", inst.AccountMetaSlice[3])) }) }) }) diff --git a/programs/token/InitializeAccount2.go b/programs/token/InitializeAccount2.go index 28ad5793..0b7ecbc7 100644 --- a/programs/token/InitializeAccount2.go +++ b/programs/token/InitializeAccount2.go @@ -138,9 +138,9 @@ func (inst *InitializeAccount2) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" account", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("SysVarRent", inst.AccountMetaSlice[2])) }) }) }) diff --git a/programs/token/InitializeAccount3.go b/programs/token/InitializeAccount3.go index 243df14b..b7e8d1d6 100644 --- a/programs/token/InitializeAccount3.go +++ b/programs/token/InitializeAccount3.go @@ -116,7 +116,7 @@ func (inst *InitializeAccount3) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("account", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" mint", inst.AccountMetaSlice[1])) }) }) }) diff --git a/programs/token/InitializeMint.go b/programs/token/InitializeMint.go index b4f1b034..f9c08148 100644 --- a/programs/token/InitializeMint.go +++ b/programs/token/InitializeMint.go @@ -141,15 +141,15 @@ func (inst *InitializeMint) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) - paramsBranch.Child(ag_format.Param("MintAuthority", *inst.MintAuthority)) - paramsBranch.Child(ag_format.Param("FreezeAuthority (OPTIONAL)", inst.FreezeAuthority)) + paramsBranch.Child(ag_format.Param(" Decimals", *inst.Decimals)) + paramsBranch.Child(ag_format.Param(" MintAuthority", *inst.MintAuthority)) + paramsBranch.Child(ag_format.Param("FreezeAuthority (OPT)", inst.FreezeAuthority)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("mint", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" mint", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("SysVarRent", inst.AccountMetaSlice[1])) }) }) }) diff --git a/programs/token/InitializeMint2.go b/programs/token/InitializeMint2.go index a8486a90..c85772bd 100644 --- a/programs/token/InitializeMint2.go +++ b/programs/token/InitializeMint2.go @@ -114,9 +114,9 @@ func (inst *InitializeMint2) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) - paramsBranch.Child(ag_format.Param("MintAuthority", *inst.MintAuthority)) - paramsBranch.Child(ag_format.Param("FreezeAuthority (OPTIONAL)", inst.FreezeAuthority)) + paramsBranch.Child(ag_format.Param(" Decimals", *inst.Decimals)) + paramsBranch.Child(ag_format.Param(" MintAuthority", *inst.MintAuthority)) + paramsBranch.Child(ag_format.Param("FreezeAuthority (OPT)", inst.FreezeAuthority)) }) // Accounts of the instruction: diff --git a/programs/token/InitializeMultisig.go b/programs/token/InitializeMultisig.go index 025295da..9938d81f 100644 --- a/programs/token/InitializeMultisig.go +++ b/programs/token/InitializeMultisig.go @@ -161,12 +161,16 @@ func (inst *InitializeMultisig) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) - accountsBranch.Child(ag_format.Meta("$(SysVarRentPubkey)", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta(" account", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta("SysVarRent", inst.Accounts[1])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/InitializeMultisig2.go b/programs/token/InitializeMultisig2.go index 29edf4ad..670e1bc3 100644 --- a/programs/token/InitializeMultisig2.go +++ b/programs/token/InitializeMultisig2.go @@ -132,7 +132,11 @@ func (inst *InitializeMultisig2) EncodeToTree(parent ag_treeout.Branches) { signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/MintTo.go b/programs/token/MintTo.go index f5f9a609..8ec023b0 100644 --- a/programs/token/MintTo.go +++ b/programs/token/MintTo.go @@ -164,15 +164,18 @@ func (inst *MintTo) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[0])) accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) - accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta(" authority", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } - }) }) }) diff --git a/programs/token/MintToChecked.go b/programs/token/MintToChecked.go index 45c0d44f..090cc890 100644 --- a/programs/token/MintToChecked.go +++ b/programs/token/MintToChecked.go @@ -175,19 +175,23 @@ func (inst *MintToChecked) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + paramsBranch.Child(ag_format.Param(" Amount", *inst.Amount)) paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[0])) accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) - accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta(" authority", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/Revoke.go b/programs/token/Revoke.go index 97fcc426..5067fa9b 100644 --- a/programs/token/Revoke.go +++ b/programs/token/Revoke.go @@ -127,11 +127,15 @@ func (inst *Revoke) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) - accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[1])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/SetAuthority.go b/programs/token/SetAuthority.go index ef7f4452..5fc7eed1 100644 --- a/programs/token/SetAuthority.go +++ b/programs/token/SetAuthority.go @@ -149,18 +149,22 @@ func (inst *SetAuthority) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("AuthorityType", *inst.AuthorityType)) - paramsBranch.Child(ag_format.Param("NewAuthority (OPTIONAL)", inst.NewAuthority)) + paramsBranch.Child(ag_format.Param(" AuthorityType", *inst.AuthorityType)) + paramsBranch.Child(ag_format.Param("NewAuthority (OPT)", inst.NewAuthority)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("subject", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" subject", inst.Accounts[0])) accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[1])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/ThawAccount.go b/programs/token/ThawAccount.go index e8a5ddd1..90aaf081 100644 --- a/programs/token/ThawAccount.go +++ b/programs/token/ThawAccount.go @@ -145,13 +145,17 @@ func (inst *ThawAccount) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("account", inst.Accounts[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta(" account", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[1])) accountsBranch.Child(ag_format.Meta("authority", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/Transfer.go b/programs/token/Transfer.go index 45aea2a9..6104c0eb 100644 --- a/programs/token/Transfer.go +++ b/programs/token/Transfer.go @@ -166,13 +166,17 @@ func (inst *Transfer) EncodeToTree(parent ag_treeout.Branches) { // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" source", inst.Accounts[0])) accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[1])) - accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[2])) + accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[2])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) diff --git a/programs/token/TransferChecked.go b/programs/token/TransferChecked.go index dbfd2fd1..7cbd533a 100644 --- a/programs/token/TransferChecked.go +++ b/programs/token/TransferChecked.go @@ -197,20 +197,24 @@ func (inst *TransferChecked) EncodeToTree(parent ag_treeout.Branches) { // Parameters of the instruction: instructionBranch.Child("Params").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Amount", *inst.Amount)) + paramsBranch.Child(ag_format.Param(" Amount", *inst.Amount)) paramsBranch.Child(ag_format.Param("Decimals", *inst.Decimals)) }) // Accounts of the instruction: instructionBranch.Child("Accounts").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("source", inst.Accounts[0])) - accountsBranch.Child(ag_format.Meta("mint", inst.Accounts[1])) + accountsBranch.Child(ag_format.Meta(" source", inst.Accounts[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.Accounts[1])) accountsBranch.Child(ag_format.Meta("destination", inst.Accounts[2])) - accountsBranch.Child(ag_format.Meta("owner", inst.Accounts[3])) + accountsBranch.Child(ag_format.Meta(" owner", inst.Accounts[3])) signersBranch := accountsBranch.Child(fmt.Sprintf("signers[len=%v]", len(inst.Signers))) for i, v := range inst.Signers { - signersBranch.Child(ag_format.Meta(fmt.Sprintf("signers[%v]", i), v)) + if len(inst.Signers) > 9 && i < 10 { + signersBranch.Child(ag_format.Meta(fmt.Sprintf(" [%v]", i), v)) + } else { + signersBranch.Child(ag_format.Meta(fmt.Sprintf("[%v]", i), v)) + } } }) }) From d6cc34649f80dcf8f95f8429277e5f13915011a9 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 15:45:03 +0200 Subject: [PATCH 16/24] Fix tree visualizer of transaction --- go.mod | 2 +- go.sum | 4 ++-- text/format/format.go | 29 ++++++++++++++++++++++++++++- text/tools.go | 4 ---- text/tree.go | 4 ++-- transaction.go | 4 ++-- 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 2adc5bc8..41da33d6 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/fatih/color v1.7.0 github.com/gagliardetto/binary v0.4.1 github.com/gagliardetto/gofuzz v1.2.2 - github.com/gagliardetto/treeout v0.1.2 + github.com/gagliardetto/treeout v0.1.4 github.com/google/go-cmp v0.5.1 github.com/gorilla/rpc v1.2.0 github.com/gorilla/websocket v1.4.2 diff --git a/go.sum b/go.sum index ba847950..a3f543b2 100644 --- a/go.sum +++ b/go.sum @@ -93,8 +93,8 @@ github.com/gagliardetto/binary v0.4.1 h1:3HXeBOfmR2HHIrF1YBnoqgFKQBtN8+rWA770KyX github.com/gagliardetto/binary v0.4.1/go.mod h1:peJR9PvwamL4YOh1nHWCPLry2VEfeeD1ADvewka7HnQ= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= -github.com/gagliardetto/treeout v0.1.2 h1:WXO7LDJTwINO37OQfNlf7s095Z1bAiwN2ACaZQic33Q= -github.com/gagliardetto/treeout v0.1.2/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= +github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= +github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= diff --git a/text/format/format.go b/text/format/format.go index 1e8a3fac..979341ca 100644 --- a/text/format/format.go +++ b/text/format/format.go @@ -18,7 +18,15 @@ func Instruction(name string) string { } func Param(name string, value interface{}) string { - return Sf(CC(Shakespeare(name), ": %s"), Lime(strings.TrimSpace(spew.Sdump(value)))) + return Sf( + Shakespeare(name)+": %s", + strings.TrimSpace( + prefixEachLineExceptFirst( + strings.Repeat(" ", len(name)+2), + strings.TrimSpace(spew.Sdump(value)), + ), + ), + ) } func Account(name string, pubKey solana.PublicKey) string { @@ -40,3 +48,22 @@ func Meta(name string, meta *solana.AccountMeta) string { out += "] " return out } + +func prefixEachLineExceptFirst(prefix string, s string) string { + return foreachLine(s, + func(i int, line string) string { + if i == 0 { + return Lime(line) + "\n" + } + return prefix + Lime(line) + "\n" + }) +} + +type sf func(int, string) string + +func foreachLine(str string, transform sf) (out string) { + for idx, line := range strings.Split(str, "\n") { + out += transform(idx, line) + } + return +} diff --git a/text/tools.go b/text/tools.go index 65ddb33a..4d841044 100644 --- a/text/tools.go +++ b/text/tools.go @@ -173,14 +173,10 @@ func Bold(str string) string { type sf func(int, string) string -// Apply given transformation func for each line in string func foreachLine(str string, transform sf) (out string) { - out = "" - for idx, line := range strings.Split(str, "\n") { out += transform(idx, line) } - return } diff --git a/text/tree.go b/text/tree.go index 55393e57..a28239a5 100644 --- a/text/tree.go +++ b/text/tree.go @@ -15,10 +15,10 @@ type EncodableToTree interface { EncodeToTree(parent treeout.Branches) } -func NewTreeEncoder(w io.Writer, docs ...string) *TreeEncoder { +func NewTreeEncoder(w io.Writer, doc string) *TreeEncoder { return &TreeEncoder{ output: w, - Tree: treeout.New(docs...), + Tree: treeout.New(doc), } } diff --git a/transaction.go b/transaction.go index c99f1e4a..c05dff7d 100644 --- a/transaction.go +++ b/transaction.go @@ -327,8 +327,8 @@ func (tx *Transaction) Sign(getter privateKeyGetter) (out []Signature, err error } func (tx *Transaction) EncodeTree(encoder *text.TreeEncoder) (int, error) { - if len(encoder.Docs) == 0 { - encoder.Docs = []string{"Transaction"} + if len(encoder.Doc) == 0 { + encoder.Doc = "Transaction" } tx.EncodeToTree(encoder) return encoder.WriteString(encoder.Tree.String()) From 3d58df10e879d7a562b142e2aed921e8a3e2ebd3 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 16:01:40 +0200 Subject: [PATCH 17/24] Improve DecodeInstruction error --- registry.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry.go b/registry.go index 61477f93..8d68489d 100644 --- a/registry.go +++ b/registry.go @@ -21,11 +21,11 @@ func RegisterInstructionDecoder(programID PublicKey, decoder InstructionDecoder) } func DecodeInstruction(programID PublicKey, accounts []*AccountMeta, data []byte) (interface{}, error) { - p := programID.String() + pid := programID.String() - decoder, found := InstructionDecoderRegistry[p] + decoder, found := InstructionDecoderRegistry[pid] if !found { - return nil, fmt.Errorf("unknown programID, cannot find any instruction decoder %q", p) + return nil, fmt.Errorf("instruction decoder not found for %s", pid) } return decoder(accounts, data) From b124787015efc244081a98329ad03cea11416ec9 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 17:58:08 +0200 Subject: [PATCH 18/24] Improve naming --- registry.go | 8 +-- rpc/sendAndConfirmTransaction.go | 52 ++++++++++++++++++ .../sendAndConfirmTransaction.go | 53 +++++++++++++++++++ 3 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 rpc/sendAndConfirmTransaction.go create mode 100644 rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go diff --git a/registry.go b/registry.go index 8d68489d..a3a0ae8b 100644 --- a/registry.go +++ b/registry.go @@ -12,12 +12,12 @@ type InstructionDecoder func(instructionAccounts []*AccountMeta, data []byte) (i var InstructionDecoderRegistry = map[string]InstructionDecoder{} func RegisterInstructionDecoder(programID PublicKey, decoder InstructionDecoder) { - p := programID.String() - if _, found := InstructionDecoderRegistry[p]; found { - panic(fmt.Sprintf("unable to re-register instruction decoder for program %q", p)) + pid := programID.String() + if _, found := InstructionDecoderRegistry[pid]; found { + panic(fmt.Sprintf("unable to re-register instruction decoder for program %q", pid)) } - InstructionDecoderRegistry[p] = decoder + InstructionDecoderRegistry[pid] = decoder } func DecodeInstruction(programID PublicKey, accounts []*AccountMeta, data []byte) (interface{}, error) { diff --git a/rpc/sendAndConfirmTransaction.go b/rpc/sendAndConfirmTransaction.go new file mode 100644 index 00000000..ee39146c --- /dev/null +++ b/rpc/sendAndConfirmTransaction.go @@ -0,0 +1,52 @@ +package rpc + +import ( + "context" + + "github.com/davecgh/go-spew/spew" + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc/ws" +) + +func (cl *Client) SendAndConfirmTransactionWithOpts( + ctx context.Context, + transaction *solana.Transaction, + skipPreflight bool, // if true, skip the preflight transaction checks (default: false) + preflightCommitment CommitmentType, // optional; Commitment level to use for preflight (default: "finalized"). +) (signature solana.Signature, err error) { + + sig, err := cl.SendTransactionWithOpts( + ctx, + transaction, + skipPreflight, + preflightCommitment, + ) + if err != nil { + return sig, err + } + + client, err := ws.Connect(context.Background(), TestNet_WS) + if err != nil { + panic(err) + } + + txSig := solana.MustSignatureFromBase58("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") + + sub, err := client.SignatureSubscribe( + txSig, + "", + ) + if err != nil { + panic(err) + } + defer sub.Unsubscribe() + + for { + got, err := sub.Recv() + if err != nil { + panic(err) + } + spew.Dump(got) + } + return +} diff --git a/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go b/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go new file mode 100644 index 00000000..0942fd82 --- /dev/null +++ b/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go @@ -0,0 +1,53 @@ +package sendandconfirmtransaction + +import ( + "context" + "fmt" + + "github.com/davecgh/go-spew/spew" + "github.com/gagliardetto/solana-go" + "github.com/gagliardetto/solana-go/rpc" + "github.com/gagliardetto/solana-go/rpc/ws" +) + +func SendAndConfirmTransactionWithOpts( + ctx context.Context, + rpcClient *rpc.Client, + wsClient *ws.Client, + transaction *solana.Transaction, + skipPreflight bool, // if true, skip the preflight transaction checks (default: false) + preflightCommitment rpc.CommitmentType, // optional; Commitment level to use for preflight (default: "finalized"). +) (signature solana.Signature, err error) { + + sig, err := rpcClient.SendTransactionWithOpts( + ctx, + transaction, + skipPreflight, + preflightCommitment, + ) + if err != nil { + return sig, err + } + + sub, err := wsClient.SignatureSubscribe( + sig, + rpc.CommitmentConfirmed, + ) + if err != nil { + panic(err) + } + defer sub.Unsubscribe() + + for { + got, err := sub.Recv() + if err != nil { + return sig, err + } + spew.Dump(got) + if got.Value.Err != nil { + return sig, fmt.Errorf("confirmation error: %v", got.Value.Err) + } else { + return sig, nil + } + } +} From b57a76710819dc1c0d548213764fd48edf38099a Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 18:02:45 +0200 Subject: [PATCH 19/24] Add SendAndConfirmTransaction --- rpc/sendAndConfirmTransaction.go | 52 ------------------- .../sendAndConfirmTransaction.go | 24 +++++++-- 2 files changed, 20 insertions(+), 56 deletions(-) delete mode 100644 rpc/sendAndConfirmTransaction.go diff --git a/rpc/sendAndConfirmTransaction.go b/rpc/sendAndConfirmTransaction.go deleted file mode 100644 index ee39146c..00000000 --- a/rpc/sendAndConfirmTransaction.go +++ /dev/null @@ -1,52 +0,0 @@ -package rpc - -import ( - "context" - - "github.com/davecgh/go-spew/spew" - "github.com/gagliardetto/solana-go" - "github.com/gagliardetto/solana-go/rpc/ws" -) - -func (cl *Client) SendAndConfirmTransactionWithOpts( - ctx context.Context, - transaction *solana.Transaction, - skipPreflight bool, // if true, skip the preflight transaction checks (default: false) - preflightCommitment CommitmentType, // optional; Commitment level to use for preflight (default: "finalized"). -) (signature solana.Signature, err error) { - - sig, err := cl.SendTransactionWithOpts( - ctx, - transaction, - skipPreflight, - preflightCommitment, - ) - if err != nil { - return sig, err - } - - client, err := ws.Connect(context.Background(), TestNet_WS) - if err != nil { - panic(err) - } - - txSig := solana.MustSignatureFromBase58("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") - - sub, err := client.SignatureSubscribe( - txSig, - "", - ) - if err != nil { - panic(err) - } - defer sub.Unsubscribe() - - for { - got, err := sub.Recv() - if err != nil { - panic(err) - } - spew.Dump(got) - } - return -} diff --git a/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go b/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go index 0942fd82..fa391630 100644 --- a/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go +++ b/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go @@ -4,12 +4,29 @@ import ( "context" "fmt" - "github.com/davecgh/go-spew/spew" "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" "github.com/gagliardetto/solana-go/rpc/ws" ) +// Send and wait for confirmation of a transaction. +func SendAndConfirmTransaction( + ctx context.Context, + rpcClient *rpc.Client, + wsClient *ws.Client, + transaction *solana.Transaction, +) (signature solana.Signature, err error) { + return SendAndConfirmTransactionWithOpts( + ctx, + rpcClient, + wsClient, + transaction, + false, + rpc.CommitmentFinalized, + ) +} + +// Send and wait for confirmation of a transaction. func SendAndConfirmTransactionWithOpts( ctx context.Context, rpcClient *rpc.Client, @@ -31,10 +48,10 @@ func SendAndConfirmTransactionWithOpts( sub, err := wsClient.SignatureSubscribe( sig, - rpc.CommitmentConfirmed, + rpc.CommitmentFinalized, ) if err != nil { - panic(err) + return sig, err } defer sub.Unsubscribe() @@ -43,7 +60,6 @@ func SendAndConfirmTransactionWithOpts( if err != nil { return sig, err } - spew.Dump(got) if got.Value.Err != nil { return sig, fmt.Errorf("confirmation error: %v", got.Value.Err) } else { From b0c07ef8eae8f4756dd7429dbcbbbcd6e185bf17 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 18:02:53 +0200 Subject: [PATCH 20/24] Add LocalNet_WS --- rpc/endpoints.go | 1 + 1 file changed, 1 insertion(+) diff --git a/rpc/endpoints.go b/rpc/endpoints.go index d60116ea..2a387e05 100644 --- a/rpc/endpoints.go +++ b/rpc/endpoints.go @@ -27,4 +27,5 @@ const ( TestNet_WS = protocolWSS + hostTestNet MainNetBeta_WS = protocolWSS + hostMainNetBeta MainNetBetaSerum_WS = protocolWSS + hostMainNetBetaSerum + LocalNet_WS = "ws://127.0.0.1:8900" ) From 328bcea00daa38170cfed0a65743e110649ef8f0 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 18:03:13 +0200 Subject: [PATCH 21/24] Fix format.Meta --- text/format/format.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/format/format.go b/text/format/format.go index 979341ca..fb0f53ad 100644 --- a/text/format/format.go +++ b/text/format/format.go @@ -40,7 +40,7 @@ func Meta(name string, meta *solana.AccountMeta) string { out += "WRITE" } if meta.IsSigner { - if meta.IsSigner { + if meta.IsWritable { out += ", " } out += "SIGN" From ef5ea7ca0fa95947b3118b49e505e083f2d470b1 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 18:04:17 +0200 Subject: [PATCH 22/24] Improve confirmation error --- rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go b/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go index fa391630..06fd547b 100644 --- a/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go +++ b/rpc/sendAndConfirmTransaction/sendAndConfirmTransaction.go @@ -61,7 +61,7 @@ func SendAndConfirmTransactionWithOpts( return sig, err } if got.Value.Err != nil { - return sig, fmt.Errorf("confirmation error: %v", got.Value.Err) + return sig, fmt.Errorf("transaction confirmation failed: %v", got.Value.Err) } else { return sig, nil } From 611f6cdfaf001de5874299881f9b6fbf85522b54 Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 18:19:12 +0200 Subject: [PATCH 23/24] WS: fix ping/pong --- rpc/ws/client.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/rpc/ws/client.go b/rpc/ws/client.go index 2fda3530..2d316907 100644 --- a/rpc/ws/client.go +++ b/rpc/ws/client.go @@ -40,6 +40,15 @@ type Client struct { reconnectOnErr bool } +const ( + // Time allowed to write a message to the peer. + writeWait = 10 * time.Second + // Time allowed to read the next pong message from the peer. + pongWait = 60 * time.Second + // Send pings to peer with this period. Must be less than pongWait. + pingPeriod = (pongWait * 9) / 10 +) + // Connect creates a new websocket client connecting to the provided endpoint. func Connect(ctx context.Context, rpcEndpoint string) (c *Client, err error) { c = &Client{ @@ -60,12 +69,17 @@ func Connect(ctx context.Context, rpcEndpoint string) (c *Client, err error) { } go func() { + c.conn.SetReadDeadline(time.Now().Add(pongWait)) + c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil }) + ticker := time.NewTicker(pingPeriod) for { - c.conn.SetWriteDeadline(time.Now().Add(10 * time.Second)) - if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil { - return + select { + case <-ticker.C: + c.conn.SetWriteDeadline(time.Now().Add(writeWait)) + if err := c.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil { + return + } } - time.Sleep(20 * time.Second) } }() go c.receiveMessages() From 18f8518a351bfd02ced3cada055830c34381e4bf Mon Sep 17 00:00:00 2001 From: Slavomir Date: Mon, 6 Sep 2021 18:36:56 +0200 Subject: [PATCH 24/24] Bump version to v0.4.4 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 93bb9638..1a817088 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Solana SDK library for Go -[![GoDoc](https://pkg.go.dev/badge/github.com/gagliardetto/solana-go?status.svg)](https://pkg.go.dev/github.com/gagliardetto/solana-go@v0.4.3?tab=doc) +[![GoDoc](https://pkg.go.dev/badge/github.com/gagliardetto/solana-go?status.svg)](https://pkg.go.dev/github.com/gagliardetto/solana-go@v0.4.4?tab=doc) [![GitHub tag (latest SemVer pre-release)](https://img.shields.io/github/v/tag/gagliardetto/solana-go?include_prereleases&label=release-tag)](https://github.com/gagliardetto/solana-go/releases) [![Build Status](https://github.com/gagliardetto/solana-go/workflows/tests/badge.svg?branch=main)](https://github.com/gagliardetto/solana-go/actions?query=branch%3Amain) [![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/gagliardetto/solana-go/main)](https://www.tickgit.com/browse?repo=github.com/gagliardetto/solana-go&branch=main) @@ -57,7 +57,7 @@ More contracts to come. ## Current development status -There is currently **no stable release**. The SDK is actively developed and latest is `v0.4.3` which is an `alpha` release. +There is currently **no stable release**. The SDK is actively developed and latest is `v0.4.4` which is an `alpha` release. The RPC and WS client implementation is based on [this RPC spec](https://github.com/solana-labs/solana/blob/dff9c88193da142693cabebfcd3bf68fa8e8b873/docs/src/developing/clients/jsonrpc-api.md). @@ -71,7 +71,7 @@ The RPC and WS client implementation is based on [this RPC spec](https://github. ```bash $ cd my-project -$ go get github.com/gagliardetto/solana-go@v0.4.3 +$ go get github.com/gagliardetto/solana-go@v0.4.4 $ go get github.com/gagliardetto/binary@v0.4.1 $ go get github.com/gagliardetto/gofuzz@v1.2.2 ```