Skip to main content

Laser Trade

POST /v1/trades/execute

Laser Trade executes a Pump bonding-curve or PumpSwap trade from a SolanaLaser-managed wallet. Your app sends the trade intent as JSON. SolanaLaser selects the managed wallet, builds the transaction, signs it server-side, sends it through Helius Sender, and returns the Solana signature.

You never send a private key to this endpoint. To choose a wallet, pass its public key in wallet. If wallet is omitted, SolanaLaser uses the default managed wallet for that API key.

Execution Model

The endpoint has one job: turn a trading intent into one submitted Solana transaction.

For a new Pump token, the trade routes through the Pump bonding curve. When the bonding curve is complete, SolanaLaser derives the PumpSwap pool_v2 address for the mint and routes through PumpSwap. You can also pass an explicit PumpSwap pool when you already know which pool you want to trade against.

Before submission, SolanaLaser quotes the trade, applies your slippage settings, builds the Pump or PumpSwap instruction, adds priority-fee compute budget instructions, adds the Sender tip, signs with the managed wallet, and sends the transaction. By default it also simulates before sending and waits for confirmation after sending.

Request

This is the full request shape:

const response = await fetch("https://api.solanalaser.xyz/v1/trades/execute", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": "sl_your_key",
},
body: JSON.stringify({
action: "buy",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: 0.01,
denominated_in_sol: true,
slippage: 5,
simulate: true,
confirm: true,
measure_timing: false,
}),
});

const trade = await response.json();

Request Fields

FieldTypeRequiredMeaning
action"buy" or "sell"YesTrade direction. side is accepted as an alias.
mintstringYesToken mint address. token_mint is accepted as an alias.
poolstringNoExplicit PumpSwap pool address. If present, the trade routes to this pool. Keep mint equal to the pool base mint.
amountnumber or stringYesAmount to trade. Interpretation depends on action and denominated_in_sol.
denominated_in_solboolean or boolean stringNoDefaults to true for buys and false for sells. denominatedInSol is accepted as an alias.
slippagenumber or stringNoPercentage slippage. Default is 2, maximum is 50, and up to 2 decimals are accepted.
slippage_bpsintegerNoBackward-compatible basis-points field. 500 means 5%. Do not send it together with slippage.
simulatebooleanNoDefaults to true. If true, the transaction is simulated before submission.
confirmbooleanNoDefaults to true. If true, SolanaLaser waits for signature confirmation before responding.
measure_timingbooleanNoDefaults to false. If true, the response includes timing_ms.
walletstringNoManaged wallet public key. If omitted, the default wallet is used.

Amount Rules

amount is intentionally flexible, but it must match the type of trade.

For a SOL-denominated buy, amount is SOL. It can be a number or string and can have up to 9 decimal places.

body: JSON.stringify({
action: "buy",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: "0.01",
})

For a token-denominated buy, amount is token atomic units and denominated_in_sol must be false. This asks for an exact token amount, and SolanaLaser calculates the maximum SOL input after slippage. This works for bonding-curve trades and PumpSwap trades.

body: JSON.stringify({
action: "buy",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: "1000000000",
denominated_in_sol: false,
})

For a sell, amount is token atomic units by default. A SOL-denominated sell is rejected because the chain instruction sells tokens, not a target SOL amount.

body: JSON.stringify({
action: "sell",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: "250000000",
})

For a percentage sell, use a string ending in %. SolanaLaser reads the selected wallet's token account balance at execution time and converts the percentage into token atomic units.

body: JSON.stringify({
action: "sell",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: "50%",
})

Accepted percentage values are greater than 0% and up to 100%, with up to 2 decimal places.

Slippage

Use slippage for normal integrations. It is a percentage, so 5 means 5%.

body: JSON.stringify({
action: "buy",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: 0.01,
slippage: 5,
})

You can also pass a string:

body: JSON.stringify({
action: "sell",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: "100%",
slippage: "7.5",
})

slippage_bps exists for older clients. Prefer slippage because it matches how traders think about slippage.

Routing

If pool is omitted, SolanaLaser auto-routes:

  1. Fetch the Pump bonding curve for mint.
  2. If the curve is not complete, trade on bonding_curve.
  3. If the curve is complete, derive the PumpSwap pool and trade on pumpswap.

If pool is provided, SolanaLaser uses that PumpSwap pool directly. Only SOL-quoted PumpSwap pools are supported.

The response always tells you where the trade actually went:

{
"venue": "bonding_curve",
"pool": null
}

or:

{
"venue": "pumpswap",
"pool": "PUMPSWAP_POOL_ADDRESS"
}

Response

Successful responses return the submitted signature plus the normalized trade details used by the server.

{
"wallet": "MANAGED_WALLET_PUBLIC_KEY",
"action": "buy",
"mint": "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
"amount": "0.01",
"amount_units": 10000000,
"denominated_in_sol": true,
"signature": "5h6QxYvDk1vK7pR5n9wQeX9oYxL6WvX9PpVb7bZf9mHjV8u9A3f7nY6x2r4b1a2c3d4e5f6g7h8i9j",
"confirmed": true,
"confirmation_status": "confirmed",
"venue": "bonding_curve",
"pool": null,
"expected_output": "348912340",
"timing_ms": {
"wallet": 8,
"amount": 0,
"build": 430,
"sender": 210,
"confirmation": 820,
"database": 4,
"total": 1472
}
}

Response Fields

FieldMeaning
walletManaged wallet that signed the transaction and paid network fees, priority fee, and Sender tip.
actionNormalized action, always buy or sell.
mintToken mint that was traded. For explicit PumpSwap pools, this is resolved from the pool base mint.
amountOriginal request amount as text.
amount_unitsParsed base-unit amount. SOL buys return lamports. Token buys and sells return token atomic units. Percentage sells return the resolved token amount.
denominated_in_solFinal denomination used by the server after applying defaults.
signatureSolana transaction signature returned after submission.
confirmedtrue only when confirmation polling observed the transaction. With confirm: false, this is false even if the transaction lands later.
confirmation_statusRPC confirmation status such as processed, confirmed, or finalized. It is null when confirm: false.
venueActual route used: bonding_curve or pumpswap.
poolPumpSwap pool address when venue is pumpswap; otherwise null.
expected_outputLegacy response name for the slippage threshold used in the transaction. See the table below.
timing_msOptional timings returned only with measure_timing: true.

expected_output depends on the trade type:

TradeWhat expected_output means
Bonding-curve SOL buyMinimum token atomic units out after slippage.
Bonding-curve exact-token buyMaximum lamports in after slippage.
Bonding-curve sellMinimum lamports out after slippage.
PumpSwap SOL buyMaximum lamports threshold after slippage.
PumpSwap exact-token buyMaximum lamports threshold after slippage.
PumpSwap sellMinimum lamports out after slippage.

Examples

Buy With SOL, Auto-Routed

Use this for the normal buy flow. The server decides whether the mint is still on the bonding curve or has moved to PumpSwap.

Request

const response = await fetch("https://api.solanalaser.xyz/v1/trades/execute", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": "sl_your_key",
},
body: JSON.stringify({
action: "buy",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: 0.01,
slippage: 5,
}),
});

const trade = await response.json();

Response: 200

{
"wallet": "DEFAULT_WALLET_PUBLIC_KEY",
"action": "buy",
"mint": "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
"amount": "0.01",
"amount_units": 10000000,
"denominated_in_sol": true,
"signature": "TRANSACTION_SIGNATURE",
"confirmed": true,
"confirmation_status": "confirmed",
"venue": "bonding_curve",
"pool": null,
"expected_output": "TOKEN_UNITS_THRESHOLD"
}

Sell 100 Percent From a Specific Wallet

Use this when your API key has multiple managed wallets and you want to sell a position from one non-default wallet.

Request

const response = await fetch("https://api.solanalaser.xyz/v1/trades/execute", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": "sl_your_key",
},
body: JSON.stringify({
action: "sell",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: "100%",
wallet: "MANAGED_WALLET_PUBLIC_KEY",
slippage: 10,
}),
});

const trade = await response.json();

Response: 200

{
"wallet": "MANAGED_WALLET_PUBLIC_KEY",
"action": "sell",
"mint": "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
"amount": "100%",
"amount_units": 4389123401,
"denominated_in_sol": false,
"signature": "TRANSACTION_SIGNATURE",
"confirmed": true,
"confirmation_status": "confirmed",
"venue": "pumpswap",
"pool": "PUMPSWAP_POOL_ADDRESS",
"expected_output": "MIN_LAMPORTS_OUT"
}

Submit Fast and Check Later

Set confirm: false when you want the API to return after submission instead of waiting for RPC confirmation. Set simulate: false only when you accept that a bad transaction can be submitted and fail on-chain.

Request

const startedAt = performance.now();

const response = await fetch("https://api.solanalaser.xyz/v1/trades/execute", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": "sl_your_key",
},
body: JSON.stringify({
action: "buy",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: "0.005",
slippage: 8,
simulate: false,
confirm: false,
measure_timing: true,
}),
});

const trade = await response.json();
const elapsedMs = Math.round(performance.now() - startedAt);

console.log(trade.signature);
console.log(`HTTP round trip: ${elapsedMs}ms`);
console.log(trade.timing_ms);

Response: 200

{
"wallet": "DEFAULT_WALLET_PUBLIC_KEY",
"action": "buy",
"mint": "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
"amount": "0.005",
"amount_units": 5000000,
"denominated_in_sol": true,
"signature": "TRANSACTION_SIGNATURE",
"confirmed": false,
"confirmation_status": null,
"venue": "bonding_curve",
"pool": null,
"expected_output": "TOKEN_UNITS_THRESHOLD",
"timing_ms": {
"wallet": 9,
"amount": 0,
"build": 280,
"sender": 190,
"confirmation": 0,
"database": 3,
"total": 482
}
}

Use an Explicit PumpSwap Pool

Use pool when your system already has a PumpSwap pool address and you do not want auto-routing. The request still includes mint, and it should match the pool base mint.

Request

const response = await fetch("https://api.solanalaser.xyz/v1/trades/execute", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": "sl_your_key",
},
body: JSON.stringify({
action: "buy",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
pool: "PUMPSWAP_POOL_ADDRESS",
amount: "0.01",
slippage: 5,
}),
});

const trade = await response.json();

Response: 200

{
"wallet": "DEFAULT_WALLET_PUBLIC_KEY",
"action": "buy",
"mint": "PUMPSWAP_POOL_BASE_MINT",
"amount": "0.01",
"amount_units": 10000000,
"denominated_in_sol": true,
"signature": "TRANSACTION_SIGNATURE",
"confirmed": true,
"confirmation_status": "confirmed",
"venue": "pumpswap",
"pool": "PUMPSWAP_POOL_ADDRESS",
"expected_output": "MAX_LAMPORTS_THRESHOLD"
}

Buy an Exact Token Amount

This asks for an exact token amount and lets SolanaLaser calculate the maximum SOL input after slippage. It works on the bonding curve and on PumpSwap.

Request

const response = await fetch("https://api.solanalaser.xyz/v1/trades/execute", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": "sl_your_key",
},
body: JSON.stringify({
action: "buy",
mint: "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
amount: "1000000000",
denominated_in_sol: false,
slippage: 5,
}),
});

const trade = await response.json();

Response: 200

{
"wallet": "DEFAULT_WALLET_PUBLIC_KEY",
"action": "buy",
"mint": "G282Uu6G6QV8VBrQgzi3DAwV5CvcMkTz9rDgpvBBpump",
"amount": "1000000000",
"amount_units": 1000000000,
"denominated_in_sol": false,
"signature": "TRANSACTION_SIGNATURE",
"confirmed": true,
"confirmation_status": "confirmed",
"venue": "bonding_curve",
"pool": null,
"expected_output": "MAX_LAMPORTS_IN"
}

Common Errors

HTTPDetailMeaning
400action must be buy or sellaction was not buy or sell.
400amount must be a number or stringamount was not a JSON number or string.
400SOL amounts cannot have more than 9 decimal placesSOL values map to lamports, so only 9 decimals are valid.
400sell amount must be denominated in token unitsSells cannot use denominated_in_sol: true.
400use either slippage or slippage_bps, not bothSend one slippage format. Prefer slippage.
400trade simulation failedThe transaction failed pre-submit simulation and was not sent.
502Jito, RPC, or Sender detailUpstream submission, RPC, or confirmation infrastructure failed. Check the signature if one was returned.

Operational Notes

  • confirm: true is safer for normal integrations because the response tells you whether RPC observed the transaction.
  • confirm: false is faster, but the API cannot tell you whether the transaction landed. Store the returned signature and check it later.
  • simulate: true catches many bad trades before submission, but it adds RPC latency. simulate: false skips that protection.
  • measure_timing: true is for diagnostics. It reports server-side timing for wallet lookup, amount parsing, transaction build, Sender submission, confirmation, database recording, and total request time.
  • A confirmation timeout does not prove the transaction failed. It means the API stopped waiting. Check the returned signature when available.