Skip to main content

Installation

go get github.com/lasersell/lasersell-sdk/go

Packages

PackagePurpose
github.com/lasersell/lasersell-sdk/goExitAPIClient, SendTarget, SignUnsignedTx, SendTransaction
github.com/lasersell/lasersell-sdk/go/streamStreamClient, StreamSession, StreamConfigure, message types

API Client

All methods accept a context.Context for cancellation and timeouts.
package main

import (
    "context"
    "fmt"
    "log"

    lasersell "github.com/lasersell/lasersell-sdk/go"
)

func main() {
    ctx := context.Background()
    client := lasersell.NewExitAPIClientWithAPIKey("YOUR_API_KEY")

    // Build sell
    sellResp, err := client.BuildSellTx(ctx, lasersell.BuildSellTxRequest{
        Mint:         "TOKEN_MINT",
        UserPubkey:   "WALLET",
        AmountTokens: 1_000_000,
        Output:       lasersell.SellOutputSOL,
        SlippageBps:  2_000,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Sell tx:", sellResp.Tx)

    // Build buy
    buyResp, err := client.BuildBuyTx(ctx, lasersell.BuildBuyTxRequest{
        Mint:          "TOKEN_MINT",
        UserPubkey:    "WALLET",
        AmountInTotal: 100_000_000,
        SlippageBps:   2_000,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Buy tx:", buyResp.Tx)
}

// Helper functions for pointer fields (not part of the SDK)
func intPtr(v int) *int       { return &v }
func strPtr(v string) *string { return &v }
Optional fields in the Go SDK use pointer types (*int, *string). The intPtr and strPtr helpers above are not part of the SDK. Define them in your own code or use inline expressions like &[]int{2000}[0].

Custom Options

opts := lasersell.ExitAPIClientOptions{
    ConnectTimeout: 500 * time.Millisecond,
    AttemptTimeout: 2 * time.Second,
    RetryPolicy: lasersell.RetryPolicy{
        MaxAttempts:    3,
        InitialBackoff: 50 * time.Millisecond,
        MaxBackoff:     200 * time.Millisecond,
        Jitter:         50 * time.Millisecond,
    },
}
client := lasersell.NewExitAPIClientWithOptions("YOUR_API_KEY", opts)

Exit Intelligence Stream Session

package main

import (
    "context"
    "errors"
    "fmt"
    "io"
    "log"

    "github.com/gagliardetto/solana-go"
    lasersell "github.com/lasersell/lasersell-sdk/go"
    "github.com/lasersell/lasersell-sdk/go/stream"
)

func main() {
    ctx := context.Background()

    privateKey, err := solana.PrivateKeyFromSolanaKeygenFile("./keypair.json")
    if err != nil {
        log.Fatal(err)
    }

    client := stream.NewStreamClient("YOUR_API_KEY")
    sendMode := "helius_sender"
    tipLamports := uint64(1000)
    session, err := stream.ConnectSession(ctx, client, stream.StreamConfigure{
        WalletPubkeys: []string{"WALLET_PUBKEY"},
        Strategy: stream.StrategyConfigMsg{
            TargetProfitPct: 5.0,
            StopLossPct:     1.5,
        },
        DeadlineTimeoutSec: 45,
        SendMode:           &sendMode,
        TipLamports:        &tipLamports,
    })
    if err != nil {
        log.Fatal(err)
    }

    for {
        event, err := session.Recv(ctx)
        if errors.Is(err, io.EOF) {
            break
        }
        if err != nil {
            log.Fatal(err)
        }

        switch msg := event.Message.(type) {
        case stream.PositionOpenedServerMessage:
            fmt.Printf("New position: %s\n", msg.Mint)

        case stream.ExitSignalWithTxServerMessage:
            signedTx, err := lasersell.SignUnsignedTx(msg.UnsignedTxB64, privateKey)
            if err != nil {
                log.Printf("Sign error: %v", err)
                continue
            }
            sig, err := lasersell.SendTransaction(
                ctx, nil, lasersell.SendTargetHeliusSender(), signedTx,
            )
            if err != nil {
                log.Printf("Send error: %v", err)
                continue
            }
            fmt.Printf("Exit submitted: %s\n", sig)

        case stream.ErrorServerMessage:
            log.Printf("Stream error: code=%s message=%s", msg.Code, msg.Message)
        }
    }
}

Liquidity Snapshots and Partial Sells

Tier 1+ only. Requires a Professional or Advanced subscription. See the announcement for full details.
StreamSession caches the latest liquidity snapshot per position. Query slippage bands, maximum sellable amounts, and liquidity trends:
bands := session.GetSlippageBands(positionID)
maxTokens := session.GetMaxSellAtSlippage(positionID, 500) // 5% slippage
trend := session.GetLiquidityTrend(positionID) // "growing" | "stable" | "draining"
Use BuildPartialSellTx() to sell a portion of a position based on slippage data:
maxTokens := session.GetMaxSellAtSlippage(positionID, 500)
if maxTokens != nil {
    response, err := client.BuildPartialSellTx(ctx, handle, *maxTokens, 500, lasersell.SellOutputSOL)
}

Mirror Trading

Configure watch wallets to mirror trades from other wallets. When a watched wallet opens a position on a supported market, the stream sends a MirrorBuySignalServerMessage with an unsigned transaction for your wallet to execute.
package main

import (
    "context"
    "errors"
    "fmt"
    "io"
    "log"

    "github.com/gagliardetto/solana-go"
    lasersell "github.com/lasersell/lasersell-sdk/go"
    "github.com/lasersell/lasersell-sdk/go/stream"
)

func main() {
    ctx := context.Background()

    privateKey, err := solana.PrivateKeyFromSolanaKeygenFile("./keypair.json")
    if err != nil {
        log.Fatal(err)
    }

    walletPubkey := "YOUR_WALLET_PUBKEY"

    sendMode := "helius_sender"
    tipLamports := uint64(1000)
    session, err := stream.ConnectSession(ctx, stream.NewStreamClient("YOUR_API_KEY"), stream.StreamConfigure{
        WalletPubkeys: []string{walletPubkey},
        Strategy: stream.StrategyConfigMsg{
            TargetProfitPct: 50.0,
            StopLossPct:     25.0,
        },
        DeadlineTimeoutSec: 45,
        SendMode:           &sendMode,
        TipLamports:        &tipLamports,
        WatchWallets: []stream.WatchWalletConfig{
            {
                Pubkey: "WatchedWalletPubkey...",
                AutoBuy: &stream.AutoBuyConfig{
                    WalletPubkey:    walletPubkey,
                    AmountQuoteUnits: intPtr(100_000_000),
                },
                MirrorSell: false,
            },
        },
        MirrorConfig: &stream.MirrorConfig{
            MaxPositionsPerWallet: 1,
            CooldownSec:          30,
            MaxActiveSOL:         5.0,
            BuySlippageBps:       2500,
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    for {
        event, err := session.Recv(ctx)
        if errors.Is(err, io.EOF) {
            break
        }
        if err != nil {
            log.Fatal(err)
        }

        switch msg := event.Message.(type) {
        case stream.MirrorBuySignalServerMessage:
            signedTx, err := lasersell.SignUnsignedTx(msg.UnsignedTxB64, privateKey)
            if err != nil {
                log.Printf("Sign error: %v", err)
                continue
            }
            sig, err := lasersell.SendTransaction(
                ctx, nil, lasersell.SendTargetHeliusSender(), signedTx,
            )
            if err != nil {
                log.Printf("Send error: %v", err)
                continue
            }
            session.Sender().MirrorBuyResult(msg.Mint, true)
            fmt.Printf("Mirror buy submitted: %s\n", sig)

        case stream.MirrorBuyFailedServerMessage:
            log.Printf("Mirror buy failed: %s", msg.Reason)

        case stream.ExitSignalWithTxServerMessage:
            signedTx, err := lasersell.SignUnsignedTx(msg.UnsignedTxB64, privateKey)
            if err != nil {
                log.Printf("Sign error: %v", err)
                continue
            }
            sig, err := lasersell.SendTransaction(
                ctx, nil, lasersell.SendTargetHeliusSender(), signedTx,
            )
            if err != nil {
                log.Printf("Send error: %v", err)
                continue
            }
            fmt.Printf("Exit submitted: %s\n", sig)
        }
    }
}

func intPtr(v int) *int { return &v }
The WatchWallets slice specifies which wallets to mirror. Each WatchWalletConfig includes an AutoBuy configuration that controls how much to spend when mirroring a trade, and a MirrorSell flag that determines whether to also mirror sell transactions. The MirrorConfig struct sets global limits: MaxPositionsPerWallet caps concurrent mirrored positions, CooldownSec enforces a delay between mirror buys, MaxActiveSOL limits total SOL exposure, and BuySlippageBps sets the slippage tolerance for mirror buy transactions.

Transaction Helpers

The second parameter to SendTransaction is an *http.Client. Pass nil to use the SDK’s default HTTP client.
import lasersell "github.com/lasersell/lasersell-sdk/go"

// Sign
signedTx, err := lasersell.SignUnsignedTx(unsignedTxB64, privateKey)

// Send via Helius Sender (nil = use default HTTP client)
sig, err := lasersell.SendTransaction(ctx, nil, lasersell.SendTargetHeliusSender(), signedTx)

// Send via custom RPC
sig, err = lasersell.SendTransaction(ctx, nil,
    lasersell.SendTargetRpc("https://rpc.example.com"), signedTx)

// Send via Astralane
sig, err = lasersell.SendTransaction(ctx, nil,
    lasersell.SendTargetAstralane("KEY", "fr"), signedTx)

// With a custom HTTP client
customClient := &http.Client{Timeout: 5 * time.Second}
sig, err = lasersell.SendTransaction(ctx, customClient,
    lasersell.SendTargetHeliusSender(), signedTx)

Error Handling

import lasersell "github.com/lasersell/lasersell-sdk/go"

resp, err := client.BuildSellTx(ctx, request)
if err != nil {
    var apiErr *lasersell.ExitAPIError
    if errors.As(err, &apiErr) {
        fmt.Println("Kind:", apiErr.Kind)
        fmt.Println("Retryable:", apiErr.IsRetryable())
        fmt.Println("Status:", apiErr.Status)
    }
}

context.Context Patterns

All Go SDK methods accept context.Context as their first argument. Use this to control:
  • Timeouts: context.WithTimeout(ctx, 5*time.Second)
  • Cancellation: context.WithCancel(ctx) for graceful shutdown
  • Deadlines: context.WithDeadline(ctx, time.Now().Add(30*time.Second))
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

resp, err := client.BuildSellTx(ctx, request)

Complete Example

See the Quickstart for a full working example.