@thru/abi 0.1.38 → 0.2.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/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import * as yaml from 'yaml';
2
+
1
3
  // src/utils/bytes.ts
2
4
  function hexToBytes(hex) {
3
5
  let normalized = hex.trim().replace(/[\s_]/g, "");
@@ -192,7 +194,628 @@ function formatReflection(raw, options) {
192
194
  const result = bindings.format_reflection(serialized);
193
195
  return JSON.parse(result);
194
196
  }
197
+ async function callReflectWithManifest(manifest, rootPackage, typeName, buffer) {
198
+ const bindings = await loadBindings();
199
+ const manifestJson = JSON.stringify(manifest);
200
+ const result = bindings.reflect_with_manifest(manifestJson, rootPackage, typeName, buffer);
201
+ return JSON.parse(result);
202
+ }
203
+ async function callReflectInstructionWithManifest(manifest, rootPackage, buffer) {
204
+ const bindings = await loadBindings();
205
+ const manifestJson = JSON.stringify(manifest);
206
+ const result = bindings.reflect_instruction_with_manifest(manifestJson, rootPackage, buffer);
207
+ return JSON.parse(result);
208
+ }
209
+ async function callReflectAccountWithManifest(manifest, rootPackage, buffer) {
210
+ const bindings = await loadBindings();
211
+ const manifestJson = JSON.stringify(manifest);
212
+ const result = bindings.reflect_account_with_manifest(manifestJson, rootPackage, buffer);
213
+ return JSON.parse(result);
214
+ }
215
+ async function callReflectEventWithManifest(manifest, rootPackage, buffer) {
216
+ const bindings = await loadBindings();
217
+ const manifestJson = JSON.stringify(manifest);
218
+ const result = bindings.reflect_event_with_manifest(manifestJson, rootPackage, buffer);
219
+ return JSON.parse(result);
220
+ }
221
+ async function reflectWithManifest(manifest, rootPackage, typeName, payload) {
222
+ if (payload.type === "binary") {
223
+ return callReflectWithManifest(manifest, rootPackage, typeName, toUint8Array(payload.value));
224
+ }
225
+ if (payload.type === "hex") {
226
+ return callReflectWithManifest(manifest, rootPackage, typeName, hexToBytes(payload.value));
227
+ }
228
+ throw new Error(`Invalid payload type`);
229
+ }
230
+ async function reflectInstructionWithManifest(manifest, rootPackage, payload) {
231
+ if (payload.type === "binary") {
232
+ return callReflectInstructionWithManifest(manifest, rootPackage, toUint8Array(payload.value));
233
+ }
234
+ if (payload.type === "hex") {
235
+ return callReflectInstructionWithManifest(manifest, rootPackage, hexToBytes(payload.value));
236
+ }
237
+ throw new Error(`Invalid payload type`);
238
+ }
239
+ async function reflectAccountWithManifest(manifest, rootPackage, payload) {
240
+ if (payload.type === "binary") {
241
+ return callReflectAccountWithManifest(manifest, rootPackage, toUint8Array(payload.value));
242
+ }
243
+ if (payload.type === "hex") {
244
+ return callReflectAccountWithManifest(manifest, rootPackage, hexToBytes(payload.value));
245
+ }
246
+ throw new Error(`Invalid payload type`);
247
+ }
248
+ async function reflectEventWithManifest(manifest, rootPackage, payload) {
249
+ if (payload.type === "binary") {
250
+ return callReflectEventWithManifest(manifest, rootPackage, toUint8Array(payload.value));
251
+ }
252
+ if (payload.type === "hex") {
253
+ return callReflectEventWithManifest(manifest, rootPackage, hexToBytes(payload.value));
254
+ }
255
+ throw new Error(`Invalid payload type`);
256
+ }
257
+ async function buildLayoutIrWithManifest(manifest, rootPackage) {
258
+ const bindings = await loadBindings();
259
+ const manifestJson = JSON.stringify(manifest);
260
+ const result = bindings.build_layout_ir_with_manifest(manifestJson, rootPackage);
261
+ return JSON.parse(result);
262
+ }
263
+ async function getManifestPackages(manifest) {
264
+ const bindings = await loadBindings();
265
+ const manifestJson = JSON.stringify(manifest);
266
+ const result = bindings.get_manifest_packages(manifestJson);
267
+ return JSON.parse(result);
268
+ }
269
+ async function validateManifest(manifest) {
270
+ const bindings = await loadBindings();
271
+ const manifestJson = JSON.stringify(manifest);
272
+ const result = bindings.validate_manifest(manifestJson);
273
+ return JSON.parse(result);
274
+ }
275
+
276
+ // src/imports/types.ts
277
+ var ResolutionError = class extends Error {
278
+ constructor(code, message, details) {
279
+ super(message);
280
+ this.code = code;
281
+ this.details = details;
282
+ this.name = "ResolutionError";
283
+ }
284
+ };
285
+ var ABI_ACCOUNT_HEADER_SIZE = 45;
286
+ var ABI_STATE_OPEN = 0;
287
+ var ABI_STATE_FINALIZED = 1;
288
+ var DEFAULT_RPC_ENDPOINTS = {
289
+ mainnet: "https://rpc.thru.network",
290
+ testnet: "https://rpc-testnet.thru.network"
291
+ };
292
+
293
+ // src/imports/onchainFetcher.ts
294
+ var ABI_ACCOUNT_SUFFIX = "_abi_account";
295
+ var ABI_ACCOUNT_SUFFIX_BYTES = new TextEncoder().encode(ABI_ACCOUNT_SUFFIX);
296
+ var ABI_META_HEADER_SIZE = 4;
297
+ var ABI_META_BODY_SIZE = 96;
298
+ var ABI_META_ACCOUNT_SIZE = ABI_META_HEADER_SIZE + ABI_META_BODY_SIZE;
299
+ var ABI_META_VERSION = 1;
300
+ var ABI_META_KIND_OFFICIAL = 0;
301
+ var ABI_META_KIND_EXTERNAL = 1;
302
+ var DEFAULT_ABI_MANAGER_PROGRAM_ID = "taWqAAOSe9pavaaMpkc9VbSLBUMbuW6Mk59sZlSbcNHsJA";
303
+ async function sha256Bytes(data) {
304
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
305
+ return new Uint8Array(hashBuffer);
306
+ }
307
+ function concatBytes(...chunks) {
308
+ const total = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
309
+ const out = new Uint8Array(total);
310
+ let offset = 0;
311
+ for (const chunk of chunks) {
312
+ out.set(chunk, offset);
313
+ offset += chunk.length;
314
+ }
315
+ return out;
316
+ }
317
+ function abiMetaBodyForProgram(program) {
318
+ const body = new Uint8Array(ABI_META_BODY_SIZE);
319
+ body.set(program.slice(0, 32), 0);
320
+ return body;
321
+ }
322
+ async function deriveAbiAccountSeed(kind, body) {
323
+ return sha256Bytes(concatBytes(new Uint8Array([kind]), body, ABI_ACCOUNT_SUFFIX_BYTES));
324
+ }
325
+ async function createProgramDefinedAccountAddress(owner, isEphemeral, seed) {
326
+ const flag = new Uint8Array([isEphemeral ? 1 : 0]);
327
+ return sha256Bytes(concatBytes(owner, flag, seed));
328
+ }
329
+ async function deriveAbiAccountAddress(kind, body, owner, isEphemeral) {
330
+ const seed = await deriveAbiAccountSeed(kind, body);
331
+ return createProgramDefinedAccountAddress(owner, isEphemeral, seed);
332
+ }
333
+ async function deriveOfficialAbiAddress(programAddress, abiManagerProgramId = DEFAULT_ABI_MANAGER_PROGRAM_ID) {
334
+ const programBytes = decodeAddress(programAddress);
335
+ const managerBytes = decodeAddress(abiManagerProgramId);
336
+ const body = abiMetaBodyForProgram(programBytes);
337
+ return deriveAbiAccountAddress(ABI_META_KIND_OFFICIAL, body, managerBytes, false);
338
+ }
339
+ function parseAbiMetaAccount(data) {
340
+ if (data.length < ABI_META_ACCOUNT_SIZE) {
341
+ throw new Error(
342
+ `ABI meta account data too short: ${data.length} bytes, expected at least ${ABI_META_ACCOUNT_SIZE}`
343
+ );
344
+ }
345
+ const version = data[0];
346
+ const kind = data[1];
347
+ const flags = data[2] | data[3] << 8;
348
+ const body = data.slice(ABI_META_HEADER_SIZE, ABI_META_HEADER_SIZE + ABI_META_BODY_SIZE);
349
+ if (version !== ABI_META_VERSION) {
350
+ throw new Error(`Unsupported ABI meta version: ${version}`);
351
+ }
352
+ if (kind !== ABI_META_KIND_OFFICIAL && kind !== ABI_META_KIND_EXTERNAL) {
353
+ throw new Error(`Unsupported ABI meta kind: ${kind}`);
354
+ }
355
+ return { version, kind, flags, body };
356
+ }
357
+ function parseAbiAccountData(data) {
358
+ if (data.length < ABI_ACCOUNT_HEADER_SIZE) {
359
+ throw new Error(
360
+ `ABI account data too short: ${data.length} bytes, expected at least ${ABI_ACCOUNT_HEADER_SIZE}`
361
+ );
362
+ }
363
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
364
+ const abiMetaAccount = data.slice(0, 32);
365
+ const revision = view.getBigUint64(32, true);
366
+ const state = data[40];
367
+ const contentSize = view.getUint32(41, true);
368
+ if (state !== ABI_STATE_OPEN && state !== ABI_STATE_FINALIZED) {
369
+ throw new Error(`Invalid ABI account state: ${state}`);
370
+ }
371
+ const expectedSize = ABI_ACCOUNT_HEADER_SIZE + contentSize;
372
+ if (data.length < expectedSize) {
373
+ throw new Error(
374
+ `ABI account data truncated: ${data.length} bytes, expected ${expectedSize}`
375
+ );
376
+ }
377
+ const contentBytes = data.slice(ABI_ACCOUNT_HEADER_SIZE, expectedSize);
378
+ const content = new TextDecoder().decode(contentBytes);
379
+ return {
380
+ abiMetaAccount,
381
+ revision,
382
+ state,
383
+ content
384
+ };
385
+ }
386
+ function revisionMatches(revision, spec) {
387
+ switch (spec.type) {
388
+ case "latest":
389
+ return true;
390
+ case "exact":
391
+ return revision === BigInt(spec.value);
392
+ case "minimum":
393
+ return revision >= BigInt(spec.value);
394
+ default:
395
+ return false;
396
+ }
397
+ }
398
+ var OnchainFetcher = class {
399
+ constructor(config = {}) {
400
+ this.rpcEndpoints = { ...DEFAULT_RPC_ENDPOINTS, ...config.rpcEndpoints };
401
+ this.thruClient = config.thruClient;
402
+ const managerId = config.abiManagerProgramId ?? DEFAULT_ABI_MANAGER_PROGRAM_ID;
403
+ this.abiManagerProgramId = decodeAddress(managerId);
404
+ this.abiManagerIsEphemeral = config.abiManagerIsEphemeral ?? false;
405
+ }
406
+ /**
407
+ * Fetch ABI content from an on-chain account.
408
+ */
409
+ async fetch(address, target, network, revision) {
410
+ const addressBytes = this.parseAddress(address);
411
+ let abiAddress;
412
+ if (target === "program") {
413
+ const body = abiMetaBodyForProgram(addressBytes);
414
+ abiAddress = await deriveAbiAccountAddress(
415
+ ABI_META_KIND_OFFICIAL,
416
+ body,
417
+ this.abiManagerProgramId,
418
+ this.abiManagerIsEphemeral
419
+ );
420
+ } else if (target === "abi-meta") {
421
+ const metaData = await this.fetchAccountData(addressBytes, network);
422
+ const meta = parseAbiMetaAccount(metaData);
423
+ abiAddress = await deriveAbiAccountAddress(
424
+ meta.kind,
425
+ meta.body,
426
+ this.abiManagerProgramId,
427
+ this.abiManagerIsEphemeral
428
+ );
429
+ } else {
430
+ abiAddress = addressBytes;
431
+ }
432
+ const accountData = await this.fetchAccountData(abiAddress, network);
433
+ const parsed = parseAbiAccountData(accountData);
434
+ if (!revisionMatches(parsed.revision, revision)) {
435
+ const revisionStr = revision.type === "exact" ? `exactly ${revision.value}` : revision.type === "minimum" ? `at least ${revision.value}` : "latest";
436
+ throw new Error(
437
+ `ABI revision mismatch: got ${parsed.revision}, expected ${revisionStr}`
438
+ );
439
+ }
440
+ return {
441
+ abiYaml: parsed.content,
442
+ revision: parsed.revision,
443
+ isFinalized: parsed.state === ABI_STATE_FINALIZED
444
+ };
445
+ }
446
+ /**
447
+ * Get the RPC endpoint for a network.
448
+ */
449
+ getRpcEndpoint(network) {
450
+ const endpoint = this.rpcEndpoints[network];
451
+ if (!endpoint) {
452
+ throw new Error(
453
+ `Unknown network: ${network}. Configure rpcEndpoints for this network.`
454
+ );
455
+ }
456
+ return endpoint;
457
+ }
458
+ parseAddress(address) {
459
+ return decodeAddress(address);
460
+ }
461
+ async fetchAccountData(address, network) {
462
+ if (this.thruClient) {
463
+ return this.fetchWithThruClient(address);
464
+ }
465
+ return this.fetchWithHttp(address, network);
466
+ }
467
+ async fetchWithThruClient(address) {
468
+ if (!this.thruClient) {
469
+ throw new Error("ThruClient not configured");
470
+ }
471
+ const response = await this.thruClient.query.getRawAccount({
472
+ address: { value: address },
473
+ versionContext: {}
474
+ });
475
+ if (!response.rawData) {
476
+ throw new Error("Account not found or has no data");
477
+ }
478
+ return response.rawData;
479
+ }
480
+ async fetchWithHttp(address, network) {
481
+ const endpoint = this.getRpcEndpoint(network);
482
+ const addressStr = encodeThruAddress(address);
483
+ const response = await fetch(`${endpoint}/v1/accounts/${addressStr}:raw`, {
484
+ method: "GET",
485
+ headers: {
486
+ Accept: "application/json"
487
+ }
488
+ });
489
+ if (!response.ok) {
490
+ if (response.status === 404) {
491
+ throw new Error(`ABI account not found: ${addressStr}`);
492
+ }
493
+ throw new Error(`Failed to fetch account: ${response.status} ${response.statusText}`);
494
+ }
495
+ const json = await response.json();
496
+ if (!json.rawData) {
497
+ throw new Error("Account has no data");
498
+ }
499
+ return base64Decode(json.rawData);
500
+ }
501
+ };
502
+ var BASE64_URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
503
+ function decodeAddress(address) {
504
+ if (address.startsWith("ta") && address.length === 46) {
505
+ return decodeThruAddress(address);
506
+ }
507
+ throw new Error(`Invalid Thru address format: ${address} (expected 46-char ta-prefixed address)`);
508
+ }
509
+ function decodeThruAddress(address) {
510
+ if (address.length !== 46 || !address.startsWith("ta")) {
511
+ throw new Error(`Invalid Thru address: ${address}`);
512
+ }
513
+ const invlut = new Int16Array(256);
514
+ invlut.fill(-1);
515
+ for (let i = 0; i < BASE64_URL_ALPHABET.length; i += 1) {
516
+ invlut[BASE64_URL_ALPHABET.charCodeAt(i)] = i;
517
+ }
518
+ let inIdx = 2;
519
+ let inSz = 40;
520
+ let outIdx = 0;
521
+ let checksum = 0;
522
+ const out = new Uint8Array(32);
523
+ while (inSz >= 4) {
524
+ const a2 = invlut[address.charCodeAt(inIdx + 0)];
525
+ const b2 = invlut[address.charCodeAt(inIdx + 1)];
526
+ const c2 = invlut[address.charCodeAt(inIdx + 2)];
527
+ const d2 = invlut[address.charCodeAt(inIdx + 3)];
528
+ if (a2 < 0 || b2 < 0 || c2 < 0 || d2 < 0) {
529
+ throw new Error(`Invalid Thru address character at ${inIdx}`);
530
+ }
531
+ const triple2 = a2 << 18 | b2 << 12 | c2 << 6 | d2;
532
+ const temp12 = triple2 >> 16 & 255;
533
+ checksum += temp12;
534
+ out[outIdx++] = temp12;
535
+ const temp22 = triple2 >> 8 & 255;
536
+ checksum += temp22;
537
+ out[outIdx++] = temp22;
538
+ const temp3 = triple2 & 255;
539
+ checksum += temp3;
540
+ out[outIdx++] = temp3;
541
+ inIdx += 4;
542
+ inSz -= 4;
543
+ }
544
+ const a = invlut[address.charCodeAt(inIdx + 0)];
545
+ const b = invlut[address.charCodeAt(inIdx + 1)];
546
+ const c = invlut[address.charCodeAt(inIdx + 2)];
547
+ const d = invlut[address.charCodeAt(inIdx + 3)];
548
+ if (a < 0 || b < 0 || c < 0 || d < 0) {
549
+ throw new Error(`Invalid Thru address character at ${inIdx}`);
550
+ }
551
+ const triple = a << 18 | b << 12 | c << 6 | d;
552
+ const temp1 = triple >> 16 & 255;
553
+ checksum += temp1;
554
+ out[outIdx++] = temp1;
555
+ const temp2 = triple >> 8 & 255;
556
+ checksum += temp2;
557
+ out[outIdx++] = temp2;
558
+ const incomingChecksum = triple & 255;
559
+ if ((checksum & 255) !== incomingChecksum) {
560
+ throw new Error("Invalid Thru address checksum");
561
+ }
562
+ return out;
563
+ }
564
+ function encodeThruAddress(bytes) {
565
+ if (bytes.length !== 32) {
566
+ throw new Error(`Expected 32 bytes, got ${bytes.length}`);
567
+ }
568
+ function maskForBits(bits) {
569
+ return bits === 0 ? 0 : (1 << bits) - 1;
570
+ }
571
+ let output = "ta";
572
+ let checksum = 0;
573
+ let accumulator = 0;
574
+ let bitsCollected = 0;
575
+ for (let i = 0; i < 30; i++) {
576
+ const byte = bytes[i];
577
+ checksum += byte;
578
+ accumulator = accumulator << 8 | byte;
579
+ bitsCollected += 8;
580
+ while (bitsCollected >= 6) {
581
+ const index = accumulator >> bitsCollected - 6 & 63;
582
+ output += BASE64_URL_ALPHABET[index];
583
+ bitsCollected -= 6;
584
+ accumulator &= maskForBits(bitsCollected);
585
+ }
586
+ }
587
+ const secondLast = bytes[30];
588
+ checksum += secondLast;
589
+ accumulator = accumulator << 8 | secondLast;
590
+ bitsCollected += 8;
591
+ const last = bytes[31];
592
+ checksum += last;
593
+ accumulator = accumulator << 8 | last;
594
+ bitsCollected += 8;
595
+ accumulator = accumulator << 8 | checksum & 255;
596
+ bitsCollected += 8;
597
+ while (bitsCollected >= 6) {
598
+ const index = accumulator >> bitsCollected - 6 & 63;
599
+ output += BASE64_URL_ALPHABET[index];
600
+ bitsCollected -= 6;
601
+ accumulator &= maskForBits(bitsCollected);
602
+ }
603
+ return output;
604
+ }
605
+ function base64Decode(str) {
606
+ const binaryStr = atob(str);
607
+ const bytes = new Uint8Array(binaryStr.length);
608
+ for (let i = 0; i < binaryStr.length; i++) {
609
+ bytes[i] = binaryStr.charCodeAt(i);
610
+ }
611
+ return bytes;
612
+ }
613
+ async function resolveImports(rootAbiYaml, config = {}) {
614
+ const resolver = new ImportResolver(config);
615
+ return resolver.resolve(rootAbiYaml);
616
+ }
617
+ function createManifest(result) {
618
+ return result.manifest;
619
+ }
620
+ var ImportResolver = class {
621
+ constructor(config = {}) {
622
+ this.onchainFetcher = config.onchainFetcher ?? new OnchainFetcher({
623
+ rpcEndpoints: { ...DEFAULT_RPC_ENDPOINTS, ...config.rpcEndpoints }
624
+ });
625
+ this.maxDepth = config.maxDepth ?? 10;
626
+ this.visited = /* @__PURE__ */ new Map();
627
+ this.inProgress = /* @__PURE__ */ new Set();
628
+ }
629
+ async resolve(rootAbiYaml) {
630
+ this.visited.clear();
631
+ this.inProgress.clear();
632
+ const rootPackage = await this.resolvePackage(rootAbiYaml, false, 0);
633
+ const allPackages = Array.from(this.visited.values());
634
+ const manifest = {};
635
+ for (const pkg of allPackages) {
636
+ manifest[pkg.id.packageName] = pkg.abiYaml;
637
+ }
638
+ return {
639
+ root: rootPackage,
640
+ allPackages,
641
+ manifest
642
+ };
643
+ }
644
+ async resolvePackage(abiYaml, isRemote, depth) {
645
+ if (depth > this.maxDepth) {
646
+ throw new ResolutionError(
647
+ "CYCLIC_DEPENDENCY",
648
+ `Maximum resolution depth (${this.maxDepth}) exceeded`
649
+ );
650
+ }
651
+ const abiFile = this.parseAbiYaml(abiYaml);
652
+ const packageId = this.extractPackageId(abiFile);
653
+ const canonicalKey = `${packageId.packageName}@${packageId.version}`;
654
+ if (this.inProgress.has(canonicalKey)) {
655
+ throw new ResolutionError(
656
+ "CYCLIC_DEPENDENCY",
657
+ `Cyclic dependency detected: ${canonicalKey}`
658
+ );
659
+ }
660
+ const existing = this.visited.get(canonicalKey);
661
+ if (existing) {
662
+ return existing;
663
+ }
664
+ for (const [key, pkg] of this.visited) {
665
+ if (pkg.id.packageName === packageId.packageName && pkg.id.version !== packageId.version) {
666
+ throw new ResolutionError(
667
+ "VERSION_CONFLICT",
668
+ `Version conflict for ${packageId.packageName}: ${pkg.id.version} vs ${packageId.version}`,
669
+ { existing: pkg.id, conflicting: packageId }
670
+ );
671
+ }
672
+ }
673
+ this.inProgress.add(canonicalKey);
674
+ const imports = abiFile.abi.imports ?? [];
675
+ const dependencies = [];
676
+ for (const importYaml of imports) {
677
+ const importSource = this.normalizeImportSource(importYaml);
678
+ if (isRemote && importSource.type === "path") {
679
+ throw new ResolutionError(
680
+ "UNSUPPORTED_IMPORT_TYPE",
681
+ `Remote package ${packageId.packageName} cannot import local path: ${importSource.path}`
682
+ );
683
+ }
684
+ const childIsRemote = importSource.type !== "path";
685
+ const depPackage = await this.resolveImport(importSource, childIsRemote, depth + 1);
686
+ dependencies.push(depPackage.id);
687
+ }
688
+ this.inProgress.delete(canonicalKey);
689
+ const resolvedPackage = {
690
+ id: packageId,
691
+ source: { type: "path", path: "<root>" },
692
+ abiYaml,
693
+ dependencies,
694
+ isRemote
695
+ };
696
+ this.visited.set(canonicalKey, resolvedPackage);
697
+ return resolvedPackage;
698
+ }
699
+ async resolveImport(source, parentIsRemote, depth) {
700
+ switch (source.type) {
701
+ case "path":
702
+ throw new ResolutionError(
703
+ "UNSUPPORTED_IMPORT_TYPE",
704
+ `Path imports are not supported in browser. Use CLI 'bundle' command. Path: ${source.path}`
705
+ );
706
+ case "git":
707
+ throw new ResolutionError(
708
+ "UNSUPPORTED_IMPORT_TYPE",
709
+ `Git imports are not supported in browser. Use CLI 'bundle' command. URL: ${source.url}`
710
+ );
711
+ case "http":
712
+ throw new ResolutionError(
713
+ "UNSUPPORTED_IMPORT_TYPE",
714
+ `HTTP imports are not supported in browser. Use CLI 'bundle' command. URL: ${source.url}`
715
+ );
716
+ case "onchain":
717
+ return this.resolveOnchainImport(source, depth);
718
+ default:
719
+ throw new ResolutionError(
720
+ "UNSUPPORTED_IMPORT_TYPE",
721
+ `Unknown import type: ${source.type}`
722
+ );
723
+ }
724
+ }
725
+ async resolveOnchainImport(source, depth) {
726
+ const result = await this.onchainFetcher.fetch(
727
+ source.address,
728
+ source.target,
729
+ source.network,
730
+ source.revision
731
+ );
732
+ const resolved = await this.resolvePackage(result.abiYaml, true, depth);
733
+ resolved.source = source;
734
+ resolved.isRemote = true;
735
+ return resolved;
736
+ }
737
+ parseAbiYaml(yamlContent) {
738
+ try {
739
+ const parsed = yaml.parse(yamlContent);
740
+ if (!parsed || typeof parsed !== "object") {
741
+ throw new Error("Invalid ABI YAML: not an object");
742
+ }
743
+ if (!parsed.abi || typeof parsed.abi !== "object") {
744
+ throw new Error("Invalid ABI YAML: missing 'abi' section");
745
+ }
746
+ return parsed;
747
+ } catch (error) {
748
+ throw new ResolutionError(
749
+ "PARSE_ERROR",
750
+ `Failed to parse ABI YAML: ${error instanceof Error ? error.message : String(error)}`,
751
+ error
752
+ );
753
+ }
754
+ }
755
+ extractPackageId(abiFile) {
756
+ const metadata = abiFile.abi;
757
+ if (!metadata.package) {
758
+ throw new ResolutionError("PARSE_ERROR", "ABI missing 'package' field");
759
+ }
760
+ return {
761
+ packageName: metadata.package,
762
+ version: metadata["package-version"] ?? "0.0.0"
763
+ };
764
+ }
765
+ normalizeImportSource(source) {
766
+ switch (source.type) {
767
+ case "path":
768
+ return { type: "path", path: source.path };
769
+ case "git":
770
+ return {
771
+ type: "git",
772
+ url: source.url,
773
+ ref: source.ref,
774
+ path: source.path
775
+ };
776
+ case "http":
777
+ return { type: "http", url: source.url };
778
+ case "onchain": {
779
+ const revision = this.parseRevisionSpec(source.revision);
780
+ return {
781
+ type: "onchain",
782
+ address: source.address,
783
+ target: source.target ?? "program",
784
+ network: source.network,
785
+ revision
786
+ };
787
+ }
788
+ default:
789
+ throw new ResolutionError(
790
+ "UNSUPPORTED_IMPORT_TYPE",
791
+ `Unknown import type: ${source.type}`
792
+ );
793
+ }
794
+ }
795
+ parseRevisionSpec(revision) {
796
+ if (revision === void 0 || revision === "latest") {
797
+ return { type: "latest" };
798
+ }
799
+ if (typeof revision === "number") {
800
+ return { type: "exact", value: revision };
801
+ }
802
+ if (typeof revision === "string") {
803
+ if (revision.startsWith(">=")) {
804
+ const value2 = parseInt(revision.slice(2), 10);
805
+ if (isNaN(value2)) {
806
+ throw new Error(`Invalid minimum revision: ${revision}`);
807
+ }
808
+ return { type: "minimum", value: value2 };
809
+ }
810
+ const value = parseInt(revision, 10);
811
+ if (!isNaN(value)) {
812
+ return { type: "exact", value };
813
+ }
814
+ }
815
+ throw new Error(`Invalid revision specification: ${revision}`);
816
+ }
817
+ };
195
818
 
196
- export { buildLayoutIr, configureWasm, ensureWasmLoaded, formatReflection, reflect, reflectAccount, reflectEvent, reflectInstruction };
819
+ export { ABI_ACCOUNT_HEADER_SIZE, ABI_STATE_FINALIZED, ABI_STATE_OPEN, DEFAULT_RPC_ENDPOINTS, OnchainFetcher, ResolutionError, buildLayoutIr, buildLayoutIrWithManifest, configureWasm, createManifest, deriveOfficialAbiAddress, ensureWasmLoaded, formatReflection, getManifestPackages, parseAbiAccountData, reflect, reflectAccount, reflectAccountWithManifest, reflectEvent, reflectEventWithManifest, reflectInstruction, reflectInstructionWithManifest, reflectWithManifest, resolveImports, revisionMatches, validateManifest };
197
820
  //# sourceMappingURL=index.js.map
198
821
  //# sourceMappingURL=index.js.map