Skip to content
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,6 @@ Running these before pushing means CI passes on the first try. See [`CONTRIBUTIN

🔱

[Discussions](https://github.com/trident-build/trident/discussions) · [Specification](./docs/SPECIFICATION.md) · [API Stability Policy](./docs/API_STABILITY.md) · [SDK Versioning Policy](./docs/SDK_VERSIONING_POLICY.md) · [10-Min Quickstart](./docs/QUICKSTART.md) · [Cutover Runbook](./docs/runbooks/testnet-cutover.md)
[Discussions](https://github.com/trident-build/trident/discussions) · [Specification](./docs/SPECIFICATION.md) · [API Stability Policy](./docs/API_STABILITY.md) · [SDK Versioning Policy](./docs/SDK_VERSIONING_POLICY.md) · [10-Min Quickstart](./docs/QUICKSTART.md) · [Cutover Runbook](./docs/runbooks/testnet-cutover.md) · [Example App](./examples/testnet-monitor)

</div>
50 changes: 50 additions & 0 deletions examples/testnet-monitor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# 🔱 Trident Testnet Event Monitor Example

This is a working, production-grade example application that connects to **Trident Indexer** on **Stellar Testnet** using the official `@trident/sdk` TypeScript client.

---

## Features Demonstrated

1. **Client Setup**: Authenticating and configuring the typed TypeScript client for Stellar Testnet.
2. **Historical Queries**: Querying indexed events by contract ID with limit and keyset pagination.
3. **Live Streaming**: Real-time event subscription via WebSocket (`client.subscribe`).

---

## Prerequisites

- **Node.js** (v20 LTS or later)
- **npm** (v9 or later)

---

## Quick Start

### 1. Install Dependencies

```bash
npm install
```

### 2. Configure Environment

Create a `.env` file (optional; sensible defaults point to public testnet):

```ini
TRIDENT_API_URL=https://api.testnet.trident.telocel.com
TRIDENT_API_KEY=your-api-key
CONTRACT_ID=CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
```

### 3. Run the Monitor

```bash
npm start
```

### 4. CI Dry-Run Validation

```bash
npm test
```
22 changes: 22 additions & 0 deletions examples/testnet-monitor/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "testnet-event-monitor",
"version": "1.0.0",
"description": "End-to-end example application demonstrating Soroban event indexing and live streaming on Stellar Testnet with Trident TypeScript SDK.",
"main": "dist/index.js",
"scripts": {
"start": "ts-node src/index.ts",
"build": "tsc",
"test": "ts-node src/index.ts --dry-run"
},
"dependencies": {
"@trident/sdk": "file:../../sdk/typescript",
"dotenv": "^16.4.5",
"ws": "^8.16.0"
},
"devDependencies": {
"@types/node": "^20.11.24",
"@types/ws": "^8.5.10",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}
97 changes: 97 additions & 0 deletions examples/testnet-monitor/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* Trident Testnet Event Monitor Example Application
*
* Demonstrates:
* 1. Initializing the official Trident TypeScript SDK for Stellar Testnet
* 2. Querying historical paginated contract events via REST
* 3. Subscribing to live real-time contract events via WebSocket
*/

import { TridentClient, iterEvents, SorobanEvent } from "@trident/sdk";
import WebSocket from "ws";
import * as dotenv from "dotenv";

dotenv.config();

// Configuration
const TRIDENT_API_URL = process.env.TRIDENT_API_URL || "https://api.testnet.trident.telocel.com";
const TRIDENT_API_KEY = process.env.TRIDENT_API_KEY || "trident_demo_key";
const CONTRACT_ID =
process.env.CONTRACT_ID || "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC";

const isDryRun = process.argv.includes("--dry-run");

async function main() {
console.log("=================================================");
console.log("🔱 Trident Testnet Event Monitor");
console.log("=================================================");
console.log(`🌐 Network: Testnet`);
console.log(`🔗 Endpoint: ${TRIDENT_API_URL}`);
console.log(`📜 Contract: ${CONTRACT_ID}`);
console.log("-------------------------------------------------");

// 1. Initialize Trident Client
const client = new TridentClient({
apiUrl: TRIDENT_API_URL,
apiKey: TRIDENT_API_KEY,
network: "testnet",
webSocketImpl: WebSocket,
});

if (isDryRun) {
console.log("✅ Dry-run validation mode: SDK initialized and configured successfully.");
process.exit(0);
}

try {
// 2. Query Recent Historical Events
console.log("\n📦 Fetching latest indexed events...");
const result = await client.queryEvents({
contractId: CONTRACT_ID,
limit: 5,
});

console.log(`Found ${result.events.length} recent events.\n`);
for (const ev of result.events) {
displayEvent(ev);
}

// 3. Live WebSocket Subscription
console.log("\n⚡ Subscribing to real-time events over WebSocket...");
const sub = client.subscribeToContract({
contractId: CONTRACT_ID,
onEvent: (event: SorobanEvent) => {
console.log("\n🔔 [LIVE EVENT RECEIVED]");
displayEvent(event);
},
onError: (err: Error) => {
console.error("❌ Subscription error:", err.message);
},
});

// Keep process alive for streaming
process.on("SIGINT", () => {
console.log("\nShutting down monitor...");
sub.unsubscribe();
process.exit(0);
});
} catch (err: any) {
console.error("⚠️ Error querying Trident API:", err.message);
// Don't crash dry-run or mock environments
if (!isDryRun) {
process.exit(1);
}
}
}

function displayEvent(ev: SorobanEvent) {
console.log(` [Ledger ${ev.ledgerSequence}] ${ev.eventType.toUpperCase()} | Tx: ${ev.transactionHash.slice(0, 10)}...`);
console.log(` Topics: [${ev.topics.join(", ")}]`);
console.log(` Data: ${JSON.stringify(ev.data)}`);
console.log(" ---------------------------------------------");
}

main().catch((err) => {
console.error("Fatal error:", err);
process.exit(1);
});
13 changes: 13 additions & 0 deletions examples/testnet-monitor/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["src/**/*"]
}
Loading