Una demo pequeña y didáctica para entender cómo funcionan Solana Actions + Blinks sin comenzar desde un scaffold enorme ni desplegar un programa personalizado.
La aplicación crea una Action que prepara una transferencia de 0.001 SOL en Devnet. El usuario revisa la transacción, la firma con Phantom y la envía a Solana.
Esta demo fue preparada para el trayecto de incubación de WayLearn.
El proyecto tiene tres piezas principales:
- Una Solana Action que responde con metadata mediante
GET. - Un endpoint
POSTque construye una transferencia de SOL sin firmar. - Una página
/donateque funciona como cliente sencillo para conectar Phantom, firmar y enviar la transacción.
El flujo completo es:
Usuario abre /donate
↓
GET /api/actions/donate
↓
Se muestra la metadata de la Action
↓
Usuario presiona "Donate 0.001 SOL"
↓
POST /api/actions/donate
↓
El backend construye una transacción sin firmar
↓
Phantom muestra el preview y solicita autorización
↓
El usuario firma y la transacción se envía a Devnet
-
Página de donación:
https://solana-donation-blink.vercel.app/donate -
Action directa:
https://solana-donation-blink.vercel.app/api/actions/donate -
Archivo de descubrimiento:
https://solana-donation-blink.vercel.app/actions.json
No para esta demo.
La transferencia utiliza SystemProgram.transfer, una instrucción del System Program nativo de Solana. Nuestro backend solamente construye la transacción; Phantom conserva la private key, solicita la firma y envía la operación.
Esto permite concentrarnos primero en el ciclo de vida de Actions y Blinks:
GET → metadata
POST → transacción
Wallet → firma
Devnet → ejecución
Antes de comenzar necesitas:
- Node.js 20.9 o superior.
- npm.
- Git.
- Phantom instalado en el navegador.
- Testnet Mode activado en Phantom.
- Un poco de SOL de Devnet en la wallet que firmará.
- Una dirección pública de Solana que recibirá la donación.
No agregues una seed phrase ni una private key al proyecto. DONATION_WALLET contiene únicamente una dirección pública.
Clona el repositorio:
git clone <URL-DE-ESTE-REPOSITORIO>
cd solana-donation-blinkInstala las dependencias:
npm installCrea el archivo de variables locales:
cp .env.example .env.localEdita .env.local:
DONATION_WALLET=PEGA_AQUI_LA_DIRECCION_PUBLICA_RECEPTORAInicia el servidor:
npm run devAbre en el navegador:
http://localhost:3000/donate
El repositorio debería incluir un archivo .env.example como este:
DONATION_WALLET=REPLACE_WITH_A_DEVNET_PUBLIC_ADDRESSLa dirección receptora puede pertenecer a Phantom, Solana Playground o cualquier otra wallet de Solana. Para ver claramente el movimiento de fondos, conviene que sea distinta de la wallet que firmará.
| Ruta | Propósito |
|---|---|
/donate |
Cliente web para probar la donación con Phantom |
/api/actions/donate |
Endpoint GET y POST de la Solana Action |
/actions.json |
Mapea una URL normal hacia la Action |
/donation.svg |
Imagen utilizada por la metadata de la Action |
El GET devuelve la información necesaria para que un cliente Blink construya su interfaz:
curl -i http://localhost:3000/api/actions/donateLa respuesta debe incluir datos similares a:
{
"type": "action",
"icon": "http://localhost:3000/donation.svg",
"title": "Support the WayLearn demo",
"description": "Donate 0.001 devnet SOL and see how a Solana Action becomes a Blink.",
"label": "Donate 0.001 SOL"
}En esta etapa todavía no se ha construido ni enviado ninguna transacción.
Los clientes Blink pueden enviar una petición OPTIONS antes de consumir la Action:
curl -i -X OPTIONS \
http://localhost:3000/api/actions/donateTambién puedes revisar actions.json:
curl -i http://localhost:3000/actions.jsonBusca un header como este:
Access-Control-Allow-Origin: *
Define la dirección pública de la wallet que actuaría como sender:
export SENDER_WALLET="PEGA_AQUI_LA_DIRECCION_PUBLICA"Ejecuta el POST:
curl -i \
-X POST \
http://localhost:3000/api/actions/donate \
-H "Content-Type: application/json" \
--data "{\"type\":\"transaction\",\"account\":\"$SENDER_WALLET\"}"La respuesta incluirá una transacción serializada:
{
"type": "transaction",
"transaction": "AQAAAAAAAAAAAAAAAA...",
"message": "Thanks! You are donating 0.001 devnet SOL."
}Esto no envía la donación. El endpoint solamente construye la transacción. Todavía falta que una wallet la revise, firme y envíe.
- Abre Phantom.
- Entra a
Settings. - Abre
Developer Settings. - Activa
Testnet Mode. - Confirma que la cuenta tenga SOL de Devnet.
- Abre
http://localhost:3000/donate. - Presiona
Donate 0.001 SOL. - Conecta Phantom.
- Revisa el preview de la transacción.
- Aprueba la firma.
Al terminar, la página mostrará un enlace hacia Solana Explorer usando cluster=devnet.
La wallet que firma necesita saldo suficiente para:
- Transferir 0.001 SOL.
- Pagar la comisión de red.
Puedes usar el faucet oficial:
Con Solana CLI también puedes solicitar un airdrop:
solana airdrop 2 TU_DIRECCION_PUBLICA --url devnetEl SOL de Devnet no tiene valor real y se utiliza únicamente para desarrollo y pruebas.
Antes de desplegar, ejecuta:
npm run buildSi el build termina correctamente, el proyecto está listo para desplegarse.
Instala o ejecuta la CLI de Vercel:
npx vercel loginVincula la carpeta con un proyecto de Vercel:
npx vercel linkAgrega la dirección receptora al ambiente de producción:
npx vercel env add DONATION_WALLET productionCuando la CLI lo solicite, pega únicamente la dirección pública.
Despliega a producción:
npx vercel --prodCada cambio en una variable de entorno requiere un deployment nuevo para que se aplique:
npx vercel --prodTambién puedes conectar el repositorio a Vercel y dejar que cada push a la rama principal genere un deployment automáticamente.
El Inspector permite comprobar:
- La existencia y estructura de
actions.json. - Los headers CORS.
- El código HTTP.
- El mapeo desde
/donatehacia la Action. - La respuesta del
GET. - La respuesta del
POST. - Los botones y parámetros declarados por la Action.
Actualmente el Inspector puede ejecutarse localmente desde su repositorio:
git clone https://github.com/solana-developers/blinks-xyz.git
cd blinks-xyz
npm install
npm run devAbre:
http://localhost:3000/inspector
Pega una de estas URLs:
https://solana-donation-blink.vercel.app/donate
o la Action directa:
https://solana-donation-blink.vercel.app/api/actions/donate
Usar /donate también comprueba que actions.json pueda detectar la página y mapearla hacia /api/actions/donate.
Si la aplicación ya usa el puerto 3000, inicia el Inspector en el puerto 3001:
npm run dev -- -p 3001Después abre:
http://localhost:3001/inspector
Y prueba:
http://localhost:3000/donate
El Inspector valida la especificación y permite probar las respuestas de la API. La firma real sigue requiriendo un cliente con integración de wallet, como la página /donate incluida en este proyecto.
Un navegador común entiende esta URL:
https://example.com/donate
Pero un cliente Blink necesita saber cuál es el endpoint de la Action. actions.json crea el mapeo:
/donate → /api/actions/donate
También incluye una regla idempotente para reconocer directamente las rutas bajo:
/api/actions/**
El archivo debe estar disponible en la raíz del dominio:
https://example.com/actions.json
y responder con headers CORS tanto para GET como para OPTIONS.
solana-donation-blink/
├── public/
│ └── donation.svg
├── src/
│ └── app/
│ ├── actions.json/
│ │ └── route.ts
│ ├── api/
│ │ └── actions/
│ │ └── donate/
│ │ └── route.ts
│ ├── donate/
│ │ └── page.tsx
│ └── page.tsx
├── .env.example
└── README.md
Crea .env.local o agrega la variable en Vercel:
npx vercel env add DONATION_WALLET production
npx vercel --prodComprueba que:
- La extensión esté instalada y habilitada.
- La página se abra desde
localhosto mediante HTTPS. - Phantom no esté bloqueado para ese sitio.
Activa Testnet Mode desde las opciones de desarrollador de Phantom.
La wallet sender necesita SOL de Devnet para la cantidad enviada y la comisión.
Revisa:
curl -i -X OPTIONS \
https://TU-DOMINIO/api/actions/donatey:
curl -i \
https://TU-DOMINIO/actions.jsonAmbos deben permitir peticiones cross-origin.
Abre directamente:
https://TU-DOMINIO/donation.svg
El valor de icon en el GET debe ser una URL absoluta.
Vuelve a presionar el botón. El backend generará una transacción nueva con un blockhash reciente.
Usa dos direcciones distintas para que el cambio sea fácil de observar durante la demo.
Una vez entendido este ejemplo, se puede extender para:
- Elegir la cantidad de SOL.
- Donar un token SPL.
- Agregar varias acciones o botones.
- Recibir parámetros del usuario.
- Registrar una donación mediante un programa de Anchor.
- Votar por un proyecto incubado.
- Reclamar una insignia on-chain.
- Encadenar varias Actions.
-
Solana Actions and Blinks:
https://solana.com/es/developers/guides/advanced/actions -
SDK
@solana/actions:
https://github.com/solana-developers/solana-actions -
Blink Inspector:
https://github.com/solana-developers/blinks-xyz -
Solana Explorer:
https://explorer.solana.com -
Devnet Faucet:
https://faucet.solana.com