Installation

Install the Fraction SDK using your preferred package manager:
pnpm install @sendaifun/fraction

Quick Start

Initialize Client

import { Fraction } from '@sendaifun/fraction';
import { Connection, Keypair } from '@solana/web3.js';

const connection = new Connection('https://api.devnet.solana.com');
const payer = Keypair.generate();

// Initialize client
const client = new Fraction(
  'https://api.devnet.solana.com', // RPC endpoint
  payer.publicKey                  // Transaction payer
);

Create Revenue Split Configuration

const participants = [
  { wallet: teamMember1.publicKey, shareBps: 4000 }, // 40%
  { wallet: teamMember2.publicKey, shareBps: 3000 }, // 30%
  { wallet: teamMember3.publicKey, shareBps: 2000 }, // 20%
  { wallet: teamMember4.publicKey, shareBps: 1000 }, // 10%
];

const { tx, fractionConfigPda } = await client.createFraction({
  participants,
  authority: authority.publicKey,
  name: 'team-revenue-split',
  botWallet: distributionAgent.publicKey
});

Execute Distribution

// Agent triggers distribution
const tx = await client.claimAndDistribute(
  fractionConfigPda,     // Configuration account
  usdcMint               // Token mint to distribute
);

API Reference

Client Class

Constructor

new Fraction(rpc?: string, payer?: PublicKey)
rpc
string
RPC endpoint URL (defaults to mainnet-beta)
payer
PublicKey
Transaction fee payer (only required for versioned transactions)

Methods

State Queries

Advanced Usage

Low-Level Instructions

For advanced users who need fine-grained control over transaction building:
import { createFractionIx, getProgram } from '@sendaifun/fraction';

const program = getProgram(connection);

// Create instruction
const { ix, fractionConfigPda } = await createFractionIx(program, {
  participants: participants,
  authority: authority.publicKey,
  botWallet: agent.publicKey
});

// Build composite transaction
const tx = new Transaction()
  .add(setupInstruction)
  .add(ix)
  .add(followupInstruction);

Treasury Management

Calculate and manage treasury accounts:
import { getAssociatedTokenAddressSync } from '@solana/spl-token';

// Calculate treasury address
const treasuryAddress = getAssociatedTokenAddressSync(
  tokenMint,          // Token to be distributed
  fractionConfigPda,  // Treasury owner (PDA)
  true                // Allow off-curve addresses
);

// Fund treasury
await transfer(
  connection,
  payer,
  sourceTokenAccount,
  treasuryAddress,
  authority,
  amount
);

Examples

Enterprise Revenue Distribution

import { Fraction } from '@sendaifun/fraction';
import { Connection, Keypair } from '@solana/web3.js';

const connection = new Connection('https://api.mainnet-beta.solana.com');
const client = new Fraction(connection.rpcEndpoint, authority.publicKey);

// Define revenue allocation
const participants = [
  { wallet: founder.publicKey, shareBps: 4000 },    // 40% founder
  { wallet: team.publicKey, shareBps: 3000 },       // 30% team  
  { wallet: investors.publicKey, shareBps: 2000 },  // 20% investors
  { wallet: operations.publicKey, shareBps: 1000 }  // 10% operations
];

// Deploy configuration
const { tx, fractionConfigPda } = await client.createFraction({
  participants,
  authority: company.publicKey,
  name: 'quarterly-revenue-2024',
  botWallet: automatedAgent.publicKey
});

// Sign and submit
await connection.sendTransaction(tx, [authority]);

Multi-Token Distribution

const tokens = [
  { mint: usdcMint, name: 'USDC Revenue' },
  { mint: solMint, name: 'SOL Rewards' },
  { mint: projectToken, name: 'Token Emissions' }
];

// Distribute multiple tokens using same configuration
for (const token of tokens) {
  const distributionTx = await client.claimAndDistribute(
    fractionConfigPda,
    token.mint
  );
  
  await connection.sendTransaction(distributionTx, [agent]);
  console.log(`Distributed ${token.name}`);
}

Dynamic Updates

// Quarterly rebalancing
const newAllocation = [
  { wallet: founder.publicKey, shareBps: 3500 },    // Reduced to 35%
  { wallet: team.publicKey, shareBps: 3500 },       // Increased to 35%
  { wallet: investors.publicKey, shareBps: 2000 },  // Maintained 20%
  { wallet: operations.publicKey, shareBps: 1000 }  // Maintained 10%
];

const updateTx = await client.updateFraction(fractionConfigPda, {
  participants: newAllocation,
  botWallet: newAgent.publicKey // Optional: update agent
});

await connection.sendTransaction(updateTx, [authority]);

Error Handling

Common Validation Errors

The SDK implements client-side validation with clear error messages:
ErrorDescription
InvalidShareDistributionParticipant shares don’t sum to 10,000 BPS
NoFundsToDistributeTreasury account is empty
DuplicateParticipantWalletSame wallet appears multiple times
BotWalletConflictAgent wallet matches participant wallet
SystemProgramParticipantSystem program cannot have non-zero shares

Error Handling Pattern

async function safeDistribution(config: PublicKey, mint: PublicKey) {
  try {
    const tx = await client.claimAndDistribute(config, mint);
    const signature = await connection.sendTransaction(tx, [agent]);
    return { success: true, signature };
  } catch (error) {
    if (error.message.includes('NoFundsToDistribute')) {
      return { success: false, reason: 'Treasury empty' };
    }
    throw error; // Re-throw unexpected errors
  }
}

Type Definitions

Core Types

type Participant = {
  wallet: PublicKey;
  shareBps: number; // 0-10,000 basis points (0-100%)
}

type FractionConfig = {
  authority: PublicKey;
  name: string;
  participants: Participant[];
  botWallet: PublicKey;
  incentiveBps: number;
  bump: number;
}
Basis Points (BPS): Share allocations use basis points where 10,000 BPS = 100%. For example, 4000 BPS = 40%.

Configuration Derivation

import { PublicKey } from '@solana/web3.js';

// Derive configuration PDA
const [configPda, bump] = PublicKey.findProgramAddressSync(
  [
    Buffer.from("fraction_config"),
    authority.toBuffer(),
    Buffer.from(configurationName)
  ],
  programId
);

Program IDL

The complete Interface Description Language (IDL) for the Fraction protocol:
{
  "address": "FracVQuBhSeBvbw1qNrJKkDmcdPcFYWdneoKbJa3HMrj",
  "metadata": {
    "name": "fraction",
    "version": "0.1.0",
    "spec": "0.1.0",
    "description": "Created with Anchor"
  },
  "instructions": [
    {
      "name": "claim_and_distribute",
      "discriminator": [3],
      "accounts": [
        { "name": "bot_wallet", "writable": true, "signer": true },
        { "name": "authority" },
        {
          "name": "fraction_config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  102, 114, 97, 99, 116, 105, 111, 110, 95, 99, 111, 110, 102,
                  105, 103
                ]
              },
              {
                "kind": "account",
                "path": "fraction_config.authority",
                "account": "FractionConfig"
              },
              {
                "kind": "account",
                "path": "fraction_config.name",
                "account": "FractionConfig"
              }
            ]
          }
        },
        {
          "name": "treasury",
          "writable": true,
          "pda": {
            "seeds": [
              { "kind": "account", "path": "fraction_config" },
              { "kind": "account", "path": "token_program" },
              { "kind": "account", "path": "treasury_mint" }
            ],
            "program": {
              "kind": "const",
              "value": [
                140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142,
                13, 131, 11, 90, 19, 153, 218, 255, 16, 132, 4, 142, 123, 216,
                219, 233, 248, 89
              ]
            }
          }
        },
        { "name": "treasury_mint" },
        { "name": "bot_token_account", "writable": true },
        { "name": "participant_token_account_0", "writable": true },
        { "name": "participant_token_account_1", "writable": true },
        { "name": "participant_token_account_2", "writable": true },
        { "name": "participant_token_account_3", "writable": true },
        { "name": "participant_token_account_4", "writable": true },
        { "name": "token_program" },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": []
    },
    {
      "name": "initialize_fraction",
      "discriminator": [1],
      "accounts": [
        { "name": "authority", "writable": true, "signer": true },
        {
          "name": "fraction_config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  102, 114, 97, 99, 116, 105, 111, 110, 95, 99, 111, 110, 102,
                  105, 103
                ]
              },
              { "kind": "account", "path": "authority" },
              { "kind": "arg", "path": "name" }
            ]
          }
        },
        {
          "name": "system_program",
          "address": "11111111111111111111111111111111"
        }
      ],
      "args": [
        { "name": "name", "type": "string" },
        {
          "name": "participants",
          "type": { "array": [{ "defined": { "name": "Participant" } }, 5] }
        },
        { "name": "bot_wallet", "type": "pubkey" }
      ]
    },
    {
      "name": "update_fraction",
      "discriminator": [2],
      "accounts": [
        {
          "name": "authority",
          "signer": true,
          "relations": ["fraction_config"]
        },
        {
          "name": "fraction_config",
          "writable": true,
          "pda": {
            "seeds": [
              {
                "kind": "const",
                "value": [
                  102, 114, 97, 99, 116, 105, 111, 110, 95, 99, 111, 110, 102,
                  105, 103
                ]
              },
              {
                "kind": "account",
                "path": "fraction_config.authority",
                "account": "FractionConfig"
              },
              {
                "kind": "account",
                "path": "fraction_config.name",
                "account": "FractionConfig"
              }
            ]
          }
        }
      ],
      "args": [
        {
          "name": "participants",
          "type": { "array": [{ "defined": { "name": "Participant" } }, 5] }
        },
        { "name": "bot_wallet", "type": "pubkey" }
      ]
    }
  ],
  "accounts": [{ "name": "FractionConfig", "discriminator": [1] }],
  "errors": [
    {
      "code": 6000,
      "name": "InvalidShareDistribution",
      "msg": "Invalid share distribution - must sum to 10,000"
    },
    { "code": 6001, "name": "NameTooLong", "msg": "Name too long" },
    {
      "code": 6002,
      "name": "NoFundsToDistribute",
      "msg": "No funds to distribute"
    },
    {
      "code": 6003,
      "name": "ArithmeticOverflow",
      "msg": "Arithmetic overflow"
    },
    {
      "code": 6004,
      "name": "DuplicateParticipantWallet",
      "msg": "Duplicate participant wallet detected"
    },
    {
      "code": 6005,
      "name": "BotWalletConflict",
      "msg": "Bot wallet cannot be the same as any participant wallet"
    },
    {
      "code": 6006,
      "name": "InvalidAuthority",
      "msg": "Invalid authority provided"
    },
    { "code": 6007, "name": "InvalidBot", "msg": "Invalid bot wallet" },
    {
      "code": 6008,
      "name": "SystemProgramParticipant",
      "msg": "System program cannot be a participant wallet"
    },
    { "code": 6009, "name": "InvalidAccount", "msg": "Invalid account owner" }
  ],
  "types": [
    {
      "name": "FractionConfig",
      "type": {
        "kind": "struct",
        "fields": [
          { "name": "authority", "type": "pubkey" },
          { "name": "name", "type": "string" },
          {
            "name": "participants",
            "type": { "array": [{ "defined": { "name": "Participant" } }, 5] }
          },
          { "name": "bot_wallet", "type": "pubkey" },
          { "name": "incentive_bps", "type": "u8" },
          { "name": "bump", "type": "u8" }
        ]
      }
    },
    {
      "name": "Participant",
      "type": {
        "kind": "struct",
        "fields": [
          { "name": "wallet", "type": "pubkey" },
          { "name": "share_bps", "type": "u16" }
        ]
      }
    }
  ]
}

Program Address: The Fraction protocol is deployed at Ck2PtB73t36kjk4mLUztwsBV9jvq7q3mGfSNmQevwFgg. This IDL can be used with Anchor clients or other Solana development tools for direct program interaction.

Best Practices

Share Distribution: Always ensure participant shares sum to exactly 10,000 BPS (100%) to avoid validation errors.
Agent Selection: Choose reliable agents for distribution triggers. Consider using services like Clockwork for automated scheduling.
Authority Security: The authority can update configurations and should use secure key management practices.
Multi-Token Support: The same configuration can distribute different SPL tokens - just call claimAndDistribute with different mint addresses.