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,50 @@
1
+ /**
2
+ * Merge pruned / missing height ranges and compute safe contiguous cursor advancement.
3
+ * Pair with {@link summarizeIndexerFetchGaps} and `onMissingBlock: 'omit'` fetches.
4
+ */
5
+ import type { IndexerFetchGapSummary } from './indexerBatch.js';
6
+ /** Inclusive block height range (same shape as {@link IndexerFetchGapSummary.missingHeightRangesInclusive}). */
7
+ export interface InclusiveHeightRange {
8
+ fromHeight: number;
9
+ toHeight: number;
10
+ }
11
+ /**
12
+ * Sort and merge overlapping or adjacent inclusive ranges into a minimal cover.
13
+ */
14
+ export declare function mergeInclusiveHeightRanges(ranges: readonly InclusiveHeightRange[]): InclusiveHeightRange[];
15
+ /** Union of two range lists (merge + normalize). */
16
+ export declare function unionInclusiveHeightRanges(a: readonly InclusiveHeightRange[], b: readonly InclusiveHeightRange[]): InclusiveHeightRange[];
17
+ /**
18
+ * Remove heights **`indexed`** from each stored gap (e.g. after archive backfill). Input gaps are normalized
19
+ * (merged) first; the result is merged again so adjacent remnants stay minimal.
20
+ */
21
+ export declare function subtractInclusiveRangeFromRanges(indexed: InclusiveHeightRange, gaps: readonly InclusiveHeightRange[]): InclusiveHeightRange[];
22
+ /** One row matching **`tools/observer-indexer-schema.sql`** → **`block_height_gaps`**. */
23
+ export interface BlockHeightGapInsertRow {
24
+ chain_id: string;
25
+ from_height: number;
26
+ to_height: number;
27
+ reason: string;
28
+ recorded_at: number;
29
+ }
30
+ /**
31
+ * Normalized **`block_height_gaps`** rows for parameterized INSERT (one row per merged contiguous run).
32
+ */
33
+ export declare function blockHeightGapRowsForInsert(input: {
34
+ chainId: string;
35
+ ranges: readonly InclusiveHeightRange[];
36
+ reason?: string;
37
+ recordedAtSec?: number;
38
+ }): BlockHeightGapInsertRow[];
39
+ /**
40
+ * After fetching `[lastIndexedHeight + 1, …]` with omissions, highest height that remains **contiguous**
41
+ * from `lastIndexedHeight` (i.e. you may set `ingest_cursor.last_committed_height` here without holes).
42
+ *
43
+ * - Full success (no omissions): `requestedToHeight`.
44
+ * - Gap at the start of the tick: `lastIndexedHeight` (no forward progress on the contiguous cursor).
45
+ * - Gap in the middle/end: `lastContiguousFromStart` from the summary (may be below `requestedToHeight`).
46
+ *
47
+ * @throws if `summary.requestedFromHeight !== lastIndexedHeight + 1`
48
+ */
49
+ export declare function nextContiguousIndexedHeightAfterOmittedFetch(lastIndexedHeight: number, summary: IndexerFetchGapSummary): number;
50
+ //# sourceMappingURL=indexerGaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexerGaps.d.ts","sourceRoot":"","sources":["../src/indexerGaps.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,gHAAgH;AAChH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAcD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,oBAAoB,EAAE,GAAG,oBAAoB,EAAE,CAmB1G;AAED,oDAAoD;AACpD,wBAAgB,0BAA0B,CACxC,CAAC,EAAE,SAAS,oBAAoB,EAAE,EAClC,CAAC,EAAE,SAAS,oBAAoB,EAAE,GACjC,oBAAoB,EAAE,CAExB;AAgBD;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,SAAS,oBAAoB,EAAE,GACpC,oBAAoB,EAAE,CASxB;AAED,0FAA0F;AAC1F,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,uBAAuB,EAAE,CAW5B;AAOD;;;;;;;;;GASG;AACH,wBAAgB,4CAA4C,CAC1D,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,sBAAsB,GAC9B,MAAM,CAeR"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Merge pruned / missing height ranges and compute safe contiguous cursor advancement.
3
+ * Pair with {@link summarizeIndexerFetchGaps} and `onMissingBlock: 'omit'` fetches.
4
+ */
5
+ function assertInclusiveRange(r, label) {
6
+ if (!Number.isInteger(r.fromHeight) || !Number.isInteger(r.toHeight)) {
7
+ throw new TypeError(`${label}: fromHeight and toHeight must be integers`);
8
+ }
9
+ if (r.fromHeight < 0 || r.toHeight < 0) {
10
+ throw new RangeError(`${label}: heights must be >= 0`);
11
+ }
12
+ if (r.fromHeight > r.toHeight) {
13
+ throw new RangeError(`${label}: fromHeight must be <= toHeight`);
14
+ }
15
+ }
16
+ /**
17
+ * Sort and merge overlapping or adjacent inclusive ranges into a minimal cover.
18
+ */
19
+ export function mergeInclusiveHeightRanges(ranges) {
20
+ if (ranges.length === 0)
21
+ return [];
22
+ for (let i = 0; i < ranges.length; i++) {
23
+ assertInclusiveRange(ranges[i], `ranges[${i}]`);
24
+ }
25
+ const sorted = [...ranges].sort((a, b) => a.fromHeight - b.fromHeight);
26
+ const out = [];
27
+ let cur = { ...sorted[0] };
28
+ for (let i = 1; i < sorted.length; i++) {
29
+ const r = sorted[i];
30
+ if (r.fromHeight > cur.toHeight + 1) {
31
+ out.push(cur);
32
+ cur = { ...r };
33
+ }
34
+ else {
35
+ cur.toHeight = Math.max(cur.toHeight, r.toHeight);
36
+ }
37
+ }
38
+ out.push(cur);
39
+ return out;
40
+ }
41
+ /** Union of two range lists (merge + normalize). */
42
+ export function unionInclusiveHeightRanges(a, b) {
43
+ return mergeInclusiveHeightRanges([...a, ...b]);
44
+ }
45
+ function subtractOneGapByIndexedRange(indexed, gap) {
46
+ if (indexed.toHeight < gap.fromHeight || indexed.fromHeight > gap.toHeight) {
47
+ return [{ ...gap }];
48
+ }
49
+ const out = [];
50
+ if (gap.fromHeight < indexed.fromHeight) {
51
+ out.push({ fromHeight: gap.fromHeight, toHeight: indexed.fromHeight - 1 });
52
+ }
53
+ if (indexed.toHeight < gap.toHeight) {
54
+ out.push({ fromHeight: indexed.toHeight + 1, toHeight: gap.toHeight });
55
+ }
56
+ return out;
57
+ }
58
+ /**
59
+ * Remove heights **`indexed`** from each stored gap (e.g. after archive backfill). Input gaps are normalized
60
+ * (merged) first; the result is merged again so adjacent remnants stay minimal.
61
+ */
62
+ export function subtractInclusiveRangeFromRanges(indexed, gaps) {
63
+ assertInclusiveRange(indexed, 'indexed');
64
+ if (gaps.length === 0)
65
+ return [];
66
+ const normalized = mergeInclusiveHeightRanges(gaps);
67
+ const pieces = [];
68
+ for (const g of normalized) {
69
+ pieces.push(...subtractOneGapByIndexedRange(indexed, g));
70
+ }
71
+ return mergeInclusiveHeightRanges(pieces);
72
+ }
73
+ /**
74
+ * Normalized **`block_height_gaps`** rows for parameterized INSERT (one row per merged contiguous run).
75
+ */
76
+ export function blockHeightGapRowsForInsert(input) {
77
+ const reason = input.reason ?? 'pruned';
78
+ const recorded_at = input.recordedAtSec ?? Math.floor(Date.now() / 1000);
79
+ const merged = mergeInclusiveHeightRanges(input.ranges);
80
+ return merged.map((r) => ({
81
+ chain_id: input.chainId,
82
+ from_height: r.fromHeight,
83
+ to_height: r.toHeight,
84
+ reason,
85
+ recorded_at,
86
+ }));
87
+ }
88
+ function assertIndexerCursor(name, h) {
89
+ if (!Number.isInteger(h))
90
+ throw new TypeError(`${name} must be an integer`);
91
+ if (h < -1)
92
+ throw new RangeError(`${name} must be >= -1`);
93
+ }
94
+ /**
95
+ * After fetching `[lastIndexedHeight + 1, …]` with omissions, highest height that remains **contiguous**
96
+ * from `lastIndexedHeight` (i.e. you may set `ingest_cursor.last_committed_height` here without holes).
97
+ *
98
+ * - Full success (no omissions): `requestedToHeight`.
99
+ * - Gap at the start of the tick: `lastIndexedHeight` (no forward progress on the contiguous cursor).
100
+ * - Gap in the middle/end: `lastContiguousFromStart` from the summary (may be below `requestedToHeight`).
101
+ *
102
+ * @throws if `summary.requestedFromHeight !== lastIndexedHeight + 1`
103
+ */
104
+ export function nextContiguousIndexedHeightAfterOmittedFetch(lastIndexedHeight, summary) {
105
+ assertIndexerCursor('lastIndexedHeight', lastIndexedHeight);
106
+ const next = lastIndexedHeight + 1;
107
+ if (summary.requestedFromHeight !== next) {
108
+ throw new RangeError(`summary.requestedFromHeight (${summary.requestedFromHeight}) must equal lastIndexedHeight + 1 (${next})`);
109
+ }
110
+ if (summary.omittedHeights.length === 0) {
111
+ return summary.requestedToHeight;
112
+ }
113
+ if (summary.lastContiguousFromStart === null) {
114
+ return lastIndexedHeight;
115
+ }
116
+ return summary.lastContiguousFromStart;
117
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Finality / tip helpers for indexers using `boing_getSyncState`.
3
+ * See `docs/RPC-API-SPEC.md` — today `head_height` and `finalized_height` match; they may diverge later.
4
+ */
5
+ import type { BoingClient } from './client.js';
6
+ export interface IndexerChainTips {
7
+ headHeight: number;
8
+ finalizedHeight: number;
9
+ /**
10
+ * Inclusive upper bound for **durable** indexing: min(head, finalized).
11
+ * Prefer indexing only through this height until the node exposes lagging finalized semantics.
12
+ */
13
+ durableIndexThrough: number;
14
+ /** Tip block hash (32-byte hex). */
15
+ latestBlockHash: string;
16
+ }
17
+ /**
18
+ * Read committed tip + finalized fields from the node (single RPC).
19
+ */
20
+ export declare function getIndexerChainTips(client: BoingClient): Promise<IndexerChainTips>;
21
+ /**
22
+ * Clamp an inclusive `[fromHeight, toHeight]` so `toHeight` does not exceed `durableIndexThrough`.
23
+ * Returns `null` if the range is empty after clamping or if `fromHeight > toHeight`.
24
+ */
25
+ export declare function clampIndexerHeightRange(fromHeight: number, toHeight: number, durableIndexThrough: number): {
26
+ fromHeight: number;
27
+ toHeight: number;
28
+ } | null;
29
+ /** How {@link planIndexerChainTipsWithFallback} obtained {@link IndexerChainTips}. */
30
+ export type IndexerTipsSource = 'sync_state' | 'chain_height';
31
+ export interface PlanIndexerCatchUpOptions {
32
+ /**
33
+ * Cap one tick to at most this many block heights (inclusive count).
34
+ * When unset, the planned range runs through the clamped durable tip.
35
+ */
36
+ maxBlocksPerTick?: number;
37
+ }
38
+ /** Result of {@link planIndexerCatchUp}: durable range `[fromHeight, toHeight]` to fetch next. */
39
+ export interface IndexerCatchUpPlan {
40
+ tips: IndexerChainTips;
41
+ tipsSource: IndexerTipsSource;
42
+ fromHeight: number;
43
+ toHeight: number;
44
+ }
45
+ /**
46
+ * Like {@link getIndexerChainTips}, but when **`boing_getSyncState`** returns **-32601**,
47
+ * builds tips from **`boing_chainHeight`** + **`boing_getBlockByHeight(tip, false)`** (needs block **`hash`**).
48
+ */
49
+ export declare function planIndexerChainTipsWithFallback(client: BoingClient): Promise<{
50
+ tips: IndexerChainTips;
51
+ tipsSource: IndexerTipsSource;
52
+ }>;
53
+ /**
54
+ * One ingestion tick: load chain tips (with **`getSyncState`** fallback), then
55
+ * **`clampIndexerHeightRange(lastIndexedHeight + 1, headHeight, durableIndexThrough)`**.
56
+ * Returns **`null`** when there is nothing to index yet.
57
+ *
58
+ * @param lastIndexedHeight — height you have fully persisted (**`-1`** before genesis).
59
+ */
60
+ export declare function planIndexerCatchUp(client: BoingClient, lastIndexedHeight: number, options?: PlanIndexerCatchUpOptions): Promise<IndexerCatchUpPlan | null>;
61
+ //# sourceMappingURL=indexerSync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexerSync.d.ts","sourceRoot":"","sources":["../src/indexerSync.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oCAAoC;IACpC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAUxF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,GAC1B;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAQjD;AAYD,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,cAAc,CAAC;AAE9D,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,kGAAkG;AAClG,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,UAAU,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAsBpE;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,WAAW,EACnB,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAoBpC"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Finality / tip helpers for indexers using `boing_getSyncState`.
3
+ * See `docs/RPC-API-SPEC.md` — today `head_height` and `finalized_height` match; they may diverge later.
4
+ */
5
+ import { isBoingRpcMethodNotFound } from './errors.js';
6
+ /**
7
+ * Read committed tip + finalized fields from the node (single RPC).
8
+ */
9
+ export async function getIndexerChainTips(client) {
10
+ const s = await client.getSyncState();
11
+ const headHeight = s.head_height;
12
+ const finalizedHeight = s.finalized_height;
13
+ return {
14
+ headHeight,
15
+ finalizedHeight,
16
+ durableIndexThrough: Math.min(headHeight, finalizedHeight),
17
+ latestBlockHash: s.latest_block_hash,
18
+ };
19
+ }
20
+ /**
21
+ * Clamp an inclusive `[fromHeight, toHeight]` so `toHeight` does not exceed `durableIndexThrough`.
22
+ * Returns `null` if the range is empty after clamping or if `fromHeight > toHeight`.
23
+ */
24
+ export function clampIndexerHeightRange(fromHeight, toHeight, durableIndexThrough) {
25
+ assertNonNegInt('fromHeight', fromHeight);
26
+ assertNonNegInt('toHeight', toHeight);
27
+ assertNonNegInt('durableIndexThrough', durableIndexThrough);
28
+ if (fromHeight > toHeight)
29
+ return null;
30
+ const cappedTo = Math.min(toHeight, durableIndexThrough);
31
+ if (fromHeight > cappedTo)
32
+ return null;
33
+ return { fromHeight, toHeight: cappedTo };
34
+ }
35
+ function assertNonNegInt(name, h) {
36
+ if (!Number.isInteger(h))
37
+ throw new TypeError(`${name} must be an integer`);
38
+ if (h < 0)
39
+ throw new RangeError(`${name} must be >= 0`);
40
+ }
41
+ function assertIndexerCursor(name, h) {
42
+ if (!Number.isInteger(h))
43
+ throw new TypeError(`${name} must be an integer`);
44
+ if (h < -1)
45
+ throw new RangeError(`${name} must be >= -1 (use -1 before genesis)`);
46
+ }
47
+ /**
48
+ * Like {@link getIndexerChainTips}, but when **`boing_getSyncState`** returns **-32601**,
49
+ * builds tips from **`boing_chainHeight`** + **`boing_getBlockByHeight(tip, false)`** (needs block **`hash`**).
50
+ */
51
+ export async function planIndexerChainTipsWithFallback(client) {
52
+ try {
53
+ const tips = await getIndexerChainTips(client);
54
+ return { tips, tipsSource: 'sync_state' };
55
+ }
56
+ catch (e) {
57
+ if (!isBoingRpcMethodNotFound(e))
58
+ throw e;
59
+ const height = await client.chainHeight();
60
+ const head = await client.getBlockByHeight(height, false);
61
+ const hash = head?.hash;
62
+ if (hash == null || !/^0x[0-9a-f]{64}$/i.test(hash)) {
63
+ throw new Error('Indexer fallback: boing_getSyncState missing and tip block has no hash — use a current boing-node RPC');
64
+ }
65
+ const tips = {
66
+ headHeight: height,
67
+ finalizedHeight: height,
68
+ durableIndexThrough: height,
69
+ latestBlockHash: hash,
70
+ };
71
+ return { tips, tipsSource: 'chain_height' };
72
+ }
73
+ }
74
+ /**
75
+ * One ingestion tick: load chain tips (with **`getSyncState`** fallback), then
76
+ * **`clampIndexerHeightRange(lastIndexedHeight + 1, headHeight, durableIndexThrough)`**.
77
+ * Returns **`null`** when there is nothing to index yet.
78
+ *
79
+ * @param lastIndexedHeight — height you have fully persisted (**`-1`** before genesis).
80
+ */
81
+ export async function planIndexerCatchUp(client, lastIndexedHeight, options) {
82
+ assertIndexerCursor('lastIndexedHeight', lastIndexedHeight);
83
+ const { tips, tipsSource } = await planIndexerChainTipsWithFallback(client);
84
+ const nextFrom = lastIndexedHeight + 1;
85
+ const clamped = clampIndexerHeightRange(nextFrom, tips.headHeight, tips.durableIndexThrough);
86
+ if (clamped == null)
87
+ return null;
88
+ let { fromHeight, toHeight } = clamped;
89
+ const cap = options?.maxBlocksPerTick;
90
+ if (cap != null) {
91
+ if (!Number.isInteger(cap) || cap < 1) {
92
+ throw new RangeError('maxBlocksPerTick must be an integer >= 1');
93
+ }
94
+ const span = toHeight - fromHeight + 1;
95
+ if (span > cap) {
96
+ toHeight = fromHeight + cap - 1;
97
+ }
98
+ }
99
+ return { tips, tipsSource, fromHeight, toHeight };
100
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Native constant-product pool calldata (Boing VM). See `docs/NATIVE-AMM-CALLDATA.md`.
3
+ * Reserves and amounts should stay ≤ `Number.MAX_SAFE_INTEGER` / u64 range for VM `Mul` parity.
4
+ */
5
+ /** `swap` selector (low byte of word0). */
6
+ export declare const SELECTOR_NATIVE_AMM_SWAP = 16;
7
+ /** `add_liquidity` selector. */
8
+ export declare const SELECTOR_NATIVE_AMM_ADD_LIQUIDITY = 17;
9
+ /** `remove_liquidity` selector (LP burn + pro-rata withdrawal). */
10
+ export declare const SELECTOR_NATIVE_AMM_REMOVE_LIQUIDITY = 18;
11
+ /** **v2 pool:** one-time `set_tokens(token_a, token_b)`. */
12
+ export declare const SELECTOR_NATIVE_AMM_SET_TOKENS = 19;
13
+ /** **v3/v4 pool:** `set_swap_fee_bps(fee)` — **64-byte** calldata; only when **total LP == 0**; **`1 ≤ fee ≤ 10_000`**. */
14
+ export declare const SELECTOR_NATIVE_AMM_SET_SWAP_FEE_BPS = 20;
15
+ /** **v5 pool:** `swap_to` — like `swap` plus **word4** = output recipient (**160-byte** calldata). */
16
+ export declare const SELECTOR_NATIVE_AMM_SWAP_TO = 21;
17
+ /** **v5 pool:** `remove_liquidity_to` — like `remove_liquidity` plus **recipient_a** / **recipient_b** (**192-byte** calldata). */
18
+ export declare const SELECTOR_NATIVE_AMM_REMOVE_LIQUIDITY_TO = 22;
19
+ /** Swap fee in basis points on **output** (matches `native_amm::NATIVE_CP_SWAP_FEE_BPS`). */
20
+ export declare const NATIVE_CP_SWAP_FEE_BPS = 30;
21
+ /** Build 32-byte `Log2` **topic0** (UTF-8 ASCII + zero pad), matching `native_amm` constants. */
22
+ export declare function nativeAmmLogTopic0Utf8(ascii: string): Uint8Array;
23
+ /** `Log2` topic0 hex for a successful **`swap`** (see `NATIVE-AMM-CALLDATA.md` § Logs). */
24
+ export declare const NATIVE_AMM_TOPIC_SWAP_HEX: string;
25
+ /** `Log2` topic0 hex for **`add_liquidity`**. */
26
+ export declare const NATIVE_AMM_TOPIC_ADD_LIQUIDITY_HEX: string;
27
+ /** `Log2` topic0 hex for **`remove_liquidity`**. */
28
+ export declare const NATIVE_AMM_TOPIC_REMOVE_LIQUIDITY_HEX: string;
29
+ /** 128-byte `swap` calldata: direction 0 = A→B, 1 = B→A. */
30
+ export declare function encodeNativeAmmSwapCalldata(direction: bigint, amountIn: bigint, minOut: bigint): Uint8Array;
31
+ /** **160-byte** `swap_to` calldata (v5 pool): explicit **output recipient** for token `transfer`. */
32
+ export declare function encodeNativeAmmSwapToCalldata(direction: bigint, amountIn: bigint, minOut: bigint, recipientHex32: string): Uint8Array;
33
+ /**
34
+ * 128-byte `add_liquidity` calldata. On success the pool **returns** **32** bytes: LP minted in this
35
+ * call as **u128** in the **low 16 bytes** of the word (big-endian word; value in bytes 16..32).
36
+ */
37
+ export declare function encodeNativeAmmAddLiquidityCalldata(amountA: bigint, amountB: bigint, minLiquidity: bigint): Uint8Array;
38
+ /** 128-byte `remove_liquidity` calldata. */
39
+ export declare function encodeNativeAmmRemoveLiquidityCalldata(liquidityBurn: bigint, minA: bigint, minB: bigint): Uint8Array;
40
+ /** **192-byte** `remove_liquidity_to` (v5 pool): explicit **recipient_a** / **recipient_b** for reference-token `transfer`. */
41
+ export declare function encodeNativeAmmRemoveLiquidityToCalldata(liquidityBurn: bigint, minA: bigint, minB: bigint, recipientAHex32: string, recipientBHex32: string): Uint8Array;
42
+ /** **v2:** 96-byte `set_tokens` — each id is 32-byte account hex (`0x` + 64 hex). Use `0x` + 64 zeros for “no token” on that side. */
43
+ export declare function encodeNativeAmmSetTokensCalldata(tokenAHex32: string, tokenBHex32: string): Uint8Array;
44
+ /** **v3/v4:** 64-byte `set_swap_fee_bps` calldata (`native_amm::encode_set_swap_fee_bps_calldata`). */
45
+ export declare function encodeNativeAmmSetSwapFeeBpsCalldata(feeBps: bigint): Uint8Array;
46
+ export declare function encodeNativeAmmSwapCalldataHex(direction: bigint, amountIn: bigint, minOut: bigint): string;
47
+ export declare function encodeNativeAmmSwapToCalldataHex(direction: bigint, amountIn: bigint, minOut: bigint, recipientHex32: string): string;
48
+ export declare function encodeNativeAmmAddLiquidityCalldataHex(amountA: bigint, amountB: bigint, minLiquidity?: bigint): string;
49
+ export declare function encodeNativeAmmRemoveLiquidityCalldataHex(liquidityBurn: bigint, minA: bigint, minB: bigint): string;
50
+ export declare function encodeNativeAmmRemoveLiquidityToCalldataHex(liquidityBurn: bigint, minA: bigint, minB: bigint, recipientAHex32: string, recipientBHex32: string): string;
51
+ export declare function encodeNativeAmmSetTokensCalldataHex(tokenAHex32: string, tokenBHex32: string): string;
52
+ export declare function encodeNativeAmmSetSwapFeeBpsCalldataHex(feeBps: bigint): string;
53
+ /** Raw CP step (no swap fee): Δout = ⌊ r_out · Δin / (r_in + Δin) ⌋. */
54
+ export declare function constantProductAmountOutNoFee(reserveIn: bigint, reserveOut: bigint, amountIn: bigint): bigint;
55
+ /**
56
+ * Amount out after an explicit **output-side** fee in basis points (`native_amm::constant_product_amount_out_after_fee_with_bps`).
57
+ * **`feeBps`** must be **`0`…`10000`** (inclusive). For **v3/v4** pools, if storage at `swap_fee_bps_key` reads **`0`**, treat as **`NATIVE_CP_SWAP_FEE_BPS`** before quoting.
58
+ */
59
+ export declare function constantProductAmountOutWithFeeBps(reserveIn: bigint, reserveOut: bigint, amountIn: bigint, feeBps: bigint): bigint;
60
+ /**
61
+ * Amount out after pool swap fee (output-side): same as **`constantProductAmountOutWithFeeBps`** with **`NATIVE_CP_SWAP_FEE_BPS`**.
62
+ */
63
+ export declare function constantProductAmountOut(reserveIn: bigint, reserveOut: bigint, amountIn: bigint): bigint;
64
+ //# sourceMappingURL=nativeAmm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeAmm.d.ts","sourceRoot":"","sources":["../src/nativeAmm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Native constant-product pool calldata (Boing VM). See `docs/NATIVE-AMM-CALLDATA.md`.
3
+ * Reserves and amounts should stay ≤ `Number.MAX_SAFE_INTEGER` / u64 range for VM `Mul` parity.
4
+ */
5
+ import { bytesToHex, hexToBytes, validateHex32 } from './hex.js';
6
+ /** `swap` selector (low byte of word0). */
7
+ export const SELECTOR_NATIVE_AMM_SWAP = 0x10;
8
+ /** `add_liquidity` selector. */
9
+ export const SELECTOR_NATIVE_AMM_ADD_LIQUIDITY = 0x11;
10
+ /** `remove_liquidity` selector (LP burn + pro-rata withdrawal). */
11
+ export const SELECTOR_NATIVE_AMM_REMOVE_LIQUIDITY = 0x12;
12
+ /** **v2 pool:** one-time `set_tokens(token_a, token_b)`. */
13
+ export const SELECTOR_NATIVE_AMM_SET_TOKENS = 0x13;
14
+ /** **v3/v4 pool:** `set_swap_fee_bps(fee)` — **64-byte** calldata; only when **total LP == 0**; **`1 ≤ fee ≤ 10_000`**. */
15
+ export const SELECTOR_NATIVE_AMM_SET_SWAP_FEE_BPS = 0x14;
16
+ /** **v5 pool:** `swap_to` — like `swap` plus **word4** = output recipient (**160-byte** calldata). */
17
+ export const SELECTOR_NATIVE_AMM_SWAP_TO = 0x15;
18
+ /** **v5 pool:** `remove_liquidity_to` — like `remove_liquidity` plus **recipient_a** / **recipient_b** (**192-byte** calldata). */
19
+ export const SELECTOR_NATIVE_AMM_REMOVE_LIQUIDITY_TO = 0x16;
20
+ /** Swap fee in basis points on **output** (matches `native_amm::NATIVE_CP_SWAP_FEE_BPS`). */
21
+ export const NATIVE_CP_SWAP_FEE_BPS = 30;
22
+ /** Build 32-byte `Log2` **topic0** (UTF-8 ASCII + zero pad), matching `native_amm` constants. */
23
+ export function nativeAmmLogTopic0Utf8(ascii) {
24
+ const u8 = new Uint8Array(32);
25
+ const enc = new TextEncoder().encode(ascii);
26
+ if (enc.length > 32) {
27
+ throw new RangeError('native AMM topic0 label too long');
28
+ }
29
+ u8.set(enc);
30
+ return u8;
31
+ }
32
+ /** `Log2` topic0 hex for a successful **`swap`** (see `NATIVE-AMM-CALLDATA.md` § Logs). */
33
+ export const NATIVE_AMM_TOPIC_SWAP_HEX = bytesToHex(nativeAmmLogTopic0Utf8('BOING_NATIVEAMM_SWAP_V1'));
34
+ /** `Log2` topic0 hex for **`add_liquidity`**. */
35
+ export const NATIVE_AMM_TOPIC_ADD_LIQUIDITY_HEX = bytesToHex(nativeAmmLogTopic0Utf8('BOING_NATIVEAMM_ADDLP_V1'));
36
+ /** `Log2` topic0 hex for **`remove_liquidity`**. */
37
+ export const NATIVE_AMM_TOPIC_REMOVE_LIQUIDITY_HEX = bytesToHex(nativeAmmLogTopic0Utf8('BOING_NATIVEAMM_RMLP_V1'));
38
+ function selectorWord(selector) {
39
+ const w = new Uint8Array(32);
40
+ w[31] = selector & 0xff;
41
+ return w;
42
+ }
43
+ function amountWord(amount) {
44
+ const w = new Uint8Array(32);
45
+ if (amount < 0n || amount > (1n << 128n) - 1n) {
46
+ throw new RangeError('amount must fit in u128');
47
+ }
48
+ const be = new Uint8Array(16);
49
+ let x = amount;
50
+ for (let i = 15; i >= 0; i--) {
51
+ be[i] = Number(x & 0xffn);
52
+ x >>= 8n;
53
+ }
54
+ w.set(be, 16);
55
+ return w;
56
+ }
57
+ /** 128-byte `swap` calldata: direction 0 = A→B, 1 = B→A. */
58
+ export function encodeNativeAmmSwapCalldata(direction, amountIn, minOut) {
59
+ const out = new Uint8Array(128);
60
+ out.set(selectorWord(SELECTOR_NATIVE_AMM_SWAP), 0);
61
+ out.set(amountWord(direction), 32);
62
+ out.set(amountWord(amountIn), 64);
63
+ out.set(amountWord(minOut), 96);
64
+ return out;
65
+ }
66
+ /** **160-byte** `swap_to` calldata (v5 pool): explicit **output recipient** for token `transfer`. */
67
+ export function encodeNativeAmmSwapToCalldata(direction, amountIn, minOut, recipientHex32) {
68
+ const out = new Uint8Array(160);
69
+ out.set(selectorWord(SELECTOR_NATIVE_AMM_SWAP_TO), 0);
70
+ out.set(amountWord(direction), 32);
71
+ out.set(amountWord(amountIn), 64);
72
+ out.set(amountWord(minOut), 96);
73
+ out.set(hexToBytes(validateHex32(recipientHex32)), 128);
74
+ return out;
75
+ }
76
+ /**
77
+ * 128-byte `add_liquidity` calldata. On success the pool **returns** **32** bytes: LP minted in this
78
+ * call as **u128** in the **low 16 bytes** of the word (big-endian word; value in bytes 16..32).
79
+ */
80
+ export function encodeNativeAmmAddLiquidityCalldata(amountA, amountB, minLiquidity) {
81
+ const out = new Uint8Array(128);
82
+ out.set(selectorWord(SELECTOR_NATIVE_AMM_ADD_LIQUIDITY), 0);
83
+ out.set(amountWord(amountA), 32);
84
+ out.set(amountWord(amountB), 64);
85
+ out.set(amountWord(minLiquidity), 96);
86
+ return out;
87
+ }
88
+ /** 128-byte `remove_liquidity` calldata. */
89
+ export function encodeNativeAmmRemoveLiquidityCalldata(liquidityBurn, minA, minB) {
90
+ const out = new Uint8Array(128);
91
+ out.set(selectorWord(SELECTOR_NATIVE_AMM_REMOVE_LIQUIDITY), 0);
92
+ out.set(amountWord(liquidityBurn), 32);
93
+ out.set(amountWord(minA), 64);
94
+ out.set(amountWord(minB), 96);
95
+ return out;
96
+ }
97
+ /** **192-byte** `remove_liquidity_to` (v5 pool): explicit **recipient_a** / **recipient_b** for reference-token `transfer`. */
98
+ export function encodeNativeAmmRemoveLiquidityToCalldata(liquidityBurn, minA, minB, recipientAHex32, recipientBHex32) {
99
+ const out = new Uint8Array(192);
100
+ out.set(selectorWord(SELECTOR_NATIVE_AMM_REMOVE_LIQUIDITY_TO), 0);
101
+ out.set(amountWord(liquidityBurn), 32);
102
+ out.set(amountWord(minA), 64);
103
+ out.set(amountWord(minB), 96);
104
+ out.set(hexToBytes(validateHex32(recipientAHex32)), 128);
105
+ out.set(hexToBytes(validateHex32(recipientBHex32)), 160);
106
+ return out;
107
+ }
108
+ /** **v2:** 96-byte `set_tokens` — each id is 32-byte account hex (`0x` + 64 hex). Use `0x` + 64 zeros for “no token” on that side. */
109
+ export function encodeNativeAmmSetTokensCalldata(tokenAHex32, tokenBHex32) {
110
+ const out = new Uint8Array(96);
111
+ out.set(selectorWord(SELECTOR_NATIVE_AMM_SET_TOKENS), 0);
112
+ out.set(hexToBytes(validateHex32(tokenAHex32)), 32);
113
+ out.set(hexToBytes(validateHex32(tokenBHex32)), 64);
114
+ return out;
115
+ }
116
+ /** **v3/v4:** 64-byte `set_swap_fee_bps` calldata (`native_amm::encode_set_swap_fee_bps_calldata`). */
117
+ export function encodeNativeAmmSetSwapFeeBpsCalldata(feeBps) {
118
+ if (feeBps < 1n || feeBps > 10000n) {
119
+ throw new RangeError('feeBps must satisfy 1 <= feeBps <= 10000');
120
+ }
121
+ const out = new Uint8Array(64);
122
+ out.set(selectorWord(SELECTOR_NATIVE_AMM_SET_SWAP_FEE_BPS), 0);
123
+ out.set(amountWord(feeBps), 32);
124
+ return out;
125
+ }
126
+ export function encodeNativeAmmSwapCalldataHex(direction, amountIn, minOut) {
127
+ return bytesToHex(encodeNativeAmmSwapCalldata(direction, amountIn, minOut));
128
+ }
129
+ export function encodeNativeAmmSwapToCalldataHex(direction, amountIn, minOut, recipientHex32) {
130
+ return bytesToHex(encodeNativeAmmSwapToCalldata(direction, amountIn, minOut, recipientHex32));
131
+ }
132
+ export function encodeNativeAmmAddLiquidityCalldataHex(amountA, amountB, minLiquidity = 0n) {
133
+ return bytesToHex(encodeNativeAmmAddLiquidityCalldata(amountA, amountB, minLiquidity));
134
+ }
135
+ export function encodeNativeAmmRemoveLiquidityCalldataHex(liquidityBurn, minA, minB) {
136
+ return bytesToHex(encodeNativeAmmRemoveLiquidityCalldata(liquidityBurn, minA, minB));
137
+ }
138
+ export function encodeNativeAmmRemoveLiquidityToCalldataHex(liquidityBurn, minA, minB, recipientAHex32, recipientBHex32) {
139
+ return bytesToHex(encodeNativeAmmRemoveLiquidityToCalldata(liquidityBurn, minA, minB, recipientAHex32, recipientBHex32));
140
+ }
141
+ export function encodeNativeAmmSetTokensCalldataHex(tokenAHex32, tokenBHex32) {
142
+ return bytesToHex(encodeNativeAmmSetTokensCalldata(tokenAHex32, tokenBHex32));
143
+ }
144
+ export function encodeNativeAmmSetSwapFeeBpsCalldataHex(feeBps) {
145
+ return bytesToHex(encodeNativeAmmSetSwapFeeBpsCalldata(feeBps));
146
+ }
147
+ /** Raw CP step (no swap fee): Δout = ⌊ r_out · Δin / (r_in + Δin) ⌋. */
148
+ export function constantProductAmountOutNoFee(reserveIn, reserveOut, amountIn) {
149
+ if (reserveIn < 0n || reserveOut < 0n || amountIn < 0n) {
150
+ throw new RangeError('reserves and amountIn must be non-negative');
151
+ }
152
+ const denom = reserveIn + amountIn;
153
+ if (denom === 0n)
154
+ return 0n;
155
+ return (reserveOut * amountIn) / denom;
156
+ }
157
+ /**
158
+ * Amount out after an explicit **output-side** fee in basis points (`native_amm::constant_product_amount_out_after_fee_with_bps`).
159
+ * **`feeBps`** must be **`0`…`10000`** (inclusive). For **v3/v4** pools, if storage at `swap_fee_bps_key` reads **`0`**, treat as **`NATIVE_CP_SWAP_FEE_BPS`** before quoting.
160
+ */
161
+ export function constantProductAmountOutWithFeeBps(reserveIn, reserveOut, amountIn, feeBps) {
162
+ if (feeBps < 0n || feeBps > 10000n) {
163
+ throw new RangeError('feeBps must satisfy 0 <= feeBps <= 10000');
164
+ }
165
+ const dy = constantProductAmountOutNoFee(reserveIn, reserveOut, amountIn);
166
+ const keep = 10000n - feeBps;
167
+ return (dy * keep) / 10000n;
168
+ }
169
+ /**
170
+ * Amount out after pool swap fee (output-side): same as **`constantProductAmountOutWithFeeBps`** with **`NATIVE_CP_SWAP_FEE_BPS`**.
171
+ */
172
+ export function constantProductAmountOut(reserveIn, reserveOut, amountIn) {
173
+ return constantProductAmountOutWithFeeBps(reserveIn, reserveOut, amountIn, BigInt(NATIVE_CP_SWAP_FEE_BPS));
174
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Parse native constant-product pool **`Log2`** rows (`topic0` + caller `topic1` + 96-byte `data`).
3
+ * Matches `native_amm` emission and `docs/NATIVE-AMM-CALLDATA.md` § Logs.
4
+ */
5
+ import type { ExecutionLog, ExecutionReceipt, RpcLogEntry } from './types.js';
6
+ /** Discriminant for a parsed native AMM `Log2` event. */
7
+ export type NativeAmmLog2Kind = 'swap' | 'addLiquidity' | 'removeLiquidity';
8
+ export type NativeAmmLog2Event = {
9
+ kind: 'swap';
10
+ callerHex: string;
11
+ /** Calldata-style direction: `0` = A→B, `1` = B→A. */
12
+ direction: bigint;
13
+ amountIn: bigint;
14
+ amountOutAfterFee: bigint;
15
+ } | {
16
+ kind: 'addLiquidity';
17
+ callerHex: string;
18
+ amountA: bigint;
19
+ amountB: bigint;
20
+ lpMinted: bigint;
21
+ } | {
22
+ kind: 'removeLiquidity';
23
+ callerHex: string;
24
+ liquidityBurned: bigint;
25
+ amountAOut: bigint;
26
+ amountBOut: bigint;
27
+ };
28
+ /** `tryParseNativeAmmRpcLogEntry` result: parsed fields plus RPC placement. */
29
+ export type NativeAmmRpcLogParsed = NativeAmmLog2Event & Pick<RpcLogEntry, 'block_height' | 'tx_index' | 'tx_id' | 'log_index' | 'address'>;
30
+ /** True if `topic` (any casing / optional `0x`) is one of the three native AMM `Log2` topic0 values. */
31
+ export declare function isNativeAmmLog2Topic0(topic: string): boolean;
32
+ /**
33
+ * True if `log` looks like a native AMM `Log2` (two topics, known topic0). Does not validate `data`.
34
+ */
35
+ export declare function isNativeAmmLog2Shape(log: Pick<ExecutionLog, 'topics'>): boolean;
36
+ /**
37
+ * Parse one receipt / RPC log into a typed event, or `null` if shape or `data` does not match.
38
+ */
39
+ export declare function tryParseNativeAmmLog2(log: Pick<ExecutionLog, 'topics' | 'data'>): NativeAmmLog2Event | null;
40
+ export declare function tryParseNativeAmmRpcLogEntry(entry: RpcLogEntry): NativeAmmRpcLogParsed | null;
41
+ /** Keep only `RpcLogEntry` rows that parse as native AMM `Log2`, with placement fields attached. */
42
+ export declare function filterMapNativeAmmRpcLogs(entries: readonly RpcLogEntry[]): NativeAmmRpcLogParsed[];
43
+ /** All successfully parsed native AMM logs in one receipt (in log order). */
44
+ export declare function collectNativeAmmLog2FromReceipt(receipt: ExecutionReceipt): Array<{
45
+ logIndex: number;
46
+ event: NativeAmmLog2Event;
47
+ }>;
48
+ //# sourceMappingURL=nativeAmmLogs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeAmmLogs.d.ts","sourceRoot":"","sources":["../src/nativeAmmLogs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9E,yDAAyD;AACzD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,cAAc,GAAG,iBAAiB,CAAC;AAE5E,MAAM,MAAM,kBAAkB,GAC1B;IACE,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GACD;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,GACD;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEN,+EAA+E;AAC/E,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,GACpD,IAAI,CAAC,WAAW,EAAE,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,CAAC,CAAC;AASrF,wGAAwG;AACxG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAM5D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG,OAAO,CAG/E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,MAAM,CAAC,GAAG,kBAAkB,GAAG,IAAI,CAsC3G;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,WAAW,GAAG,qBAAqB,GAAG,IAAI,CAW7F;AAED,oGAAoG;AACpG,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,qBAAqB,EAAE,CAOlG;AAED,6EAA6E;AAC7E,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,gBAAgB,GACxB,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAAC,CAOxD"}