@tributary-so/sdk
v1.4.0
Published
[](https://badge.fury.io/js/%40tributary-so%2Fsdk) [](https://opensource.org/licenses/MIT) [ - Framework: Anchor 0.31.0 for smart contract interaction
- Libraries: @solana/web3.js, @coral-xyz/anchor, @metaplex-foundation/umi
- Package Manager: pnpm 9.6.0+
- Node.js: >=16.0.0
Prerequisites
- Node.js 16.0.0 or higher
- pnpm (recommended) or npm
- A Solana RPC endpoint (mainnet-beta, devnet, or localnet)
Installation
# Using pnpm (recommended)
pnpm add @tributary-so/sdk
# Using npm
npm install @tributary-so/sdk
# Using yarn
yarn add @tributary-so/sdkGetting Started
Basic Setup
import { Tributary } from "@tributary-so/sdk";
import { Connection, Keypair } from "@solana/web3.js";
// Connect to Solana
const connection = new Connection("https://api.mainnet-beta.solana.com");
// Create a wallet (replace with your wallet loading logic)
const wallet = Keypair.generate(); // For demo only - use proper wallet in production
// Initialize SDK
const sdk = new Tributary(connection, wallet);Creating a Subscription
import { Tributary, getPaymentFrequency } from "@tributary-so/sdk";
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";
// Initialize SDK
const sdk = new Tributary(connection, wallet);
// Token addresses (example: USDC on mainnet)
const tokenMint = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
const recipient = new PublicKey("..."); // Recipient wallet
const gateway = new PublicKey("..."); // Payment gateway address
// Create subscription instructions
const instructions = await sdk.createSubscription(
tokenMint,
recipient,
gateway,
new BN("10000000"), // 10 USDC (6 decimals)
true, // auto-renew
12, // max renewals
getPaymentFrequency("monthly"), // monthly payments
[], // memo (empty)
undefined, // start immediately
undefined, // auto-calculate approval amount
false // don't execute immediately
);
// Send transaction
const tx = new Transaction().add(...instructions);
const signature = await connection.sendTransaction(tx, [wallet]);Architecture
Directory Structure
src/
├── index.ts # Main exports
├── sdk.ts # Core Tributary class
├── pda.ts # Program Derived Address utilities
├── types.ts # TypeScript type definitions
├── constants.ts # Protocol constants
├── utils.ts # Helper functions
└── token.ts # Token metadata utilitiesCore Classes
Tributary (Main SDK Class)
The primary interface for interacting with the Tributary protocol:
class Tributary {
program: Program; // Anchor program instance
programId: PublicKey; // Tributary program ID
connection: Connection; // Solana RPC connection
provider: AnchorProvider; // Anchor provider with wallet
// Payment creation methods
createSubscription(...)
createMilestone(...)
createPayAsYouGo(...)
// Gateway management
createPaymentGateway(...)
updateGatewayReferralSettings(...)
// Payment execution
executePayment(...)
// Query methods
getAllPaymentGateway()
getPaymentPoliciesByUser(...)
getUserPayment(...)
}Payment Types
Tributary supports three payment models:
1. Subscriptions
Fixed recurring payments at regular intervals:
const instructions = await sdk.createSubscription(
tokenMint,
recipient,
gateway,
new BN("1000000"), // 1 USDC per month
true, // auto-renew
null, // unlimited renewals
getPaymentFrequency("monthly"),
encodeMemo("Monthly subscription"),
undefined, // start now
undefined, // auto-calculate approval
false // don't execute immediately
);2. Milestone Payments
Project-based compensation with configurable milestones:
const milestoneAmounts = [
new BN("5000000"), // $5 for milestone 1
new BN("5000000"), // $5 for milestone 2
new BN("10000000"), // $10 for milestone 3
];
const milestoneTimestamps = [
new BN(Math.floor(Date.now() / 1000) + 86400 * 30), // 30 days
new BN(Math.floor(Date.now() / 1000) + 86400 * 60), // 60 days
new BN(Math.floor(Date.now() / 1000) + 86400 * 90), // 90 days
];
const instructions = await sdk.createMilestone(
tokenMint,
recipient,
gateway,
milestoneAmounts,
milestoneTimestamps,
1, // release condition: gateway signer approval
encodeMemo("Project milestones")
);3. Pay-as-you-go
Usage-based billing with period limits:
const instructions = await sdk.createPayAsYouGo(
tokenMint,
recipient,
gateway,
new BN("10000000"), // $10 max per period
new BN("1000000"), // $1 max per chunk
new BN(86400 * 30), // 30-day periods
encodeMemo("Usage-based billing")
);Program Derived Addresses (PDAs)
The SDK provides utilities for deriving all protocol PDAs:
import {
getConfigPda,
getGatewayPda,
getUserPaymentPda,
} from "@tributary-so/sdk";
// Program configuration PDA (singleton)
const configPda = getConfigPda(sdk.programId);
// Gateway PDA for a specific authority
const gatewayPda = getGatewayPda(gatewayAuthority, sdk.programId);
// User payment PDA for tracking payments
const userPaymentPda = getUserPaymentPda(userWallet, tokenMint, sdk.programId);Environment Variables
Required
| Variable | Description | Example |
| ---------------- | ------------------- | ------------------------------------- |
| SOLANA_RPC_URL | Solana RPC endpoint | https://api.mainnet-beta.solana.com |
Optional
| Variable | Description | Default |
| --------------------- | ---------------------- | -------------------------- |
| ANCHOR_WALLET | Path to wallet keypair | ~/.config/solana/id.json |
| ANCHOR_PROVIDER_URL | Anchor provider URL | Localnet URL |
Available Scripts
| Command | Description |
| ------------------ | ------------------------------ |
| pnpm run build | Build TypeScript to JavaScript |
| pnpm run clean | Remove build artifacts |
| pnpm run lint | Run ESLint |
| pnpm run manager | Run CLI manager tool |
API Reference
Core Methods
Payment Creation
// Create subscription
createSubscription(
tokenMint: PublicKey,
recipient: PublicKey,
gateway: PublicKey,
amount: BN,
autoRenew: boolean,
maxRenewals: number | null,
paymentFrequency: PaymentFrequency,
memo: number[],
startTime?: BN | null,
approvalAmount?: BN,
executeImmediately?: boolean,
referralCode?: string
): Promise<TransactionInstruction[]>
// Create milestone payment
createMilestone(
tokenMint: PublicKey,
recipient: PublicKey,
gateway: PublicKey,
milestoneAmounts: BN[],
milestoneTimestamps: BN[],
releaseCondition: number,
memo: number[],
approvalAmount?: BN,
executeImmediately?: boolean,
referralCode?: string
): Promise<TransactionInstruction[]>
// Create pay-as-you-go payment
createPayAsYouGo(
tokenMint: PublicKey,
recipient: PublicKey,
gateway: PublicKey,
maxAmountPerPeriod: BN,
maxChunkAmount: BN,
periodLengthSeconds: BN,
memo: number[],
approvalAmount?: BN,
referralCode?: string
): Promise<TransactionInstruction[]>Payment Execution
// Execute a payment
executePayment(
paymentPolicyPda: PublicKey,
paymentAmount?: BN,
recipient?: PublicKey,
tokenMint?: PublicKey,
gateway?: PublicKey,
user?: PublicKey
): Promise<TransactionInstruction[]>Gateway Management
// Create payment gateway
createPaymentGateway(
authority: PublicKey,
gatewayFeeBps: number,
gatewayFeeRecipient: PublicKey,
name: string,
url: string
): Promise<TransactionInstruction>
// Update gateway referral settings
updateGatewayReferralSettings(
gatewayAuthority: PublicKey,
featureFlags: number,
referralAllocationBps: number,
referralTiersBps: [number, number, number]
): Promise<TransactionInstruction>Query Methods
// Get all payment gateways
getAllPaymentGateway(): Promise<Array<{ publicKey: PublicKey; account: PaymentGateway }>>
// Get payment policies by user
getPaymentPoliciesByUser(user: PublicKey): Promise<Array<{ publicKey: PublicKey; account: PaymentPolicy }>>
// Get user payment account
getUserPayment(userPaymentAddress: PublicKey): Promise<UserPayment | null>
// Get payment gateway
getPaymentGateway(gatewayAddress: PublicKey): Promise<PaymentGateway | null>Utility Functions
Payment Frequency
import { getPaymentFrequency } from "@tributary-so/sdk";
// Convert string to PaymentFrequency enum
const monthly = getPaymentFrequency("monthly");
const custom = getPaymentFrequency("custom", 86400 * 7); // weeklyMemo Encoding
import { encodeMemo, decodeMemo } from "@tributary-so/sdk";
// Encode string to memo buffer
const memoBuffer = encodeMemo("Payment for services", 64);
// Decode memo buffer to string
const memoString = decodeMemo(memoBuffer);Token Metadata
import { getTokenInfo } from "@tributary-so/sdk";
// Get token metadata
const metadata = await getTokenInfo(connection, tokenMint);
if (metadata) {
console.log(`Token: ${metadata.data.name} (${metadata.data.symbol})`);
}PDA Utilities
import {
getConfigPda,
getGatewayPda,
getUserPaymentPda,
getPaymentPolicyPda,
getPaymentsDelegatePda,
getReferralPda,
} from "@tributary-so/sdk";
// All PDA functions return { address: PublicKey, bump: number }
const configPda = getConfigPda(programId);
const gatewayPda = getGatewayPda(authority, programId);
const userPaymentPda = getUserPaymentPda(user, tokenMint, programId);
const paymentPolicyPda = getPaymentPolicyPda(
userPaymentPda.address,
policyId,
programId
);
const paymentsDelegatePda = getPaymentsDelegatePda(programId);
const referralPda = getReferralPda(gateway, referralCodeBuffer, programId);Usage Examples
Complete Subscription Flow
import { Tributary, getPaymentFrequency, encodeMemo } from "@tributary-so/sdk";
import {
Connection,
Keypair,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import BN from "bn.js";
// Setup
const connection = new Connection("https://api.devnet.solana.com");
const wallet = Keypair.generate(); // Replace with your wallet
const sdk = new Tributary(connection, wallet);
// Airdrop SOL for fees (devnet only)
const airdropSig = await connection.requestAirdrop(
wallet.publicKey,
1_000_000_000
);
await connection.confirmTransaction(airdropSig);
// Token addresses (devnet USDC)
const tokenMint = new PublicKey("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU");
const recipient = new PublicKey("..."); // Replace with recipient
const gateway = new PublicKey("..."); // Replace with gateway
// Create subscription
const instructions = await sdk.createSubscription(
tokenMint,
recipient,
gateway,
new BN("1000000"), // 1 USDC
true, // auto-renew
12, // 12 months
getPaymentFrequency("monthly"),
encodeMemo("Monthly subscription"),
undefined, // start now
undefined, // auto-calculate approval
false // don't execute immediately
);
// Execute transaction
const tx = new Transaction().add(...instructions);
const signature = await sendAndConfirmTransaction(connection, tx, [wallet]);
console.log(`Subscription created: ${signature}`);Gateway Setup
// Create a payment gateway
const gatewayInstructions = await sdk.createPaymentGateway(
wallet.publicKey, // gateway authority
500, // 5% gateway fee
wallet.publicKey, // fee recipient
"My Payment Gateway",
"https://mygateway.com"
);
// Send transaction
const tx = new Transaction().add(gatewayInstructions);
const signature = await sendAndConfirmTransaction(connection, tx, [wallet]);Querying Protocol State
// Get all payment gateways
const gateways = await sdk.getAllPaymentGateway();
console.log(`Found ${gateways.length} gateways`);
// Get user's payment policies
const policies = await sdk.getPaymentPoliciesByUser(wallet.publicKey);
console.log(`User has ${policies.length} payment policies`);
// Get specific payment policy
const policy = await sdk.getPaymentPolicy(policyAddress);
if (policy) {
console.log(`Policy type: ${Object.keys(policy.policyType)[0]}`);
}Referral System
// Create referral account
const referralIx = await sdk.createReferralAccount(
gateway,
"ABC123", // 6-character referral code
referrerAddress // optional referrer
);
// Update gateway referral settings
const updateIx = await sdk.updateGatewayReferralSettings(
gatewayAuthority,
1, // feature flags (referrals enabled)
2500, // 25% of gateway fee for referrals
[5000, 3000, 2000] // L1: 50%, L2: 30%, L3: 20%
);Testing
Running Tests
# From project root
cd tests
npx jestTest Coverage
The SDK includes comprehensive integration tests covering:
- Program initialization
- User payment account creation
- Gateway setup and configuration
- All payment policy types (subscription, milestone, pay-as-you-go)
- Token delegation and approval
- Payment execution with fee distribution
- Referral system functionality
Building
# Build the SDK
pnpm run build
# Clean build artifacts
pnpm run clean
# Run linting
pnpm run lintContributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Make your changes with tests
- Run the test suite:
cd tests && npx jest - Ensure linting passes:
pnpm run lint - Commit with conventional commits
- Push and create a pull request
Development Setup
# Clone the repository
git clone https://github.com/tributary-so/tributary
cd tributary
# Install dependencies
pnpm install
# Build SDK
cd sdk
pnpm run buildTroubleshooting
Common Issues
Build fails with TypeScript errors:
# Clear node_modules and rebuild
rm -rf node_modules pnpm-lock.yaml
pnpm install
pnpm run buildConnection errors:
# Check your RPC endpoint
curl https://api.mainnet-beta.solana.com -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"getVersion"}'Insufficient funds for transaction:
# Check wallet balance
solana balance
# Airdrop SOL (devnet only)
solana airdrop 1Token approval errors:
- Ensure the token account exists and has sufficient balance
- Verify the approval amount covers the payment requirements
- Check that delegation hasn't already been set to another address
Security
- Non-custodial: Funds remain in user wallets
- Delegation-based: Uses SPL token delegation for automation
- Type-safe: Full TypeScript coverage prevents runtime errors
- Audited: Smart contract has been audited by professional security firms
- Access control: Proper authority verification on all operations
License
MIT License - see LICENSE file for details.
Links
- Documentation: docs.tributary.so
- Protocol Repository: github.com/tributary-so/tributary
- NPM Package: npmjs.com/package/@tributary-so/sdk
- Discord: Community discussions and support
