github.com/gagliardetto/solana-go@v1.11.0/programs/associated-token-account/Create.go (about) 1 // Copyright 2021 github.com/gagliardetto 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package associatedtokenaccount 16 17 import ( 18 "errors" 19 "fmt" 20 21 bin "github.com/gagliardetto/binary" 22 solana "github.com/gagliardetto/solana-go" 23 format "github.com/gagliardetto/solana-go/text/format" 24 treeout "github.com/gagliardetto/treeout" 25 ) 26 27 type Create struct { 28 Payer solana.PublicKey `bin:"-" borsh_skip:"true"` 29 Wallet solana.PublicKey `bin:"-" borsh_skip:"true"` 30 Mint solana.PublicKey `bin:"-" borsh_skip:"true"` 31 32 // [0] = [WRITE, SIGNER] Payer 33 // ··········· Funding account 34 // 35 // [1] = [WRITE] AssociatedTokenAccount 36 // ··········· Associated token account address to be created 37 // 38 // [2] = [] Wallet 39 // ··········· Wallet address for the new associated token account 40 // 41 // [3] = [] TokenMint 42 // ··········· The token mint for the new associated token account 43 // 44 // [4] = [] SystemProgram 45 // ··········· System program ID 46 // 47 // [5] = [] TokenProgram 48 // ··········· SPL token program ID 49 // 50 // [6] = [] SysVarRent 51 // ··········· SysVarRentPubkey 52 solana.AccountMetaSlice `bin:"-" borsh_skip:"true"` 53 } 54 55 // NewCreateInstructionBuilder creates a new `Create` instruction builder. 56 func NewCreateInstructionBuilder() *Create { 57 nd := &Create{} 58 return nd 59 } 60 61 func (inst *Create) SetPayer(payer solana.PublicKey) *Create { 62 inst.Payer = payer 63 return inst 64 } 65 66 func (inst *Create) SetWallet(wallet solana.PublicKey) *Create { 67 inst.Wallet = wallet 68 return inst 69 } 70 71 func (inst *Create) SetMint(mint solana.PublicKey) *Create { 72 inst.Mint = mint 73 return inst 74 } 75 76 func (inst Create) Build() *Instruction { 77 78 // Find the associatedTokenAddress; 79 associatedTokenAddress, _, _ := solana.FindAssociatedTokenAddress( 80 inst.Wallet, 81 inst.Mint, 82 ) 83 84 keys := []*solana.AccountMeta{ 85 { 86 PublicKey: inst.Payer, 87 IsSigner: true, 88 IsWritable: true, 89 }, 90 { 91 PublicKey: associatedTokenAddress, 92 IsSigner: false, 93 IsWritable: true, 94 }, 95 { 96 PublicKey: inst.Wallet, 97 IsSigner: false, 98 IsWritable: false, 99 }, 100 { 101 PublicKey: inst.Mint, 102 IsSigner: false, 103 IsWritable: false, 104 }, 105 { 106 PublicKey: solana.SystemProgramID, 107 IsSigner: false, 108 IsWritable: false, 109 }, 110 { 111 PublicKey: solana.TokenProgramID, 112 IsSigner: false, 113 IsWritable: false, 114 }, 115 { 116 PublicKey: solana.SysVarRentPubkey, 117 IsSigner: false, 118 IsWritable: false, 119 }, 120 } 121 122 inst.AccountMetaSlice = keys 123 124 return &Instruction{BaseVariant: bin.BaseVariant{ 125 Impl: inst, 126 TypeID: bin.NoTypeIDDefaultID, 127 }} 128 } 129 130 // ValidateAndBuild validates the instruction accounts. 131 // If there is a validation error, return the error. 132 // Otherwise, build and return the instruction. 133 func (inst Create) ValidateAndBuild() (*Instruction, error) { 134 if err := inst.Validate(); err != nil { 135 return nil, err 136 } 137 return inst.Build(), nil 138 } 139 140 func (inst *Create) Validate() error { 141 if inst.Payer.IsZero() { 142 return errors.New("Payer not set") 143 } 144 if inst.Wallet.IsZero() { 145 return errors.New("Wallet not set") 146 } 147 if inst.Mint.IsZero() { 148 return errors.New("Mint not set") 149 } 150 _, _, err := solana.FindAssociatedTokenAddress( 151 inst.Wallet, 152 inst.Mint, 153 ) 154 if err != nil { 155 return fmt.Errorf("error while FindAssociatedTokenAddress: %w", err) 156 } 157 return nil 158 } 159 160 func (inst *Create) EncodeToTree(parent treeout.Branches) { 161 parent.Child(format.Program(ProgramName, ProgramID)). 162 // 163 ParentFunc(func(programBranch treeout.Branches) { 164 programBranch.Child(format.Instruction("Create")). 165 // 166 ParentFunc(func(instructionBranch treeout.Branches) { 167 168 // Parameters of the instruction: 169 instructionBranch.Child("Params[len=0]").ParentFunc(func(paramsBranch treeout.Branches) {}) 170 171 // Accounts of the instruction: 172 instructionBranch.Child("Accounts[len=7").ParentFunc(func(accountsBranch treeout.Branches) { 173 accountsBranch.Child(format.Meta(" payer", inst.AccountMetaSlice.Get(0))) 174 accountsBranch.Child(format.Meta("associatedTokenAddress", inst.AccountMetaSlice.Get(1))) 175 accountsBranch.Child(format.Meta(" wallet", inst.AccountMetaSlice.Get(2))) 176 accountsBranch.Child(format.Meta(" tokenMint", inst.AccountMetaSlice.Get(3))) 177 accountsBranch.Child(format.Meta(" systemProgram", inst.AccountMetaSlice.Get(4))) 178 accountsBranch.Child(format.Meta(" tokenProgram", inst.AccountMetaSlice.Get(5))) 179 accountsBranch.Child(format.Meta(" sysVarRent", inst.AccountMetaSlice.Get(6))) 180 }) 181 }) 182 }) 183 } 184 185 func (inst Create) MarshalWithEncoder(encoder *bin.Encoder) error { 186 return encoder.WriteBytes([]byte{}, false) 187 } 188 189 func (inst *Create) UnmarshalWithDecoder(decoder *bin.Decoder) error { 190 return nil 191 } 192 193 func NewCreateInstruction( 194 payer solana.PublicKey, 195 walletAddress solana.PublicKey, 196 splTokenMintAddress solana.PublicKey, 197 ) *Create { 198 return NewCreateInstructionBuilder(). 199 SetPayer(payer). 200 SetWallet(walletAddress). 201 SetMint(splTokenMintAddress) 202 }