Sol.College

Blinks and Solana Actions

A Solana Action is an HTTP API. GET returns metadata (title, icon, buttons), and POST receives the user's account and returns a serialized transaction for the wallet to sign. A Blink is a link that clients unfurl into that interactive card. Servers must send the CORS headers the spec requires and should serve an actions.json at the domain root.

Reference: Solana docs: Actions and Blinks · Dialect Blinks docs

Real code, line by line

4 excerpts from different projects. Each caption links the exact lines at the fork's pinned commit. The notes below each excerpt explain the lines that matter.

shubhiscoding/getblink.fun · app/api/actions/tokens/[uniqueid]/route.ts L1–26 @ 08bfbac · MIT · original
import { ObjectId } from 'mongodb';import { NextRequest, NextResponse } from 'next/server';import clientPromise from '@/lib/mongodb';import {  ActionGetResponse,  ACTIONS_CORS_HEADERS,  ActionPostRequest,  createPostResponse,  ActionPostResponse,} from "@solana/actions";import {  AddressLookupTableAccount,  clusterApiUrl,  Connection,  LAMPORTS_PER_SOL,  PublicKey,  SystemProgram,  Transaction,  TransactionInstruction,  TransactionMessage,  VersionedTransaction,} from "@solana/web3.js";import { TOKEN_PROGRAM_ID } from "@solana/spl-token";import { getAssociatedTokenAddress, createAssociatedTokenAccountInstruction } from "@/lib/constant"; const PUMP_PROGRAM_ID = new PublicKey("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");
  1. Line 5 ActionGetResponse,: The metadata a Blink client renders (title, icon, buttons).
  2. Line 8 createPostResponse,: Returns the serialized transaction the wallet will sign.
JohnPaulPabelico/Candy-Blinks · candyblinks/app/blinks/mint/[handle]/route.ts L1–25 @ 88bf53d · Apache-2.0 · original
import {  ACTIONS_CORS_HEADERS,  ActionGetResponse,  ActionPostRequest,  ActionPostResponse,  createPostResponse,} from "@solana/actions";import { mintTransaction, getBlink } from "./utils";import client from "@/app/lib/blinksightsClient"; export const GET = async (  req: Request,  { params }: { params: { handle: string } }) => {  const handle = params.handle;   try {    console.log("fetching blink");    console.log(getBlink);    const blinksData = await getBlink(handle);     if (blinksData.length === 0) {      console.error("No blinks found for the given handle");      throw new Error("No blinks found for the given handle");    }
  1. Line 3 ActionGetResponse,: The metadata a Blink client renders (title, icon, buttons).
  2. Line 5 ActionPostResponse,: Returns the serialized transaction the wallet will sign.
mintr-solana/mintr-backend · src/lambda/services/ActionService.ts L11–36 @ 54f4b3c · Apache-2.0 · original
  signTransaction,} from '@metaplex-foundation/umi'import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'import { toWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters'import { ActionPostResponse, createPostResponse } from '@solana/actions'import { ActionGetResponse } from '@solana/actions-spec'import { InternalServerError } from 'http-errors'import { FileService } from './FileService'import { KeyService } from './KeyService'import { getMandatoryEnv } from '../../utils/getMandatoryEnv'import { CreateAssetRequest } from '../types/CreateAssetRequest' export class ActionService {  private readonly logger = new Logger({ serviceName: 'ActionService' })  private readonly keyService: KeyService  private readonly fileService: FileService  private readonly solanaRpcNode = getMandatoryEnv('SOLANA_RPC_NODE')   constructor(keyService: KeyService, fileService: FileService) {    this.keyService = keyService    this.fileService = fileService  }   getOneOfActionDefinition = (): ActionGetResponse => ({    description: 'Create a NFT',    title: 'NFT creation',
  1. Line 15 import { ActionPostResponse, createPostResponse } from '@solana/actions': Returns the serialized transaction the wallet will sign.
  2. Line 16 import { ActionGetResponse } from '@solana/actions-spec': The metadata a Blink client renders (title, icon, buttons).
dimitrov-d/blinkord · packages/backend/src/routers/blinks.ts L1–26 @ 4199f5b · MIT · original
import { createPostResponse } from '@solana/actions';import { Action } from '@solana/actions-spec';import express, { Request, Response } from 'express';import {  findAccessTokenByCode,  findGuildById,  getGrandfatheredPriceForUser,  getUserGrandfatheredPricesForGuild,  saveRolePurchase,} from '../database/database';import { RolePurchase } from '../database/entities/role-purchase';import { decryptText } from '../services/encrypt';import env from '../services/env';import { discordApi, sendDiscordLogMessage } from '../services/oauth';import { generateSendTransaction, isTxConfirmed } from '../services/transaction'; export const blinksRouter = express.Router(); const BASE_URL = env.APP_BASE_URL; const generalAction = {  title: 'Use Blinkord',  label: 'Go to blinkord.com',  type: 'action',  links: {    actions: [
  1. Line 1 import { createPostResponse } from '@solana/actions';: Returns the serialized transaction the wallet will sign.

Go further

Related lessons

Topics: Payments · Learning path · Glossary