@gvnrdao/dh-sdk 0.0.269 → 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/browser/dist/browser.js +1 -1
- package/dist/index.js +89 -332
- package/dist/index.mjs +89 -332
- package/dist/modules/bitcoin/bitcoin-operations.module.d.ts +8 -6
- package/dist/server.js +1 -1
- package/dist/server.mjs +1 -1
- package/package.json +3 -3
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: "
|
|
31394
|
+
cid: "QmWZJpS3Q25XKo9ptzVcYz7pnW5hbqhuSvrhu7Qo7EcxEk",
|
|
31396
31395
|
authorizedCidHex: cidToHex(
|
|
31397
|
-
"
|
|
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:
|
|
31404
|
-
size:
|
|
31405
|
-
hash: "
|
|
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: "
|
|
31412
|
+
cid: "QmRZjMcJzEAzepwN3uJBbgGxMPULvCw6LMpQ94w19sv3Cx",
|
|
31414
31413
|
authorizedCidHex: cidToHex(
|
|
31415
|
-
"
|
|
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:
|
|
31422
|
-
size:
|
|
31423
|
-
hash: "
|
|
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: "
|
|
31430
|
+
cid: "Qmb4y62Ftjar5EXcREyXC84U7QEMhCQgycHYCmJxLichvt",
|
|
31432
31431
|
authorizedCidHex: cidToHex(
|
|
31433
|
-
"
|
|
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:
|
|
31440
|
-
size:
|
|
31441
|
-
hash: "
|
|
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: "
|
|
31448
|
+
cid: "QmetrNkAUQ54PHzHLRR7TfDk3oGKnCf22m2bQwj24eB253",
|
|
31450
31449
|
authorizedCidHex: cidToHex(
|
|
31451
|
-
"
|
|
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:
|
|
31458
|
-
size:
|
|
31459
|
-
hash: "
|
|
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: "
|
|
31466
|
+
cid: "QmRuLKJmsD8yN6Ez89L9mzSM3zyarjGwFMBwn23CkajizZ",
|
|
31468
31467
|
authorizedCidHex: cidToHex(
|
|
31469
|
-
"
|
|
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:
|
|
31476
|
-
size:
|
|
31477
|
-
hash: "
|
|
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: "
|
|
31484
|
+
cid: "QmR5mjqhxfEPuBMbxhcXkJpdAMDzYfkpUWPgcPNCiSuhqh",
|
|
31486
31485
|
authorizedCidHex: cidToHex(
|
|
31487
|
-
"
|
|
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:
|
|
31494
|
-
size:
|
|
31495
|
-
hash: "
|
|
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: "
|
|
31502
|
+
cid: "QmbXoFbhtqWsgKkLxtxwd6fDuKvvBpPhpMmdqUU1UC9GMn",
|
|
31504
31503
|
authorizedCidHex: cidToHex(
|
|
31505
|
-
"
|
|
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:
|
|
31512
|
-
size:
|
|
31513
|
-
hash: "
|
|
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
|
|
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.
|
|
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.
|
|
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.,
|
|
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.
|
|
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
|
|
33849
|
-
* deduplicated so three entries with
|
|
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
|
-
*
|
|
33854
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
|
33870
|
+
if (this.sources.length !== _PriceOracleModule.REQUIRED_PROVIDER_COUNT) {
|
|
33883
33871
|
throw new Error(
|
|
33884
|
-
`Price oracle requires
|
|
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
|
|
33892
|
-
* -
|
|
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.
|
|
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
|
|
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
|
|
33888
|
+
if (priceProviders.length !== _PriceOracleModule.REQUIRED_PROVIDER_COUNT) {
|
|
33905
33889
|
throw new Error(
|
|
33906
|
-
|
|
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}".
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
34071
|
+
*
|
|
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.
|
|
34173
34075
|
*
|
|
34174
|
-
*
|
|
34175
|
-
*
|
|
34176
|
-
*
|
|
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 !==
|
|
34082
|
+
if (this.sources.length !== _PriceOracleModule.REQUIRED_PROVIDER_COUNT) {
|
|
34181
34083
|
throw new Error(
|
|
34182
|
-
`Price oracle requires exactly
|
|
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
|
|
34746
|
-
* -
|
|
34747
|
-
* -
|
|
34748
|
-
* -
|
|
34749
|
-
*
|
|
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 (
|
|
34558
|
+
description: "Get current BTC price (strict 3-of-3 consensus)",
|
|
34757
34559
|
executor: executePriceOracle,
|
|
34758
|
-
version: "
|
|
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
|
}
|
|
@@ -110387,30 +110171,6 @@ var LoanCreator = class {
|
|
|
110387
110171
|
`\u2705 Using btc-transaction-signer authorizedCidHex for certification (on-chain v${this.config.loanCreationValidatorVersion} getCid): ${certificationCid}`
|
|
110388
110172
|
);
|
|
110389
110173
|
}
|
|
110390
|
-
const litAny = this.config.litOps;
|
|
110391
|
-
if (litAny.config && isServiceMode) {
|
|
110392
|
-
litAny.config.validatorVersion = this.config.loanCreationValidatorVersion;
|
|
110393
|
-
if (this.config.ethRpcUrl) {
|
|
110394
|
-
litAny.config.ethRpcUrl = this.config.ethRpcUrl;
|
|
110395
|
-
}
|
|
110396
|
-
}
|
|
110397
|
-
if (certificationCid && isServiceMode) {
|
|
110398
|
-
if (typeof this.config.litOps.updateCertificationCid === "function") {
|
|
110399
|
-
this.config.litOps.updateCertificationCid(certificationCid);
|
|
110400
|
-
if (this.config.debug) {
|
|
110401
|
-
log.info(
|
|
110402
|
-
`\u2705 Stored certificationCid in LitOps for validation: ${certificationCid}`
|
|
110403
|
-
);
|
|
110404
|
-
}
|
|
110405
|
-
} else {
|
|
110406
|
-
this.config.litOps._certificationCid = certificationCid;
|
|
110407
|
-
if (this.config.debug) {
|
|
110408
|
-
log.info(
|
|
110409
|
-
`\u26A0\uFE0F LitOps.updateCertificationCid not available; stored _certificationCid fallback`
|
|
110410
|
-
);
|
|
110411
|
-
}
|
|
110412
|
-
}
|
|
110413
|
-
}
|
|
110414
110174
|
if (!isServiceMode && !this.config.litOpsSigner) {
|
|
110415
110175
|
return failure(
|
|
110416
110176
|
new SDKError({
|
|
@@ -112420,16 +112180,17 @@ var BitcoinOperations = class {
|
|
|
112420
112180
|
return { verified: false, reason: "not yet visible after retries" };
|
|
112421
112181
|
}
|
|
112422
112182
|
/**
|
|
112423
|
-
* Get current BTC price using LIT Protocol price oracle
|
|
112183
|
+
* Get current BTC price using LIT Protocol price oracle.
|
|
112424
112184
|
*
|
|
112425
|
-
*
|
|
112426
|
-
*
|
|
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.
|
|
112427
112189
|
*
|
|
112428
|
-
* @param mode - Price fetch mode: "fast" (single source) or "full" (consensus)
|
|
112429
112190
|
* @param sign - Whether to request PKP signature on the price
|
|
112430
112191
|
* @returns BTC price result with timestamp and source
|
|
112431
112192
|
*/
|
|
112432
|
-
async getPrice(
|
|
112193
|
+
async getPrice(sign = false) {
|
|
112433
112194
|
if (!this.litOps) {
|
|
112434
112195
|
return failure(
|
|
112435
112196
|
new SDKError({
|
|
@@ -112444,13 +112205,11 @@ var BitcoinOperations = class {
|
|
|
112444
112205
|
async () => {
|
|
112445
112206
|
if (this.config.debug) {
|
|
112446
112207
|
log.info("\u{1F4B0} Fetching BTC price via LIT Protocol oracle", {
|
|
112447
|
-
mode,
|
|
112448
112208
|
sign,
|
|
112449
112209
|
hasSigner: !!this.config.signer
|
|
112450
112210
|
});
|
|
112451
112211
|
}
|
|
112452
112212
|
const result = await this.litOps.getBTCPrice({
|
|
112453
|
-
mode,
|
|
112454
112213
|
sign,
|
|
112455
112214
|
signer: this.config.signer,
|
|
112456
112215
|
pkpId: this.config.priceOraclePkpId,
|
|
@@ -112488,7 +112247,6 @@ var BitcoinOperations = class {
|
|
|
112488
112247
|
try {
|
|
112489
112248
|
const litOpsConfig = this.litOps?.getConfig?.() || {};
|
|
112490
112249
|
log.error("\u274C BTC price oracle failed", {
|
|
112491
|
-
mode,
|
|
112492
112250
|
sign,
|
|
112493
112251
|
errorMessage: error2 instanceof Error ? error2.message : String(error2),
|
|
112494
112252
|
errorStack: error2 instanceof Error ? error2.stack : void 0,
|
|
@@ -112505,7 +112263,6 @@ var BitcoinOperations = class {
|
|
|
112505
112263
|
severity: "MEDIUM" /* MEDIUM */,
|
|
112506
112264
|
originalError: error2 instanceof Error ? error2 : new Error(String(error2)),
|
|
112507
112265
|
context: {
|
|
112508
|
-
mode,
|
|
112509
112266
|
sign,
|
|
112510
112267
|
serviceEndpoint: this.litOps?.getConfig?.()?.serviceEndpoint,
|
|
112511
112268
|
network: this.litOps?.getConfig?.()?.network
|
|
@@ -122872,7 +122629,7 @@ Error data: ${errorData || "none"}`
|
|
|
122872
122629
|
source: json.data.source
|
|
122873
122630
|
};
|
|
122874
122631
|
}
|
|
122875
|
-
const result = await this.bitcoinOperations.getPrice(
|
|
122632
|
+
const result = await this.bitcoinOperations.getPrice(false);
|
|
122876
122633
|
if (!result.success) {
|
|
122877
122634
|
const cause = result.error?.originalError?.message ?? String(result.error);
|
|
122878
122635
|
throw new Error(`Failed to get BTC price: ${cause}`);
|