@thru/sdk 0.2.22 → 0.2.23

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.
Files changed (33) hide show
  1. package/README.abi.md +10 -0
  2. package/dist/abi/index.cjs +156 -7
  3. package/dist/abi/index.cjs.map +1 -1
  4. package/dist/abi/index.d.cts +38 -3
  5. package/dist/abi/index.d.ts +38 -3
  6. package/dist/abi/index.js +155 -8
  7. package/dist/abi/index.js.map +1 -1
  8. package/dist/abi/wasm/bundler/abi_reflect_wasm_bg.wasm +0 -0
  9. package/dist/abi/wasm/node/abi_reflect_wasm_bg.wasm +0 -0
  10. package/dist/abi/wasm/web/abi_reflect_wasm_bg.wasm +0 -0
  11. package/dist/{chunk-YQDWOMNO.js → chunk-7IYMAAGA.js} +2 -2
  12. package/dist/{chunk-YQDWOMNO.js.map → chunk-7IYMAAGA.js.map} +1 -1
  13. package/dist/{chunk-CVBQ4UPL.js → chunk-UFG6YDCG.js} +3 -3
  14. package/dist/{chunk-CVBQ4UPL.js.map → chunk-UFG6YDCG.js.map} +1 -1
  15. package/dist/{client-worIo0a3.d.ts → client-BmDvZzhb.d.ts} +1 -1
  16. package/dist/{client-Cfi7zRLm.d.cts → client-DjifFmSR.d.cts} +1 -1
  17. package/dist/client.cjs.map +1 -1
  18. package/dist/client.d.cts +2 -2
  19. package/dist/client.d.ts +2 -2
  20. package/dist/client.js +2 -2
  21. package/dist/metafile-cjs.json +1 -1
  22. package/dist/metafile-esm.json +1 -1
  23. package/dist/proto/index.cjs.map +1 -1
  24. package/dist/proto/index.d.cts +2 -2
  25. package/dist/proto/index.d.ts +2 -2
  26. package/dist/proto/index.js +1 -1
  27. package/dist/sdk.cjs.map +1 -1
  28. package/dist/sdk.d.cts +3 -3
  29. package/dist/sdk.d.ts +3 -3
  30. package/dist/sdk.js +2 -2
  31. package/dist/{streaming_service_pb-DvCdJiCr.d.ts → streaming_service_pb-CqoILI8i.d.cts} +10 -0
  32. package/dist/{streaming_service_pb-DvCdJiCr.d.cts → streaming_service_pb-CqoILI8i.d.ts} +10 -0
  33. package/package.json +1 -1
package/README.abi.md CHANGED
@@ -72,6 +72,16 @@ That script runs `wasm-pack build` three times (bundler + node + web targets) in
72
72
  `tsup` and copies those WASM folders into `dist/abi/wasm` so published packages
73
73
  resolve the dynamic imports automatically.
74
74
 
75
+ Browser apps that cannot serve package-relative dynamic imports can publish the
76
+ web target as static assets and configure both URLs before calling reflection:
77
+
78
+ ```ts
79
+ configureWasm({
80
+ moduleUrl: "/wasm/abi/web/abi_reflect_wasm.js",
81
+ wasmUrl: "/wasm/abi/web/abi_reflect_wasm_bg.wasm",
82
+ });
83
+ ```
84
+
75
85
  When developing inside the monorepo, Vitest loads the TypeScript sources
76
86
  directly. The runtime detects when it is executing from `src/` and reaches for
77
87
  `../wasm`, so make sure the synced artifacts exist before running the tests.
@@ -73,12 +73,19 @@ function isNodeRuntime() {
73
73
 
74
74
  // src/abi/wasmBridge.ts
75
75
  var configuredWasmUrl;
76
- function configureWasm(url) {
76
+ var configuredWasmModuleUrl;
77
+ function configureWasm(config) {
77
78
  if (cachedBindings) {
78
79
  console.warn("configureWasm called after WASM was already loaded. Configuration ignored.");
79
80
  return;
80
81
  }
81
- configuredWasmUrl = url;
82
+ if (typeof config === "string") {
83
+ configuredWasmUrl = config;
84
+ configuredWasmModuleUrl = void 0;
85
+ return;
86
+ }
87
+ configuredWasmUrl = config.wasmUrl;
88
+ configuredWasmModuleUrl = config.moduleUrl;
82
89
  }
83
90
  var wasmDir = resolveWasmDir();
84
91
  var bindingsPromise;
@@ -124,6 +131,14 @@ function resolveImportMetaUrl() {
124
131
  async function importModule(specifier) {
125
132
  return dynamicImport(specifier);
126
133
  }
134
+ function resolveRuntimeUrl(url) {
135
+ if (/^(?:[a-zA-Z][a-zA-Z\d+.-]*:|\/\/)/.test(url)) {
136
+ return url;
137
+ }
138
+ const location = typeof globalThis.location === "object" && globalThis.location ? globalThis.location : void 0;
139
+ const base = typeof location?.href === "string" && location.href.length > 0 ? location.href : resolveImportMetaUrl();
140
+ return resolveModuleUrl(url, base);
141
+ }
127
142
  function requireModule(moduleUrl) {
128
143
  try {
129
144
  const requireFn = typeof __require === "function" ? __require : void 0;
@@ -140,6 +155,22 @@ function resolveWasmDir() {
140
155
  if (url.includes("/dist/")) return "./wasm";
141
156
  return "./wasm";
142
157
  }
158
+ function resolveConfiguredWasmModuleUrl(wasmUrl) {
159
+ const base = typeof globalThis.location === "object" && typeof globalThis.location?.href === "string" ? globalThis.location.href : resolveImportMetaUrl();
160
+ const resolved = new URL(wasmUrl, base);
161
+ if (resolved.pathname.endsWith("_bg.wasm")) {
162
+ resolved.pathname = resolved.pathname.slice(0, -"_bg.wasm".length) + ".js";
163
+ } else if (resolved.pathname.endsWith(".wasm")) {
164
+ resolved.pathname = resolved.pathname.slice(0, -".wasm".length) + ".js";
165
+ } else {
166
+ throw new Error(
167
+ `Configured WASM URL must end in .wasm (received ${wasmUrl})`
168
+ );
169
+ }
170
+ resolved.search = "";
171
+ resolved.hash = "";
172
+ return resolved.href;
173
+ }
143
174
  async function loadBindings() {
144
175
  if (cachedBindings) {
145
176
  return cachedBindings;
@@ -149,7 +180,7 @@ async function loadBindings() {
149
180
  if (isNodeRuntime()) {
150
181
  loader = loadNodeBindings();
151
182
  } else if (configuredWasmUrl) {
152
- loader = loadWebBindings(configuredWasmUrl);
183
+ loader = loadWebBindings(configuredWasmUrl, configuredWasmModuleUrl);
153
184
  } else {
154
185
  loader = loadBundlerBindings();
155
186
  }
@@ -166,10 +197,15 @@ async function loadBindings() {
166
197
  }
167
198
  return bindingsPromise;
168
199
  }
169
- async function loadWebBindings(wasmUrl) {
170
- const moduleUrl = resolveModuleUrl(`${wasmDir}/web/abi_reflect_wasm.js`, resolveImportMetaUrl());
171
- const mod = await importModule(moduleUrl);
172
- await mod.default(wasmUrl);
200
+ async function loadWebBindings(wasmUrl, moduleUrlOverride) {
201
+ const moduleUrl = moduleUrlOverride ? resolveRuntimeUrl(moduleUrlOverride) : resolveConfiguredWasmModuleUrl(wasmUrl);
202
+ const imported = await importModule(moduleUrl);
203
+ const mod = unwrapImportedBindings(imported, moduleUrl);
204
+ const initializer = isObjectLike(imported) ? imported.default : void 0;
205
+ if (typeof initializer !== "function") {
206
+ throw new Error(`WASM web module is missing default initializer for ${moduleUrl}`);
207
+ }
208
+ await initializer({ module_or_path: resolveRuntimeUrl(wasmUrl) });
173
209
  return mod;
174
210
  }
175
211
  async function loadBundlerBindings() {
@@ -354,6 +390,117 @@ async function validateManifest(manifest) {
354
390
  return JSON.parse(result);
355
391
  }
356
392
 
393
+ // src/abi/nestedInstructionData.ts
394
+ var MAX_NESTED_INSTRUCTION_DEPTH = 15;
395
+ async function resolveNestedInstructionData(reflection, accountAddresses, decoder, options = {}) {
396
+ await resolveValue(
397
+ reflection.value,
398
+ 0,
399
+ accountAddresses,
400
+ decoder,
401
+ options.maxDepth ?? MAX_NESTED_INSTRUCTION_DEPTH
402
+ );
403
+ return reflection;
404
+ }
405
+ async function resolveValue(value, instructionDepth, accountAddresses, decoder, maxDepth) {
406
+ if (Array.isArray(value)) {
407
+ for (const item of value) {
408
+ await resolveValue(item, instructionDepth, accountAddresses, decoder, maxDepth);
409
+ }
410
+ return;
411
+ }
412
+ if (!isJsonObject(value)) return;
413
+ if (isInstructionDataValue(value)) {
414
+ await resolveInstructionDataValue(
415
+ value,
416
+ instructionDepth,
417
+ accountAddresses,
418
+ decoder,
419
+ maxDepth
420
+ );
421
+ return;
422
+ }
423
+ for (const [key, child] of Object.entries(value)) {
424
+ if (key === "decodedInstruction") continue;
425
+ await resolveValue(child, instructionDepth, accountAddresses, decoder, maxDepth);
426
+ }
427
+ }
428
+ async function resolveInstructionDataValue(value, instructionDepth, accountAddresses, decoder, maxDepth) {
429
+ delete value.decodeError;
430
+ delete value.decodedInstruction;
431
+ delete value.programAddress;
432
+ const programIndex = value.programIndex;
433
+ const dataHex = value.dataHex;
434
+ if (instructionDepth >= maxDepth) {
435
+ insertError(value, "Nested instruction depth limit reached");
436
+ return;
437
+ }
438
+ const programAddress = accountAddresses[programIndex];
439
+ if (!programAddress) {
440
+ insertError(value, `Invalid program index ${programIndex}`);
441
+ return;
442
+ }
443
+ value.programAddress = programAddress;
444
+ let data;
445
+ try {
446
+ data = parseHexBytes(dataHex);
447
+ } catch (err) {
448
+ insertError(value, `Nested instruction decode failed: ${errorMessage(err)}`);
449
+ return;
450
+ }
451
+ try {
452
+ const decoded = await decoder(programAddress, data);
453
+ if (!decoded) {
454
+ insertError(value, `ABI unavailable for program ${programAddress}`);
455
+ return;
456
+ }
457
+ await resolveValue(
458
+ decoded.value,
459
+ instructionDepth + 1,
460
+ accountAddresses,
461
+ decoder,
462
+ maxDepth
463
+ );
464
+ value.decodedInstruction = decoded;
465
+ } catch (err) {
466
+ insertError(value, `Nested instruction decode failed: ${errorMessage(err)}`);
467
+ }
468
+ }
469
+ function isInstructionDataValue(value) {
470
+ return value._pendingReflection === true && Number.isSafeInteger(value.programIndex) && value.programIndex >= 0 && typeof value.dataHex === "string";
471
+ }
472
+ function insertError(value, message) {
473
+ value.decodeError = message;
474
+ }
475
+ function parseHexBytes(value) {
476
+ const hex = value.startsWith("0x") || value.startsWith("0X") ? value.slice(2) : value;
477
+ if (hex.length % 2 !== 0) {
478
+ throw new Error("hex payload has an odd number of digits");
479
+ }
480
+ const bytes = new Uint8Array(hex.length / 2);
481
+ for (let idx = 0; idx < bytes.length; idx += 1) {
482
+ const high = decodeHexNibble(hex.charCodeAt(idx * 2));
483
+ const low = decodeHexNibble(hex.charCodeAt(idx * 2 + 1));
484
+ if (high === void 0 || low === void 0) {
485
+ throw new Error(`invalid hex payload at byte ${idx}`);
486
+ }
487
+ bytes[idx] = high << 4 | low;
488
+ }
489
+ return bytes;
490
+ }
491
+ function decodeHexNibble(value) {
492
+ if (value >= 48 && value <= 57) return value - 48;
493
+ if (value >= 97 && value <= 102) return value - 97 + 10;
494
+ if (value >= 65 && value <= 70) return value - 65 + 10;
495
+ return void 0;
496
+ }
497
+ function isJsonObject(value) {
498
+ return typeof value === "object" && value !== null && !Array.isArray(value);
499
+ }
500
+ function errorMessage(err) {
501
+ return err instanceof Error ? err.message : String(err);
502
+ }
503
+
357
504
  // src/abi/imports/types.ts
358
505
  var ResolutionError = class extends Error {
359
506
  constructor(code, message, details) {
@@ -920,6 +1067,7 @@ exports.ABI_ACCOUNT_HEADER_SIZE = ABI_ACCOUNT_HEADER_SIZE;
920
1067
  exports.ABI_STATE_FINALIZED = ABI_STATE_FINALIZED;
921
1068
  exports.ABI_STATE_OPEN = ABI_STATE_OPEN;
922
1069
  exports.DEFAULT_RPC_ENDPOINTS = DEFAULT_RPC_ENDPOINTS;
1070
+ exports.MAX_NESTED_INSTRUCTION_DEPTH = MAX_NESTED_INSTRUCTION_DEPTH;
923
1071
  exports.OnchainFetcher = OnchainFetcher;
924
1072
  exports.ResolutionError = ResolutionError;
925
1073
  exports.buildLayoutIr = buildLayoutIr;
@@ -940,6 +1088,7 @@ exports.reflectInstruction = reflectInstruction;
940
1088
  exports.reflectInstructionWithManifest = reflectInstructionWithManifest;
941
1089
  exports.reflectWithManifest = reflectWithManifest;
942
1090
  exports.resolveImports = resolveImports;
1091
+ exports.resolveNestedInstructionData = resolveNestedInstructionData;
943
1092
  exports.revisionMatches = revisionMatches;
944
1093
  exports.validateManifest = validateManifest;
945
1094
  //# sourceMappingURL=index.cjs.map