@secondlayer/stacks 4.3.2 → 5.0.1
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/README.md +27 -11
- package/dist/shared/{stacks-bfan7ex7.js → stacks-4d7c3x27.js} +5 -5
- package/dist/shared/{stacks-bfan7ex7.js.map → stacks-4d7c3x27.js.map} +3 -3
- package/dist/shared/{stacks-709tra19.js → stacks-4hs8r4q2.js} +16 -2
- package/dist/shared/stacks-4hs8r4q2.js.map +10 -0
- package/dist/shared/{stacks-w23294am.js → stacks-51ybf135.js} +3 -3
- package/dist/shared/{stacks-0jk7vd8r.cjs → stacks-69nq48jp.js} +120 -17
- package/dist/shared/stacks-69nq48jp.js.map +15 -0
- package/dist/shared/{stacks-8pfdscq6.js → stacks-6gavarmy.js} +37 -9
- package/dist/shared/stacks-6gavarmy.js.map +12 -0
- package/dist/shared/{stacks-gxq2pbky.js → stacks-71k0vmct.js} +65 -8
- package/dist/shared/stacks-71k0vmct.js.map +13 -0
- package/dist/shared/{stacks-7wkf2rph.js → stacks-7bqkf3b0.js} +86 -71
- package/dist/shared/{stacks-7wkf2rph.js.map → stacks-7bqkf3b0.js.map} +9 -10
- package/dist/shared/{stacks-zcpvzbr0.js → stacks-8brgfvqx.js} +3 -3
- package/dist/shared/{stacks-4vzmhw3q.cjs → stacks-8vzxax5e.cjs} +13 -3
- package/dist/shared/stacks-8vzxax5e.cjs.map +10 -0
- package/dist/shared/{stacks-hnqt5rz4.js → stacks-9c1yam8b.js} +3 -3
- package/dist/shared/{stacks-bnbdqznq.cjs → stacks-bdgh9n83.cjs} +11 -10
- package/dist/shared/{stacks-bnbdqznq.cjs.map → stacks-bdgh9n83.cjs.map} +3 -3
- package/dist/shared/{stacks-fb75yew8.js → stacks-db3kwavg.cjs} +346 -138
- package/dist/shared/stacks-db3kwavg.cjs.map +23 -0
- package/dist/shared/{stacks-jpt52csy.js → stacks-e3nwm1dz.js} +14 -17
- package/dist/shared/stacks-e3nwm1dz.js.map +10 -0
- package/dist/shared/{stacks-ta1gar0b.cjs → stacks-ee53k9j2.cjs} +62 -6
- package/dist/shared/stacks-ee53k9j2.cjs.map +13 -0
- package/dist/shared/{stacks-27fmgajb.js → stacks-ga026yxz.js} +9 -9
- package/dist/shared/{stacks-27fmgajb.js.map → stacks-ga026yxz.js.map} +3 -3
- package/dist/shared/{stacks-nyaw1z2a.cjs → stacks-ggdz96r1.cjs} +4 -4
- package/dist/shared/{stacks-nyaw1z2a.cjs.map → stacks-ggdz96r1.cjs.map} +3 -3
- package/dist/shared/{stacks-08y0y0t7.js → stacks-gjz26k6b.js} +2 -2
- package/dist/shared/{stacks-x5386y2y.cjs → stacks-gza2n1zs.cjs} +5 -5
- package/dist/shared/{stacks-x5386y2y.cjs.map → stacks-gza2n1zs.cjs.map} +3 -3
- package/dist/shared/{stacks-ztzygy90.js → stacks-mftyrc60.js} +2 -2
- package/dist/shared/stacks-n4d8j8q3.js +801 -0
- package/dist/shared/stacks-n4d8j8q3.js.map +23 -0
- package/dist/shared/{stacks-ycbq8pf7.cjs → stacks-p337hp6m.cjs} +74 -59
- package/dist/shared/{stacks-ycbq8pf7.cjs.map → stacks-p337hp6m.cjs.map} +9 -10
- package/dist/shared/{stacks-ttdk2g2f.js → stacks-s5vej5z6.cjs} +92 -41
- package/dist/shared/stacks-s5vej5z6.cjs.map +15 -0
- package/dist/shared/stacks-sdqkapct.cjs +67 -0
- package/dist/shared/stacks-sdqkapct.cjs.map +12 -0
- package/dist/shared/{stacks-1arrcd11.js → stacks-v2rfr46a.js} +2 -2
- package/dist/shared/{stacks-9mqveyjv.cjs → stacks-w9t61fra.cjs} +7 -10
- package/dist/shared/stacks-w9t61fra.cjs.map +10 -0
- package/dist/shared/{stacks-tjjnkt3r.js → stacks-wxfd6r4b.js} +2 -2
- package/dist/shared/{stacks-4z72akdf.js → stacks-x0qqwrev.js} +3 -3
- package/dist/shared/{stacks-gck1sq7h.cjs → stacks-xjkn3en1.cjs} +16 -2
- package/dist/shared/stacks-xjkn3en1.cjs.map +10 -0
- package/dist/shared/stacks-xnrywjf1.cjs +131 -0
- package/dist/shared/stacks-xnrywjf1.cjs.map +11 -0
- package/dist/shared/stacks-yajyej2y.js +139 -0
- package/dist/shared/stacks-yajyej2y.js.map +11 -0
- package/dist/shared/{stacks-913a2rx7.js → stacks-yvb7rvwk.js} +13 -3
- package/dist/shared/stacks-yvb7rvwk.js.map +10 -0
- package/dist/shared/{stacks-0cdm20eh.js → stacks-z90xdr1x.js} +7 -11
- package/dist/shared/{stacks-0cdm20eh.js.map → stacks-z90xdr1x.js.map} +3 -3
- package/dist/src/accounts/index.js +2 -3
- package/dist/src/accounts/index.js.map +2 -2
- package/dist/src/actions/index.cjs +2 -1
- package/dist/src/actions/index.cjs.map +1 -1
- package/dist/src/actions/index.d.cts +108 -20
- package/dist/src/actions/index.d.ts +108 -20
- package/dist/src/actions/index.js +17 -15
- package/dist/src/actions/index.js.map +1 -1
- package/dist/src/bitcoin/index.d.cts +27 -0
- package/dist/src/bitcoin/index.d.ts +27 -0
- package/dist/src/bitcoin/index.js +10 -11
- package/dist/src/bitcoin/index.js.map +2 -2
- package/dist/src/bns/index.d.cts +27 -0
- package/dist/src/bns/index.d.ts +27 -0
- package/dist/src/bns/index.js +13 -13
- package/dist/src/bns/index.js.map +1 -1
- package/dist/src/clarity/index.js +7 -6
- package/dist/src/clarity/index.js.map +1 -1
- package/dist/src/connect/index.cjs +44 -30
- package/dist/src/connect/index.cjs.map +7 -7
- package/dist/src/connect/index.d.cts +16 -1
- package/dist/src/connect/index.d.ts +16 -1
- package/dist/src/connect/index.js +44 -30
- package/dist/src/connect/index.js.map +7 -7
- package/dist/src/connect/walletconnect/index.cjs +49 -413
- package/dist/src/connect/walletconnect/index.cjs.map +4 -4
- package/dist/src/connect/walletconnect/index.js +47 -411
- package/dist/src/connect/walletconnect/index.js.map +4 -4
- package/dist/src/filters/index.js +2 -2
- package/dist/src/index.cjs +49 -124
- package/dist/src/index.cjs.map +6 -8
- package/dist/src/index.d.cts +163 -54
- package/dist/src/index.d.ts +163 -54
- package/dist/src/index.js +79 -147
- package/dist/src/index.js.map +6 -8
- package/dist/src/postconditions/index.js +6 -5
- package/dist/src/postconditions/index.js.map +1 -1
- package/dist/src/pox/index.cjs +7 -83
- package/dist/src/pox/index.cjs.map +3 -3
- package/dist/src/pox/index.d.cts +32 -1
- package/dist/src/pox/index.d.ts +32 -1
- package/dist/src/pox/index.js +22 -102
- package/dist/src/pox/index.js.map +3 -3
- package/dist/src/pox5/index.cjs +4 -112
- package/dist/src/pox5/index.cjs.map +3 -4
- package/dist/src/pox5/index.d.cts +27 -0
- package/dist/src/pox5/index.d.ts +27 -0
- package/dist/src/pox5/index.js +20 -131
- package/dist/src/pox5/index.js.map +3 -4
- package/dist/src/sbtc/index.cjs +2 -27
- package/dist/src/sbtc/index.cjs.map +3 -3
- package/dist/src/sbtc/index.d.cts +30 -2
- package/dist/src/sbtc/index.d.ts +30 -2
- package/dist/src/sbtc/index.js +15 -45
- package/dist/src/sbtc/index.js.map +3 -3
- package/dist/src/stackingdao/index.d.cts +27 -0
- package/dist/src/stackingdao/index.d.ts +27 -0
- package/dist/src/stackingdao/index.js +11 -11
- package/dist/src/stackingdao/index.js.map +1 -1
- package/dist/src/subscriptions/index.d.cts +27 -0
- package/dist/src/subscriptions/index.d.ts +27 -0
- package/dist/src/subscriptions/index.js +2 -2
- package/dist/src/tools/btc/index.cjs.map +2 -2
- package/dist/src/tools/btc/index.js.map +2 -2
- package/dist/src/tools/index.cjs +629 -392
- package/dist/src/tools/index.cjs.map +30 -28
- package/dist/src/tools/index.d.cts +44 -0
- package/dist/src/tools/index.d.ts +44 -0
- package/dist/src/tools/index.js +628 -391
- package/dist/src/tools/index.js.map +30 -28
- package/dist/src/transactions/index.js +6 -5
- package/dist/src/transactions/index.js.map +1 -1
- package/dist/src/utils/index.d.cts +2 -5
- package/dist/src/utils/index.d.ts +2 -5
- package/dist/src/utils/index.js +2 -2
- package/package.json +18 -7
- package/dist/shared/stacks-0eatsx6d.cjs +0 -25
- package/dist/shared/stacks-0eatsx6d.cjs.map +0 -10
- package/dist/shared/stacks-0jk7vd8r.cjs.map +0 -14
- package/dist/shared/stacks-4vzmhw3q.cjs.map +0 -10
- package/dist/shared/stacks-5nmz5ad9.js +0 -409
- package/dist/shared/stacks-5nmz5ad9.js.map +0 -10
- package/dist/shared/stacks-709tra19.js.map +0 -10
- package/dist/shared/stacks-8pfdscq6.js.map +0 -12
- package/dist/shared/stacks-913a2rx7.js.map +0 -10
- package/dist/shared/stacks-9mqveyjv.cjs.map +0 -10
- package/dist/shared/stacks-e4xn4m7j.js +0 -27
- package/dist/shared/stacks-e4xn4m7j.js.map +0 -10
- package/dist/shared/stacks-fb75yew8.js.map +0 -21
- package/dist/shared/stacks-gck1sq7h.cjs.map +0 -10
- package/dist/shared/stacks-gxq2pbky.js.map +0 -13
- package/dist/shared/stacks-jpt52csy.js.map +0 -10
- package/dist/shared/stacks-mnnhpex3.cjs +0 -407
- package/dist/shared/stacks-mnnhpex3.cjs.map +0 -10
- package/dist/shared/stacks-ta1gar0b.cjs.map +0 -13
- package/dist/shared/stacks-tdsp5gsb.cjs +0 -527
- package/dist/shared/stacks-tdsp5gsb.cjs.map +0 -21
- package/dist/shared/stacks-ttdk2g2f.js.map +0 -14
- package/dist/shared/stacks-wdp5yr8n.cjs +0 -39
- package/dist/shared/stacks-wdp5yr8n.cjs.map +0 -12
- /package/dist/shared/{stacks-w23294am.js.map → stacks-51ybf135.js.map} +0 -0
- /package/dist/shared/{stacks-zcpvzbr0.js.map → stacks-8brgfvqx.js.map} +0 -0
- /package/dist/shared/{stacks-hnqt5rz4.js.map → stacks-9c1yam8b.js.map} +0 -0
- /package/dist/shared/{stacks-08y0y0t7.js.map → stacks-gjz26k6b.js.map} +0 -0
- /package/dist/shared/{stacks-ztzygy90.js.map → stacks-mftyrc60.js.map} +0 -0
- /package/dist/shared/{stacks-1arrcd11.js.map → stacks-v2rfr46a.js.map} +0 -0
- /package/dist/shared/{stacks-tjjnkt3r.js.map → stacks-wxfd6r4b.js.map} +0 -0
- /package/dist/shared/{stacks-4z72akdf.js.map → stacks-x0qqwrev.js.map} +0 -0
|
@@ -1,32 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MalformedResponseError
|
|
3
|
-
} from "./stacks-27fmgajb.js";
|
|
4
|
-
import {
|
|
5
|
-
BaseError
|
|
6
|
-
} from "./stacks-709tra19.js";
|
|
7
|
-
import {
|
|
8
|
-
buildContractCall,
|
|
9
|
-
getTransactionId,
|
|
10
|
-
signTransactionWithAccount
|
|
11
|
-
} from "./stacks-hnqt5rz4.js";
|
|
12
|
-
import {
|
|
13
|
-
clearTxCache,
|
|
14
|
-
serializePayload,
|
|
15
|
-
serializeTransaction
|
|
16
|
-
} from "./stacks-w23294am.js";
|
|
17
|
-
import {
|
|
18
|
-
deserializeCVBytes,
|
|
19
|
-
serializeCVBytes
|
|
20
|
-
} from "./stacks-ttdk2g2f.js";
|
|
21
|
-
import {
|
|
22
|
-
parseContractId
|
|
23
|
-
} from "./stacks-bfan7ex7.js";
|
|
24
|
-
import {
|
|
25
|
-
bytesToHex,
|
|
26
|
-
intToBigInt,
|
|
27
|
-
with0x
|
|
28
|
-
} from "./stacks-qs5fzts5.js";
|
|
29
|
-
|
|
30
1
|
// src/actions/public/estimateFee.ts
|
|
31
2
|
function isValidEstimation(e) {
|
|
32
3
|
return typeof e === "object" && e !== null && "fee_rate" in e && "fee" in e && (typeof e.fee_rate === "number" || typeof e.fee_rate === "string") && (typeof e.fee === "number" || typeof e.fee === "string");
|
|
@@ -66,9 +37,14 @@ async function getBlockHeight(client) {
|
|
|
66
37
|
class HttpRequestError extends BaseError {
|
|
67
38
|
name = "HttpRequestError";
|
|
68
39
|
status;
|
|
40
|
+
url;
|
|
41
|
+
method;
|
|
69
42
|
constructor(status, options) {
|
|
70
|
-
|
|
43
|
+
const where = options?.url !== undefined ? ` (${options.method ?? "GET"} ${options.url})` : "";
|
|
44
|
+
super(`HTTP request failed with status ${status}${where}`, options);
|
|
71
45
|
this.status = status;
|
|
46
|
+
this.url = options?.url;
|
|
47
|
+
this.method = options?.method;
|
|
72
48
|
}
|
|
73
49
|
}
|
|
74
50
|
|
|
@@ -98,12 +74,250 @@ async function getNonce(client, params) {
|
|
|
98
74
|
return BigInt(nonce);
|
|
99
75
|
}
|
|
100
76
|
|
|
77
|
+
// src/errors/transport.ts
|
|
78
|
+
class TimeoutError extends BaseError {
|
|
79
|
+
name = "TimeoutError";
|
|
80
|
+
method;
|
|
81
|
+
url;
|
|
82
|
+
timeout;
|
|
83
|
+
attempt;
|
|
84
|
+
constructor(params) {
|
|
85
|
+
super(`${params.method} ${params.url} did not complete within ${params.timeout}ms (attempt ${params.attempt + 1})`);
|
|
86
|
+
this.method = params.method;
|
|
87
|
+
this.url = params.url;
|
|
88
|
+
this.timeout = params.timeout;
|
|
89
|
+
this.attempt = params.attempt;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/transports/createTransport.ts
|
|
94
|
+
function createTransport(type, config) {
|
|
95
|
+
const { request, apiKey: _apiKey, ...exposed } = config;
|
|
96
|
+
return {
|
|
97
|
+
type,
|
|
98
|
+
request,
|
|
99
|
+
config: exposed
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
var MAX_ERROR_DETAILS_BYTES = 4096;
|
|
103
|
+
function capDetails(body) {
|
|
104
|
+
if (body === undefined)
|
|
105
|
+
return;
|
|
106
|
+
const bytes = new TextEncoder().encode(body);
|
|
107
|
+
if (bytes.length <= MAX_ERROR_DETAILS_BYTES)
|
|
108
|
+
return body;
|
|
109
|
+
const head = new TextDecoder().decode(bytes.subarray(0, MAX_ERROR_DETAILS_BYTES));
|
|
110
|
+
return `${head}... [truncated ${bytes.length - MAX_ERROR_DETAILS_BYTES} bytes]`;
|
|
111
|
+
}
|
|
112
|
+
function isRetryableStatus(status) {
|
|
113
|
+
return status === 429 || status >= 500;
|
|
114
|
+
}
|
|
115
|
+
var MAX_RETRY_AFTER_MS = 60000;
|
|
116
|
+
function retryAfterMs(response) {
|
|
117
|
+
const value = response.headers.get("Retry-After");
|
|
118
|
+
if (!value)
|
|
119
|
+
return;
|
|
120
|
+
const seconds = Number(value);
|
|
121
|
+
const ms = Number.isFinite(seconds) ? seconds * 1000 : Date.parse(value) - Date.now();
|
|
122
|
+
if (!Number.isFinite(ms) || ms < 0 || ms > MAX_RETRY_AFTER_MS)
|
|
123
|
+
return;
|
|
124
|
+
return ms;
|
|
125
|
+
}
|
|
126
|
+
function abortReason(signal) {
|
|
127
|
+
const reason = signal.reason;
|
|
128
|
+
if (reason instanceof Error)
|
|
129
|
+
return reason;
|
|
130
|
+
return new DOMException(typeof reason === "string" ? reason : "The operation was aborted", "AbortError");
|
|
131
|
+
}
|
|
132
|
+
function sleep(ms, signal) {
|
|
133
|
+
return new Promise((resolve, reject) => {
|
|
134
|
+
if (signal?.aborted)
|
|
135
|
+
return reject(abortReason(signal));
|
|
136
|
+
const onAbort = () => {
|
|
137
|
+
clearTimeout(id);
|
|
138
|
+
reject(abortReason(signal));
|
|
139
|
+
};
|
|
140
|
+
const id = setTimeout(() => {
|
|
141
|
+
signal?.removeEventListener("abort", onAbort);
|
|
142
|
+
resolve();
|
|
143
|
+
}, ms);
|
|
144
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
async function fetchWithRetry(url, options, retryCount, retryDelay, timeout, extra = {}) {
|
|
148
|
+
const { signal } = extra;
|
|
149
|
+
const read = extra.read ?? (async (response) => response);
|
|
150
|
+
const method = options.method ?? "GET";
|
|
151
|
+
let lastError;
|
|
152
|
+
for (let attempt = 0;attempt <= retryCount; attempt++) {
|
|
153
|
+
if (signal?.aborted)
|
|
154
|
+
throw abortReason(signal);
|
|
155
|
+
const controller = new AbortController;
|
|
156
|
+
let timedOut = false;
|
|
157
|
+
const timeoutId = setTimeout(() => {
|
|
158
|
+
timedOut = true;
|
|
159
|
+
controller.abort(new TimeoutError({ method, url, timeout, attempt }));
|
|
160
|
+
}, timeout);
|
|
161
|
+
const onCallerAbort = () => controller.abort(abortReason(signal));
|
|
162
|
+
signal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
163
|
+
const aborted = new Promise((_, reject) => {
|
|
164
|
+
if (controller.signal.aborted)
|
|
165
|
+
return reject(controller.signal.reason);
|
|
166
|
+
controller.signal.addEventListener("abort", () => reject(controller.signal.reason), { once: true });
|
|
167
|
+
});
|
|
168
|
+
let response;
|
|
169
|
+
try {
|
|
170
|
+
try {
|
|
171
|
+
response = await Promise.race([
|
|
172
|
+
fetch(url, { ...options, signal: controller.signal }),
|
|
173
|
+
aborted
|
|
174
|
+
]);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
if (signal?.aborted)
|
|
177
|
+
throw abortReason(signal);
|
|
178
|
+
lastError = timedOut ? new TimeoutError({ method, url, timeout, attempt }) : error instanceof Error ? error : new Error(String(error));
|
|
179
|
+
if (attempt < retryCount) {
|
|
180
|
+
clearTimeout(timeoutId);
|
|
181
|
+
await sleep(retryDelay * (attempt + 1), signal);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
throw lastError;
|
|
185
|
+
}
|
|
186
|
+
if (response.ok) {
|
|
187
|
+
try {
|
|
188
|
+
return await Promise.race([read(response), aborted]);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
response.body?.cancel().catch(() => {});
|
|
191
|
+
if (signal?.aborted)
|
|
192
|
+
throw abortReason(signal);
|
|
193
|
+
if (!timedOut)
|
|
194
|
+
throw error;
|
|
195
|
+
lastError = new TimeoutError({ method, url, timeout, attempt });
|
|
196
|
+
if (attempt < retryCount) {
|
|
197
|
+
clearTimeout(timeoutId);
|
|
198
|
+
await sleep(retryDelay * (attempt + 1), signal);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
throw lastError;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const retryable = isRetryableStatus(response.status);
|
|
205
|
+
if (!retryable || attempt === retryCount) {
|
|
206
|
+
const body = await Promise.race([
|
|
207
|
+
response.text().catch(() => {
|
|
208
|
+
return;
|
|
209
|
+
}),
|
|
210
|
+
aborted.catch(() => {
|
|
211
|
+
return;
|
|
212
|
+
})
|
|
213
|
+
]);
|
|
214
|
+
throw new HttpRequestError(response.status, {
|
|
215
|
+
details: capDetails(body),
|
|
216
|
+
url,
|
|
217
|
+
method
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
lastError = new HttpRequestError(response.status, { url, method });
|
|
221
|
+
const delay = retryAfterMs(response) ?? retryDelay * (attempt + 1);
|
|
222
|
+
response.body?.cancel().catch(() => {});
|
|
223
|
+
clearTimeout(timeoutId);
|
|
224
|
+
await sleep(delay, signal);
|
|
225
|
+
} finally {
|
|
226
|
+
clearTimeout(timeoutId);
|
|
227
|
+
signal?.removeEventListener("abort", onCallerAbort);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
throw lastError ?? new Error("Request failed");
|
|
231
|
+
}
|
|
232
|
+
async function readBody(response) {
|
|
233
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
234
|
+
if (contentType.includes("application/json")) {
|
|
235
|
+
return response.json();
|
|
236
|
+
}
|
|
237
|
+
return response.text();
|
|
238
|
+
}
|
|
239
|
+
function buildRequestFn(baseUrl, config) {
|
|
240
|
+
const {
|
|
241
|
+
timeout = 30000,
|
|
242
|
+
retryCount = 3,
|
|
243
|
+
retryDelay = 150,
|
|
244
|
+
fetchOptions = {},
|
|
245
|
+
apiKey
|
|
246
|
+
} = config;
|
|
247
|
+
return async (path, options) => {
|
|
248
|
+
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
249
|
+
const headers = {
|
|
250
|
+
"Content-Type": "application/json",
|
|
251
|
+
...fetchOptions.headers,
|
|
252
|
+
...options?.headers
|
|
253
|
+
};
|
|
254
|
+
if (apiKey) {
|
|
255
|
+
headers["x-api-key"] = apiKey;
|
|
256
|
+
}
|
|
257
|
+
const init = {
|
|
258
|
+
...fetchOptions,
|
|
259
|
+
method: options?.method ?? "GET",
|
|
260
|
+
headers
|
|
261
|
+
};
|
|
262
|
+
if (options?.body !== undefined) {
|
|
263
|
+
init.body = JSON.stringify(options.body);
|
|
264
|
+
}
|
|
265
|
+
return fetchWithRetry(url, init, options?.retryCount ?? retryCount, retryDelay, timeout, { signal: options?.signal, read: readBody });
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
101
269
|
// src/actions/public/txSources.ts
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
270
|
+
class IndexSourceConfigError extends Error {
|
|
271
|
+
name = "IndexSourceConfigError";
|
|
272
|
+
}
|
|
273
|
+
function isHiroHost(url, client) {
|
|
274
|
+
let hostname;
|
|
275
|
+
try {
|
|
276
|
+
hostname = new URL(url).hostname;
|
|
277
|
+
} catch {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
if (hostname === "hiro.so" || hostname.endsWith(".hiro.so"))
|
|
281
|
+
return true;
|
|
282
|
+
const defaults = client.chain?.rpcUrls?.default?.http ?? [];
|
|
283
|
+
return defaults.some((d) => {
|
|
284
|
+
try {
|
|
285
|
+
return new URL(d).hostname === hostname && hostname !== "localhost";
|
|
286
|
+
} catch {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
function indexRequestFn(client, baseUrl, sourceName) {
|
|
292
|
+
const transportUrl = client.transport.config.url?.replace(/\/$/, "");
|
|
293
|
+
if (baseUrl === undefined) {
|
|
294
|
+
if (!transportUrl) {
|
|
295
|
+
throw new IndexSourceConfigError(`${sourceName} needs the URL of your Secondlayer instance: pass baseUrl, or use an http() transport pointed at the instance`);
|
|
296
|
+
}
|
|
297
|
+
if (isHiroHost(transportUrl, client)) {
|
|
298
|
+
throw new IndexSourceConfigError(`${sourceName} reads /v1/index on a Secondlayer instance, and ${transportUrl} is a Hiro host: pass baseUrl with the URL of your instance`);
|
|
299
|
+
}
|
|
300
|
+
return client.request;
|
|
301
|
+
}
|
|
302
|
+
const target = baseUrl.replace(/\/$/, "");
|
|
303
|
+
if (target === transportUrl)
|
|
304
|
+
return client.request;
|
|
305
|
+
const { timeout, retryCount, retryDelay } = client.transport.config;
|
|
306
|
+
return buildRequestFn(target, { timeout, retryCount, retryDelay });
|
|
307
|
+
}
|
|
308
|
+
function indexNotFound(error, sourceName) {
|
|
309
|
+
if (!(error instanceof HttpRequestError) || error.status !== 404) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
const body = error.details;
|
|
313
|
+
if (body !== undefined) {
|
|
314
|
+
try {
|
|
315
|
+
JSON.parse(body);
|
|
316
|
+
} catch {
|
|
317
|
+
throw new IndexSourceConfigError(`${sourceName} got a non-JSON 404 from ${error.url ?? "the transport host"}: it does not serve /v1/index, pass baseUrl with the URL of your Secondlayer instance`, { cause: error });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return true;
|
|
107
321
|
}
|
|
108
322
|
function normalizeTxid(txid) {
|
|
109
323
|
return txid.startsWith("0x") ? txid : `0x${txid}`;
|
|
@@ -133,9 +347,7 @@ function extendedApiSource() {
|
|
|
133
347
|
async get({ client, txid }) {
|
|
134
348
|
let data;
|
|
135
349
|
try {
|
|
136
|
-
data = await client.request(`/extended/v1/tx/${normalizeTxid(txid)}`, {
|
|
137
|
-
method: "GET"
|
|
138
|
-
});
|
|
350
|
+
data = await client.request(`/extended/v1/tx/${encodeURIComponent(normalizeTxid(txid))}`, { method: "GET" });
|
|
139
351
|
} catch (error) {
|
|
140
352
|
if (error instanceof HttpRequestError && error.status === 404) {
|
|
141
353
|
return { receipt: null };
|
|
@@ -163,20 +375,22 @@ function extendedApiSource() {
|
|
|
163
375
|
};
|
|
164
376
|
}
|
|
165
377
|
function indexTxSource(params = {}) {
|
|
166
|
-
const
|
|
167
|
-
const fetchImpl = resolveFetch(params.fetchImpl);
|
|
378
|
+
const headers = params.apiKey ? { authorization: `Bearer ${params.apiKey}` } : undefined;
|
|
168
379
|
return {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
380
|
+
canonicalOnly: true,
|
|
381
|
+
async get({ client, txid }) {
|
|
382
|
+
const request = indexRequestFn(client, params.baseUrl, "indexTxSource");
|
|
383
|
+
let data;
|
|
384
|
+
try {
|
|
385
|
+
data = await request(`/v1/index/transactions/${normalizeTxid(txid)}`, {
|
|
386
|
+
method: "GET",
|
|
387
|
+
headers
|
|
388
|
+
});
|
|
389
|
+
} catch (error) {
|
|
390
|
+
if (indexNotFound(error, "indexTxSource"))
|
|
391
|
+
return { receipt: null };
|
|
392
|
+
throw error;
|
|
178
393
|
}
|
|
179
|
-
const data = await res.json();
|
|
180
394
|
const tx = data.transaction;
|
|
181
395
|
const tip = data.tip?.block_height;
|
|
182
396
|
if (!tx)
|
|
@@ -197,70 +411,24 @@ function indexTxSource(params = {}) {
|
|
|
197
411
|
};
|
|
198
412
|
}
|
|
199
413
|
|
|
200
|
-
// src/
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
class BroadcastError extends BaseError {
|
|
206
|
-
name = "BroadcastError";
|
|
207
|
-
txid;
|
|
208
|
-
reason;
|
|
209
|
-
reasonData;
|
|
210
|
-
constructor(message, options) {
|
|
211
|
-
super(message, options);
|
|
212
|
-
this.txid = options?.txid;
|
|
213
|
-
this.reason = options?.reason;
|
|
214
|
-
this.reasonData = options?.reasonData;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
class TransactionAbortedError extends BaseError {
|
|
219
|
-
name = "TransactionAbortedError";
|
|
220
|
-
receipt;
|
|
221
|
-
constructor(message, options) {
|
|
222
|
-
super(message, options);
|
|
223
|
-
this.receipt = options.receipt;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
class TransactionDroppedError extends BaseError {
|
|
228
|
-
name = "TransactionDroppedError";
|
|
229
|
-
txid;
|
|
230
|
-
constructor(message, options) {
|
|
231
|
-
super(message, options);
|
|
232
|
-
this.txid = options.txid;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
class WaitForTransactionTimeoutError extends BaseError {
|
|
237
|
-
name = "WaitForTransactionTimeoutError";
|
|
238
|
-
txid;
|
|
239
|
-
constructor(message, options) {
|
|
240
|
-
super(message, options);
|
|
241
|
-
this.txid = options.txid;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
class SerializationError extends BaseError {
|
|
246
|
-
name = "SerializationError";
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
class SigningError extends BaseError {
|
|
250
|
-
name = "SigningError";
|
|
414
|
+
// src/actions/public/getTransaction.ts
|
|
415
|
+
async function getTransaction(client, params) {
|
|
416
|
+
const source = params.source ?? extendedApiSource();
|
|
417
|
+
const { receipt } = await source.get({ client, txid: params.txid });
|
|
418
|
+
return receipt;
|
|
251
419
|
}
|
|
252
420
|
|
|
253
421
|
// src/actions/public/waitForTransactionReceipt.ts
|
|
254
|
-
var
|
|
422
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
255
423
|
async function waitForTransactionReceipt(client, params) {
|
|
256
424
|
const {
|
|
257
425
|
txid,
|
|
258
426
|
confirmations = 1,
|
|
259
427
|
timeout = 180000,
|
|
260
|
-
pollingInterval = 3000
|
|
261
|
-
droppedGracePeriod = 30000
|
|
428
|
+
pollingInterval = 3000
|
|
262
429
|
} = params;
|
|
263
430
|
const source = params.source ?? extendedApiSource();
|
|
431
|
+
const droppedGracePeriod = params.droppedGracePeriod ?? (source.canonicalOnly ? timeout : 30000);
|
|
264
432
|
const startedAt = Date.now();
|
|
265
433
|
let unknownSince = null;
|
|
266
434
|
let everPending = false;
|
|
@@ -298,7 +466,7 @@ async function waitForTransactionReceipt(client, params) {
|
|
|
298
466
|
if (Date.now() - startedAt >= timeout) {
|
|
299
467
|
throw new WaitForTransactionTimeoutError(`Timed out after ${timeout}ms waiting for transaction ${txid}`, { txid });
|
|
300
468
|
}
|
|
301
|
-
await
|
|
469
|
+
await sleep2(pollingInterval);
|
|
302
470
|
}
|
|
303
471
|
}
|
|
304
472
|
|
|
@@ -311,7 +479,11 @@ async function sendTransaction(client, params) {
|
|
|
311
479
|
}
|
|
312
480
|
let data;
|
|
313
481
|
try {
|
|
314
|
-
data = await client.request("/v2/transactions", {
|
|
482
|
+
data = await client.request("/v2/transactions", {
|
|
483
|
+
method: "POST",
|
|
484
|
+
body,
|
|
485
|
+
retryCount: 0
|
|
486
|
+
});
|
|
315
487
|
} catch (error) {
|
|
316
488
|
if (error instanceof HttpRequestError && error.details) {
|
|
317
489
|
try {
|
|
@@ -319,6 +491,12 @@ async function sendTransaction(client, params) {
|
|
|
319
491
|
} catch {
|
|
320
492
|
throw error;
|
|
321
493
|
}
|
|
494
|
+
} else if (error instanceof TimeoutError) {
|
|
495
|
+
const txid2 = getTransactionId(params.transaction);
|
|
496
|
+
const receipt = await getTransaction(client, { txid: txid2 }).catch(() => null);
|
|
497
|
+
if (receipt === null)
|
|
498
|
+
throw error;
|
|
499
|
+
data = { txid: txid2 };
|
|
322
500
|
} else {
|
|
323
501
|
throw error;
|
|
324
502
|
}
|
|
@@ -370,6 +548,12 @@ function memoryStore() {
|
|
|
370
548
|
reset(key) {
|
|
371
549
|
next.delete(key);
|
|
372
550
|
},
|
|
551
|
+
release(key, nonce) {
|
|
552
|
+
return withLock(key, async () => {
|
|
553
|
+
if (next.get(key) === nonce + 1n)
|
|
554
|
+
next.set(key, nonce);
|
|
555
|
+
});
|
|
556
|
+
},
|
|
373
557
|
peek(key) {
|
|
374
558
|
return next.get(key);
|
|
375
559
|
}
|
|
@@ -388,6 +572,9 @@ function createNonceManager(params = {}) {
|
|
|
388
572
|
reset({ client, address }) {
|
|
389
573
|
return store.reset(nonceKey(client, address));
|
|
390
574
|
},
|
|
575
|
+
release({ client, address, nonce }) {
|
|
576
|
+
return store.release?.(nonceKey(client, address), nonce);
|
|
577
|
+
},
|
|
391
578
|
async peek({ client, address }) {
|
|
392
579
|
return store.peek?.(nonceKey(client, address));
|
|
393
580
|
}
|
|
@@ -398,6 +585,13 @@ async function resolveNonce(client, address) {
|
|
|
398
585
|
return client.nonceManager.consume({ client, address });
|
|
399
586
|
return getNonce(client, { address });
|
|
400
587
|
}
|
|
588
|
+
async function releaseNonce(client, address, nonce) {
|
|
589
|
+
if (!client.nonceManager)
|
|
590
|
+
return;
|
|
591
|
+
try {
|
|
592
|
+
await client.nonceManager.release({ client, address, nonce });
|
|
593
|
+
} catch {}
|
|
594
|
+
}
|
|
401
595
|
async function reconcileNonce(manager, params) {
|
|
402
596
|
const { client, address, source } = params;
|
|
403
597
|
const downward = params.downward ?? true;
|
|
@@ -489,19 +683,27 @@ function isFeeTier(fee) {
|
|
|
489
683
|
function minimumFee(transaction) {
|
|
490
684
|
return BigInt(serializeTransaction(transaction).length);
|
|
491
685
|
}
|
|
686
|
+
function isNoEstimateAvailable(error) {
|
|
687
|
+
return error instanceof HttpRequestError && error.status === 400 && (error.details?.includes("NoEstimateAvailable") ?? false);
|
|
688
|
+
}
|
|
492
689
|
async function resolveFee(client, transaction, fee) {
|
|
493
690
|
if (fee !== undefined && !isFeeTier(fee))
|
|
494
|
-
return intToBigInt(fee);
|
|
691
|
+
return { fee: intToBigInt(fee) };
|
|
495
692
|
const tier = fee ?? "mid";
|
|
496
693
|
if (tier === "min")
|
|
497
|
-
return minimumFee(transaction);
|
|
694
|
+
return { fee: minimumFee(transaction), tier };
|
|
695
|
+
let estimates;
|
|
498
696
|
try {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
if (
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
697
|
+
estimates = await estimateFee(client, { transaction });
|
|
698
|
+
} catch (error) {
|
|
699
|
+
if (!isNoEstimateAvailable(error))
|
|
700
|
+
throw error;
|
|
701
|
+
return { fee: minimumFee(transaction), tier: "min" };
|
|
702
|
+
}
|
|
703
|
+
const pick = estimates[TIER_INDEX[tier]] ?? estimates[estimates.length - 1];
|
|
704
|
+
if (pick)
|
|
705
|
+
return { fee: BigInt(pick.fee), tier };
|
|
706
|
+
return { fee: minimumFee(transaction), tier: "min" };
|
|
505
707
|
}
|
|
506
708
|
function setUnsignedFee(transaction, fee) {
|
|
507
709
|
transaction.auth.spendingCondition.fee = fee;
|
|
@@ -528,31 +730,37 @@ async function callContract(client, params) {
|
|
|
528
730
|
});
|
|
529
731
|
return result.txid;
|
|
530
732
|
}
|
|
733
|
+
const managed = params.nonce === undefined && client.nonceManager !== undefined;
|
|
531
734
|
const nonce = params.nonce ?? await resolveNonce(client, account.address);
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
735
|
+
try {
|
|
736
|
+
const needsFeeResolution = params.fee === undefined || isFeeTier(params.fee);
|
|
737
|
+
const unsigned = buildContractCall({
|
|
738
|
+
contractAddress,
|
|
739
|
+
contractName,
|
|
740
|
+
functionName: params.functionName,
|
|
741
|
+
functionArgs: params.functionArgs ?? [],
|
|
742
|
+
fee: needsFeeResolution ? 0n : params.fee,
|
|
743
|
+
nonce,
|
|
744
|
+
publicKey: account.publicKey,
|
|
745
|
+
chain: client.chain,
|
|
746
|
+
postConditionMode: params.postConditionMode,
|
|
747
|
+
postConditions: params.postConditions
|
|
748
|
+
});
|
|
749
|
+
if (needsFeeResolution) {
|
|
750
|
+
const { fee } = await resolveFee(client, unsigned, params.fee);
|
|
751
|
+
setUnsignedFee(unsigned, fee);
|
|
752
|
+
}
|
|
753
|
+
const signed = await signTransactionWithAccount(unsigned, account);
|
|
754
|
+
return await broadcastWithNonceReset(client, {
|
|
755
|
+
transaction: signed,
|
|
756
|
+
address: account.address
|
|
757
|
+
});
|
|
758
|
+
} catch (error) {
|
|
759
|
+
if (managed)
|
|
760
|
+
await releaseNonce(client, account.address, nonce);
|
|
761
|
+
throw error;
|
|
547
762
|
}
|
|
548
|
-
const signed = await signTransactionWithAccount(unsigned, account);
|
|
549
|
-
return broadcastWithNonceReset(client, {
|
|
550
|
-
transaction: signed,
|
|
551
|
-
address: account.address
|
|
552
|
-
});
|
|
553
763
|
}
|
|
554
764
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
//# debugId=822AF008FBCE784B64756E2164756E21
|
|
558
|
-
//# sourceMappingURL=stacks-fb75yew8.js.map
|
|
765
|
+
//# debugId=DC00E5DBCD8CE8AA64756E2164756E21
|
|
766
|
+
//# sourceMappingURL=stacks-db3kwavg.cjs.map
|