TypeScript SDK for the Tributary recurring payments protocol on Solana. Provides a complete interface for creating payment gateways, managing subscriptions, executing payments, and interacting with the protocol.
TRibg8W8zmPHQqWtyAD1rEBRXEdyU13Mu6qX1Sg42tJ)# Using pnpm (recommended)
pnpm add @tributary-so/sdk
# Using npm
npm install @tributary-so/sdk
# Using yarn
yarn add @tributary-so/sdk
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);
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]);
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 utilities
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(...)
}
Tributary supports three payment models:
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
);
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")
);
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")
);
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);
| Variable | Description | Example |
|---|---|---|
SOLANA_RPC_URL |
Solana RPC endpoint | https://api.mainnet-beta.solana.com |
| Variable | Description | Default |
|---|---|---|
ANCHOR_WALLET |
Path to wallet keypair | ~/.config/solana/id.json |
ANCHOR_PROVIDER_URL |
Anchor provider URL | Localnet URL |
| 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 |
// 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[]>
// Execute a payment
executePayment(
paymentPolicyPda: PublicKey,
paymentAmount?: BN,
recipient?: PublicKey,
tokenMint?: PublicKey,
gateway?: PublicKey,
user?: PublicKey
): Promise<TransactionInstruction[]>
// 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>
// 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>
import { getPaymentFrequency } from "@tributary-so/sdk";
// Convert string to PaymentFrequency enum
const monthly = getPaymentFrequency("monthly");
const custom = getPaymentFrequency("custom", 86400 * 7); // weekly
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);
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})`);
}
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);
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}`);
// 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]);
// 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]}`);
}
// 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%
);
# From project root
cd tests
npx jest
The SDK includes comprehensive integration tests covering:
# Build the SDK
pnpm run build
# Clean build artifacts
pnpm run clean
# Run linting
pnpm run lint
git checkout -b feature/your-featurecd tests && npx jestpnpm run lint# Clone the repository
git clone https://github.com/tributary-so/tributary
cd tributary
# Install dependencies
pnpm install
# Build SDK
cd sdk
pnpm run build
Build fails with TypeScript errors:
# Clear node_modules and rebuild
rm -rf node_modules pnpm-lock.yaml
pnpm install
pnpm run build
Connection 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 1
Token approval errors:
MIT License - see LICENSE file for details.