Skip to main content

SDK Overview

Detailed overview of the Mass Payout SDK architecture and available operations.

What the SDK Does​

The Mass Payout SDK is a TypeScript library for interacting with the LifeCycle Cash Flow smart contract on Hedera. It provides two core functionalities:

  1. Contract Interaction: Create and execute transactions with the LifeCycle Cash Flow contract
  2. Transaction Signing: Sign transactions using custodial wallet providers (DFNS)

Transaction Signing with Custodial Wallets​

The SDK uses the Hedera Custodians Library for secure transaction signing. Instead of managing private keys directly, transactions are signed remotely by DFNS.

How Transaction Signing Works​

Your Application
│
▼
SDK creates unsigned transaction
│
▼
Transaction sent to DFNS API
│
▼
DFNS signs with secure private key
│
▼
Signed transaction submitted to Hedera
│
▼
Transaction receipt returned

Benefits:

  • Private keys never leave the custodial provider's infrastructure
  • Enterprise-grade audit trails and access controls
  • Compliance with regulatory requirements

Available Operations​

Commands (Write Operations)​

Commands modify blockchain state and require transaction signing:

  • DeployCommand - Deploy new LifeCycle Cash Flow contract
  • ExecuteDistributionCommand - Execute payment distribution (paginated)
  • ExecuteDistributionByAddressesCommand - Execute distribution for specific addresses
  • ExecuteAmountSnapshotCommand - Create fixed-amount snapshot (paginated)
  • ExecuteAmountSnapshotByAddressesCommand - Create fixed-amount snapshot for specific addresses
  • ExecutePercentageSnapshotCommand - Create percentage-based snapshot (paginated)
  • ExecutePercentageSnapshotByAddressesCommand - Create percentage snapshot for specific addresses
  • ExecuteBondCashOutCommand - Execute bond maturity cash-out (paginated)
  • ExecuteBondCashOutByAddressesCommand - Execute bond cash-out for specific addresses
  • PauseCommand - Pause contract (emergency stop)
  • UnpauseCommand - Resume contract operations

Queries (Read Operations)​

Queries read contract state without transactions:

  • GetPaymentTokenQuery - Get payment token address
  • GetPaymentTokenDecimalsQuery - Get payment token decimals
  • IsPausedQuery - Check if contract is paused

Usage Examples​

Deploy a Contract​

import { DeployCommand } from "@hashgraph/mass-payout-sdk";

const command = new DeployCommand({
tokenAddress: "0.0.789012", // Asset token address
paymentTokenAddress: "0.0.429274", // Payment token (e.g., USDC)
});

const result = await commandBus.execute(command);
console.log("Contract deployed at:", result.contractId);

Execute a Distribution​

import { ExecuteDistributionCommand } from "@hashgraph/mass-payout-sdk";

const command = new ExecuteDistributionCommand({
contractId: "0.0.123456",
holderAddresses: ["0xabc...", "0xdef...", "0xghi..."],
amounts: ["100", "200", "150"], // In smallest unit (e.g., cents for USDC)
startIndex: 0,
endIndex: 100, // For pagination with large holder lists
});

const receipt = await commandBus.execute(command);
console.log("Distribution executed:", receipt.transactionId);

Create a Snapshot (Fixed Amount)​

import { ExecuteAmountSnapshotCommand } from "@hashgraph/mass-payout-sdk";

const command = new ExecuteAmountSnapshotCommand({
contractId: "0.0.123456",
holderAddresses: ["0xabc...", "0xdef..."],
amounts: ["100", "100"], // Same amount for all holders
startIndex: 0,
endIndex: 50,
});

await commandBus.execute(command);

Create a Snapshot (Percentage-based)​

import { ExecutePercentageSnapshotCommand } from "@hashgraph/mass-payout-sdk";

const command = new ExecutePercentageSnapshotCommand({
contractId: "0.0.123456",
holderAddresses: ["0xabc...", "0xdef..."],
balances: ["1000", "2000"], // Token balances for each holder
totalAmount: "300", // Total amount to distribute proportionally
startIndex: 0,
endIndex: 50,
});

await commandBus.execute(command);

Execute Bond Cash-Out​

import { ExecuteBondCashOutCommand } from "@hashgraph/mass-payout-sdk";

const command = new ExecuteBondCashOutCommand({
contractId: "0.0.123456",
holderAddresses: ["0xabc...", "0xdef..."],
amounts: ["1000", "2000"], // Maturity amounts
startIndex: 0,
endIndex: 100,
});

await commandBus.execute(command);

Query Contract State​

import { GetPaymentTokenQuery, IsPausedQuery } from "@hashgraph/mass-payout-sdk";

// Get payment token
const paymentToken = await queryBus.execute(new GetPaymentTokenQuery({ contractId: "0.0.123456" }));

// Check if paused
const isPaused = await queryBus.execute(new IsPausedQuery({ contractId: "0.0.123456" }));

Pause/Unpause Contract​

import { PauseCommand, UnpauseCommand } from "@hashgraph/mass-payout-sdk";

// Emergency pause
await commandBus.execute(new PauseCommand({ contractId: "0.0.123456" }));

// Resume operations
await commandBus.execute(new UnpauseCommand({ contractId: "0.0.123456" }));

Pagination for Large Distributions​

When distributing to many holders, use startIndex and endIndex to paginate:

// Distribute to first 100 holders
await commandBus.execute(
new ExecuteDistributionCommand({
contractId: "0.0.123456",
holderAddresses: allHolders,
amounts: allAmounts,
startIndex: 0,
endIndex: 100,
}),
);

// Distribute to next 100 holders
await commandBus.execute(
new ExecuteDistributionCommand({
contractId: "0.0.123456",
holderAddresses: allHolders,
amounts: allAmounts,
startIndex: 100,
endIndex: 200,
}),
);

For small lists, use the ByAddresses variants which don't require pagination.

Error Handling​

import { CommandError } from "@hashgraph/mass-payout-sdk";

try {
await commandBus.execute(command);
} catch (error) {
if (error instanceof CommandError) {
console.error("Command failed:", error.message);
console.error("Details:", error.details);
}
throw error;
}

Architecture​

The SDK uses a clean architecture pattern:

  • Commands/Queries: High-level operations for contract interaction
  • Adapters: Pluggable implementations for transaction signing (DFNS, future providers)
  • Services: Network management, contract handling, events

This design allows swapping custodial providers without changing your application code.

Best Practices​

  1. Never hardcode private keys - Always use custodial wallets in production
  2. Use pagination - For distributions with >100 holders, use startIndex/endIndex
  3. Test on testnet first - Validate all operations before mainnet deployment
  4. Handle errors properly - Implement retry logic for transient failures
  5. Monitor gas costs - Each transaction costs HBAR (~$0.0001 per transaction)

Additional Resources​