@orbinum/sdk 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1019,397 +1019,6 @@ var EvmExplorer = class _EvmExplorer {
1019
1019
  }
1020
1020
  };
1021
1021
 
1022
- // src/indexer/IndexerClient.ts
1023
- var LOCAL_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
1024
- function normalizeBaseUrl(baseUrl) {
1025
- let url;
1026
- try {
1027
- url = new URL(baseUrl);
1028
- } catch {
1029
- throw new Error(`IndexerClient: invalid baseUrl ${JSON.stringify(baseUrl)}`);
1030
- }
1031
- const isLocal = LOCAL_HOSTS.has(url.hostname);
1032
- if (url.protocol !== "https:" && !(url.protocol === "http:" && isLocal)) {
1033
- throw new Error(
1034
- `IndexerClient: baseUrl must use https:// (got ${url.protocol}//${url.hostname}). Plain http is only allowed for localhost.`
1035
- );
1036
- }
1037
- return baseUrl.replace(/\/$/, "");
1038
- }
1039
- var IndexerClient = class _IndexerClient {
1040
- baseUrl;
1041
- timeoutMs;
1042
- constructor(config) {
1043
- this.baseUrl = normalizeBaseUrl(config.baseUrl);
1044
- this.timeoutMs = config.timeoutMs ?? 1e4;
1045
- }
1046
- // ─── Internal helpers ──────────────────────────────────────────────────────
1047
- async _fetchResponse(path) {
1048
- const controller = new AbortController();
1049
- const timer = setTimeout(() => controller.abort(), this.timeoutMs);
1050
- try {
1051
- return await fetch(`${this.baseUrl}${path}`, { signal: controller.signal });
1052
- } finally {
1053
- clearTimeout(timer);
1054
- }
1055
- }
1056
- async get(path) {
1057
- const res = await this._fetchResponse(path);
1058
- if (!res.ok) {
1059
- throw new Error(`IndexerClient: HTTP ${res.status} for ${path}`);
1060
- }
1061
- return res.json();
1062
- }
1063
- async getOrNull(path) {
1064
- const res = await this._fetchResponse(path);
1065
- if (res.status === 404) return null;
1066
- if (!res.ok) {
1067
- throw new Error(`IndexerClient: HTTP ${res.status} for ${path}`);
1068
- }
1069
- return res.json();
1070
- }
1071
- buildQuery(params) {
1072
- const entries = Object.entries(params).filter(([, v]) => v !== void 0);
1073
- if (entries.length === 0) return "";
1074
- const qs = entries.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
1075
- return `?${qs}`;
1076
- }
1077
- // ─── Commitments ───────────────────────────────────────────────────────────
1078
- /** Returns the total count of shielded commitments. */
1079
- async getCommitmentsCount() {
1080
- const res = await this.get("/shielded/commitments/count");
1081
- return res.total;
1082
- }
1083
- /** Returns a paginated list of shielded commitments. */
1084
- async getCommitments(params) {
1085
- const qs = this.buildQuery({
1086
- page: params?.page,
1087
- limit: params?.limit,
1088
- since_leaf_index: params?.sinceLeafIndex
1089
- });
1090
- return this.get(`/shielded/commitments${qs}`);
1091
- }
1092
- /** Returns a single commitment by its hex string, or null if not found. */
1093
- async getCommitmentByHex(hex) {
1094
- return this.getOrNull(
1095
- `/shielded/commitments/${encodeURIComponent(hex)}`
1096
- );
1097
- }
1098
- /**
1099
- * Returns a paginated list of stealth scan hints ordered ascending by leafIndex.
1100
- * Each hint contains only the fields required for ECDH triage and decryption:
1101
- * leafIndex, commitmentHex, assetId, ephPkHex, encryptedMemo, circuitVersion.
1102
- *
1103
- * Use `sinceLeafIndex` for incremental scans (cursor = last seen leafIndex + 1).
1104
- */
1105
- async getScanHints(params) {
1106
- const qs = this.buildQuery({
1107
- page: params?.page,
1108
- limit: params?.limit,
1109
- since_leaf_index: params?.sinceLeafIndex
1110
- });
1111
- return this.get(`/shielded/scan-hints${qs}`);
1112
- }
1113
- // ─── Nullifiers ────────────────────────────────────────────────────────────
1114
- /** Returns a paginated list of spent nullifiers. */
1115
- async getNullifiers(params) {
1116
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1117
- return this.get(`/shielded/nullifiers${qs}`);
1118
- }
1119
- /** Returns the spent/unspent status of a nullifier. */
1120
- async getNullifierStatus(hex) {
1121
- return this.get(
1122
- `/shielded/nullifier/${encodeURIComponent(hex)}/status`
1123
- );
1124
- }
1125
- /**
1126
- * Downloads the full spent nullifier set and returns it as a Set of lowercase hex strings.
1127
- *
1128
- * The server sees an identical GET request regardless of which notes the wallet holds —
1129
- * the intersection is computed locally (PIR-A privacy model).
1130
- *
1131
- * Kept as the FALLBACK for readers that don't serve sealed chunks yet (and for
1132
- * small sets). New integrations should prefer the incremental chunk flow:
1133
- * `getNullifierManifest` → `getNullifierChunk` for missing chunks →
1134
- * `getNullifierTail`, persisting the set locally between rescans.
1135
- */
1136
- async getAllSpentNullifiers() {
1137
- const res = await this.get("/shielded/nullifiers/all");
1138
- return new Set(res.data.map((h) => h.toLowerCase()));
1139
- }
1140
- /**
1141
- * Universal index of the sealed nullifier chunks — identical request and
1142
- * response for every caller (no client-supplied position: PIR-A preserved).
1143
- *
1144
- * Returns `null` when the reader does not serve chunks yet (404) — the
1145
- * caller should fall back to `getAllSpentNullifiers`.
1146
- */
1147
- async getNullifierManifest() {
1148
- return this.getOrNull("/shielded/nullifiers/manifest");
1149
- }
1150
- /**
1151
- * One sealed, immutable chunk of the spent-nullifier set (ascending hex,
1152
- * lowercased). The digest comes from the manifest and lives in the URL, so
1153
- * a corrected chunk is a different URL — safe to cache forever client-side.
1154
- */
1155
- async getNullifierChunk(idx, digest) {
1156
- const res = await this.get(
1157
- `/shielded/nullifiers/chunks/${idx}/${encodeURIComponent(digest)}`
1158
- );
1159
- return res.data.map((h) => h.toLowerCase());
1160
- }
1161
- /**
1162
- * The mutable remainder of the nullifier set after the last sealed chunk.
1163
- * Identical request for every caller (no input). `afterChunks` lets the
1164
- * client detect a chunk sealed between its manifest fetch and this one.
1165
- */
1166
- async getNullifierTail() {
1167
- const res = await this.get("/shielded/nullifiers/tail");
1168
- return { afterChunks: res.afterChunks, data: res.data.map((h) => h.toLowerCase()) };
1169
- }
1170
- // ─── Private transfers ─────────────────────────────────────────────────────
1171
- /** Server-enforced max items per by-nullifiers / by-commitments request. */
1172
- static TRANSFER_LOOKUP_CHUNK = 50;
1173
- /**
1174
- * Chunked fetch for the transfer timestamp lookups. The reader silently
1175
- * truncates each request to 50 items, so larger inputs MUST be split or
1176
- * results are silently lost. Responses are merged per extrinsic
1177
- * (`blockNumber:extrinsicIndex`), concatenating the matched arrays, and
1178
- * sorted by block descending.
1179
- *
1180
- * Privacy note: these lookups send the wallet's own note identifiers to
1181
- * the indexer — a bounded, documented linkage tradeoff for timestamp
1182
- * recovery. They are NEVER used for spent-STATUS checks (PIR-A: status
1183
- * comes from the anonymous full-set `/shielded/nullifiers/all` download).
1184
- */
1185
- async fetchTransfersChunked(path, param, items, matchedField) {
1186
- if (items.length === 0) return [];
1187
- const normalized = items.map((i) => i.toLowerCase());
1188
- const chunks = [];
1189
- for (let i = 0; i < normalized.length; i += _IndexerClient.TRANSFER_LOOKUP_CHUNK) {
1190
- chunks.push(normalized.slice(i, i + _IndexerClient.TRANSFER_LOOKUP_CHUNK));
1191
- }
1192
- const responses = await Promise.all(
1193
- chunks.map((chunk) => {
1194
- const qs = this.buildQuery({ [param]: chunk.join(",") });
1195
- return this.get(
1196
- `${path}${qs}`
1197
- );
1198
- })
1199
- );
1200
- const byExtrinsic = /* @__PURE__ */ new Map();
1201
- for (const res of responses) {
1202
- for (const transfer of res.data) {
1203
- const key = `${transfer.blockNumber}:${transfer.extrinsicIndex ?? "null"}`;
1204
- const existing = byExtrinsic.get(key);
1205
- if (!existing) {
1206
- byExtrinsic.set(key, transfer);
1207
- continue;
1208
- }
1209
- const merged = /* @__PURE__ */ new Set([
1210
- ...existing[matchedField] ?? [],
1211
- ...transfer[matchedField] ?? []
1212
- ]);
1213
- existing[matchedField] = [...merged];
1214
- }
1215
- }
1216
- return [...byExtrinsic.values()].sort((a, b) => b.blockNumber - a.blockNumber);
1217
- }
1218
- /**
1219
- * Returns temporal metadata for private transfers that spent any of the given nullifiers.
1220
- * Only blockNumber, extrinsicIndex, timestampMs, and hash are returned — no cross-link
1221
- * between inputs and outputs to prevent graph reconstruction.
1222
- * Inputs of any size are transparently chunked into requests of 50 (the server cap)
1223
- * and merged per extrinsic.
1224
- */
1225
- async getTransfersByNullifiers(nullifiers) {
1226
- return this.fetchTransfersChunked(
1227
- "/shielded/transfers/by-nullifiers",
1228
- "nullifiers",
1229
- nullifiers,
1230
- "matchedNullifiers"
1231
- );
1232
- }
1233
- /**
1234
- * Returns temporal metadata for private transfers that produced any of the given commitments.
1235
- * Only blockNumber, extrinsicIndex, timestampMs, and hash are returned — no cross-link
1236
- * between outputs and inputs to prevent graph reconstruction.
1237
- * Inputs of any size are transparently chunked into requests of 50 (the server cap)
1238
- * and merged per extrinsic.
1239
- */
1240
- async getTransfersByCommitments(commitments) {
1241
- return this.fetchTransfersChunked(
1242
- "/shielded/transfers/by-commitments",
1243
- "commitments",
1244
- commitments,
1245
- "matchedCommitments"
1246
- );
1247
- }
1248
- // ─── Unshields ─────────────────────────────────────────────────────────────
1249
- /** Returns a paginated list of unshield events. */
1250
- async getUnshields(params) {
1251
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1252
- return this.get(`/shielded/unshields${qs}`);
1253
- }
1254
- // ─── Merkle roots ──────────────────────────────────────────────────────────
1255
- /** Returns a paginated list of Merkle root checkpoints. */
1256
- async getMerkleRoots(params) {
1257
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1258
- return this.get(`/shielded/merkle-roots${qs}`);
1259
- }
1260
- /** Returns the latest Merkle root, or null if none exists. */
1261
- async getLatestMerkleRoot() {
1262
- return this.getOrNull("/shielded/merkle-roots/latest");
1263
- }
1264
- // ─── Address activity ──────────────────────────────────────────────────────
1265
- /** Returns a paginated list of extrinsics signed by the given address. */
1266
- async getAddressExtrinsics(address, params) {
1267
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1268
- return this.get(
1269
- `/address/${encodeURIComponent(address.toLowerCase())}/extrinsics${qs}`
1270
- );
1271
- }
1272
- /** Returns a paginated list of EVM transactions filtered by address and/or block number. */
1273
- async getEvmTransactions(params) {
1274
- const qs = this.buildQuery({
1275
- page: params?.page,
1276
- limit: params?.limit,
1277
- address: params?.address?.toLowerCase(),
1278
- blockNumber: params?.blockNumber
1279
- });
1280
- return this.get(`/evm/transactions${qs}`);
1281
- }
1282
- /** Returns a single EVM transaction by hash, or null if not found. */
1283
- async getEvmTransactionByHash(hash) {
1284
- return this.getOrNull(
1285
- `/evm/transactions/${encodeURIComponent(hash.toLowerCase())}`
1286
- );
1287
- }
1288
- // ─── Blocks ────────────────────────────────────────────────────────────────
1289
- /** Returns a paginated list of indexed blocks. */
1290
- async getBlocks(params) {
1291
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1292
- return this.get(`/blocks${qs}`);
1293
- }
1294
- /** Returns a single block by number or hash, or null if not found. */
1295
- async getBlock(numberOrHash) {
1296
- return this.getOrNull(`/blocks/${encodeURIComponent(String(numberOrHash))}`);
1297
- }
1298
- // ─── Address-scoped shielded activity ─────────────────────────────────────
1299
- /**
1300
- * Returns a paginated list of unshield events where the given address is the recipient.
1301
- * Accepts a 0x-prefixed EVM address or an SS58 Substrate address.
1302
- */
1303
- async getAddressUnshields(address, params) {
1304
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1305
- return this.get(
1306
- `/address/${encodeURIComponent(address)}/unshields${qs}`
1307
- );
1308
- }
1309
- /**
1310
- * Returns the shielded-pool BOUNDARY activity for an address: shields it
1311
- * deposited and unshields it received, tagged `kind: 'shield' | 'unshield'`.
1312
- * Only boundary fields are returned (block, asset, amount for unshields,
1313
- * timestamp, tx hash) — note internals are never served per-address, and
1314
- * private transfers carry no address at all (PIR-A).
1315
- */
1316
- async getAddressShieldedActivity(address, params) {
1317
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1318
- return this.get(
1319
- `/shielded/address/${encodeURIComponent(address)}${qs}`
1320
- );
1321
- }
1322
- // ─── Relayers ──────────────────────────────────────────────────────────────
1323
- /** Returns a paginated list of relayers. Filter by active status with `active`. */
1324
- async getRelayers(params) {
1325
- const qs = this.buildQuery({
1326
- page: params?.page,
1327
- limit: params?.limit,
1328
- active: params?.active === void 0 ? void 0 : params.active ? "true" : "false"
1329
- });
1330
- return this.get(`/relayers${qs}`);
1331
- }
1332
- /** Returns a single relayer by EVM address, or null if not found. */
1333
- async getRelayer(evmAddress) {
1334
- return this.getOrNull(`/relayers/${encodeURIComponent(evmAddress.toLowerCase())}`);
1335
- }
1336
- /** Returns a paginated list of relay fee events. */
1337
- async getRelayFees(params) {
1338
- const qs = this.buildQuery({
1339
- page: params?.page,
1340
- limit: params?.limit,
1341
- relayer: params?.relayer,
1342
- type: params?.type
1343
- });
1344
- return this.get(`/relayers/fees${qs}`);
1345
- }
1346
- /** Returns aggregated relay fee balances per asset for a given relayer account. */
1347
- async getRelayFeesSummary(relayer) {
1348
- return this.get(
1349
- `/relayers/fees/summary/${encodeURIComponent(relayer)}`
1350
- );
1351
- }
1352
- // ─── Registered assets ─────────────────────────────────────────────────────
1353
- /** Returns a paginated list of assets registered via register_asset. */
1354
- async getRegisteredAssets(params) {
1355
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1356
- return this.get(`/shielded/assets${qs}`);
1357
- }
1358
- /** Returns a single registered asset by its ID, or null if not found. */
1359
- async getRegisteredAsset(assetId) {
1360
- return this.getOrNull(`/shielded/assets/${encodeURIComponent(assetId)}`);
1361
- }
1362
- // ─── Validators ────────────────────────────────────────────────────────────
1363
- /** Returns a paginated list of validators. Filter by lifecycle status with `status`. */
1364
- async getValidators(params) {
1365
- const qs = this.buildQuery({
1366
- page: params?.page,
1367
- limit: params?.limit,
1368
- status: params?.status
1369
- });
1370
- return this.get(`/validators${qs}`);
1371
- }
1372
- /** Returns a single validator by account address, or null if not found. */
1373
- async getValidator(account) {
1374
- return this.getOrNull(`/validators/${encodeURIComponent(account)}`);
1375
- }
1376
- // ─── Sessions ──────────────────────────────────────────────────────────────
1377
- /** Returns a paginated list of session rotations, ordered by most recent first. */
1378
- async getSessions(params) {
1379
- const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1380
- return this.get(`/sessions${qs}`);
1381
- }
1382
- // ─── Stats & Health ────────────────────────────────────────────────────────
1383
- /** Returns aggregated indexer statistics. */
1384
- async getStats() {
1385
- return this.get("/stats");
1386
- }
1387
- /**
1388
- * Returns transaction activity bucketed per hour over the last `hours` hours
1389
- * of chain time (default 24, max 168). For sparklines / activity charts.
1390
- */
1391
- async getActivity(hours = 24) {
1392
- return this.get(`/stats/activity?hours=${hours}`);
1393
- }
1394
- /** Returns true if the indexer health endpoint responds OK. */
1395
- async isHealthy() {
1396
- try {
1397
- const controller = new AbortController();
1398
- const timer = setTimeout(() => controller.abort(), this.timeoutMs);
1399
- try {
1400
- const res = await fetch(`${this.baseUrl}/health`, {
1401
- signal: controller.signal
1402
- });
1403
- return res.ok;
1404
- } finally {
1405
- clearTimeout(timer);
1406
- }
1407
- } catch {
1408
- return false;
1409
- }
1410
- }
1411
- };
1412
-
1413
1022
  // src/shielded-pool/pallet/ShieldedPoolModule.ts
1414
1023
  import "polkadot-api";
1415
1024
 
@@ -3511,12 +3120,6 @@ var OrbinumClient = class _OrbinumClient {
3511
3120
  * `null` when `evmRpc` is not configured.
3512
3121
  */
3513
3122
  evmExplorer;
3514
- /**
3515
- * HTTP client for the Orbinum indexer REST API.
3516
- * Provides paginated access to indexed blocks, extrinsics, shielded events, and nullifiers.
3517
- * `null` when `indexerUrl` is not configured.
3518
- */
3519
- indexer;
3520
3123
  /** Shielded-pool extrinsics and Merkle tree queries (`shield`, `unshield`, `privateTransfer`, …). */
3521
3124
  shieldedPool;
3522
3125
  /** Account-mapping extrinsics: aliases, chain links, metadata, marketplace, and identity. */
@@ -3540,11 +3143,10 @@ var OrbinumClient = class _OrbinumClient {
3540
3143
  */
3541
3144
  precompiles;
3542
3145
  /** @internal Use `OrbinumClient.connect()` to obtain an instance. */
3543
- constructor(substrate, evm, indexer, circuitsBaseUrl) {
3146
+ constructor(substrate, evm, circuitsBaseUrl) {
3544
3147
  this.substrate = substrate;
3545
3148
  this.evm = evm;
3546
3149
  this.evmExplorer = evm ? new EvmExplorer(evm) : null;
3547
- this.indexer = indexer;
3548
3150
  this.shieldedPool = new ShieldedPoolModule(substrate);
3549
3151
  this.accountMapping = new AccountMappingModule(substrate);
3550
3152
  this.privacy = new PrivacyModule(substrate);
@@ -3570,8 +3172,7 @@ var OrbinumClient = class _OrbinumClient {
3570
3172
  config.connectTimeoutMs ?? 15e3
3571
3173
  );
3572
3174
  const evm = config.evmRpc ? new EvmClient(config.evmRpc) : null;
3573
- const indexer = config.indexerUrl ? new IndexerClient({ baseUrl: config.indexerUrl }) : null;
3574
- return new _OrbinumClient(substrate, evm, indexer, config.circuitsBaseUrl);
3175
+ return new _OrbinumClient(substrate, evm, config.circuitsBaseUrl);
3575
3176
  }
3576
3177
  /** Closes the underlying Substrate WebSocket connection and releases all resources. */
3577
3178
  destroy() {
@@ -3692,7 +3293,6 @@ var OrbinumClientProvider = class {
3692
3293
  substrateWs: this.config.substrateWs
3693
3294
  };
3694
3295
  if (this.config.evmRpc) connectConfig.evmRpc = this.config.evmRpc;
3695
- if (this.config.indexerUrl) connectConfig.indexerUrl = this.config.indexerUrl;
3696
3296
  if (this.config.circuitsBaseUrl)
3697
3297
  connectConfig.circuitsBaseUrl = this.config.circuitsBaseUrl;
3698
3298
  const clientPromise = OrbinumClient.connect(connectConfig);
@@ -5536,7 +5136,6 @@ export {
5536
5136
  EncryptedMemo,
5537
5137
  EvmClient,
5538
5138
  EvmExplorer,
5539
- IndexerClient,
5540
5139
  KNOWN_PRECOMPILES,
5541
5140
  Keccak256,
5542
5141
  NoteBuilder,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orbinum/sdk",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Official TypeScript SDK for Orbinum.",
5
5
  "author": "Orbinum",
6
6
  "license": "MIT",