Przegląd
Wypłata z Private Channels to proces dwuetapowy. Najpierw użytkownik spala
saldo tokenów po stronie kanału, wywołując WithdrawFunds w programie Withdraw
Program. Następnie operator wywołuje ReleaseFunds w programie Escrow Program (devnet,
w tym przewodniku) z ważnym dowodem wykluczenia Sparse Merkle Tree, aby zwolnić
środki. Dowód SMT gwarantuje, że każdy nonce wypłaty może zostać użyty tylko raz,
zapobiegając podwójnemu wydaniu.
Krok 1: Zainicjuj wypłatę w kanale
Wywołaj WithdrawFunds w programie Withdraw Program, aby spalić saldo po stronie kanału.
Użyj wariantu Async, który automatycznie wyprowadza PDA tokenAccount i jest
zalecaną formą do użytku produkcyjnego:
import { getWithdrawFundsInstructionAsync } from "../private-channel-withdraw-program/clients/typescript/src/generated";import {createSolanaRpc,address,pipe,createTransactionMessage,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,appendTransactionMessageInstruction,signAndSendTransactionMessageWithSigners,assertIsTransactionMessageWithSingleSendingSigner,getBase58Decoder} from "@solana/kit";// Point to the gateway, not a public Solana RPCconst privateChannelRpc = createSolanaRpc("http://localhost:8899");const withdrawIx = await getWithdrawFundsInstructionAsync({user: userSigner,mint: address(mintAddress),amount: 1_000_000n, // 1 USDC (6 decimals)destination: null // null = release to signer's devnet wallet});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 = pipe(createTransactionMessage({ version: "legacy" }),(m) => setTransactionMessageFeePayerSigner(userSigner, m),(m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),(m) => appendTransactionMessageInstruction(withdrawIx, m));assertIsTransactionMessageWithSingleSendingSigner(transactionMessage);const signatureBytes =await signAndSendTransactionMessageWithSigners(transactionMessage);const signature = getBase58Decoder().decode(signatureBytes);console.log("Withdrawal initiated:", signature);
- ID programu Withdraw Program:
J231K9UEpS4y4KAPwGc4gsMNCjKFRMYcQBcjVW7vBhVi - Prześlij tę transakcję do bramki (
http://localhost:8899), a nie do publicznego RPC Solana - Jeśli podano
destination, zwolnione środki trafią do tego portfela zamiast do portfela podpisującego
Czego się spodziewać
Po wywołaniu WithdrawFunds nie są wymagane żadne dalsze działania. Usługi
operatora obsługują rozliczenie automatycznie:
indexer-private-channelodpytuje kanał co 1 sekundę w poszukiwaniu zdarzeń spalania i zapisuje rekord oczekującej wypłaty po wykryciu Twojej transakcjioperator-private-channelodpytuje bazę danych co 1 sekundę w poszukiwaniu oczekujących rekordów i przesyłaReleaseFundsdo programu Escrow Program w sieci Solana devnet z wymaganym dowodem wykluczenia SMT; odpytuje o potwierdzenie w devnet do 5 razy w odstępach 400 ms przed ponowną próbą
Środki zazwyczaj pojawiają się w portfelu devnet w ciągu kilku sekund w normalnych warunkach.
Jak operator przeprowadza rozliczenie (informacje referencyjne)
Po spaleniu po stronie kanału, skonfigurowany operator musi wywołać ReleaseFunds w
programie Escrow Program z ważnym dowodem wykluczenia SMT; operator nie może zwolnić
środków bez udowodnienia, że nonce wypłaty nie był wcześniej używany. Ten krok
jest obsługiwany automatycznie przez operator-private-channel; nie musisz go
wywoływać samodzielnie.
Operator dostarcza:
amount: musi odpowiadać spalonej kwocieuser: portfel odbiorcy w devnetnew_withdrawal_root: zaktualizowany korzeń SMT po tej wypłacietransaction_nonce: unikalny nonce dla tego liściasibling_proofs: 512 bajtów (16 x 32-bajtowe skróty rodzeństwa dla dowodu drzewa)
Weryfikacja
Po potwierdzeniu wywołania operatora sprawdź saldo tokenów w devnet:
spl-token balance <MINT_ADDRESS> --owner <YOUR_WALLET>
Lub przez RPC:
import { createSolanaRpc, address } from "@solana/kit";import { findAssociatedTokenPda } from "@solana-program/token";const TOKEN_PROGRAM_ADDRESS = address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");// Query devnet directly; ReleaseFunds settles here, not through the gatewayconst rpc = createSolanaRpc("https://api.devnet.solana.com");const [yourDevnetAta] = await findAssociatedTokenPda({mint: address(mintAddress),owner: address(userSigner.address),tokenProgram: TOKEN_PROGRAM_ADDRESS});const balance = await rpc.getTokenAccountBalance(yourDevnetAta).send();console.log(balance.value.uiAmountString);
Ukończyłeś Quickstart
Przeszedłeś pełny cykl Private Channels w sieci devnet: wpłaciłeś tokeny SPL do depozytariusza, wysłałeś transfer off-chain przez bramkę i wypłaciłeś środki z powrotem do portfela devnet.
Cykl życia kanału
Poznaj uczestników i pełny przepływ od depozytu do wypłaty.
Uwierzytelnianie i role
Dodaj uwierzytelnianie JWT do swojej integracji.
Informacje referencyjne: ReleaseFunds
Pełne informacje referencyjne instrukcji ReleaseFunds dla narzędzi operatora.
Sparse Merkle Tree
Dowiedz się, jak dowody wypłaty zapobiegają podwójnemu wydaniu.
Is this page helpful?