stablekit

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 9, 2026 License: MIT Imports: 21 Imported by: 0

README

stablekit

A focused Go SDK for stablecoin operations on Solana — balance queries, SPL transfers (regular and gasless via Kora), and Jupiter quotes.

Wraps solana-go and bundles internal Kora and Jupiter clients so callers only need a single import.

Scope

Intentionally narrow — stablecoin send + balance + quote. Not a general-purpose Solana SDK; drop down to client.RPC() for anything outside this surface.

Installation

go get github.com/rillehq/stablekit

Quick start

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/gagliardetto/solana-go"
	"github.com/rillehq/stablekit"
)

func main() {
	c := stablekit.NewClient(stablekit.Config{
		RPCEndpoint:  "https://api.mainnet-beta.solana.com",
		KoraEndpoint: "https://kora.example.com",
		KoraAPIKey:   "...",
	})
	ctx := context.Background()

	owner := solana.MustPublicKeyFromBase58("...")

	// Balance
	bal, err := c.Balance(ctx, owner, stablekit.USDC)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("USDC balance: %d\n", bal)

	// Gasless transfer (Kora pays SOL fee)
	sig, err := c.GaslessTransfer(ctx, stablekit.GaslessTransferOpts{
		SenderSigner: solana.MustPrivateKeyFromBase58("..."),
		Recipient:    solana.MustPublicKeyFromBase58("..."),
		Mint:         stablekit.USDC,
		Amount:       1_000_000, // 1 USDC
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Sent:", sig)

	// Jupiter quote (USDT → USDC)
	quote, err := c.Quote(ctx, stablekit.USDT, stablekit.USDC, 1_000_000, 10)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Out:", quote.OutAmount, "Impact:", quote.PriceImpactPct)
}

API surface

Method Purpose
Balance SPL token balance for an owner+mint (returns 0 if ATA missing)
ResolveATA Derive the owner's ATA address; report whether it exists on-chain
SendStable SPL transfer where the sender pays the SOL fee
GaslessTransfer SPL transfer where Kora pays the SOL fee (user pays in token)
GaslessTransferTx Kora-built simple transfer (returns base64 transaction)
Quote Jupiter v6 quote (USDT↔USDC etc.)
RPC() Underlying solana-go RPC client (escape hatch)
KoraEnabled() Whether Kora was configured

Configuration

Field Description Default
RPCEndpoint Solana JSON-RPC URL (required)
KoraEndpoint Kora fee-abstraction URL. Empty = gasless calls return ErrKoraDisabled
KoraAPIKey x-api-key header for Kora
KoraHMACSecret HMAC secret for x-hmac-signature per Kora request
JupiterEndpoint Override Jupiter v6 URL https://quote-api.jup.ag/v6
JupiterAPIKey x-api-key for paid Jupiter tiers
HTTPClient Shared *http.Client 15s timeout
MaxRetries Retries on 429 / 5xx / transport errors 3

Errors

import "errors"

_, err := c.GaslessTransfer(ctx, opts)
if errors.Is(err, stablekit.ErrKoraDisabled) {
	// Kora not configured
}

var ke *stablekit.KoraError
if errors.As(err, &ke) {
	fmt.Printf("kora rpc error %d: %s\n", ke.Code, ke.Message)
}

var je *stablekit.JupiterError
if errors.As(err, &je) {
	fmt.Printf("jupiter http %d: %s\n", je.StatusCode, je.Body)
}

License

MIT

Documentation

Overview

Package stablekit is a focused Go SDK for stablecoin operations on Solana: balance queries, SPL transfers (regular and gasless via Kora), and Jupiter quotes. It wraps solana-go and bundles internal Kora JSON-RPC and Jupiter HTTP clients.

Scope is intentionally narrow: stablecoin balance + send + quote. It is not a general-purpose Solana SDK — drop down to the underlying solana-go RPC when you need more.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrSourceATAMissing    = errors.New("stablekit: source associated token account does not exist")
	ErrDestATAMissing      = errors.New("stablekit: destination associated token account does not exist")
	ErrInsufficientBalance = errors.New("stablekit: insufficient token balance")
	ErrKoraDisabled        = errors.New("stablekit: Kora is not configured (set Config.KoraEndpoint to enable gasless calls)")
)

Sentinel errors.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a thread-safe stablecoin SDK over solana-go, with Kora and Jupiter clients bundled.

func NewClient

func NewClient(cfg Config) *Client

NewClient creates a stablekit Client. Panics if RPCEndpoint is empty.

func (*Client) Balance

func (c *Client) Balance(ctx context.Context, owner solana.PublicKey, mint Mint) (uint64, error)

Balance returns the raw token balance held by owner's Associated Token Account for mint. Returns 0 (no error) if the ATA does not yet exist.

func (*Client) GaslessTransfer

func (c *Client) GaslessTransfer(ctx context.Context, opts GaslessTransferOpts) (string, error)

GaslessTransfer transfers SPL stablecoin via Kora. Kora pays the SOL fee and broadcasts; the user only pays the fee in opts.FeeToken (defaults to opts.Mint). Returns the on-chain transaction signature.

func (*Client) GaslessTransferTx

func (c *Client) GaslessTransferTx(ctx context.Context, opts GaslessTransferTxOpts) (string, error)

GaslessTransferTx asks Kora to build a complete pre-signed transfer transaction (Kora's TransferTransaction RPC) and returns the base64 transaction. Useful when you want Kora to handle the entire flow.

func (*Client) KoraEnabled

func (c *Client) KoraEnabled() bool

KoraEnabled reports whether the Kora client was configured.

func (*Client) Quote

func (c *Client) Quote(ctx context.Context, in, out Mint, amount uint64, slippageBps int) (QuoteResponse, error)

Quote returns a Jupiter swap quote between two stablecoin mints.

func (*Client) RPC

func (c *Client) RPC() *rpc.Client

RPC returns the underlying solana-go RPC client. Use this when stablekit does not expose an operation directly. The returned client is shared — do not Close it.

func (*Client) ResolveATA

func (c *Client) ResolveATA(ctx context.Context, owner solana.PublicKey, mint Mint) (address solana.PublicKey, exists bool, err error)

ResolveATA derives the Associated Token Account address for owner+mint and reports whether it exists on-chain.

func (*Client) SendStable

func (c *Client) SendStable(ctx context.Context, opts SendOpts) (SendResult, error)

SendStable transfers SPL stablecoin from opts.From to opts.To. The sender pays the SOL fee. Auto-creates the destination ATA if opts.CreateDestATA is true.

type Config

type Config struct {
	// RPCEndpoint is a Solana JSON-RPC endpoint URL (required).
	// Example: https://api.mainnet-beta.solana.com
	RPCEndpoint string

	// KoraEndpoint is the Kora fee-abstraction JSON-RPC URL.
	// Optional. When unset, GaslessTransfer/GaslessTransferTx return ErrKoraDisabled.
	KoraEndpoint string
	// KoraAPIKey is sent as the x-api-key header when calling Kora.
	KoraAPIKey string
	// KoraHMACSecret signs each Kora request as x-hmac-signature.
	KoraHMACSecret string

	// JupiterEndpoint overrides the default Jupiter v6 endpoint
	// (https://quote-api.jup.ag/v6).
	JupiterEndpoint string
	// JupiterAPIKey is an optional Jupiter API key for paid tiers.
	JupiterAPIKey string

	// HTTPClient is shared by Kora and Jupiter clients. Defaults to a 15s
	// timeout client.
	HTTPClient *http.Client
	// MaxRetries on transient errors (5xx, 429, transport). Defaults to 3.
	MaxRetries int
}

Config holds the configuration for a stablekit Client.

type GaslessTransferOpts

type GaslessTransferOpts struct {
	// SenderSigner is the user's private key (also derives the source wallet).
	SenderSigner solana.PrivateKey
	// Recipient is the recipient owner pubkey (not an ATA).
	Recipient solana.PublicKey
	// Mint identifies the stablecoin.
	Mint Mint
	// Amount is in the token's smallest unit.
	Amount uint64
	// FeeToken is the mint that Kora will deduct the fee from. Defaults to
	// Mint when empty.
	FeeToken Mint
}

GaslessTransferOpts is the parameter for Client.GaslessTransfer.

The user signs only their portion of the transaction; Kora signs as fee payer and broadcasts. The user pays the fee in the transfer token (or any token Kora supports), not in SOL.

type GaslessTransferTxOpts

type GaslessTransferTxOpts struct {
	// Source is the sender wallet address.
	Source string
	// Destination is the recipient wallet address.
	Destination string
	// Mint identifies the stablecoin.
	Mint Mint
	// Amount is in the token's smallest unit.
	Amount uint64
}

GaslessTransferTxOpts is the parameter for Client.GaslessTransferTx — the Kora-built "simple transfer" path.

type JupiterError

type JupiterError struct {
	StatusCode int
	Body       string
}

JupiterError represents a non-2xx response from Jupiter.

func (*JupiterError) Error

func (e *JupiterError) Error() string

Error implements the error interface.

type KoraError

type KoraError struct {
	Code    int
	Message string
}

KoraError represents an error returned by the Kora JSON-RPC server.

func (*KoraError) Error

func (e *KoraError) Error() string

Error implements the error interface.

type Mint

type Mint string

Mint is the on-chain mint address of a stablecoin.

const (
	USDC Mint = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
	USDT Mint = "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"
	EURC Mint = "HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr"
)

Common Solana stablecoin mints. Adding a constant here is a convenience — any base58 mint address works at the API surface.

func (Mint) PublicKey

func (m Mint) PublicKey() (solana.PublicKey, error)

PublicKey parses the mint as a solana.PublicKey.

func (Mint) String

func (m Mint) String() string

String returns the mint address as a string.

type QuoteResponse

type QuoteResponse struct {
	InputMint            string         `json:"inputMint"`
	InAmount             string         `json:"inAmount"`
	OutputMint           string         `json:"outputMint"`
	OutAmount            string         `json:"outAmount"`
	OtherAmountThreshold string         `json:"otherAmountThreshold"`
	SwapMode             string         `json:"swapMode"`
	SlippageBps          int            `json:"slippageBps"`
	PriceImpactPct       string         `json:"priceImpactPct"`
	RoutePlan            []routePlanHop `json:"routePlan"`
}

QuoteResponse is the body returned by Jupiter's GET /quote.

type SendOpts

type SendOpts struct {
	// From is the sender wallet (also the SOL fee payer).
	From solana.PublicKey
	// FromSigner signs the transaction. Must control the wallet at From.
	FromSigner solana.PrivateKey
	// To is the recipient owner pubkey (not an ATA).
	To solana.PublicKey
	// Mint identifies the stablecoin.
	Mint Mint
	// Amount is in the token's smallest unit (e.g. 1 USDC = 1_000_000).
	Amount uint64
	// CreateDestATA controls whether to add an ATA-creation instruction
	// when the recipient's ATA does not yet exist. When false, SendStable
	// returns ErrDestATAMissing.
	CreateDestATA bool
}

SendOpts is the parameter for Client.SendStable.

type SendResult

type SendResult struct {
	// Signature is the on-chain transaction signature.
	Signature solana.Signature
	// CreatedDestATA is true if the recipient's ATA was created in this tx.
	CreatedDestATA bool
}

SendResult is what Client.SendStable returns.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL