Skip to content
Closed
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
8 changes: 8 additions & 0 deletions PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,11 @@ is closed — see [CONTRIBUTING.md](CONTRIBUTING.md).
- **By:** ALLEN-AYODEJI
- **Closes:** N/A
- **Status:** Merged.

### Testnet read client — configurable contract ID and RPC endpoint

- **What:** Replaces the hard-coded `CONTRACT_ID` and `RPC_URL` in `client/src/index.ts` with `--contract` and `--rpc` CLI flags, with `DEPRADAR_CONTRACT_ID` and `DEPRADAR_RPC_URL` environment variables as fallbacks, defaulting to the current testnet deployment values. Updates `client/README.md` with usage examples and options table.
- **Verified:** `npm run typecheck` passes in `client/`. Tested live reads against Stellar testnet with default flags and explicit `--contract` and `--rpc` options.
- **By:** dezzy-music
- **Closes:** #183
- **Status:** PR open.
19 changes: 18 additions & 1 deletion client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,33 @@ submitted against it via `get_claim`, and prints the result. No transactions are
submitted, no funded account is required — reads are simulated calls
against the RPC endpoint.

Contract ID: `CCPRQANY467KKE4ROKCNW6TH3LY3EPVFRXIXJ5V4VCYHLJKWZPOZYQJQ`
Default Contract ID: `CCPRQANY467KKE4ROKCNW6TH3LY3EPVFRXIXJ5V4VCYHLJKWZPOZYQJQ`
Default RPC URL: `https://soroban-testnet.stellar.org`

## Usage

```bash
npm install
npm start # defaults to bounty-id 1
npm start -- --bounty-id 2

# Point to custom contract or RPC endpoint via CLI flags:
npm start -- --bounty-id 1 --contract <CONTRACT_ID> --rpc <RPC_URL>

# Or configure via environment variables:
export DEPRADAR_CONTRACT_ID="<CONTRACT_ID>"
export DEPRADAR_RPC_URL="<RPC_URL>"
npm start -- --bounty-id 1
```

### Options

| Flag | Env Var | Description | Default |
|---|---|---|---|
| `--bounty-id <id>` | — | Bounty ID to inspect (non-negative integer) | `1` |
| `--contract <id>` | `DEPRADAR_CONTRACT_ID` | Soroban contract ID | `CCPRQANY...` (testnet deployment) |
| `--rpc <url>` | `DEPRADAR_RPC_URL` | Stellar RPC endpoint URL | `https://soroban-testnet.stellar.org` |

Bounty `1` is real on-chain data: the `create_bounty` -> `submit_claim`
(x2) -> `reject_claim` -> `release` cycle recorded in
[PROGRESS.md](../PROGRESS.md), so it shows one rejected and one accepted
Expand Down
42 changes: 29 additions & 13 deletions client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,29 @@
*
* Usage:
* npm start -- --bounty-id 1
* npm start -- --bounty-id 1 --contract <CONTRACT_ID> --rpc <RPC_URL>
*
* Flags and Environment Variables:
* --bounty-id <number> Bounty ID to inspect (default: 1)
* --contract <string> Contract ID (fallback: DEPRADAR_CONTRACT_ID env var, default: testnet deployment)
* --rpc <url> Stellar RPC endpoint (fallback: DEPRADAR_RPC_URL env var, default: testnet RPC)
*
* --bounty-id defaults to 1, the bounty used in the on-chain
* create_bounty -> submit_claim -> reject_claim -> release cycle described
* in PROGRESS.md, so running with no flags exercises real data.
*/
import { rpc } from "@stellar/stellar-sdk";

const CONTRACT_ID = "CCPRQANY467KKE4ROKCNW6TH3LY3EPVFRXIXJ5V4VCYHLJKWZPOZYQJQ";
const RPC_URL = "https://soroban-testnet.stellar.org";
const DEFAULT_CONTRACT_ID = "CCPRQANY467KKE4ROKCNW6TH3LY3EPVFRXIXJ5V4VCYHLJKWZPOZYQJQ";
const DEFAULT_RPC_URL = "https://soroban-testnet.stellar.org";

interface ClientConfig {
bountyId: number;
contractId: string;
rpcUrl: string;
}

function parseArgs(argv: string[]): { bountyId: number } {
function parseArgs(argv: string[]): ClientConfig {
const flags = new Map<string, string>();
for (let i = 0; i < argv.length; i += 1) {
const arg = argv[i];
Expand All @@ -25,26 +37,30 @@ function parseArgs(argv: string[]): { bountyId: number } {
}
}

const bountyId = Number(flags.get("bounty-id") ?? "1");
const bountyIdRaw = flags.get("bounty-id") ?? "1";
const bountyId = Number(bountyIdRaw);
if (!Number.isInteger(bountyId) || bountyId < 0) {
throw new Error(`--bounty-id must be a non-negative integer, got: ${flags.get("bounty-id")}`);
throw new Error(`--bounty-id must be a non-negative integer, got: ${bountyIdRaw}`);
}

return { bountyId };
const contractId = flags.get("contract") ?? process.env.DEPRADAR_CONTRACT_ID ?? DEFAULT_CONTRACT_ID;
const rpcUrl = flags.get("rpc") ?? process.env.DEPRADAR_RPC_URL ?? DEFAULT_RPC_URL;

return { bountyId, contractId, rpcUrl };
}

async function main() {
const { bountyId } = parseArgs(process.argv.slice(2));
const server = new rpc.Server(RPC_URL);
const { bountyId, contractId, rpcUrl } = parseArgs(process.argv.slice(2));
const server = new rpc.Server(rpcUrl);

const health = await server.getHealth();
console.log(`Connected to ${RPC_URL} (status: ${health.status}, latest ledger: ${health.latestLedger})`);
console.log(`Contract: ${CONTRACT_ID}`);
console.log(`Connected to ${rpcUrl} (status: ${health.status}, latest ledger: ${health.latestLedger})`);
console.log(`Contract: ${contractId}`);

const { result: count } = await server.queryContract(CONTRACT_ID, "bounty_count", {});
const { result: count } = await server.queryContract(contractId, "bounty_count", {});
console.log(`Bounties created: ${count}\n`);

const { result: bounty } = await server.queryContract(CONTRACT_ID, "get_bounty", { bounty_id: bountyId });
const { result: bounty } = await server.queryContract(contractId, "get_bounty", { bounty_id: bountyId });
console.log(`get_bounty(${bountyId}) =>`);
if (bounty === null) {
console.log(" (no bounty with this ID)");
Expand All @@ -54,7 +70,7 @@ async function main() {

const claimCount = Number((bounty as { claim_count: number }).claim_count);
for (let claimId = 0; claimId < claimCount; claimId += 1) {
const { result: claim } = await server.queryContract(CONTRACT_ID, "get_claim", {
const { result: claim } = await server.queryContract(contractId, "get_claim", {
bounty_id: bountyId,
claim_id: claimId,
});
Expand Down