Skip to content

Create an Associated Token Account

pzupan edited this page Jul 5, 2026 · 1 revision

Create an Associated Token Account

A complete example showing how to create an SPL token account for a wallet. The ATA address is deterministic — derived from the wallet + mint — so no extra keypair is needed.

require 'base64'
require 'solana/ruby/kit'

Kit = Solana::Ruby::Kit

# ── 1. Signer and addresses ───────────────────────────────────────────────────

# Load your payer from 64 raw bytes (seed || public key).
# Replace File.binread with however you store your keypair.
payer = Kit::Signers.create_key_pair_signer_from_bytes(File.binread('wallet.bin'))

mint = Kit::Addresses.address('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v') # USDC

# ── 2. Build the instruction ──────────────────────────────────────────────────
# create_instruction derives the ATA address internally. Passing idempotent: true
# means the transaction succeeds even if the ATA already exists.

ix = Kit::Programs::AssociatedTokenAccount.create_instruction(
  payer:      payer.address,
  wallet:     payer.address,
  mint:       mint,
  idempotent: true
)

# The derived ATA address is the second account in the instruction.
puts "ATA address : #{ix.accounts[1].address}"

# ── 3. Fetch a recent blockhash ───────────────────────────────────────────────

rpc = Kit::Rpc::Client.new(Kit::RpcTypes.mainnet)

bh = rpc.get_latest_blockhash
constraint = Kit::TransactionMessages::BlockhashLifetimeConstraint.new(
  blockhash:               bh.value.blockhash,
  last_valid_block_height: bh.value.last_valid_block_height
)

# ── 4. Build the transaction message ─────────────────────────────────────────

message = Kit::Functional.pipe(
  Kit::TransactionMessages.create_transaction_message(version: :legacy),
  ->(tx) { Kit::TransactionMessages.set_fee_payer(payer.address, tx) },
  ->(tx) { Kit::TransactionMessages.set_blockhash_lifetime(constraint, tx) },
  ->(tx) { Kit::TransactionMessages.append_instructions(tx, [ix]) }
)

# ── 5. Compile → sign → encode → send ────────────────────────────────────────

# compile_transaction_message serialises the message into Solana's on-wire
# format and reserves a nil signature slot for every required signer.
transaction = Kit::Transactions.compile_transaction_message(message)

# sign_transaction fills every slot and raises if any signer is missing.
signed = Kit::Transactions.sign_transaction(
  [payer.key_pair.signing_key],
  transaction
)

# wire_encode_transaction prepends the compact-u16 signature count + raw
# 64-byte signatures to the message bytes — the full payload for sendTransaction.
wire_base64 = Base64.strict_encode64(
  Kit::Transactions.wire_encode_transaction(signed)
)

signature = rpc.send_transaction(wire_base64, skip_preflight: false)
puts "Transaction signature: #{signature}"

← Back to guides

Clone this wiki locally