solana_kit_memo 0.5.0 copy "solana_kit_memo: ^0.5.0" to clipboard
solana_kit_memo: ^0.5.0 copied to clipboard

Memo program client for the Solana Kit Dart SDK.

solana_kit_memo #

Coverage website Memo program client for the Solana Kit Dart SDK.

Provides generated codecs and ergonomic helpers for the Memo program, which attaches arbitrary UTF-8 memo text to Solana transactions.

Installation #

Installation #

Install the package directly:

dependencies:
  "solana_kit_memo": ^0.5.0

If your app uses several Solana Kit packages together, you can also depend on the umbrella package instead:

dart pub add solana_kit

Inside this monorepo, Dart workspace resolution uses the local package automatically.

Usage #

import 'package:solana_kit_address_constants/solana_kit_address_constants.dart';
import 'package:solana_kit_memo/solana_kit_memo.dart';

void main() {
  final instruction = getAddMemoInstruction(
    programAddress: memoProgramAddress,
    memo: 'Hello from Solana Kit',
  );

  print(instruction.programAddress);
}

Use memoLegacyProgramAddress (v1) or memoLegacyProgramAddressV3 when you need to target a legacy Memo program:

import 'package:solana_kit_address_constants/solana_kit_address_constants.dart';
import 'package:solana_kit_memo/solana_kit_memo.dart';

void main() {
  final legacyInstruction = getAddMemoInstruction(
    programAddress: memoLegacyProgramAddressV3,
    memo: 'legacy memo',
  );

  print(legacyInstruction.programAddress);
}

The Memo program has been deployed under several addresses over time. supportedMemoProgramAddresses lists every deployed address (v1, v3, and v4), which is what you want when detecting memos rather than building them:

import 'package:solana_kit_instructions/solana_kit_instructions.dart';
import 'package:solana_kit_memo/solana_kit_memo.dart';

void printMemos(List<Instruction> instructions) {
  final memos = getMemosFromInstructions(instructions);
  for (final extracted in memos) {
    print('${extracted.memo} from ${extracted.programAddress} (index ${extracted.index})');
  }
}

getMemosFromInstructions matches instructions against every supported Memo program address, decodes the memo text as UTF-8, and preserves the original instruction ordering.

How generated program clients work #

Generated program clients share one API shape, so what you learn in one program transfers to the next:

  • Program address constant — a ...ProgramAddress constant identifies the program on-chain.
  • Identification helpers — identify...Program and identify...Instruction match programs and instructions without string comparisons.
  • Instruction builders and parsers — get...Instruction encodes parameters, parse...Instruction decodes a transaction instruction back into typed arguments.
  • Account codecs — get...AccountCodec and decode...Account turn on-chain bytes into typed account objects.
  • Plan helpers — get...InstructionPlan helpers compose multi-instruction flows (such as creating an account before acting on it) into transaction plans the standard executor can run.

Errors thrown by these helpers and by transaction execution surface as SolanaError; match program-specific failures with the program error helpers.

Match program errors from your program #

Transaction failures surface as SolanaError values. When a transaction fails with a custom program error, the RPC response identifies the failing instruction by index — pair it with the transaction message to attribute the error to a program and match custom error codes.

import 'package:solana_kit_addresses/solana_kit_addresses.dart';
import 'package:solana_kit_programs/solana_kit_programs.dart';

Future<void> handleTransactionFailure(Object error) async {
  const myProgramAddress = Address('11111111111111111111111111111111');
  final transactionMessage = TransactionMessageInput(
    instructions: {0: InstructionInput(programAddress: myProgramAddress)},
  );

  if (isProgramError(error, transactionMessage, myProgramAddress, 42)) {
    // Custom program error code 42 from this program.
  } else if (isProgramError(error, transactionMessage, myProgramAddress)) {
    // Any other custom error from this program.
  }
}

transactionMessage is a lightweight TransactionMessageInput — a map from instruction index to InstructionInput(programAddress: ...). Build it from the same instructions you sent, so matching stays accurate even when the transaction mixes instructions from several programs.

Key APIs #

  • getAddMemoInstruction({required String memo}) — builds a Memo instruction from plain Dart text.
  • getMemosFromInstructions(List<Instruction> instructions) — extracts every memo from a list of instructions, matching all deployed Memo program addresses.
  • ExtractedMemo — one extracted memo: UTF-8 memo text, raw bytes, source programAddress, and instruction index.
  • supportedMemoProgramAddresses — every deployed Memo program address, ordered from oldest (v1) to newest (v4).
  • AddMemoInstructionData — generated instruction data model.
  • getAddMemoInstructionDataCodec() — UTF-8 codec for AddMemo data.
  • memoProgramAddress — current Memo program address (v4).
  • memoLegacyProgramAddressV3 — legacy Memo program address (v3).
  • memoLegacyProgramAddress — legacy Memo program address (v1).

Upstream reference #

Generated layer mirrors solana-program/memo at js@v0.14.1. js@v0.14.0 pointed the generated client at the v4 memo program; the v1 and v3 addresses remain available as legacy constants, matching the upstream extraction helpers.