Class: SolanaRuby::TransactionHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/solana_ruby/transaction_helper.rb

Constant Summary collapse

SYSTEM_PROGRAM_ID =

Constants for program IDs

'11111111111111111111111111111111'
TOKEN_PROGRAM_ID =
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
ASSOCIATED_TOKEN_PROGRAM_ID =
'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL'
SYSVAR_RENT_ID =
'SysvarRent111111111111111111111111111111111'
INSTRUCTION_LAYOUTS =
{
  # Native SOL transfer
  sol_transfer: {
    instruction: :uint32,
    lamports: :near_int64
  },
  # SPL token transfer
  spl_transfer: {
    instruction: :uint8,
    amount: :uint64
  },
  # Create account layout
  create_account: {
    instruction: :uint32,
    lamports: :uint64,
    space: :uint64,
    program_id: :blob32
  },
  # SPL token transfer_checked
  spl_transfer_checked: {
    instruction: :uint8,
    amount: :uint64,
    decimals: :uint8
  },
  # mint spl tokens
  spl_mint_to: {
    instruction: :uint8,
    amount: :uint64
  },
  # burn spl tokens
  spl_burn: {
    instruction: :uint8,
    amount: :uint64
  },
  # Close account layout (added here)
  close_account: {
    instruction: :uint8
  }
}

Class Method Summary collapse

Class Method Details

.account_instruction(from_pubkey, new_account_pubkey, lamports, space, program_id) ⇒ Object

Method to create a system account (e.g., for SPL token or SOL)



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/solana_ruby/transaction_helper.rb', line 53

def self.(from_pubkey, , lamports, space, program_id)
  # Encode the instruction data
  instruction_data = encode_data(
    INSTRUCTION_LAYOUTS[:create_account],
    {
      instruction: 0,      # '0' corresponds to the Create Account instruction
      lamports: lamports,  # The amount of lamports to transfer to the new account
      space: space,        # Amount of space allocated for the account's data
      program_id: Base58.base58_to_binary(program_id, :bitcoin).bytes # Convert public key to binary
    }
  )

  keys = [
    { pubkey: from_pubkey, is_signer: true, is_writable: true },  # Funder's account
    { pubkey: , is_signer: true, is_writable: true } # New account
  ]

  # return instruction data
  create_instruction(keys, instruction_data, program_id)
end

.burn_spl_token(token_account, mint, mint_authority, amount, multi_signers = []) ⇒ Object

Method to create a burn instruction for SPL tokens



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/solana_ruby/transaction_helper.rb', line 222

def self.burn_spl_token(, mint, mint_authority, amount, multi_signers = [])
  # Define the fields for the burn instruction
  fields = INSTRUCTION_LAYOUTS[:spl_burn]
  
  # Encode the instruction data
  data = encode_data(fields, { instruction: 8, amount: amount }) # Instruction type 8: Burn

  keys = SolanaRuby::TransactionHelpers::TokenAccount.add_signers(
    [
      { pubkey: , is_signer: false, is_writable: true }, # Token account holding tokens to burn
      { pubkey: mint, is_signer: false, is_writable: true }          # Mint address
    ], mint_authority, multi_signers)

  # Return the transaction instruction
  create_instruction(keys, data)
end

.burn_spl_tokens(token_account, mint, owner, amount, recent_blockhash, multi_signers = []) ⇒ Object

Helper to create a transaction for burning SPL tokens



240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/solana_ruby/transaction_helper.rb', line 240

def self.burn_spl_tokens(, mint, owner, amount, recent_blockhash, multi_signers = [])
  # Create a new transaction
  transaction = Transaction.new
  transaction.set_fee_payer(owner)
  transaction.set_recent_blockhash(recent_blockhash)

  # Add the burn instruction to the transaction
  burn_instruction = burn_spl_token(, mint, owner, amount, multi_signers)
  transaction.add_instruction(burn_instruction)

  # Return the transaction for signing
  transaction
end

.close_account(account_to_close, destination, owner, payer, multi_signers, recent_blockhash) ⇒ Object

Method to close an account (helper)



109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/solana_ruby/transaction_helper.rb', line 109

def self.(, destination, owner, payer, multi_signers, recent_blockhash)
  # Create the transaction
  transaction = Transaction.new
  transaction.set_fee_payer(payer)
  transaction.set_recent_blockhash(recent_blockhash)

  # Add the close account instruction to the transaction
  instruction = (, destination, owner, payer, multi_signers)
  transaction.add_instruction(instruction)

  # Return the transaction for signing
  transaction
end

.close_account_instruction(account_to_close, destination, owner, payer, multi_signers) ⇒ Object

Method to create a close account instruction



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/solana_ruby/transaction_helper.rb', line 90

def self.( , destination, owner, payer, multi_signers)
  # Encode the instruction data
  instruction_data = encode_data(
    INSTRUCTION_LAYOUTS[:close_account],
    { instruction: 9 } # Close account instruction number is 9
  )

  signer = multi_signers.empty? ? payer : multi_signers
  # Set up the keys for the close account instruction
  keys = SolanaRuby::TransactionHelpers::TokenAccount.add_signers(
    [{ pubkey: , is_signer: false, is_writable: true },
      { pubkey: destination, is_signer: false, is_writable: true }],
      owner, signer)

  # Return the instruction
  create_instruction(keys, instruction_data)
end

.create_account(from_pubkey, new_account_pubkey, lamports, space, recent_blockhash, program_id = SYSTEM_PROGRAM_ID) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/solana_ruby/transaction_helper.rb', line 75

def self.(from_pubkey, , lamports, space, recent_blockhash, program_id = SYSTEM_PROGRAM_ID)
  # Create the transaction
  transaction = Transaction.new
  transaction.set_fee_payer(from_pubkey)
  transaction.set_recent_blockhash(recent_blockhash)

  # Add the create account instruction to the transaction
  instruction = (from_pubkey, , lamports, space, program_id)
  transaction.add_instruction(instruction)
  
  # return the transaction for signing
  transaction
end

.create_associated_token_account(payer, mint, owner, recent_blockhash, program_id = SYSTEM_PROGRAM_ID) ⇒ Object

Method to create an associated token account



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/solana_ruby/transaction_helper.rb', line 169

def self.(payer, mint, owner, recent_blockhash, program_id = SYSTEM_PROGRAM_ID)
  transaction = Transaction.new
  transaction.set_fee_payer(payer)  # Payer funds the transaction
  transaction.set_recent_blockhash(recent_blockhash)

  # Derive the associated token account address
   = SolanaRuby::TransactionHelpers::TokenAccount.get_associated_token_address(mint, owner)
  puts "associated_token_account_pubkey: #{}"

  
  # Create the associated token account instruction
   = TransactionInstruction.new(
    keys: [
      { pubkey: payer, is_signer: true, is_writable: true },                 # Payer account
      { pubkey: , is_signer: false, is_writable: true },  # New ATA
      { pubkey: owner, is_signer: false, is_writable: false },               # Owner of the ATA
      { pubkey: mint, is_signer: false, is_writable: false },                # Token mint
      { pubkey: SYSTEM_PROGRAM_ID, is_signer: false, is_writable: false },   # System program
      { pubkey: TOKEN_PROGRAM_ID, is_signer: false, is_writable: false },   # Token program
      { pubkey: SYSVAR_RENT_ID, is_signer: false, is_writable: false }
    ],
    program_id: ASSOCIATED_TOKEN_PROGRAM_ID,
    data: []  # No data required for creating an associated token account
  )

  # Add the instruction to the transaction
  transaction.add_instruction()
  transaction
end

.create_instruction(keys, data, token_program_id = TOKEN_PROGRAM_ID) ⇒ Object



271
272
273
274
275
276
277
# File 'lib/solana_ruby/transaction_helper.rb', line 271

def self.create_instruction(keys, data, token_program_id = TOKEN_PROGRAM_ID)
  TransactionInstruction.new(
    keys: keys,
    program_id: token_program_id,
    data: data
  )
end

.decode_data(fields, data) ⇒ Object

Utility to decode data using predefined layouts



266
267
268
269
# File 'lib/solana_ruby/transaction_helper.rb', line 266

def self.decode_data(fields, data)
  layout = SolanaRuby::DataTypes::Layout.new(fields)
  layout.deserialize(data)
end

.encode_data(fields, data) ⇒ Object

Utility to encode data using predefined layouts



260
261
262
263
# File 'lib/solana_ruby/transaction_helper.rb', line 260

def self.encode_data(fields, data)
  layout = SolanaRuby::DataTypes::Layout.new(fields)
  layout.serialize(data)
end

.get_associated_token_address(mint, owner, program_id) ⇒ Object

Derive the associated token account address



255
256
257
# File 'lib/solana_ruby/transaction_helper.rb', line 255

def self.get_associated_token_address(mint, owner, program_id)
  SolanaRuby::TransactionHelpers::TokenAccount.get_associated_token_address(mint, owner, program_id)
end

.mint_spl_token(mint, destination, mint_authority, amount, multi_signers = []) ⇒ Object

Method to create a mint instruction for SPL tokens



200
201
202
203
204
205
206
207
208
209
# File 'lib/solana_ruby/transaction_helper.rb', line 200

def self.mint_spl_token(mint, destination, mint_authority, amount, multi_signers = [])
  fields = INSTRUCTION_LAYOUTS[:spl_mint_to]
  data = encode_data(fields, { instruction: 7, amount: amount }) # Instruction type 7: Mint to
  keys = SolanaRuby::TransactionHelpers::TokenAccount.add_signers(
    [{ pubkey: mint, is_signer: false, is_writable: true },
      { pubkey: destination, is_signer: false, is_writable: true }],
      mint_authority, multi_signers)

  create_instruction(keys, data)
end

.mint_spl_tokens(mint, destination, mint_authority, amount, recent_blockhash, multi_signers = []) ⇒ Object

Helper to create a transaction for minting SPL tokens



212
213
214
215
216
217
218
219
# File 'lib/solana_ruby/transaction_helper.rb', line 212

def self.mint_spl_tokens(mint, destination, mint_authority, amount, recent_blockhash, multi_signers = [])
  transaction = Transaction.new
  transaction.set_fee_payer(mint_authority)
  transaction.set_recent_blockhash(recent_blockhash)
  mint_instruction = mint_spl_token(mint, destination, mint_authority, amount, multi_signers)
  transaction.add_instruction(mint_instruction)
  transaction
end

.new_spl_token_transaction(source, mint, destination, owner, amount, decimals, recent_blockhash, multi_signers = []) ⇒ Object

Helper to create a new transaction for SPL token transfer



159
160
161
162
163
164
165
166
# File 'lib/solana_ruby/transaction_helper.rb', line 159

def self.new_spl_token_transaction(source, mint, destination, owner, amount, decimals, recent_blockhash, multi_signers=[])
  transaction = Transaction.new
  transaction.set_fee_payer(owner)
  transaction.set_recent_blockhash(recent_blockhash)
  transfer_instruction = transfer_spl_token(source, mint, destination, owner, amount, decimals, multi_signers)
  transaction.add_instruction(transfer_instruction)
  transaction
end

.sol_transfer(from_pubkey, to_pubkey, lamports, recent_blockhash) ⇒ Object

Helper to create a new transaction for SOL transfer



136
137
138
139
140
141
142
143
# File 'lib/solana_ruby/transaction_helper.rb', line 136

def self.sol_transfer(from_pubkey, to_pubkey, lamports, recent_blockhash)
  transaction = Transaction.new
  transaction.set_fee_payer(from_pubkey)
  transaction.set_recent_blockhash(recent_blockhash)
  transfer_instruction = transfer_sol_instruction(from_pubkey, to_pubkey, lamports)
  transaction.add_instruction(transfer_instruction)
  transaction
end

.transfer_sol_instruction(from_pubkey, to_pubkey, lamports) ⇒ Object

Method to create a SOL transfer instruction



124
125
126
127
128
129
130
131
132
133
# File 'lib/solana_ruby/transaction_helper.rb', line 124

def self.transfer_sol_instruction(from_pubkey, to_pubkey, lamports)
  fields = INSTRUCTION_LAYOUTS[:sol_transfer]
  data = encode_data(fields, { instruction: 2, lamports: lamports })
  keys = [
      { pubkey: from_pubkey, is_signer: true, is_writable: true },
      { pubkey: to_pubkey, is_signer: false, is_writable: true }
    ]

  create_instruction(keys, data, SYSTEM_PROGRAM_ID)
end

.transfer_spl_token(source, token, destination, owner, amount, decimals, multi_signers) ⇒ Object

Method to create an SPL token transfer instruction



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/solana_ruby/transaction_helper.rb', line 146

def self.transfer_spl_token(source, token, destination, owner, amount, decimals, multi_signers)
  fields = INSTRUCTION_LAYOUTS[:spl_transfer_checked]
  data = encode_data(fields, { instruction: 12, amount: amount, decimals: decimals }) # Instruction type 3: Transfer tokens
  keys = SolanaRuby::TransactionHelpers::TokenAccount.add_signers(
    [{ pubkey: source, is_signer: false, is_writable: true },
      { pubkey: token, is_signer: false, is_writable: false },
      { pubkey: destination, is_signer: false, is_writable: true }],
      owner, multi_signers)
  
  create_instruction(keys, data)
end