boing-sdk 0.3.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.
Files changed (186) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +191 -0
  3. package/dist/accessList.d.ts +22 -0
  4. package/dist/accessList.d.ts.map +1 -0
  5. package/dist/accessList.js +45 -0
  6. package/dist/bincode.d.ts +92 -0
  7. package/dist/bincode.d.ts.map +1 -0
  8. package/dist/bincode.js +154 -0
  9. package/dist/callAbi.d.ts +119 -0
  10. package/dist/callAbi.d.ts.map +1 -0
  11. package/dist/callAbi.js +156 -0
  12. package/dist/calldata.d.ts +35 -0
  13. package/dist/calldata.d.ts.map +1 -0
  14. package/dist/calldata.js +93 -0
  15. package/dist/canonicalDeployArtifacts.d.ts +154 -0
  16. package/dist/canonicalDeployArtifacts.d.ts.map +1 -0
  17. package/dist/canonicalDeployArtifacts.js +271 -0
  18. package/dist/canonicalTestnet.d.ts +15 -0
  19. package/dist/canonicalTestnet.d.ts.map +1 -0
  20. package/dist/canonicalTestnet.js +15 -0
  21. package/dist/canonicalTestnetDex.d.ts +17 -0
  22. package/dist/canonicalTestnetDex.d.ts.map +1 -0
  23. package/dist/canonicalTestnetDex.js +17 -0
  24. package/dist/chainIds.d.ts +18 -0
  25. package/dist/chainIds.d.ts.map +1 -0
  26. package/dist/chainIds.js +56 -0
  27. package/dist/client.d.ts +223 -0
  28. package/dist/client.d.ts.map +1 -0
  29. package/dist/client.js +659 -0
  30. package/dist/connectionMonitor.d.ts +47 -0
  31. package/dist/connectionMonitor.d.ts.map +1 -0
  32. package/dist/connectionMonitor.js +93 -0
  33. package/dist/create2.d.ts +94 -0
  34. package/dist/create2.d.ts.map +1 -0
  35. package/dist/create2.js +225 -0
  36. package/dist/dappDeploy.d.ts +100 -0
  37. package/dist/dappDeploy.d.ts.map +1 -0
  38. package/dist/dappDeploy.js +140 -0
  39. package/dist/dappUiHelpers.d.ts +28 -0
  40. package/dist/dappUiHelpers.d.ts.map +1 -0
  41. package/dist/dappUiHelpers.js +69 -0
  42. package/dist/defaultReferenceFungibleSecuredRuntimeBytecodeHex.d.ts +6 -0
  43. package/dist/defaultReferenceFungibleSecuredRuntimeBytecodeHex.d.ts.map +1 -0
  44. package/dist/defaultReferenceFungibleSecuredRuntimeBytecodeHex.js +5 -0
  45. package/dist/defaultReferenceFungibleSecuredTemplateBytecodeHex.d.ts +6 -0
  46. package/dist/defaultReferenceFungibleSecuredTemplateBytecodeHex.d.ts.map +1 -0
  47. package/dist/defaultReferenceFungibleSecuredTemplateBytecodeHex.js +5 -0
  48. package/dist/defaultReferenceFungibleTemplateBytecodeHex.d.ts +6 -0
  49. package/dist/defaultReferenceFungibleTemplateBytecodeHex.d.ts.map +1 -0
  50. package/dist/defaultReferenceFungibleTemplateBytecodeHex.js +5 -0
  51. package/dist/defaultReferenceNftCollectionTemplateBytecodeHex.d.ts +7 -0
  52. package/dist/defaultReferenceNftCollectionTemplateBytecodeHex.d.ts.map +1 -0
  53. package/dist/defaultReferenceNftCollectionTemplateBytecodeHex.js +6 -0
  54. package/dist/dexIntegration.d.ts +61 -0
  55. package/dist/dexIntegration.d.ts.map +1 -0
  56. package/dist/dexIntegration.js +193 -0
  57. package/dist/erc721Logs.d.ts +21 -0
  58. package/dist/erc721Logs.d.ts.map +1 -0
  59. package/dist/erc721Logs.js +69 -0
  60. package/dist/errors.d.ts +60 -0
  61. package/dist/errors.d.ts.map +1 -0
  62. package/dist/errors.js +153 -0
  63. package/dist/hex.d.ts +27 -0
  64. package/dist/hex.d.ts.map +1 -0
  65. package/dist/hex.js +82 -0
  66. package/dist/index.d.ts +83 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +78 -0
  69. package/dist/indexerBatch.d.ts +111 -0
  70. package/dist/indexerBatch.d.ts.map +1 -0
  71. package/dist/indexerBatch.js +253 -0
  72. package/dist/indexerGaps.d.ts +50 -0
  73. package/dist/indexerGaps.d.ts.map +1 -0
  74. package/dist/indexerGaps.js +117 -0
  75. package/dist/indexerSync.d.ts +61 -0
  76. package/dist/indexerSync.d.ts.map +1 -0
  77. package/dist/indexerSync.js +100 -0
  78. package/dist/nativeAmm.d.ts +64 -0
  79. package/dist/nativeAmm.d.ts.map +1 -0
  80. package/dist/nativeAmm.js +174 -0
  81. package/dist/nativeAmmLogs.d.ts +48 -0
  82. package/dist/nativeAmmLogs.d.ts.map +1 -0
  83. package/dist/nativeAmmLogs.js +114 -0
  84. package/dist/nativeAmmLpVault.d.ts +94 -0
  85. package/dist/nativeAmmLpVault.d.ts.map +1 -0
  86. package/dist/nativeAmmLpVault.js +205 -0
  87. package/dist/nativeAmmPool.d.ts +124 -0
  88. package/dist/nativeAmmPool.d.ts.map +1 -0
  89. package/dist/nativeAmmPool.js +245 -0
  90. package/dist/nativeContractSubmit.d.ts +26 -0
  91. package/dist/nativeContractSubmit.d.ts.map +1 -0
  92. package/dist/nativeContractSubmit.js +23 -0
  93. package/dist/nativeDexDirectory.d.ts +83 -0
  94. package/dist/nativeDexDirectory.d.ts.map +1 -0
  95. package/dist/nativeDexDirectory.js +147 -0
  96. package/dist/nativeDexDirectoryApi.d.ts +121 -0
  97. package/dist/nativeDexDirectoryApi.d.ts.map +1 -0
  98. package/dist/nativeDexDirectoryApi.js +408 -0
  99. package/dist/nativeDexFactory.d.ts +25 -0
  100. package/dist/nativeDexFactory.d.ts.map +1 -0
  101. package/dist/nativeDexFactory.js +72 -0
  102. package/dist/nativeDexFactoryLogs.d.ts +19 -0
  103. package/dist/nativeDexFactoryLogs.d.ts.map +1 -0
  104. package/dist/nativeDexFactoryLogs.js +61 -0
  105. package/dist/nativeDexFactoryPool.d.ts +61 -0
  106. package/dist/nativeDexFactoryPool.d.ts.map +1 -0
  107. package/dist/nativeDexFactoryPool.js +120 -0
  108. package/dist/nativeDexIndexerStats.d.ts +96 -0
  109. package/dist/nativeDexIndexerStats.d.ts.map +1 -0
  110. package/dist/nativeDexIndexerStats.js +448 -0
  111. package/dist/nativeDexLedgerRouter.d.ts +67 -0
  112. package/dist/nativeDexLedgerRouter.d.ts.map +1 -0
  113. package/dist/nativeDexLedgerRouter.js +108 -0
  114. package/dist/nativeDexLpPositions.d.ts +39 -0
  115. package/dist/nativeDexLpPositions.d.ts.map +1 -0
  116. package/dist/nativeDexLpPositions.js +69 -0
  117. package/dist/nativeDexNftIndexer.d.ts +26 -0
  118. package/dist/nativeDexNftIndexer.d.ts.map +1 -0
  119. package/dist/nativeDexNftIndexer.js +50 -0
  120. package/dist/nativeDexPoolHistory.d.ts +40 -0
  121. package/dist/nativeDexPoolHistory.d.ts.map +1 -0
  122. package/dist/nativeDexPoolHistory.js +110 -0
  123. package/dist/nativeDexReceiptArchive.d.ts +25 -0
  124. package/dist/nativeDexReceiptArchive.d.ts.map +1 -0
  125. package/dist/nativeDexReceiptArchive.js +47 -0
  126. package/dist/nativeDexRouting.d.ts +160 -0
  127. package/dist/nativeDexRouting.d.ts.map +1 -0
  128. package/dist/nativeDexRouting.js +345 -0
  129. package/dist/nativeDexSeamless.d.ts +86 -0
  130. package/dist/nativeDexSeamless.d.ts.map +1 -0
  131. package/dist/nativeDexSeamless.js +131 -0
  132. package/dist/nativeDexSwap2Router.d.ts +45 -0
  133. package/dist/nativeDexSwap2Router.d.ts.map +1 -0
  134. package/dist/nativeDexSwap2Router.js +276 -0
  135. package/dist/nativeLpShareToken.d.ts +54 -0
  136. package/dist/nativeLpShareToken.d.ts.map +1 -0
  137. package/dist/nativeLpShareToken.js +135 -0
  138. package/dist/nativeTokenSecurity.d.ts +59 -0
  139. package/dist/nativeTokenSecurity.d.ts.map +1 -0
  140. package/dist/nativeTokenSecurity.js +59 -0
  141. package/dist/networkProfile.d.ts +8 -0
  142. package/dist/networkProfile.d.ts.map +1 -0
  143. package/dist/networkProfile.js +29 -0
  144. package/dist/newHeadsWs.d.ts +43 -0
  145. package/dist/newHeadsWs.d.ts.map +1 -0
  146. package/dist/newHeadsWs.js +139 -0
  147. package/dist/preflightGate.d.ts +16 -0
  148. package/dist/preflightGate.d.ts.map +1 -0
  149. package/dist/preflightGate.js +29 -0
  150. package/dist/receiptLogs.d.ts +29 -0
  151. package/dist/receiptLogs.d.ts.map +1 -0
  152. package/dist/receiptLogs.js +66 -0
  153. package/dist/referenceFungibleSecuredDeployBytecode.d.ts +54 -0
  154. package/dist/referenceFungibleSecuredDeployBytecode.d.ts.map +1 -0
  155. package/dist/referenceFungibleSecuredDeployBytecode.js +274 -0
  156. package/dist/referenceNft.d.ts +14 -0
  157. package/dist/referenceNft.d.ts.map +1 -0
  158. package/dist/referenceNft.js +34 -0
  159. package/dist/referenceToken.d.ts +14 -0
  160. package/dist/referenceToken.d.ts.map +1 -0
  161. package/dist/referenceToken.js +29 -0
  162. package/dist/retryAfter.d.ts +6 -0
  163. package/dist/retryAfter.d.ts.map +1 -0
  164. package/dist/retryAfter.js +24 -0
  165. package/dist/rpcCapabilities.d.ts +43 -0
  166. package/dist/rpcCapabilities.d.ts.map +1 -0
  167. package/dist/rpcCapabilities.js +159 -0
  168. package/dist/rpcDoctor.d.ts +27 -0
  169. package/dist/rpcDoctor.d.ts.map +1 -0
  170. package/dist/rpcDoctor.js +66 -0
  171. package/dist/rpcSurfaceUi.d.ts +32 -0
  172. package/dist/rpcSurfaceUi.d.ts.map +1 -0
  173. package/dist/rpcSurfaceUi.js +49 -0
  174. package/dist/submitFlow.d.ts +70 -0
  175. package/dist/submitFlow.d.ts.map +1 -0
  176. package/dist/submitFlow.js +121 -0
  177. package/dist/transactionBuilder.d.ts +55 -0
  178. package/dist/transactionBuilder.d.ts.map +1 -0
  179. package/dist/transactionBuilder.js +100 -0
  180. package/dist/types.d.ts +436 -0
  181. package/dist/types.d.ts.map +1 -0
  182. package/dist/types.js +4 -0
  183. package/dist/walletProvider.d.ts +46 -0
  184. package/dist/walletProvider.d.ts.map +1 -0
  185. package/dist/walletProvider.js +126 -0
  186. package/package.json +44 -0
@@ -0,0 +1,66 @@
1
+ /**
2
+ * One-shot environment check: preflight HTTP discovery + capability probes + optional required methods.
3
+ */
4
+ import { explainBoingRpcError } from './errors.js';
5
+ import { explainBoingRpcProbeGaps, probeBoingRpcCapabilities } from './rpcCapabilities.js';
6
+ /**
7
+ * Run {@link BoingClient.preflightRpc}, {@link probeBoingRpcCapabilities}, and optional required-method checks.
8
+ * `messages` collects short strings suitable for logs or UI (includes `explainBoingRpcProbeGaps` when probes fail).
9
+ */
10
+ export async function doctorBoingRpcEnvironment(client, options) {
11
+ const preflight = await client.preflightRpc();
12
+ const capabilityProbe = await probeBoingRpcCapabilities(client);
13
+ const messages = [];
14
+ if (!preflight.httpLiveOk)
15
+ messages.push('GET /live did not return HTTP 200.');
16
+ if (!preflight.httpReadyOk)
17
+ messages.push('GET /ready did not return HTTP 200 (orchestrator may hold traffic).');
18
+ if (!preflight.jsonrpcBatchOk)
19
+ messages.push('JSON-RPC batch probe failed (expect current boing-node).');
20
+ if (!preflight.httpOpenApiJsonOk)
21
+ messages.push('GET /openapi.json missing or not OpenAPI JSON (upgrade boing-node for HTTP discovery).');
22
+ if (!preflight.wellKnownBoingRpcOk)
23
+ messages.push('GET /.well-known/boing-rpc missing (optional HTTP discovery).');
24
+ if (!preflight.httpLiveJsonOk)
25
+ messages.push('GET /live.json did not return { ok: true } (optional JSON probes).');
26
+ const probeExplain = explainBoingRpcProbeGaps(capabilityProbe);
27
+ if (probeExplain)
28
+ messages.push(probeExplain);
29
+ const supported = new Set(capabilityProbe.supportedMethods ?? []);
30
+ const required = options?.requiredMethods?.filter(Boolean) ?? [];
31
+ const missingRequiredMethods = required.filter((m) => !supported.has(m));
32
+ for (const m of missingRequiredMethods) {
33
+ messages.push(`Required RPC method not advertised: ${m}`);
34
+ }
35
+ const ok = preflight.httpLiveOk &&
36
+ preflight.httpReadyOk &&
37
+ preflight.jsonrpcBatchOk &&
38
+ missingRequiredMethods.length === 0 &&
39
+ probeExplain == null;
40
+ return {
41
+ ok,
42
+ preflight,
43
+ capabilityProbe,
44
+ missingRequiredMethods,
45
+ messages,
46
+ };
47
+ }
48
+ /** Format {@link BoingRpcDoctorResult} as a multi-line string for stdout. */
49
+ export function formatBoingRpcDoctorReport(result) {
50
+ const lines = [
51
+ `ok: ${result.ok}`,
52
+ `methods_supported: ${result.preflight.supportedMethodCount}`,
53
+ `http_openapi_json: ${result.preflight.httpOpenApiJsonOk}`,
54
+ `well_known: ${result.preflight.wellKnownBoingRpcOk}`,
55
+ `live_json: ${result.preflight.httpLiveJsonOk}`,
56
+ ];
57
+ if (result.messages.length > 0) {
58
+ lines.push('---');
59
+ lines.push(...result.messages);
60
+ }
61
+ return lines.join('\n');
62
+ }
63
+ /** Map arbitrary errors to a short doctor message (uses {@link explainBoingRpcError} for `BoingRpcError`). */
64
+ export function doctorErrorMessage(e) {
65
+ return explainBoingRpcError(e);
66
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * UI-oriented helpers from **`boing_health.rpc_surface`** / **`boing_getNetworkInfo.rpc_surface`**.
3
+ */
4
+ import type { BoingHealthRpcSurface } from './types.js';
5
+ /** Prefer **`networkInfo.rpc_surface`**, then **`health.rpc_surface`**. */
6
+ export declare function mergeRpcSurface(health: {
7
+ rpc_surface?: BoingHealthRpcSurface;
8
+ } | null, networkInfo: {
9
+ rpc_surface?: BoingHealthRpcSurface;
10
+ } | null): BoingHealthRpcSurface | null;
11
+ /**
12
+ * Clamp an inclusive block span to the node’s **`get_logs_max_block_range`** (inclusive pair length).
13
+ */
14
+ export declare function clampGetLogsBlockSpan(surface: BoingHealthRpcSurface | null | undefined, fromBlock: number, toBlock: number): {
15
+ fromBlock: number;
16
+ toBlock: number;
17
+ clamped: boolean;
18
+ };
19
+ /**
20
+ * Suggested minimum delay between steady-state read RPCs when HTTP JSON-RPC rate limiting is enabled (**RPS > 0**).
21
+ * Returns **`0`** when unlimited.
22
+ */
23
+ export declare function suggestedReadSpacingMs(surface: BoingHealthRpcSurface | null | undefined): number;
24
+ /**
25
+ * Short tooltip copy for logs cap (span and max rows).
26
+ */
27
+ export declare function describeGetLogsLimits(surface: BoingHealthRpcSurface | null | undefined): string;
28
+ /**
29
+ * Whether the node advertises a finite WebSocket subscriber cap (non-zero).
30
+ */
31
+ export declare function websocketHasConnectionCap(surface: BoingHealthRpcSurface | null | undefined): boolean;
32
+ //# sourceMappingURL=rpcSurfaceUi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpcSurfaceUi.d.ts","sourceRoot":"","sources":["../src/rpcSurfaceUi.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,2EAA2E;AAC3E,wBAAgB,eAAe,CAC7B,MAAM,EAAE;IAAE,WAAW,CAAC,EAAE,qBAAqB,CAAA;CAAE,GAAG,IAAI,EACtD,WAAW,EAAE;IAAE,WAAW,CAAC,EAAE,qBAAqB,CAAA;CAAE,GAAG,IAAI,GAC1D,qBAAqB,GAAG,IAAI,CAE9B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,EACjD,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAU1D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAIhG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAO/F;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAGpG"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * UI-oriented helpers from **`boing_health.rpc_surface`** / **`boing_getNetworkInfo.rpc_surface`**.
3
+ */
4
+ /** Prefer **`networkInfo.rpc_surface`**, then **`health.rpc_surface`**. */
5
+ export function mergeRpcSurface(health, networkInfo) {
6
+ return networkInfo?.rpc_surface ?? health?.rpc_surface ?? null;
7
+ }
8
+ /**
9
+ * Clamp an inclusive block span to the node’s **`get_logs_max_block_range`** (inclusive pair length).
10
+ */
11
+ export function clampGetLogsBlockSpan(surface, fromBlock, toBlock) {
12
+ const lo = Math.min(fromBlock, toBlock);
13
+ const hi = Math.max(fromBlock, toBlock);
14
+ const span = hi - lo;
15
+ const max = surface?.get_logs_max_block_range;
16
+ if (max == null || max <= 0 || span <= max) {
17
+ return { fromBlock: lo, toBlock: hi, clamped: false };
18
+ }
19
+ const newHi = lo + max;
20
+ return { fromBlock: lo, toBlock: newHi, clamped: true };
21
+ }
22
+ /**
23
+ * Suggested minimum delay between steady-state read RPCs when HTTP JSON-RPC rate limiting is enabled (**RPS > 0**).
24
+ * Returns **`0`** when unlimited.
25
+ */
26
+ export function suggestedReadSpacingMs(surface) {
27
+ const rps = surface?.http_rate_limit_requests_per_sec ?? 0;
28
+ if (rps <= 0)
29
+ return 0;
30
+ return Math.ceil(1000 / rps);
31
+ }
32
+ /**
33
+ * Short tooltip copy for logs cap (span and max rows).
34
+ */
35
+ export function describeGetLogsLimits(surface) {
36
+ if (surface == null) {
37
+ return 'Log query limits depend on the node; call boing_health for rpc_surface.';
38
+ }
39
+ const span = surface.get_logs_max_block_range;
40
+ const n = surface.get_logs_max_results;
41
+ return `This RPC allows up to ${span} blocks per query and up to ${n} log rows per response.`;
42
+ }
43
+ /**
44
+ * Whether the node advertises a finite WebSocket subscriber cap (non-zero).
45
+ */
46
+ export function websocketHasConnectionCap(surface) {
47
+ const n = surface?.websocket_max_connections ?? 0;
48
+ return n > 0;
49
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Simulate → refine access list → submit flows (roadmap P4).
3
+ */
4
+ import type { BoingClient } from './client.js';
5
+ import type { SimulateResult } from './types.js';
6
+ import { type Ed25519SecretKey32 } from './transactionBuilder.js';
7
+ /** Thrown when simulation fails and access-list widening cannot proceed (or retries exhausted). */
8
+ export declare class SimulationFailedError extends Error {
9
+ readonly simulation: SimulateResult;
10
+ readonly attempt: number;
11
+ constructor(message: string, simulation: SimulateResult, attempt: number);
12
+ }
13
+ export interface SubmitTransferWithSimulationOptions {
14
+ client: BoingClient;
15
+ secretKey32: Ed25519SecretKey32;
16
+ senderHex: string;
17
+ toHex: string;
18
+ amount: bigint;
19
+ /** Defaults to sender+to on both sides (matches parallel scheduling hint for transfers). */
20
+ accessList?: {
21
+ read: string[];
22
+ write: string[];
23
+ };
24
+ /** Default 6. */
25
+ maxSimulationRetries?: number;
26
+ }
27
+ export interface SubmitContractCallWithSimulationOptions {
28
+ client: BoingClient;
29
+ secretKey32: Ed25519SecretKey32;
30
+ senderHex: string;
31
+ contractHex: string;
32
+ calldata: Uint8Array;
33
+ /** Defaults to sender+contract on both sides. */
34
+ accessList?: {
35
+ read: string[];
36
+ write: string[];
37
+ };
38
+ maxSimulationRetries?: number;
39
+ }
40
+ export interface SubmitFlowResult {
41
+ tx_hash: string;
42
+ lastSimulation: SimulateResult;
43
+ attempts: number;
44
+ }
45
+ /**
46
+ * Sign a transfer, run `boing_simulateTransaction`, widen access lists when the node reports
47
+ * `access_list_covers_suggestion: false`, then `boing_submitTransaction` after a successful sim.
48
+ */
49
+ export declare function submitTransferWithSimulationRetry(opts: SubmitTransferWithSimulationOptions): Promise<SubmitFlowResult>;
50
+ /** Same pattern as transfer for `ContractCall` payloads. */
51
+ export declare function submitContractCallWithSimulationRetry(opts: SubmitContractCallWithSimulationOptions): Promise<SubmitFlowResult>;
52
+ /**
53
+ * Run `boing_qaCheck` (reject stops here), then sign → simulate → submit a purpose-bearing deploy.
54
+ * Mempool may still return `-32050` / `-32051` / pool caps — catch `BoingRpcError` on submit.
55
+ */
56
+ export declare function submitDeployWithPurposeFlow(opts: {
57
+ client: BoingClient;
58
+ secretKey32: Ed25519SecretKey32;
59
+ senderHex: string;
60
+ bytecode: Uint8Array;
61
+ purposeCategory: string;
62
+ descriptionHash?: Uint8Array | null;
63
+ create2Salt?: Uint8Array | null;
64
+ accessList?: {
65
+ read: string[];
66
+ write: string[];
67
+ };
68
+ maxSimulationRetries?: number;
69
+ }): Promise<SubmitFlowResult>;
70
+ //# sourceMappingURL=submitFlow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submitFlow.d.ts","sourceRoot":"","sources":["../src/submitFlow.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAML,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAEjC,mGAAmG;AACnG,qBAAa,qBAAsB,SAAQ,KAAK;aAG5B,UAAU,EAAE,cAAc;aAC1B,OAAO,EAAE,MAAM;gBAF/B,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,cAAc,EAC1B,OAAO,EAAE,MAAM;CAKlC;AAED,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACjD,iBAAiB;IACjB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,uCAAuC;IACtD,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,CAAC;IACrB,iDAAiD;IACjD,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACjD,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,mCAAmC,GACxC,OAAO,CAAC,gBAAgB,CAAC,CA0C3B;AAED,4DAA4D;AAC5D,wBAAsB,qCAAqC,CACzD,IAAI,EAAE,uCAAuC,GAC5C,OAAO,CAAC,gBAAgB,CAAC,CA0C3B;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAAC,IAAI,EAAE;IACtD,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,UAAU,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACjD,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0D5B"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Simulate → refine access list → submit flows (roadmap P4).
3
+ */
4
+ import { mergeAccessListWithSimulation } from './accessList.js';
5
+ import { BoingRpcError } from './errors.js';
6
+ import { bytesToHex } from './hex.js';
7
+ import { buildContractCallTransaction, buildDeployWithPurposeTransaction, buildTransferTransaction, fetchNextNonce, signTransactionInput, } from './transactionBuilder.js';
8
+ /** Thrown when simulation fails and access-list widening cannot proceed (or retries exhausted). */
9
+ export class SimulationFailedError extends Error {
10
+ constructor(message, simulation, attempt) {
11
+ super(message);
12
+ this.simulation = simulation;
13
+ this.attempt = attempt;
14
+ this.name = 'SimulationFailedError';
15
+ }
16
+ }
17
+ /**
18
+ * Sign a transfer, run `boing_simulateTransaction`, widen access lists when the node reports
19
+ * `access_list_covers_suggestion: false`, then `boing_submitTransaction` after a successful sim.
20
+ */
21
+ export async function submitTransferWithSimulationRetry(opts) {
22
+ const max = opts.maxSimulationRetries ?? 6;
23
+ let read = opts.accessList?.read ?? [opts.senderHex, opts.toHex];
24
+ let write = opts.accessList?.write ?? [opts.senderHex, opts.toHex];
25
+ const nonce = await fetchNextNonce(opts.client, opts.senderHex);
26
+ let lastSim = null;
27
+ for (let attempt = 0; attempt < max; attempt++) {
28
+ const tx = buildTransferTransaction({
29
+ nonce,
30
+ senderHex: opts.senderHex,
31
+ toHex: opts.toHex,
32
+ amount: opts.amount,
33
+ accessList: { read, write },
34
+ });
35
+ const signedHex = await signTransactionInput(tx, opts.secretKey32);
36
+ lastSim = await opts.client.simulateTransaction(signedHex);
37
+ if (lastSim.success) {
38
+ const sub = await opts.client.submitTransaction(signedHex);
39
+ return { tx_hash: sub.tx_hash, lastSimulation: lastSim, attempts: attempt + 1 };
40
+ }
41
+ if (lastSim.access_list_covers_suggestion === false && lastSim.suggested_access_list) {
42
+ const m = mergeAccessListWithSimulation(read, write, lastSim);
43
+ read = m.read;
44
+ write = m.write;
45
+ continue;
46
+ }
47
+ throw new SimulationFailedError(lastSim.error ?? 'Simulation failed', lastSim, attempt);
48
+ }
49
+ throw new SimulationFailedError(`Exceeded maxSimulationRetries (${max})`, lastSim, max - 1);
50
+ }
51
+ /** Same pattern as transfer for `ContractCall` payloads. */
52
+ export async function submitContractCallWithSimulationRetry(opts) {
53
+ const max = opts.maxSimulationRetries ?? 6;
54
+ let read = opts.accessList?.read ?? [opts.senderHex, opts.contractHex];
55
+ let write = opts.accessList?.write ?? [opts.senderHex, opts.contractHex];
56
+ const nonce = await fetchNextNonce(opts.client, opts.senderHex);
57
+ let lastSim = null;
58
+ for (let attempt = 0; attempt < max; attempt++) {
59
+ const tx = buildContractCallTransaction({
60
+ nonce,
61
+ senderHex: opts.senderHex,
62
+ contractHex: opts.contractHex,
63
+ calldata: opts.calldata,
64
+ accessList: { read, write },
65
+ });
66
+ const signedHex = await signTransactionInput(tx, opts.secretKey32);
67
+ lastSim = await opts.client.simulateTransaction(signedHex);
68
+ if (lastSim.success) {
69
+ const sub = await opts.client.submitTransaction(signedHex);
70
+ return { tx_hash: sub.tx_hash, lastSimulation: lastSim, attempts: attempt + 1 };
71
+ }
72
+ if (lastSim.access_list_covers_suggestion === false && lastSim.suggested_access_list) {
73
+ const m = mergeAccessListWithSimulation(read, write, lastSim);
74
+ read = m.read;
75
+ write = m.write;
76
+ continue;
77
+ }
78
+ throw new SimulationFailedError(lastSim.error ?? 'Simulation failed', lastSim, attempt);
79
+ }
80
+ throw new SimulationFailedError(`Exceeded maxSimulationRetries (${max})`, lastSim, max - 1);
81
+ }
82
+ /**
83
+ * Run `boing_qaCheck` (reject stops here), then sign → simulate → submit a purpose-bearing deploy.
84
+ * Mempool may still return `-32050` / `-32051` / pool caps — catch `BoingRpcError` on submit.
85
+ */
86
+ export async function submitDeployWithPurposeFlow(opts) {
87
+ const qa = await opts.client.qaCheck(bytesToHex(opts.bytecode), opts.purposeCategory, opts.descriptionHash ? bytesToHex(opts.descriptionHash) : undefined);
88
+ if (qa.result === 'reject') {
89
+ throw new BoingRpcError(-32050, qa.message ?? 'QA preflight rejected', { rule_id: qa.rule_id, message: qa.message }, 'boing_qaCheck');
90
+ }
91
+ const max = opts.maxSimulationRetries ?? 6;
92
+ let read = opts.accessList?.read ?? [opts.senderHex];
93
+ let write = opts.accessList?.write ?? [opts.senderHex];
94
+ const nonce = await fetchNextNonce(opts.client, opts.senderHex);
95
+ let lastSim = null;
96
+ for (let attempt = 0; attempt < max; attempt++) {
97
+ const tx = buildDeployWithPurposeTransaction({
98
+ nonce,
99
+ senderHex: opts.senderHex,
100
+ bytecode: opts.bytecode,
101
+ purposeCategory: opts.purposeCategory,
102
+ descriptionHash: opts.descriptionHash ?? null,
103
+ create2Salt: opts.create2Salt ?? null,
104
+ accessList: { read, write },
105
+ });
106
+ const signedHex = await signTransactionInput(tx, opts.secretKey32);
107
+ lastSim = await opts.client.simulateTransaction(signedHex);
108
+ if (lastSim.success) {
109
+ const sub = await opts.client.submitTransaction(signedHex);
110
+ return { tx_hash: sub.tx_hash, lastSimulation: lastSim, attempts: attempt + 1 };
111
+ }
112
+ if (lastSim.access_list_covers_suggestion === false && lastSim.suggested_access_list) {
113
+ const m = mergeAccessListWithSimulation(read, write, lastSim);
114
+ read = m.read;
115
+ write = m.write;
116
+ continue;
117
+ }
118
+ throw new SimulationFailedError(lastSim.error ?? 'Simulation failed', lastSim, attempt);
119
+ }
120
+ throw new SimulationFailedError(`Exceeded maxSimulationRetries (${max})`, lastSim, max - 1);
121
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * High-level transaction construction + Ed25519 signing (browser/Node).
3
+ * Produces hex `SignedTransaction` for `boing_submitTransaction`.
4
+ */
5
+ import type { BoingClient } from './client.js';
6
+ import { type TransactionInput } from './bincode.js';
7
+ /** 32-byte Ed25519 seed / secret key (same format as Rust `SigningKey::from_bytes`). */
8
+ export type Ed25519SecretKey32 = Uint8Array;
9
+ /** Derive Boing `AccountId` hex (0x + 64 hex) from a 32-byte Ed25519 secret seed. */
10
+ export declare function senderHexFromSecretKey(secretKey32: Ed25519SecretKey32): Promise<string>;
11
+ /** Next tx nonce from chain (`boing_getAccount`). */
12
+ export declare function fetchNextNonce(client: BoingClient, senderHex: string): Promise<bigint>;
13
+ export interface BuildTransferInput {
14
+ nonce: bigint;
15
+ /** 32-byte account hex (must match public key of signer). */
16
+ senderHex: string;
17
+ toHex: string;
18
+ amount: bigint;
19
+ accessList?: {
20
+ read: string[];
21
+ write: string[];
22
+ };
23
+ }
24
+ export declare function buildTransferTransaction(input: BuildTransferInput): TransactionInput;
25
+ export interface BuildContractCallInput {
26
+ nonce: bigint;
27
+ senderHex: string;
28
+ contractHex: string;
29
+ calldata: Uint8Array;
30
+ accessList?: {
31
+ read: string[];
32
+ write: string[];
33
+ };
34
+ }
35
+ export declare function buildContractCallTransaction(input: BuildContractCallInput): TransactionInput;
36
+ export interface BuildDeployWithPurposeInput {
37
+ nonce: bigint;
38
+ senderHex: string;
39
+ bytecode: Uint8Array;
40
+ purposeCategory: string;
41
+ descriptionHash?: Uint8Array | null;
42
+ create2Salt?: Uint8Array | null;
43
+ accessList?: {
44
+ read: string[];
45
+ write: string[];
46
+ };
47
+ }
48
+ export declare function buildDeployWithPurposeTransaction(input: BuildDeployWithPurposeInput): TransactionInput;
49
+ export declare function signTransactionInput(tx: TransactionInput, secretKey32: Ed25519SecretKey32): Promise<string>;
50
+ /**
51
+ * Sign with a custom async signer (e.g. hardware wallet or IPC to Boing Express).
52
+ * Caller must ensure the signer corresponds to `tx.sender`; no verification here.
53
+ */
54
+ export declare function signTransactionInputWithSigner(tx: TransactionInput, signHash: (hash32: Uint8Array) => Promise<Uint8Array>): Promise<string>;
55
+ //# sourceMappingURL=transactionBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactionBuilder.d.ts","sourceRoot":"","sources":["../src/transactionBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AAGtB,wFAAwF;AACxF,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAE5C,qFAAqF;AACrF,wBAAsB,sBAAsB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAI7F;AAED,qDAAqD;AACrD,wBAAsB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5F;AAMD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAClD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,gBAAgB,CAapF;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAClD;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,sBAAsB,GAAG,gBAAgB,CAa5F;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,UAAU,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAClD;AAED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,2BAA2B,GACjC,gBAAgB,CAelB;AAWD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,gBAAgB,EACpB,WAAW,EAAE,kBAAkB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED;;;GAGG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,gBAAgB,EACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,GACpD,OAAO,CAAC,MAAM,CAAC,CAKjB"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * High-level transaction construction + Ed25519 signing (browser/Node).
3
+ * Produces hex `SignedTransaction` for `boing_submitTransaction`.
4
+ */
5
+ import * as ed25519 from '@noble/ed25519';
6
+ import { encodeSignedTransaction, signableTransactionHash, } from './bincode.js';
7
+ import { bytesToHex, hexToAccountId, validateHex32 } from './hex.js';
8
+ /** Derive Boing `AccountId` hex (0x + 64 hex) from a 32-byte Ed25519 secret seed. */
9
+ export async function senderHexFromSecretKey(secretKey32) {
10
+ if (secretKey32.length !== 32)
11
+ throw new Error('secret key must be 32 bytes');
12
+ const pub = await ed25519.getPublicKeyAsync(secretKey32);
13
+ return validateHex32(bytesToHex(pub));
14
+ }
15
+ /** Next tx nonce from chain (`boing_getAccount`). */
16
+ export async function fetchNextNonce(client, senderHex) {
17
+ const acc = await client.getAccount(validateHex32(senderHex));
18
+ return BigInt(acc.nonce);
19
+ }
20
+ function accountVec(hexList) {
21
+ return hexList.map((h) => hexToAccountId(validateHex32(h)));
22
+ }
23
+ export function buildTransferTransaction(input) {
24
+ const read = input.accessList?.read ?? [];
25
+ const write = input.accessList?.write ?? [];
26
+ return {
27
+ nonce: input.nonce,
28
+ sender: hexToAccountId(validateHex32(input.senderHex)),
29
+ payload: {
30
+ kind: 'transfer',
31
+ to: hexToAccountId(validateHex32(input.toHex)),
32
+ amount: input.amount,
33
+ },
34
+ accessList: { read: accountVec(read), write: accountVec(write) },
35
+ };
36
+ }
37
+ export function buildContractCallTransaction(input) {
38
+ const read = input.accessList?.read ?? [];
39
+ const write = input.accessList?.write ?? [];
40
+ return {
41
+ nonce: input.nonce,
42
+ sender: hexToAccountId(validateHex32(input.senderHex)),
43
+ payload: {
44
+ kind: 'contractCall',
45
+ contract: hexToAccountId(validateHex32(input.contractHex)),
46
+ calldata: input.calldata,
47
+ },
48
+ accessList: { read: accountVec(read), write: accountVec(write) },
49
+ };
50
+ }
51
+ export function buildDeployWithPurposeTransaction(input) {
52
+ const read = input.accessList?.read ?? [];
53
+ const write = input.accessList?.write ?? [];
54
+ return {
55
+ nonce: input.nonce,
56
+ sender: hexToAccountId(validateHex32(input.senderHex)),
57
+ payload: {
58
+ kind: 'contractDeployWithPurpose',
59
+ bytecode: input.bytecode,
60
+ purposeCategory: input.purposeCategory,
61
+ descriptionHash: input.descriptionHash ?? null,
62
+ create2Salt: input.create2Salt ?? null,
63
+ },
64
+ accessList: { read: accountVec(read), write: accountVec(write) },
65
+ };
66
+ }
67
+ /**
68
+ * Sign the Boing signable hash with Ed25519 and return bincode `SignedTransaction` as 0x-hex.
69
+ */
70
+ function bytesEqual(a, b) {
71
+ if (a.length !== b.length)
72
+ return false;
73
+ for (let i = 0; i < a.length; i++)
74
+ if (a[i] !== b[i])
75
+ return false;
76
+ return true;
77
+ }
78
+ export async function signTransactionInput(tx, secretKey32) {
79
+ if (secretKey32.length !== 32)
80
+ throw new Error('secret key must be 32 bytes');
81
+ const pub = await ed25519.getPublicKeyAsync(secretKey32);
82
+ if (!bytesEqual(pub, tx.sender)) {
83
+ throw new Error('tx.sender must equal the Ed25519 public key derived from the secret key');
84
+ }
85
+ const hash = signableTransactionHash(tx);
86
+ const sig = await ed25519.signAsync(hash, secretKey32);
87
+ const raw = encodeSignedTransaction(tx, sig);
88
+ return bytesToHex(raw);
89
+ }
90
+ /**
91
+ * Sign with a custom async signer (e.g. hardware wallet or IPC to Boing Express).
92
+ * Caller must ensure the signer corresponds to `tx.sender`; no verification here.
93
+ */
94
+ export async function signTransactionInputWithSigner(tx, signHash) {
95
+ const hash = signableTransactionHash(tx);
96
+ const sig = await signHash(hash);
97
+ if (sig.length !== 64)
98
+ throw new Error('Ed25519 signature must be 64 bytes');
99
+ return bytesToHex(encodeSignedTransaction(tx, sig));
100
+ }