Transactions
Build unsigned deposit and withdraw transactions, check withdrawal status, and sign, submit, and record them.
The deposit and withdraw endpoints return an unsigned, base64-encoded VersionedTransaction that your wallet signs and submits. They require a write-scope key. The withdraw-status read requires read. After a transaction confirms, record it with POST /api/history so the activity feed updates immediately.
POST /api/vault/{vault_id}/deposit
Builds an unsigned deposit transaction.
Body:
| Field | Description |
|---|---|
wallet |
Wallet pubkey (required). |
amount |
Deposit amount in lamports (smallest asset unit). Wins if both are present. |
uiAmount |
Human amount (e.g. 1.5 USDC) — an ergonomic alternative to amount. |
curl -X POST "https://app.gma.fi/api/vault/GPZW7ihHMMfZg5eNDmn376mwVzBKHh867vdWmjvNvYPK/deposit" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"wallet":"YOUR_WALLET_PUBKEY","amount":100000000}'
Response data:
| Field | Description |
|---|---|
transaction |
Base64 VersionedTransaction to sign and submit. |
message |
Human summary of the deposit. |
details |
{ vaultId, vaultName, depositAmount, depositAmountHuman, assetDecimals, estimatedSharesReceived, currentSharePrice }. |
GET /api/vault/{vault_id}/withdraw
Withdrawal status for a wallet.
| Param | Description |
|---|---|
wallet |
Wallet pubkey (required). |
curl "https://app.gma.fi/api/vault/GPZW7ihHMMfZg5eNDmn376mwVzBKHh867vdWmjvNvYPK/withdraw?wallet=YOUR_WALLET_PUBKEY" \
-H "Authorization: Bearer YOUR_API_KEY"
Response data:
| Field | Description |
|---|---|
hasPendingWithdrawal |
Whether a pending withdrawal exists. |
pendingShares |
Pending shares (raw), or 0. |
estimatedUsdcAmount |
Estimated asset value of the pending shares. |
canClaimNow |
Whether the receipt is claimable on-chain now. |
createdAt |
Latest verified queued-withdrawal request's confirmed block time (ISO 8601), or null if no shares are pending or request history is unavailable. The receipt's NAV ordering floor is not a request timestamp. |
estimate |
Arrival-time band { kind, band }, or null. |
progress |
Live staging progress, or null. |
POST /api/vault/{vault_id}/withdraw
Initiates a new withdrawal or claims a pending one, chosen from on-chain state (or forced with an explicit action). PUT is an alias for POST.
Body:
| Field | Description |
|---|---|
wallet |
Wallet pubkey (required). |
sharesAmount |
Shares to withdraw, raw units (required when initiating a new withdrawal). |
action |
initiate or claim (optional; auto-detected otherwise). |
curl -X POST "https://app.gma.fi/api/vault/GPZW7ihHMMfZg5eNDmn376mwVzBKHh867vdWmjvNvYPK/withdraw" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"wallet":"YOUR_WALLET_PUBKEY","sharesAmount":50000000}'
Response data always includes action (initiate or claim), the base64 transaction, a message, and details. When initiating, details carries the withdrawal accounting:
| Field | Description |
|---|---|
withdrawalPolicy |
Fee/cap policy in effect. |
withdrawalLimits |
Current net-withdrawal limit state. |
withdrawalEstimate |
Gross/fee/net asset breakdown for the request. |
withdrawalReservation |
Deprecated; always null. Preparation does not reserve capacity. Withdrawal caps are enforced on-chain when the signed transaction executes. |
When claiming, the reservation and estimate fields are null; the message states the approximate amount to claim.
Withdrawal capacity errors
Preparation checks capacity without reserving it. Another withdrawal can consume capacity before your signed transaction executes. The program can return:
| Code | Error | Recovery |
|---|---|---|
6020 |
HourlyWithdrawalCapExceeded |
Refresh the quote and reduce the amount, or wait for capacity to become available. |
6021 |
DailyWithdrawalCapExceeded |
Refresh the quote and reduce the amount, or wait for capacity to become available. |
Signing, submitting, and recording
- Deserialize the base64 into a
VersionedTransaction. - Simulate (recommended) before signing.
- Sign with the wallet.
- Submit and confirm.
- Record the confirmed signature with
POST /api/history. Omit the deprecatedwithdrawal_reservation_idfor newly prepared withdrawals.
Blockhash freshness matters: build, sign, and submit promptly. A transaction whose blockhash has expired must be rebuilt (call the endpoint again) rather than retried as-is.
import { Connection, VersionedTransaction } from '@solana/web3.js';
// Your backend keeps the _gamma write key server-side; the browser never sees it.
const PARTNER_API = '/api/gamma';
// 1. Ask your backend for the unsigned transaction.
const res = await fetch(PARTNER_API + '/deposit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
wallet: wallet.publicKey.toBase58(),
amount: 100_000_000, // 100 USDC in lamports (6 decimals)
}),
});
const { data } = await res.json();
// 2. Deserialize the base64 transaction.
const transaction = VersionedTransaction.deserialize(
Buffer.from(data.transaction, 'base64'),
);
// 3. Sign (browser wallet shown; a Keypair works server-side).
const signedTx = await window.solana.signTransaction(transaction);
// 4. Submit and confirm.
const connection = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
const signature = await connection.sendRawTransaction(signedTx.serialize());
const confirmation = await connection.confirmTransaction(signature, 'confirmed');
if (confirmation.value.err) throw new Error('Transaction failed');
// 5. Record the confirmed signature (idempotent; duplicate === true is success).
await fetch(PARTNER_API + '/history', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
wallet: wallet.publicKey.toBase58(),
vault_id: 'GPZW7ihHMMfZg5eNDmn376mwVzBKHh867vdWmjvNvYPK',
signature,
}),
});
For a queued withdrawal, record the initiate signature before recording the claim; a claim recorded first returns 409. See POST /api/history.
Next: Public endpoints