@gvnrdao/dh-sdk 0.0.270 → 0.0.271

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.js CHANGED
@@ -31149,7 +31149,6 @@ var require_pkg_src = __commonJS({
31149
31149
  executeLitAction: () => executeLitAction,
31150
31150
  executePkpOperation: () => executePkpOperation,
31151
31151
  executePriceOracle: () => executePriceOracle,
31152
- executePriceOracleConsensus: () => executePriceOracleConsensus,
31153
31152
  executeVaultSnapshot: () => executeVaultSnapshot,
31154
31153
  generateSessionSignatures: () => generateSessionSignatures,
31155
31154
  generateSessionSignaturesWithCache: () => generateSessionSignaturesWithCache,
@@ -31392,17 +31391,17 @@ var require_pkg_src = __commonJS({
31392
31391
  hash: "856da2d48ac2b76fc0d493a5a3df2decbf8e0fbbaff550996a0c48733bdd4660"
31393
31392
  },
31394
31393
  ucdMintValidator: {
31395
- cid: "QmNgE555xr7SGduoJWXk8oLMPiKCT3xYdDg7uCWLVp6Ewk",
31394
+ cid: "QmWZJpS3Q25XKo9ptzVcYz7pnW5hbqhuSvrhu7Qo7EcxEk",
31396
31395
  authorizedCidHex: cidToHex(
31397
- "QmNgE555xr7SGduoJWXk8oLMPiKCT3xYdDg7uCWLVp6Ewk"
31396
+ "QmWZJpS3Q25XKo9ptzVcYz7pnW5hbqhuSvrhu7Qo7EcxEk"
31398
31397
  ),
31399
31398
  name: "Ucd Mint Validator",
31400
31399
  description: "Production Ucd Mint Validator",
31401
31400
  version: "1.0.0",
31402
31401
  deployed: true,
31403
- deployedAt: 1779894180903,
31404
- size: 69530,
31405
- hash: "64e45e5a1918af2e375f12e5036757364080a15b640e8b7d76b513109c1e0b3c",
31402
+ deployedAt: 1780330809889,
31403
+ size: 66616,
31404
+ hash: "6015049e636fc2dd4dcce07e2f2bc1df20a8e8c466a5f054918e5f6773c26ac4",
31406
31405
  validatorWalletAddress: "0x36f3dd61c4c08a56d29ed2fd6d5f111b67b6a7a1",
31407
31406
  pkp: {
31408
31407
  publicKey: "0x041ab17cd91fc5c0b761eea6092d032807561b621b82c488826776e04a9158d61ba64d809a4729f0501289d980732cb06d8dfd06999dd9c8efd2f495dad78b31bb",
@@ -31410,17 +31409,17 @@ var require_pkg_src = __commonJS({
31410
31409
  }
31411
31410
  },
31412
31411
  processPaymentValidator: {
31413
- cid: "QmVmgq1zAuwdiyYsBx9LoUZFJetz2qC7EAjjwB55Yb3ZPJ",
31412
+ cid: "QmRZjMcJzEAzepwN3uJBbgGxMPULvCw6LMpQ94w19sv3Cx",
31414
31413
  authorizedCidHex: cidToHex(
31415
- "QmVmgq1zAuwdiyYsBx9LoUZFJetz2qC7EAjjwB55Yb3ZPJ"
31414
+ "QmRZjMcJzEAzepwN3uJBbgGxMPULvCw6LMpQ94w19sv3Cx"
31416
31415
  ),
31417
31416
  name: "Process Payment Validator",
31418
31417
  description: "Production Process Payment Validator",
31419
31418
  version: "1.0.0",
31420
31419
  deployed: true,
31421
- deployedAt: 1779894189375,
31422
- size: 65519,
31423
- hash: "cc3d394347166f9611bdb780f0dfcabea0d5e6fe21ebfddd1b481432e59e0d8d",
31420
+ deployedAt: 1780330829127,
31421
+ size: 62605,
31422
+ hash: "44e7fa2bc52d08c52821945a2bfd8fb8a5745d1f5669b2a45666fa34e7966198",
31424
31423
  validatorWalletAddress: "0xc2ed5a59bd81eb4d1a19a0147b86ab69aa4c28ba",
31425
31424
  pkp: {
31426
31425
  publicKey: "0x04cfccb9b6c7addc79469c0e9fafebef4c70801302c62cdb26b610723a9b8527d23f98a40158c7340d83fd0e62d02b5ec74c12f7a86d98e8c6973b4811110f19ad",
@@ -31428,17 +31427,17 @@ var require_pkg_src = __commonJS({
31428
31427
  }
31429
31428
  },
31430
31429
  extendPositionValidator: {
31431
- cid: "QmSVjVq18N2mzhrjxCLs1UGFqAD4TLwG6CEGZzCFSb4GoZ",
31430
+ cid: "Qmb4y62Ftjar5EXcREyXC84U7QEMhCQgycHYCmJxLichvt",
31432
31431
  authorizedCidHex: cidToHex(
31433
- "QmSVjVq18N2mzhrjxCLs1UGFqAD4TLwG6CEGZzCFSb4GoZ"
31432
+ "Qmb4y62Ftjar5EXcREyXC84U7QEMhCQgycHYCmJxLichvt"
31434
31433
  ),
31435
31434
  name: "Extend Position Validator",
31436
31435
  description: "Production Extend Position Validator",
31437
31436
  version: "1.0.1",
31438
31437
  deployed: true,
31439
- deployedAt: 1779894197740,
31440
- size: 64948,
31441
- hash: "97cdc90fa70e4dfb3c64b073bb22257c3a696d3392e3cca3b4d7ae7304751845",
31438
+ deployedAt: 1780330862404,
31439
+ size: 62034,
31440
+ hash: "2eedfed0a406fa24457b29621de7657ca598bf9a3bc928ea5d5febdeef17c1e1",
31442
31441
  validatorWalletAddress: "0xb3f4271c475887a86a2f21446f0968c30cc74c97",
31443
31442
  pkp: {
31444
31443
  publicKey: "0x04e52338f6a0c3362800f1a94c4c8f08be5030dde0fa217388c53d1c1a4790f4443c9f2886b2d2d8f4b75a9a156e9b028011b1a1cf7648da0e556aa980ec692836",
@@ -31446,17 +31445,17 @@ var require_pkg_src = __commonJS({
31446
31445
  }
31447
31446
  },
31448
31447
  btcWithdrawal: {
31449
- cid: "QmWBZxCTXP52fxakJRRQ4wiDwF9AS4E5RJXtRinnaShbtu",
31448
+ cid: "QmetrNkAUQ54PHzHLRR7TfDk3oGKnCf22m2bQwj24eB253",
31450
31449
  authorizedCidHex: cidToHex(
31451
- "QmWBZxCTXP52fxakJRRQ4wiDwF9AS4E5RJXtRinnaShbtu"
31450
+ "QmetrNkAUQ54PHzHLRR7TfDk3oGKnCf22m2bQwj24eB253"
31452
31451
  ),
31453
31452
  name: "Btc Withdrawal",
31454
31453
  description: "Production Btc Withdrawal",
31455
31454
  version: "1.0.0",
31456
31455
  deployed: true,
31457
- deployedAt: 1779894206894,
31458
- size: 76209,
31459
- hash: "ac5756d09e0a4f04513af18fdb6f3054ebd0bcb61bc51e8de7c98049b1a296c3",
31456
+ deployedAt: 1780330882060,
31457
+ size: 73295,
31458
+ hash: "c31e8f993806e8031fec42712eca04cb2e3b12f4ff37db98bcd28f46c766d710",
31460
31459
  validatorWalletAddress: "0xbb137fbda353199e9419b698c57a742124d4987d",
31461
31460
  pkp: {
31462
31461
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
@@ -31464,17 +31463,17 @@ var require_pkg_src = __commonJS({
31464
31463
  }
31465
31464
  },
31466
31465
  liquidationValidator: {
31467
- cid: "QmcQAWj3nCsAbHkqBnBnk6LzqKEvVy7Ed5awnTQ9s9Nznq",
31466
+ cid: "QmRuLKJmsD8yN6Ez89L9mzSM3zyarjGwFMBwn23CkajizZ",
31468
31467
  authorizedCidHex: cidToHex(
31469
- "QmcQAWj3nCsAbHkqBnBnk6LzqKEvVy7Ed5awnTQ9s9Nznq"
31468
+ "QmRuLKJmsD8yN6Ez89L9mzSM3zyarjGwFMBwn23CkajizZ"
31470
31469
  ),
31471
31470
  name: "Liquidation Validator",
31472
31471
  description: "Production Liquidation Validator",
31473
31472
  version: "1.0.0",
31474
31473
  deployed: true,
31475
- deployedAt: 1779894215050,
31476
- size: 56114,
31477
- hash: "b0fcc1acfbf40e4e77de2d3327447e691b0e4a82fe0b34bd8d47d1c6051e9766",
31474
+ deployedAt: 1780330901287,
31475
+ size: 53200,
31476
+ hash: "7bb6d4451dbdcc4f5e4d60bf15db064608877afb4800e44f186fcb987194c36b",
31478
31477
  validatorWalletAddress: "0x1542f863ee0340f6a067573e80ae66dd9b3838fa",
31479
31478
  pkp: {
31480
31479
  publicKey: "0x041a241de58976c13e3d7ca5a18e494f7330151e3818706135d50176e78ffb673e58b11f0b67a87c73fade6c6b27d6e7a7377ea9f4c10bf31880f1d725f18cc6f8",
@@ -31482,17 +31481,17 @@ var require_pkg_src = __commonJS({
31482
31481
  }
31483
31482
  },
31484
31483
  priceOracle: {
31485
- cid: "QmYvwgGkFcvkqFB93oebMRDeqFgiHBAxRUcd6qKgktqXAf",
31484
+ cid: "QmR5mjqhxfEPuBMbxhcXkJpdAMDzYfkpUWPgcPNCiSuhqh",
31486
31485
  authorizedCidHex: cidToHex(
31487
- "QmYvwgGkFcvkqFB93oebMRDeqFgiHBAxRUcd6qKgktqXAf"
31486
+ "QmR5mjqhxfEPuBMbxhcXkJpdAMDzYfkpUWPgcPNCiSuhqh"
31488
31487
  ),
31489
31488
  name: "Price Oracle",
31490
31489
  description: "Production Price Oracle (Chipotle main+getPrivateKey)",
31491
31490
  version: "1.1.0",
31492
31491
  deployed: true,
31493
- deployedAt: 1779199116800,
31494
- size: 11179,
31495
- hash: "83102b059588020143ca5fbc0f651318fa1436914a6236e356758c8d31468a78",
31492
+ deployedAt: 1780330918696,
31493
+ size: 8134,
31494
+ hash: "7aa3339f0501c3f628e4eaf00d39cfff76789d923aa440894c4e5a0b696c7f12",
31496
31495
  validatorWalletAddress: "0x831ddf3048547b983efe3ccbbb35a45a53191651",
31497
31496
  pkp: {
31498
31497
  publicKey: "0x043beaa1da47875601a8d6f430b1438ee2d4732eefd06e5c63a474bbdaf9e7df1797b1b951e041b627c2bf839788164825324c9cbd1e2d6f740fdd4bff69b1900b",
@@ -31500,17 +31499,17 @@ var require_pkg_src = __commonJS({
31500
31499
  }
31501
31500
  },
31502
31501
  loanVaultBtcBalance: {
31503
- cid: "QmWqHBGzyhQB4Usfs47W7nGGYsCivJXFaJQCRqoPE8hy6i",
31502
+ cid: "QmbXoFbhtqWsgKkLxtxwd6fDuKvvBpPhpMmdqUU1UC9GMn",
31504
31503
  authorizedCidHex: cidToHex(
31505
- "QmWqHBGzyhQB4Usfs47W7nGGYsCivJXFaJQCRqoPE8hy6i"
31504
+ "QmbXoFbhtqWsgKkLxtxwd6fDuKvvBpPhpMmdqUU1UC9GMn"
31506
31505
  ),
31507
31506
  name: "Loan Vault Btc Balance",
31508
31507
  description: "Production Loan Vault Btc Balance",
31509
31508
  version: "1.0.0",
31510
31509
  deployed: true,
31511
- deployedAt: 1779894223069,
31512
- size: 45960,
31513
- hash: "7ee25d0058e7f9f50f7c97f966cbbea46c53e3e08891d0403b41223ddaf03a5f",
31510
+ deployedAt: 1780330936276,
31511
+ size: 43046,
31512
+ hash: "160e4ed6d0c05871d65408906cb2ce900f3ce67a2a3a27549254773e3569d37e",
31514
31513
  validatorWalletAddress: "0x47feea74c8739d24b44faa67217f2f99970e15e7",
31515
31514
  pkp: {
31516
31515
  publicKey: "0x043616787c5432415c24378c4ef48de2bcd6bb7b575b837e3cff09171802662da7105d79586c7659677a0ecbaddac4cce06cb2a11f69a16fa0c4d7002ac7d51a4d",
@@ -32306,14 +32305,11 @@ ${errorReport}`);
32306
32305
  init_debug_logger();
32307
32306
  init_session_signature_cache();
32308
32307
  var import_ethers13 = require_lib2();
32309
- var ACTIVE_LOAN_LIQUIDATION_THRESHOLD_BPS = 13e3;
32310
32308
  var EXPIRED_LOAN_MIN_LIQUIDATION_THRESHOLD_BPS = 11e3;
32311
32309
  var GRACE_PERIOD_DAYS = 30;
32312
32310
  var SATOSHIS_PER_BITCOIN = 100000000n;
32313
32311
  var PRICE_ORACLE_DECIMALS = 100000000n;
32314
32312
  var UCD_TOKEN_DECIMALS = 1000000000000000000n;
32315
- var PRICE_ORACLE_OUTLIER_DEVIATION_THRESHOLD = 0.02;
32316
- var PRICE_ORACLE_DISPERSION_THRESHOLD = 0.05;
32317
32313
  var MAX_BTC_AMOUNT = 25e6 * 1e8;
32318
32314
  var UTXO_QUERY_MAX_RETRIES = 3;
32319
32315
  var UTXO_QUERY_RETRY_DELAY_MS = 500;
@@ -32397,7 +32393,7 @@ ${errorReport}`);
32397
32393
  }
32398
32394
  function calculateLiquidationThreshold(isExpired, daysIntoGracePeriod, activeLoanThresholdBps, maxExpiredThresholdBps) {
32399
32395
  if (!isExpired) {
32400
- return activeLoanThresholdBps ?? ACTIVE_LOAN_LIQUIDATION_THRESHOLD_BPS;
32396
+ return activeLoanThresholdBps;
32401
32397
  }
32402
32398
  const maxThreshold = maxExpiredThresholdBps ?? EXPIRED_LOAN_MIN_LIQUIDATION_THRESHOLD_BPS;
32403
32399
  const day = Math.min(daysIntoGracePeriod, GRACE_PERIOD_DAYS);
@@ -32665,7 +32661,7 @@ ${errorReport}`);
32665
32661
  positionId,
32666
32662
  positionState.vaultAddress
32667
32663
  ),
32668
- this.config.priceOracle.getBTCPriceConsensus()
32664
+ this.config.priceOracle.getBTCPrice()
32669
32665
  ]);
32670
32666
  const protocolParams = createProtocolParametersModule({
32671
32667
  termManagerAddress: this.config.termManagerAddress,
@@ -32771,7 +32767,7 @@ ${errorReport}`);
32771
32767
  true
32772
32768
  // Always skip UTXO validation for fast path
32773
32769
  ),
32774
- this.config.priceOracle.getBTCPriceConsensus()
32770
+ this.config.priceOracle.getBTCPrice()
32775
32771
  ]);
32776
32772
  const protocolParams = createProtocolParametersModule({
32777
32773
  termManagerAddress: this.config.termManagerAddress,
@@ -33073,7 +33069,7 @@ ${errorReport}`);
33073
33069
  *
33074
33070
  * @param positionId - Position to check
33075
33071
  * @param additionalDebt - Additional UCD debt to add
33076
- * @param requiredRatioBps - Required collateral ratio (e.g., 13000 for 130%)
33072
+ * @param requiredRatioBps - Required collateral ratio (e.g., 11000 for 110%)
33077
33073
  * @returns True if sufficient collateral exists
33078
33074
  */
33079
33075
  async hasSufficientCollateral(positionId, additionalDebt, requiredRatioBps) {
@@ -33834,27 +33830,23 @@ ${errorReport}`);
33834
33830
  static {
33835
33831
  this.ACTIVE_PROVIDER_NAMES = [
33836
33832
  "cryptocompare",
33837
- "coinbase",
33838
- "binance",
33839
33833
  "coinmarketcap",
33840
33834
  "coingecko"
33841
33835
  ];
33842
33836
  }
33843
33837
  static {
33844
- this.MIN_DISTINCT_PROVIDERS = 3;
33838
+ this.REQUIRED_PROVIDER_COUNT = 3;
33845
33839
  }
33846
33840
  /**
33847
33841
  * @param priceProvidersOrConfig - REQUIRED in production flows. An array of
33848
- * `{name, apiKey}` entries. Every provider needs an apiKey. Names are
33849
- * deduplicated so three entries with `name: "coingecko"` collapse to a
33850
- * single provider.
33842
+ * exactly 3 `{name, apiKey}` entries, one per locked provider. Every entry
33843
+ * needs an apiKey. Names are deduplicated so three entries with
33844
+ * `name: "coingecko"` collapse to a single provider — which then fails the
33845
+ * strict count check.
33851
33846
  * @param legacySources - Test-only back door. When supplied, the constructor
33852
33847
  * trusts the caller-supplied array verbatim and skips credential checks.
33853
- * This path is exercised exclusively by unit tests that inject in-process
33854
- * `fetchPrice` stubs.
33855
- * @param _mode - Ignored. Previously used to branch between dev / prod
33856
- * validation. The oracle no longer has a "dev" relaxation; the parameter
33857
- * is kept only for backward compatibility with existing call sites.
33848
+ * The strict count is still enforced (exactly 3).
33849
+ * @param _mode - Ignored. Retained for backward-compatible call sites.
33858
33850
  */
33859
33851
  constructor(priceProvidersOrConfig, legacySources, _mode) {
33860
33852
  if (legacySources && Array.isArray(legacySources)) {
@@ -33862,7 +33854,7 @@ ${errorReport}`);
33862
33854
  } else {
33863
33855
  if (!Array.isArray(priceProvidersOrConfig)) {
33864
33856
  throw new Error(
33865
- "Price oracle requires a priceProviders array \u2014 defaults and fallbacks have been removed. Pass 3 distinct {name, apiKey} entries from the supported set: " + _PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")
33857
+ `Price oracle requires a priceProviders array \u2014 defaults and fallbacks have been removed. Pass exactly ${_PriceOracleModule.REQUIRED_PROVIDER_COUNT} distinct {name, apiKey} entries from the locked set: ` + _PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")
33866
33858
  );
33867
33859
  }
33868
33860
  this.sources = this.buildSources(priceProvidersOrConfig);
@@ -33871,39 +33863,31 @@ ${errorReport}`);
33871
33863
  this.validateProviderCount();
33872
33864
  }
33873
33865
  /**
33874
- * Enforces the unconditional, mode-independent 3-provider rule.
33875
- *
33876
- * Every caller — mint, extend, withdraw, liquidate, payment, balance — must
33877
- * end up with at least {@link PriceOracleModule.MIN_DISTINCT_PROVIDERS}
33878
- * distinct sources. Any relaxation here re-opens the oracle-manipulation
33879
- * path flagged as H-5 in the audit.
33866
+ * Enforces strict 3-of-3. Any deviation re-opens the consensus-manipulation
33867
+ * path flagged as H-2 in the audit. There is no "≥3" or "3 of N" mode.
33880
33868
  */
33881
33869
  validateProviderCount() {
33882
- if (this.sources.length < _PriceOracleModule.MIN_DISTINCT_PROVIDERS) {
33870
+ if (this.sources.length !== _PriceOracleModule.REQUIRED_PROVIDER_COUNT) {
33883
33871
  throw new Error(
33884
- `Price oracle requires at least ${_PriceOracleModule.MIN_DISTINCT_PROVIDERS} eligible providers for consensus. Currently configured: ${this.sources.length} provider(s). Supported active providers: ${_PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")}`
33872
+ `Price oracle requires exactly ${_PriceOracleModule.REQUIRED_PROVIDER_COUNT} providers. Currently configured: ${this.sources.length} provider(s). Locked production set: ${_PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")}`
33885
33873
  );
33886
33874
  }
33887
33875
  }
33888
33876
  /**
33889
33877
  * Build price sources from the caller-supplied config.
33890
33878
  *
33891
- * Rules (all unconditional — there is no dev-mode relaxation):
33892
- * - Every entry must be a supported provider name.
33879
+ * Rules (all unconditional):
33880
+ * - Exactly 3 entries reject fewer and reject more.
33881
+ * - Every entry must be a supported provider name from the locked set.
33893
33882
  * - Every entry must carry an `apiKey`.
33894
- * - Duplicates by `name` are rejected outright. Three CoinGecko entries
33895
- * with different keys are still "one provider" from a risk standpoint
33896
- * and do not satisfy the distinct-source requirement.
33897
- * - The final set must contain at least 3 distinct providers.
33883
+ * - Duplicates by `name` are rejected outright.
33898
33884
  *
33899
- * Throws as soon as any rule is violated — silently dropping an invalid
33900
- * entry would let the caller think consensus was achieved while the oracle
33901
- * was actually running on a smaller / weaker pool.
33885
+ * Throws as soon as any rule is violated.
33902
33886
  */
33903
33887
  buildSources(priceProviders) {
33904
- if (priceProviders.length === 0) {
33888
+ if (priceProviders.length !== _PriceOracleModule.REQUIRED_PROVIDER_COUNT) {
33905
33889
  throw new Error(
33906
- "priceProviders must be a non-empty array of 3 distinct providers, each with an apiKey."
33890
+ `priceProviders must contain exactly ${_PriceOracleModule.REQUIRED_PROVIDER_COUNT} entries. Received: ${priceProviders.length}. Locked production set: ${_PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")}`
33907
33891
  );
33908
33892
  }
33909
33893
  const sources = [];
@@ -33916,35 +33900,16 @@ ${errorReport}`);
33916
33900
  const name = provider.name.toLowerCase();
33917
33901
  if (!_PriceOracleModule.ACTIVE_PROVIDER_NAMES.includes(name)) {
33918
33902
  throw new Error(
33919
- `Unsupported price provider "${provider.name}". Supported: ${_PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")}`
33903
+ `Unsupported price provider "${provider.name}". Locked production set: ${_PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")}`
33920
33904
  );
33921
33905
  }
33922
33906
  if (seen.has(name)) {
33923
33907
  throw new Error(
33924
- `Duplicate price provider "${name}" \u2014 the oracle requires 3 DISTINCT providers so a single upstream failure or manipulation cannot compromise consensus. Use 3 different provider names from: ${_PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")}`
33908
+ `Duplicate price provider "${name}" \u2014 the oracle requires ${_PriceOracleModule.REQUIRED_PROVIDER_COUNT} DISTINCT providers so a single upstream failure or manipulation cannot compromise consensus. Use ${_PriceOracleModule.REQUIRED_PROVIDER_COUNT} different provider names from: ${_PriceOracleModule.ACTIVE_PROVIDER_NAMES.join(", ")}`
33925
33909
  );
33926
33910
  }
33927
33911
  seen.add(name);
33928
33912
  switch (name) {
33929
- case "binance":
33930
- if (!provider.apiKey) {
33931
- throw new Error(
33932
- "Binance provider requires an apiKey"
33933
- );
33934
- }
33935
- sources.push(
33936
- this.createBinanceSource(
33937
- provider.apiKey,
33938
- priority++
33939
- )
33940
- );
33941
- break;
33942
- case "coinbase":
33943
- if (!provider.apiKey) {
33944
- throw new Error("Coinbase provider requires an apiKey");
33945
- }
33946
- sources.push(this.createCoinbaseSource(provider.apiKey, priority++));
33947
- break;
33948
33913
  case "cryptocompare":
33949
33914
  if (!provider.apiKey) {
33950
33915
  throw new Error("CryptoCompare provider requires an apiKey");
@@ -33975,12 +33940,7 @@ ${errorReport}`);
33975
33940
  throw new Error(`Unhandled provider: ${name}`);
33976
33941
  }
33977
33942
  }
33978
- if (sources.length < _PriceOracleModule.MIN_DISTINCT_PROVIDERS) {
33979
- throw new Error(
33980
- `Insufficient price providers: need at least ${_PriceOracleModule.MIN_DISTINCT_PROVIDERS} distinct entries, got ${sources.length}.`
33981
- );
33982
- }
33983
- return this.selectSampledSources(sources);
33943
+ return sources;
33984
33944
  }
33985
33945
  /**
33986
33946
  * Create CryptoCompare price source
@@ -34052,21 +34012,12 @@ ${errorReport}`);
34052
34012
  }
34053
34013
  };
34054
34014
  }
34055
- selectSampledSources(sources) {
34056
- return [...sources].sort((a, b2) => a.name.toLowerCase().localeCompare(b2.name.toLowerCase())).slice(0, 3).map((s, idx) => ({ ...s, priority: idx + 1 }));
34057
- }
34058
34015
  /**
34059
34016
  * Create CoinGecko price source.
34060
34017
  *
34061
34018
  * CoinGecko's public endpoint has no authentication, but we intentionally
34062
34019
  * require the caller to supply either a Demo (`x-cg-demo-api-key`) or Pro
34063
- * (`x-cg-pro-api-key`) key. Reasons:
34064
- * - An authenticated call has a predictable rate limit and per-key quota,
34065
- * so node-level retries won't silently drop under load.
34066
- * - The key identifies the Diamond Hands tenant, making ETL/abuse
34067
- * traceable and revokable.
34068
- * - It keeps the same "every provider needs a credential" invariant
34069
- * across all supported providers (removes a special case).
34020
+ * (`x-cg-pro-api-key`) key.
34070
34021
  */
34071
34022
  createCoinGeckoSource(apiKey, priority) {
34072
34023
  if (!apiKey) {
@@ -34092,59 +34043,6 @@ ${errorReport}`);
34092
34043
  priority
34093
34044
  };
34094
34045
  }
34095
- /**
34096
- * Create Binance price source. Requires apiKey.
34097
- *
34098
- * The public `/ticker/price` endpoint does not require a secret; only the
34099
- * API key is sent as `X-MBX-APIKEY` for per-key rate limiting and
34100
- * revokability.
34101
- */
34102
- createBinanceSource(apiKey, priority) {
34103
- if (!apiKey) {
34104
- throw new Error("createBinanceSource requires an apiKey");
34105
- }
34106
- const fetchJson = this.createFetchJson();
34107
- return {
34108
- name: "Binance",
34109
- fetchPrice: async () => {
34110
- const url = new URL("https://api.binance.com/api/v3/ticker/price");
34111
- url.searchParams.set("symbol", "BTCUSDT");
34112
- const data = await fetchJson(url.toString(), {
34113
- "X-MBX-APIKEY": apiKey
34114
- });
34115
- const price = Number(data?.price);
34116
- if (!Number.isFinite(price) || price <= 0) {
34117
- throw new Error("Invalid Binance price payload");
34118
- }
34119
- return price;
34120
- },
34121
- priority
34122
- };
34123
- }
34124
- /**
34125
- * Create Coinbase price source. Requires apiKey.
34126
- */
34127
- createCoinbaseSource(apiKey, priority) {
34128
- if (!apiKey) {
34129
- throw new Error("createCoinbaseSource requires an apiKey");
34130
- }
34131
- const fetchJson = this.createFetchJson();
34132
- return {
34133
- name: "Coinbase",
34134
- fetchPrice: async () => {
34135
- const data = await fetchJson(
34136
- "https://api.coinbase.com/v2/prices/BTC-USDT/spot",
34137
- { "CB-ACCESS-KEY": apiKey }
34138
- );
34139
- const price = Number(data?.data?.amount);
34140
- if (!Number.isFinite(price) || price <= 0) {
34141
- throw new Error("Invalid Coinbase price payload");
34142
- }
34143
- return price;
34144
- },
34145
- priority
34146
- };
34147
- }
34148
34046
  createCoinMarketCapSource(apiKey, priority) {
34149
34047
  const fetchJson = this.createFetchJson();
34150
34048
  return {
@@ -34169,17 +34067,21 @@ ${errorReport}`);
34169
34067
  };
34170
34068
  }
34171
34069
  /**
34172
- * Get BTC price in USD with 8 decimals
34070
+ * Get BTC price in USD with 8 decimals.
34173
34071
  *
34174
- * CRITICAL OPTIMIZATION: Queries all sources in parallel with Promise.race()
34175
- * All three providers must resolve and agree within 1% tolerance.
34176
- * Returns the median price.
34072
+ * Strict 3-of-3: queries all sources in parallel; if any one fails, the whole
34073
+ * call fails (no fallback). All three prices must lie within 1% of each other
34074
+ * (`(hi - lo) / lo <= 0.01`). Returns the median of the three.
34075
+ *
34076
+ * This is the only signed-price path in the codebase. The previously-exposed
34077
+ * `getBTCPriceConsensus()` (with outlier filtering + lenient survivor median)
34078
+ * was removed in the H-2 fix.
34177
34079
  */
34178
34080
  async getBTCPrice() {
34179
34081
  const startTime = Date.now();
34180
- if (this.sources.length !== 3) {
34082
+ if (this.sources.length !== _PriceOracleModule.REQUIRED_PROVIDER_COUNT) {
34181
34083
  throw new Error(
34182
- `Price oracle requires exactly 3 providers. Currently configured: ${this.sources.length}`
34084
+ `Price oracle requires exactly ${_PriceOracleModule.REQUIRED_PROVIDER_COUNT} providers. Currently configured: ${this.sources.length}`
34183
34085
  );
34184
34086
  }
34185
34087
  const GLOBAL_TIMEOUT_MS = 8e3;
@@ -34216,91 +34118,6 @@ ${errorReport}`);
34216
34118
  console.log(`[Price Oracle] Price with 8 decimals: ${priceWith8Decimals}`);
34217
34119
  return priceWith8Decimals;
34218
34120
  }
34219
- /**
34220
- * Consensus across multiple sources with outlier detection
34221
- * Returns median price from valid sources after filtering outliers
34222
- *
34223
- * Master's Wisdom: Two-Path Validation
34224
- * 1. If ONE source is outlier (>2% from median) → FILTER it, continue with remaining
34225
- * 2. If ALL sources too dispersed (>5% spread) → REJECT all, throw error
34226
- *
34227
- * Logic Flow:
34228
- * 1. Calculate initial median from all sources
34229
- * 2. Filter individual outliers (>2% from median)
34230
- * 3. If outliers found: remove them, require minimum 2 sources remaining
34231
- * 4. Recalculate median from valid sources only
34232
- * 5. Check if remaining sources are too dispersed (max/min ratio > 1.05)
34233
- * 6. Return final median or throw appropriate error
34234
- */
34235
- async getBTCPriceConsensus() {
34236
- console.log(`[Price Oracle] Fetching BTC price with consensus...`);
34237
- const OUTLIER_DEVIATION = PRICE_ORACLE_OUTLIER_DEVIATION_THRESHOLD;
34238
- const DISPERSION_THRESHOLD = PRICE_ORACLE_DISPERSION_THRESHOLD;
34239
- const results = await Promise.allSettled(
34240
- this.sources.map(async (source) => {
34241
- const price = await source.fetchPrice();
34242
- return { source: source.name, price };
34243
- })
34244
- );
34245
- const successful = results.filter((r) => r.status === "fulfilled").map((r) => r.value);
34246
- if (successful.length === 0) {
34247
- throw new Error("No price sources returned data");
34248
- }
34249
- console.log(
34250
- `[Price Oracle] Got prices from ${successful.length}/${this.sources.length} sources:`
34251
- );
34252
- successful.forEach((s) => {
34253
- console.log(` ${s.source}: $${s.price.toLocaleString()}`);
34254
- });
34255
- const prices = successful.map((s) => s.price);
34256
- prices.sort((a, b2) => a - b2);
34257
- const initialMedian = prices[Math.floor(prices.length / 2)];
34258
- const minPrice = prices[0];
34259
- const maxPrice = prices[prices.length - 1];
34260
- const dispersionRatio = maxPrice / minPrice;
34261
- const validPrices = successful.filter((s) => {
34262
- const deviation = Math.abs(s.price - initialMedian) / initialMedian;
34263
- return deviation <= OUTLIER_DEVIATION;
34264
- });
34265
- if (dispersionRatio > 1 + DISPERSION_THRESHOLD && validPrices.length === successful.length) {
34266
- throw new Error(
34267
- `Price consensus failed: sources too dispersed (${((dispersionRatio - 1) * 100).toFixed(1)}% spread)`
34268
- );
34269
- }
34270
- if (validPrices.length < successful.length) {
34271
- const outliers = successful.filter(
34272
- (s) => !validPrices.find((v) => v.source === s.source)
34273
- );
34274
- console.log(`[Price Oracle] \u26A0\uFE0F Detected ${outliers.length} outlier(s):`);
34275
- outliers.forEach((o) => {
34276
- const deviation = Math.abs(o.price - initialMedian) / initialMedian;
34277
- console.log(
34278
- ` ${o.source}: $${o.price.toLocaleString()} (${(deviation * 100).toFixed(1)}% deviation)`
34279
- );
34280
- });
34281
- if (validPrices.length < 2) {
34282
- throw new Error(
34283
- "Price consensus failed: insufficient valid sources after outlier removal"
34284
- );
34285
- }
34286
- console.log(
34287
- `[Price Oracle] \u2705 Outliers filtered, continuing with ${validPrices.length} valid sources`
34288
- );
34289
- const validPricesOnly = validPrices.map((v) => v.price);
34290
- validPricesOnly.sort((a, b2) => a - b2);
34291
- const finalMedian = validPricesOnly[Math.floor(validPricesOnly.length / 2)];
34292
- console.log(
34293
- `[Price Oracle] \u2705 Consensus price (median): $${finalMedian.toLocaleString()}`
34294
- );
34295
- const priceCents2 = Math.round(finalMedian * 100);
34296
- return BigInt(priceCents2) * 1000000n;
34297
- }
34298
- console.log(
34299
- `[Price Oracle] \u2705 Consensus price (median): $${initialMedian.toLocaleString()}`
34300
- );
34301
- const priceCents = Math.round(initialMedian * 100);
34302
- return BigInt(priceCents) * 1000000n;
34303
- }
34304
34121
  };
34305
34122
  var VaultBalanceModule = class {
34306
34123
  constructor(config) {
@@ -34706,30 +34523,16 @@ ${errorReport}`);
34706
34523
  const oracle = params?.customSources ? new PriceOracleModule({}, params.customSources, params?.mode) : new PriceOracleModule(params?.priceProviders, void 0, params?.mode);
34707
34524
  return await oracle.getBTCPrice();
34708
34525
  }
34709
- async function executePriceOracleConsensus(params) {
34710
- global.Lit = {
34711
- Actions: {
34712
- broadcastAndCollect: async ({
34713
- name,
34714
- value
34715
- }) => {
34716
- return [value];
34717
- }
34718
- }
34719
- };
34720
- const oracle = params?.customSources ? new PriceOracleModule({}, params.customSources, params?.mode) : new PriceOracleModule(params?.priceProviders, void 0, params?.mode);
34721
- return await oracle.getBTCPriceConsensus();
34722
- }
34723
34526
  var NOLA_EXECUTORS = {
34724
34527
  /**
34725
34528
  * Vault Snapshot Executor
34726
- *
34529
+ *
34727
34530
  * Returns complete position health metrics:
34728
34531
  * - BTC balance (total, authorized, available)
34729
34532
  * - Collateral ratio and liquidation risk
34730
34533
  * - Term status (duration, expiry, grace period)
34731
34534
  * - Protocol parameters (fees, thresholds)
34732
- *
34535
+ *
34733
34536
  * Cost: FREE (no LIT Action execution)
34734
34537
  * Same data as LIT Action would return
34735
34538
  */
@@ -34741,39 +34544,20 @@ ${errorReport}`);
34741
34544
  },
34742
34545
  /**
34743
34546
  * Price Oracle Executor
34744
- *
34745
- * Returns current BTC price in USD with 8 decimals:
34746
- * - Queries CoinGecko, Binance, Coinbase in parallel
34747
- * - First successful response wins (fastest path)
34748
- * - Automatic fallback if primary source fails
34749
- * - Same price format as LIT Action validator
34750
- *
34547
+ *
34548
+ * Returns BTC price in USD (8 decimals) via strict 3-of-3 consensus:
34549
+ * - All 3 configured providers must respond
34550
+ * - Prices must agree within 1%
34551
+ * - Returns the median
34552
+ *
34751
34553
  * Cost: FREE (no LIT Action execution)
34752
34554
  * Use for: Price display, mint preview, collateral ratio calculation
34753
34555
  */
34754
34556
  priceOracle: {
34755
34557
  name: "price-oracle",
34756
- description: "Get current BTC price (fastest source)",
34558
+ description: "Get current BTC price (strict 3-of-3 consensus)",
34757
34559
  executor: executePriceOracle,
34758
- version: "1.0.0"
34759
- },
34760
- /**
34761
- * Price Oracle Consensus Executor
34762
- *
34763
- * Returns BTC price using multi-source consensus:
34764
- * - Queries ALL configured sources
34765
- * - Filters outliers (>2% deviation from median)
34766
- * - Returns median of valid sources
34767
- * - Rejects if sources too dispersed (>5% spread)
34768
- *
34769
- * Cost: FREE (no LIT Action execution)
34770
- * Use for: High-stakes operations requiring price validation
34771
- */
34772
- priceOracleConsensus: {
34773
- name: "price-oracle-consensus",
34774
- description: "Get BTC price with multi-source consensus",
34775
- executor: executePriceOracleConsensus,
34776
- version: "1.0.0"
34560
+ version: "2.0.0"
34777
34561
  }
34778
34562
  };
34779
34563
  }
@@ -112396,16 +112180,17 @@ var BitcoinOperations = class {
112396
112180
  return { verified: false, reason: "not yet visible after retries" };
112397
112181
  }
112398
112182
  /**
112399
- * Get current BTC price using LIT Protocol price oracle
112183
+ * Get current BTC price using LIT Protocol price oracle.
112400
112184
  *
112401
- * Queries the decentralized price oracle via LIT Actions.
112402
- * Supports fast mode (single source) and full mode (consensus).
112185
+ * Strict 3-of-3: all three configured providers must respond within 1% of
112186
+ * each other, and the median is returned. The previous `mode: "fast" | "full"`
112187
+ * parameter (with single-source and lenient-consensus variants) was removed
112188
+ * in the H-2 audit fix — there is only one strict path now.
112403
112189
  *
112404
- * @param mode - Price fetch mode: "fast" (single source) or "full" (consensus)
112405
112190
  * @param sign - Whether to request PKP signature on the price
112406
112191
  * @returns BTC price result with timestamp and source
112407
112192
  */
112408
- async getPrice(mode = "fast", sign = false) {
112193
+ async getPrice(sign = false) {
112409
112194
  if (!this.litOps) {
112410
112195
  return failure(
112411
112196
  new SDKError({
@@ -112420,13 +112205,11 @@ var BitcoinOperations = class {
112420
112205
  async () => {
112421
112206
  if (this.config.debug) {
112422
112207
  log.info("\u{1F4B0} Fetching BTC price via LIT Protocol oracle", {
112423
- mode,
112424
112208
  sign,
112425
112209
  hasSigner: !!this.config.signer
112426
112210
  });
112427
112211
  }
112428
112212
  const result = await this.litOps.getBTCPrice({
112429
- mode,
112430
112213
  sign,
112431
112214
  signer: this.config.signer,
112432
112215
  pkpId: this.config.priceOraclePkpId,
@@ -112464,7 +112247,6 @@ var BitcoinOperations = class {
112464
112247
  try {
112465
112248
  const litOpsConfig = this.litOps?.getConfig?.() || {};
112466
112249
  log.error("\u274C BTC price oracle failed", {
112467
- mode,
112468
112250
  sign,
112469
112251
  errorMessage: error2 instanceof Error ? error2.message : String(error2),
112470
112252
  errorStack: error2 instanceof Error ? error2.stack : void 0,
@@ -112481,7 +112263,6 @@ var BitcoinOperations = class {
112481
112263
  severity: "MEDIUM" /* MEDIUM */,
112482
112264
  originalError: error2 instanceof Error ? error2 : new Error(String(error2)),
112483
112265
  context: {
112484
- mode,
112485
112266
  sign,
112486
112267
  serviceEndpoint: this.litOps?.getConfig?.()?.serviceEndpoint,
112487
112268
  network: this.litOps?.getConfig?.()?.network
@@ -122848,7 +122629,7 @@ Error data: ${errorData || "none"}`
122848
122629
  source: json.data.source
122849
122630
  };
122850
122631
  }
122851
- const result = await this.bitcoinOperations.getPrice("fast", false);
122632
+ const result = await this.bitcoinOperations.getPrice(false);
122852
122633
  if (!result.success) {
122853
122634
  const cause = result.error?.originalError?.message ?? String(result.error);
122854
122635
  throw new Error(`Failed to get BTC price: ${cause}`);