@secondlayer/sdk 6.54.1 → 8.0.0
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 +3 -7
- package/dist/index.d.ts +10 -740
- package/dist/index.js +41 -623
- package/dist/index.js.map +14 -22
- package/dist/sinks/bun-sqlite.js +2 -24
- package/dist/sinks/bun-sqlite.js.map +3 -3
- package/dist/sinks/core.js +2 -24
- package/dist/sinks/core.js.map +3 -3
- package/dist/sinks/drizzle.js +2 -24
- package/dist/sinks/drizzle.js.map +3 -3
- package/dist/sinks/kysely.js +2 -24
- package/dist/sinks/kysely.js.map +3 -3
- package/dist/streams/index.d.ts +9 -378
- package/dist/streams/index.js +35 -309
- package/dist/streams/index.js.map +9 -15
- package/dist/streams/rows.d.ts +2 -355
- package/dist/streams/rows.js +26 -280
- package/dist/streams/rows.js.map +4 -10
- package/dist/subgraphs/index.d.ts +1 -294
- package/dist/subgraphs/index.js +10 -174
- package/dist/subgraphs/index.js.map +10 -13
- package/package.json +4 -8
- package/dist/x402.d.ts +0 -160
- package/dist/x402.js +0 -531
- package/dist/x402.js.map +0 -12
package/dist/index.js
CHANGED
|
@@ -57,7 +57,7 @@ function statusRetryable(status) {
|
|
|
57
57
|
return status === 429 || status >= 500;
|
|
58
58
|
}
|
|
59
59
|
function docsFor(status, code) {
|
|
60
|
-
if (code === "UPGRADE_REQUIRED" ||
|
|
60
|
+
if (code === "UPGRADE_REQUIRED" || status === 402)
|
|
61
61
|
return `${DOCS_BASE}/docs/authentication#pay-as-you-go-credits`;
|
|
62
62
|
if (status === 429 || status === 401)
|
|
63
63
|
return `${DOCS_BASE}/docs/authentication`;
|
|
@@ -133,28 +133,6 @@ class VersionConflictError extends ApiError {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
class ByoBreakingChangeError extends ApiError {
|
|
137
|
-
details;
|
|
138
|
-
constructor(message, details) {
|
|
139
|
-
super(422, message, details, "BYO_BREAKING_CHANGE", {
|
|
140
|
-
metaMessages: [
|
|
141
|
-
"Review and run manually on your database:",
|
|
142
|
-
details.plan.dropStatement,
|
|
143
|
-
...details.plan.statements
|
|
144
|
-
]
|
|
145
|
-
});
|
|
146
|
-
this.name = "ByoBreakingChangeError";
|
|
147
|
-
this.details = details;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
function isByoBreakingDetails(x) {
|
|
151
|
-
if (!x || typeof x !== "object")
|
|
152
|
-
return false;
|
|
153
|
-
const d = x;
|
|
154
|
-
const plan = d.plan;
|
|
155
|
-
return Array.isArray(d.reasons) && !!plan && typeof plan === "object" && typeof plan.dropStatement === "string";
|
|
156
|
-
}
|
|
157
|
-
|
|
158
136
|
// src/base.ts
|
|
159
137
|
var LOCAL_API_URL = "http://127.0.0.1:3800";
|
|
160
138
|
function resolveBaseUrl(explicit) {
|
|
@@ -283,9 +261,6 @@ class BaseClient {
|
|
|
283
261
|
if (errorBody)
|
|
284
262
|
message = errorBody;
|
|
285
263
|
}
|
|
286
|
-
if (response.status === 422 && code === "BYO_BREAKING_CHANGE" && parsedBody && typeof parsedBody === "object" && isByoBreakingDetails(parsedBody.details)) {
|
|
287
|
-
throw new ByoBreakingChangeError(message, parsedBody.details);
|
|
288
|
-
}
|
|
289
264
|
throw new ApiError(response.status, message, parsedBody, code);
|
|
290
265
|
}
|
|
291
266
|
return response;
|
|
@@ -398,12 +373,6 @@ class Subgraphs extends BaseClient {
|
|
|
398
373
|
const qs = buildQuery({ force: options?.force ? true : undefined });
|
|
399
374
|
return this.request("DELETE", `/api/subgraphs/${name}${qs}`);
|
|
400
375
|
}
|
|
401
|
-
async publish(name) {
|
|
402
|
-
return this.request("POST", `/api/subgraphs/${name}/publish`);
|
|
403
|
-
}
|
|
404
|
-
async unpublish(name) {
|
|
405
|
-
return this.request("POST", `/api/subgraphs/${name}/unpublish`);
|
|
406
|
-
}
|
|
407
376
|
async rows(name, table, params = {}) {
|
|
408
377
|
const { cursor, ...rest } = params;
|
|
409
378
|
const qs = buildSubgraphQueryString(rest);
|
|
@@ -512,25 +481,6 @@ class Subgraphs extends BaseClient {
|
|
|
512
481
|
};
|
|
513
482
|
}
|
|
514
483
|
}
|
|
515
|
-
// src/api-keys/client.ts
|
|
516
|
-
class ApiKeys extends BaseClient {
|
|
517
|
-
constructor(options = {}) {
|
|
518
|
-
super(options);
|
|
519
|
-
}
|
|
520
|
-
create(params = {}) {
|
|
521
|
-
return this.request("POST", "/v1/api-keys", {
|
|
522
|
-
product: params.product,
|
|
523
|
-
name: params.name
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
list() {
|
|
527
|
-
return this.request("GET", "/api/keys");
|
|
528
|
-
}
|
|
529
|
-
revoke(id) {
|
|
530
|
-
return this.request("DELETE", `/api/keys/${id}`);
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
484
|
// src/contracts/client.ts
|
|
535
485
|
class Contracts extends BaseClient {
|
|
536
486
|
constructor(options = {}) {
|
|
@@ -974,9 +924,6 @@ class Index extends BaseClient {
|
|
|
974
924
|
constructor(options = {}) {
|
|
975
925
|
super(options);
|
|
976
926
|
}
|
|
977
|
-
usage() {
|
|
978
|
-
return this.request("GET", "/v1/index/usage");
|
|
979
|
-
}
|
|
980
927
|
discover() {
|
|
981
928
|
return this.request("GET", "/v1/index");
|
|
982
929
|
}
|
|
@@ -1316,97 +1263,16 @@ class Index extends BaseClient {
|
|
|
1316
1263
|
}
|
|
1317
1264
|
}
|
|
1318
1265
|
|
|
1319
|
-
// src/projects/client.ts
|
|
1320
|
-
class Projects extends BaseClient {
|
|
1321
|
-
constructor(options = {}) {
|
|
1322
|
-
super(options);
|
|
1323
|
-
}
|
|
1324
|
-
list() {
|
|
1325
|
-
return this.request("GET", "/api/projects");
|
|
1326
|
-
}
|
|
1327
|
-
get(slug) {
|
|
1328
|
-
return this.request("GET", `/api/projects/${slug}`);
|
|
1329
|
-
}
|
|
1330
|
-
create(params) {
|
|
1331
|
-
return this.request("POST", "/api/projects", params);
|
|
1332
|
-
}
|
|
1333
|
-
update(slug, patch) {
|
|
1334
|
-
return this.request("PATCH", `/api/projects/${slug}`, patch);
|
|
1335
|
-
}
|
|
1336
|
-
delete(slug) {
|
|
1337
|
-
return this.request("DELETE", `/api/projects/${slug}`);
|
|
1338
|
-
}
|
|
1339
|
-
team(slug) {
|
|
1340
|
-
return this.request("GET", `/api/projects/${slug}/team`);
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
1266
|
// src/streams/client.ts
|
|
1345
1267
|
import { ed25519 as ed255192 } from "@secondlayer/shared";
|
|
1346
1268
|
|
|
1347
|
-
// src/streams/_payload.ts
|
|
1348
|
-
function requireString(payload, field, eventType) {
|
|
1349
|
-
const value = payload[field];
|
|
1350
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
1351
|
-
throw new Error(`${eventType} payload missing ${field}`);
|
|
1352
|
-
}
|
|
1353
|
-
return value;
|
|
1354
|
-
}
|
|
1355
|
-
function optionalString(value) {
|
|
1356
|
-
return typeof value === "string" && value.length > 0 ? value : null;
|
|
1357
|
-
}
|
|
1358
|
-
function requireAmountField(payload, field, eventType) {
|
|
1359
|
-
const amount = requireString(payload, field, eventType);
|
|
1360
|
-
if (!/^(0|[1-9]\d*)$/.test(amount)) {
|
|
1361
|
-
throw new Error(`${eventType} payload has malformed ${field}`);
|
|
1362
|
-
}
|
|
1363
|
-
return amount;
|
|
1364
|
-
}
|
|
1365
|
-
function requireAmount(payload, eventType) {
|
|
1366
|
-
return requireAmountField(payload, "amount", eventType);
|
|
1367
|
-
}
|
|
1368
|
-
function parseAssetIdentifier(assetIdentifier, eventType) {
|
|
1369
|
-
const [contractId, tokenName] = assetIdentifier.split("::");
|
|
1370
|
-
if (!contractId) {
|
|
1371
|
-
throw new Error(`${eventType} payload has malformed asset_identifier`);
|
|
1372
|
-
}
|
|
1373
|
-
return {
|
|
1374
|
-
contract_id: contractId,
|
|
1375
|
-
token_name: tokenName && tokenName.length > 0 ? tokenName : null
|
|
1376
|
-
};
|
|
1377
|
-
}
|
|
1378
|
-
function requireHexValue(payload, eventType) {
|
|
1379
|
-
const rawValue = payload.raw_value;
|
|
1380
|
-
if (typeof rawValue === "string") {
|
|
1381
|
-
if (!/^0x[0-9a-fA-F]*$/.test(rawValue)) {
|
|
1382
|
-
throw new Error(`${eventType} payload has malformed value`);
|
|
1383
|
-
}
|
|
1384
|
-
return rawValue;
|
|
1385
|
-
}
|
|
1386
|
-
const value = payload.value;
|
|
1387
|
-
const hex = typeof value === "string" ? value : value && typeof value === "object" && typeof value.hex === "string" ? value.hex : null;
|
|
1388
|
-
if (!hex) {
|
|
1389
|
-
throw new Error(`${eventType} payload missing value`);
|
|
1390
|
-
}
|
|
1391
|
-
if (!/^0x[0-9a-fA-F]*$/.test(hex)) {
|
|
1392
|
-
throw new Error(`${eventType} payload has malformed value`);
|
|
1393
|
-
}
|
|
1394
|
-
return hex;
|
|
1395
|
-
}
|
|
1396
|
-
function decodedRow(event, eventType, decoded_payload) {
|
|
1397
|
-
return {
|
|
1398
|
-
cursor: event.cursor,
|
|
1399
|
-
block_height: event.block_height,
|
|
1400
|
-
tx_id: event.tx_id,
|
|
1401
|
-
tx_index: event.tx_index,
|
|
1402
|
-
event_index: event.event_index,
|
|
1403
|
-
event_type: eventType,
|
|
1404
|
-
decoded_payload,
|
|
1405
|
-
source_cursor: event.cursor
|
|
1406
|
-
};
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
1269
|
// src/streams/decode.ts
|
|
1270
|
+
import {
|
|
1271
|
+
optionalString,
|
|
1272
|
+
requireAmountField,
|
|
1273
|
+
requireHexValue,
|
|
1274
|
+
requireString
|
|
1275
|
+
} from "@secondlayer/shared/streams-rows";
|
|
1410
1276
|
function decode(event) {
|
|
1411
1277
|
const base = {
|
|
1412
1278
|
cursor: event.cursor,
|
|
@@ -1986,9 +1852,6 @@ function createStreamsClient(options) {
|
|
|
1986
1852
|
},
|
|
1987
1853
|
tip() {
|
|
1988
1854
|
return request("/v1/streams/tip");
|
|
1989
|
-
},
|
|
1990
|
-
usage() {
|
|
1991
|
-
return request("/v1/streams/usage");
|
|
1992
1855
|
}
|
|
1993
1856
|
};
|
|
1994
1857
|
}
|
|
@@ -2045,8 +1908,6 @@ class SecondLayer extends BaseClient {
|
|
|
2045
1908
|
contracts;
|
|
2046
1909
|
subgraphs;
|
|
2047
1910
|
subscriptions;
|
|
2048
|
-
apiKeys;
|
|
2049
|
-
projects;
|
|
2050
1911
|
constructor(options = {}) {
|
|
2051
1912
|
super(options);
|
|
2052
1913
|
this.streams = createStreamsClient({
|
|
@@ -2059,30 +1920,18 @@ class SecondLayer extends BaseClient {
|
|
|
2059
1920
|
this.contracts = new Contracts(options);
|
|
2060
1921
|
this.subgraphs = new Subgraphs(options);
|
|
2061
1922
|
this.subscriptions = new Subscriptions(options);
|
|
2062
|
-
this.apiKeys = new ApiKeys(options);
|
|
2063
|
-
this.projects = new Projects(options);
|
|
2064
1923
|
}
|
|
2065
1924
|
async batch(requests) {
|
|
2066
1925
|
return this.request("POST", "/v1/batch", { requests });
|
|
2067
1926
|
}
|
|
2068
1927
|
async context() {
|
|
2069
1928
|
const safe = (p) => p.then((v) => v).catch(() => null);
|
|
2070
|
-
const [
|
|
2071
|
-
account,
|
|
2072
|
-
streamsTip,
|
|
2073
|
-
indexEnv,
|
|
2074
|
-
subgraphsRes,
|
|
2075
|
-
subscriptionsRes,
|
|
2076
|
-
projectsRes,
|
|
2077
|
-
apiKeysRes
|
|
2078
|
-
] = await Promise.all([
|
|
1929
|
+
const [account, streamsTip, indexEnv, subgraphsRes, subscriptionsRes] = await Promise.all([
|
|
2079
1930
|
safe(this.request("GET", "/api/accounts/me")),
|
|
2080
1931
|
safe(this.streams.tip()),
|
|
2081
1932
|
safe(this.index.canonical.list({ limit: 1 })),
|
|
2082
1933
|
safe(this.subgraphs.list()),
|
|
2083
|
-
safe(this.subscriptions.list())
|
|
2084
|
-
safe(this.projects.list()),
|
|
2085
|
-
safe(this.apiKeys.list())
|
|
1934
|
+
safe(this.subscriptions.list())
|
|
2086
1935
|
]);
|
|
2087
1936
|
const subgraphs = subgraphsRes?.data ?? null;
|
|
2088
1937
|
let subscriptions = null;
|
|
@@ -2108,25 +1957,12 @@ class SecondLayer extends BaseClient {
|
|
|
2108
1957
|
}));
|
|
2109
1958
|
activeOperations = probed.filter((o) => o !== null);
|
|
2110
1959
|
}
|
|
2111
|
-
const projects = projectsRes ? projectsRes.projects.map((p) => ({
|
|
2112
|
-
name: p.name,
|
|
2113
|
-
slug: p.slug,
|
|
2114
|
-
network: p.network
|
|
2115
|
-
})) : null;
|
|
2116
|
-
const apiKeys = apiKeysRes ? apiKeysRes.keys.map((k) => ({
|
|
2117
|
-
prefix: k.prefix,
|
|
2118
|
-
name: k.name,
|
|
2119
|
-
status: k.status,
|
|
2120
|
-
product: k.product
|
|
2121
|
-
})) : null;
|
|
2122
1960
|
return {
|
|
2123
1961
|
account,
|
|
2124
1962
|
streamsTip,
|
|
2125
1963
|
indexTip: indexEnv?.tip ?? null,
|
|
2126
1964
|
subgraphs,
|
|
2127
1965
|
subscriptions,
|
|
2128
|
-
projects,
|
|
2129
|
-
apiKeys,
|
|
2130
1966
|
activeOperations
|
|
2131
1967
|
};
|
|
2132
1968
|
}
|
|
@@ -2142,446 +1978,36 @@ function getSubgraph(def, options = {}) {
|
|
|
2142
1978
|
}
|
|
2143
1979
|
return new Subgraphs(options).typed(def);
|
|
2144
1980
|
}
|
|
2145
|
-
// src/streams/
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
return event.event_type === "nft_transfer";
|
|
2171
|
-
}
|
|
2172
|
-
function decodeNftTransfer(event) {
|
|
2173
|
-
if (!isNftTransfer(event)) {
|
|
2174
|
-
throw new Error(`Expected nft_transfer event, got ${event.event_type}`);
|
|
2175
|
-
}
|
|
2176
|
-
const payload = event.payload;
|
|
2177
|
-
const assetIdentifier = requireString(payload, "asset_identifier", "nft_transfer");
|
|
2178
|
-
const sender = requireString(payload, "sender", "nft_transfer");
|
|
2179
|
-
const recipient = requireString(payload, "recipient", "nft_transfer");
|
|
2180
|
-
const value = requireHexValue(payload, "nft_transfer");
|
|
2181
|
-
const { contract_id, token_name } = parseAssetIdentifier(assetIdentifier, "nft_transfer");
|
|
2182
|
-
return decodedRow(event, "nft_transfer", {
|
|
2183
|
-
asset_identifier: assetIdentifier,
|
|
2184
|
-
contract_id: event.contract_id ?? contract_id,
|
|
2185
|
-
token_name,
|
|
2186
|
-
sender,
|
|
2187
|
-
recipient,
|
|
2188
|
-
value
|
|
2189
|
-
});
|
|
2190
|
-
}
|
|
2191
|
-
// src/streams/stx-events.ts
|
|
2192
|
-
function isStxTransfer(event) {
|
|
2193
|
-
return event.event_type === "stx_transfer";
|
|
2194
|
-
}
|
|
2195
|
-
function decodeStxTransfer(event) {
|
|
2196
|
-
if (!isStxTransfer(event)) {
|
|
2197
|
-
throw new Error(`Expected stx_transfer event, got ${event.event_type}`);
|
|
2198
|
-
}
|
|
2199
|
-
const payload = event.payload;
|
|
2200
|
-
return decodedRow(event, "stx_transfer", {
|
|
2201
|
-
sender: requireString(payload, "sender", "stx_transfer"),
|
|
2202
|
-
recipient: requireString(payload, "recipient", "stx_transfer"),
|
|
2203
|
-
amount: requireAmount(payload, "stx_transfer"),
|
|
2204
|
-
memo: optionalString(payload.memo)
|
|
2205
|
-
});
|
|
2206
|
-
}
|
|
2207
|
-
function isStxMint(event) {
|
|
2208
|
-
return event.event_type === "stx_mint";
|
|
2209
|
-
}
|
|
2210
|
-
function decodeStxMint(event) {
|
|
2211
|
-
if (!isStxMint(event)) {
|
|
2212
|
-
throw new Error(`Expected stx_mint event, got ${event.event_type}`);
|
|
2213
|
-
}
|
|
2214
|
-
const payload = event.payload;
|
|
2215
|
-
return decodedRow(event, "stx_mint", {
|
|
2216
|
-
recipient: requireString(payload, "recipient", "stx_mint"),
|
|
2217
|
-
amount: requireAmount(payload, "stx_mint")
|
|
2218
|
-
});
|
|
2219
|
-
}
|
|
2220
|
-
function isStxBurn(event) {
|
|
2221
|
-
return event.event_type === "stx_burn";
|
|
2222
|
-
}
|
|
2223
|
-
function decodeStxBurn(event) {
|
|
2224
|
-
if (!isStxBurn(event)) {
|
|
2225
|
-
throw new Error(`Expected stx_burn event, got ${event.event_type}`);
|
|
2226
|
-
}
|
|
2227
|
-
const payload = event.payload;
|
|
2228
|
-
return decodedRow(event, "stx_burn", {
|
|
2229
|
-
sender: requireString(payload, "sender", "stx_burn"),
|
|
2230
|
-
amount: requireAmount(payload, "stx_burn")
|
|
2231
|
-
});
|
|
2232
|
-
}
|
|
2233
|
-
function isStxLock(event) {
|
|
2234
|
-
return event.event_type === "stx_lock";
|
|
2235
|
-
}
|
|
2236
|
-
function decodeStxLock(event) {
|
|
2237
|
-
if (!isStxLock(event)) {
|
|
2238
|
-
throw new Error(`Expected stx_lock event, got ${event.event_type}`);
|
|
2239
|
-
}
|
|
2240
|
-
const payload = event.payload;
|
|
2241
|
-
return decodedRow(event, "stx_lock", {
|
|
2242
|
-
sender: requireString(payload, "locked_address", "stx_lock"),
|
|
2243
|
-
amount: requireAmountField(payload, "locked_amount", "stx_lock"),
|
|
2244
|
-
payload: { unlock_height: optionalString(payload.unlock_height) }
|
|
2245
|
-
});
|
|
2246
|
-
}
|
|
2247
|
-
// src/streams/token-mint-burn.ts
|
|
2248
|
-
function assetFields(event, eventType) {
|
|
2249
|
-
const assetIdentifier = requireString(event.payload, "asset_identifier", eventType);
|
|
2250
|
-
const { contract_id, token_name } = parseAssetIdentifier(assetIdentifier, eventType);
|
|
2251
|
-
return {
|
|
2252
|
-
asset_identifier: assetIdentifier,
|
|
2253
|
-
contract_id: event.contract_id ?? contract_id,
|
|
2254
|
-
token_name
|
|
2255
|
-
};
|
|
2256
|
-
}
|
|
2257
|
-
function isFtMint(event) {
|
|
2258
|
-
return event.event_type === "ft_mint";
|
|
2259
|
-
}
|
|
2260
|
-
function decodeFtMint(event) {
|
|
2261
|
-
if (!isFtMint(event)) {
|
|
2262
|
-
throw new Error(`Expected ft_mint event, got ${event.event_type}`);
|
|
2263
|
-
}
|
|
2264
|
-
return decodedRow(event, "ft_mint", {
|
|
2265
|
-
...assetFields(event, "ft_mint"),
|
|
2266
|
-
recipient: requireString(event.payload, "recipient", "ft_mint"),
|
|
2267
|
-
amount: requireAmount(event.payload, "ft_mint")
|
|
2268
|
-
});
|
|
2269
|
-
}
|
|
2270
|
-
function isFtBurn(event) {
|
|
2271
|
-
return event.event_type === "ft_burn";
|
|
2272
|
-
}
|
|
2273
|
-
function decodeFtBurn(event) {
|
|
2274
|
-
if (!isFtBurn(event)) {
|
|
2275
|
-
throw new Error(`Expected ft_burn event, got ${event.event_type}`);
|
|
2276
|
-
}
|
|
2277
|
-
return decodedRow(event, "ft_burn", {
|
|
2278
|
-
...assetFields(event, "ft_burn"),
|
|
2279
|
-
sender: requireString(event.payload, "sender", "ft_burn"),
|
|
2280
|
-
amount: requireAmount(event.payload, "ft_burn")
|
|
2281
|
-
});
|
|
2282
|
-
}
|
|
2283
|
-
function isNftMint(event) {
|
|
2284
|
-
return event.event_type === "nft_mint";
|
|
2285
|
-
}
|
|
2286
|
-
function decodeNftMint(event) {
|
|
2287
|
-
if (!isNftMint(event)) {
|
|
2288
|
-
throw new Error(`Expected nft_mint event, got ${event.event_type}`);
|
|
2289
|
-
}
|
|
2290
|
-
return decodedRow(event, "nft_mint", {
|
|
2291
|
-
...assetFields(event, "nft_mint"),
|
|
2292
|
-
recipient: requireString(event.payload, "recipient", "nft_mint"),
|
|
2293
|
-
value: requireHexValue(event.payload, "nft_mint")
|
|
2294
|
-
});
|
|
2295
|
-
}
|
|
2296
|
-
function isNftBurn(event) {
|
|
2297
|
-
return event.event_type === "nft_burn";
|
|
2298
|
-
}
|
|
2299
|
-
function decodeNftBurn(event) {
|
|
2300
|
-
if (!isNftBurn(event)) {
|
|
2301
|
-
throw new Error(`Expected nft_burn event, got ${event.event_type}`);
|
|
2302
|
-
}
|
|
2303
|
-
return decodedRow(event, "nft_burn", {
|
|
2304
|
-
...assetFields(event, "nft_burn"),
|
|
2305
|
-
sender: requireString(event.payload, "sender", "nft_burn"),
|
|
2306
|
-
value: requireHexValue(event.payload, "nft_burn")
|
|
2307
|
-
});
|
|
2308
|
-
}
|
|
2309
|
-
// src/clarity.ts
|
|
2310
|
-
import { cvToValue, deserializeCV } from "@secondlayer/stacks/clarity";
|
|
2311
|
-
function toJsonSafe(value) {
|
|
2312
|
-
if (typeof value === "bigint")
|
|
2313
|
-
return value.toString();
|
|
2314
|
-
if (Array.isArray(value))
|
|
2315
|
-
return value.map(toJsonSafe);
|
|
2316
|
-
if (value && typeof value === "object") {
|
|
2317
|
-
const out = {};
|
|
2318
|
-
for (const [key, val] of Object.entries(value)) {
|
|
2319
|
-
out[key] = toJsonSafe(val);
|
|
2320
|
-
}
|
|
2321
|
-
return out;
|
|
2322
|
-
}
|
|
2323
|
-
return value;
|
|
2324
|
-
}
|
|
2325
|
-
function decodeClarityValue(hex) {
|
|
2326
|
-
try {
|
|
2327
|
-
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
2328
|
-
return toJsonSafe(cvToValue(deserializeCV(clean)));
|
|
2329
|
-
} catch {
|
|
2330
|
-
return hex;
|
|
2331
|
-
}
|
|
2332
|
-
}
|
|
1981
|
+
// src/streams/index.ts
|
|
1982
|
+
import {
|
|
1983
|
+
decodeFtTransfer,
|
|
1984
|
+
isFtTransfer,
|
|
1985
|
+
decodeNftTransfer,
|
|
1986
|
+
isNftTransfer,
|
|
1987
|
+
decodeStxBurn,
|
|
1988
|
+
decodeStxLock,
|
|
1989
|
+
decodeStxMint,
|
|
1990
|
+
decodeStxTransfer,
|
|
1991
|
+
isStxBurn,
|
|
1992
|
+
isStxLock,
|
|
1993
|
+
isStxMint,
|
|
1994
|
+
isStxTransfer,
|
|
1995
|
+
decodeFtBurn,
|
|
1996
|
+
decodeFtMint,
|
|
1997
|
+
decodeNftBurn,
|
|
1998
|
+
decodeNftMint,
|
|
1999
|
+
isFtBurn,
|
|
2000
|
+
isFtMint,
|
|
2001
|
+
isNftBurn,
|
|
2002
|
+
isNftMint,
|
|
2003
|
+
decodePrint,
|
|
2004
|
+
isPrint
|
|
2005
|
+
} from "@secondlayer/shared/streams-rows";
|
|
2333
2006
|
|
|
2334
|
-
// src/streams/print.ts
|
|
2335
|
-
function printValueHex(payload) {
|
|
2336
|
-
if (typeof payload.raw_value === "string")
|
|
2337
|
-
return payload.raw_value;
|
|
2338
|
-
const value = payload.value;
|
|
2339
|
-
if (typeof value === "string" && value.startsWith("0x"))
|
|
2340
|
-
return value;
|
|
2341
|
-
if (value && typeof value === "object" && typeof value.hex === "string") {
|
|
2342
|
-
return value.hex;
|
|
2343
|
-
}
|
|
2344
|
-
return null;
|
|
2345
|
-
}
|
|
2346
|
-
function isPrint(event) {
|
|
2347
|
-
return event.event_type === "print";
|
|
2348
|
-
}
|
|
2349
|
-
function decodePrint(event) {
|
|
2350
|
-
if (!isPrint(event)) {
|
|
2351
|
-
throw new Error(`Expected print event, got ${event.event_type}`);
|
|
2352
|
-
}
|
|
2353
|
-
const payload = event.payload;
|
|
2354
|
-
const topic = optionalString(payload.topic);
|
|
2355
|
-
const rawValue = printValueHex(payload);
|
|
2356
|
-
const value = rawValue ? decodeClarityValue(rawValue) : toJsonSafe(payload.value ?? null);
|
|
2357
|
-
return decodedRow(event, "print", {
|
|
2358
|
-
contract_id: event.contract_id ?? optionalString(payload.contract_id),
|
|
2359
|
-
payload: { topic, value, raw_value: rawValue }
|
|
2360
|
-
});
|
|
2361
|
-
}
|
|
2362
2007
|
// src/streams/types.ts
|
|
2363
2008
|
import {
|
|
2364
2009
|
STREAMS_EVENT_TYPES
|
|
2365
|
-
} from "@secondlayer/shared";
|
|
2366
|
-
// src/x402.ts
|
|
2367
|
-
import {
|
|
2368
|
-
X402_TOKENS,
|
|
2369
|
-
findX402TokenByAsset
|
|
2370
|
-
} from "@secondlayer/shared/x402";
|
|
2371
|
-
import { http, createPublicClient } from "@secondlayer/stacks";
|
|
2372
|
-
import { getNonce } from "@secondlayer/stacks/actions";
|
|
2373
|
-
import {
|
|
2374
|
-
serializeTransactionHex,
|
|
2375
|
-
signTransactionWithAccount
|
|
2376
|
-
} from "@secondlayer/stacks/transactions";
|
|
2377
|
-
import { buildExactTransfer } from "@secondlayer/stacks/x402";
|
|
2378
|
-
var DEFAULT_PREFER_ASSETS = [
|
|
2379
|
-
"sBTC",
|
|
2380
|
-
"USDCx",
|
|
2381
|
-
"STX"
|
|
2382
|
-
];
|
|
2383
|
-
var DEFAULT_NONCE_NODE_URL = "https://api.hiro.so";
|
|
2384
|
-
|
|
2385
|
-
class X402SpendGuardError extends Error {
|
|
2386
|
-
constructor(message) {
|
|
2387
|
-
super(message);
|
|
2388
|
-
this.name = "X402SpendGuardError";
|
|
2389
|
-
}
|
|
2390
|
-
}
|
|
2391
|
-
function b64encode(value) {
|
|
2392
|
-
const utf8 = new TextEncoder().encode(JSON.stringify(value));
|
|
2393
|
-
let binary = "";
|
|
2394
|
-
for (const byte of utf8)
|
|
2395
|
-
binary += String.fromCharCode(byte);
|
|
2396
|
-
return btoa(binary);
|
|
2397
|
-
}
|
|
2398
|
-
function b64decodeJson(value) {
|
|
2399
|
-
try {
|
|
2400
|
-
const binary = atob(value);
|
|
2401
|
-
const utf8 = Uint8Array.from(binary, (ch) => ch.charCodeAt(0));
|
|
2402
|
-
return JSON.parse(new TextDecoder().decode(utf8));
|
|
2403
|
-
} catch {
|
|
2404
|
-
return null;
|
|
2405
|
-
}
|
|
2406
|
-
}
|
|
2407
|
-
async function readX402Challenge(res) {
|
|
2408
|
-
const header = res.headers.get("PAYMENT-REQUIRED");
|
|
2409
|
-
if (header) {
|
|
2410
|
-
const decoded = b64decodeJson(header);
|
|
2411
|
-
if (decoded)
|
|
2412
|
-
return decoded;
|
|
2413
|
-
}
|
|
2414
|
-
try {
|
|
2415
|
-
return await res.clone().json();
|
|
2416
|
-
} catch {
|
|
2417
|
-
return null;
|
|
2418
|
-
}
|
|
2419
|
-
}
|
|
2420
|
-
function readX402Receipt(res) {
|
|
2421
|
-
const header = res.headers.get("PAYMENT-RESPONSE");
|
|
2422
|
-
return header ? b64decodeJson(header) : null;
|
|
2423
|
-
}
|
|
2424
|
-
function selectOffer(challenge, opts = {}) {
|
|
2425
|
-
const prefer = opts.preferAssets ?? DEFAULT_PREFER_ASSETS;
|
|
2426
|
-
for (const symbol of prefer) {
|
|
2427
|
-
const token = X402_TOKENS[symbol];
|
|
2428
|
-
const accept = challenge.accepts.find((a) => a.asset === token.asset);
|
|
2429
|
-
if (!accept)
|
|
2430
|
-
continue;
|
|
2431
|
-
const cap = opts.maxAmountPerCall?.[symbol];
|
|
2432
|
-
if (cap !== undefined && BigInt(accept.amount) > cap)
|
|
2433
|
-
continue;
|
|
2434
|
-
return { accept, symbol };
|
|
2435
|
-
}
|
|
2436
|
-
throw new X402SpendGuardError("no x402 offer matched preferAssets within maxAmountPerCall");
|
|
2437
|
-
}
|
|
2438
|
-
async function resolveAccountNonce(address, nodeUrl = DEFAULT_NONCE_NODE_URL) {
|
|
2439
|
-
const client = createPublicClient({ transport: http(nodeUrl) });
|
|
2440
|
-
return Number(await getNonce(client, { address }));
|
|
2441
|
-
}
|
|
2442
|
-
async function buildSignedX402Payment(opts) {
|
|
2443
|
-
const accept = opts.asset ? opts.challenge.accepts.find((a) => a.asset === opts.asset) : opts.challenge.accepts[0];
|
|
2444
|
-
if (!accept) {
|
|
2445
|
-
throw new Error(`No x402 offer${opts.asset ? ` for asset ${opts.asset}` : ""}`);
|
|
2446
|
-
}
|
|
2447
|
-
const token = findX402TokenByAsset(accept.asset);
|
|
2448
|
-
if (!token)
|
|
2449
|
-
throw new Error(`Unknown x402 asset: ${accept.asset}`);
|
|
2450
|
-
const asset = token.contractId && token.assetName ? {
|
|
2451
|
-
kind: "sip010",
|
|
2452
|
-
contractId: token.contractId,
|
|
2453
|
-
assetName: token.assetName
|
|
2454
|
-
} : { kind: "stx" };
|
|
2455
|
-
const tx = buildExactTransfer({
|
|
2456
|
-
asset,
|
|
2457
|
-
amount: BigInt(accept.amount),
|
|
2458
|
-
payTo: accept.payTo,
|
|
2459
|
-
payer: opts.account.address,
|
|
2460
|
-
payerPublicKey: opts.account.publicKey,
|
|
2461
|
-
accountNonce: opts.accountNonce,
|
|
2462
|
-
nonce: accept.extra.nonce,
|
|
2463
|
-
chain: opts.chain
|
|
2464
|
-
});
|
|
2465
|
-
const signed = await signTransactionWithAccount(tx, opts.account);
|
|
2466
|
-
const header = b64encode({
|
|
2467
|
-
x402Version: opts.challenge.x402Version ?? 2,
|
|
2468
|
-
scheme: "exact",
|
|
2469
|
-
network: accept.network,
|
|
2470
|
-
asset: accept.asset,
|
|
2471
|
-
payload: { transaction: serializeTransactionHex(signed) },
|
|
2472
|
-
extra: { nonce: accept.extra.nonce }
|
|
2473
|
-
});
|
|
2474
|
-
return { header, accept };
|
|
2475
|
-
}
|
|
2476
|
-
function withX402(baseFetch, opts) {
|
|
2477
|
-
const sessions = new Map;
|
|
2478
|
-
let balanceToken = opts.balanceToken ?? null;
|
|
2479
|
-
let toppingUp = false;
|
|
2480
|
-
const originOf = (input) => {
|
|
2481
|
-
try {
|
|
2482
|
-
return new URL(String(input)).origin;
|
|
2483
|
-
} catch {
|
|
2484
|
-
return "";
|
|
2485
|
-
}
|
|
2486
|
-
};
|
|
2487
|
-
const wrapped = async (input, init) => {
|
|
2488
|
-
const origin = originOf(input);
|
|
2489
|
-
const run = (extra, signal2) => baseFetch(input, {
|
|
2490
|
-
...init,
|
|
2491
|
-
headers: { ...init?.headers, ...extra },
|
|
2492
|
-
...signal2 ? { signal: signal2 } : {}
|
|
2493
|
-
});
|
|
2494
|
-
const maybeTopUp = (res) => {
|
|
2495
|
-
const policy = opts.topUp;
|
|
2496
|
-
if (!policy || toppingUp || !origin)
|
|
2497
|
-
return;
|
|
2498
|
-
const remaining = res.headers.get("X-BALANCE-REMAINING-USD");
|
|
2499
|
-
if (remaining === null || Number(remaining) >= policy.whenBelow)
|
|
2500
|
-
return;
|
|
2501
|
-
toppingUp = true;
|
|
2502
|
-
(async () => {
|
|
2503
|
-
try {
|
|
2504
|
-
const dep = await wrapped(`${origin}/v1/x402/deposit?usd=${policy.usd}`, { method: "POST" });
|
|
2505
|
-
if (dep.ok) {
|
|
2506
|
-
const body = await dep.json();
|
|
2507
|
-
if (body.balance_token)
|
|
2508
|
-
balanceToken = body.balance_token;
|
|
2509
|
-
}
|
|
2510
|
-
} catch {} finally {
|
|
2511
|
-
toppingUp = false;
|
|
2512
|
-
}
|
|
2513
|
-
})();
|
|
2514
|
-
};
|
|
2515
|
-
const remember = (res) => {
|
|
2516
|
-
const voucher = res.headers.get("PAYMENT-SESSION");
|
|
2517
|
-
if (voucher && origin)
|
|
2518
|
-
sessions.set(origin, voucher);
|
|
2519
|
-
maybeTopUp(res);
|
|
2520
|
-
return res;
|
|
2521
|
-
};
|
|
2522
|
-
const cached = origin ? sessions.get(origin) : undefined;
|
|
2523
|
-
const first = await run({
|
|
2524
|
-
...cached ? { "PAYMENT-SESSION": cached } : {},
|
|
2525
|
-
...balanceToken ? { "PAYMENT-BALANCE": balanceToken } : {}
|
|
2526
|
-
});
|
|
2527
|
-
if (first.status !== 402)
|
|
2528
|
-
return remember(first);
|
|
2529
|
-
if (cached && origin)
|
|
2530
|
-
sessions.delete(origin);
|
|
2531
|
-
const challenge = await readX402Challenge(first);
|
|
2532
|
-
if (!challenge)
|
|
2533
|
-
return first;
|
|
2534
|
-
const { accept } = selectOffer(challenge, opts);
|
|
2535
|
-
const accountNonce = opts.accountNonce ?? await resolveAccountNonce(opts.account.address, opts.nodeUrl);
|
|
2536
|
-
const { header } = await buildSignedX402Payment({
|
|
2537
|
-
challenge,
|
|
2538
|
-
account: opts.account,
|
|
2539
|
-
accountNonce,
|
|
2540
|
-
asset: accept.asset,
|
|
2541
|
-
chain: opts.chain
|
|
2542
|
-
});
|
|
2543
|
-
opts.onSettling?.({ asset: accept.asset, amount: accept.amount });
|
|
2544
|
-
const signal = opts.timeoutMs ? AbortSignal.timeout(opts.timeoutMs) : undefined;
|
|
2545
|
-
return remember(await run({ "PAYMENT-SIGNATURE": header }, signal));
|
|
2546
|
-
};
|
|
2547
|
-
return wrapped;
|
|
2548
|
-
}
|
|
2549
|
-
function createX402Client(opts) {
|
|
2550
|
-
const f = withX402(opts.fetch ?? fetch, opts);
|
|
2551
|
-
const base = resolveBaseUrl(opts.baseUrl);
|
|
2552
|
-
async function request(method, path, o = {}) {
|
|
2553
|
-
const qs = o.query ? `?${new URLSearchParams(o.query).toString()}` : "";
|
|
2554
|
-
const init = { method };
|
|
2555
|
-
if (o.body !== undefined) {
|
|
2556
|
-
init.body = JSON.stringify(o.body);
|
|
2557
|
-
init.headers = { "content-type": "application/json" };
|
|
2558
|
-
}
|
|
2559
|
-
const response = await f(`${base}${path}${qs}`, init);
|
|
2560
|
-
const data = await response.json().catch(() => null);
|
|
2561
|
-
return { data, payment: readX402Receipt(response), response };
|
|
2562
|
-
}
|
|
2563
|
-
return {
|
|
2564
|
-
get: (path, o) => request("GET", path, o),
|
|
2565
|
-
post: (path, o) => request("POST", path, o)
|
|
2566
|
-
};
|
|
2567
|
-
}
|
|
2568
|
-
async function payAndRetry(doFetch, opts) {
|
|
2569
|
-
const first = await doFetch({});
|
|
2570
|
-
if (first.status !== 402)
|
|
2571
|
-
return first;
|
|
2572
|
-
const challenge = await readX402Challenge(first);
|
|
2573
|
-
if (!challenge)
|
|
2574
|
-
return first;
|
|
2575
|
-
const { accept } = selectOffer(challenge, opts);
|
|
2576
|
-
const { header } = await buildSignedX402Payment({
|
|
2577
|
-
challenge,
|
|
2578
|
-
account: opts.account,
|
|
2579
|
-
accountNonce: opts.accountNonce,
|
|
2580
|
-
asset: accept.asset,
|
|
2581
|
-
chain: opts.chain
|
|
2582
|
-
});
|
|
2583
|
-
return doFetch({ "PAYMENT-SIGNATURE": header });
|
|
2584
|
-
}
|
|
2010
|
+
} from "@secondlayer/shared/streams-rows";
|
|
2585
2011
|
// src/consumer-ops.ts
|
|
2586
2012
|
function consumerHealth(options = {}) {
|
|
2587
2013
|
const staleAfterMs = options.staleAfterMs ?? 120000;
|
|
@@ -2775,8 +2201,12 @@ function verifyTransactionProof(proof, opts) {
|
|
|
2775
2201
|
errors
|
|
2776
2202
|
};
|
|
2777
2203
|
}
|
|
2204
|
+
// src/clarity.ts
|
|
2205
|
+
import {
|
|
2206
|
+
decodeClarityValue,
|
|
2207
|
+
toJsonSafe
|
|
2208
|
+
} from "@secondlayer/shared/streams-rows";
|
|
2778
2209
|
export {
|
|
2779
|
-
withX402,
|
|
2780
2210
|
verifyWebhookSignature,
|
|
2781
2211
|
verifyTransactionProof,
|
|
2782
2212
|
verify2 as verifyStandardWebhooksHeaders,
|
|
@@ -2784,13 +2214,8 @@ export {
|
|
|
2784
2214
|
trigger,
|
|
2785
2215
|
toJsonSafe,
|
|
2786
2216
|
shutdownSignal,
|
|
2787
|
-
selectOffer,
|
|
2788
2217
|
resolveBaseUrl,
|
|
2789
2218
|
resolveApiKey,
|
|
2790
|
-
resolveAccountNonce,
|
|
2791
|
-
readX402Receipt,
|
|
2792
|
-
readX402Challenge,
|
|
2793
|
-
payAndRetry,
|
|
2794
2219
|
parseRetryAfter,
|
|
2795
2220
|
isStxTransfer,
|
|
2796
2221
|
isStxMint,
|
|
@@ -2819,12 +2244,9 @@ export {
|
|
|
2819
2244
|
decodeClarityValue,
|
|
2820
2245
|
decodeChainWebhook,
|
|
2821
2246
|
decode,
|
|
2822
|
-
createX402Client,
|
|
2823
2247
|
createStreamsClient,
|
|
2824
2248
|
consumerHealth,
|
|
2825
2249
|
consumeIndexFeed,
|
|
2826
|
-
buildSignedX402Payment,
|
|
2827
|
-
X402SpendGuardError,
|
|
2828
2250
|
VersionConflictError,
|
|
2829
2251
|
ValidationError,
|
|
2830
2252
|
Subscriptions,
|
|
@@ -2834,17 +2256,13 @@ export {
|
|
|
2834
2256
|
SecondLayerError,
|
|
2835
2257
|
SecondLayer,
|
|
2836
2258
|
RateLimitError,
|
|
2837
|
-
Projects,
|
|
2838
2259
|
LOCAL_API_URL,
|
|
2839
2260
|
Index,
|
|
2840
|
-
DEFAULT_PREFER_ASSETS,
|
|
2841
2261
|
Cursor,
|
|
2842
2262
|
Contracts,
|
|
2843
|
-
ByoBreakingChangeError,
|
|
2844
2263
|
AuthError,
|
|
2845
|
-
ApiKeys,
|
|
2846
2264
|
ApiError
|
|
2847
2265
|
};
|
|
2848
2266
|
|
|
2849
|
-
//# debugId=
|
|
2267
|
+
//# debugId=E54023F57B45037464756E2164756E21
|
|
2850
2268
|
//# sourceMappingURL=index.js.map
|