@kaspacom/kcc20-tx-builder 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 (234) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +104 -0
  3. package/artifacts/KCC20.placeholder.json +77479 -0
  4. package/artifacts/KCC20FeeTicket.placeholder.json +16846 -0
  5. package/artifacts/KCC20Orderbook.placeholder.json +78001 -0
  6. package/artifacts/KCC20Vesting.placeholder.json +4298 -0
  7. package/artifacts/KCC20Wrapper.placeholder.json +12246 -0
  8. package/dist/abi.d.ts +44 -0
  9. package/dist/abi.d.ts.map +1 -0
  10. package/dist/abi.js +336 -0
  11. package/dist/abi.js.map +1 -0
  12. package/dist/action-source-resolver.d.ts +80 -0
  13. package/dist/action-source-resolver.d.ts.map +1 -0
  14. package/dist/action-source-resolver.js +412 -0
  15. package/dist/action-source-resolver.js.map +1 -0
  16. package/dist/artifacts.d.ts +14 -0
  17. package/dist/artifacts.d.ts.map +1 -0
  18. package/dist/artifacts.js +44 -0
  19. package/dist/artifacts.js.map +1 -0
  20. package/dist/builder.d.ts +12 -0
  21. package/dist/builder.d.ts.map +1 -0
  22. package/dist/builder.js +18 -0
  23. package/dist/builder.js.map +1 -0
  24. package/dist/cjs/abi.d.ts +43 -0
  25. package/dist/cjs/abi.js +361 -0
  26. package/dist/cjs/abi.js.map +1 -0
  27. package/dist/cjs/action-source-resolver.d.ts +79 -0
  28. package/dist/cjs/action-source-resolver.js +435 -0
  29. package/dist/cjs/action-source-resolver.js.map +1 -0
  30. package/dist/cjs/artifacts.d.ts +13 -0
  31. package/dist/cjs/artifacts.js +51 -0
  32. package/dist/cjs/artifacts.js.map +1 -0
  33. package/dist/cjs/builder.d.ts +11 -0
  34. package/dist/cjs/builder.js +22 -0
  35. package/dist/cjs/builder.js.map +1 -0
  36. package/dist/cjs/deploy-operation.d.ts +103 -0
  37. package/dist/cjs/deploy-operation.js +335 -0
  38. package/dist/cjs/deploy-operation.js.map +1 -0
  39. package/dist/cjs/encoding.d.ts +5 -0
  40. package/dist/cjs/encoding.js +51 -0
  41. package/dist/cjs/encoding.js.map +1 -0
  42. package/dist/cjs/engine.d.ts +40 -0
  43. package/dist/cjs/engine.js +8972 -0
  44. package/dist/cjs/engine.js.map +1 -0
  45. package/dist/cjs/errors.d.ts +7 -0
  46. package/dist/cjs/errors.js +23 -0
  47. package/dist/cjs/errors.js.map +1 -0
  48. package/dist/cjs/fee-ticket-operation.d.ts +204 -0
  49. package/dist/cjs/fee-ticket-operation.js +327 -0
  50. package/dist/cjs/fee-ticket-operation.js.map +1 -0
  51. package/dist/cjs/index.d.ts +27 -0
  52. package/dist/cjs/index.js +45 -0
  53. package/dist/cjs/index.js.map +1 -0
  54. package/dist/cjs/ladder-limit-orders.d.ts +41 -0
  55. package/dist/cjs/ladder-limit-orders.js +129 -0
  56. package/dist/cjs/ladder-limit-orders.js.map +1 -0
  57. package/dist/cjs/mint-availability-operation.d.ts +56 -0
  58. package/dist/cjs/mint-availability-operation.js +95 -0
  59. package/dist/cjs/mint-availability-operation.js.map +1 -0
  60. package/dist/cjs/models.d.ts +90 -0
  61. package/dist/cjs/models.js +6 -0
  62. package/dist/cjs/models.js.map +1 -0
  63. package/dist/cjs/operations.d.ts +6 -0
  64. package/dist/cjs/operations.js +41 -0
  65. package/dist/cjs/operations.js.map +1 -0
  66. package/dist/cjs/package.json +1 -0
  67. package/dist/cjs/paid-mint-amount.d.ts +69 -0
  68. package/dist/cjs/paid-mint-amount.js +281 -0
  69. package/dist/cjs/paid-mint-amount.js.map +1 -0
  70. package/dist/cjs/protocol.d.ts +21 -0
  71. package/dist/cjs/protocol.js +25 -0
  72. package/dist/cjs/protocol.js.map +1 -0
  73. package/dist/cjs/runtime.d.ts +27 -0
  74. package/dist/cjs/runtime.js +3 -0
  75. package/dist/cjs/runtime.js.map +1 -0
  76. package/dist/cjs/sale-common.d.ts +287 -0
  77. package/dist/cjs/sale-common.js +928 -0
  78. package/dist/cjs/sale-common.js.map +1 -0
  79. package/dist/cjs/source-provider.d.ts +11 -0
  80. package/dist/cjs/source-provider.js +3 -0
  81. package/dist/cjs/source-provider.js.map +1 -0
  82. package/dist/cjs/source-validation.d.ts +9 -0
  83. package/dist/cjs/source-validation.js +33 -0
  84. package/dist/cjs/source-validation.js.map +1 -0
  85. package/dist/cjs/token-amount.d.ts +31 -0
  86. package/dist/cjs/token-amount.js +252 -0
  87. package/dist/cjs/token-amount.js.map +1 -0
  88. package/dist/cjs/token-operation.d.ts +135 -0
  89. package/dist/cjs/token-operation.js +236 -0
  90. package/dist/cjs/token-operation.js.map +1 -0
  91. package/dist/cjs/trade-fee.d.ts +60 -0
  92. package/dist/cjs/trade-fee.js +185 -0
  93. package/dist/cjs/trade-fee.js.map +1 -0
  94. package/dist/cjs/trading-operation.d.ts +212 -0
  95. package/dist/cjs/trading-operation.js +587 -0
  96. package/dist/cjs/trading-operation.js.map +1 -0
  97. package/dist/cjs/verify-operation.d.ts +79 -0
  98. package/dist/cjs/verify-operation.js +246 -0
  99. package/dist/cjs/verify-operation.js.map +1 -0
  100. package/dist/cjs/wallet-operation.d.ts +52 -0
  101. package/dist/cjs/wallet-operation.js +58 -0
  102. package/dist/cjs/wallet-operation.js.map +1 -0
  103. package/dist/cjs/wasm-provider.d.ts +15 -0
  104. package/dist/cjs/wasm-provider.js +20 -0
  105. package/dist/cjs/wasm-provider.js.map +1 -0
  106. package/dist/cjs/wrapper-operation.d.ts +196 -0
  107. package/dist/cjs/wrapper-operation.js +317 -0
  108. package/dist/cjs/wrapper-operation.js.map +1 -0
  109. package/dist/deploy-operation.d.ts +104 -0
  110. package/dist/deploy-operation.d.ts.map +1 -0
  111. package/dist/deploy-operation.js +327 -0
  112. package/dist/deploy-operation.js.map +1 -0
  113. package/dist/encoding.d.ts +6 -0
  114. package/dist/encoding.d.ts.map +1 -0
  115. package/dist/encoding.js +44 -0
  116. package/dist/encoding.js.map +1 -0
  117. package/dist/engine.d.ts +41 -0
  118. package/dist/engine.d.ts.map +1 -0
  119. package/dist/engine.js +8969 -0
  120. package/dist/engine.js.map +1 -0
  121. package/dist/errors.d.ts +8 -0
  122. package/dist/errors.d.ts.map +1 -0
  123. package/dist/errors.js +18 -0
  124. package/dist/errors.js.map +1 -0
  125. package/dist/fee-ticket-operation.d.ts +205 -0
  126. package/dist/fee-ticket-operation.d.ts.map +1 -0
  127. package/dist/fee-ticket-operation.js +320 -0
  128. package/dist/fee-ticket-operation.js.map +1 -0
  129. package/dist/index.d.ts +28 -0
  130. package/dist/index.d.ts.map +1 -0
  131. package/dist/index.js +28 -0
  132. package/dist/index.js.map +1 -0
  133. package/dist/ladder-limit-orders.d.ts +42 -0
  134. package/dist/ladder-limit-orders.d.ts.map +1 -0
  135. package/dist/ladder-limit-orders.js +121 -0
  136. package/dist/ladder-limit-orders.js.map +1 -0
  137. package/dist/mint-availability-operation.d.ts +57 -0
  138. package/dist/mint-availability-operation.d.ts.map +1 -0
  139. package/dist/mint-availability-operation.js +91 -0
  140. package/dist/mint-availability-operation.js.map +1 -0
  141. package/dist/models.d.ts +91 -0
  142. package/dist/models.d.ts.map +1 -0
  143. package/dist/models.js +3 -0
  144. package/dist/models.js.map +1 -0
  145. package/dist/operations.d.ts +7 -0
  146. package/dist/operations.d.ts.map +1 -0
  147. package/dist/operations.js +36 -0
  148. package/dist/operations.js.map +1 -0
  149. package/dist/paid-mint-amount.d.ts +70 -0
  150. package/dist/paid-mint-amount.d.ts.map +1 -0
  151. package/dist/paid-mint-amount.js +268 -0
  152. package/dist/paid-mint-amount.js.map +1 -0
  153. package/dist/protocol.d.ts +22 -0
  154. package/dist/protocol.d.ts.map +1 -0
  155. package/dist/protocol.js +22 -0
  156. package/dist/protocol.js.map +1 -0
  157. package/dist/runtime.d.ts +28 -0
  158. package/dist/runtime.d.ts.map +1 -0
  159. package/dist/runtime.js +2 -0
  160. package/dist/runtime.js.map +1 -0
  161. package/dist/sale-common.d.ts +288 -0
  162. package/dist/sale-common.d.ts.map +1 -0
  163. package/dist/sale-common.js +844 -0
  164. package/dist/sale-common.js.map +1 -0
  165. package/dist/source-provider.d.ts +12 -0
  166. package/dist/source-provider.d.ts.map +1 -0
  167. package/dist/source-provider.js +2 -0
  168. package/dist/source-provider.js.map +1 -0
  169. package/dist/source-validation.d.ts +10 -0
  170. package/dist/source-validation.d.ts.map +1 -0
  171. package/dist/source-validation.js +28 -0
  172. package/dist/source-validation.js.map +1 -0
  173. package/dist/token-amount.d.ts +32 -0
  174. package/dist/token-amount.d.ts.map +1 -0
  175. package/dist/token-amount.js +237 -0
  176. package/dist/token-amount.js.map +1 -0
  177. package/dist/token-operation.d.ts +136 -0
  178. package/dist/token-operation.d.ts.map +1 -0
  179. package/dist/token-operation.js +231 -0
  180. package/dist/token-operation.js.map +1 -0
  181. package/dist/trade-fee.d.ts +61 -0
  182. package/dist/trade-fee.d.ts.map +1 -0
  183. package/dist/trade-fee.js +173 -0
  184. package/dist/trade-fee.js.map +1 -0
  185. package/dist/trading-operation.d.ts +213 -0
  186. package/dist/trading-operation.d.ts.map +1 -0
  187. package/dist/trading-operation.js +580 -0
  188. package/dist/trading-operation.js.map +1 -0
  189. package/dist/verify-operation.d.ts +80 -0
  190. package/dist/verify-operation.d.ts.map +1 -0
  191. package/dist/verify-operation.js +243 -0
  192. package/dist/verify-operation.js.map +1 -0
  193. package/dist/wallet-operation.d.ts +53 -0
  194. package/dist/wallet-operation.d.ts.map +1 -0
  195. package/dist/wallet-operation.js +55 -0
  196. package/dist/wallet-operation.js.map +1 -0
  197. package/dist/wasm-provider.d.ts +16 -0
  198. package/dist/wasm-provider.d.ts.map +1 -0
  199. package/dist/wasm-provider.js +17 -0
  200. package/dist/wasm-provider.js.map +1 -0
  201. package/dist/wrapper-operation.d.ts +197 -0
  202. package/dist/wrapper-operation.d.ts.map +1 -0
  203. package/dist/wrapper-operation.js +311 -0
  204. package/dist/wrapper-operation.js.map +1 -0
  205. package/index.d.ts +1 -0
  206. package/package.json +84 -0
  207. package/src/abi.ts +493 -0
  208. package/src/action-source-resolver.ts +660 -0
  209. package/src/artifacts.ts +87 -0
  210. package/src/builder.ts +37 -0
  211. package/src/deploy-operation.ts +458 -0
  212. package/src/encoding.ts +58 -0
  213. package/src/engine.ts +13226 -0
  214. package/src/errors.ts +35 -0
  215. package/src/fee-ticket-operation.ts +518 -0
  216. package/src/index.ts +27 -0
  217. package/src/ladder-limit-orders.ts +184 -0
  218. package/src/mint-availability-operation.ts +146 -0
  219. package/src/models.ts +103 -0
  220. package/src/operations.ts +46 -0
  221. package/src/paid-mint-amount.ts +402 -0
  222. package/src/protocol.ts +28 -0
  223. package/src/runtime.ts +29 -0
  224. package/src/sale-common.ts +1238 -0
  225. package/src/source-provider.ts +12 -0
  226. package/src/source-validation.ts +47 -0
  227. package/src/token-amount.ts +302 -0
  228. package/src/token-operation.ts +384 -0
  229. package/src/trade-fee.ts +264 -0
  230. package/src/trading-operation.ts +842 -0
  231. package/src/verify-operation.ts +400 -0
  232. package/src/wallet-operation.ts +86 -0
  233. package/src/wasm-provider.ts +32 -0
  234. package/src/wrapper-operation.ts +531 -0
package/src/abi.ts ADDED
@@ -0,0 +1,493 @@
1
+ /* eslint-disable @typescript-eslint/ban-ts-comment */
2
+ // @ts-nocheck
3
+ import { blake3 } from "@noble/hashes/blake3";
4
+
5
+ function hexBytes(value: string): Uint8Array {
6
+ const hex = value.replace(/^0x/i, "");
7
+ if (!/^(?:[0-9a-f]{2})*$/i.test(hex)) {
8
+ throw new Error("expected an even-length hexadecimal string");
9
+ }
10
+ const bytes = new Uint8Array(hex.length / 2);
11
+ for (let index = 0; index < bytes.length; index += 1) {
12
+ bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
13
+ }
14
+ return bytes;
15
+ }
16
+
17
+ const MAX_I64 = 9_223_372_036_854_775_807n;
18
+ const MIN_I64 = -MAX_I64;
19
+
20
+ export function normalizeSilverScriptArtifact(rawArtifact) {
21
+ const script = rawArtifact?.script ?? rawArtifact?.bytecode;
22
+ if (Array.isArray(script)) {
23
+ return {
24
+ ...rawArtifact,
25
+ script: Array.from(script, Number),
26
+ bytecode: Array.from(rawArtifact?.bytecode ?? script, Number),
27
+ without_selector: false,
28
+ };
29
+ }
30
+
31
+ const portable = normalizePortableSilverScriptArtifact(rawArtifact);
32
+ if (portable) return portable;
33
+
34
+ throw new Error(
35
+ `${rawArtifact?.contract_name || "contract"} artifact is missing compiled bytecode`,
36
+ );
37
+ }
38
+
39
+ function normalizePortableSilverScriptArtifact(rawArtifact) {
40
+ if (
41
+ rawArtifact?.schema_version !== 1 ||
42
+ !rawArtifact?.contracts ||
43
+ typeof rawArtifact.contracts !== "object"
44
+ ) {
45
+ return null;
46
+ }
47
+
48
+ const entries = Object.entries(rawArtifact.contracts);
49
+ if (entries.length !== 1) {
50
+ throw new Error(
51
+ "portable SilverScript artifact must contain exactly one contract",
52
+ );
53
+ }
54
+
55
+ const [contractName, contract] = entries[0];
56
+ const script = contract?.compiled?.bytecode;
57
+ const stateSpan = contract?.compiled?.state_span;
58
+ if (!Array.isArray(script)) {
59
+ throw new Error(
60
+ `${rawArtifact?.contract_name || "contract"} artifact is missing compiled bytecode`,
61
+ );
62
+ }
63
+
64
+ const abi = Object.entries(contract.entries || {}).map(([name, entry]) => ({
65
+ name,
66
+ inputs: (entry.params || []).map((param) => ({
67
+ name: param.name,
68
+ type_name: portableTypeName(param.type),
69
+ })),
70
+ dispatch_tag: entry.dispatch_tag,
71
+ }));
72
+
73
+ return {
74
+ ...rawArtifact,
75
+ contract_name: contractName,
76
+ bytecode: Array.from(script, Number),
77
+ script: Array.from(script, Number),
78
+ state_layout: {
79
+ start: stateSpan?.offset,
80
+ len: stateSpan?.len,
81
+ },
82
+ abi,
83
+ without_selector: false,
84
+ };
85
+ }
86
+
87
+ function portableTypeName(type) {
88
+ if (!type?.kind) throw new Error("portable ABI param is missing type kind");
89
+ switch (type.kind) {
90
+ case "bool":
91
+ case "byte":
92
+ case "int":
93
+ case "pubkey":
94
+ case "sig":
95
+ case "datasig":
96
+ return type.kind;
97
+ case "bytes":
98
+ return "byte[]";
99
+ case "fixed_bytes":
100
+ return `byte[${type.len}]`;
101
+ case "dynamic_array":
102
+ return `${portableTypeName(type.item)}[]`;
103
+ case "fixed_array":
104
+ return `${portableTypeName(type.item)}[${type.len}]`;
105
+ case "struct":
106
+ return type.name;
107
+ default:
108
+ throw new Error(`unsupported portable ABI type kind: ${type.kind}`);
109
+ }
110
+ }
111
+
112
+ export function canonicalFunctionSignature(abiEntry) {
113
+ if (!abiEntry?.name || !Array.isArray(abiEntry.inputs)) {
114
+ throw new Error("invalid KCC1 ABI entry");
115
+ }
116
+ return `${abiEntry.name}(${abiEntry.inputs.map((input) => input.type_name).join(",")})`;
117
+ }
118
+
119
+ export function dispatchTag(abiEntry) {
120
+ return blake3(
121
+ new TextEncoder().encode(canonicalFunctionSignature(abiEntry)),
122
+ ).slice(0, 4);
123
+ }
124
+
125
+ export function dispatchTagFor(artifact, entrypointName) {
126
+ const entry = artifact?.abi?.find(
127
+ (candidate) => candidate.name === entrypointName,
128
+ );
129
+ if (!entry)
130
+ throw new Error(`artifact is missing ${entrypointName} ABI entry`);
131
+ if (
132
+ typeof entry.dispatch_tag === "string" &&
133
+ /^[0-9a-fA-F]{8}$/.test(entry.dispatch_tag)
134
+ ) {
135
+ return hexBytes(entry.dispatch_tag);
136
+ }
137
+ return dispatchTag(entry);
138
+ }
139
+
140
+ export function templateHash(prefix, suffix) {
141
+ return blake3(
142
+ concatBytes(
143
+ unsignedLe64(BigInt(prefix.length)),
144
+ Uint8Array.from(prefix),
145
+ unsignedLe64(BigInt(suffix.length)),
146
+ Uint8Array.from(suffix),
147
+ ),
148
+ );
149
+ }
150
+
151
+ export function templateParts(artifact) {
152
+ const normalized = normalizeSilverScriptArtifact(artifact);
153
+ const script = Uint8Array.from(normalized.script);
154
+ const start = normalized.state_layout?.start;
155
+ const length = normalized.state_layout?.len;
156
+ if (
157
+ !Number.isInteger(start) ||
158
+ !Number.isInteger(length) ||
159
+ start < 0 ||
160
+ length < 0 ||
161
+ start + length > script.length
162
+ ) {
163
+ throw new Error(
164
+ `${normalized.contract_name || "contract"} artifact has invalid state_layout`,
165
+ );
166
+ }
167
+ const prefix = script.slice(0, start);
168
+ const suffix = script.slice(start + length);
169
+ return {
170
+ prefix,
171
+ suffix,
172
+ prefixLength: prefix.length,
173
+ suffixLength: suffix.length,
174
+ hash: templateHash(prefix, suffix),
175
+ };
176
+ }
177
+
178
+ export function mintExtensionCommitment(extension) {
179
+ const { kind = 1, remainingSupply, publicMintActive } = extension;
180
+ const kindValue = Number(kind);
181
+ if (!Number.isInteger(kindValue) || kindValue < 0 || kindValue > 255)
182
+ throw new Error("mint extension kind must be a byte");
183
+ return blake3(
184
+ concatBytes(
185
+ Uint8Array.of(kindValue),
186
+ requireBytes(extension.creator, 32, "creator"),
187
+ requireBytes(extension.ticker, 32, "ticker"),
188
+ requireBytes(extension.name, 32, "name"),
189
+ signedI64Payload(BigInt(extension.displayScale)),
190
+ signedI64Payload(BigInt(extension.maxSupply)),
191
+ signedI64Payload(BigInt(extension.mintLaneCount ?? 1)),
192
+ Uint8Array.of(requireByte(extension.mintPolicy, "mintPolicy")),
193
+ signedI64Payload(BigInt(extension.mintPriceSompi)),
194
+ requireBytes(extension.treasury, 32, "treasury"),
195
+ requireBytes(extension.protocolFeeRecipient, 32, "protocolFeeRecipient"),
196
+ signedI64Payload(BigInt(extension.protocolFeeBps)),
197
+ signedI64Payload(BigInt(remainingSupply)),
198
+ Uint8Array.of(publicMintActive ? 1 : 0),
199
+ requireBytes(
200
+ extension.holderExtensionCommitment,
201
+ 32,
202
+ "holderExtensionCommitment",
203
+ ),
204
+ ),
205
+ );
206
+ }
207
+
208
+ export function holderExtensionCommitment(extension) {
209
+ const { kind = 1 } = extension;
210
+ return blake3(
211
+ concatBytes(
212
+ new TextEncoder().encode("KASPACOM/KCC20/HOLDER/V1"),
213
+ Uint8Array.of(requireByte(kind, "kind")),
214
+ requireBytes(extension.creator, 32, "creator"),
215
+ requireBytes(extension.ticker, 32, "ticker"),
216
+ requireBytes(extension.name, 32, "name"),
217
+ signedI64Payload(BigInt(extension.displayScale)),
218
+ signedI64Payload(BigInt(extension.maxSupply)),
219
+ signedI64Payload(BigInt(extension.mintLaneCount ?? 1)),
220
+ Uint8Array.of(requireByte(extension.mintPolicy, "mintPolicy")),
221
+ signedI64Payload(BigInt(extension.mintPriceSompi)),
222
+ requireBytes(extension.treasury, 32, "treasury"),
223
+ requireBytes(extension.protocolFeeRecipient, 32, "protocolFeeRecipient"),
224
+ signedI64Payload(BigInt(extension.protocolFeeBps)),
225
+ ),
226
+ );
227
+ }
228
+
229
+ export function buildKcc20ScriptForState(artifact, state) {
230
+ const normalized = normalizeSilverScriptArtifact(artifact);
231
+ const script = Uint8Array.from(normalized.script);
232
+ const start = normalized.state_layout?.start;
233
+ const length = normalized.state_layout?.len;
234
+ const encodedState = encodeKcc20State(state);
235
+ if (encodedState.length !== length) {
236
+ throw new Error(
237
+ `KCC20 encoded state is ${encodedState.length} bytes, artifact requires ${length}`,
238
+ );
239
+ }
240
+ return concatBytes(
241
+ script.slice(0, start),
242
+ encodedState,
243
+ script.slice(start + length),
244
+ );
245
+ }
246
+
247
+ export function encodeKcc20State(state) {
248
+ return concatBytes(
249
+ pushExplicit(signedI64Payload(BigInt(state.amount))),
250
+ pushExplicit(requireBytes(state.owner, 32, "owner")),
251
+ pushExplicit(Uint8Array.of(requireByte(state.ownerScheme, "ownerScheme"))),
252
+ pushExplicit(
253
+ Uint8Array.of(requireByte(state.borrowScheme, "borrowScheme")),
254
+ ),
255
+ pushExplicit(requireBytes(state.borrowGuard, 32, "borrowGuard")),
256
+ pushExplicit(
257
+ requireBytes(state.extensionCommitment, 32, "extensionCommitment"),
258
+ ),
259
+ );
260
+ }
261
+
262
+ export function encodeKcc20StateRecordArrays(states) {
263
+ if (!Array.isArray(states)) throw new Error("KCC20 states must be an array");
264
+ return [
265
+ concatBytes(
266
+ ...states.map((state) => signedI64Payload(BigInt(state.amount))),
267
+ ),
268
+ concatBytes(
269
+ ...states.map((state) => requireBytes(state.owner, 32, "owner")),
270
+ ),
271
+ Uint8Array.from(
272
+ states.map((state) => requireByte(state.ownerScheme, "ownerScheme")),
273
+ ),
274
+ Uint8Array.from(
275
+ states.map((state) => requireByte(state.borrowScheme, "borrowScheme")),
276
+ ),
277
+ concatBytes(
278
+ ...states.map((state) =>
279
+ requireBytes(state.borrowGuard, 32, "borrowGuard"),
280
+ ),
281
+ ),
282
+ concatBytes(
283
+ ...states.map((state) =>
284
+ requireBytes(state.extensionCommitment, 32, "extensionCommitment"),
285
+ ),
286
+ ),
287
+ ];
288
+ }
289
+
290
+ export function buildKcc20TransferSigScript(
291
+ kw,
292
+ artifact,
293
+ { nextStates, witness },
294
+ ) {
295
+ const builder = new kw.ScriptBuilder();
296
+ addKcc20StateRecordArrays(builder, nextStates);
297
+ builder.addData(Uint8Array.from(witness));
298
+ builder.addData(dispatchTagFor(artifact, "transfer"));
299
+ return builder.drain();
300
+ }
301
+
302
+ export function buildKcc20TransferDelegatorSigScript(
303
+ kw,
304
+ artifact,
305
+ { witness },
306
+ ) {
307
+ const builder = new kw.ScriptBuilder();
308
+ builder.addData(Uint8Array.from(witness));
309
+ builder.addData(dispatchTagFor(artifact, "transfer_delegator"));
310
+ return builder.drain();
311
+ }
312
+
313
+ export function buildKcc20MintByOwnerSigScript(kw, artifact, args) {
314
+ const builder = new kw.ScriptBuilder();
315
+ addKcc20MintExtension(builder, args.extension);
316
+ builder.addData(Uint8Array.from(args.authoritySignature));
317
+ addMintDestination(builder, args);
318
+ builder.addData(dispatchTagFor(artifact, "mint_by_owner"));
319
+ return builder.drain();
320
+ }
321
+
322
+ export function buildKcc20MintPublicSigScript(kw, artifact, args) {
323
+ const builder = new kw.ScriptBuilder();
324
+ addKcc20MintExtension(builder, args.extension);
325
+ addMintDestination(builder, args);
326
+ builder.addData(dispatchTagFor(artifact, "mint_public"));
327
+ return builder.drain();
328
+ }
329
+
330
+ export function buildKcc20BurnSigScript(
331
+ kw,
332
+ artifact,
333
+ { nextStates, burnAmount, witness },
334
+ ) {
335
+ const builder = new kw.ScriptBuilder();
336
+ addKcc20StateRecordArrays(builder, nextStates);
337
+ builder.addI64(BigInt(burnAmount));
338
+ builder.addData(Uint8Array.from(witness));
339
+ builder.addData(dispatchTagFor(artifact, "burn"));
340
+ return builder.drain();
341
+ }
342
+
343
+ export function buildKcc20SetPublicMintActiveSigScript(
344
+ kw,
345
+ artifact,
346
+ { extension, authoritySignature, active, minterOutputIndex },
347
+ ) {
348
+ const builder = new kw.ScriptBuilder();
349
+ addKcc20MintExtension(builder, extension);
350
+ builder.addData(Uint8Array.from(authoritySignature));
351
+ builder.addI64(active ? 1n : 0n);
352
+ builder.addI64(BigInt(minterOutputIndex));
353
+ builder.addData(dispatchTagFor(artifact, "set_public_mint_active"));
354
+ return builder.drain();
355
+ }
356
+
357
+ export function p2pkOwnerWitness(signature) {
358
+ const bytes = Uint8Array.from(signature);
359
+ if (bytes.length !== 65)
360
+ throw new Error("P2PK Schnorr signature must be 65 bytes");
361
+ return ownerAuthorizationWitness(bytes);
362
+ }
363
+
364
+ export function ownerAuthorizationWitness(witness) {
365
+ return concatBytes(Uint8Array.of(0), Uint8Array.from(witness));
366
+ }
367
+
368
+ function addKcc20StateRecordArrays(builder, states) {
369
+ for (const encodedField of encodeKcc20StateRecordArrays(states))
370
+ builder.addData(encodedField);
371
+ }
372
+
373
+ function addKcc20MintExtension(builder, extension) {
374
+ addExplicitByte(builder, extension.kind ?? 1, "mint extension kind");
375
+ builder.addData(requireBytes(extension.creator, 32, "creator"));
376
+ builder.addData(requireBytes(extension.ticker, 32, "ticker"));
377
+ builder.addData(requireBytes(extension.name, 32, "name"));
378
+ builder.addI64(BigInt(extension.displayScale));
379
+ builder.addI64(BigInt(extension.maxSupply));
380
+ builder.addI64(BigInt(extension.mintLaneCount ?? 1));
381
+ addExplicitByte(builder, extension.mintPolicy, "mintPolicy");
382
+ builder.addI64(BigInt(extension.mintPriceSompi));
383
+ builder.addData(requireBytes(extension.treasury, 32, "treasury"));
384
+ builder.addData(
385
+ requireBytes(extension.protocolFeeRecipient, 32, "protocolFeeRecipient"),
386
+ );
387
+ builder.addI64(BigInt(extension.protocolFeeBps));
388
+ builder.addI64(BigInt(extension.remainingSupply));
389
+ builder.addI64(extension.publicMintActive ? 1n : 0n);
390
+ builder.addData(
391
+ requireBytes(
392
+ extension.holderExtensionCommitment,
393
+ 32,
394
+ "holderExtensionCommitment",
395
+ ),
396
+ );
397
+ }
398
+
399
+ function addMintDestination(builder, args) {
400
+ builder.addData(requireBytes(args.toOwner, 32, "toOwner"));
401
+ addExplicitByte(builder, args.toOwnerScheme, "toOwnerScheme");
402
+ addExplicitByte(builder, args.toBorrowScheme, "toBorrowScheme");
403
+ builder.addData(requireBytes(args.toBorrowGuard, 32, "toBorrowGuard"));
404
+ builder.addI64(BigInt(args.tokenAmount));
405
+ builder.addI64(BigInt(args.tokenOutputIndex));
406
+ builder.addI64(BigInt(args.minterOutputIndex));
407
+ builder.addI64(BigInt(args.treasuryOutputIndex));
408
+ builder.addI64(BigInt(args.feeOutputIndex));
409
+ }
410
+
411
+ function addExplicitByte(builder, value, label) {
412
+ const byte = requireByte(value, label);
413
+ builder.addData(Uint8Array.of(byte));
414
+ }
415
+
416
+ export function signedI64Payload(value) {
417
+ const n = BigInt(value);
418
+ if (n < MIN_I64 || n > MAX_I64)
419
+ throw new Error(`KCC1 int is outside signed 64-bit range: ${n}`);
420
+ const negative = n < 0n;
421
+ let magnitude = negative ? -n : n;
422
+ const out = new Uint8Array(8);
423
+ for (let i = 0; i < out.length; i++) {
424
+ out[i] = Number(magnitude & 0xffn);
425
+ magnitude >>= 8n;
426
+ }
427
+ if (negative) out[7] |= 0x80;
428
+ return out;
429
+ }
430
+
431
+ export function unsignedLe64(value) {
432
+ let n = BigInt(value);
433
+ if (n < 0n || n > 0xffff_ffff_ffff_ffffn) {
434
+ throw new Error(`KCC1 length is outside unsigned 64-bit range: ${n}`);
435
+ }
436
+ const out = new Uint8Array(8);
437
+ for (let i = 0; i < out.length; i++) {
438
+ out[i] = Number(n & 0xffn);
439
+ n >>= 8n;
440
+ }
441
+ return out;
442
+ }
443
+
444
+ export function pushExplicit(payload) {
445
+ const bytes = Uint8Array.from(payload);
446
+ if (bytes.length === 0) return Uint8Array.of(0x00);
447
+ if (bytes.length <= 75)
448
+ return concatBytes(Uint8Array.of(bytes.length), bytes);
449
+ if (bytes.length <= 0xff)
450
+ return concatBytes(Uint8Array.of(0x4c, bytes.length), bytes);
451
+ if (bytes.length <= 0xffff) {
452
+ return concatBytes(
453
+ Uint8Array.of(0x4d, bytes.length & 0xff, bytes.length >> 8),
454
+ bytes,
455
+ );
456
+ }
457
+ throw new Error(`explicit payload is too large: ${bytes.length}`);
458
+ }
459
+
460
+ export function concatBytes(...parts) {
461
+ const length = parts.reduce((sum, part) => sum + part.length, 0);
462
+ const out = new Uint8Array(length);
463
+ let offset = 0;
464
+ for (const part of parts) {
465
+ out.set(part, offset);
466
+ offset += part.length;
467
+ }
468
+ return out;
469
+ }
470
+
471
+ function requireByte(value, label) {
472
+ const parsed = Number(value);
473
+ if (!Number.isInteger(parsed) || parsed < 0 || parsed > 255)
474
+ throw new Error(`${label} must be a byte`);
475
+ return parsed;
476
+ }
477
+
478
+ function requireBytes(value, length, label) {
479
+ const bytes =
480
+ typeof value === "string"
481
+ ? hexBytes(value)
482
+ : value instanceof Uint8Array
483
+ ? value
484
+ : Array.isArray(value)
485
+ ? Uint8Array.from(value)
486
+ : null;
487
+ if (!bytes) {
488
+ throw new Error(`${label} must be ${length} bytes or hex`);
489
+ }
490
+ if (bytes.length !== length)
491
+ throw new Error(`${label} must be ${length} bytes`);
492
+ return bytes;
493
+ }