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
14 changes: 7 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ POLL_INTERVAL_MS=6000
# ─── SAC Contract IDs ────────────────────────────────────────
# Comma-separated list of Soroban SAC (Stellar Asset Contract) IDs to watch.
# When unset, defaults to the native XLM SAC for the configured STELLAR_NETWORK:
# testnet → CDMLFMKMMD7MWZP3FKUBZPVHTUEDLSX4BYGYKH4GCESXYHS3IHQ4EIG4
# mainnet → CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
# testnet → CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
# mainnet → CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA
#
# How to derive a SAC address for any Stellar asset:
# import { Asset, Networks } from '@stellar/stellar-sdk';
Expand All @@ -57,15 +57,15 @@ POLL_INTERVAL_MS=6000
# .contractId(Networks.PUBLIC);
#
# Known mainnet SAC addresses:
# XLM (native): CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
# USDC (Centre): CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA
# XLM (native): CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA
# USDC (Centre): CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75
#
# Example (watch XLM + USDC on mainnet):
# SAC_CONTRACT_IDS=CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC,CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA
# SAC_CONTRACT_IDS=CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA,CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75
#
# Per-network watch lists (for dual-network deployments when NETWORKS=testnet,mainnet):
# SAC_CONTRACT_IDS_TESTNET=CDMLFMKMMD7MWZP3FKUBZPVHTUEDLSX4BYGYKH4GCESXYHS3IHQ4EIG4
# SAC_CONTRACT_IDS_MAINNET=CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
# SAC_CONTRACT_IDS_TESTNET=CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
# SAC_CONTRACT_IDS_MAINNET=CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA
#
# Soroban RPC's getEvents accepts multiple contract IDs in a single request —
# there is no N+1 query penalty for watching multiple contracts.
Expand Down
6 changes: 6 additions & 0 deletions src/__tests__/multiNetworkIndexer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
runningNetworks,
_resetIndexerLoops,
} from "../indexer";
import { Asset, Networks } from "@stellar/stellar-sdk";
import { getRpc, validateNetworkConfig, _resetRpcClients } from "../rpc";
import { currentNetwork, enabledNetworks, parseNetwork } from "../network";

Expand Down Expand Up @@ -82,6 +83,11 @@ describe("enabledNetworks", () => {
});

describe("per-network watch lists", () => {
it("matches the Stellar SDK's native SAC derivation", () => {
expect(DEFAULT_XLM_SAC_MAINNET).toBe(Asset.native().contractId(Networks.PUBLIC));
expect(DEFAULT_XLM_SAC_TESTNET).toBe(Asset.native().contractId(Networks.TESTNET));
});

it("defaults each network to its own native XLM SAC", () => {
// The bug this prevents: reading STELLAR_NETWORK inside the resolver, so
// both loops watch the same chain's SAC and one indexes nothing.
Expand Down
13 changes: 8 additions & 5 deletions src/__tests__/sacDetect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import { xdr } from "@stellar/stellar-sdk";
import { DEFAULT_XLM_SAC_MAINNET, DEFAULT_XLM_SAC_TESTNET } from "../indexer";
import {
executableIsSac,
instanceValIsSac,
Expand All @@ -17,9 +18,6 @@ import {
type InstanceFetcher,
} from "../indexer/sac-detect";

// The native XLM SACs are hard-coded as known SACs in the module.
const TESTNET_XLM_SAC = "CDMLFMKMMD7MWZP3FKUBZPVHTUEDLSX4BYGYKH4GCESXYHS3IHQ4EIG4";

function sacInstanceVal(): xdr.ScVal {
return xdr.ScVal.scvContractInstance(
new xdr.ScContractInstance({
Expand Down Expand Up @@ -67,9 +65,14 @@ describe("instanceValIsSac", () => {
});

describe("detectSac", () => {
it("returns true for a known native XLM SAC without fetching", async () => {
it("returns true for known native XLM SACs without fetching", async () => {
const fetcher = jest.fn<Promise<xdr.ScVal | null>, [string]>();
await expect(detectSac(TESTNET_XLM_SAC, fetcher)).resolves.toBe(true);
await expect(
Promise.all([
detectSac(DEFAULT_XLM_SAC_MAINNET, fetcher),
detectSac(DEFAULT_XLM_SAC_TESTNET, fetcher),
]),
).resolves.toEqual([true, true]);
expect(fetcher).not.toHaveBeenCalled();
});

Expand Down
4 changes: 2 additions & 2 deletions src/indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ export function resolveNftContractIds(network?: Network): string[] {
// These are derived from Asset.native().contractId(Networks.PUBLIC / Networks.TESTNET)
// and serve as the backwards-compatible default when SAC_CONTRACT_IDS is unset.
export const DEFAULT_XLM_SAC_MAINNET =
"CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC";
"CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA";
export const DEFAULT_XLM_SAC_TESTNET =
"CDMLFMKMMD7MWZP3FKUBZPVHTUEDLSX4BYGYKH4GCESXYHS3IHQ4EIG4";
"CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC";

/**
* Resolve the list of SAC contract IDs to watch.
Expand Down
4 changes: 2 additions & 2 deletions src/indexer/sac-detect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import { resolveNetwork, type Network } from "../network";
// The native XLM SAC on mainnet and testnet. These are fixed by the network and
// never change, so we short-circuit detection (and any RPC call) for them.
const KNOWN_SAC_IDS = new Set<string>([
"CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC", // mainnet native XLM
"CDMLFMKMMD7MWZP3FKUBZPVHTUEDLSX4BYGYKH4GCESXYHS3IHQ4EIG4", // testnet native XLM
"CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA", // mainnet native XLM
"CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC", // testnet native XLM
]);

// ─── Pure helpers ─────────────────────────────────────────────────────────────
Expand Down
Loading