tbc-tx-parser 0.1.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 (183) hide show
  1. package/README.md +214 -0
  2. package/dist/adapters/partial-sha256.d.ts +2 -0
  3. package/dist/adapters/partial-sha256.d.ts.map +1 -0
  4. package/dist/adapters/partial-sha256.js +5 -0
  5. package/dist/adapters/partial-sha256.js.map +1 -0
  6. package/dist/adapters/tbc-lib.d.ts +4 -0
  7. package/dist/adapters/tbc-lib.d.ts.map +1 -0
  8. package/dist/adapters/tbc-lib.js +4 -0
  9. package/dist/adapters/tbc-lib.js.map +1 -0
  10. package/dist/constants/chain.d.ts +4 -0
  11. package/dist/constants/chain.d.ts.map +1 -0
  12. package/dist/constants/chain.js +7 -0
  13. package/dist/constants/chain.js.map +1 -0
  14. package/dist/core/chain.d.ts +10 -0
  15. package/dist/core/chain.d.ts.map +1 -0
  16. package/dist/core/chain.js +41 -0
  17. package/dist/core/chain.js.map +1 -0
  18. package/dist/core/input-utxos.d.ts +3 -0
  19. package/dist/core/input-utxos.d.ts.map +1 -0
  20. package/dist/core/input-utxos.js +69 -0
  21. package/dist/core/input-utxos.js.map +1 -0
  22. package/dist/core/public-chain-compression.d.ts +4 -0
  23. package/dist/core/public-chain-compression.d.ts.map +1 -0
  24. package/dist/core/public-chain-compression.js +87 -0
  25. package/dist/core/public-chain-compression.js.map +1 -0
  26. package/dist/core/public-script.d.ts +4 -0
  27. package/dist/core/public-script.d.ts.map +1 -0
  28. package/dist/core/public-script.js +94 -0
  29. package/dist/core/public-script.js.map +1 -0
  30. package/dist/decode-tx-raw.d.ts +3 -0
  31. package/dist/decode-tx-raw.d.ts.map +1 -0
  32. package/dist/decode-tx-raw.js +350 -0
  33. package/dist/decode-tx-raw.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +3 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/protocols/ft/index.d.ts +7 -0
  39. package/dist/protocols/ft/index.d.ts.map +1 -0
  40. package/dist/protocols/ft/index.js +393 -0
  41. package/dist/protocols/ft/index.js.map +1 -0
  42. package/dist/protocols/index.d.ts +5 -0
  43. package/dist/protocols/index.d.ts.map +1 -0
  44. package/dist/protocols/index.js +61 -0
  45. package/dist/protocols/index.js.map +1 -0
  46. package/dist/protocols/nft/index.d.ts +8 -0
  47. package/dist/protocols/nft/index.d.ts.map +1 -0
  48. package/dist/protocols/nft/index.js +335 -0
  49. package/dist/protocols/nft/index.js.map +1 -0
  50. package/dist/protocols/nft/media.js.map +1 -0
  51. package/dist/protocols/order-book/actions.d.ts +7 -0
  52. package/dist/protocols/order-book/actions.d.ts.map +1 -0
  53. package/dist/protocols/order-book/actions.js +102 -0
  54. package/dist/protocols/order-book/actions.js.map +1 -0
  55. package/dist/protocols/order-book/facts.d.ts +7 -0
  56. package/dist/protocols/order-book/facts.d.ts.map +1 -0
  57. package/dist/protocols/order-book/facts.js +81 -0
  58. package/dist/protocols/order-book/facts.js.map +1 -0
  59. package/dist/protocols/order-book/identity.d.ts +3 -0
  60. package/dist/protocols/order-book/identity.d.ts.map +1 -0
  61. package/dist/protocols/order-book/identity.js +46 -0
  62. package/dist/protocols/order-book/identity.js.map +1 -0
  63. package/dist/protocols/order-book/index.d.ts +12 -0
  64. package/dist/protocols/order-book/index.d.ts.map +1 -0
  65. package/dist/protocols/order-book/index.js +34 -0
  66. package/dist/protocols/order-book/index.js.map +1 -0
  67. package/dist/protocols/order-book/settlement.d.ts +10 -0
  68. package/dist/protocols/order-book/settlement.d.ts.map +1 -0
  69. package/dist/protocols/order-book/settlement.js +318 -0
  70. package/dist/protocols/order-book/settlement.js.map +1 -0
  71. package/dist/protocols/order-book/types.d.ts +101 -0
  72. package/dist/protocols/order-book/types.d.ts.map +1 -0
  73. package/dist/protocols/order-book/types.js +2 -0
  74. package/dist/protocols/order-book/types.js.map +1 -0
  75. package/dist/protocols/piggy-bank/index.d.ts +7 -0
  76. package/dist/protocols/piggy-bank/index.d.ts.map +1 -0
  77. package/dist/protocols/piggy-bank/index.js +91 -0
  78. package/dist/protocols/piggy-bank/index.js.map +1 -0
  79. package/dist/protocols/pool-nft/actions.d.ts +15 -0
  80. package/dist/protocols/pool-nft/actions.d.ts.map +1 -0
  81. package/dist/protocols/pool-nft/actions.js +90 -0
  82. package/dist/protocols/pool-nft/actions.js.map +1 -0
  83. package/dist/protocols/pool-nft/amounts.d.ts +10 -0
  84. package/dist/protocols/pool-nft/amounts.d.ts.map +1 -0
  85. package/dist/protocols/pool-nft/amounts.js +45 -0
  86. package/dist/protocols/pool-nft/amounts.js.map +1 -0
  87. package/dist/protocols/pool-nft/constants.d.ts +15 -0
  88. package/dist/protocols/pool-nft/constants.d.ts.map +1 -0
  89. package/dist/protocols/pool-nft/constants.js +27 -0
  90. package/dist/protocols/pool-nft/constants.js.map +1 -0
  91. package/dist/protocols/pool-nft/facts.d.ts +11 -0
  92. package/dist/protocols/pool-nft/facts.d.ts.map +1 -0
  93. package/dist/protocols/pool-nft/facts.js +113 -0
  94. package/dist/protocols/pool-nft/facts.js.map +1 -0
  95. package/dist/protocols/pool-nft/fees.d.ts +14 -0
  96. package/dist/protocols/pool-nft/fees.d.ts.map +1 -0
  97. package/dist/protocols/pool-nft/fees.js +161 -0
  98. package/dist/protocols/pool-nft/fees.js.map +1 -0
  99. package/dist/protocols/pool-nft/index.d.ts +4 -0
  100. package/dist/protocols/pool-nft/index.d.ts.map +1 -0
  101. package/dist/protocols/pool-nft/index.js +19 -0
  102. package/dist/protocols/pool-nft/index.js.map +1 -0
  103. package/dist/protocols/pool-nft/movements.d.ts +5 -0
  104. package/dist/protocols/pool-nft/movements.d.ts.map +1 -0
  105. package/dist/protocols/pool-nft/movements.js +804 -0
  106. package/dist/protocols/pool-nft/movements.js.map +1 -0
  107. package/dist/protocols/pool-nft/selectors.d.ts +40 -0
  108. package/dist/protocols/pool-nft/selectors.d.ts.map +1 -0
  109. package/dist/protocols/pool-nft/selectors.js +173 -0
  110. package/dist/protocols/pool-nft/selectors.js.map +1 -0
  111. package/dist/protocols/pool-nft/types.d.ts +34 -0
  112. package/dist/protocols/pool-nft/types.d.ts.map +1 -0
  113. package/dist/protocols/pool-nft/types.js +2 -0
  114. package/dist/protocols/pool-nft/types.js.map +1 -0
  115. package/dist/protocols/tbc/index.d.ts +3 -0
  116. package/dist/protocols/tbc/index.d.ts.map +1 -0
  117. package/dist/protocols/tbc/index.js +21 -0
  118. package/dist/protocols/tbc/index.js.map +1 -0
  119. package/dist/protocols/types.d.ts +15 -0
  120. package/dist/protocols/types.d.ts.map +1 -0
  121. package/dist/protocols/types.js +2 -0
  122. package/dist/protocols/types.js.map +1 -0
  123. package/dist/result/index.d.ts +7 -0
  124. package/dist/result/index.d.ts.map +1 -0
  125. package/dist/result/index.js +869 -0
  126. package/dist/result/index.js.map +1 -0
  127. package/dist/result/semantic.d.ts +6 -0
  128. package/dist/result/semantic.d.ts.map +1 -0
  129. package/dist/result/semantic.js +950 -0
  130. package/dist/result/semantic.js.map +1 -0
  131. package/dist/script-parser/contracts.d.ts +7 -0
  132. package/dist/script-parser/contracts.d.ts.map +1 -0
  133. package/dist/script-parser/contracts.js +104 -0
  134. package/dist/script-parser/contracts.js.map +1 -0
  135. package/dist/script-parser/op-return.d.ts +8 -0
  136. package/dist/script-parser/op-return.d.ts.map +1 -0
  137. package/dist/script-parser/op-return.js +315 -0
  138. package/dist/script-parser/op-return.js.map +1 -0
  139. package/dist/script-parser/origin.d.ts +6 -0
  140. package/dist/script-parser/origin.d.ts.map +1 -0
  141. package/dist/script-parser/origin.js +68 -0
  142. package/dist/script-parser/origin.js.map +1 -0
  143. package/dist/script-parser.d.ts +3 -0
  144. package/dist/script-parser.d.ts.map +1 -0
  145. package/dist/script-parser.js +183 -0
  146. package/dist/script-parser.js.map +1 -0
  147. package/dist/types/protocol.d.ts +175 -0
  148. package/dist/types/protocol.d.ts.map +1 -0
  149. package/dist/types/protocol.js +2 -0
  150. package/dist/types/protocol.js.map +1 -0
  151. package/dist/types/result.d.ts +167 -0
  152. package/dist/types/result.d.ts.map +1 -0
  153. package/dist/types/result.js +2 -0
  154. package/dist/types/result.js.map +1 -0
  155. package/dist/types/script.d.ts +180 -0
  156. package/dist/types/script.d.ts.map +1 -0
  157. package/dist/types/script.js +9 -0
  158. package/dist/types/script.js.map +1 -0
  159. package/dist/types/semantic.d.ts +94 -0
  160. package/dist/types/semantic.d.ts.map +1 -0
  161. package/dist/types/semantic.js +2 -0
  162. package/dist/types/semantic.js.map +1 -0
  163. package/dist/types.d.ts +6 -0
  164. package/dist/types.d.ts.map +1 -0
  165. package/dist/types.js +4 -0
  166. package/dist/types.js.map +1 -0
  167. package/dist/utils/asm-converter.d.ts +7 -0
  168. package/dist/utils/asm-converter.d.ts.map +1 -0
  169. package/dist/utils/asm-converter.js +105 -0
  170. package/dist/utils/asm-converter.js.map +1 -0
  171. package/dist/utils/binary.d.ts +3 -0
  172. package/dist/utils/binary.d.ts.map +1 -0
  173. package/dist/utils/binary.js +17 -0
  174. package/dist/utils/binary.js.map +1 -0
  175. package/dist/utils/multi-sig.d.ts +9 -0
  176. package/dist/utils/multi-sig.d.ts.map +1 -0
  177. package/dist/utils/multi-sig.js +125 -0
  178. package/dist/utils/multi-sig.js.map +1 -0
  179. package/dist/utils/token-amount.d.ts +3 -0
  180. package/dist/utils/token-amount.d.ts.map +1 -0
  181. package/dist/utils/token-amount.js +37 -0
  182. package/dist/utils/token-amount.js.map +1 -0
  183. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # tbc-tx-parser
2
+
3
+ An SDK for decoding raw TBC transactions (`txraw`) into on-chain facts and asset flows for wallets, block explorers, and debugging tools.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install tbc-tx-parser
9
+ ```
10
+
11
+ ```bash
12
+ pnpm add tbc-tx-parser
13
+ ```
14
+
15
+ ## Supported Features
16
+
17
+ Currently supported:
18
+
19
+ - Native TBC transfers, coinbase rewards, self/change flows, fees, and common locking-script outputs.
20
+ - FT / StableCoin mint, transfer, merge, and mixed FT/TBC transactions.
21
+ - NFT collection mint, ordinary NFT mint/transfer, and hash-only Hold burn detection.
22
+ - OrderBook placement, cancellation, update, and matching semantics.
23
+ - PoolNFT create, init, increase liquidity, consume liquidity, TBC-to-FT swaps, FT-to-TBC swaps, merge FT in pool, standalone LP merge, and LP burn.
24
+ - PiggyBank freeze / unfreeze.
25
+
26
+ The parser never accesses the network or fetches prevouts by txid. The caller must provide `inputUtxos` for every transaction input.
27
+ Coinbase reward transactions have no spendable input prevouts and are the only exception that may omit `inputUtxos`.
28
+
29
+ ## Basic Usage
30
+
31
+ ```ts
32
+ import { decodeTxRaw } from 'tbc-tx-parser';
33
+
34
+ const result = await decodeTxRaw(txraw, {
35
+ inputUtxos,
36
+ });
37
+ ```
38
+
39
+ ## Input UTXOs
40
+
41
+ Asset-flow decoding requires the prevout for every input. Passing only `txraw` throws because the parser cannot reliably determine where assets originated:
42
+
43
+ ```ts
44
+ const result = await decodeTxRaw(txraw, {
45
+ inputUtxos: {
46
+ 'prevTxid:0': {
47
+ satoshis: 1000000,
48
+ lockingScript: '76a914...88ac',
49
+ },
50
+ },
51
+ });
52
+ ```
53
+
54
+ The key format is:
55
+
56
+ ```ts
57
+ `${prevTxid}:${vout}`
58
+ ```
59
+
60
+ An array ordered by input may also be used:
61
+
62
+ ```ts
63
+ const result = await decodeTxRaw(txraw, {
64
+ inputUtxos: [
65
+ {
66
+ satoshis: 1000000,
67
+ lockingScript: '76a914...88ac',
68
+ },
69
+ ],
70
+ });
71
+ ```
72
+
73
+ Contract-asset inputs also require their paired unspendable tape prevouts:
74
+
75
+ - FT / StableCoin Code input: `associatedTape` is `vout + 1` in the same transaction and must be a zero-satoshi `FTape`.
76
+ - NFT Code input: `associatedTape` is `vout + 2` in the same transaction and must be a zero-satoshi `NTape`; the same spend must also contain the corresponding NFT Hold input. `associatedOrigin` should provide the origin UTXO referenced by the Code script. A Mint NHold origin proves collection membership, while an ordinary P2PKH origin proves a standalone NFT that does not use a collection UTXO.
77
+ - PoolNFT state input: when the state prevout does not directly carry the PoolNFT tape, provide the adjacent PoolNFT OP_RETURN tape at `vout + 1` as `associatedTape` so the parser can compare the previous and current pool states.
78
+
79
+ If a paired tape is missing, scripts do not match, or an input prevout is not a valid script for the asset, the result does not emit strongly verified protocol asset flows. Related positive-value locking outputs are displayed as TBC flowing to an address, a known contract, or an unknown locking script.
80
+
81
+ ## Return Value
82
+
83
+ ```ts
84
+ const result = await decodeTxRaw(txraw, { inputUtxos });
85
+
86
+ result.txid;
87
+ result.version;
88
+ result.locktime;
89
+ result.size;
90
+ result.chain.inputs;
91
+ result.chain.outputs;
92
+ result.chain.fee;
93
+ result.assetFlows;
94
+ ```
95
+
96
+ Common fields:
97
+
98
+ - `chain.inputs`: transaction inputs and decoded prevout facts.
99
+ - `chain.outputs`: transaction outputs, addresses, script classifications, and protocol tape state.
100
+ - `chain.fee`: transaction fee.
101
+ - `assetFlows`: primary asset-flow data for application displays.
102
+
103
+ The top-level SDK result does not expose `transactionType`. Transaction-type labels can make `unknown` or weakly evidenced transactions look definitive, so presentation layers should build descriptions from verifiable facts in `assetFlows`, `chain.inputs`, and `chain.outputs`.
104
+
105
+ The current version also keeps internal `semantic`, `protocolDetails`, and `unsupported` data private. These remain internal protocol-classification and diagnostic capabilities and can later be exposed through an optional diagnostic result if an explorer or protocol-details view needs them.
106
+
107
+ Core `assetFlows` structure:
108
+
109
+ ```ts
110
+ result.assetFlows[0]?.purpose; // transfer | self | fee | lock | release | mint | merge | burn | state | unknown
111
+ result.assetFlows[0]?.direction; // in | out | self | unknown
112
+ result.assetFlows[0]?.asset; // { type: 'tbc' | 'ft' | 'stablecoin' | 'nft', ... }
113
+ result.assetFlows[0]?.amount; // Present for divisible assets such as TBC/FT; absent from NFT flows
114
+ result.assetFlows[0]?.from; // address / addresses / hash / txid / vout
115
+ result.assetFlows[0]?.to; // address / addresses / hash / script / txid / vout
116
+ result.assetFlows[0]?.context; // optional { protocol, recognized, action?, markers? }
117
+ ```
118
+
119
+ Protocol-specific flows retain a generic `purpose` and may include `context`. For example, PiggyBank freeze and OrderBook placement both use `purpose: "lock"`, while `context.protocol` and `context.action` distinguish `piggyBank/freeze` from `orderBook/placeBuy` or `orderBook/placeSell`. Recognized OrderBook context is attached only to placement locks. Match settlement and match fee-recipient payments are plain transfers, cancellation refunds are releases, and recreated partial-fill or update order state is read from `chain.outputs[].script.data.orderBook` rather than exposed as an asset flow. OrderBook fee-recipient payments use `purpose: "transfer"`. PoolNFT reserve snapshots are likewise read from `chain.outputs[].script.data.poolNft`; `assetFlows` contains only the pool's observable transfers, LP mint/burn, self/change, and visible fee flows. Unknown contract carriers remain `purpose: "transfer"` and use `protocol: "unknown"` with `recognized: false`; marker evidence may be included without guessing a protocol name. When no owner address or hash can be extracted from a locking script, the destination is represented by `to.script`.
120
+
121
+ Display guidance:
122
+
123
+ - Summarize what a transaction does from `assetFlows`, script facts, and application context.
124
+ - Use `assetFlows` as the primary source for showing how assets move.
125
+ - Read `chain.inputs` / `chain.outputs` `script.data` when displaying contract state or protocol tape fields.
126
+
127
+ ## Amount Units
128
+
129
+ TBC amounts use satoshis:
130
+
131
+ ```ts
132
+ result.chain.outputs[0].satoshis;
133
+ result.chain.fee?.satoshis;
134
+ ```
135
+
136
+ FT / StableCoin / PoolNFT LP amounts use raw smallest-unit strings:
137
+
138
+ ```ts
139
+ result.assetFlows[0]?.amount;
140
+ ```
141
+
142
+ NFTs are indivisible, so ordinary NFT flows do not contain `amount`. `supply` is collection-creation metadata and does not represent a quantity for an individual NFT. An NFT minted from a collection Mint NHold may include `collectionId`; a standalone NFT originating from ordinary P2PKH retains only its own `contractId` and has no collection fields.
143
+
144
+ ## PoolNFT Notes
145
+
146
+ PoolNFT is a composite protocol. Decoding considers all of the following rather than relying only on the PoolNFT tape:
147
+
148
+ - Previous pool state input.
149
+ - Current pool state output.
150
+ - PoolNFT OP_RETURN tape.
151
+ - FT A / FTLP movements.
152
+ - TBC reserve delta, payout, and fee output.
153
+ - LP token identity, partial hash, and burn receiver.
154
+
155
+ The active PoolNFT fixture corpus contains exactly 18 real testnet broadcasts: the nine operations above for one unlocked and one public-key-locked PoolNFT v2 pool. Both modes use independent ordinary FT contracts and independent pools. The locked cases have `withLock: true`; the unlocked cases have `withLock: false`; all 18 cases use `withLockTime: false`.
156
+
157
+ Current PoolNFT coverage includes the primary paths and several false-positive protections:
158
+
159
+ - Reserve delta, FT A amount, and fee relationships for both swap directions.
160
+ - FT A, LP, and TBC relationships for increase / consume liquidity.
161
+ - LP change, no-visible-fee cases, and small TBC rounding boundaries during consume.
162
+ - Current FT A reserve validation for merge FT in pool.
163
+ - Standalone FTLP merges remain FT self flows without recreating PoolNFT state.
164
+ - Standalone FTLP burns remain FT burn flows without recreating PoolNFT state.
165
+ - Multiple PoolNFT tapes or multiple previous PoolNFT state inputs are currently treated as unsupported and do not produce PoolNFT movements.
166
+
167
+ If the caller omits the previous pool state's associated tape, PoolNFT may still be recognized as `heuristic`, but a complete state delta cannot be calculated.
168
+
169
+ ### Regenerating PoolNFT broadcast fixtures
170
+
171
+ The runner is testnet-only and resumable. Its key file, public transaction journal, and generated candidates remain ignored under `scripts/`. Preserve the journal until fixture generation finishes: it records both the 18 target transactions and the preparation transactions needed to resume safely. Preparation transactions are never promoted as fixtures.
172
+
173
+ Run the read-only checks first:
174
+
175
+ ```bash
176
+ TBC_KEYS_FILE=/absolute/path/to/tbc-test-addresses.json \
177
+ TBC_POOL_NFT_JOURNAL=/absolute/path/to/pool-nft-broadcast-journal.json \
178
+ npm run pool-nft:preflight
179
+
180
+ TBC_POOL_NFT_JOURNAL=/absolute/path/to/pool-nft-broadcast-journal.json \
181
+ npm run pool-nft:status
182
+ ```
183
+
184
+ Broadcast each lifecycle only when testnet spending is intended. `TBC_BROADCAST=1` is an explicit mutation guard and these commands spend testnet UTXOs:
185
+
186
+ ```bash
187
+ TBC_BROADCAST=1 TBC_KEYS_FILE=/absolute/path/to/tbc-test-addresses.json \
188
+ TBC_POOL_NFT_JOURNAL=/absolute/path/to/pool-nft-broadcast-journal.json \
189
+ npm run pool-nft:run -- unlocked
190
+
191
+ TBC_BROADCAST=1 TBC_KEYS_FILE=/absolute/path/to/tbc-test-addresses.json \
192
+ TBC_POOL_NFT_JOURNAL=/absolute/path/to/pool-nft-broadcast-journal.json \
193
+ npm run pool-nft:run -- locked
194
+ ```
195
+
196
+ After `status` reports all 18 targets complete, generate reviewed candidates without broadcasting:
197
+
198
+ ```bash
199
+ TBC_POOL_NFT_JOURNAL=/absolute/path/to/pool-nft-broadcast-journal.json \
200
+ npm run pool-nft:fixtures
201
+ ```
202
+
203
+ The generator re-fetches every target raw transaction from testnet, verifies its txid, decodes its prevouts, validates lock flags, rejects public `purpose: "state"` flows, and writes candidates under `scripts/pool-nft-generated/`. Pool reserve state belongs under `chain.outputs[].script.data.poolNft`; only observable transfers, mint/burn, self/change, and visible fees belong in `assetFlows`.
204
+
205
+ ## Notes
206
+
207
+ - The SDK does not access the network.
208
+ - The SDK does not accept a `network` parameter.
209
+ - The SDK does not query transactions by `txid`.
210
+ - The SDK does not fetch input prevouts; callers must provide `inputUtxos`.
211
+ - The SDK does not currently expose top-level `transactionType`, `semantic`, `protocolDetails`, or `unsupported` fields.
212
+ - TBC addresses use canonical TBC address encoding.
213
+ - `tbc-lib-js` and `tbc-contract` are runtime dependencies installed with the npm package.
214
+ - `docs/`, `scripts/`, and `tests/` are not published to npm; the package contains only `dist`, `README.md`, and `package.json`.
@@ -0,0 +1,2 @@
1
+ export declare function calculatePartialSha256(input: Buffer): string;
2
+ //# sourceMappingURL=partial-sha256.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partial-sha256.d.ts","sourceRoot":"","sources":["../../src/adapters/partial-sha256.ts"],"names":[],"mappings":"AAEA,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,UAEnD"}
@@ -0,0 +1,5 @@
1
+ import partialSha256 from 'tbc-lib-js/lib/util/partial-sha256.js';
2
+ export function calculatePartialSha256(input) {
3
+ return partialSha256.calculate_partial_hash(input);
4
+ }
5
+ //# sourceMappingURL=partial-sha256.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partial-sha256.js","sourceRoot":"","sources":["../../src/adapters/partial-sha256.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,uCAAuC,CAAC;AAElE,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,OAAO,aAAa,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import * as tbcModule from 'tbc-lib-js';
2
+ export declare const tbc: typeof tbcModule;
3
+ export type TbcScript = InstanceType<typeof tbc.Script>;
4
+ //# sourceMappingURL=tbc-lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tbc-lib.d.ts","sourceRoot":"","sources":["../../src/adapters/tbc-lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,YAAY,CAAC;AAGxC,eAAO,MAAM,GAAG,EAA2E,OAAO,SAAS,CAAC;AAC5G,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import * as tbcModule from 'tbc-lib-js';
2
+ // Normalize tbc-lib-js imports across ESM and CJS so callers do not handle default-export compatibility.
3
+ export const tbc = (tbcModule.default ?? tbcModule);
4
+ //# sourceMappingURL=tbc-lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tbc-lib.js","sourceRoot":"","sources":["../../src/adapters/tbc-lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,YAAY,CAAC;AAExC,yGAAyG;AACzG,MAAM,CAAC,MAAM,GAAG,GAAG,CAAE,SAA4C,CAAC,OAAO,IAAI,SAAS,CAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const TBC_DECIMALS = 6;
2
+ export declare const SATOSHIS_PER_TBC = 1000000;
3
+ export declare const TBC_SYMBOL = "TBC";
4
+ //# sourceMappingURL=chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../src/constants/chain.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,YAAY,IAAI,CAAC;AAG9B,eAAO,MAAM,gBAAgB,UAAY,CAAC;AAG1C,eAAO,MAAM,UAAU,QAAQ,CAAC"}
@@ -0,0 +1,7 @@
1
+ // Decimal precision used when converting between display TBC and satoshis.
2
+ export const TBC_DECIMALS = 6;
3
+ // Native smallest-unit conversion: 1 TBC = 1,000,000 satoshis.
4
+ export const SATOSHIS_PER_TBC = 1_000_000;
5
+ // Native asset symbol used in public asset-flow and semantic results.
6
+ export const TBC_SYMBOL = 'TBC';
7
+ //# sourceMappingURL=chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.js","sourceRoot":"","sources":["../../src/constants/chain.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAE9B,+DAA+D;AAC/D,MAAM,CAAC,MAAM,gBAAgB,GAAG,SAAS,CAAC;AAE1C,sEAAsE;AACtE,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { DecodedInput, DecodedOutput, ScriptDetail, ScriptKind } from '../types.js';
2
+ export declare function parseScriptWithHex(scriptHex: string): ScriptDetail;
3
+ export declare function inferScriptKind(script: ScriptDetail): ScriptKind;
4
+ export declare function calculateChainStats(inputs: DecodedInput[], outputs: DecodedOutput[], size: number): {
5
+ inputValue: number | undefined;
6
+ outputValue: number;
7
+ fee: number | undefined;
8
+ feeRate: number | undefined;
9
+ };
10
+ //# sourceMappingURL=chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../src/core/chain.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CAKlE;AAGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CAkBhE;AAGD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM;;;;;EAcjG"}
@@ -0,0 +1,41 @@
1
+ import { parseScript } from '../script-parser.js';
2
+ import { ScriptType } from '../types.js';
3
+ // The script parser returns structured facts; restore raw hex here for chain facts and debugging displays.
4
+ export function parseScriptWithHex(scriptHex) {
5
+ return {
6
+ ...parseScript(scriptHex),
7
+ hex: scriptHex,
8
+ };
9
+ }
10
+ // Reduce detailed script results to the broad classifications required by the public chain layer.
11
+ export function inferScriptKind(script) {
12
+ if (script.originUtxo) {
13
+ return 'contract';
14
+ }
15
+ if (script.type === ScriptType.P2PKH) {
16
+ return 'p2pkh';
17
+ }
18
+ if (script.type === ScriptType.MULTISIG) {
19
+ return 'multisig';
20
+ }
21
+ if (script.data) {
22
+ return 'op_return';
23
+ }
24
+ return 'unrecognized';
25
+ }
26
+ // Calculate fees only when every input prevout amount is known to avoid reporting fees from incomplete data.
27
+ export function calculateChainStats(inputs, outputs, size) {
28
+ const inputValue = inputs.every((input) => input.prevout?.satoshis !== undefined)
29
+ ? inputs.reduce((sum, input) => sum + (input.prevout?.satoshis ?? 0), 0)
30
+ : undefined;
31
+ const outputValue = outputs.reduce((sum, output) => sum + output.satoshis, 0);
32
+ const valueDelta = inputValue === undefined ? undefined : inputValue - outputValue;
33
+ const fee = valueDelta === undefined || valueDelta < 0 ? undefined : valueDelta;
34
+ return {
35
+ inputValue,
36
+ outputValue,
37
+ fee,
38
+ feeRate: fee === undefined ? undefined : Math.ceil(fee / Math.max(1, Math.ceil(size / 1000))),
39
+ };
40
+ }
41
+ //# sourceMappingURL=chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.js","sourceRoot":"","sources":["../../src/core/chain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,2GAA2G;AAC3G,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,OAAO;QACL,GAAG,WAAW,CAAC,SAAS,CAAC;QACzB,GAAG,EAAE,SAAS;KACf,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;QACrC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,QAAQ,EAAE,CAAC;QACxC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,6GAA6G;AAC7G,MAAM,UAAU,mBAAmB,CAAC,MAAsB,EAAE,OAAwB,EAAE,IAAY;IAChG,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,KAAK,SAAS,CAAC;QAC/E,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,UAAU,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,GAAG,WAAW,CAAC;IACnF,MAAM,GAAG,GAAG,UAAU,KAAK,SAAS,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;IAEhF,OAAO;QACL,UAAU;QACV,WAAW;QACX,GAAG;QACH,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC;KAC9F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { DecodeTxRawOptions, InputUTXODetail } from '../types.js';
2
+ export declare function parseInputUtxo(txid: string, outputIndex: number, inputIndex: number, options: DecodeTxRawOptions): InputUTXODetail | undefined;
3
+ //# sourceMappingURL=input-utxos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-utxos.d.ts","sourceRoot":"","sources":["../../src/core/input-utxos.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA2DxF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,GAC1B,eAAe,GAAG,SAAS,CA2B7B"}
@@ -0,0 +1,69 @@
1
+ import { parseScriptWithHex } from './chain.js';
2
+ function parseAssociatedInputUtxo(value) {
3
+ if (!value) {
4
+ return undefined;
5
+ }
6
+ const script = parseScriptWithHex(value.lockingScript);
7
+ return {
8
+ txid: value.txid,
9
+ outputIndex: value.outputIndex,
10
+ script,
11
+ address: script.address ?? script.data?.address,
12
+ satoshis: value.satoshis,
13
+ };
14
+ }
15
+ // Record-form input UTXOs use on-chain outpoints as keys.
16
+ function getInputUtxoKey(txid, outputIndex) {
17
+ return `${txid}:${outputIndex}`;
18
+ }
19
+ // Support array and Record inputs; array mode can progressively match by input index or outpoint.
20
+ function findInputUtxo(inputUtxos, txid, outputIndex, inputIndex) {
21
+ if (!inputUtxos) {
22
+ return undefined;
23
+ }
24
+ if (Array.isArray(inputUtxos)) {
25
+ return inputUtxos.find((utxo, index) => {
26
+ if (utxo.inputIndex !== undefined) {
27
+ return utxo.inputIndex === inputIndex;
28
+ }
29
+ if (utxo.txid !== undefined && utxo.outputIndex !== undefined) {
30
+ return utxo.txid === txid && utxo.outputIndex === outputIndex;
31
+ }
32
+ if (utxo.txid !== undefined) {
33
+ return utxo.txid === txid;
34
+ }
35
+ if (utxo.outputIndex !== undefined) {
36
+ return utxo.outputIndex === outputIndex;
37
+ }
38
+ return index === inputIndex;
39
+ });
40
+ }
41
+ return inputUtxos[getInputUtxoKey(txid, outputIndex)] ?? inputUtxos[inputIndex.toString()];
42
+ }
43
+ // Parse caller-provided prevouts into fact-layer structures consumed directly by chain inputs.
44
+ export function parseInputUtxo(txid, outputIndex, inputIndex, options) {
45
+ const inputUtxo = findInputUtxo(options.inputUtxos, txid, outputIndex, inputIndex);
46
+ if (!inputUtxo) {
47
+ return undefined;
48
+ }
49
+ if (!Number.isFinite(inputUtxo.satoshis) || inputUtxo.satoshis < 0) {
50
+ return {
51
+ script: { asm: '' },
52
+ error: 'invalid input utxo satoshis',
53
+ };
54
+ }
55
+ const script = parseScriptWithHex(inputUtxo.lockingScript);
56
+ // associatedTape is the key prevout used to verify input-state continuity for FT, NFT, PoolNFT, and similar protocols.
57
+ const associatedTape = parseAssociatedInputUtxo(inputUtxo.associatedTape);
58
+ const associatedOrigin = parseAssociatedInputUtxo(inputUtxo.associatedOrigin);
59
+ return {
60
+ script,
61
+ address: script.address ?? script.data?.address,
62
+ hash: script.data?.hash,
63
+ satoshis: inputUtxo.satoshis,
64
+ ...(inputUtxo.contractId ? { contractId: inputUtxo.contractId } : {}),
65
+ ...(associatedTape ? { associatedTape } : {}),
66
+ ...(associatedOrigin ? { associatedOrigin } : {}),
67
+ };
68
+ }
69
+ //# sourceMappingURL=input-utxos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-utxos.js","sourceRoot":"","sources":["../../src/core/input-utxos.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { PublicDecodedInput, PublicDecodedOutput } from '../types.js';
2
+ export declare function compressPublicInputs(inputs: PublicDecodedInput[], minimumRunLength?: number): PublicDecodedInput[];
3
+ export declare function compressPublicOutputs(outputs: PublicDecodedOutput[], minimumRunLength?: number): PublicDecodedOutput[];
4
+ //# sourceMappingURL=public-chain-compression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-chain-compression.d.ts","sourceRoot":"","sources":["../../src/core/public-chain-compression.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAoB3E,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,kBAAkB,EAAE,EAC5B,gBAAgB,SAA6B,GAC5C,kBAAkB,EAAE,CAiCtB;AAaD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,EAAE,EAC9B,gBAAgB,SAA6B,GAC5C,mBAAmB,EAAE,CA+BvB"}
@@ -0,0 +1,87 @@
1
+ import { ScriptType } from '../types.js';
2
+ const DEFAULT_MINIMUM_RUN_LENGTH = 3;
3
+ function samePublicPrevout(left, right) {
4
+ return JSON.stringify(left.prevout) === JSON.stringify(right.prevout);
5
+ }
6
+ function continuesTbcInputRun(previous, current) {
7
+ return !previous.compression &&
8
+ !current.compression &&
9
+ previous.prevout?.script.type === ScriptType.P2PKH &&
10
+ current.prevout?.script.type === ScriptType.P2PKH &&
11
+ current.index === previous.index + 1 &&
12
+ current.prevTxid === previous.prevTxid &&
13
+ current.vout === previous.vout + 1 &&
14
+ current.sequence === previous.sequence &&
15
+ samePublicPrevout(previous, current);
16
+ }
17
+ export function compressPublicInputs(inputs, minimumRunLength = DEFAULT_MINIMUM_RUN_LENGTH) {
18
+ const compressed = [];
19
+ for (let start = 0; start < inputs.length;) {
20
+ let end = start + 1;
21
+ while (end < inputs.length && continuesTbcInputRun(inputs[end - 1], inputs[end])) {
22
+ end += 1;
23
+ }
24
+ const run = inputs.slice(start, end);
25
+ const first = run[0];
26
+ const last = run[run.length - 1];
27
+ if (first && last && run.length >= minimumRunLength && first.prevout?.satoshis !== undefined) {
28
+ compressed.push({
29
+ ...first,
30
+ compression: {
31
+ type: 'tbcInputs',
32
+ count: run.length,
33
+ indexRange: { from: first.index, to: last.index },
34
+ prevTxid: first.prevTxid,
35
+ voutRange: { from: first.vout, to: last.vout },
36
+ satoshisPerInput: first.prevout.satoshis,
37
+ totalSatoshis: run.reduce((sum, input) => sum + (input.prevout?.satoshis ?? 0), 0),
38
+ },
39
+ });
40
+ }
41
+ else {
42
+ compressed.push(...run);
43
+ }
44
+ start = end;
45
+ }
46
+ return compressed;
47
+ }
48
+ function continuesTbcOutputRun(previous, current) {
49
+ return !previous.compression &&
50
+ !current.compression &&
51
+ previous.script.type === ScriptType.P2PKH &&
52
+ current.script.type === ScriptType.P2PKH &&
53
+ current.index === previous.index + 1 &&
54
+ current.satoshis === previous.satoshis &&
55
+ current.address === previous.address &&
56
+ JSON.stringify(current.script) === JSON.stringify(previous.script);
57
+ }
58
+ export function compressPublicOutputs(outputs, minimumRunLength = DEFAULT_MINIMUM_RUN_LENGTH) {
59
+ const compressed = [];
60
+ for (let start = 0; start < outputs.length;) {
61
+ let end = start + 1;
62
+ while (end < outputs.length && continuesTbcOutputRun(outputs[end - 1], outputs[end])) {
63
+ end += 1;
64
+ }
65
+ const run = outputs.slice(start, end);
66
+ const first = run[0];
67
+ const last = run[run.length - 1];
68
+ if (first && last && run.length >= minimumRunLength) {
69
+ compressed.push({
70
+ ...first,
71
+ compression: {
72
+ type: 'tbcOutputs',
73
+ count: run.length,
74
+ indexRange: { from: first.index, to: last.index },
75
+ satoshisPerOutput: first.satoshis,
76
+ totalSatoshis: run.reduce((sum, output) => sum + output.satoshis, 0),
77
+ },
78
+ });
79
+ }
80
+ else {
81
+ compressed.push(...run);
82
+ }
83
+ start = end;
84
+ }
85
+ return compressed;
86
+ }
87
+ //# sourceMappingURL=public-chain-compression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-chain-compression.js","sourceRoot":"","sources":["../../src/core/public-chain-compression.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { PublicScriptDetail, ScriptDetail } from '../types.js';
2
+ export declare const PUBLIC_SCRIPT_COMPACTION_THRESHOLD_BYTES = 256;
3
+ export declare function sanitizeScriptForPublicResult(script: ScriptDetail): PublicScriptDetail;
4
+ //# sourceMappingURL=public-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-script.d.ts","sourceRoot":"","sources":["../../src/core/public-script.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,kBAAkB,EAElB,YAAY,EAEb,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,wCAAwC,MAAM,CAAC;AAgG5D,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,YAAY,GAAG,kBAAkB,CAyBtF"}
@@ -0,0 +1,94 @@
1
+ import { createHash } from 'node:crypto';
2
+ export const PUBLIC_SCRIPT_COMPACTION_THRESHOLD_BYTES = 256;
3
+ const PUBLIC_ASM_EDGE_MAX_BYTES = 256;
4
+ function scriptByteLength(hex) {
5
+ return hex && hex.length % 2 === 0 && /^[0-9a-f]*$/iu.test(hex)
6
+ ? Buffer.from(hex, 'hex').length
7
+ : undefined;
8
+ }
9
+ function tbcApiScriptHash(hex) {
10
+ return createHash('sha256')
11
+ .update(Buffer.from(hex, 'hex'))
12
+ .digest()
13
+ .reverse()
14
+ .toString('hex');
15
+ }
16
+ function takeWholeTokens(tokens, maxBytes, fromEnd = false) {
17
+ const selected = [];
18
+ const ordered = fromEnd ? [...tokens].reverse() : tokens;
19
+ for (const token of ordered) {
20
+ const candidate = fromEnd ? [token, ...selected].join(' ') : [...selected, token].join(' ');
21
+ if (Buffer.byteLength(candidate, 'utf8') > maxBytes) {
22
+ break;
23
+ }
24
+ if (fromEnd) {
25
+ selected.unshift(token);
26
+ }
27
+ else {
28
+ selected.push(token);
29
+ }
30
+ }
31
+ return selected.join(' ');
32
+ }
33
+ function compactAsm(asm) {
34
+ const tokens = asm.trim() ? asm.trim().split(/\s+/u) : [];
35
+ return {
36
+ byteLength: Buffer.byteLength(asm, 'utf8'),
37
+ prefix: takeWholeTokens(tokens, PUBLIC_ASM_EDGE_MAX_BYTES),
38
+ suffix: takeWholeTokens(tokens, PUBLIC_ASM_EDGE_MAX_BYTES, true),
39
+ };
40
+ }
41
+ function sanitizeFtTape(ftTape) {
42
+ return {
43
+ name: ftTape.name,
44
+ symbol: ftTape.symbol,
45
+ decimal: ftTape.decimal,
46
+ ...(ftTape.lockTime !== undefined ? { lockTime: ftTape.lockTime } : {}),
47
+ ...(ftTape.isStableCoin !== undefined ? { isStableCoin: ftTape.isStableCoin } : {}),
48
+ };
49
+ }
50
+ function sanitizeNftTape(nftTape) {
51
+ const { file: _file, media: _media, image: _image, ...publicTape } = nftTape;
52
+ return publicTape;
53
+ }
54
+ function sanitizeCollectionTape(collectionTape) {
55
+ return {
56
+ collectionName: collectionTape.collectionName,
57
+ ...(collectionTape.description !== undefined ? { description: collectionTape.description } : {}),
58
+ supply: collectionTape.supply,
59
+ };
60
+ }
61
+ function sanitizeData(data) {
62
+ if (!data) {
63
+ return undefined;
64
+ }
65
+ const { nftHoldLabel: _nftHoldLabel, nftHoldType: _nftHoldType, ...publicData } = data;
66
+ const sanitizedData = {
67
+ ...publicData,
68
+ ...(data.ftTape ? { ftTape: sanitizeFtTape(data.ftTape) } : {}),
69
+ ...(data.nftTape ? { nftTape: sanitizeNftTape(data.nftTape) } : {}),
70
+ ...(data.collectionTape ? { collectionTape: sanitizeCollectionTape(data.collectionTape) } : {}),
71
+ };
72
+ return Object.keys(sanitizedData).length ? sanitizedData : undefined;
73
+ }
74
+ export function sanitizeScriptForPublicResult(script) {
75
+ const { asm, hex, data: scriptData, ...scriptFacts } = script;
76
+ const byteLength = scriptByteLength(hex);
77
+ const shouldCompact = byteLength !== undefined && byteLength > PUBLIC_SCRIPT_COMPACTION_THRESHOLD_BYTES;
78
+ const data = sanitizeData(scriptData);
79
+ return {
80
+ ...scriptFacts,
81
+ asm: shouldCompact ? compactAsm(asm) : asm,
82
+ ...(hex
83
+ ? {
84
+ hex: {
85
+ ...(!shouldCompact ? { value: hex } : {}),
86
+ byteLength: byteLength ?? Buffer.from(hex, 'hex').length,
87
+ scriptHash: tbcApiScriptHash(hex),
88
+ },
89
+ }
90
+ : {}),
91
+ ...(data ? { data } : {}),
92
+ };
93
+ }
94
+ //# sourceMappingURL=public-script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-script.js","sourceRoot":"","sources":["../../src/core/public-script.ts"],"names":[],"mappings":"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"}