@gvnrdao/dh-sdk 0.0.293 → 0.0.294
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 +500 -171
- package/dist/index.mjs +500 -171
- 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
|
|
@@ -108108,6 +108108,9 @@ function validateSDKConfig(config) {
|
|
|
108108
108108
|
|
|
108109
108109
|
// src/utils/quantum-timing.ts
|
|
108110
108110
|
var QUANTUM_WINDOW_SECONDS = 60;
|
|
108111
|
+
var DEAD_ZONE_SECONDS = 8;
|
|
108112
|
+
var INCLUSION_LATENCY_BUDGET = 16;
|
|
108113
|
+
var POST_BOUNDARY_SKEW_MARGIN = 3;
|
|
108111
108114
|
function calculateNextQuantumTimestamp() {
|
|
108112
108115
|
const now = Math.floor(Date.now() / 1e3);
|
|
108113
108116
|
const currentQuantum = Math.floor(now / QUANTUM_WINDOW_SECONDS) * QUANTUM_WINDOW_SECONDS;
|
|
@@ -108136,6 +108139,27 @@ function validateQuantumTiming(signedTimestamp, _bufferSeconds = 30) {
|
|
|
108136
108139
|
console.log(" Current quantum:", currentQuantum);
|
|
108137
108140
|
console.log(" Valid window: PAST/CURRENT/NEXT (180s total)");
|
|
108138
108141
|
}
|
|
108142
|
+
async function awaitSafeSubmissionWindow(quantumTimestamp, opts = {}) {
|
|
108143
|
+
const now = opts.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
108144
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
108145
|
+
const nowSec = now();
|
|
108146
|
+
const signatureQuantum = Math.floor(quantumTimestamp / QUANTUM_WINDOW_SECONDS) * QUANTUM_WINDOW_SECONDS;
|
|
108147
|
+
const currentQuantum = Math.floor(nowSec / QUANTUM_WINDOW_SECONDS) * QUANTUM_WINDOW_SECONDS;
|
|
108148
|
+
const secsToBoundary = QUANTUM_WINDOW_SECONDS - nowSec % QUANTUM_WINDOW_SECONDS;
|
|
108149
|
+
const isNextQuantumSig = signatureQuantum === currentQuantum + QUANTUM_WINDOW_SECONDS;
|
|
108150
|
+
if (isNextQuantumSig && secsToBoundary <= DEAD_ZONE_SECONDS + INCLUSION_LATENCY_BUDGET) {
|
|
108151
|
+
const target = currentQuantum + QUANTUM_WINDOW_SECONDS + POST_BOUNDARY_SKEW_MARGIN;
|
|
108152
|
+
const waitSeconds = target - nowSec;
|
|
108153
|
+
if (waitSeconds > 0) {
|
|
108154
|
+
console.log(
|
|
108155
|
+
`[Quantum Timing] \u23F3 Deferring send ${waitSeconds}s to clear the quantum dead zone (sig quantum ${signatureQuantum}, current ${currentQuantum}, ${secsToBoundary}s to boundary)`
|
|
108156
|
+
);
|
|
108157
|
+
await sleep(waitSeconds * 1e3);
|
|
108158
|
+
return { waited: true, waitedSeconds: waitSeconds };
|
|
108159
|
+
}
|
|
108160
|
+
}
|
|
108161
|
+
return { waited: false, waitedSeconds: 0 };
|
|
108162
|
+
}
|
|
108139
108163
|
|
|
108140
108164
|
// src/utils/mint-authorization.utils.ts
|
|
108141
108165
|
var PKP_NFT_ABI = [
|
|
@@ -109745,106 +109769,365 @@ function createContractManager(config) {
|
|
|
109745
109769
|
}
|
|
109746
109770
|
|
|
109747
109771
|
// src/modules/cache/cache-manager.module.ts
|
|
109748
|
-
var
|
|
109749
|
-
cache
|
|
109772
|
+
var LRUCache = class {
|
|
109773
|
+
cache;
|
|
109774
|
+
/**
|
|
109775
|
+
* Audit M-J: singleflight registry for `getOrCompute` / `getOrComputeResult`.
|
|
109776
|
+
* Concurrent cache-miss callers for the same key share one inflight promise
|
|
109777
|
+
* instead of each running `compute()` independently — important when the
|
|
109778
|
+
* compute spends a paid LIT capacity credit or hits a rate-limited upstream.
|
|
109779
|
+
*/
|
|
109780
|
+
inflight = /* @__PURE__ */ new Map();
|
|
109781
|
+
inflightResult = /* @__PURE__ */ new Map();
|
|
109750
109782
|
maxSize;
|
|
109751
109783
|
ttlMs;
|
|
109752
|
-
|
|
109753
|
-
|
|
109754
|
-
|
|
109784
|
+
debug;
|
|
109785
|
+
name;
|
|
109786
|
+
// Statistics
|
|
109787
|
+
stats = {
|
|
109788
|
+
hits: 0,
|
|
109789
|
+
misses: 0,
|
|
109790
|
+
evictions: 0
|
|
109791
|
+
};
|
|
109792
|
+
constructor(config = {}) {
|
|
109793
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
109794
|
+
this.maxSize = config.maxSize || 1e3;
|
|
109795
|
+
this.ttlMs = config.ttlMs || 6e4;
|
|
109796
|
+
this.debug = config.debug || false;
|
|
109797
|
+
this.name = config.name || "Cache";
|
|
109798
|
+
if (this.debug) {
|
|
109799
|
+
console.log(
|
|
109800
|
+
`\u{1F4BE} [${this.name}] Initialized: maxSize=${this.maxSize}, ttl=${this.ttlMs}ms`
|
|
109801
|
+
);
|
|
109802
|
+
}
|
|
109755
109803
|
}
|
|
109756
109804
|
/**
|
|
109757
109805
|
* Get value from cache
|
|
109806
|
+
*
|
|
109807
|
+
* Returns null if:
|
|
109808
|
+
* - Key not found
|
|
109809
|
+
* - Entry has expired
|
|
109810
|
+
*
|
|
109811
|
+
* @param key - Cache key
|
|
109812
|
+
* @returns Cached value or null
|
|
109758
109813
|
*/
|
|
109759
109814
|
get(key) {
|
|
109760
109815
|
const entry = this.cache.get(key);
|
|
109761
109816
|
if (!entry) {
|
|
109762
|
-
|
|
109817
|
+
this.stats.misses++;
|
|
109818
|
+
if (this.debug) {
|
|
109819
|
+
console.log(`\u274C [${this.name}] Cache MISS: ${String(key)}`);
|
|
109820
|
+
}
|
|
109821
|
+
return null;
|
|
109763
109822
|
}
|
|
109764
|
-
|
|
109765
|
-
if (now - entry.timestamp > entry.ttl) {
|
|
109823
|
+
if (this.isExpired(entry)) {
|
|
109766
109824
|
this.cache.delete(key);
|
|
109767
|
-
|
|
109825
|
+
this.stats.misses++;
|
|
109826
|
+
if (this.debug) {
|
|
109827
|
+
const age = Date.now() - entry.timestamp;
|
|
109828
|
+
console.log(`\u23F0 [${this.name}] Cache EXPIRED: ${String(key)} (age: ${age}ms)`);
|
|
109829
|
+
}
|
|
109830
|
+
return null;
|
|
109831
|
+
}
|
|
109832
|
+
entry.hits++;
|
|
109833
|
+
entry.lastAccessed = Date.now();
|
|
109834
|
+
this.cache.set(key, entry);
|
|
109835
|
+
this.stats.hits++;
|
|
109836
|
+
if (this.debug) {
|
|
109837
|
+
const age = Date.now() - entry.timestamp;
|
|
109838
|
+
console.log(
|
|
109839
|
+
`\u2705 [${this.name}] Cache HIT: ${String(key)} (age: ${age}ms, hits: ${entry.hits})`
|
|
109840
|
+
);
|
|
109768
109841
|
}
|
|
109769
109842
|
return entry.value;
|
|
109770
109843
|
}
|
|
109844
|
+
/**
|
|
109845
|
+
* Get value from cache with Result wrapper
|
|
109846
|
+
*
|
|
109847
|
+
* Useful when you want to distinguish between "not found" and "expired"
|
|
109848
|
+
*/
|
|
109849
|
+
getResult(key) {
|
|
109850
|
+
const value = this.get(key);
|
|
109851
|
+
if (value === null) {
|
|
109852
|
+
return failure(
|
|
109853
|
+
new SDKError({
|
|
109854
|
+
message: `Cache miss for key: ${String(key)}`,
|
|
109855
|
+
category: "CACHE" /* CACHE */,
|
|
109856
|
+
severity: "LOW" /* LOW */,
|
|
109857
|
+
originalError: new Error("Cache miss")
|
|
109858
|
+
})
|
|
109859
|
+
);
|
|
109860
|
+
}
|
|
109861
|
+
return success(value);
|
|
109862
|
+
}
|
|
109771
109863
|
/**
|
|
109772
109864
|
* Set value in cache
|
|
109865
|
+
*
|
|
109866
|
+
* If cache is full, evicts the least recently used entry
|
|
109867
|
+
*
|
|
109868
|
+
* @param key - Cache key
|
|
109869
|
+
* @param value - Value to cache
|
|
109870
|
+
* @param ttl - Optional custom TTL for this entry (ms)
|
|
109773
109871
|
*/
|
|
109774
109872
|
set(key, value, ttl) {
|
|
109775
109873
|
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
109776
|
-
|
|
109777
|
-
if (firstKey) {
|
|
109778
|
-
this.cache.delete(firstKey);
|
|
109779
|
-
}
|
|
109874
|
+
this.evictLRU();
|
|
109780
109875
|
}
|
|
109781
|
-
|
|
109876
|
+
const entry = {
|
|
109782
109877
|
value,
|
|
109783
109878
|
timestamp: Date.now(),
|
|
109784
|
-
|
|
109785
|
-
|
|
109879
|
+
hits: 0,
|
|
109880
|
+
lastAccessed: Date.now()
|
|
109881
|
+
};
|
|
109882
|
+
this.cache.set(key, entry);
|
|
109883
|
+
if (this.debug) {
|
|
109884
|
+
const effectiveTtl = ttl || this.ttlMs;
|
|
109885
|
+
console.log(
|
|
109886
|
+
`\u{1F4BE} [${this.name}] Cache SET: ${String(key)} (ttl: ${effectiveTtl}ms, size: ${this.cache.size}/${this.maxSize})`
|
|
109887
|
+
);
|
|
109888
|
+
}
|
|
109786
109889
|
}
|
|
109787
109890
|
/**
|
|
109788
|
-
*
|
|
109891
|
+
* Set value in cache with Result wrapper
|
|
109892
|
+
*/
|
|
109893
|
+
setResult(key, value, ttl) {
|
|
109894
|
+
try {
|
|
109895
|
+
this.set(key, value, ttl);
|
|
109896
|
+
return success(void 0);
|
|
109897
|
+
} catch (error2) {
|
|
109898
|
+
return failure(
|
|
109899
|
+
new SDKError({
|
|
109900
|
+
message: `Failed to set cache value for key: ${String(key)}`,
|
|
109901
|
+
category: "CACHE" /* CACHE */,
|
|
109902
|
+
severity: "MEDIUM" /* MEDIUM */,
|
|
109903
|
+
originalError: error2 instanceof Error ? error2 : new Error(String(error2))
|
|
109904
|
+
})
|
|
109905
|
+
);
|
|
109906
|
+
}
|
|
109907
|
+
}
|
|
109908
|
+
/**
|
|
109909
|
+
* Check if key exists in cache (without affecting stats)
|
|
109789
109910
|
*/
|
|
109790
109911
|
has(key) {
|
|
109791
|
-
|
|
109912
|
+
const entry = this.cache.get(key);
|
|
109913
|
+
return entry !== void 0 && !this.isExpired(entry);
|
|
109792
109914
|
}
|
|
109793
109915
|
/**
|
|
109794
|
-
* Delete key from cache
|
|
109916
|
+
* Delete specific key from cache
|
|
109795
109917
|
*/
|
|
109796
109918
|
delete(key) {
|
|
109797
|
-
|
|
109919
|
+
const deleted = this.cache.delete(key);
|
|
109920
|
+
if (deleted && this.debug) {
|
|
109921
|
+
console.log(`\u{1F5D1}\uFE0F [${this.name}] Cache DELETE: ${String(key)}`);
|
|
109922
|
+
}
|
|
109923
|
+
return deleted;
|
|
109798
109924
|
}
|
|
109799
109925
|
/**
|
|
109800
|
-
* Clear
|
|
109926
|
+
* Clear entire cache
|
|
109801
109927
|
*/
|
|
109802
109928
|
clear() {
|
|
109929
|
+
const previousSize = this.cache.size;
|
|
109803
109930
|
this.cache.clear();
|
|
109931
|
+
this.stats = {
|
|
109932
|
+
hits: 0,
|
|
109933
|
+
misses: 0,
|
|
109934
|
+
evictions: 0
|
|
109935
|
+
};
|
|
109936
|
+
if (this.debug) {
|
|
109937
|
+
console.log(`\u{1F9F9} [${this.name}] Cache CLEARED: removed ${previousSize} entries`);
|
|
109938
|
+
}
|
|
109804
109939
|
}
|
|
109805
109940
|
/**
|
|
109806
|
-
*
|
|
109941
|
+
* Get current cache size
|
|
109942
|
+
*/
|
|
109943
|
+
size() {
|
|
109944
|
+
return this.cache.size;
|
|
109945
|
+
}
|
|
109946
|
+
/**
|
|
109947
|
+
* Get cache statistics
|
|
109948
|
+
*/
|
|
109949
|
+
getStats() {
|
|
109950
|
+
const entries = Array.from(this.cache.values());
|
|
109951
|
+
const timestamps = entries.map((e) => e.timestamp);
|
|
109952
|
+
const total = this.stats.hits + this.stats.misses;
|
|
109953
|
+
const hitRate = total === 0 ? 0 : this.stats.hits / total * 100;
|
|
109954
|
+
return {
|
|
109955
|
+
size: this.cache.size,
|
|
109956
|
+
hits: this.stats.hits,
|
|
109957
|
+
misses: this.stats.misses,
|
|
109958
|
+
evictions: this.stats.evictions,
|
|
109959
|
+
oldestEntry: timestamps.length > 0 ? Math.min(...timestamps) : 0,
|
|
109960
|
+
newestEntry: timestamps.length > 0 ? Math.max(...timestamps) : 0,
|
|
109961
|
+
hitRate
|
|
109962
|
+
};
|
|
109963
|
+
}
|
|
109964
|
+
/**
|
|
109965
|
+
* Get hit rate percentage
|
|
109966
|
+
*/
|
|
109967
|
+
getHitRate() {
|
|
109968
|
+
const total = this.stats.hits + this.stats.misses;
|
|
109969
|
+
return total === 0 ? 0 : this.stats.hits / total * 100;
|
|
109970
|
+
}
|
|
109971
|
+
/**
|
|
109972
|
+
* Get all cached keys (for debugging)
|
|
109973
|
+
*/
|
|
109974
|
+
getKeys() {
|
|
109975
|
+
return Array.from(this.cache.keys());
|
|
109976
|
+
}
|
|
109977
|
+
/**
|
|
109978
|
+
* Get all cached values (for debugging)
|
|
109979
|
+
*/
|
|
109980
|
+
getValues() {
|
|
109981
|
+
return Array.from(this.cache.values()).map((entry) => entry.value);
|
|
109982
|
+
}
|
|
109983
|
+
/**
|
|
109984
|
+
* Get all cache entries with metadata (for debugging)
|
|
109985
|
+
*/
|
|
109986
|
+
getEntries() {
|
|
109987
|
+
return Array.from(this.cache.entries()).map(([key, entry]) => ({
|
|
109988
|
+
key,
|
|
109989
|
+
value: entry.value,
|
|
109990
|
+
metadata: {
|
|
109991
|
+
timestamp: entry.timestamp,
|
|
109992
|
+
hits: entry.hits,
|
|
109993
|
+
lastAccessed: entry.lastAccessed
|
|
109994
|
+
}
|
|
109995
|
+
}));
|
|
109996
|
+
}
|
|
109997
|
+
/**
|
|
109998
|
+
* Clean up expired entries
|
|
109999
|
+
*
|
|
110000
|
+
* Useful for periodic maintenance
|
|
110001
|
+
*
|
|
110002
|
+
* @returns Number of entries cleaned
|
|
109807
110003
|
*/
|
|
109808
110004
|
cleanExpired() {
|
|
109809
110005
|
const now = Date.now();
|
|
109810
|
-
let
|
|
110006
|
+
let cleanedCount = 0;
|
|
109811
110007
|
for (const [key, entry] of this.cache.entries()) {
|
|
109812
|
-
if (now - entry.timestamp >
|
|
110008
|
+
if (now - entry.timestamp > this.ttlMs) {
|
|
109813
110009
|
this.cache.delete(key);
|
|
109814
|
-
|
|
110010
|
+
cleanedCount++;
|
|
109815
110011
|
}
|
|
109816
110012
|
}
|
|
109817
|
-
|
|
110013
|
+
if (cleanedCount > 0 && this.debug) {
|
|
110014
|
+
console.log(`\u{1F9F9} [${this.name}] Cleaned ${cleanedCount} expired entries`);
|
|
110015
|
+
}
|
|
110016
|
+
return cleanedCount;
|
|
109818
110017
|
}
|
|
109819
110018
|
/**
|
|
109820
|
-
*
|
|
110019
|
+
* Check if cache entry is expired
|
|
109821
110020
|
*/
|
|
109822
|
-
|
|
109823
|
-
return
|
|
109824
|
-
|
|
109825
|
-
|
|
109826
|
-
|
|
109827
|
-
|
|
110021
|
+
isExpired(entry) {
|
|
110022
|
+
return Date.now() - entry.timestamp > this.ttlMs;
|
|
110023
|
+
}
|
|
110024
|
+
/**
|
|
110025
|
+
* Evict least recently used entry
|
|
110026
|
+
*/
|
|
110027
|
+
evictLRU() {
|
|
110028
|
+
let oldestKey = null;
|
|
110029
|
+
let oldestAccess = Infinity;
|
|
110030
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
110031
|
+
if (entry.lastAccessed < oldestAccess) {
|
|
110032
|
+
oldestAccess = entry.lastAccessed;
|
|
110033
|
+
oldestKey = key;
|
|
110034
|
+
}
|
|
110035
|
+
}
|
|
110036
|
+
if (oldestKey !== null) {
|
|
110037
|
+
this.cache.delete(oldestKey);
|
|
110038
|
+
this.stats.evictions++;
|
|
110039
|
+
if (this.debug) {
|
|
110040
|
+
const timeSinceAccess = Date.now() - oldestAccess;
|
|
110041
|
+
console.log(
|
|
110042
|
+
`\u267B\uFE0F [${this.name}] Cache EVICT (LRU): ${String(oldestKey)} (last accessed: ${timeSinceAccess}ms ago)`
|
|
110043
|
+
);
|
|
110044
|
+
}
|
|
110045
|
+
}
|
|
110046
|
+
}
|
|
110047
|
+
/**
|
|
110048
|
+
* Get or compute value
|
|
110049
|
+
*
|
|
110050
|
+
* If key exists in cache, returns cached value.
|
|
110051
|
+
* Otherwise, computes value using provided function and caches it.
|
|
110052
|
+
*
|
|
110053
|
+
* @param key - Cache key
|
|
110054
|
+
* @param compute - Function to compute value if not in cache
|
|
110055
|
+
* @param ttl - Optional custom TTL for this entry
|
|
110056
|
+
* @returns Cached or computed value
|
|
110057
|
+
*/
|
|
110058
|
+
async getOrCompute(key, compute, ttl) {
|
|
110059
|
+
const cached = this.get(key);
|
|
110060
|
+
if (cached !== null) {
|
|
110061
|
+
return cached;
|
|
110062
|
+
}
|
|
110063
|
+
const existing = this.inflight.get(key);
|
|
110064
|
+
if (existing) {
|
|
110065
|
+
return existing;
|
|
110066
|
+
}
|
|
110067
|
+
const computePromise = (async () => {
|
|
110068
|
+
try {
|
|
110069
|
+
const value = await compute();
|
|
110070
|
+
this.set(key, value, ttl);
|
|
110071
|
+
return value;
|
|
110072
|
+
} finally {
|
|
110073
|
+
this.inflight.delete(key);
|
|
110074
|
+
}
|
|
110075
|
+
})();
|
|
110076
|
+
this.inflight.set(key, computePromise);
|
|
110077
|
+
return computePromise;
|
|
110078
|
+
}
|
|
110079
|
+
/**
|
|
110080
|
+
* Get or compute value with Result wrapper
|
|
110081
|
+
*/
|
|
110082
|
+
async getOrComputeResult(key, compute, ttl) {
|
|
110083
|
+
const cached = this.get(key);
|
|
110084
|
+
if (cached !== null) {
|
|
110085
|
+
return success(cached);
|
|
110086
|
+
}
|
|
110087
|
+
const existing = this.inflightResult.get(key);
|
|
110088
|
+
if (existing) {
|
|
110089
|
+
return existing;
|
|
110090
|
+
}
|
|
110091
|
+
const computePromise = (async () => {
|
|
110092
|
+
try {
|
|
110093
|
+
return await compute();
|
|
110094
|
+
} finally {
|
|
110095
|
+
this.inflightResult.delete(key);
|
|
110096
|
+
}
|
|
110097
|
+
})();
|
|
110098
|
+
this.inflightResult.set(key, computePromise);
|
|
110099
|
+
const result = await computePromise;
|
|
110100
|
+
if (result.success) {
|
|
110101
|
+
this.set(key, result.value, ttl);
|
|
110102
|
+
}
|
|
110103
|
+
return result;
|
|
109828
110104
|
}
|
|
109829
110105
|
};
|
|
109830
110106
|
var CacheManager = class {
|
|
109831
110107
|
caches = /* @__PURE__ */ new Map();
|
|
109832
|
-
|
|
109833
|
-
constructor(
|
|
109834
|
-
this.
|
|
110108
|
+
globalConfig;
|
|
110109
|
+
constructor(globalConfig = {}) {
|
|
110110
|
+
this.globalConfig = globalConfig;
|
|
109835
110111
|
}
|
|
109836
110112
|
/**
|
|
109837
|
-
*
|
|
110113
|
+
* Create or get a named cache
|
|
110114
|
+
*
|
|
110115
|
+
* @param name - Unique cache name
|
|
110116
|
+
* @param config - Optional cache-specific configuration
|
|
110117
|
+
* @returns LRU cache instance
|
|
109838
110118
|
*/
|
|
109839
110119
|
getCache(name, config) {
|
|
109840
|
-
|
|
109841
|
-
|
|
110120
|
+
const existingCache = this.caches.get(name);
|
|
110121
|
+
if (existingCache) {
|
|
110122
|
+
return existingCache;
|
|
109842
110123
|
}
|
|
109843
|
-
const
|
|
110124
|
+
const mergedConfig = {
|
|
110125
|
+
...this.globalConfig,
|
|
110126
|
+
...config,
|
|
110127
|
+
name
|
|
110128
|
+
};
|
|
110129
|
+
const cache = new LRUCache(mergedConfig);
|
|
109844
110130
|
this.caches.set(name, cache);
|
|
109845
|
-
if (this.debug) {
|
|
109846
|
-
console.log(`[CacheManager] Created cache: ${name}`, config);
|
|
109847
|
-
}
|
|
109848
110131
|
return cache;
|
|
109849
110132
|
}
|
|
109850
110133
|
/**
|
|
@@ -109859,11 +110142,11 @@ var CacheManager = class {
|
|
|
109859
110142
|
* Clean expired entries from all caches
|
|
109860
110143
|
*/
|
|
109861
110144
|
cleanAllExpired() {
|
|
109862
|
-
let
|
|
110145
|
+
let totalCleaned = 0;
|
|
109863
110146
|
for (const cache of this.caches.values()) {
|
|
109864
|
-
|
|
110147
|
+
totalCleaned += cache.cleanExpired();
|
|
109865
110148
|
}
|
|
109866
|
-
return
|
|
110149
|
+
return totalCleaned;
|
|
109867
110150
|
}
|
|
109868
110151
|
/**
|
|
109869
110152
|
* Get statistics for all caches
|
|
@@ -109876,11 +110159,16 @@ var CacheManager = class {
|
|
|
109876
110159
|
return stats;
|
|
109877
110160
|
}
|
|
109878
110161
|
/**
|
|
109879
|
-
*
|
|
110162
|
+
* Get list of all cache names
|
|
109880
110163
|
*/
|
|
109881
|
-
|
|
109882
|
-
this.
|
|
109883
|
-
|
|
110164
|
+
getCacheNames() {
|
|
110165
|
+
return Array.from(this.caches.keys());
|
|
110166
|
+
}
|
|
110167
|
+
/**
|
|
110168
|
+
* Delete a named cache
|
|
110169
|
+
*/
|
|
110170
|
+
deleteCache(name) {
|
|
110171
|
+
return this.caches.delete(name);
|
|
109884
110172
|
}
|
|
109885
110173
|
};
|
|
109886
110174
|
function createCacheManager(config) {
|
|
@@ -118373,12 +118661,11 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
118373
118661
|
{}
|
|
118374
118662
|
);
|
|
118375
118663
|
}
|
|
118376
|
-
|
|
118377
|
-
|
|
118378
|
-
|
|
118379
|
-
const errorMsg = error2.message || String(error2);
|
|
118664
|
+
const result = await this._requestMintUCDAttempt(request);
|
|
118665
|
+
if (!result.success && fullRetry < MAX_FULL_RETRIES) {
|
|
118666
|
+
const errorMsg = result.error || "";
|
|
118380
118667
|
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
|
|
118668
|
+
if (isStaleTimestamp) {
|
|
118382
118669
|
if (this.config.debug) {
|
|
118383
118670
|
log.warn(
|
|
118384
118671
|
`\u26A0\uFE0F Timestamp became stale during mint process. Retrying from beginning...`,
|
|
@@ -118388,8 +118675,8 @@ var DiamondHandsSDK = class _DiamondHandsSDK {
|
|
|
118388
118675
|
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
118389
118676
|
continue;
|
|
118390
118677
|
}
|
|
118391
|
-
throw error2;
|
|
118392
118678
|
}
|
|
118679
|
+
return result;
|
|
118393
118680
|
}
|
|
118394
118681
|
return {
|
|
118395
118682
|
success: false,
|
|
@@ -119011,6 +119298,7 @@ Context: Quantum timestamp=${validationResponse.timestamp}, Position=${request.p
|
|
|
119011
119298
|
"0x131d9a21": "QuantumExpired()",
|
|
119012
119299
|
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
119013
119300
|
"0x137f3b70": "InDeadZone()",
|
|
119301
|
+
"0xbe4b82c1": "DeadZoneViolation()",
|
|
119014
119302
|
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
119015
119303
|
"0x62278171": "InvalidValidatorSignature()",
|
|
119016
119304
|
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
@@ -119031,7 +119319,7 @@ Mint/debt diagnostics (LoanOperationsManager mint path \u2192 increaseDebtFromMi
|
|
|
119031
119319
|
Contract expects UCD supply increase to match mintAmount+mintFee and debt update to newDebt.
|
|
119032
119320
|
` : "";
|
|
119033
119321
|
let quantumContext = "";
|
|
119034
|
-
if (selector === "0x131d9a21" || selector === "0x52ce5d58" || selector === "0x137f3b70" || selector === "0x3e76a3c9") {
|
|
119322
|
+
if (selector === "0x131d9a21" || selector === "0x52ce5d58" || selector === "0x137f3b70" || selector === "0xbe4b82c1" || selector === "0x3e76a3c9") {
|
|
119035
119323
|
const currentTime2 = Math.floor(Date.now() / 1e3);
|
|
119036
119324
|
const currentQuantum = Math.floor(currentTime2 / 60) * 60;
|
|
119037
119325
|
const sigQuantum2 = Math.floor(validationResponse.timestamp / 60) * 60;
|
|
@@ -119293,6 +119581,7 @@ Position: ${request.positionId}`
|
|
|
119293
119581
|
validationResponse.timestamp,
|
|
119294
119582
|
signatureHexMint
|
|
119295
119583
|
]);
|
|
119584
|
+
await awaitSafeSubmissionWindow(Number(validationResponse.timestamp));
|
|
119296
119585
|
const fromAddress = await signer.getAddress();
|
|
119297
119586
|
const estimatedGas = await estimateContractCallGasWithMargin(
|
|
119298
119587
|
signerProvider,
|
|
@@ -119351,6 +119640,7 @@ Position: ${request.positionId}`
|
|
|
119351
119640
|
"0x131d9a21": "QuantumExpired()",
|
|
119352
119641
|
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
119353
119642
|
"0x137f3b70": "InDeadZone()",
|
|
119643
|
+
"0xbe4b82c1": "DeadZoneViolation()",
|
|
119354
119644
|
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
119355
119645
|
"0x62278171": "InvalidValidatorSignature()",
|
|
119356
119646
|
"0xb9d419a7": "DebtUpdateVerificationFailed()",
|
|
@@ -119530,6 +119820,7 @@ Error data: ${errorData || "none"}`
|
|
|
119530
119820
|
"0x131d9a21": "QuantumExpired() - Signature quantum window has closed",
|
|
119531
119821
|
"0x52ce5d58": "QuantumAlreadyUsed() - This quantum was already used for this position",
|
|
119532
119822
|
"0x137f3b70": "InDeadZone() - Timestamp in dead zone (near quantum boundary)",
|
|
119823
|
+
"0xbe4b82c1": "DeadZoneViolation() - Non-current-quantum signature mined in the last 8s of the current quantum",
|
|
119533
119824
|
"0x3e76a3c9": "QuantumOutsideWindow() - Timestamp not in past/current/next quantum window"
|
|
119534
119825
|
};
|
|
119535
119826
|
const errorName = knownErrors[selector] || `Unknown error ${selector}`;
|
|
@@ -120598,6 +120889,7 @@ Error data: ${errorData || "none"}`
|
|
|
120598
120889
|
);
|
|
120599
120890
|
}
|
|
120600
120891
|
const positionManager = positionManagerResult.value;
|
|
120892
|
+
await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
120601
120893
|
const tx = await positionManager["extendPosition"](
|
|
120602
120894
|
positionIdBytes32,
|
|
120603
120895
|
BigInt(_selectedTerm),
|
|
@@ -121030,6 +121322,57 @@ Error data: ${errorData || "none"}`
|
|
|
121030
121322
|
if (!pauseCheck.ok) {
|
|
121031
121323
|
return { success: false, error: pauseCheck.error };
|
|
121032
121324
|
}
|
|
121325
|
+
const MAX_FULL_RETRIES = 3;
|
|
121326
|
+
for (let fullRetry = 1; fullRetry <= MAX_FULL_RETRIES; fullRetry++) {
|
|
121327
|
+
if (fullRetry > 1 && this.config.debug) {
|
|
121328
|
+
log.info(
|
|
121329
|
+
`\u{1F504} Full payment retry ${fullRetry}/${MAX_FULL_RETRIES} due to quantum-timing failure...`,
|
|
121330
|
+
{}
|
|
121331
|
+
);
|
|
121332
|
+
}
|
|
121333
|
+
const result = await this._makePaymentAttempt(request);
|
|
121334
|
+
if (fullRetry < MAX_FULL_RETRIES && this.isRetryablePaymentQuantumFailure(result)) {
|
|
121335
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
121336
|
+
continue;
|
|
121337
|
+
}
|
|
121338
|
+
return result;
|
|
121339
|
+
}
|
|
121340
|
+
return {
|
|
121341
|
+
success: false,
|
|
121342
|
+
error: "Max retries exceeded for payment operation"
|
|
121343
|
+
};
|
|
121344
|
+
} finally {
|
|
121345
|
+
this.invalidateCachesForPosition(request.positionId);
|
|
121346
|
+
this.releaseWriteLock(request.positionId);
|
|
121347
|
+
}
|
|
121348
|
+
}
|
|
121349
|
+
/**
|
|
121350
|
+
* Whether a failed payment attempt is a quantum-timing failure that a fresh
|
|
121351
|
+
* re-sign can fix (safe to retry), versus a terminal failure.
|
|
121352
|
+
*
|
|
121353
|
+
* Retryable: pre-send simulation quantum errors, or an atomic mined revert
|
|
121354
|
+
* (status 0) — no funds moved and the quantum was not recorded on-chain, so a
|
|
121355
|
+
* fresh signature + resubmit is safe.
|
|
121356
|
+
*
|
|
121357
|
+
* NOT retryable: a confirmation timeout — the original tx may still be pending, so
|
|
121358
|
+
* a resubmit could double-pay. It is surfaced (with its tx hash) instead.
|
|
121359
|
+
*/
|
|
121360
|
+
isRetryablePaymentQuantumFailure(result) {
|
|
121361
|
+
if (result.success || !result.error)
|
|
121362
|
+
return false;
|
|
121363
|
+
const e = result.error;
|
|
121364
|
+
if (e.includes("Transaction timeout"))
|
|
121365
|
+
return false;
|
|
121366
|
+
return e.includes("DeadZoneViolation") || e.includes("QuantumOutsideWindow") || e.includes("QuantumAlreadyUsed") || e.includes("QuantumExpired") || e === "Transaction reverted";
|
|
121367
|
+
}
|
|
121368
|
+
/**
|
|
121369
|
+
* One payment attempt: user auth → Lit Action authorization → dead-zone gate →
|
|
121370
|
+
* pre-send simulation → broadcast → confirmation. Always resolves to a
|
|
121371
|
+
* PartialPaymentResult (never throws to the caller); the makePayment wrapper owns
|
|
121372
|
+
* the write lock, the pause pre-check, and the bounded re-sign retry loop.
|
|
121373
|
+
*/
|
|
121374
|
+
async _makePaymentAttempt(request) {
|
|
121375
|
+
try {
|
|
121033
121376
|
if (this.config.debug) {
|
|
121034
121377
|
log.info(`\u{1F4B3} Making payment...`, {});
|
|
121035
121378
|
log.info(` Request object:`, { request });
|
|
@@ -121290,7 +121633,6 @@ Error data: ${errorData || "none"}`
|
|
|
121290
121633
|
error: `Failed to get PositionManager: ${positionManagerResult.error.message}`
|
|
121291
121634
|
};
|
|
121292
121635
|
}
|
|
121293
|
-
const positionManager = positionManagerResult.value;
|
|
121294
121636
|
if (this.config.debug) {
|
|
121295
121637
|
log.info(
|
|
121296
121638
|
` About to call toBytes32 with: ${request.positionId} (type: ${typeof request.positionId})`
|
|
@@ -121350,9 +121692,6 @@ Error data: ${errorData || "none"}`
|
|
|
121350
121692
|
currentQuantum
|
|
121351
121693
|
});
|
|
121352
121694
|
}
|
|
121353
|
-
if (this.config.debug) {
|
|
121354
|
-
log.info("\u23ED\uFE0F Skipping dead zone check to isolate BigNumber issue", {});
|
|
121355
|
-
}
|
|
121356
121695
|
if (this.config.debug) {
|
|
121357
121696
|
log.info("\u{1F50D} Final timestamp validation:", {
|
|
121358
121697
|
litActionTimestamp: litActionResult.timestamp,
|
|
@@ -121419,108 +121758,100 @@ Error data: ${errorData || "none"}`
|
|
|
121419
121758
|
quantumTimestamp: quantumTimestamp.toString()
|
|
121420
121759
|
});
|
|
121421
121760
|
}
|
|
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)
|
|
121761
|
+
await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
121762
|
+
const paymentAmountStr = paymentAmountWei.toString();
|
|
121763
|
+
const quantumTimestampStr = quantumTimestamp.toString();
|
|
121764
|
+
const btcPriceStr = btcPrice.toString();
|
|
121765
|
+
const paymentContractAddress = this.getContractAddressesOrThrow().positionManager;
|
|
121766
|
+
const paymentSigner = this.getSignerOrThrow();
|
|
121767
|
+
const paymentFrom = await paymentSigner.getAddress();
|
|
121768
|
+
const paymentProvider = contractManager.getProvider();
|
|
121769
|
+
const paymentIface = new Interface([
|
|
121770
|
+
"function makePayment(bytes32 positionId, uint256 paymentAmount, uint256 quantumTimestamp, uint256 btcPrice, bytes calldata paymentValidatorSignature) external returns (bool)"
|
|
121771
|
+
]);
|
|
121772
|
+
const paymentCalldata = paymentIface.encodeFunctionData("makePayment", [
|
|
121773
|
+
positionIdBytes32,
|
|
121774
|
+
paymentAmountStr,
|
|
121775
|
+
quantumTimestampStr,
|
|
121776
|
+
btcPriceStr,
|
|
121777
|
+
signature
|
|
121778
|
+
]);
|
|
121779
|
+
const decodePaymentRevert = (e) => {
|
|
121780
|
+
const raw = e?.data ?? e?.info?.error?.data ?? e?.error?.data?.data ?? e?.error?.data;
|
|
121781
|
+
const data = typeof raw === "string" ? raw : void 0;
|
|
121782
|
+
if (!data || !data.startsWith("0x") || data.length < 10)
|
|
121783
|
+
return null;
|
|
121784
|
+
const selector = data.slice(0, 10);
|
|
121785
|
+
const map3 = {
|
|
121786
|
+
"0xbe4b82c1": "DeadZoneViolation()",
|
|
121787
|
+
"0x137f3b70": "InDeadZone()",
|
|
121788
|
+
"0x52ce5d58": "QuantumAlreadyUsed()",
|
|
121789
|
+
"0x3e76a3c9": "QuantumOutsideWindow()",
|
|
121790
|
+
"0x131d9a21": "QuantumExpired()",
|
|
121791
|
+
"0x8baa579f": "InvalidSignature()",
|
|
121792
|
+
"0x62278171": "InvalidValidatorSignature()",
|
|
121793
|
+
"0x3ee5aeb5": "OperationNotAuthorized()",
|
|
121794
|
+
"0x48f5c3ed": "Unauthorized()"
|
|
121795
|
+
};
|
|
121796
|
+
return map3[selector] ?? `Unknown error ${selector}`;
|
|
121797
|
+
};
|
|
121798
|
+
const MAX_DEADZONE_RESIMULATIONS = 3;
|
|
121799
|
+
for (let sim = 1; ; sim++) {
|
|
121800
|
+
try {
|
|
121801
|
+
await paymentProvider.call({
|
|
121802
|
+
to: paymentContractAddress,
|
|
121803
|
+
from: paymentFrom,
|
|
121804
|
+
data: paymentCalldata
|
|
121479
121805
|
});
|
|
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)
|
|
121806
|
+
break;
|
|
121807
|
+
} catch (simError) {
|
|
121808
|
+
const decoded = decodePaymentRevert(simError);
|
|
121809
|
+
if (decoded === "DeadZoneViolation()" && sim <= MAX_DEADZONE_RESIMULATIONS) {
|
|
121810
|
+
const nowSec = Math.floor(Date.now() / 1e3);
|
|
121811
|
+
const sigQuantum = Math.floor(Number(quantumTimestamp) / 60) * 60;
|
|
121812
|
+
const realCurrentQuantum = Math.floor(nowSec / 60) * 60;
|
|
121813
|
+
if (sigQuantum === realCurrentQuantum) {
|
|
121814
|
+
if (this.config.debug) {
|
|
121815
|
+
log.info(
|
|
121816
|
+
"\u21AA\uFE0F Simulated DeadZoneViolation is a stale-latest-block artifact (signature is the current quantum) \u2014 proceeding to broadcast",
|
|
121817
|
+
{}
|
|
121818
|
+
);
|
|
121819
|
+
}
|
|
121820
|
+
break;
|
|
121497
121821
|
}
|
|
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
|
-
});
|
|
121822
|
+
const gate = await awaitSafeSubmissionWindow(Number(quantumTimestamp));
|
|
121823
|
+
if (gate.waited) {
|
|
121824
|
+
if (this.config.debug) {
|
|
121825
|
+
log.info(
|
|
121826
|
+
`\u{1F501} Re-simulating makePayment after crossing the quantum boundary (attempt ${sim}/${MAX_DEADZONE_RESIMULATIONS})`,
|
|
121827
|
+
{}
|
|
121828
|
+
);
|
|
121829
|
+
}
|
|
121830
|
+
continue;
|
|
121831
|
+
}
|
|
121832
|
+
}
|
|
121833
|
+
const label = decoded ?? simError?.reason ?? simError?.shortMessage ?? (simError instanceof Error ? simError.message : String(simError));
|
|
121834
|
+
if (this.config.debug) {
|
|
121835
|
+
log.error("\u274C makePayment pre-send simulation reverted", { error: label });
|
|
121836
|
+
}
|
|
121837
|
+
return {
|
|
121838
|
+
success: false,
|
|
121839
|
+
error: `Payment would revert (pre-send simulation): ${label}`,
|
|
121840
|
+
positionId: request.positionId,
|
|
121841
|
+
paymentAmountUCD: request.paymentAmount
|
|
121842
|
+
};
|
|
121522
121843
|
}
|
|
121523
121844
|
}
|
|
121845
|
+
const MAKE_PAYMENT_GAS_CEILING = 500000n;
|
|
121846
|
+
const tx = await sendEip1559Transaction({
|
|
121847
|
+
signer: paymentSigner,
|
|
121848
|
+
to: paymentContractAddress,
|
|
121849
|
+
data: paymentCalldata,
|
|
121850
|
+
gasLimit: MAKE_PAYMENT_GAS_CEILING
|
|
121851
|
+
});
|
|
121852
|
+
if (this.config.debug) {
|
|
121853
|
+
log.info("\u2705 makePayment broadcast", { txHash: tx.hash });
|
|
121854
|
+
}
|
|
121524
121855
|
if (this.config.debug) {
|
|
121525
121856
|
log.info(`\u{1F4E4} Transaction sent: ${tx.hash}`);
|
|
121526
121857
|
log.info("\u23F3 Waiting for transaction confirmation...");
|
|
@@ -121664,9 +121995,6 @@ Error data: ${errorData || "none"}`
|
|
|
121664
121995
|
result.effectiveGasPrice = receipt.effectiveGasPrice?.toString() || receipt.gasPrice?.toString();
|
|
121665
121996
|
}
|
|
121666
121997
|
return result;
|
|
121667
|
-
} finally {
|
|
121668
|
-
this.invalidateCachesForPosition(request.positionId);
|
|
121669
|
-
this.releaseWriteLock(request.positionId);
|
|
121670
121998
|
}
|
|
121671
121999
|
}
|
|
121672
122000
|
/**
|
|
@@ -122228,6 +122556,7 @@ Error data: ${errorData || "none"}`
|
|
|
122228
122556
|
utxoVout: withdrawalParams.utxoVout
|
|
122229
122557
|
});
|
|
122230
122558
|
}
|
|
122559
|
+
await awaitSafeSubmissionWindow(Number(withdrawalParams.quantumTimestamp));
|
|
122231
122560
|
let tx;
|
|
122232
122561
|
try {
|
|
122233
122562
|
tx = await positionManagerContract["withdrawBTC"](
|
|
@@ -124449,7 +124778,7 @@ export {
|
|
|
124449
124778
|
ErrorSeverity,
|
|
124450
124779
|
EventHelpers,
|
|
124451
124780
|
LOCALHOST_CONTRACTS,
|
|
124452
|
-
|
|
124781
|
+
LRUCache,
|
|
124453
124782
|
LoanCreator,
|
|
124454
124783
|
LoanQuery,
|
|
124455
124784
|
LoanStatus,
|