Devnet Walkthrough
Devnet Walkthrough
A six-step pass through the API against Solana devnet. Every step is a single curl call. By the end, you'll have hit every major namespace — accounts, pools, tx — without spending a lamport of real SOL.
Setup
Export your sandbox API key and a devnet RPC URL:
export PIRATE_API_KEY="pk_..." # ideally a sandbox-labeled key
export DEVNET_RPC="https://api.devnet.solana.com"The API host stays the same — https://api.piratecrew.fun. The cluster is decided by the routes that take an explicit rpcUrl (Jupiter quote, swap-tx) or by what's at the address you're querying. See Sandbox Overview for the model.
Throughout this walkthrough, replace POOL_ADDRESS with a real devnet pool address you have access to.
Step 1 — Health check
curl https://api.piratecrew.fun/v2/health{
"data": {
"status": "healthy",
"service": "PirateCrew Blockchain API",
"version": "v2"
},
"meta": {
"request_id": "req_…",
"timestamp": "2026-05-18T19:42:11.000Z"
}
}If this doesn't return healthy, stop here. Everything below depends on it.
Step 2 — Derive a PDA
PDA derivation is pure compute — no RPC, no chain hit, no signing. The fastest way to verify your auth setup is working:
curl -X POST https://api.piratecrew.fun/v2/pdas/platform \
-H "Authorization: Bearer $PIRATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "platform_id": "pirate-crew" }'{
"data": {
"address": "8mP3aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890aB",
"bump": 254,
"kind": "platform"
},
"meta": { "request_id": "req_…" }
}If you get a 401, your Authorization header isn't right. A 403 means the key isn't recognized. Both fail fast — fix and rerun.
Step 3 — Fetch raw account state
Pick any devnet account (a pool, mint, or user PDA) and read it back:
curl https://api.piratecrew.fun/v2/accounts/POOL_ADDRESS \
-H "Authorization: Bearer $PIRATE_API_KEY"{
"data": {
"address": "POOL_ADDRESS",
"lamports": "5097600",
"owner": "dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN",
"executable": false,
"rent_epoch": "18446744073709552000",
"data_len": 992,
"data_base64": "AQABA..."
},
"meta": { "request_id": "req_…" }
}A 404 not_found here means the account doesn't exist on the cluster — check that you're using a devnet address against the devnet cluster (the API reads from the cluster baked into the service config, not your client).
Step 4 — Fetch decoded pool state
For a DBC pool, the typed read endpoint is much friendlier — it decodes the account, joins partner-fee metrics, and surfaces the curve progress:
curl https://api.piratecrew.fun/v2/pools/POOL_ADDRESS \
-H "Authorization: Bearer $PIRATE_API_KEY"{
"data": {
"address": "POOL_ADDRESS",
"type": "dbc",
"status": "live",
"base_mint": "MintAddr...",
"quote_mint": "So11111111111111111111111111111111111111112",
"config": "ConfigAddr...",
"state": {
"base_reserve": "98472103…",
"quote_reserve": "1842030000",
"trading_fee_numerator": "100"
},
"partner_fees_base": "0",
"partner_fees_quote": "542100",
"migration_progress_bps": 1800
},
"meta": { "request_id": "req_…" }
}A 404 not_found here means the pool isn't on chain — either the address is wrong or it hasn't been initialized. Step 3 helps disambiguate (Step 3 returns the raw account, Step 4 needs that account plus the config PDA to decode).
Step 5 — Simulate a transaction
Before you submit anything, dry-run it. Build any VersionedTransaction client-side (a swap, a fee claim, a stake — whatever you're building), serialize to base64, and post it:
curl -X POST https://api.piratecrew.fun/v2/transaction-simulations \
-H "Authorization: Bearer $PIRATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transaction": "AQABAo...<base64>...",
"sig_verify": false
}'{
"data": {
"context": { "slot": 271234567 },
"value": {
"err": null,
"logs": [
"Program 11111111111111111111111111111111 invoke [1]",
"Program 11111111111111111111111111111111 success",
"Program ComputeBudget111111111111111111111111111111 invoke [1]",
"Program ComputeBudget111111111111111111111111111111 success"
],
"units_consumed": 42013,
"return_data": null,
"post_balances": ["9991820000", "5097600", "1"],
"post_token_balances": []
}
},
"meta": { "request_id": "req_…" }
}value.err === null means the transaction would land. Anything else — InstructionError, InsufficientFundsForRent, BlockhashNotFound — fix before submitting. See Simulating Transactions for what each error class typically means.
sig_verify: false skips signature checks, which is what you want for a pre-flight on an unsigned transaction.
Step 6 — Submit
Once simulation looks clean, sign the transaction locally and submit:
curl -X POST https://api.piratecrew.fun/v2/transactions \
-H "Authorization: Bearer $PIRATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transaction": "AQABAo...<signed base64>...",
"skip_preflight": false
}'{
"data": {
"signature": "5kJ2nP3aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890aBcDeFgHiJkLmNoPqRs",
"lifecycle": "submitted"
},
"meta": { "request_id": "req_…" }
}Poll for confirmation:
curl https://api.piratecrew.fun/v2/transactions/5kJ2... \
-H "Authorization: Bearer $PIRATE_API_KEY"{
"data": {
"signature": "5kJ2...",
"lifecycle": "confirmed",
"confirmation_status": "confirmed",
"err": null,
"slot": 271234580,
"confirmations": 12
},
"meta": { "request_id": "req_…" }
}Once you see lifecycle: "confirmed" (or "finalized" for stronger guarantees), the transaction has landed.
SDK side: same flow, less boilerplate
If you're using @piratecrewfun/pirate-sdk, the equivalent setup is:
import { PirateSDK } from "@piratecrewfun/pirate-sdk";
const sdk = new PirateSDK({
apiKey: process.env.PIRATE_API_KEY!,
secretKey: process.env.WALLET_SECRET_KEY!,
network: "devnet",
rpcUrl: process.env.DEVNET_RPC,
});The SDK handles serialize/sign/submit/poll for you — see SDK Quickstart.
What to do next
- Pick the namespace you care about and walk through its endpoint reference at
/v2/docs. - Read Simulating Transactions for a deeper look at the simulate response.
- Read Test Wallets & Faucets before you sign real transactions on devnet.
- Read Sandbox Overview for the limits of devnet testing.