A powerful, type-safe Go SDK for the Tensor Protocol - The leading NFT marketplace on Solana
Installation β’ Quick Start β’ Examples β’ Contributing
- π₯ Complete API Coverage - Support for all major Tensor endpoints
- π‘οΈ Type Safety - Fully typed requests and responses
- β‘ High Performance - Optimized for speed and efficiency
- π Context Support - Built-in timeout and cancellation support
- π Rich Error Handling - Detailed error types and messages
- π§ͺ Well Tested - Comprehensive test coverage
- π Great Documentation - Clear examples and API docs
- π§ Easy Integration - Simple, intuitive API design
go get github.com/srpvpn/tensor-go-sdkpackage main
import (
"context"
"fmt"
"log"
"time"
"github.com/srpvpn/tensor-go-sdk/api/collections"
"github.com/srpvpn/tensor-go-sdk/api/escrow"
"github.com/srpvpn/tensor-go-sdk/api/marketplace"
"github.com/srpvpn/tensor-go-sdk/api/nfts"
"github.com/srpvpn/tensor-go-sdk/api/rpc"
"github.com/srpvpn/tensor-go-sdk/api/tswap"
"github.com/srpvpn/tensor-go-sdk/api/user"
"github.com/srpvpn/tensor-go-sdk/client"
)
func main() {
// Initialize client
cfg := &client.Config{
APIKey: "your-api-key",
Timeout: 30 * time.Second,
}
tensorClient := client.New(cfg)
ctx := context.Background()
// Get user portfolio
portfolio, _, err := tensorClient.User.GetPortfolio(ctx, &user.PortfolioRequest{
Wallet: "DRpbCBMxVnDK7maPM5tGv6MvB3v1sRMC86PZ8okm21hy",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d collections in portfolio\n", len(portfolio.Collections))
// Buy an NFT
buyTx, _, err := tensorClient.Marketplace.BuyNFT(ctx, &marketplace.BuyNFTRequest{
Buyer: "buyer-wallet-address",
Mint: "nft-mint-address",
Owner: "current-owner-address",
MaxPrice: 1.5,
Blockhash: "recent-blockhash",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Generated %d transactions for NFT purchase\n", len(buyTx.Txs))
// Close a TSwap pool
closeResp, statusCode, err := tensorClient.TSwap.CloseTSwapPool(ctx, &tswap.CloseTSwapPoolRequest{
PoolAddress: "pool-address",
Blockhash: "recent-blockhash",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Pool close transaction status: %d, transactions: %d\n", statusCode, len(closeResp.Txs))
// Get priority fees for optimized transactions
priorityFees, _, err := tensorClient.RPC.GetPriorityFees(ctx, &rpc.PriorityFeesRequest{})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Current priority fees - Medium: %d micro-lamports\n", priorityFees.Medium)
// Deposit to escrow account
escrowDeposit, statusCode, err := tensorClient.Escrow.DepositWithdrawEscrow(ctx, &escrow.DepositWithdrawEscrowRequest{
Action: "DEPOSIT",
Owner: "owner-wallet-address",
Lamports: 1000000000.0, // 1 SOL
Blockhash: "recent-blockhash",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Escrow deposit status: %d, response: %s\n", statusCode, escrowDeposit.Status)
// Get NFT information
nftInfo, statusCode, err := tensorClient.NFTs.GetNFTsInfo(ctx, &nfts.NFTsInfoRequest{
Mints: []string{"nft-mint-address-1", "nft-mint-address-2"},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("NFT info status: %d, data length: %d bytes\n", statusCode, len(nftInfo))
// Get verified collections
collections, statusCode, err := tensorClient.Collections.GetVerifiedCollections(ctx, &collections.GetVerifiedCollectionsRequest{
SortBy: "statsV2.volume1h:desc",
Limit: 10,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found %d verified collections\n", len(collections))
}Portfolio Management
// Get user's NFT portfolio
portfolio, _, err := client.User.GetPortfolio(ctx, &user.PortfolioRequest{
Wallet: "wallet-address",
IncludeBidCount: &[]bool{true}[0],
IncludeFavouriteCount: &[]bool{true}[0],
IncludeUnverified: &[]bool{false}[0],
Currencies: []string{"SOL", "USDC"},
})Active Listings
// Get user's active NFT listings
listings, _, err := client.User.GetListings(ctx, &user.ListingsRequest{
Wallets: []string{"wallet1", "wallet2"},
SortBy: "PriceDesc",
Limit: 50,
CollId: &[]string{"collection-id"}[0],
Currencies: []string{"SOL"},
})Bid Management
// Get NFT bids
nftBids, _, err := client.User.GetNFTBids(ctx, &user.NFTBidsRequest{
Owner: "wallet-address",
Limit: 100,
CollId: &[]string{"collection-id"}[0],
})
// Get collection bids
collBids, _, err := client.User.GetCollectionBids(ctx, &user.CollectionBidsRequest{
Owner: "wallet-address",
Limit: 100,
CollId: &[]string{"collection-id"}[0],
})
// Get trait bids
traitBids, _, err := client.User.GetTraitBids(ctx, &user.TraitBidsRequest{
Owner: "wallet-address",
Limit: 100,
CollId: &[]string{"collection-id"}[0],
})Transaction History
// Get user's transaction history
transactions, _, err := client.User.GetTransactions(ctx, &user.TransactionsRequest{
Wallets: []string{"wallet-address"},
Limit: 100,
TxTypes: []string{"SALE_BUY_NOW", "SALE_ACCEPT_BID", "LIST"},
Collid: "collection-id",
})Pool Management
// Get TSwap pools
tswapPools, _, err := client.User.GetTSwapPools(ctx, &user.TSwapsPoolsRequest{
Owner: "wallet-address",
PoolAddresses: []string{"pool1", "pool2"},
Limit: 50,
})
// Get TAmm pools
tammPools, _, err := client.User.GetTAmmPools(ctx, &user.TAmmPoolsRequest{
Owner: "wallet-address",
PoolAddresses: []string{"pool1", "pool2"},
Limit: 50,
})Escrow & Inventory
// Get escrow accounts
escrow, _, err := client.User.GetEscrowAccounts(ctx, &user.EscrowAccountsRequest{
Owner: "wallet-address",
})
// Get inventory for collection
inventory, _, err := client.User.GetInventoryForCollection(ctx, &user.InventoryForCollectionRequest{
Wallets: []string{"wallet-address"},
CollId: &[]string{"collection-id"}[0],
Limit: &[]int32{100}[0],
})Pool Management
// Close TSwap pool
closeResp, statusCode, err := client.TSwap.CloseTSwapPool(ctx, &tswap.CloseTSwapPoolRequest{
PoolAddress: "pool-address",
Blockhash: "recent-blockhash",
Compute: &[]int32{200000}[0],
PriorityMicroLamports: &[]int32{1000}[0],
})
// Edit TSwap pool
editResp, statusCode, err := client.TSwap.EditTSwapPool(ctx, &tswap.EditTSwapPoolRequest{
PoolAddress: "pool-address",
PoolType: "TOKEN", // TOKEN, NFT, or TRADE
CurveType: "linear", // linear or exponential
StartingPrice: 1.5,
Delta: 0.1,
Blockhash: "recent-blockhash",
MmKeepFeesSeparate: &[]bool{true}[0],
MmFeeBps: &[]float64{250.0}[0], // 2.5%
MaxTakerSellCount: &[]int32{10}[0],
UseSharedEscrow: &[]bool{false}[0],
Compute: &[]int32{200000}[0],
PriorityMicroLamports: &[]int32{1000}[0],
})NFT Deposit/Withdraw
// Deposit NFT to TSwap pool
depositNFTResp, statusCode, err := client.TSwap.DepositWithdrawNFT(ctx, &tswap.DepositWithdrawNFTRequest{
Action: "DEPOSIT", // DEPOSIT or WITHDRAW
PoolAddress: "pool-address",
Mint: "nft-mint-address",
Blockhash: "recent-blockhash",
NftSource: &[]string{"source-address"}[0],
Compute: &[]int32{200000}[0],
PriorityMicroLamports: &[]int32{1000}[0],
})
// Withdraw NFT from TSwap pool
withdrawNFTResp, statusCode, err := client.TSwap.DepositWithdrawNFT(ctx, &tswap.DepositWithdrawNFTRequest{
Action: "WITHDRAW",
PoolAddress: "pool-address",
Mint: "nft-mint-address",
Blockhash: "recent-blockhash",
})SOL Deposit/Withdraw
// Deposit SOL to TSwap pool
depositSOLResp, statusCode, err := client.TSwap.DepositWithdrawSOL(ctx, &tswap.DepositWithdrawSOLRequest{
Action: "DEPOSIT", // DEPOSIT or WITHDRAW (case insensitive, normalized to uppercase)
PoolAddress: "pool-address",
Lamports: 1000000000.0, // 1 SOL in lamports
Blockhash: "recent-blockhash",
Compute: &[]int32{200000}[0],
PriorityMicroLamports: &[]int32{1000}[0],
})
// Withdraw SOL from TSwap pool
withdrawSOLResp, statusCode, err := client.TSwap.DepositWithdrawSOL(ctx, &tswap.DepositWithdrawSOLRequest{
Action: "WITHDRAW",
PoolAddress: "pool-address",
Lamports: 500000000.0, // 0.5 SOL in lamports
Blockhash: "recent-blockhash",
})NFT Trading
// Buy NFT
buyTx, _, err := client.Marketplace.BuyNFT(ctx, &marketplace.BuyNFTRequest{
Buyer: "buyer-wallet",
Mint: "nft-mint",
Owner: "current-owner",
MaxPrice: 1.5,
Blockhash: "recent-blockhash",
OptionalRoyaltyPct: &[]int32{5}[0],
})
// Sell NFT (accept bid)
sellTx, _, err := client.Marketplace.SellNFT(ctx, &marketplace.SellNFTRequest{
Seller: "seller-wallet",
Mint: "nft-mint",
BidAddress: "bid-address",
MinPrice: 1.0,
Blockhash: "recent-blockhash",
})Listing Management
// List NFT
listTx, _, err := client.Marketplace.ListNFT(ctx, &marketplace.ListNFTRequest{
Mint: "nft-mint",
Owner: "owner-wallet",
Price: 2.5,
Blockhash: "recent-blockhash",
ExpireIn: &[]int32{3600}[0], // 1 hour
})
// Edit listing
editTx, _, err := client.Marketplace.EditListing(ctx, &marketplace.EditListingRequest{
Mint: "nft-mint",
Owner: "owner-wallet",
Price: 3.0, // New price
Blockhash: "recent-blockhash",
})
// Delist NFT
delistTx, _, err := client.Marketplace.DelistNFT(ctx, &marketplace.DelistNFTRequest{
Mint: "nft-mint",
Owner: "owner-wallet",
Blockhash: "recent-blockhash",
})Bidding
// Place NFT bid
nftBidTx, _, err := client.Marketplace.PlaceNFTBid(ctx, &marketplace.PlaceNFTBidRequest{
Owner: "bidder-wallet",
Price: 1.5,
Mint: "nft-mint",
Blockhash: "recent-blockhash",
UseSharedEscrow: &[]bool{true}[0],
})
// Place collection bid
collBidTx, _, err := client.Marketplace.PlaceCollectionBid(ctx, &marketplace.PlaceCollectionBidRequest{
Owner: "bidder-wallet",
Price: 1.0,
Quantity: 5,
CollId: "collection-id",
Blockhash: "recent-blockhash",
})
// Place trait bid
traitBidTx, _, err := client.Marketplace.PlaceTraitBid(ctx, &marketplace.PlaceTraitBidRequest{
Owner: "bidder-wallet",
Price: 0.8,
Quantity: 3,
CollId: "collection-id",
Traits: []string{"trait1", "trait2"},
Blockhash: "recent-blockhash",
})Bid Management
// Edit bid
editBidTx, _, err := client.Marketplace.EditBid(ctx, &marketplace.EditBidRequest{
BidStateAddress: "bid-state-address",
Blockhash: "recent-blockhash",
Price: &[]float64{2.0}[0], // New price
Quantity: &[]int32{10}[0], // New quantity
})
// Cancel bid
cancelTx, _, err := client.Marketplace.CancelBid(ctx, &marketplace.CancelBidRequest{
BidStateAddress: "bid-state-address",
Blockhash: "recent-blockhash",
})Priority Fees
// Get market-based priority fees for transaction creation
priorityFees, statusCode, err := client.RPC.GetPriorityFees(ctx, &rpc.PriorityFeesRequest{})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Priority Fees - Min: %d, Low: %d, Medium: %d, High: %d, Very High: %d\n",
priorityFees.Min, priorityFees.Low, priorityFees.Medium, priorityFees.High, priorityFees.VeryHigh)
// Use the fees in your transaction
compute := int32(200000)
priorityMicroLamports := int32(priorityFees.Medium) // Use medium priority
buyTx, _, err := client.Marketplace.BuyNFT(ctx, &marketplace.BuyNFTRequest{
Buyer: "buyer-wallet",
Mint: "nft-mint",
Owner: "current-owner",
MaxPrice: 1.5,
Blockhash: "recent-blockhash",
Compute: &compute,
PriorityMicroLamports: &priorityMicroLamports,
})Escrow Management
// Deposit SOL to escrow account
depositResp, statusCode, err := client.Escrow.DepositWithdrawEscrow(ctx, &escrow.DepositWithdrawEscrowRequest{
Action: "DEPOSIT", // DEPOSIT or WITHDRAW (case insensitive, normalized to uppercase)
Owner: "owner-wallet-address",
Lamports: 1000000000.0, // 1 SOL in lamports
Blockhash: "recent-blockhash",
Compute: &[]int32{200000}[0],
PriorityMicroLamports: &[]int32{1000}[0],
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Escrow deposit status: %d, response: %s\n", statusCode, depositResp.Status)
// Withdraw SOL from escrow account
withdrawResp, statusCode, err := client.Escrow.DepositWithdrawEscrow(ctx, &escrow.DepositWithdrawEscrowRequest{
Action: "WITHDRAW",
Owner: "owner-wallet-address",
Lamports: 500000000.0, // 0.5 SOL in lamports
Blockhash: "recent-blockhash",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Escrow withdraw status: %d, response: %s\n", statusCode, withdrawResp.Status)
// Use with priority fees for optimized transactions
priorityFees, _, err := client.RPC.GetPriorityFees(ctx, &rpc.PriorityFeesRequest{})
if err != nil {
log.Fatal(err)
}
compute := int32(200000)
priorityMicroLamports := int32(priorityFees.Medium)
optimizedDeposit, _, err := client.Escrow.DepositWithdrawEscrow(ctx, &escrow.DepositWithdrawEscrowRequest{
Action: "DEPOSIT",
Owner: "owner-wallet-address",
Lamports: 2000000000.0, // 2 SOL
Blockhash: "recent-blockhash",
Compute: &compute,
PriorityMicroLamports: &priorityMicroLamports,
})NFT Information
// Get NFT info by mint addresses
nftInfoBytes, statusCode, err := client.NFTs.GetNFTsInfo(ctx, &nfts.NFTsInfoRequest{
Mints: []string{
"nft-mint-address-1",
"nft-mint-address-2",
"nft-mint-address-3",
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("NFT info response (status: %d): %s\n", statusCode, string(nftInfoBytes))
// Single NFT info
singleNFTBytes, statusCode, err := client.NFTs.GetNFTsInfo(ctx, &nfts.NFTsInfoRequest{
Mints: []string{"single-nft-mint-address"},
})NFTs by Collection
// Get NFTs by collection with basic filters
collectionNFTsBytes, statusCode, err := client.NFTs.GetNFTsByCollection(ctx, &nfts.NFTsByCollectionRequest{
CollId: "collection-id",
SortBy: "PriceAsc", // PriceAsc, PriceDesc, RarityAsc, RarityDesc, etc.
Limit: 50,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Collection NFTs response (status: %d): %s\n", statusCode, string(collectionNFTsBytes))
// Advanced filtering with all options
advancedFilterBytes, statusCode, err := client.NFTs.GetNFTsByCollection(ctx, &nfts.NFTsByCollectionRequest{
CollId: "collection-id",
SortBy: "PriceDesc",
Limit: 100,
OnlyListings: &[]bool{true}[0], // Only show listed NFTs
MinPrice: &[]float64{0.5}[0], // Minimum price filter
MaxPrice: &[]float64{10.0}[0], // Maximum price filter
TraitCountMin: &[]int32{3}[0], // Minimum trait count
TraitCountMax: &[]int32{8}[0], // Maximum trait count
Name: &[]string{"Cool NFT"}[0], // Name filter
ExcludeOwners: []string{"owner-to-exclude"}, // Exclude specific owners
IncludeOwners: []string{"owner-to-include"}, // Include only specific owners
IncludeCurrencies: []string{"SOL", "USDC"}, // Currency filters
Traits: []string{`{"Background": ["Blue", "Red"]}`}, // Trait filters
RaritySystem: &[]string{"tensor"}[0], // Rarity system
RarityMin: &[]float64{1.0}[0], // Minimum rarity
RarityMax: &[]float64{100.0}[0], // Maximum rarity
OnlyInscriptions: &[]bool{false}[0], // Solana Inscriptions filter
ImmutableStatus: &[]string{"mutable"}[0], // Immutability filter
})
// Pagination with cursor
paginatedBytes, statusCode, err := client.NFTs.GetNFTsByCollection(ctx, &nfts.NFTsByCollectionRequest{
CollId: "collection-id",
SortBy: "PriceAsc",
Limit: 50,
Cursor: &[]string{"cursor-from-previous-response"}[0],
})
// Filter by specific mints within collection
specificMintsBytes, statusCode, err := client.NFTs.GetNFTsByCollection(ctx, &nfts.NFTsByCollectionRequest{
CollId: "collection-id",
SortBy: "PriceAsc",
Limit: 50,
Mints: []string{"mint1", "mint2", "mint3"}, // Filter for specific mints
})Get Verified Collections
// Get top collections by volume
collectionsBytes, statusCode, err := client.Collections.GetVerifiedCollections(ctx, &collections.GetVerifiedCollectionsRequest{
SortBy: "statsV2.volume1h:desc", // Sort by 1h volume descending
Limit: 10, // Get top 10 collections
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Collections response (status: %d): %s\n", statusCode, string(collectionsBytes))
// Get specific collections by slug
specificCollections, statusCode, err := client.Collections.GetVerifiedCollections(ctx, &collections.GetVerifiedCollectionsRequest{
SortBy: "statsV2.volume24h:desc",
Limit: 5,
SlugDisplays: []string{"portalsuniverse", "degods", "madlads"},
})
// Get collections by collection IDs
collByIds, statusCode, err := client.Collections.GetVerifiedCollections(ctx, &collections.GetVerifiedCollectionsRequest{
SortBy: "statsV2.floor1h:asc",
Limit: 20,
CollIds: []string{"ec2fc59c-8240-4166-ad76-478f57958188"},
})
// Get collections with pagination
page1, statusCode, err := client.Collections.GetVerifiedCollections(ctx, &collections.GetVerifiedCollectionsRequest{
SortBy: "statsV2.marketCap:desc",
Limit: 50,
Page: func() *int32 { v := int32(1); return &v }(),
})
page2, statusCode, err := client.Collections.GetVerifiedCollections(ctx, &collections.GetVerifiedCollectionsRequest{
SortBy: "statsV2.marketCap:desc",
Limit: 50,
Page: func() *int32 { v := int32(2); return &v }(),
})
// Filter by verified on-chain collection (max 10 vocs/fvcs)
onChainFiltered, statusCode, err := client.Collections.GetVerifiedCollections(ctx, &collections.GetVerifiedCollectionsRequest{
SortBy: "statsV2.volume7d:desc",
Limit: 25,
Vocs: []string{"voc-address-1", "voc-address-2"},
})
// Filter by first verified creators (max 10 vocs/fvcs)
creatorFiltered, statusCode, err := client.Collections.GetVerifiedCollections(ctx, &collections.GetVerifiedCollectionsRequest{
SortBy: "statsV2.sales24h:desc",
Limit: 25,
Fvcs: []string{"creator-address-1", "creator-address-2"},
})
| API Category | Status | Endpoints |
|---|---|---|
| User API | β Complete | Portfolio, Listings, Bids, Transactions, Pools, Escrow, Inventory |
| Marketplace API | β Complete | Buy, Sell, List, Delist, Edit, Bid, Cancel |
| TSwap API | β Complete | Close Pool, Edit Pool, Deposit/Withdraw NFT, Deposit/Withdraw SOL |
| RPC API | β Complete | Priority Fees |
| Shared Escrow API | β Complete | Deposit/Withdraw Escrow |
| NFTs API | β Complete | NFT Info, NFTs by Collection |
| API Category | Status | Priority | Description |
|---|---|---|---|
| TAmm API | π Planned | Medium | Advanced AMM features |
| Data API - Orders | π Planned | Medium | Order book and market data |
| Data API - Collections | π Planned | Medium | Collection statistics |
| Refresh API | π Planned | Low | Data refresh endpoints |
| SDK API - Mint Proof | π Planned | Medium | Mint proof generation |
| SDK API - Trait Bids | π Planned | Medium | Advanced trait bidding |
| SDK API - Whitelist | π Planned | Low | Whitelist management |
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run tests with race detection
go test -race ./...
# Run specific package tests
go test ./api/user
go test ./api/marketplaceCheck out the examples directory for complete working examples:
- Basic Usage - Simple portfolio and trading operations
- Advanced Trading - Complex trading scenarios
We welcome contributions! This project is growing fast and we'd love your help to make it even better.
- π Report Bugs - Found an issue? Let us know!
- π‘ Feature Requests - Have an idea? We'd love to hear it!
- π Documentation - Help improve our docs
- π§ Code Contributions - Submit PRs for new features or fixes
- π§ͺ Testing - Help us improve test coverage
- π Spread the Word - Star the repo and tell others!
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for your changes
- Ensure all tests pass (
go test ./...) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Clone the repo
git clone https://github.com/srpvpn/tensor-go-sdk.git
cd tensor-go-sdk
# Install dependencies
go mod download
# Run tests
go test ./...
# Run linter (if you have golangci-lint installed)
golangci-lint runThis project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Built with β€οΈ for the Solana NFT ecosystem