@gvnrdao/dh-sdk 0.0.293 → 0.0.295
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/833.browser.js +2 -0
- package/browser/dist/833.browser.js.LICENSE.txt +1 -0
- package/browser/dist/browser.js +1 -1
- package/dist/index.js +505 -173
- package/dist/index.mjs +505 -173
- package/dist/modules/bitcoin/bitcoin-operations.module.d.ts +2 -10
- package/dist/modules/cache/cache-manager.module.d.ts +208 -41
- package/dist/modules/diamond-hands-sdk.d.ts +20 -5
- package/dist/modules/loan/loan-query.module.d.ts +1 -5
- package/dist/modules/pkp/pkp-manager.module.d.ts +1 -5
- package/dist/utils/quantum-timing.d.ts +68 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -3750,7 +3750,7 @@ var require_abstract_coder = __commonJS({
|
|
|
3750
3750
|
function toObject2(names2, items, deep) {
|
|
3751
3751
|
if (names2.indexOf(null) >= 0) {
|
|
3752
3752
|
return items.map((item, index) => {
|
|
3753
|
-
if (item instanceof
|
|
3753
|
+
if (item instanceof Result11) {
|
|
3754
3754
|
return toObject2(getNames2(item), item, deep);
|
|
3755
3755
|
}
|
|
3756
3756
|
return item;
|
|
@@ -3759,7 +3759,7 @@ var require_abstract_coder = __commonJS({
|
|
|
3759
3759
|
return names2.reduce((accum, name, index) => {
|
|
3760
3760
|
let item = items.getValue(name);
|
|
3761
3761
|
if (!(name in accum)) {
|
|
3762
|
-
if (deep && item instanceof
|
|
3762
|
+
if (deep && item instanceof Result11) {
|
|
3763
3763
|
item = toObject2(getNames2(item), item, deep);
|
|
3764
3764
|
}
|
|
3765
3765
|
accum[name] = item;
|
|
@@ -3767,7 +3767,7 @@ var require_abstract_coder = __commonJS({
|
|
|
3767
3767
|
return accum;
|
|
3768
3768
|
}, {});
|
|
3769
3769
|
}
|
|
3770
|
-
var
|
|
3770
|
+
var Result11 = class _Result extends Array {
|
|
3771
3771
|
// No longer used; but cannot be removed as it will remove the
|
|
3772
3772
|
// #private field from the .d.ts which may break backwards
|
|
3773
3773
|
// compatibility
|
|
@@ -3971,7 +3971,7 @@ var require_abstract_coder = __commonJS({
|
|
|
3971
3971
|
return new _Result(_guard5, items, keys);
|
|
3972
3972
|
}
|
|
3973
3973
|
};
|
|
3974
|
-
exports2.Result =
|
|
3974
|
+
exports2.Result = Result11;
|
|
3975
3975
|
function checkResultErrors2(result) {
|
|
3976
3976
|
const errors2 = [];
|
|
3977
3977
|
const checkErrors = function(path2, object2) {
|
|
@@ -32409,8 +32409,8 @@ ${errorReport}`);
|
|
|
32409
32409
|
var UTXO_QUERY_MAX_RETRIES = 3;
|
|
32410
32410
|
var UTXO_QUERY_RETRY_DELAY_MS = 500;
|
|
32411
32411
|
var QUANTUM_WINDOW_SECONDS2 = 60;
|
|
32412
|
-
var
|
|
32413
|
-
var SAFE_EXECUTION_WINDOW_SECONDS = QUANTUM_WINDOW_SECONDS2 -
|
|
32412
|
+
var DEAD_ZONE_SECONDS2 = 16;
|
|
32413
|
+
var SAFE_EXECUTION_WINDOW_SECONDS = QUANTUM_WINDOW_SECONDS2 - DEAD_ZONE_SECONDS2;
|
|
32414
32414
|
var SECONDS_PER_DAY = 86400;
|
|
32415
32415
|
var DAYS_PER_MONTH = 30;
|
|
32416
32416
|
var LIT_ACTION_ETH_RPC_TIMEOUT_MS = 8e3;
|
|
@@ -34949,8 +34949,8 @@ function getMainnetConfig() {
|
|
|
34949
34949
|
bitcoinWithdrawalAddressRegistry: MAINNET_CONTRACTS.BitcoinWithdrawalAddressRegistry || ""
|
|
34950
34950
|
},
|
|
34951
34951
|
subgraphs: {
|
|
34952
|
-
diamondHandsUrl: "https://
|
|
34953
|
-
//
|
|
34952
|
+
diamondHandsUrl: "https://gateway-arbitrum.network.thegraph.com/api/subgraphs/id/CCTPsdYqco2jChDLLBQTbdJWwoukVoMt1cXeR9ti6r9A"
|
|
34953
|
+
// Published Sepolia subgraph on Arbitrum One
|
|
34954
34954
|
},
|
|
34955
34955
|
litNetwork: "chipotle",
|
|
34956
34956
|
debug: false
|
|
@@ -108002,8 +108002,11 @@ async function resolveEip1559FeeFields(provider) {
|
|
|
108002
108002
|
let maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? void 0;
|
|
108003
108003
|
if (!maxFeePerGas || !maxPriorityFeePerGas) {
|
|
108004
108004
|
const gasPrice = (await provider.getFeeData()).gasPrice ?? parseUnits("1", "gwei");
|
|
108005
|
-
maxFeePerGas = maxFeePerGas
|
|
108006
|
-
maxPriorityFeePerGas = maxPriorityFeePerGas
|
|
108005
|
+
maxFeePerGas = maxFeePerGas || gasPrice * 2n;
|
|
108006
|
+
maxPriorityFeePerGas = maxPriorityFeePerGas || parseUnits("1.5", "gwei");
|
|
108007
|
+
}
|
|
108008
|
+
if (maxFeePerGas < maxPriorityFeePerGas) {
|
|
108009
|
+
maxFeePerGas = maxPriorityFeePerGas;
|
|
108007
108010
|
}
|
|
108008
108011
|
return { maxFeePerGas, maxPriorityFeePerGas };
|
|
108009
108012
|
}
|
|
@@ -108108,6 +108111,9 @@ function validateSDKConfig(config) {
|
|
|
108108
108111
|
|
|
108109
108112
|
// src/utils/quantum-timing.ts
|
|
108110
108113
|
var QUANTUM_WINDOW_SECONDS = 60;
|
|
108114
|
+
var DEAD_ZONE_SECONDS = 8;
|
|
108115
|
+
var INCLUSION_LATENCY_BUDGET = 16;
|
|
108116
|
+
var POST_BOUNDARY_SKEW_MARGIN = 3;
|
|
108111
108117
|
function calculateNextQuantumTimestamp() {
|
|
108112
108118
|
const now = Math.floor(Date.now() / 1e3);
|
|
108113
108119
|
const currentQuantum = Math.floor(now / QUANTUM_WINDOW_SECONDS) * QUANTUM_WINDOW_SECONDS;
|
|
@@ -108136,6 +108142,27 @@ function validateQuantumTiming(signedTimestamp, _bufferSeconds = 30) {
|
|
|
108136
108142
|
console.log(" Current quantum:", currentQuantum);
|
|
108137
108143
|
console.log(" Valid window: PAST/CURRENT/NEXT (180s total)");
|
|
108138
108144
|
}
|
|
108145
|
+
async function awaitSafeSubmissionWindow(quantumTimestamp, opts = {}) {
|
|
108146
|
+
const now = opts.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
108147
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
108148
|
+
const nowSec = now();
|
|
108149
|
+
const signatureQuantum = Math.floor(quantumTimestamp / QUANTUM_WINDOW_SECONDS) * QUANTUM_WINDOW_SECONDS;
|
|
108150
|
+
const currentQuantum = Math.floor(nowSec / QUANTUM_WINDOW_SECONDS) * QUANTUM_WINDOW_SECONDS;
|
|
108151
|
+
const secsToBoundary = QUANTUM_WINDOW_SECONDS - nowSec % QUANTUM_WINDOW_SECONDS;
|
|
108152
|
+
const isNextQuantumSig = signatureQuantum === currentQuantum + QUANTUM_WINDOW_SECONDS;
|
|
108153
|
+
if (isNextQuantumSig && secsToBoundary <= DEAD_ZONE_SECONDS + INCLUSION_LATENCY_BUDGET) {
|
|
108154
|
+
const target = currentQuantum + QUANTUM_WINDOW_SECONDS + POST_BOUNDARY_SKEW_MARGIN;
|
|
108155
|
+
const waitSeconds = target - nowSec;
|
|
108156
|
+
if (waitSeconds > 0) {
|
|
108157
|
+
console.log(
|
|
108158
|
+
`[Quantum Timing] \u23F3 Deferring send ${waitSeconds}s to clear the quantum dead zone (sig quantum ${signatureQuantum}, current ${currentQuantum}, ${secsToBoundary}s to boundary)`
|
|
108159
|
+
);
|
|
108160
|
+
await sleep(waitSeconds * 1e3);
|
|
108161
|
+
return { waited: true, waitedSeconds: waitSeconds };
|
|
108162
|
+
}
|
|
108163
|
+
}
|
|
108164
|
+
return { waited: false, waitedSeconds: 0 };
|
|
108165
|
+
}
|
|
108139
108166
|
|
|
108140
108167
|
// src/utils/mint-authorization.utils.ts
|
|
108141
108168
|
var PKP_NFT_ABI = [
|
|
@@ -109745,106 +109772,365 @@ function createContractManager(config) {
|
|
|
109745
109772
|
}
|
|
109746
109773
|
|
|
109747
109774
|
// src/modules/cache/cache-manager.module.ts
|
|
109748
|
-
var
|
|
109749
|
-
cache
|
|
109775
|
+
var LRUCache = class {
|
|
109776
|
+
cache;
|
|
109777
|
+
/**
|
|
109778
|
+
* Audit M-J: singleflight registry for `getOrCompute` / `getOrComputeResult`.
|
|
109779
|
+
* Concurrent cache-miss callers for the same key share one inflight promise
|
|
109780
|
+
* instead of each running `compute()` independently — important when the
|
|
109781
|
+
* compute spends a paid LIT capacity credit or hits a rate-limited upstream.
|
|
109782
|
+
*/
|
|
109783
|
+
inflight = /* @__PURE__ */ new Map();
|
|
109784
|
+
inflightResult = /* @__PURE__ */ new Map();
|
|
109750
109785
|
maxSize;
|
|
109751
109786
|
ttlMs;
|
|
109752
|
-
|
|
109753
|
-
|
|
109754
|
-
|
|
109787
|
+
debug;
|
|
109788
|
+
name;
|
|
109789
|
+
// Statistics
|
|
109790
|
+
stats = {
|
|
109791
|
+
hits: 0,
|
|
109792
|
+
misses: 0,
|
|
109793
|
+
evictions: 0
|
|
109794
|
+
};
|
|
109795
|
+
constructor(config = {}) {
|
|
109796
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
109797
|
+
this.maxSize = config.maxSize || 1e3;
|
|
109798
|
+
this.ttlMs = config.ttlMs || 6e4;
|
|
109799
|
+
this.debug = config.debug || false;
|
|
109800
|
+
this.name = config.name || "Cache";
|
|
109801
|
+
if (this.debug) {
|
|
109802
|
+
console.log(
|
|
109803
|
+
`\u{1F4BE} [${this.name}] Initialized: maxSize=${this.maxSize}, ttl=${this.ttlMs}ms`
|
|
109804
|
+
);
|
|
109805
|
+
}
|
|
109755
109806
|
}
|
|
109756
109807
|
/**
|
|
109757
109808
|
* Get value from cache
|
|
109809
|
+
*
|
|
109810
|
+
* Returns null if:
|
|
109811
|
+
* - Key not found
|
|
109812
|
+
* - Entry has expired
|
|
109813
|
+
*
|
|
109814
|
+
* @param key - Cache key
|
|
109815
|
+
* @returns Cached value or null
|
|
109758
109816
|
*/
|
|
109759
109817
|
get(key) {
|
|
109760
109818
|
const entry = this.cache.get(key);
|
|
109761
109819
|
if (!entry) {
|
|
109762
|
-
|
|
109820
|
+
this.stats.misses++;
|
|
109821
|
+
if (this.debug) {
|
|
109822
|
+
console.log(`\u274C [${this.name}] Cache MISS: ${String(key)}`);
|
|
109823
|
+
}
|
|
109824
|
+
return null;
|
|
109763
109825
|
}
|
|
109764
|
-
|
|
109765
|
-
if (now - entry.timestamp > entry.ttl) {
|
|
109826
|
+
if (this.isExpired(entry)) {
|
|
109766
109827
|
this.cache.delete(key);
|
|
109767
|
-
|
|
109828
|
+
this.stats.misses++;
|
|
109829
|
+
if (this.debug) {
|
|
109830
|
+
const age = Date.now() - entry.timestamp;
|
|
109831
|
+
console.log(`\u23F0 [${this.name}] Cache EXPIRED: ${String(key)} (age: ${age}ms)`);
|
|
109832
|
+
}
|
|
109833
|
+
return null;
|
|
109834
|
+
}
|
|
109835
|
+
entry.hits++;
|
|
109836
|
+
entry.lastAccessed = Date.now();
|
|
109837
|
+
this.cache.set(key, entry);
|
|
109838
|
+
this.stats.hits++;
|
|
109839
|
+
if (this.debug) {
|
|
109840
|
+
const age = Date.now() - entry.timestamp;
|
|
109841
|
+
console.log(
|
|
109842
|
+
`\u2705 [${this.name}] Cache HIT: ${String(key)} (age: ${age}ms, hits: ${entry.hits})`
|
|
109843
|
+
);
|
|
109768
109844
|
}
|
|
109769
109845
|
return entry.value;
|
|
109770
109846
|
}
|
|
109847
|
+
/**
|
|
109848
|
+
* Get value from cache with Result wrapper
|
|
109849
|
+
*
|
|
109850
|
+
* Useful when you want to distinguish between "not found" and "expired"
|
|
109851
|
+
*/
|
|
109852
|
+
getResult(key) {
|
|
109853
|
+
const value = this.get(key);
|
|
109854
|
+
if (value === null) {
|
|
109855
|
+
return failure(
|
|
109856
|
+
new SDKError({
|
|
109857
|
+
message: `Cache miss for key: ${String(key)}`,
|
|
109858
|
+
category: "CACHE" /* CACHE */,
|
|
109859
|
+
severity: "LOW" /* LOW */,
|
|
109860
|
+
originalError: new Error("Cache miss")
|
|
109861
|
+
})
|
|
109862
|
+
);
|
|
109863
|
+
}
|
|
109864
|
+
return success(value);
|
|
109865
|
+
}
|
|
109771
109866
|
/**
|
|
109772
109867
|
* Set value in cache
|
|
109868
|
+
*
|
|
109869
|
+
* If cache is full, evicts the least recently used entry
|
|
109870
|
+
*
|
|
109871
|
+
* @param key - Cache key
|
|
109872
|
+
* @param value - Value to cache
|
|
109873
|
+
* @param ttl - Optional custom TTL for this entry (ms)
|
|
109773
109874
|
*/
|
|
109774
109875
|
set(key, value, ttl) {
|
|
109775
109876
|
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
109776
|
-
|
|
109777
|
-
if (firstKey) {
|
|
109778
|
-
this.cache.delete(firstKey);
|
|
109779
|
-
}
|
|
109877
|
+
this.evictLRU();
|
|
109780
109878
|
}
|
|
109781
|
-
|
|
109879
|
+
const entry = {
|
|
109782
109880
|
value,
|
|
109783
109881
|
timestamp: Date.now(),
|
|
109784
|
-
|
|
109785
|
-
|
|
109882
|
+
hits: 0,
|
|
109883
|
+
lastAccessed: Date.now()
|
|
109884
|
+
};
|
|
109885
|
+
this.cache.set(key, entry);
|
|
109886
|
+
if (this.debug) {
|
|
109887
|
+
const effectiveTtl = ttl || this.ttlMs;
|
|
109888
|
+
console.log(
|
|
109889
|
+
`\u{1F4BE} [${this.name}] Cache SET: ${String(key)} (ttl: ${effectiveTtl}ms, size: ${this.cache.size}/${this.maxSize})`
|
|
109890
|
+
);
|
|
109891
|
+
}
|
|
109786
109892
|
}
|
|
109787
109893
|
/**
|
|
109788
|
-
*
|
|
109894
|
+
* Set value in cache with Result wrapper
|
|
109895
|
+
*/
|
|
109896
|
+
setResult(key, value, ttl) {
|
|
109897
|
+
try {
|
|
109898
|
+
this.set(key, value, ttl);
|
|
109899
|
+
return success(void 0);
|
|
109900
|
+
} catch (error2) {
|
|
109901
|
+
return failure(
|
|
109902
|
+
new SDKError({
|
|
109903
|
+
message: `Failed to set cache value for key: ${String(key)}`,
|
|
109904
|
+
category: "CACHE" /* CACHE */,
|
|
109905
|
+
severity: "MEDIUM" /* MEDIUM */,
|
|
109906
|
+
originalError: error2 instanceof Error ? error2 : new Error(String(error2))
|
|
109907
|
+
})
|
|
109908
|
+
);
|
|
109909
|
+
}
|
|
109910
|
+
}
|
|
109911
|
+
/**
|
|
109912
|
+
* Check if key exists in cache (without affecting stats)
|
|
109789
109913
|
*/
|
|
109790
109914
|
has(key) {
|
|
109791
|
-
|
|
109915
|
+
const entry = this.cache.get(key);
|
|
109916
|
+
return entry !== void 0 && !this.isExpired(entry);
|
|
109792
109917
|
}
|
|
109793
109918
|
/**
|
|
109794
|
-
* Delete key from cache
|
|
109919
|
+
* Delete specific key from cache
|
|
109795
109920
|
*/
|
|
109796
109921
|
delete(key) {
|
|
109797
|
-
|
|
109922
|
+
const deleted = this.cache.delete(key);
|
|
109923
|
+
if (deleted && this.debug) {
|
|
109924
|
+
console.log(`\u{1F5D1}\uFE0F [${this.name}] Cache DELETE: ${String(key)}`);
|
|
109925
|
+
}
|
|
109926
|
+
return deleted;
|
|
109798
109927
|
}
|
|
109799
109928
|
/**
|
|
109800
|
-
* Clear
|
|
109929
|
+
* Clear entire cache
|
|
109801
109930
|
*/
|
|
109802
109931
|
clear() {
|
|
109932
|
+
const previousSize = this.cache.size;
|
|
109803
109933
|
this.cache.clear();
|
|
109934
|
+
this.stats = {
|
|
109935
|
+
hits: 0,
|
|
109936
|
+
misses: 0,
|
|
109937
|
+
evictions: 0
|
|
109938
|
+
};
|
|
109939
|
+
if (this.debug) {
|
|
109940
|
+
console.log(`\u{1F9F9} [${this.name}] Cache CLEARED: removed ${previousSize} entries`);
|
|
109941
|
+
}
|
|
109804
109942
|
}
|
|
109805
109943
|
/**
|
|
109806
|
-
*
|
|
109944
|
+
* Get current cache size
|
|
109945
|
+
*/
|
|
109946
|
+
size() {
|
|
109947
|
+
return this.cache.size;
|
|
109948
|
+
}
|
|
109949
|
+
/**
|
|
109950
|
+
* Get cache statistics
|
|
109951
|
+
*/
|
|
109952
|
+
getStats() {
|
|
109953
|
+
const entries = Array.from(this.cache.values());
|
|
109954
|
+
const timestamps = entries.map((e) => e.timestamp);
|
|
109955
|
+
const total = this.stats.hits + this.stats.misses;
|
|
109956
|
+
const hitRate = total === 0 ? 0 : this.stats.hits / total * 100;
|
|
109957
|
+
return {
|
|
109958
|
+
size: this.cache.size,
|
|
109959
|
+
hits: this.stats.hits,
|
|
109960
|
+
misses: this.stats.misses,
|
|
109961
|
+
evictions: this.stats.evictions,
|
|
109962
|
+
oldestEntry: timestamps.length > 0 ? Math.min(...timestamps) : 0,
|
|
109963
|
+
newestEntry: timestamps.length > 0 ? Math.max(...timestamps) : 0,
|
|
109964
|
+
hitRate
|
|
109965
|
+
};
|
|
109966
|
+
}
|
|
109967
|
+
/**
|
|
109968
|
+
* Get hit rate percentage
|
|
109969
|
+
*/
|
|
109970
|
+
getHitRate() {
|
|
109971
|
+
const total = this.stats.hits + this.stats.misses;
|
|
109972
|
+
return total === 0 ? 0 : this.stats.hits / total * 100;
|
|
109973
|
+
}
|
|
109974
|
+
/**
|
|
109975
|
+
* Get all cached keys (for debugging)
|
|
109976
|
+
*/
|
|
109977
|
+
getKeys() {
|
|
109978
|
+
return Array.from(this.cache.keys());
|
|
109979
|
+
}
|
|
109980
|
+
/**
|
|
109981
|
+
* Get all cached values (for debugging)
|
|
109982
|
+
*/
|
|
109983
|
+
getValues() {
|
|
109984
|
+
return Array.from(this.cache.values()).map((entry) => entry.value);
|
|
109985
|
+
}
|
|
109986
|
+
/**
|
|
109987
|
+
* Get all cache entries with metadata (for debugging)
|
|
109988
|
+
*/
|
|
109989
|
+
getEntries() {
|
|
109990
|
+
return Array.from(this.cache.entries()).map(([key, entry]) => ({
|
|
109991
|
+
key,
|
|
109992
|
+
value: entry.value,
|
|
109993
|
+
metadata: {
|
|
109994
|
+
timestamp: entry.timestamp,
|
|
109995
|
+
hits: entry.hits,
|
|
109996
|
+
lastAccessed: entry.lastAccessed
|
|
109997
|
+
}
|
|
109998
|
+
}));
|
|
109999
|
+
}
|
|
110000
|
+
/**
|
|
110001
|
+
* Clean up expired entries
|
|
110002
|
+
*
|
|
110003
|
+
* Useful for periodic maintenance
|
|
110004
|
+
*
|
|
110005
|
+
* @returns Number of entries cleaned
|
|
109807
110006
|
*/
|
|
109808
110007
|
cleanExpired() {
|
|
109809
110008
|
const now = Date.now();
|
|
109810
|
-
let
|
|
110009
|
+
let cleanedCount = 0;
|
|
109811
110010
|
for (const [key, entry] of this.cache.entries()) {
|
|
109812
|
-
if (now - entry.timestamp >
|
|
110011
|
+
if (now - entry.timestamp > this.ttlMs) {
|
|
109813
110012
|
this.cache.delete(key);
|
|
109814
|
-
|
|
110013
|
+
cleanedCount++;
|
|
109815
110014
|
}
|
|
109816
110015
|
}
|
|
109817
|
-
|
|
110016
|
+
if (cleanedCount > 0 && this.debug) {
|
|
110017
|
+
console.log(`\u{1F9F9} [${this.name}] Cleaned ${cleanedCount} expired entries`);
|
|
110018
|
+
}
|
|
110019
|
+
return cleanedCount;
|
|
109818
110020
|
}
|
|
109819
110021
|
/**
|
|
109820
|
-
*
|
|
110022
|
+
* Check if cache entry is expired
|
|
109821
110023
|
*/
|
|
109822
|
-
|
|
109823
|
-
return
|
|
109824
|
-
|
|
109825
|
-
|
|
109826
|
-
|
|
109827
|
-
|
|
110024
|
+
isExpired(entry) {
|
|
110025
|
+
return Date.now() - entry.timestamp > this.ttlMs;
|
|
110026
|
+
}
|
|
110027
|
+
/**
|
|
110028
|
+
* Evict least recently used entry
|
|
110029
|
+
*/
|
|
110030
|
+
evictLRU() {
|
|
110031
|
+
let oldestKey = null;
|
|
110032
|
+
let oldestAccess = Infinity;
|
|
110033
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
110034
|
+
if (entry.lastAccessed < oldestAccess) {
|
|
110035
|
+
oldestAccess = entry.lastAccessed;
|
|
110036
|
+
oldestKey = key;
|
|
110037
|
+
}
|
|
110038
|
+
}
|
|
110039
|
+
if (oldestKey !== null) {
|
|
110040
|
+
this.cache.delete(oldestKey);
|
|
110041
|
+
this.stats.evictions++;
|
|
110042
|
+
if (this.debug) {
|
|
110043
|
+
const timeSinceAccess = Date.now() - oldestAccess;
|
|
110044
|
+
console.log(
|
|
110045
|
+
`\u267B\uFE0F [${this.name}] Cache EVICT (LRU): ${String(oldestKey)} (last accessed: ${timeSinceAccess}ms ago)`
|
|
110046
|
+
);
|
|
110047
|
+
}
|
|
110048
|
+
}
|
|
110049
|
+
}
|
|
110050
|
+
/**
|
|
110051
|
+
* Get or compute value
|
|
110052
|
+
*
|
|
110053
|
+
* If key exists in cache, returns cached value.
|
|
110054
|
+
* Otherwise, computes value using provided function and caches it.
|
|
110055
|
+
*
|
|
110056
|
+
* @param key - Cache key
|
|
110057
|
+
* @param compute - Function to compute value if not in cache
|
|
110058
|
+
* @param ttl - Optional custom TTL for this entry
|
|
110059
|
+
* @returns Cached or computed value
|
|
110060
|
+
*/
|
|
110061
|
+
async getOrCompute(key, compute, ttl) {
|
|
110062
|
+
const cached = this.get(key);
|
|
110063
|
+
if (cached !== null) {
|
|
110064
|
+
return cached;
|
|
110065
|
+
}
|
|
110066
|
+
const existing = this.inflight.get(key);
|
|
110067
|
+
if (existing) {
|
|
110068
|
+
return existing;
|
|
110069
|
+
}
|
|
110070
|
+
const computePromise = (async () => {
|
|
110071
|
+
try {
|
|
110072
|
+
const value = await compute();
|
|
110073
|
+
this.set(key, value, ttl);
|
|
110074
|
+
return value;
|
|
110075
|
+
} finally {
|
|
110076
|
+
this.inflight.delete(key);
|
|
110077
|
+
}
|
|
110078
|
+
})();
|
|
110079
|
+
this.inflight.set(key, computePromise);
|
|
110080
|
+
return computePromise;
|
|
110081
|
+
}
|
|
110082
|
+
/**
|
|
110083
|
+
* Get or compute value with Result wrapper
|
|
110084
|
+
*/
|
|
110085
|
+
async getOrComputeResult(key, compute, ttl) {
|
|
110086
|
+
const cached = this.get(key);
|
|
110087
|
+
if (cached !== null) {
|
|
110088
|
+
return success(cached);
|
|
110089
|
+
}
|
|
110090
|
+
const existing = this.inflightResult.get(key);
|
|
110091
|
+
if (existing) {
|
|
110092
|
+
return existing;
|
|
110093
|
+
}
|
|
110094
|
+
const computePromise = (async () => {
|
|
110095
|
+
try {
|
|
110096
|
+
return await compute();
|
|
110097
|
+
} finally {
|
|
110098
|
+
this.inflightResult.delete(key);
|
|
110099
|
+
}
|
|
110100
|
+
})();
|
|
110101
|
+
this.inflightResult.set(key, computePromise);
|
|
110102
|
+
const result = await computePromise;
|
|
110103
|
+
if (result.success) {
|
|
110104
|
+
this.set(key, result.value, ttl);
|
|
110105
|
+
}
|
|
110106
|
+
return result;
|
|
109828
110107
|
}
|
|
109829
110108
|
};
|
|
109830
110109
|
var CacheManager = class {
|
|
109831
110110
|
caches = /* @__PURE__ */ new Map();
|
|
109832
|
-
|
|
109833
|
-
constructor(
|
|
109834
|
-
this.
|
|
110111
|
+
globalConfig;
|
|
110112
|
+
constructor(globalConfig = {}) {
|
|
110113
|
+
this.globalConfig = globalConfig;
|
|
109835
110114
|
}
|
|
109836
110115
|
/**
|
|
109837
|
-
*
|
|
110116
|
+
* Create or get a named cache
|
|
110117
|
+
*
|
|
110118
|
+
* @param name - Unique cache name
|
|
110119
|
+
* @param config - Optional cache-specific configuration
|
|
110120
|
+
* @returns LRU cache instance
|
|
109838
110121
|
*/
|
|
109839
110122
|
getCache(name, config) {
|
|
109840
|
-
|
|
109841
|
-
|
|
110123
|
+
const existingCache = this.caches.get(name);
|
|
110124
|
+
if (existingCache) {
|
|
110125
|
+
return existingCache;
|
|
109842
110126
|
}
|
|
109843
|
-
const
|
|
110127
|
+
const mergedConfig = {
|
|
110128
|
+
...this.globalConfig,
|
|
110129
|
+
...config,
|
|
110130
|
+
name
|
|
110131
|
+
};
|
|
110132
|
+
const cache = new LRUCache(mergedConfig);
|
|
109844
110133
|
this.caches.set(name, cache);
|
|
109845
|
-
if (this.debug) {
|
|
109846
|
-
console.log(`[CacheManager] Created cache: ${name}`, config);
|
|
109847
|
-
}
|
|
109848
110134
|
return cache;
|
|
109849
110135
|
}
|
|
109850
110136
|
/**
|
|
@@ -109859,11 +110145,11 @@ var CacheManager = class {
|
|
|
109859
110145
|
* Clean expired entries from all caches
|
|
109860
110146
|
*/
|
|
109861
110147
|
cleanAllExpired() {
|
|
109862
|
-
let
|
|
110148
|
+
let totalCleaned = 0;
|
|
109863
110149
|
for (const cache of this.caches.values()) {
|
|
109864
|
-
|
|
110150
|
+
totalCleaned += cache.cleanExpired();
|
|
109865
110151
|
}
|
|
109866
|
-
return
|
|
110152
|
+
return totalCleaned;
|
|
109867
110153
|
}
|
|
109868
110154
|
/**
|
|
109869
110155
|
* Get statistics for all caches
|
|
@@ -109876,11 +110162,16 @@ var CacheManager = class {
|
|
|
109876
110162
|
return stats;
|
|
109877
110163
|
}
|
|
109878
110164
|
/**
|
|
109879
|
-
*
|
|
110165
|
+
* Get list of all cache names
|
|
109880
110166
|
*/
|
|
109881
|
-
|
|
109882
|
-
this.
|
|
109883
|
-
|
|
110167
|
+
getCacheNames() {
|
|
110168
|
+
return Array.from(this.caches.keys());
|
|
110169
|
+
}
|
|
110170
|
+
/**
|
|
110171
|
+
* Delete a named cache
|
|
110172
|
+
*/
|
|
110173
|
+
deleteCache(name) {
|
|
110174
|
+
return this.caches.delete(name);
|
|
109884
110175
|
}
|
|
109885
110176
|
};
|
|
109886
110177
|
function createCacheManager(config) {
|
|
@@ -118373,12 +118664,11 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
118373
118664
|
{}
|
|
118374
118665
|
);
|
|
118375
118666
|
}
|
|
118376
|
-
|
|
118377
|
-
|
|
118378
|
-
|
|
118379
|
-
const errorMsg = error2.message || String(error2);
|
|
118667
|
+
const result = await this._requestMintUCDAttempt(request);
|
|
118668
|
+
if (!result.success && fullRetry < MAX_FULL_RETRIES) {
|
|
118669
|
+
const errorMsg = result.error || "";
|
|
118380
118670
|
const isStaleTimestamp = errorMsg.includes("quantumTimestamp too old") || errorMsg.includes("Timestamp staleness") || errorMsg.includes("MAX_SKEW") || errorMsg.includes("Quantum window expired") || errorMsg.includes("Too close to quantum boundary") || errorMsg.includes("QuantumOutsideWindow") || errorMsg.includes("Quantum window remaining too low");
|
|
118381
|
-
if (isStaleTimestamp
|
|
118671
|
+
if (isStaleTimestamp) {
|
|
118382
118672
|
if (this.config.debug) {
|
|
118383
118673
|
log.warn(
|
|
118384
118674
|
`\u26A0\uFE0F Timestamp became stale during mint process. Retrying from beginning...`,
|
|
@@ -118388,8 +118678,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
118388
118678
|
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
118389
118679
|
continue;
|
|
118390
118680
|
}
|
|
118391
|
-
throw error2;
|
|
118392
118681
|
}
|
|
118682
|
+
return result;
|
|
118393
118683
|
}
|
|
118394
118684
|
return {
|
|
118395
118685
|
success: false,
|
|
@@ -119011,6 +119301,7 @@ Context: Quantum timestamp=${validationResponse.timestamp}, Position=${request.p
|
|
|
119011
119301
|
"0x131d9a21": "QuantumExpired()",
|
|
119012
119302
|
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
119013
119303
|
"0x137f3b70": "InDeadZone()",
|
|
119304
|
+
"0xbe4b82c1": "DeadZoneViolation()",
|
|
119014
119305
|
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
119015
119306
|
"0x62278171": "InvalidValidatorSignature()",
|
|
119016
119307
|
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
@@ -119031,7 +119322,7 @@ Mint/debt diagnostics (LoanOperationsManager mint path \u2192 increaseDebtFromMi
|
|
|
119031
119322
|
Contract expects UCD supply increase to match mintAmount+mintFee and debt update to newDebt.
|
|
119032
119323
|
` : "";
|
|
119033
119324
|
let quantumContext = "";
|
|
119034
|
-
if (selector === "0x131d9a21" || selector === "0x52ce5d58" || selector === "0x137f3b70" || selector === "0x3e76a3c9") {
|
|
119325
|
+
if (selector === "0x131d9a21" || selector === "0x52ce5d58" || selector === "0x137f3b70" || selector === "0xbe4b82c1" || selector === "0x3e76a3c9") {
|
|
119035
119326
|
const currentTime2 = Math.floor(Date.now() / 1e3);
|
|
119036
119327
|
const currentQuantum = Math.floor(currentTime2 / 60) * 60;
|
|
119037
119328
|
const sigQuantum2 = Math.floor(validationResponse.timestamp / 60) * 60;
|
|
@@ -119293,6 +119584,7 @@ Position: ${request.positionId}`
|
|
|
119293
119584
|
validationResponse.timestamp,
|
|
119294
119585
|
signatureHexMint
|
|
119295
119586
|
]);
|
|
119587
|
+
await awaitSafeSubmissionWindow(Number(validationResponse.timestamp));
|
|
119296
119588
|
const fromAddress = await signer.getAddress();
|
|
119297
119589
|
const estimatedGas = await estimateContractCallGasWithMargin(
|
|
119298
119590
|
signerProvider,
|
|
@@ -119351,6 +119643,7 @@ Position: ${request.positionId}`
|
|
|
119351
119643
|
"0x131d9a21": "QuantumExpired()",
|
|
119352
119644
|
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
119353
119645
|
"0x137f3b70": "InDeadZone()",
|
|
119646
|
+
"0xbe4b82c1": "DeadZoneViolation()",
|
|
119354
119647
|
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
119355
119648
|
"0x62278171": "InvalidValidatorSignature()",
|
|
119356
119649
|
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
@@ -119530,6 +119823,7 @@ Error data: ${errorData || "none"}`
|
|
|
119530
119823
|
"0x131d9a21": "QuantumExpired() - Signature quantum window has closed",
|
|
119531
119824
|
"0x52ce5d58": "QuantumAlreadyUsed() - This quantum was already used for this position",
|
|
119532
119825
|
"0x137f3b70": "InDeadZone() - Timestamp in dead zone (near quantum boundary)",
|
|
119826
|
+
"0xbe4b82c1": "DeadZoneViolation() - Non-current-quantum signature mined in the last 8s of the current quantum",
|
|
119533
119827
|
"0x3e76a3c9": "QuantumOutsideWindow() - Timestamp not in past/current/next quantum window"
|
|
119534
119828
|
};
|
|
119535
119829
|
const errorName = knownErrors[selector] || `Unknown error ${selector}`;
|
|
@@ -120598,6 +120892,7 @@ Error data: ${errorData || "none"}`
|
|
|
120598
120892
|
);
|
|
120599
120893
|
}
|
|
120600
120894
|
const positionManager = positionManagerResult.value;
|
|
120895
|
+
await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
120601
120896
|
const tx = await positionManager["extendPosition"](
|
|
120602
120897
|
positionIdBytes32,
|
|
120603
120898
|
BigInt(_selectedTerm),
|
|
@@ -121030,6 +121325,57 @@ Error data: ${errorData || "none"}`
|
|
|
121030
121325
|
if (!pauseCheck.ok) {
|
|
121031
121326
|
return { success: false, error: pauseCheck.error };
|
|
121032
121327
|
}
|
|
121328
|
+
const MAX_FULL_RETRIES = 3;
|
|
121329
|
+
for (let fullRetry = 1; fullRetry <= MAX_FULL_RETRIES; fullRetry++) {
|
|
121330
|
+
if (fullRetry > 1 && this.config.debug) {
|
|
121331
|
+
log.info(
|
|
121332
|
+
`\u{1F504} Full payment retry ${fullRetry}/${MAX_FULL_RETRIES} due to quantum-timing failure...`,
|
|
121333
|
+
{}
|
|
121334
|
+
);
|
|
121335
|
+
}
|
|
121336
|
+
const result = await this._makePaymentAttempt(request);
|
|
121337
|
+
if (fullRetry < MAX_FULL_RETRIES && this.isRetryablePaymentQuantumFailure(result)) {
|
|
121338
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
121339
|
+
continue;
|
|
121340
|
+
}
|
|
121341
|
+
return result;
|
|
121342
|
+
}
|
|
121343
|
+
return {
|
|
121344
|
+
success: false,
|
|
121345
|
+
error: "Max retries exceeded for payment operation"
|
|
121346
|
+
};
|
|
121347
|
+
} finally {
|
|
121348
|
+
this.invalidateCachesForPosition(request.positionId);
|
|
121349
|
+
this.releaseWriteLock(request.positionId);
|
|
121350
|
+
}
|
|
121351
|
+
}
|
|
121352
|
+
/**
|
|
121353
|
+
* Whether a failed payment attempt is a quantum-timing failure that a fresh
|
|
121354
|
+
* re-sign can fix (safe to retry), versus a terminal failure.
|
|
121355
|
+
*
|
|
121356
|
+
* Retryable: pre-send simulation quantum errors, or an atomic mined revert
|
|
121357
|
+
* (status 0) — no funds moved and the quantum was not recorded on-chain, so a
|
|
121358
|
+
* fresh signature + resubmit is safe.
|
|
121359
|
+
*
|
|
121360
|
+
* NOT retryable: a confirmation timeout — the original tx may still be pending, so
|
|
121361
|
+
* a resubmit could double-pay. It is surfaced (with its tx hash) instead.
|
|
121362
|
+
*/
|
|
121363
|
+
isRetryablePaymentQuantumFailure(result) {
|
|
121364
|
+
if (result.success || !result.error)
|
|
121365
|
+
return false;
|
|
121366
|
+
const e = result.error;
|
|
121367
|
+
if (e.includes("Transaction timeout"))
|
|
121368
|
+
return false;
|
|
121369
|
+
return e.includes("DeadZoneViolation") || e.includes("QuantumOutsideWindow") || e.includes("QuantumAlreadyUsed") || e.includes("QuantumExpired") || e === "Transaction reverted";
|
|
121370
|
+
}
|
|
121371
|
+
/**
|
|
121372
|
+
* One payment attempt: user auth → Lit Action authorization → dead-zone gate →
|
|
121373
|
+
* pre-send simulation → broadcast → confirmation. Always resolves to a
|
|
121374
|
+
* PartialPaymentResult (never throws to the caller); the makePayment wrapper owns
|
|
121375
|
+
* the write lock, the pause pre-check, and the bounded re-sign retry loop.
|
|
121376
|
+
*/
|
|
121377
|
+
async _makePaymentAttempt(request) {
|
|
121378
|
+
try {
|
|
121033
121379
|
if (this.config.debug) {
|
|
121034
121380
|
log.info(`\u{1F4B3} Making payment...`, {});
|
|
121035
121381
|
log.info(` Request object:`, { request });
|
|
@@ -121290,7 +121636,6 @@ Error data: ${errorData || "none"}`
|
|
|
121290
121636
|
error: `Failed to get PositionManager: ${positionManagerResult.error.message}`
|
|
121291
121637
|
};
|
|
121292
121638
|
}
|
|
121293
|
-
const positionManager = positionManagerResult.value;
|
|
121294
121639
|
if (this.config.debug) {
|
|
121295
121640
|
log.info(
|
|
121296
121641
|
` About to call toBytes32 with: ${request.positionId} (type: ${typeof request.positionId})`
|
|
@@ -121350,9 +121695,6 @@ Error data: ${errorData || "none"}`
|
|
|
121350
121695
|
currentQuantum
|
|
121351
121696
|
});
|
|
121352
121697
|
}
|
|
121353
|
-
if (this.config.debug) {
|
|
121354
|
-
log.info("\u23ED\uFE0F Skipping dead zone check to isolate BigNumber issue", {});
|
|
121355
|
-
}
|
|
121356
121698
|
if (this.config.debug) {
|
|
121357
121699
|
log.info("\u{1F50D} Final timestamp validation:", {
|
|
121358
121700
|
litActionTimestamp: litActionResult.timestamp,
|
|
@@ -121419,108 +121761,100 @@ Error data: ${errorData || "none"}`
|
|
|
121419
121761
|
quantumTimestamp: quantumTimestamp.toString()
|
|
121420
121762
|
});
|
|
121421
121763
|
}
|
|
121422
|
-
|
|
121423
|
-
|
|
121424
|
-
|
|
121425
|
-
|
|
121426
|
-
|
|
121427
|
-
|
|
121428
|
-
|
|
121429
|
-
|
|
121430
|
-
|
|
121431
|
-
|
|
121432
|
-
|
|
121433
|
-
|
|
121434
|
-
|
|
121435
|
-
|
|
121436
|
-
|
|
121437
|
-
|
|
121438
|
-
|
|
121439
|
-
|
|
121440
|
-
|
|
121441
|
-
|
|
121442
|
-
|
|
121443
|
-
|
|
121444
|
-
|
|
121445
|
-
|
|
121446
|
-
|
|
121447
|
-
|
|
121448
|
-
|
|
121449
|
-
)
|
|
121450
|
-
|
|
121451
|
-
|
|
121452
|
-
|
|
121453
|
-
|
|
121454
|
-
|
|
121455
|
-
|
|
121456
|
-
|
|
121457
|
-
|
|
121458
|
-
|
|
121459
|
-
|
|
121460
|
-
|
|
121461
|
-
|
|
121462
|
-
|
|
121463
|
-
|
|
121464
|
-
|
|
121465
|
-
|
|
121466
|
-
if (typeof quantumTimestampStr !== "string" || quantumTimestampStr === "[object Object]") {
|
|
121467
|
-
throw new Error(`Invalid quantumTimestamp: ${quantumTimestampStr}`);
|
|
121468
|
-
}
|
|
121469
|
-
if (typeof btcPriceStr !== "string" || btcPriceStr === "[object Object]") {
|
|
121470
|
-
throw new Error(`Invalid btcPrice: ${btcPriceStr}`);
|
|
121471
|
-
}
|
|
121472
|
-
if (this.config.debug) {
|
|
121473
|
-
log.info("\u{1F50D} Final parameter validation before contract call:", {
|
|
121474
|
-
positionIdBytes32: typeof positionIdBytes32,
|
|
121475
|
-
paymentAmountStr: typeof paymentAmountStr + " = " + paymentAmountStr.substring(0, 20),
|
|
121476
|
-
quantumTimestampStr: typeof quantumTimestampStr + " = " + quantumTimestampStr.substring(0, 20),
|
|
121477
|
-
btcPriceStr: typeof btcPriceStr + " = " + btcPriceStr.substring(0, 20),
|
|
121478
|
-
signature: typeof signature + " = " + signature.substring(0, 20)
|
|
121764
|
+
await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
121765
|
+
const paymentAmountStr = paymentAmountWei.toString();
|
|
121766
|
+
const quantumTimestampStr = quantumTimestamp.toString();
|
|
121767
|
+
const btcPriceStr = btcPrice.toString();
|
|
121768
|
+
const paymentContractAddress = this.getContractAddressesOrThrow().positionManager;
|
|
121769
|
+
const paymentSigner = this.getSignerOrThrow();
|
|
121770
|
+
const paymentFrom = await paymentSigner.getAddress();
|
|
121771
|
+
const paymentProvider = contractManager.getProvider();
|
|
121772
|
+
const paymentIface = new Interface([
|
|
121773
|
+
"function makePayment(bytes32 positionId, uint256 paymentAmount, uint256 quantumTimestamp, uint256 btcPrice, bytes calldata paymentValidatorSignature) external returns (bool)"
|
|
121774
|
+
]);
|
|
121775
|
+
const paymentCalldata = paymentIface.encodeFunctionData("makePayment", [
|
|
121776
|
+
positionIdBytes32,
|
|
121777
|
+
paymentAmountStr,
|
|
121778
|
+
quantumTimestampStr,
|
|
121779
|
+
btcPriceStr,
|
|
121780
|
+
signature
|
|
121781
|
+
]);
|
|
121782
|
+
const decodePaymentRevert = (e) => {
|
|
121783
|
+
const raw = e?.data ?? e?.info?.error?.data ?? e?.error?.data?.data ?? e?.error?.data;
|
|
121784
|
+
const data = typeof raw === "string" ? raw : void 0;
|
|
121785
|
+
if (!data || !data.startsWith("0x") || data.length < 10)
|
|
121786
|
+
return null;
|
|
121787
|
+
const selector = data.slice(0, 10);
|
|
121788
|
+
const map3 = {
|
|
121789
|
+
"0xbe4b82c1": "DeadZoneViolation()",
|
|
121790
|
+
"0x137f3b70": "InDeadZone()",
|
|
121791
|
+
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
121792
|
+
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
121793
|
+
"0x131d9a21": "QuantumExpired()",
|
|
121794
|
+
"0x8baa579f": "InvalidSignature()",
|
|
121795
|
+
"0x62278171": "InvalidValidatorSignature()",
|
|
121796
|
+
"0x3ee5aeb5": "OperationNotAuthorized()",
|
|
121797
|
+
"0x48f5c3ed": "Unauthorized()"
|
|
121798
|
+
};
|
|
121799
|
+
return map3[selector] ?? `Unknown error ${selector}`;
|
|
121800
|
+
};
|
|
121801
|
+
const MAX_DEADZONE_RESIMULATIONS = 3;
|
|
121802
|
+
for (let sim = 1; ; sim++) {
|
|
121803
|
+
try {
|
|
121804
|
+
await paymentProvider.call({
|
|
121805
|
+
to: paymentContractAddress,
|
|
121806
|
+
from: paymentFrom,
|
|
121807
|
+
data: paymentCalldata
|
|
121479
121808
|
});
|
|
121480
|
-
|
|
121481
|
-
|
|
121482
|
-
|
|
121483
|
-
|
|
121484
|
-
|
|
121485
|
-
|
|
121486
|
-
|
|
121487
|
-
|
|
121488
|
-
|
|
121489
|
-
|
|
121490
|
-
|
|
121491
|
-
|
|
121492
|
-
|
|
121493
|
-
|
|
121494
|
-
|
|
121495
|
-
{
|
|
121496
|
-
error: contractError instanceof Error ? contractError.message : String(contractError)
|
|
121809
|
+
break;
|
|
121810
|
+
} catch (simError) {
|
|
121811
|
+
const decoded = decodePaymentRevert(simError);
|
|
121812
|
+
if (decoded === "DeadZoneViolation()" && sim <= MAX_DEADZONE_RESIMULATIONS) {
|
|
121813
|
+
const nowSec = Math.floor(Date.now() / 1e3);
|
|
121814
|
+
const sigQuantum = Math.floor(Number(quantumTimestamp) / 60) * 60;
|
|
121815
|
+
const realCurrentQuantum = Math.floor(nowSec / 60) * 60;
|
|
121816
|
+
if (sigQuantum === realCurrentQuantum) {
|
|
121817
|
+
if (this.config.debug) {
|
|
121818
|
+
log.info(
|
|
121819
|
+
"\u21AA\uFE0F Simulated DeadZoneViolation is a stale-latest-block artifact (signature is the current quantum) \u2014 proceeding to broadcast",
|
|
121820
|
+
{}
|
|
121821
|
+
);
|
|
121822
|
+
}
|
|
121823
|
+
break;
|
|
121497
121824
|
}
|
|
121498
|
-
|
|
121499
|
-
|
|
121500
|
-
|
|
121501
|
-
|
|
121502
|
-
|
|
121503
|
-
|
|
121504
|
-
|
|
121505
|
-
|
|
121506
|
-
|
|
121507
|
-
|
|
121508
|
-
|
|
121509
|
-
|
|
121510
|
-
|
|
121511
|
-
|
|
121512
|
-
|
|
121513
|
-
|
|
121514
|
-
|
|
121515
|
-
|
|
121516
|
-
|
|
121517
|
-
|
|
121518
|
-
|
|
121519
|
-
log.info("\u2705 Raw transaction fallback succeeded", {
|
|
121520
|
-
txHash: tx.hash
|
|
121521
|
-
});
|
|
121825
|
+
const gate = await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
121826
|
+
if (gate.waited) {
|
|
121827
|
+
if (this.config.debug) {
|
|
121828
|
+
log.info(
|
|
121829
|
+
`\u{1F501} Re-simulating makePayment after crossing the quantum boundary (attempt ${sim}/${MAX_DEADZONE_RESIMULATIONS})`,
|
|
121830
|
+
{}
|
|
121831
|
+
);
|
|
121832
|
+
}
|
|
121833
|
+
continue;
|
|
121834
|
+
}
|
|
121835
|
+
}
|
|
121836
|
+
const label = decoded ?? simError?.reason ?? simError?.shortMessage ?? (simError instanceof Error ? simError.message : String(simError));
|
|
121837
|
+
if (this.config.debug) {
|
|
121838
|
+
log.error("\u274C makePayment pre-send simulation reverted", { error: label });
|
|
121839
|
+
}
|
|
121840
|
+
return {
|
|
121841
|
+
success: false,
|
|
121842
|
+
error: `Payment would revert (pre-send simulation): ${label}`,
|
|
121843
|
+
positionId: request.positionId,
|
|
121844
|
+
paymentAmountUCD: request.paymentAmount
|
|
121845
|
+
};
|
|
121522
121846
|
}
|
|
121523
121847
|
}
|
|
121848
|
+
const MAKE_PAYMENT_GAS_CEILING = 500000n;
|
|
121849
|
+
const tx = await sendEip1559Transaction({
|
|
121850
|
+
signer: paymentSigner,
|
|
121851
|
+
to: paymentContractAddress,
|
|
121852
|
+
data: paymentCalldata,
|
|
121853
|
+
gasLimit: MAKE_PAYMENT_GAS_CEILING
|
|
121854
|
+
});
|
|
121855
|
+
if (this.config.debug) {
|
|
121856
|
+
log.info("\u2705 makePayment broadcast", { txHash: tx.hash });
|
|
121857
|
+
}
|
|
121524
121858
|
if (this.config.debug) {
|
|
121525
121859
|
log.info(`\u{1F4E4} Transaction sent: ${tx.hash}`);
|
|
121526
121860
|
log.info("\u23F3 Waiting for transaction confirmation...");
|
|
@@ -121664,9 +121998,6 @@ Error data: ${errorData || "none"}`
|
|
|
121664
121998
|
result.effectiveGasPrice = receipt.effectiveGasPrice?.toString() || receipt.gasPrice?.toString();
|
|
121665
121999
|
}
|
|
121666
122000
|
return result;
|
|
121667
|
-
} finally {
|
|
121668
|
-
this.invalidateCachesForPosition(request.positionId);
|
|
121669
|
-
this.releaseWriteLock(request.positionId);
|
|
121670
122001
|
}
|
|
121671
122002
|
}
|
|
121672
122003
|
/**
|
|
@@ -122228,6 +122559,7 @@ Error data: ${errorData || "none"}`
|
|
|
122228
122559
|
utxoVout: withdrawalParams.utxoVout
|
|
122229
122560
|
});
|
|
122230
122561
|
}
|
|
122562
|
+
await awaitSafeSubmissionWindow(Number(withdrawalParams.quantumTimestamp));
|
|
122231
122563
|
let tx;
|
|
122232
122564
|
try {
|
|
122233
122565
|
tx = await positionManagerContract["withdrawBTC"](
|
|
@@ -124449,7 +124781,7 @@ export {
|
|
|
124449
124781
|
ErrorSeverity,
|
|
124450
124782
|
EventHelpers,
|
|
124451
124783
|
LOCALHOST_CONTRACTS,
|
|
124452
|
-
|
|
124784
|
+
LRUCache,
|
|
124453
124785
|
LoanCreator,
|
|
124454
124786
|
LoanQuery,
|
|
124455
124787
|
LoanStatus,
|