Wypłać środki

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 RPC
const 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:

  1. indexer-private-channel odpytuje kanał co 1 sekundę w poszukiwaniu zdarzeń spalania i zapisuje rekord oczekującej wypłaty po wykryciu Twojej transakcji
  2. operator-private-channel odpytuje bazę danych co 1 sekundę w poszukiwaniu oczekujących rekordów i przesyła ReleaseFunds do 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 kwocie
  • user: portfel odbiorcy w devnet
  • new_withdrawal_root: zaktualizowany korzeń SMT po tej wypłacie
  • transaction_nonce: unikalny nonce dla tego liścia
  • sibling_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 gateway
const 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.

Is this page helpful?

Spis treści

Edytuj stronę