@secondlayer/subgraphs 7.2.0 → 7.4.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/dist/index.d.ts +10 -2
- package/dist/index.js +195 -127
- package/dist/index.js.map +5 -5
- package/dist/runtime/emitter.d.ts +2 -1
- package/dist/runtime/emitter.js +134 -24
- package/dist/runtime/emitter.js.map +6 -5
- package/dist/runtime/replay.js +30 -12
- package/dist/runtime/replay.js.map +4 -4
- package/dist/schema/index.js +3 -3
- package/dist/schema/index.js.map +1 -1
- package/dist/testing/index.js +1691 -1627
- package/dist/testing/index.js.map +7 -7
- package/dist/verification.js +3 -3
- package/dist/verification.js.map +1 -1
- package/dist/verify/index.js +101 -39
- package/dist/verify/index.js.map +5 -5
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -108,6 +108,12 @@ declare function readContractAt<const C extends AbiContract>(ctx: {
|
|
|
108
108
|
}, contractId: string, abi: C, options?: ChainReadOptions): {
|
|
109
109
|
read: ChainReadMethods<C>;
|
|
110
110
|
};
|
|
111
|
+
/**
|
|
112
|
+
* A handler asked for something no node can answer: a function missing from
|
|
113
|
+
* the ABI, or one that isn't read-only. Deterministic, so it fails only the
|
|
114
|
+
* event. A read the processor couldn't complete (no node, node down, cache
|
|
115
|
+
* error) throws {@link HandlerReadError} instead and aborts the block.
|
|
116
|
+
*/
|
|
111
117
|
declare class ChainReadError extends Error {
|
|
112
118
|
name: string;
|
|
113
119
|
}
|
|
@@ -1206,9 +1212,11 @@ declare class NondeterminismError extends Error {
|
|
|
1206
1212
|
name: string;
|
|
1207
1213
|
}
|
|
1208
1214
|
/**
|
|
1209
|
-
* A ctx read
|
|
1215
|
+
* A ctx read failed for a reason outside the handler: the database under a
|
|
1216
|
+
* verifiable subgraph, or a chain read (`ctx.client`) on any subgraph that
|
|
1217
|
+
* had no node, a node that didn't answer, or a cache error. Infra-class like
|
|
1210
1218
|
* {@link NondeterminismError}: skipping the event would make its rows depend
|
|
1211
|
-
* on whether the database was reachable.
|
|
1219
|
+
* on whether the database or node was reachable.
|
|
1212
1220
|
*/
|
|
1213
1221
|
declare class HandlerReadError extends Error {
|
|
1214
1222
|
name: string;
|
package/dist/index.js
CHANGED
|
@@ -648,9 +648,17 @@ function inferPrintTopics(samples) {
|
|
|
648
648
|
return out.sort((a, b) => b.count - a.count);
|
|
649
649
|
}
|
|
650
650
|
// src/runtime/chain-read.ts
|
|
651
|
+
import { getErrorMessage } from "@secondlayer/shared";
|
|
652
|
+
import { chainReadArgsHash } from "@secondlayer/shared/chain-read";
|
|
651
653
|
import { getSourceDb } from "@secondlayer/shared/db";
|
|
654
|
+
import { hasNoLocalChain } from "@secondlayer/shared/db/queries/instance";
|
|
652
655
|
import { logger } from "@secondlayer/shared/logger";
|
|
653
|
-
import {
|
|
656
|
+
import {
|
|
657
|
+
http,
|
|
658
|
+
HttpRequestError,
|
|
659
|
+
ReadContractError,
|
|
660
|
+
createPublicClient
|
|
661
|
+
} from "@secondlayer/stacks";
|
|
654
662
|
import {
|
|
655
663
|
ContractResponseError,
|
|
656
664
|
buildFunctionArgs,
|
|
@@ -664,136 +672,16 @@ import {
|
|
|
664
672
|
serializeCV,
|
|
665
673
|
toCamelCase
|
|
666
674
|
} from "@secondlayer/stacks/clarity";
|
|
667
|
-
function readContractAt(ctx, contractId, abi, options) {
|
|
668
|
-
return ctx.client.contract(contractId, abi, options);
|
|
669
|
-
}
|
|
670
675
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
}
|
|
674
|
-
function nodeClient(rpcUrl) {
|
|
675
|
-
return createPublicClient({
|
|
676
|
-
transport: http(rpcUrl, { retryCount: 0, timeout: 1e4 })
|
|
677
|
-
});
|
|
678
|
-
}
|
|
676
|
+
// src/runtime/realm.ts
|
|
677
|
+
import vm from "node:vm";
|
|
679
678
|
|
|
680
|
-
class ConcurrencyGate {
|
|
681
|
-
limit;
|
|
682
|
-
active = 0;
|
|
683
|
-
queue = [];
|
|
684
|
-
constructor(limit) {
|
|
685
|
-
this.limit = limit;
|
|
686
|
-
}
|
|
687
|
-
async run(fn) {
|
|
688
|
-
if (this.active >= this.limit) {
|
|
689
|
-
await new Promise((resolve) => this.queue.push(resolve));
|
|
690
|
-
}
|
|
691
|
-
this.active++;
|
|
692
|
-
try {
|
|
693
|
-
return await fn();
|
|
694
|
-
} finally {
|
|
695
|
-
this.active--;
|
|
696
|
-
this.queue.shift()?.();
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
var DEFAULT_MAX_CONCURRENT_READS = 4;
|
|
701
|
-
function maxConcurrentReads() {
|
|
702
|
-
const raw = process.env.SUBGRAPH_CHAIN_READ_CONCURRENCY;
|
|
703
|
-
const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;
|
|
704
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CONCURRENT_READS;
|
|
705
|
-
}
|
|
706
|
-
var gate = new ConcurrencyGate(maxConcurrentReads());
|
|
707
|
-
function hashArgs(args) {
|
|
708
|
-
const serialized = args.map((arg) => serializeCV(arg)).join(",");
|
|
709
|
-
return Bun.hash(serialized).toString(16);
|
|
710
|
-
}
|
|
711
|
-
function findFunction(abi, name) {
|
|
712
|
-
const fn = abi.functions.find((f) => f.name === name);
|
|
713
|
-
if (!fn) {
|
|
714
|
-
throw new ChainReadError(`No function "${name}" in the supplied ABI.`);
|
|
715
|
-
}
|
|
716
|
-
if (fn.access !== "read-only") {
|
|
717
|
-
throw new ChainReadError(`"${name}" is ${fn.access}, not read-only — a handler cannot call it.`);
|
|
718
|
-
}
|
|
719
|
-
return fn;
|
|
720
|
-
}
|
|
721
|
-
function createChainReadClient(ctx) {
|
|
722
|
-
const readValue = async (contractId, abi, functionName, args, options) => {
|
|
723
|
-
const rpcUrl = ctx.rpcUrl ?? process.env.STACKS_NODE_RPC_URL;
|
|
724
|
-
if (!rpcUrl) {
|
|
725
|
-
throw new ChainReadError("ctx.client needs a Stacks node: set STACKS_NODE_RPC_URL on the subgraph processor.");
|
|
726
|
-
}
|
|
727
|
-
const constant = options.cache === "contract-constant";
|
|
728
|
-
if (!constant && !ctx.indexBlockHash) {
|
|
729
|
-
throw new ChainReadError(`Block ${ctx.blockHeight} has no index_block_hash, so a read cannot be pinned to it. Reading at the node's tip would make this handler non-deterministic (the same reindex would produce different rows). Re-ingest the block, or pass cache: "contract-constant" if the value genuinely cannot change.`);
|
|
730
|
-
}
|
|
731
|
-
const fn = findFunction(abi, functionName);
|
|
732
|
-
const clarityArgs = buildFunctionArgs(fn, args);
|
|
733
|
-
const db = ctx.db ?? getSourceDb();
|
|
734
|
-
const argsHash = hashArgs(clarityArgs);
|
|
735
|
-
const pinnedTo = constant ? null : ctx.indexBlockHash;
|
|
736
|
-
const cached = await db.selectFrom("chain_read_cache").select("result_hex").where("contract_id", "=", contractId).where("function_name", "=", fn.name).where("args_hash", "=", argsHash).where((eb) => pinnedTo === null ? eb("index_block_hash", "is", null) : eb("index_block_hash", "=", pinnedTo)).executeTakeFirst();
|
|
737
|
-
const resultHex = cached?.result_hex ?? await gate.run(async () => {
|
|
738
|
-
if (!ctx.indexBlockHash) {
|
|
739
|
-
logger.warn("Chain read is not pinned to a block (no index_block_hash)", {
|
|
740
|
-
contractId,
|
|
741
|
-
functionName: fn.name,
|
|
742
|
-
blockHeight: ctx.blockHeight,
|
|
743
|
-
note: 'cache: "contract-constant" asserts this value cannot change; the node answered at its own tip'
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
const value = await readContract(nodeClient(rpcUrl), {
|
|
747
|
-
contract: contractId,
|
|
748
|
-
functionName: fn.name,
|
|
749
|
-
args: clarityArgs,
|
|
750
|
-
tip: ctx.indexBlockHash ?? undefined
|
|
751
|
-
});
|
|
752
|
-
return serializeCV(value);
|
|
753
|
-
});
|
|
754
|
-
if (!cached) {
|
|
755
|
-
await db.insertInto("chain_read_cache").values({
|
|
756
|
-
contract_id: contractId,
|
|
757
|
-
function_name: fn.name,
|
|
758
|
-
args_hash: argsHash,
|
|
759
|
-
index_block_hash: pinnedTo,
|
|
760
|
-
block_height: constant ? null : ctx.blockHeight,
|
|
761
|
-
result_hex: resultHex
|
|
762
|
-
}).onConflict((oc) => oc.doNothing()).execute();
|
|
763
|
-
}
|
|
764
|
-
const value = deserializeCV2(resultHex);
|
|
765
|
-
const js = clarityValueToJSUntyped(fn.outputs, value);
|
|
766
|
-
if (isResponseOutput(fn.outputs)) {
|
|
767
|
-
const response = js;
|
|
768
|
-
if ("ok" in response)
|
|
769
|
-
return response.ok;
|
|
770
|
-
throw new ContractResponseError(`${contractId}::${fn.name} returned an err response.`, response.err);
|
|
771
|
-
}
|
|
772
|
-
return js;
|
|
773
|
-
};
|
|
774
|
-
return {
|
|
775
|
-
contract(contractId, rawAbi, options = {}) {
|
|
776
|
-
const abi = normalizeAbi(rawAbi);
|
|
777
|
-
const camelToKebab = new Map;
|
|
778
|
-
for (const fn of abi.functions) {
|
|
779
|
-
camelToKebab.set(toCamelCase(fn.name), fn.name);
|
|
780
|
-
}
|
|
781
|
-
const read = new Proxy({}, {
|
|
782
|
-
get(_target, prop) {
|
|
783
|
-
const fnName = camelToKebab.get(prop) ?? prop;
|
|
784
|
-
return (args = {}) => readValue(contractId, abi, fnName, args, options);
|
|
785
|
-
}
|
|
786
|
-
});
|
|
787
|
-
return { read };
|
|
788
|
-
}
|
|
789
|
-
};
|
|
790
|
-
}
|
|
791
679
|
// src/verification.ts
|
|
792
680
|
import { createHash } from "node:crypto";
|
|
793
681
|
// package.json
|
|
794
682
|
var package_default = {
|
|
795
683
|
name: "@secondlayer/subgraphs",
|
|
796
|
-
version: "7.
|
|
684
|
+
version: "7.4.0",
|
|
797
685
|
description: "Describe the Stacks data you want as one TypeScript file; it fills itself and survives reorgs.",
|
|
798
686
|
license: "MIT",
|
|
799
687
|
repository: {
|
|
@@ -853,7 +741,7 @@ var package_default = {
|
|
|
853
741
|
prepublishOnly: "bun run build"
|
|
854
742
|
},
|
|
855
743
|
dependencies: {
|
|
856
|
-
"@secondlayer/shared": "^13.
|
|
744
|
+
"@secondlayer/shared": "^13.3.0",
|
|
857
745
|
"@secondlayer/stacks": "^6.4.0",
|
|
858
746
|
"@secondlayer/verify": "^0.6.0",
|
|
859
747
|
esbuild: "^0.28.2",
|
|
@@ -1056,8 +944,8 @@ function pinPreimage(input) {
|
|
|
1056
944
|
function computePin(input) {
|
|
1057
945
|
return sha256(pinPreimage(input));
|
|
1058
946
|
}
|
|
947
|
+
|
|
1059
948
|
// src/runtime/realm.ts
|
|
1060
|
-
import vm from "node:vm";
|
|
1061
949
|
class NondeterminismError extends Error {
|
|
1062
950
|
name = "NondeterminismError";
|
|
1063
951
|
}
|
|
@@ -1272,6 +1160,186 @@ ${code}
|
|
|
1272
1160
|
realmDefinitions.add(loaded);
|
|
1273
1161
|
return loaded;
|
|
1274
1162
|
}
|
|
1163
|
+
|
|
1164
|
+
// src/runtime/chain-read.ts
|
|
1165
|
+
function readContractAt(ctx, contractId, abi, options) {
|
|
1166
|
+
return ctx.client.contract(contractId, abi, options);
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
class ChainReadError extends Error {
|
|
1170
|
+
name = "ChainReadError";
|
|
1171
|
+
}
|
|
1172
|
+
var NO_NODE_MESSAGE = "ctx.client needs a Stacks node: set STACKS_NODE_RPC_URL on the subgraph processor.";
|
|
1173
|
+
async function resolveReadTarget(rpcUrl, db) {
|
|
1174
|
+
if (rpcUrl)
|
|
1175
|
+
return { kind: "node", rpcUrl };
|
|
1176
|
+
const apiUrl = process.env.SUBGRAPH_INDEX_API_URL;
|
|
1177
|
+
if (!apiUrl || !await hasNoLocalChain(db)) {
|
|
1178
|
+
throw new HandlerReadError(NO_NODE_MESSAGE);
|
|
1179
|
+
}
|
|
1180
|
+
const apiKey = process.env.INDEX_INTERNAL_API_KEY?.trim();
|
|
1181
|
+
if (!apiKey) {
|
|
1182
|
+
throw new HandlerReadError("Hosted contract reads need the processor's key (INDEX_INTERNAL_API_KEY), and none is set. Set STACKS_NODE_RPC_URL to read a node directly instead.");
|
|
1183
|
+
}
|
|
1184
|
+
return { kind: "hosted", apiUrl, apiKey };
|
|
1185
|
+
}
|
|
1186
|
+
function hostedReadError(err, label) {
|
|
1187
|
+
if (!(err instanceof HttpRequestError))
|
|
1188
|
+
return;
|
|
1189
|
+
if (err.status === 400) {
|
|
1190
|
+
return new ChainReadError(`${label} was refused as invalid: ${err.details ?? err.message}`);
|
|
1191
|
+
}
|
|
1192
|
+
if (err.status === 403) {
|
|
1193
|
+
return new HandlerReadError(`${label}: hosted contract reads serve hosted subgraphs only. ${NO_NODE_MESSAGE}`, { cause: err });
|
|
1194
|
+
}
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
function isChainAnswer(err) {
|
|
1198
|
+
return err instanceof ContractResponseError || err instanceof ReadContractError;
|
|
1199
|
+
}
|
|
1200
|
+
function readClient(target) {
|
|
1201
|
+
if (target.kind === "node") {
|
|
1202
|
+
return createPublicClient({
|
|
1203
|
+
transport: http(target.rpcUrl, { retryCount: 0, timeout: 1e4 })
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
return createPublicClient({
|
|
1207
|
+
transport: http(`${target.apiUrl.replace(/\/+$/, "")}/v1/chain-read`, {
|
|
1208
|
+
retryCount: 3,
|
|
1209
|
+
timeout: 1e4,
|
|
1210
|
+
fetchOptions: {
|
|
1211
|
+
headers: { authorization: `Bearer ${target.apiKey}` }
|
|
1212
|
+
}
|
|
1213
|
+
})
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
class ConcurrencyGate {
|
|
1218
|
+
limit;
|
|
1219
|
+
active = 0;
|
|
1220
|
+
queue = [];
|
|
1221
|
+
constructor(limit) {
|
|
1222
|
+
this.limit = limit;
|
|
1223
|
+
}
|
|
1224
|
+
async run(fn) {
|
|
1225
|
+
if (this.active >= this.limit) {
|
|
1226
|
+
await new Promise((resolve) => this.queue.push(resolve));
|
|
1227
|
+
}
|
|
1228
|
+
this.active++;
|
|
1229
|
+
try {
|
|
1230
|
+
return await fn();
|
|
1231
|
+
} finally {
|
|
1232
|
+
this.active--;
|
|
1233
|
+
this.queue.shift()?.();
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
var DEFAULT_MAX_CONCURRENT_READS = 4;
|
|
1238
|
+
function maxConcurrentReads() {
|
|
1239
|
+
const raw = process.env.SUBGRAPH_CHAIN_READ_CONCURRENCY;
|
|
1240
|
+
const parsed = raw ? Number.parseInt(raw, 10) : Number.NaN;
|
|
1241
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CONCURRENT_READS;
|
|
1242
|
+
}
|
|
1243
|
+
var gate = new ConcurrencyGate(maxConcurrentReads());
|
|
1244
|
+
function hashArgs(args) {
|
|
1245
|
+
return chainReadArgsHash(args.map((arg) => serializeCV(arg)));
|
|
1246
|
+
}
|
|
1247
|
+
function findFunction(abi, name) {
|
|
1248
|
+
const fn = abi.functions.find((f) => f.name === name);
|
|
1249
|
+
if (!fn) {
|
|
1250
|
+
throw new ChainReadError(`No function "${name}" in the supplied ABI.`);
|
|
1251
|
+
}
|
|
1252
|
+
if (fn.access !== "read-only") {
|
|
1253
|
+
throw new ChainReadError(`"${name}" is ${fn.access}, not read-only — a handler cannot call it.`);
|
|
1254
|
+
}
|
|
1255
|
+
return fn;
|
|
1256
|
+
}
|
|
1257
|
+
function createChainReadClient(ctx) {
|
|
1258
|
+
const readValue = async (contractId, abi, functionName, args, options) => {
|
|
1259
|
+
const db = ctx.db ?? getSourceDb();
|
|
1260
|
+
const rpcUrl = ctx.rpcUrl || process.env.STACKS_NODE_RPC_URL || undefined;
|
|
1261
|
+
if (!rpcUrl && !process.env.SUBGRAPH_INDEX_API_URL) {
|
|
1262
|
+
throw new HandlerReadError(NO_NODE_MESSAGE);
|
|
1263
|
+
}
|
|
1264
|
+
const constant = options.cache === "contract-constant";
|
|
1265
|
+
if (!constant && !ctx.indexBlockHash) {
|
|
1266
|
+
throw new HandlerReadError(`Block ${ctx.blockHeight} has no index_block_hash, so a read cannot be pinned to it. Reading at the node's tip would make this handler non-deterministic (the same reindex would produce different rows). Re-ingest the block, or pass cache: "contract-constant" if the value genuinely cannot change.`);
|
|
1267
|
+
}
|
|
1268
|
+
const fn = findFunction(abi, functionName);
|
|
1269
|
+
const clarityArgs = buildFunctionArgs(fn, args);
|
|
1270
|
+
const argsHash = hashArgs(clarityArgs);
|
|
1271
|
+
const pinnedTo = constant ? null : ctx.indexBlockHash;
|
|
1272
|
+
let resultHex;
|
|
1273
|
+
try {
|
|
1274
|
+
const cached = await db.selectFrom("chain_read_cache").select("result_hex").where("contract_id", "=", contractId).where("function_name", "=", fn.name).where("args_hash", "=", argsHash).where((eb) => pinnedTo === null ? eb("index_block_hash", "is", null) : eb("index_block_hash", "=", pinnedTo)).executeTakeFirst();
|
|
1275
|
+
resultHex = cached?.result_hex ?? await gate.run(async () => {
|
|
1276
|
+
const target = await resolveReadTarget(rpcUrl, db);
|
|
1277
|
+
if (!ctx.indexBlockHash && target.kind === "hosted") {
|
|
1278
|
+
throw new HandlerReadError(`Block ${ctx.blockHeight} has no index_block_hash, so a hosted contract read cannot be pinned to it. Reindex the subgraph from this block once the block is re-ingested.`);
|
|
1279
|
+
}
|
|
1280
|
+
if (!ctx.indexBlockHash) {
|
|
1281
|
+
logger.warn("Chain read is not pinned to a block (no index_block_hash)", {
|
|
1282
|
+
contractId,
|
|
1283
|
+
functionName: fn.name,
|
|
1284
|
+
blockHeight: ctx.blockHeight,
|
|
1285
|
+
note: 'cache: "contract-constant" asserts this value cannot change; the node answered at its own tip'
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
try {
|
|
1289
|
+
const value = await readContract(readClient(target), {
|
|
1290
|
+
contract: contractId,
|
|
1291
|
+
functionName: fn.name,
|
|
1292
|
+
args: clarityArgs,
|
|
1293
|
+
tip: ctx.indexBlockHash ?? undefined
|
|
1294
|
+
});
|
|
1295
|
+
return serializeCV(value);
|
|
1296
|
+
} catch (err) {
|
|
1297
|
+
throw target.kind === "hosted" && hostedReadError(err, `Chain read ${contractId}::${fn.name}`) || err;
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
if (!cached) {
|
|
1301
|
+
await db.insertInto("chain_read_cache").values({
|
|
1302
|
+
contract_id: contractId,
|
|
1303
|
+
function_name: fn.name,
|
|
1304
|
+
args_hash: argsHash,
|
|
1305
|
+
index_block_hash: pinnedTo,
|
|
1306
|
+
block_height: constant ? null : ctx.blockHeight,
|
|
1307
|
+
result_hex: resultHex
|
|
1308
|
+
}).onConflict((oc) => oc.doNothing()).execute();
|
|
1309
|
+
}
|
|
1310
|
+
} catch (err) {
|
|
1311
|
+
if (isChainAnswer(err) || err instanceof ChainReadError || err instanceof HandlerReadError) {
|
|
1312
|
+
throw err;
|
|
1313
|
+
}
|
|
1314
|
+
throw new HandlerReadError(`Chain read ${contractId}::${fn.name} at block ${ctx.blockHeight} failed: ${getErrorMessage(err)}`, { cause: err });
|
|
1315
|
+
}
|
|
1316
|
+
const value = deserializeCV2(resultHex);
|
|
1317
|
+
const js = clarityValueToJSUntyped(fn.outputs, value);
|
|
1318
|
+
if (isResponseOutput(fn.outputs)) {
|
|
1319
|
+
const response = js;
|
|
1320
|
+
if ("ok" in response)
|
|
1321
|
+
return response.ok;
|
|
1322
|
+
throw new ContractResponseError(`${contractId}::${fn.name} returned an err response.`, response.err);
|
|
1323
|
+
}
|
|
1324
|
+
return js;
|
|
1325
|
+
};
|
|
1326
|
+
return {
|
|
1327
|
+
contract(contractId, rawAbi, options = {}) {
|
|
1328
|
+
const abi = normalizeAbi(rawAbi);
|
|
1329
|
+
const camelToKebab = new Map;
|
|
1330
|
+
for (const fn of abi.functions) {
|
|
1331
|
+
camelToKebab.set(toCamelCase(fn.name), fn.name);
|
|
1332
|
+
}
|
|
1333
|
+
const read = new Proxy({}, {
|
|
1334
|
+
get(_target, prop) {
|
|
1335
|
+
const fnName = camelToKebab.get(prop) ?? prop;
|
|
1336
|
+
return (args = {}) => readValue(contractId, abi, fnName, args, options);
|
|
1337
|
+
}
|
|
1338
|
+
});
|
|
1339
|
+
return { read };
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1275
1343
|
// src/schema/generator.ts
|
|
1276
1344
|
import { createHash as createHash2 } from "node:crypto";
|
|
1277
1345
|
|
|
@@ -2955,5 +3023,5 @@ export {
|
|
|
2955
3023
|
validateSubgraphDefinition
|
|
2956
3024
|
};
|
|
2957
3025
|
|
|
2958
|
-
//# debugId=
|
|
3026
|
+
//# debugId=DF88F51AA47CFDD764756E2164756E21
|
|
2959
3027
|
//# sourceMappingURL=index.js.map
|