@orbinum/sdk 0.5.0 → 0.7.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
@@ -3,7 +3,7 @@ import {
3
3
  createClient,
4
4
  Binary
5
5
  } from "polkadot-api";
6
- import { getWsProvider } from "polkadot-api/ws-provider";
6
+ import { getWsProvider } from "polkadot-api/ws";
7
7
  import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders";
8
8
  import { decAnyMetadata, unifyMetadata } from "@polkadot-api/substrate-bindings";
9
9
  import { AccountId } from "@polkadot-api/substrate-bindings";
@@ -226,20 +226,20 @@ var SubstrateClient = class _SubstrateClient {
226
226
  * into a PAPI UnsafeTransaction that can be signed and submitted.
227
227
  */
228
228
  async txFromCallData(callData) {
229
- return this._papi.getUnsafeApi().txFromCallData(Binary.fromBytes(callData));
229
+ return this._papi.getUnsafeApi().txFromCallData(callData);
230
230
  }
231
231
  /**
232
232
  * Submits a pre-signed extrinsic (hex string) and waits for finalization.
233
233
  */
234
234
  async submit(signedHex) {
235
- return this._papi.submit(signedHex);
235
+ return this._papi.submit(Binary.fromHex(signedHex));
236
236
  }
237
237
  /**
238
238
  * Submits a pre-signed extrinsic and returns an Observable of tx lifecycle events.
239
239
  * Events: TxSigned → TxBroadcasted → TxBestBlocksState → TxFinalized
240
240
  */
241
241
  submitAndWatch(signedHex) {
242
- return this._papi.submitAndWatch(signedHex);
242
+ return this._papi.submitAndWatch(Binary.fromHex(signedHex));
243
243
  }
244
244
  /**
245
245
  * Submits a bare (unsigned) extrinsic hex and waits for finalization.
@@ -247,7 +247,7 @@ var SubstrateClient = class _SubstrateClient {
247
247
  * The bare tx hex is produced by `tx.getBareTx()` from polkadot-api.
248
248
  */
249
249
  async submitUnsignedAndWatch(bareTxHex) {
250
- return this._papi.submit(bareTxHex);
250
+ return this._papi.submit(Binary.fromHex(bareTxHex));
251
251
  }
252
252
  /**
253
253
  * Convenience: wrap raw call bytes and sign+submit in one step.
@@ -1190,6 +1190,46 @@ var IndexerClient = class {
1190
1190
  `/shielded/address/${encodeURIComponent(address.toLowerCase())}${qs}`
1191
1191
  );
1192
1192
  }
1193
+ // ─── Relayers ──────────────────────────────────────────────────────────────
1194
+ /** Returns a paginated list of relayers. Filter by active status with `active`. */
1195
+ async getRelayers(params) {
1196
+ const qs = this.buildQuery({
1197
+ page: params?.page,
1198
+ limit: params?.limit,
1199
+ active: params?.active === void 0 ? void 0 : params.active ? "true" : "false"
1200
+ });
1201
+ return this.get(`/relayers${qs}`);
1202
+ }
1203
+ /** Returns a single relayer by EVM address, or null if not found. */
1204
+ async getRelayer(evmAddress) {
1205
+ return this.getOrNull(`/relayers/${encodeURIComponent(evmAddress.toLowerCase())}`);
1206
+ }
1207
+ /** Returns a paginated list of relay fee events. */
1208
+ async getRelayFees(params) {
1209
+ const qs = this.buildQuery({
1210
+ page: params?.page,
1211
+ limit: params?.limit,
1212
+ relayer: params?.relayer,
1213
+ type: params?.type
1214
+ });
1215
+ return this.get(`/relayers/fees${qs}`);
1216
+ }
1217
+ /** Returns aggregated relay fee balances per asset for a given relayer account. */
1218
+ async getRelayFeesSummary(relayer) {
1219
+ return this.get(
1220
+ `/relayers/fees/summary/${encodeURIComponent(relayer)}`
1221
+ );
1222
+ }
1223
+ // ─── Registered assets ─────────────────────────────────────────────────────
1224
+ /** Returns a paginated list of assets registered via register_asset. */
1225
+ async getRegisteredAssets(params) {
1226
+ const qs = this.buildQuery({ page: params?.page, limit: params?.limit });
1227
+ return this.get(`/shielded/assets${qs}`);
1228
+ }
1229
+ /** Returns a single registered asset by its ID, or null if not found. */
1230
+ async getRegisteredAsset(assetId) {
1231
+ return this.getOrNull(`/shielded/assets/${encodeURIComponent(assetId)}`);
1232
+ }
1193
1233
  // ─── Stats & Health ────────────────────────────────────────────────────────
1194
1234
  /** Returns aggregated indexer statistics. */
1195
1235
  async getStats() {
@@ -1672,7 +1712,7 @@ var ShieldedPoolModule = class {
1672
1712
  asset_id: params.assetId,
1673
1713
  amount: params.amount,
1674
1714
  commitment: Binary2.fromHex(params.commitment),
1675
- encrypted_memo: Binary2.fromBytes(params.encryptedMemo)
1715
+ encrypted_memo: params.encryptedMemo
1676
1716
  });
1677
1717
  return toTxResult(
1678
1718
  await (txOptions !== void 0 ? tx.signAndSubmit(signer, txOptions) : tx.signAndSubmit(signer))
@@ -1692,12 +1732,12 @@ var ShieldedPoolModule = class {
1692
1732
  let changeEncryptedMemo;
1693
1733
  if (params.changeEncryptedMemo && params.changeEncryptedMemo.length > 0) {
1694
1734
  EncryptedMemo.validate(params.changeEncryptedMemo, "changeEncryptedMemo");
1695
- changeEncryptedMemo = Binary2.fromBytes(params.changeEncryptedMemo);
1735
+ changeEncryptedMemo = params.changeEncryptedMemo;
1696
1736
  } else {
1697
- changeEncryptedMemo = Binary2.fromBytes(new Uint8Array(0));
1737
+ changeEncryptedMemo = new Uint8Array(0);
1698
1738
  }
1699
1739
  const tx = callUnsafeTx(entry, {
1700
- proof: Binary2.fromBytes(params.proof),
1740
+ proof: params.proof,
1701
1741
  merkle_root: Binary2.fromHex(params.merkleRoot),
1702
1742
  nullifier: Binary2.fromHex(params.nullifier),
1703
1743
  asset_id: params.assetId,
@@ -1730,11 +1770,11 @@ var ShieldedPoolModule = class {
1730
1770
  out.encryptedMemo,
1731
1771
  `privateTransfer.outputs[${i}].encryptedMemo`
1732
1772
  );
1733
- return Binary2.fromBytes(out.encryptedMemo);
1773
+ return out.encryptedMemo;
1734
1774
  });
1735
1775
  const entry = resolveTx(this.substrate.unsafe, "ShieldedPool", "private_transfer");
1736
1776
  const tx = callUnsafeTx(entry, {
1737
- proof: Binary2.fromBytes(params.proof),
1777
+ proof: params.proof,
1738
1778
  merkle_root: Binary2.fromHex(params.merkleRoot),
1739
1779
  nullifiers,
1740
1780
  commitments,
@@ -1762,7 +1802,7 @@ var ShieldedPoolModule = class {
1762
1802
  assetId: item.assetId,
1763
1803
  amount: item.amount.toString(),
1764
1804
  commitment: Binary2.fromHex(item.commitment),
1765
- encryptedMemo: Binary2.fromBytes(item.encryptedMemo)
1805
+ encryptedMemo: item.encryptedMemo
1766
1806
  };
1767
1807
  });
1768
1808
  const entry = resolveTx(this.substrate.unsafe, "ShieldedPool", "shield_batch");
@@ -1774,7 +1814,7 @@ var ShieldedPoolModule = class {
1774
1814
  /**
1775
1815
  * Claims accrued relay fees into the shielded pool.
1776
1816
  * This is a SIGNED transaction — the relayer must sign it with their wallet.
1777
- * Before calling this, generate a ZK disclosure proof with generateFeeClaimProof().
1817
+ * Before calling this, generate a ZK value proof with generateFeeClaimProof() (not yet implemented).
1778
1818
  *
1779
1819
  * Extrinsic: shieldedPool.claim_shielded_fees(commitment, amount, asset_id, memo, proof, public_signals)
1780
1820
  */
@@ -1785,98 +1825,9 @@ var ShieldedPoolModule = class {
1785
1825
  commitment: Binary2.fromHex(params.commitment),
1786
1826
  amount: params.amount,
1787
1827
  asset_id: params.assetId,
1788
- encrypted_memo: Binary2.fromBytes(params.encryptedMemo),
1789
- proof: Binary2.fromBytes(params.proof),
1790
- public_signals: Binary2.fromBytes(params.publicSignals)
1791
- });
1792
- return toTxResult(
1793
- await (txOptions !== void 0 ? tx.signAndSubmit(signer, txOptions) : tx.signAndSubmit(signer))
1794
- );
1795
- }
1796
- // ─── Selective Disclosure ──────────────────────────────────────────────────
1797
- /**
1798
- * Requests a selective disclosure from a target account for a specific commitment.
1799
- * The auditor's Baby Jubjub public key is included so the note owner knows
1800
- * which key to encrypt to when generating the proof.
1801
- * Extrinsic: shieldedPool.request_disclosure(target, commitment, required_fields,
1802
- * reason, auditor_bjj_pk_x, auditor_bjj_pk_y)
1803
- */
1804
- async requestDisclosure(params, signer, txOptions) {
1805
- const entry = resolveTx(this.substrate.unsafe, "ShieldedPool", "request_disclosure");
1806
- const tx = callUnsafeTx(entry, {
1807
- target: params.target,
1808
- commitment: Binary2.fromBytes(new Uint8Array(params.commitment)),
1809
- required_fields: {
1810
- value: params.requiredFields.value,
1811
- asset_id: params.requiredFields.assetId,
1812
- owner: params.requiredFields.owner
1813
- },
1814
- reason: Binary2.fromText(params.reason),
1815
- auditor_bjj_pk_x: Binary2.fromBytes(new Uint8Array(params.auditorBjjPkX)),
1816
- auditor_bjj_pk_y: Binary2.fromBytes(new Uint8Array(params.auditorBjjPkY))
1817
- });
1818
- return toTxResult(
1819
- await (txOptions !== void 0 ? tx.signAndSubmit(signer, txOptions) : tx.signAndSubmit(signer))
1820
- );
1821
- }
1822
- /**
1823
- * Submits a Groth16 ZK disclosure proof for a note commitment.
1824
- * The proof reveals the selected fields (value, asset_id, owner_hash) on-chain.
1825
- * Use generateDisclosureProof() + buildDisclosurePublicSignals() before calling this.
1826
- * Extrinsic: shieldedPool.disclose(commitment, proof_bytes, public_signals, auditor)
1827
- */
1828
- async disclose(params, signer, txOptions) {
1829
- const entry = resolveTx(this.substrate.unsafe, "ShieldedPool", "disclose");
1830
- const tx = callUnsafeTx(entry, {
1831
- commitment: Binary2.fromBytes(new Uint8Array(params.commitment)),
1832
- proof_bytes: Binary2.fromBytes(new Uint8Array(params.proofBytes)),
1833
- public_signals: Binary2.fromBytes(new Uint8Array(params.publicSignals)),
1834
- auditor: params.auditor
1835
- });
1836
- return toTxResult(
1837
- await (txOptions !== void 0 ? tx.signAndSubmit(signer, txOptions) : tx.signAndSubmit(signer))
1838
- );
1839
- }
1840
- /**
1841
- * Rejects a pending disclosure request from an auditor for a specific commitment.
1842
- * Extrinsic: shieldedPool.reject_disclosure(auditor, commitment, reason)
1843
- */
1844
- async rejectDisclosure(params, signer, txOptions) {
1845
- const entry = resolveTx(this.substrate.unsafe, "ShieldedPool", "reject_disclosure");
1846
- const tx = callUnsafeTx(entry, {
1847
- auditor: params.auditor,
1848
- commitment: Binary2.fromBytes(new Uint8Array(params.commitment)),
1849
- reason: Binary2.fromText(params.reason)
1850
- });
1851
- return toTxResult(
1852
- await (txOptions !== void 0 ? tx.signAndSubmit(signer, txOptions) : tx.signAndSubmit(signer))
1853
- );
1854
- }
1855
- /**
1856
- * Cleans up a disclosure request that has passed its expiration block.
1857
- * Permissionless — any account can prune expired requests.
1858
- * Extrinsic: shieldedPool.prune_expired_request(target, auditor, commitment)
1859
- */
1860
- async pruneExpiredRequest(params, signer, txOptions) {
1861
- const entry = resolveTx(this.substrate.unsafe, "ShieldedPool", "prune_expired_request");
1862
- const tx = callUnsafeTx(entry, {
1863
- target: params.target,
1864
- auditor: params.auditor,
1865
- commitment: Binary2.fromBytes(new Uint8Array(params.commitment))
1866
- });
1867
- return toTxResult(
1868
- await (txOptions !== void 0 ? tx.signAndSubmit(signer, txOptions) : tx.signAndSubmit(signer))
1869
- );
1870
- }
1871
- /**
1872
- * Revokes a previously submitted voluntary disclosure record.
1873
- * Only applies to self-disclosures (auditor = None). Auditor-requested records are permanent.
1874
- * Extrinsic: shieldedPool.revoke_disclosure_record(commitment)
1875
- */
1876
- async revokeDisclosureRecord(params, signer, txOptions) {
1877
- const entry = resolveTx(this.substrate.unsafe, "ShieldedPool", "revoke_disclosure_record");
1878
- const tx = callUnsafeTx(entry, {
1879
- commitment: Binary2.fromBytes(new Uint8Array(params.commitment))
1828
+ encrypted_memo: params.encryptedMemo,
1829
+ proof: params.proof,
1830
+ public_signals: params.publicSignals
1880
1831
  });
1881
1832
  return toTxResult(
1882
1833
  await (txOptions !== void 0 ? tx.signAndSubmit(signer, txOptions) : tx.signAndSubmit(signer))
@@ -2188,12 +2139,7 @@ var AccountMappingModule = class {
2188
2139
  */
2189
2140
  async addChainLink(params, signer) {
2190
2141
  const entry = resolveTx(this.substrate.unsafe, "accountMapping", "addChainLink");
2191
- const tx = callUnsafeTx(
2192
- entry,
2193
- params.chainId,
2194
- Binary3.fromBytes(params.address),
2195
- Binary3.fromBytes(params.signature)
2196
- );
2142
+ const tx = callUnsafeTx(entry, params.chainId, params.address, params.signature);
2197
2143
  return toTxResult(await tx.signAndSubmit(signer));
2198
2144
  }
2199
2145
  /**
@@ -2264,14 +2210,30 @@ var AccountMappingModule = class {
2264
2210
  entry,
2265
2211
  params.owner,
2266
2212
  params.chainId,
2267
- Binary3.fromBytes(params.address),
2268
- Binary3.fromBytes(params.signature),
2269
- Binary3.fromBytes(params.callData)
2213
+ params.address,
2214
+ params.signature,
2215
+ params.callData
2270
2216
  );
2271
2217
  return toTxResult(await tx.signAndSubmit(signer));
2272
2218
  }
2273
2219
  };
2274
2220
 
2221
+ // src/rpc-v2/ChainModule.ts
2222
+ var ChainModule = class {
2223
+ constructor(substrate) {
2224
+ this.substrate = substrate;
2225
+ }
2226
+ substrate;
2227
+ /**
2228
+ * Returns `true` if the given SS58 account is an active Aura validator.
2229
+ *
2230
+ * Reads `pallet_aura::Authorities` directly from storage at the best known block.
2231
+ */
2232
+ async isValidator(ss58Address) {
2233
+ return this.substrate.request("chain_isValidator", [ss58Address]);
2234
+ }
2235
+ };
2236
+
2275
2237
  // src/rpc-v2/helpers.ts
2276
2238
  function mapAssetBalance(balance) {
2277
2239
  return {
@@ -2632,14 +2594,8 @@ var SP_SEL = {
2632
2594
  PRIVATE_TRANSFER: new Uint8Array([140, 15, 93, 36]),
2633
2595
  // unshield(bytes,bytes32,bytes32,uint32,uint256,bytes32,uint256,bytes32) → 0xd21d9a79
2634
2596
  UNSHIELD: new Uint8Array([210, 29, 154, 121]),
2635
- // requestDisclosure(bytes32,bytes32,bool,bool,bool,bytes,bytes32,bytes32) 0xe7022933 (caller = auditor)
2636
- REQUEST_DISCLOSURE: new Uint8Array([231, 2, 41, 51]),
2637
- // disclose(bytes32,bytes,bytes,bytes32) → 0xea8a4165 (caller = note owner)
2638
- DISCLOSE: new Uint8Array([234, 138, 65, 101]),
2639
- // rejectDisclosure(bytes32,bytes32,bytes) → 0x72b895a9 (caller = target)
2640
- REJECT_DISCLOSURE: new Uint8Array([114, 184, 149, 169]),
2641
- // pruneExpiredRequest(bytes32,bytes32,bytes32) → 0x0c338dcf (permissionless)
2642
- PRUNE_EXPIRED_REQUEST: new Uint8Array([12, 51, 141, 207])
2597
+ // claimShieldedFees(bytes32,uint256,uint32,bytes,bytes,bytes) 0x42e1e74c
2598
+ CLAIM_SHIELDED_FEES: new Uint8Array([66, 225, 231, 76])
2643
2599
  };
2644
2600
  var KNOWN_PRECOMPILES = {
2645
2601
  // ── Ethereum standard (EIP) ─────────────────────────────────────────────
@@ -2685,10 +2641,7 @@ var KNOWN_PRECOMPILES = {
2685
2641
  "9feb22ea": "shield(uint32,bytes32,bytes)",
2686
2642
  "8c0f5d24": "privateTransfer(bytes,bytes32,bytes32[],bytes32[],bytes[],uint32,uint256)",
2687
2643
  d21d9a79: "unshield(bytes,bytes32,bytes32,uint32,uint256,bytes32,uint256,bytes32)",
2688
- e7022933: "requestDisclosure(bytes32,bytes32,bool,bool,bool,bytes,bytes32,bytes32)",
2689
- ea8a4165: "disclose(bytes32,bytes,bytes,bytes32)",
2690
- "72b895a9": "rejectDisclosure(bytes32,bytes32,bytes)",
2691
- "0c338dcf": "pruneExpiredRequest(bytes32,bytes32,bytes32)"
2644
+ "42e1e74c": "claimShieldedFees(bytes32,uint256,uint32,bytes,bytes,bytes)"
2692
2645
  }
2693
2646
  }
2694
2647
  };
@@ -2851,132 +2804,77 @@ var ShieldedPoolPrecompile = class {
2851
2804
  data: this.buildUnshieldCalldata(params)
2852
2805
  });
2853
2806
  }
2854
- // ─── requestDisclosure ─────────────────────────────────────────────────────
2807
+ // ─── claimShieldedFees ───────────────────────────────────────────────────────────────────
2855
2808
  /**
2856
2809
  * Returns the ABI-encoded calldata for
2857
- * `requestDisclosure(bytes32,bytes32,bool,bool,bool,bytes,bytes32,bytes32)`.
2858
- *
2859
- * The **EVM caller** of the resulting transaction is treated as the **auditor**
2860
- * on-chain. No explicit auditor argument is needed.
2861
- */
2862
- buildRequestDisclosureCalldata(params) {
2863
- if (params.auditorBjjPkX.length !== 32)
2864
- throw new RangeError("requestDisclosure: auditorBjjPkX must be 32 bytes");
2865
- if (params.auditorBjjPkY.length !== 32)
2866
- throw new RangeError("requestDisclosure: auditorBjjPkY must be 32 bytes");
2867
- const target = fromHex(params.target);
2868
- const commitment = fromHex(params.commitment);
2869
- const reasonBytes = new TextEncoder().encode(params.reason);
2870
- return encodeHex(
2871
- SP_SEL.REQUEST_DISCLOSURE,
2872
- { type: "bytes32", value: target },
2873
- { type: "bytes32", value: commitment },
2874
- { type: "bool", value: params.disclosedValue },
2875
- { type: "bool", value: params.disclosedAssetId },
2876
- { type: "bool", value: params.disclosedOwner },
2877
- { type: "bytes", value: reasonBytes },
2878
- { type: "bytes32", value: params.auditorBjjPkX },
2879
- { type: "bytes32", value: params.auditorBjjPkY }
2880
- );
2881
- }
2882
- /**
2883
- * Requests selective disclosure of a specific commitment.
2810
+ * `claimShieldedFees(bytes32,uint256,uint32,bytes,bytes,bytes)`.
2884
2811
  *
2885
- * The EVM caller is recorded as the auditor on-chain. The note owner can
2886
- * respond with `disclose()` or reject with `rejectDisclosure()`.
2812
+ * ABI layout (params after selector):
2813
+ * - `commitment` bytes32 (fixed)
2814
+ * - `amount` — uint256 (fixed)
2815
+ * - `asset_id` — uint32 (fixed, right-aligned)
2816
+ * - `memo` — bytes (dynamic)
2817
+ * - `proof` — bytes (dynamic, 128 bytes Groth16)
2818
+ * - `publicSignals` — bytes (dynamic, 76 bytes)
2887
2819
  *
2888
- * Extrinsic: `shieldedPool.requestDisclosure(target, commitment, requiredFields, reason, bjjPkX, bjjPkY)`
2820
+ * The validator identity is derived from `msg.sender` in the precompile
2821
+ * do NOT include it in the calldata.
2889
2822
  */
2890
- async requestDisclosure(params, signer) {
2891
- return signer({ to: this.addr, data: this.buildRequestDisclosureCalldata(params) });
2892
- }
2893
- // ─── disclose ──────────────────────────────────────────────────────────────
2894
- /**
2895
- * Returns the ABI-encoded calldata for `disclose(bytes32,bytes,bytes,bytes32)`.
2896
- *
2897
- * The **EVM caller** is treated as the **note owner** on-chain.
2898
- * `params.proofBytes` must be exactly 128 bytes; `params.publicSignals` exactly 256 bytes.
2899
- */
2900
- buildDiscloseCalldata(params) {
2901
- if (params.proofBytes.length !== 128)
2902
- throw new RangeError("disclose: proofBytes must be exactly 128 bytes");
2903
- if (params.publicSignals.length !== 256)
2904
- throw new RangeError("disclose: publicSignals must be exactly 256 bytes");
2905
- const commitment = fromHex(params.commitment);
2906
- const auditor = fromHex(params.auditor);
2907
- return encodeHex(
2908
- SP_SEL.DISCLOSE,
2909
- { type: "bytes32", value: commitment },
2910
- { type: "bytes", value: params.proofBytes },
2911
- { type: "bytes", value: params.publicSignals },
2912
- { type: "bytes32", value: auditor }
2823
+ buildClaimShieldedFeesCalldata(params) {
2824
+ EncryptedMemo.validate(
2825
+ params.encryptedMemo,
2826
+ "buildClaimShieldedFeesCalldata.encryptedMemo"
2913
2827
  );
2914
- }
2915
- /**
2916
- * Submits a selective disclosure proof for a commitment.
2917
- *
2918
- * The EVM caller is treated as the note owner on-chain. The Groth16 proof is
2919
- * verified by the runtime; on success the encrypted signals are stored for
2920
- * the auditor to decrypt off-chain.
2921
- *
2922
- * Extrinsic: `shieldedPool.disclose(commitment, proofBytes, publicSignals, auditor)`
2923
- */
2924
- async disclose(params, signer) {
2925
- return signer({ to: this.addr, data: this.buildDiscloseCalldata(params) });
2926
- }
2927
- // ─── rejectDisclosure ──────────────────────────────────────────────────────
2928
- /**
2929
- * Returns the ABI-encoded calldata for `rejectDisclosure(bytes32,bytes32,bytes)`.
2930
- *
2931
- * The **EVM caller** is treated as the **target** (note owner) on-chain.
2932
- */
2933
- buildRejectDisclosureCalldata(params) {
2934
- const auditor = fromHex(params.auditor);
2828
+ if (params.proof.length === 0) {
2829
+ throw new Error("claimShieldedFees: proof must not be empty");
2830
+ }
2831
+ if (params.publicSignals.length !== 76) {
2832
+ throw new Error(
2833
+ `claimShieldedFees: publicSignals must be 76 bytes, got ${params.publicSignals.length}`
2834
+ );
2835
+ }
2935
2836
  const commitment = fromHex(params.commitment);
2936
- const reasonBytes = new TextEncoder().encode(params.reason);
2937
2837
  return encodeHex(
2938
- SP_SEL.REJECT_DISCLOSURE,
2939
- { type: "bytes32", value: auditor },
2838
+ SP_SEL.CLAIM_SHIELDED_FEES,
2940
2839
  { type: "bytes32", value: commitment },
2941
- { type: "bytes", value: reasonBytes }
2840
+ { type: "uint", value: params.amount },
2841
+ { type: "uint", value: BigInt(params.assetId) },
2842
+ { type: "bytes", value: params.encryptedMemo },
2843
+ { type: "bytes", value: params.proof },
2844
+ { type: "bytes", value: params.publicSignals }
2942
2845
  );
2943
2846
  }
2944
2847
  /**
2945
- * Rejects a pending disclosure request.
2848
+ * Claims accumulated relay fees as a private shielded note.
2946
2849
  *
2947
- * The EVM caller is treated as the note owner (target) on-chain.
2850
+ * This extrinsic is for **validators/relayers** who have accrued fees in
2851
+ * `pallet-relayer` and want to receive them privately inside the shielded pool
2852
+ * instead of as a public balance credit.
2948
2853
  *
2949
- * Extrinsic: `shieldedPool.rejectDisclosure(auditor, commitment, reason)`
2950
- */
2951
- async rejectDisclosure(params, signer) {
2952
- return signer({ to: this.addr, data: this.buildRejectDisclosureCalldata(params) });
2953
- }
2954
- // ─── pruneExpiredRequest ───────────────────────────────────────────────────
2955
- /**
2956
- * Returns the ABI-encoded calldata for `pruneExpiredRequest(bytes32,bytes32,bytes32)`.
2854
+ * The ZK `value_proof` binds `commitment` to `(amount, assetId, ownerPk, blinding)`
2855
+ * so the runtime can verify the note encodes exactly the claimed fee amount,
2856
+ * preventing a malicious relayer from inflating the withdrawal.
2957
2857
  *
2958
- * Permissionless: any EVM caller can prune an expired request.
2858
+ * The `msg.sender` EVM address is used as the validator identity; it must match
2859
+ * the address that has pending relay fees in `pallet-relayer`.
2860
+ *
2861
+ * Extrinsic: `shieldedPool.claim_shielded_fees(commitment, amount, assetId, memo, proof, publicSignals)`
2959
2862
  */
2960
- buildPruneExpiredRequestCalldata(params) {
2961
- const target = fromHex(params.target);
2962
- const auditor = fromHex(params.auditor);
2963
- const commitment = fromHex(params.commitment);
2964
- return encodeHex(
2965
- SP_SEL.PRUNE_EXPIRED_REQUEST,
2966
- { type: "bytes32", value: target },
2967
- { type: "bytes32", value: auditor },
2968
- { type: "bytes32", value: commitment }
2969
- );
2863
+ async claimShieldedFees(params, signer) {
2864
+ return signer({
2865
+ to: this.addr,
2866
+ data: this.buildClaimShieldedFeesCalldata(params)
2867
+ });
2970
2868
  }
2971
2869
  /**
2972
- * Removes an expired disclosure request from storage.
2973
- *
2974
- * Permissionless: any EVM account can call this once `expires_at` has passed.
2975
- *
2976
- * Extrinsic: `shieldedPool.pruneExpiredRequest(target, auditor, commitment)`
2870
+ * Estimates the EVM gas for a `claimShieldedFees` call.
2977
2871
  */
2978
- async pruneExpiredRequest(params, signer) {
2979
- return signer({ to: this.addr, data: this.buildPruneExpiredRequestCalldata(params) });
2872
+ async estimateClaimShieldedFeesGas(params, from) {
2873
+ return this.evm.estimateGas({
2874
+ from,
2875
+ to: this.addr,
2876
+ data: this.buildClaimShieldedFeesCalldata(params)
2877
+ });
2980
2878
  }
2981
2879
  };
2982
2880
 
@@ -3377,6 +3275,8 @@ var OrbinumClient = class _OrbinumClient {
3377
3275
  accountMapping;
3378
3276
  /** Typed access to `privacy_*` custom RPC endpoints. */
3379
3277
  privacy;
3278
+ /** Typed access to general chain state via `chain_*` custom RPC endpoints. */
3279
+ chain;
3380
3280
  /** Typed access to `zkVerifier_*` custom RPC endpoints. */
3381
3281
  zkVerifier;
3382
3282
  /** Typed access to `relayer_*` RPC endpoints (registry lookup and pending fee queries). */
@@ -3395,6 +3295,7 @@ var OrbinumClient = class _OrbinumClient {
3395
3295
  this.shieldedPool = new ShieldedPoolModule(substrate);
3396
3296
  this.accountMapping = new AccountMappingModule(substrate);
3397
3297
  this.privacy = new PrivacyModule(substrate);
3298
+ this.chain = new ChainModule(substrate);
3398
3299
  this.zkVerifier = new ZkVerifierModule(substrate);
3399
3300
  this.relayerStatus = new RelayerStatusModule(substrate);
3400
3301
  this.precompiles = evm ? {
@@ -3985,6 +3886,56 @@ function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwn
3985
3886
  };
3986
3887
  }
3987
3888
 
3889
+ // src/shielded-pool/protocol/NoteDisclosure.ts
3890
+ import { poseidon4 as poseidon43 } from "poseidon-lite";
3891
+ var PREFIX = "orbdisc:";
3892
+ var VERSION = 1;
3893
+ function toHex2(n) {
3894
+ return "0x" + n.toString(16);
3895
+ }
3896
+ function fromHex2(s) {
3897
+ return BigInt(s);
3898
+ }
3899
+ function createNoteDisclosureKey(note) {
3900
+ const payload = {
3901
+ v: VERSION,
3902
+ c: toHex2(note.commitment),
3903
+ val: toHex2(note.value),
3904
+ aid: toHex2(note.assetId),
3905
+ opk: toHex2(note.ownerPk),
3906
+ bld: toHex2(note.blinding)
3907
+ };
3908
+ const json = JSON.stringify(payload);
3909
+ const b64 = btoa(json).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
3910
+ return PREFIX + b64;
3911
+ }
3912
+ function decodeNoteDisclosureKey(key) {
3913
+ try {
3914
+ if (!key.startsWith(PREFIX)) return null;
3915
+ const b64 = key.slice(PREFIX.length).replace(/-/g, "+").replace(/_/g, "/");
3916
+ const json = atob(b64);
3917
+ const payload = JSON.parse(json);
3918
+ if (payload.v !== VERSION) return null;
3919
+ const disclosure = {
3920
+ commitment: fromHex2(payload.c),
3921
+ value: fromHex2(payload.val),
3922
+ assetId: fromHex2(payload.aid),
3923
+ ownerPk: fromHex2(payload.opk),
3924
+ blinding: fromHex2(payload.bld)
3925
+ };
3926
+ const recomputed = poseidon43([
3927
+ disclosure.value,
3928
+ disclosure.assetId,
3929
+ disclosure.ownerPk,
3930
+ disclosure.blinding
3931
+ ]);
3932
+ if (recomputed !== disclosure.commitment) return null;
3933
+ return disclosure;
3934
+ } catch {
3935
+ return null;
3936
+ }
3937
+ }
3938
+
3988
3939
  // src/shielded-pool/protocol/coinSelection.ts
3989
3940
  var TRANSFER_TREE_DEPTH = 20;
3990
3941
  function selectNotes(notes, needed) {
@@ -4021,51 +3972,6 @@ function buildDummyTransferInput(assetId) {
4021
3972
  };
4022
3973
  }
4023
3974
 
4024
- // src/shielded-pool/protocol/disclosure.ts
4025
- import {
4026
- generateDisclosureProof
4027
- } from "@orbinum/proof-generator";
4028
- import { mulPointEscalar as mulPointEscalar5, Base8 as Base83 } from "@zk-kit/baby-jubjub";
4029
- import { poseidon1, poseidon3 } from "poseidon-lite";
4030
- function hexFieldToBytes32(hex) {
4031
- const clean = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
4032
- return fromHex(clean.padStart(64, "0"));
4033
- }
4034
- function deriveBabyJubjubKeypair(substrateSigningKey) {
4035
- let keyBigInt = 0n;
4036
- for (let i = 0; i < substrateSigningKey.length; i++) {
4037
- keyBigInt = keyBigInt << 8n | BigInt(substrateSigningKey[i]);
4038
- }
4039
- const sk = poseidon1([keyBigInt]);
4040
- const pk = mulPointEscalar5(Base83, sk);
4041
- return { sk, pkX: pk[0], pkY: pk[1] };
4042
- }
4043
- function buildDisclosurePublicSignals(commitment, auditorPkX, auditorPkY, proofOutput) {
4044
- const buf = new Uint8Array(256);
4045
- buf.set(hexFieldToBytes32(commitment), 0);
4046
- buf.set(bigintTo32Le(auditorPkX), 32);
4047
- buf.set(bigintTo32Le(auditorPkY), 64);
4048
- buf.set(hexFieldToBytes32(proofOutput.encryptedData.epkX), 96);
4049
- buf.set(hexFieldToBytes32(proofOutput.encryptedData.epkY), 128);
4050
- buf.set(hexFieldToBytes32(proofOutput.encryptedData.encValue), 160);
4051
- buf.set(hexFieldToBytes32(proofOutput.encryptedData.encAssetId), 192);
4052
- buf.set(hexFieldToBytes32(proofOutput.encryptedData.encOwnerHash), 224);
4053
- return Array.from(buf);
4054
- }
4055
- function decryptDisclosureSignals(auditorBjjSk, enc) {
4056
- const shared = mulPointEscalar5([enc.epkX, enc.epkY], auditorBjjSk);
4057
- const sharedX = shared[0];
4058
- const sharedY = shared[1];
4059
- const k0 = poseidon3([sharedX, sharedY, 0n]);
4060
- const k1 = poseidon3([sharedX, sharedY, 1n]);
4061
- const k2 = poseidon3([sharedX, sharedY, 2n]);
4062
- return {
4063
- value: (enc.encValue - k0 + BN254_R) % BN254_R,
4064
- assetId: (enc.encAssetId - k1 + BN254_R) % BN254_R,
4065
- ownerHash: (enc.encOwnerHash - k2 + BN254_R) % BN254_R
4066
- };
4067
- }
4068
-
4069
3975
  // src/utils/blinding.ts
4070
3976
  function randomBlinding() {
4071
3977
  const buf = new Uint8Array(32);
@@ -4077,7 +3983,7 @@ function randomBlinding() {
4077
3983
  // src/privacy-keys/PrivacyKeys.ts
4078
3984
  import { hkdf as hkdf2 } from "@noble/hashes/hkdf.js";
4079
3985
  import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
4080
- import { mulPointEscalar as mulPointEscalar6, Base8 as Base84, packPoint as packPoint2 } from "@zk-kit/baby-jubjub";
3986
+ import { mulPointEscalar as mulPointEscalar5, Base8 as Base83, packPoint as packPoint2 } from "@zk-kit/baby-jubjub";
4081
3987
  var IVK_DOMAIN = new TextEncoder().encode("orbinum-ivk-v1");
4082
3988
  function deriveSpendingKeyMessage(chainId, address) {
4083
3989
  return `orbinum-spending-key-v1
@@ -4100,13 +4006,13 @@ function deriveViewingSecretKey(spendingKey) {
4100
4006
  }
4101
4007
  function deriveViewingPublicKey(ivsk) {
4102
4008
  const ivskScalar = BigInt(toHex(ivsk)) % BABYJUB_SUBORDER || 1n;
4103
- const ivkPoint = mulPointEscalar6(Base84, ivskScalar);
4009
+ const ivkPoint = mulPointEscalar5(Base83, ivskScalar);
4104
4010
  const packed = packPoint2(ivkPoint);
4105
4011
  return bigintTo32Le(packed);
4106
4012
  }
4107
4013
  function deriveOwnerPk(spendingKey) {
4108
4014
  try {
4109
- const pubPoint = mulPointEscalar6(Base84, spendingKey);
4015
+ const pubPoint = mulPointEscalar5(Base83, spendingKey);
4110
4016
  return pubPoint[0];
4111
4017
  } catch {
4112
4018
  return 0n;
@@ -4383,8 +4289,8 @@ import {
4383
4289
  WebArtifactProvider
4384
4290
  } from "@orbinum/proof-generator";
4385
4291
  import { randomBytes as randomBytes3 } from "@noble/ciphers/utils.js";
4386
- import { mulPointEscalar as mulPointEscalar7, Base8 as Base85 } from "@zk-kit/baby-jubjub";
4387
- import { poseidon4 as poseidon43 } from "poseidon-lite";
4292
+ import { mulPointEscalar as mulPointEscalar6, Base8 as Base84 } from "@zk-kit/baby-jubjub";
4293
+ import { poseidon4 as poseidon44 } from "poseidon-lite";
4388
4294
 
4389
4295
  // src/proof-generator/merkle.ts
4390
4296
  function merkleProofToCircuit(siblings, leafIndex) {
@@ -4406,9 +4312,9 @@ async function generateUnshieldProof(inputs, options = {}) {
4406
4312
  if (changeValue < 0n) {
4407
4313
  throw new Error("changeValue must be >= 0.");
4408
4314
  }
4409
- const changeOwnerPubkey = inputs.changeOwnerPubkey ?? mulPointEscalar7(Base85, inputs.spendingKey)[0];
4315
+ const changeOwnerPubkey = inputs.changeOwnerPubkey ?? mulPointEscalar6(Base84, inputs.spendingKey)[0];
4410
4316
  const changeBlinding = inputs.changeBlinding ?? (changeValue > 0n ? bytesToBigintLE(randomBytes3(32)) : 0n);
4411
- const changeCommitment = changeValue > 0n ? poseidon43([changeValue, inputs.assetId, changeOwnerPubkey, changeBlinding]) : 0n;
4317
+ const changeCommitment = changeValue > 0n ? poseidon44([changeValue, inputs.assetId, changeOwnerPubkey, changeBlinding]) : 0n;
4412
4318
  const circuitInputs = {
4413
4319
  merkle_root: leHexToBigint(inputs.merkleRoot).toString(),
4414
4320
  nullifier: inputs.nullifier.toString(),
@@ -4472,41 +4378,34 @@ async function generateTransferProof(params, options = {}) {
4472
4378
 
4473
4379
  // src/proof-generator/fee-claim.ts
4474
4380
  import {
4475
- generateDisclosureProof as generateDisclosureProof2
4381
+ CircuitType as CircuitType3,
4382
+ generateProof as generateProof3,
4383
+ WebArtifactProvider as WebArtifactProvider3
4476
4384
  } from "@orbinum/proof-generator";
4477
- function hexSignalToBytes(hex) {
4478
- const clean = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
4479
- const padded = clean.padStart(64, "0");
4480
- const bytes = new Uint8Array(32);
4481
- for (let i = 0; i < 32; i++) {
4482
- bytes[i] = parseInt(padded.slice(i * 2, i * 2 + 2), 16);
4483
- }
4484
- return bytes;
4485
- }
4486
4385
  async function generateFeeClaimProof(inputs, options = {}) {
4487
- const result = await generateDisclosureProof2(
4488
- inputs.amount,
4489
- inputs.ownerPubkey,
4490
- inputs.blinding,
4491
- inputs.assetId,
4492
- inputs.commitment,
4493
- // Baby Jubjub base point G — placeholder, no real auditor for fee claiming
4494
- 5299619240641551281634865583518297030282874472190772894086521144482721001553n,
4495
- 16950150798460657717958625567821834550301663161624707787222815936182638968203n,
4496
- 1n,
4497
- // r placeholder ephemeral scalar (NOT cryptographically secure)
4498
- { discloseValue: true, discloseAssetId: true, discloseOwner: false },
4499
- options
4500
- );
4501
- const [, , sigEncValue, sigEncAssetId, sigEncOwnerHash, sigCommitment] = result.publicSignals.map(hexSignalToBytes);
4502
- const compact = new Uint8Array(76);
4503
- compact.set(sigCommitment);
4504
- compact.set(sigEncValue.subarray(0, 8), 32);
4505
- compact.set(sigEncAssetId.subarray(0, 4), 40);
4506
- compact.set(sigEncOwnerHash, 44);
4386
+ if (inputs.amount <= 0n) {
4387
+ throw new Error("Fee claim amount must be greater than zero.");
4388
+ }
4389
+ const circuitInputs = {
4390
+ commitment: inputs.commitment.toString(),
4391
+ value: inputs.amount.toString(),
4392
+ asset_id: inputs.assetId.toString(),
4393
+ owner_pubkey: inputs.ownerPubkey.toString(),
4394
+ blinding: inputs.blinding.toString()
4395
+ };
4396
+ const provider = options.provider ?? new WebArtifactProvider3();
4397
+ const opts = { provider };
4398
+ if (options.verbose !== void 0) opts.verbose = options.verbose;
4399
+ const proofResult = await generateProof3(CircuitType3.ValueProof, circuitInputs, opts);
4400
+ const [sigCommitment, sigValue, sigAssetId, sigOwnerHash] = proofResult.publicSignals.map(BigInt);
4401
+ const buf = new Uint8Array(76);
4402
+ buf.set(bigintTo32Le(sigCommitment), 0);
4403
+ buf.set(bigintTo32Le(sigValue).subarray(0, 8), 32);
4404
+ buf.set(bigintTo32Le(sigAssetId).subarray(0, 4), 40);
4405
+ buf.set(bigintTo32Le(sigOwnerHash), 44);
4507
4406
  return {
4508
- proof: result.proof,
4509
- publicSignals: Array.from(compact)
4407
+ proof: proofResult.proof,
4408
+ publicSignals: Array.from(buf)
4510
4409
  };
4511
4410
  }
4512
4411
 
@@ -4576,6 +4475,17 @@ function decodePrecompileCalldata(address, input) {
4576
4475
  return { fnSig, args: {} };
4577
4476
  }
4578
4477
  }
4478
+ if (fnSig.startsWith("claimShieldedFees(")) {
4479
+ try {
4480
+ const data = fromHex(input.slice(10));
4481
+ const commitment = toHex(data.slice(0, 32));
4482
+ const amount = decodeUint(data, 32);
4483
+ const assetId = decodeUint(data, 64);
4484
+ return { fnSig, args: { commitment, amount, assetId } };
4485
+ } catch {
4486
+ return { fnSig, args: {} };
4487
+ }
4488
+ }
4579
4489
  return { fnSig, args: {} };
4580
4490
  }
4581
4491
 
@@ -4583,8 +4493,8 @@ function decodePrecompileCalldata(address, input) {
4583
4493
  var CircuitId = {
4584
4494
  Transfer: 1,
4585
4495
  Unshield: 2,
4586
- Disclosure: 3,
4587
- PrivateLink: 4
4496
+ ValueProof: 4,
4497
+ PrivateLink: 5
4588
4498
  };
4589
4499
 
4590
4500
  // src/utils/string.ts
@@ -4773,39 +4683,6 @@ function mapExtrinsicArgs(section, method, args) {
4773
4683
  recipient: get(5, "recipient")
4774
4684
  };
4775
4685
  }
4776
- if (m_norm === "setauditpolicy") {
4777
- return {
4778
- auditors: get(0, "auditors"),
4779
- conditions: get(1, "conditions"),
4780
- max_frequency: get(2, "max_frequency"),
4781
- valid_until: get(3, "valid_until")
4782
- };
4783
- }
4784
- if (m_norm === "requestdisclosure") {
4785
- return {
4786
- target: get(0, "target"),
4787
- commitment: get(1, "commitment"),
4788
- required_fields: get(2, "required_fields"),
4789
- reason: get(3, "reason"),
4790
- auditor_bjj_pk_x: get(4, "auditor_bjj_pk_x"),
4791
- auditor_bjj_pk_y: get(5, "auditor_bjj_pk_y")
4792
- };
4793
- }
4794
- if (m_norm === "disclose") {
4795
- return {
4796
- commitment: get(0, "commitment"),
4797
- proof_bytes: get(1, "proof_bytes"),
4798
- public_signals: get(2, "public_signals"),
4799
- auditor: get(3, "auditor")
4800
- };
4801
- }
4802
- if (m_norm === "rejectdisclosure") {
4803
- return {
4804
- auditor: get(0, "auditor"),
4805
- commitment: get(1, "commitment"),
4806
- reason: get(2, "reason")
4807
- };
4808
- }
4809
4686
  if (m_norm === "registerasset") {
4810
4687
  return {
4811
4688
  name: get(0, "name"),
@@ -4820,19 +4697,6 @@ function mapExtrinsicArgs(section, method, args) {
4820
4697
  if (m_norm === "unverifyasset") {
4821
4698
  return { asset_id: get(0, "asset_id") };
4822
4699
  }
4823
- if (m_norm === "batchsubmitdisclosureproofs") {
4824
- return { submissions: get(0, "submissions") };
4825
- }
4826
- if (m_norm === "pruneexpiredrequest") {
4827
- return {
4828
- target: get(0, "target"),
4829
- auditor: get(1, "auditor"),
4830
- commitment: get(2, "commitment")
4831
- };
4832
- }
4833
- if (m_norm === "revokedisclosurerecord") {
4834
- return { commitment: get(0, "commitment") };
4835
- }
4836
4700
  }
4837
4701
  if (s === "ethereum" && m === "transact") {
4838
4702
  return { transaction: get(0, "transaction") };
@@ -5056,51 +4920,6 @@ function mapZkEventData(method, data) {
5056
4920
  };
5057
4921
  }
5058
4922
  const m_norm = m.replace(/_/g, "");
5059
- if (m_norm === "auditpolicyset") {
5060
- return {
5061
- account: get(0, "account"),
5062
- version: get(1, "version")
5063
- };
5064
- }
5065
- if (m_norm === "disclosed") {
5066
- return {
5067
- target: get(0, "target"),
5068
- auditor: get(1, "auditor"),
5069
- commitment: get(2, "commitment"),
5070
- signals: get(3, "signals")
5071
- };
5072
- }
5073
- if (m_norm === "disclosurerequested") {
5074
- return {
5075
- target: get(0, "target"),
5076
- auditor: get(1, "auditor"),
5077
- commitment: get(2, "commitment"),
5078
- required_fields: get(3, "required_fields"),
5079
- auditor_bjj_pk_x: get(4, "auditor_bjj_pk_x"),
5080
- auditor_bjj_pk_y: get(5, "auditor_bjj_pk_y")
5081
- };
5082
- }
5083
- if (m_norm === "disclosurerejected") {
5084
- return {
5085
- target: get(0, "target"),
5086
- auditor: get(1, "auditor"),
5087
- commitment: get(2, "commitment"),
5088
- reason: get(3, "reason")
5089
- };
5090
- }
5091
- if (m_norm === "disclosurerequestexpired") {
5092
- return {
5093
- target: get(0, "target"),
5094
- auditor: get(1, "auditor"),
5095
- commitment: get(2, "commitment")
5096
- };
5097
- }
5098
- if (m_norm === "disclosurerecordrevoked") {
5099
- return {
5100
- who: get(0, "who"),
5101
- commitment: get(1, "commitment")
5102
- };
5103
- }
5104
4923
  if (m_norm === "assetregistered") {
5105
4924
  return { asset_id: get(0, "asset_id") };
5106
4925
  }
@@ -5390,17 +5209,16 @@ export {
5390
5209
  bigintTo32Be,
5391
5210
  bigintTo32Le,
5392
5211
  bigintTo32LeArr,
5393
- buildDisclosurePublicSignals,
5394
5212
  buildDummyTransferInput,
5395
5213
  bytesToBigintLE,
5396
5214
  computeNullifier,
5397
5215
  computePathIndices,
5398
5216
  connectInjectedExtension,
5217
+ createNoteDisclosureKey,
5218
+ decodeNoteDisclosureKey,
5399
5219
  decodePrecompileCalldata,
5400
- decryptDisclosureSignals,
5401
5220
  decryptJson,
5402
5221
  decryptNoteRecord,
5403
- deriveBabyJubjubKeypair,
5404
5222
  deriveMasterKeyBytes,
5405
5223
  deriveOwnerPk,
5406
5224
  deriveSpendingKeyFromSignature,
@@ -5421,7 +5239,6 @@ export {
5421
5239
  formatORB,
5422
5240
  fromBase64,
5423
5241
  fromHex,
5424
- generateDisclosureProof,
5425
5242
  generateFeeClaimProof,
5426
5243
  generateTransferProof,
5427
5244
  generateUnshieldProof,