Descripción General
Las transferencias de canal son transferencias estándar de tokens SPL enviadas al gateway; no existe una instrucción de transferencia dedicada para Private Channels. El gateway enruta la transacción al nodo de escritura, que la ejecuta contra la capa de cuentas fuera de la cadena del canal. Las transferencias se confirman cuando el secuenciador las procesa, no cuando se confirma un bloque de Solana, y no aparecen en Mainnet.
Cambia el RPC de tu Wallet
Antes de enviar una transferencia, cambia el endpoint RPC de tu wallet a la URL del gateway en lugar de Solana Devnet:
http://localhost:8899
Las transacciones enviadas a un RPC público de Solana se procesarán en Mainnet, no en el canal.
Autenticación
Si iniciaste el stack sin --profile auth (la configuración predeterminada de devnet), el gateway opera en modo abierto y no se requiere ningún token; omite esta sección.
Cuando el Auth Service está habilitado (JWT_SECRET está configurado en el gateway), todas las solicitudes requieren un token JWT de tipo bearer en el encabezado Authorization:
Authorization: Bearer <JWT_TOKEN>
Consulta Autenticación y Roles para saber cómo registrarte, iniciar sesión y obtener un token.
Construye y Envía una Transferencia
Si el associated token account del destinatario aún no existe en el canal, agrega una instrucción createAssociatedTokenAccountIdempotent antes de la transferencia. El código a continuación gestiona ambos casos:
import {address,createSolanaRpc,pipe,createTransactionMessage,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,appendTransactionMessageInstruction,signAndSendTransactionMessageWithSigners,assertIsTransactionMessageWithSingleSendingSigner,getBase58Decoder} from "@solana/kit";import {findAssociatedTokenPda,getCreateAssociatedTokenIdempotentInstruction,getTransferInstruction} from "@solana-program/token";const TOKEN_PROGRAM_ADDRESS = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");// Point to the gateway, not a public Solana RPCconst privateChannelRpc = createSolanaRpc("http://localhost:8899");// Derive source and destination associated token accountsconst [sourceAta] = await findAssociatedTokenPda({mint: address(mintAddress),owner: address(senderAddress),tokenProgram: TOKEN_PROGRAM_ADDRESS});const [destinationAta] = await findAssociatedTokenPda({mint: address(mintAddress),owner: address(recipientAddress),tokenProgram: TOKEN_PROGRAM_ADDRESS});const transferInstruction = getTransferInstruction({source: sourceAta,destination: destinationAta,authority: transactionSigner,amount: 1_000_000n // 1 USDC (6 decimals)});// Create the destination ATA on the channel if it does not exist yetconst destinationAtaInfo = await privateChannelRpc.getAccountInfo(destinationAta, { encoding: "base64" }).send();const { value: latestBlockhash } = await privateChannelRpc.getLatestBlockhash({ commitment: "confirmed" }).send();// Sent to the Private Channels gateway (not Solana RPC directly), which// expects the legacy transaction format - do not switch this to version 0.const transactionMessage = !destinationAtaInfo.value? pipe(createTransactionMessage({ version: "legacy" }),(m) => setTransactionMessageFeePayerSigner(transactionSigner, m),(m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),(m) =>appendTransactionMessageInstruction(getCreateAssociatedTokenIdempotentInstruction({payer: transactionSigner,ata: destinationAta,owner: address(recipientAddress),mint: address(mintAddress)}),m),(m) => appendTransactionMessageInstruction(transferInstruction, m)): pipe(createTransactionMessage({ version: "legacy" }),(m) => setTransactionMessageFeePayerSigner(transactionSigner, m),(m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),(m) => appendTransactionMessageInstruction(transferInstruction, m));assertIsTransactionMessageWithSingleSendingSigner(transactionMessage);const signatureBytes =await signAndSendTransactionMessageWithSigners(transactionMessage);const signature = getBase58Decoder().decode(signatureBytes);console.log("Transfer signature:", signature);
Verifica la Transferencia
Consulta el saldo del canal del destinatario a través del gateway para confirmar que la transferencia se realizó correctamente:
const [recipientAta] = await findAssociatedTokenPda({mint: address(mintAddress),owner: address(recipientAddress),tokenProgram: TOKEN_PROGRAM_ADDRESS});const balance = await privateChannelRpc.getTokenAccountBalance(recipientAta).send();console.log(balance.value.uiAmountString);
Próximos Pasos
Retirar Fondos - retira tokens de vuelta a tu wallet de Solana
Is this page helpful?