@ouronet/ouronet-core 4.3.6

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 (101) hide show
  1. package/CHANGELOG.md +3043 -0
  2. package/README.md +1940 -0
  3. package/dist/codex/codec.d.ts +77 -0
  4. package/dist/codex/codec.js +123 -0
  5. package/dist/codex/errors.d.ts +14 -0
  6. package/dist/codex/errors.js +20 -0
  7. package/dist/codex/index.d.ts +27 -0
  8. package/dist/codex/index.js +25 -0
  9. package/dist/codex/seedTypeMigration.d.ts +35 -0
  10. package/dist/codex/seedTypeMigration.js +45 -0
  11. package/dist/codex/types.d.ts +100 -0
  12. package/dist/codex/types.js +19 -0
  13. package/dist/constants/index.d.ts +2 -0
  14. package/dist/constants/index.js +3 -0
  15. package/dist/constants/ouronet.d.ts +33 -0
  16. package/dist/constants/ouronet.js +59 -0
  17. package/dist/constants/tokenIds.d.ts +13 -0
  18. package/dist/constants/tokenIds.js +21 -0
  19. package/dist/index.d.ts +18 -0
  20. package/dist/index.js +1 -0
  21. package/dist/interactions/activateFunctions.d.ts +67 -0
  22. package/dist/interactions/activateFunctions.js +154 -0
  23. package/dist/interactions/addLiquidityFunctions.d.ts +140 -0
  24. package/dist/interactions/addLiquidityFunctions.js +485 -0
  25. package/dist/interactions/coilFunctions.d.ts +73 -0
  26. package/dist/interactions/coilFunctions.js +213 -0
  27. package/dist/interactions/crossChainFunctions.d.ts +211 -0
  28. package/dist/interactions/crossChainFunctions.js +463 -0
  29. package/dist/interactions/dexAcquisitionPoolFunctions.d.ts +18 -0
  30. package/dist/interactions/dexAcquisitionPoolFunctions.js +18 -0
  31. package/dist/interactions/dexCollectablesFunctions.d.ts +28 -0
  32. package/dist/interactions/dexCollectablesFunctions.js +227 -0
  33. package/dist/interactions/dexFunctions.d.ts +23 -0
  34. package/dist/interactions/dexFunctions.js +23 -0
  35. package/dist/interactions/dexOrtoFungibleFunctions.d.ts +33 -0
  36. package/dist/interactions/dexOrtoFungibleFunctions.js +171 -0
  37. package/dist/interactions/dexParseFunctions.d.ts +150 -0
  38. package/dist/interactions/dexParseFunctions.js +316 -0
  39. package/dist/interactions/dexSwapPairAdminFunctions.d.ts +75 -0
  40. package/dist/interactions/dexSwapPairAdminFunctions.js +255 -0
  41. package/dist/interactions/dexSwapPairCalcFunctions.d.ts +55 -0
  42. package/dist/interactions/dexSwapPairCalcFunctions.js +218 -0
  43. package/dist/interactions/dexSwapPairDashboardFunctions.d.ts +47 -0
  44. package/dist/interactions/dexSwapPairDashboardFunctions.js +179 -0
  45. package/dist/interactions/dexSwapPairExecuteFunctions.d.ts +40 -0
  46. package/dist/interactions/dexSwapPairExecuteFunctions.js +301 -0
  47. package/dist/interactions/dexSwapPairSmartSwapFunctions.d.ts +25 -0
  48. package/dist/interactions/dexSwapPairSmartSwapFunctions.js +166 -0
  49. package/dist/interactions/dexTrueFungibleFunctions.d.ts +52 -0
  50. package/dist/interactions/dexTrueFungibleFunctions.js +220 -0
  51. package/dist/interactions/dexTypes.d.ts +465 -0
  52. package/dist/interactions/dexTypes.js +6 -0
  53. package/dist/interactions/errors.d.ts +12 -0
  54. package/dist/interactions/errors.js +13 -0
  55. package/dist/interactions/guardFunctions.d.ts +33 -0
  56. package/dist/interactions/guardFunctions.js +110 -0
  57. package/dist/interactions/index.d.ts +1 -0
  58. package/dist/interactions/index.js +20 -0
  59. package/dist/interactions/infoOneFunctions.d.ts +133 -0
  60. package/dist/interactions/infoOneFunctions.js +566 -0
  61. package/dist/interactions/kadenaFunctions.d.ts +11 -0
  62. package/dist/interactions/kadenaFunctions.js +40 -0
  63. package/dist/interactions/kpayFunctions.d.ts +45 -0
  64. package/dist/interactions/kpayFunctions.js +191 -0
  65. package/dist/interactions/ouroAccountFunctions.d.ts +64 -0
  66. package/dist/interactions/ouroAccountFunctions.js +229 -0
  67. package/dist/interactions/ouroBalanceFunctions.d.ts +39 -0
  68. package/dist/interactions/ouroBalanceFunctions.js +100 -0
  69. package/dist/interactions/ouroCoilFunctions.d.ts +33 -0
  70. package/dist/interactions/ouroCoilFunctions.js +190 -0
  71. package/dist/interactions/ouroFunctions.d.ts +23 -0
  72. package/dist/interactions/ouroFunctions.js +23 -0
  73. package/dist/interactions/ouroMovieBoosterFunctions.d.ts +18 -0
  74. package/dist/interactions/ouroMovieBoosterFunctions.js +203 -0
  75. package/dist/interactions/ouroPriceFunctions.d.ts +38 -0
  76. package/dist/interactions/ouroPriceFunctions.js +96 -0
  77. package/dist/interactions/ouroPrimordialsFunctions.d.ts +10 -0
  78. package/dist/interactions/ouroPrimordialsFunctions.js +480 -0
  79. package/dist/interactions/ouroRotateFunctions.d.ts +22 -0
  80. package/dist/interactions/ouroRotateFunctions.js +114 -0
  81. package/dist/interactions/ouroSubCompressFunctions.d.ts +23 -0
  82. package/dist/interactions/ouroSubCompressFunctions.js +191 -0
  83. package/dist/interactions/ouroTransferFunctions.d.ts +14 -0
  84. package/dist/interactions/ouroTransferFunctions.js +87 -0
  85. package/dist/interactions/ouroTypes.d.ts +113 -0
  86. package/dist/interactions/ouroTypes.js +6 -0
  87. package/dist/interactions/ouroUrStoaFunctions.d.ts +16 -0
  88. package/dist/interactions/ouroUrStoaFunctions.js +121 -0
  89. package/dist/interactions/ouroWrapFunctions.d.ts +22 -0
  90. package/dist/interactions/ouroWrapFunctions.js +234 -0
  91. package/dist/interactions/pensionFunctions.d.ts +12 -0
  92. package/dist/interactions/pensionFunctions.js +127 -0
  93. package/dist/interactions/urStoaFunctions.d.ts +104 -0
  94. package/dist/interactions/urStoaFunctions.js +475 -0
  95. package/dist/interactions/wrapFunctions.d.ts +46 -0
  96. package/dist/interactions/wrapFunctions.js +221 -0
  97. package/dist/pact/cfmBuilders.d.ts +807 -0
  98. package/dist/pact/cfmBuilders.js +812 -0
  99. package/dist/pact/index.d.ts +1 -0
  100. package/dist/pact/index.js +10 -0
  101. package/package.json +64 -0
@@ -0,0 +1,812 @@
1
+ /**
2
+ * CFM Pact-code builders — string construction for every Pact function
3
+ * the 23 OuronetUI CFM modals call.
4
+ *
5
+ * Background. Each CFM modal builds a Pact-code string like
6
+ * `(ouronet-ns.TS01-C2.ATS|C_Coil "<patron>" "<coiler>" "<ats>" "<rt>" <amount>)`
7
+ * and hands it to `strategy.execute({ build })`. Historically these
8
+ * strings lived inside the modal as a template literal — convenient
9
+ * but impossible to test without rendering the React component, so
10
+ * a typo (`C_Coyl`, missing quote, wrong namespace) only surfaced
11
+ * when a user clicked the button and the chain rejected the tx.
12
+ *
13
+ * This module extracts each Pact-function-specific string builder
14
+ * into a pure function. Modals import the builder and pass the
15
+ * returned string to `Pact.builder.execution(...)`. Tests in
16
+ * `tests/cfm-builders.test.ts` verify every builder produces the
17
+ * exact expected shape for a canonical input set.
18
+ *
19
+ * No React, no @kadena/client, no crypto. Just string templating
20
+ * with `formatDecimalForPact` for the amount fields. Works on
21
+ * Node + browser + any JS environment.
22
+ *
23
+ * Naming convention. Each builder is `buildX_PactCode(params)`
24
+ * where `X` is the Pact function name (C_Coil, C_Transfer, etc.).
25
+ * Return type is always `string`.
26
+ *
27
+ * All Pact function names the ecosystem currently ships are covered.
28
+ * When a new CFM modal lands, add its builder here + a test; don't
29
+ * inline the Pact code in the modal.
30
+ */
31
+ import { KADENA_NAMESPACE } from "../constants/index.js";
32
+ import { formatDecimalForPact } from "@stoachain/stoa-core/pact";
33
+ // ─── TS01-C1 family (DPTF — Dynamic Pooled Token Functions) ──────────────────
34
+ /**
35
+ * Transfer. The most-called CFM function across the UI — all 9
36
+ * Transfer* modals emit this shape, differing only in token-id.
37
+ *
38
+ * (ouronet-ns.TS01-C1.DPTF|C_Transfer
39
+ * <patron> <token-id> <sender> <receiver> <amount:decimal> <method:bool>)
40
+ *
41
+ * `method` is `false` for standard accounts and `true` for smart
42
+ * accounts. `amount` is formatted to `x.y` decimal form.
43
+ */
44
+ export function buildTransferPactCode(p) {
45
+ const dec = formatDecimalForPact(p.amount);
46
+ return `(${KADENA_NAMESPACE}.TS01-C1.DPTF|C_Transfer "${p.patron}" "${p.tokenId}" "${p.sender}" "${p.receiver}" ${dec} ${p.method})`;
47
+ }
48
+ /**
49
+ * Clear Ouroboros Dispo. Triggered when a resident has negative virtual
50
+ * OURO; this zeroes the dispo by burning from the patron.
51
+ *
52
+ * (ouronet-ns.TS01-C1.DPTF|C_ClearDispo <patron> <account>)
53
+ */
54
+ export function buildClearDispoPactCode(p) {
55
+ return `(${KADENA_NAMESPACE}.TS01-C1.DPTF|C_ClearDispo "${p.patron}" "${p.account}")`;
56
+ }
57
+ // ─── TS01-C2.ORBR family (Ouroboros) ─────────────────────────────────────────
58
+ /**
59
+ * Sublimate OURO → IGNIS. Patronless (gasless for the user —
60
+ * STOA_AUTONOMIC_OURONETGASSTATION pays the chain gas). `target` is
61
+ * usually the same as `client` (self-sublimate) but can be another
62
+ * account for gift-style flows.
63
+ *
64
+ * (ouronet-ns.TS01-C2.ORBR|C_Sublimate <client> <target> <amount:decimal>)
65
+ */
66
+ export function buildSublimatePactCode(p) {
67
+ const dec = formatDecimalForPact(p.amount);
68
+ return `(${KADENA_NAMESPACE}.TS01-C2.ORBR|C_Sublimate "${p.client}" "${p.target}" ${dec})`;
69
+ }
70
+ /**
71
+ * Compress IGNIS → OURO. Patronless, integer-valued amount only.
72
+ * `formatDecimalForPact` still runs on the amount string because the
73
+ * Pact `decimal` lexer rejects bare integers.
74
+ *
75
+ * (ouronet-ns.TS01-C2.ORBR|C_Compress <client> <ignis-amount:decimal>)
76
+ */
77
+ export function buildCompressPactCode(p) {
78
+ const dec = formatDecimalForPact(p.ignisAmount);
79
+ return `(${KADENA_NAMESPACE}.TS01-C2.ORBR|C_Compress "${p.client}" ${dec})`;
80
+ }
81
+ // ─── TS01-C2.ATS family (Autostake Pools) ────────────────────────────────────
82
+ /**
83
+ * Coil — deposit reward-token into an autostake pool.
84
+ *
85
+ * (ouronet-ns.TS01-C2.ATS|C_Coil
86
+ * <patron> <coiler> <ats> <rt> <amount:decimal>)
87
+ */
88
+ export function buildCoilPactCode(p) {
89
+ const dec = formatDecimalForPact(p.amount);
90
+ return `(${KADENA_NAMESPACE}.TS01-C2.ATS|C_Coil "${p.patron}" "${p.coiler}" "${p.atsId}" "${p.rewardTokenId}" ${dec})`;
91
+ }
92
+ /**
93
+ * Curl — deposit reward-token through TWO autostake pools (e.g. OURO
94
+ * through Auryndex + EliteAuryndex in one call).
95
+ *
96
+ * (ouronet-ns.TS01-C2.ATS|C_Curl
97
+ * <patron> <curler> <ats1> <ats2> <rt> <amount:decimal>)
98
+ */
99
+ export function buildCurlPactCode(p) {
100
+ const dec = formatDecimalForPact(p.amount);
101
+ return `(${KADENA_NAMESPACE}.TS01-C2.ATS|C_Curl "${p.patron}" "${p.curler}" "${p.ats1Id}" "${p.ats2Id}" "${p.rewardTokenId}" ${dec})`;
102
+ }
103
+ /**
104
+ * Brumate — locked Curl. Same shape as Curl plus a `dayz` lock-period
105
+ * integer.
106
+ *
107
+ * (ouronet-ns.TS01-C2.ATS|C_Brumate
108
+ * <patron> <brumator> <ats1> <ats2> <rt> <amount:decimal> <dayz:integer>)
109
+ */
110
+ export function buildBrumatePactCode(p) {
111
+ const dec = formatDecimalForPact(p.amount);
112
+ return `(${KADENA_NAMESPACE}.TS01-C2.ATS|C_Brumate "${p.patron}" "${p.brumator}" "${p.ats1Id}" "${p.ats2Id}" "${p.rewardTokenId}" ${dec} ${p.lockDays})`;
113
+ }
114
+ /**
115
+ * Constrict — locked Coil. Same shape as Coil plus a `dayz` lock-period
116
+ * integer.
117
+ *
118
+ * (ouronet-ns.TS01-C2.ATS|C_Constrict
119
+ * <patron> <constricter> <ats> <rt> <amount:decimal> <dayz:integer>)
120
+ */
121
+ export function buildConstrictPactCode(p) {
122
+ const dec = formatDecimalForPact(p.amount);
123
+ return `(${KADENA_NAMESPACE}.TS01-C2.ATS|C_Constrict "${p.patron}" "${p.constricter}" "${p.atsId}" "${p.rewardTokenId}" ${dec} ${p.lockDays})`;
124
+ }
125
+ /**
126
+ * Cold recovery — withdraw from an autostake pool with the full lockout
127
+ * reward schedule.
128
+ *
129
+ * (ouronet-ns.TS01-C2.ATS|C_ColdRecovery
130
+ * <patron> <recoverer> <ats> <ra:decimal>)
131
+ */
132
+ export function buildColdRecoveryPactCode(p) {
133
+ const dec = formatDecimalForPact(p.ra);
134
+ return `(${KADENA_NAMESPACE}.TS01-C2.ATS|C_ColdRecovery "${p.patron}" "${p.recoverer}" "${p.atsId}" ${dec})`;
135
+ }
136
+ /**
137
+ * Direct recovery — withdraw immediately with the smaller non-lockout
138
+ * reward.
139
+ *
140
+ * (ouronet-ns.TS01-C2.ATS|C_DirectRecovery
141
+ * <patron> <recoverer> <ats> <ra:decimal>)
142
+ */
143
+ export function buildDirectRecoveryPactCode(p) {
144
+ const dec = formatDecimalForPact(p.ra);
145
+ return `(${KADENA_NAMESPACE}.TS01-C2.ATS|C_DirectRecovery "${p.patron}" "${p.recoverer}" "${p.atsId}" ${dec})`;
146
+ }
147
+ /**
148
+ * Cull — harvest rewards from a single autostake pool position.
149
+ *
150
+ * (ouronet-ns.TS01-C2.ATS|C_Cull <patron> <culler> <ats>)
151
+ */
152
+ export function buildCullPactCode(p) {
153
+ return `(${KADENA_NAMESPACE}.TS01-C2.ATS|C_Cull "${p.patron}" "${p.culler}" "${p.atsId}")`;
154
+ }
155
+ // ─── TS01-C2.VST family (Virtual Stoa Tokens — GSTOA hibernation) ────────────
156
+ /**
157
+ * Awake — wake a hibernated GSTOA nonce.
158
+ *
159
+ * (ouronet-ns.TS01-C2.VST|C_Awake
160
+ * <patron> <awaker> <dpof> <nonce:integer>)
161
+ */
162
+ export function buildAwakePactCode(p) {
163
+ return `(${KADENA_NAMESPACE}.TS01-C2.VST|C_Awake "${p.patron}" "${p.awaker}" "${p.dpof}" ${p.nonce})`;
164
+ }
165
+ /**
166
+ * Slumber — hibernate one or more GSTOA nonces. The `nonces` list is
167
+ * rendered as Pact's `[n1 n2 n3]` integer-list literal.
168
+ *
169
+ * (ouronet-ns.TS01-C2.VST|C_Slumber
170
+ * <patron> <merger> <dpof> <nonces:[integer]>)
171
+ */
172
+ export function buildSlumberPactCode(p) {
173
+ const nonceList = `[${p.nonces.join(" ")}]`;
174
+ return `(${KADENA_NAMESPACE}.TS01-C2.VST|C_Slumber "${p.patron}" "${p.merger}" "${p.dpof}" ${nonceList})`;
175
+ }
176
+ // ─── TS01-C2.LQD family (Wrap / Unwrap of native STOA + UrStoa) ──────────────
177
+ /**
178
+ * Wrap STOA — convert native STOA → wSTOA. Payment key signs `coin.TRANSFER`
179
+ * to LIQUIDPOT for the wrapped amount; patron + wrapper guards sign pure.
180
+ *
181
+ * (ouronet-ns.TS01-C2.LQD|C_WrapStoa <patron> <wrapper> <amount:decimal>)
182
+ *
183
+ * `amount` is formatted via `formatDecimalForPact` (validates `/^\d+\.?\d*$/`
184
+ * and pads decimal — closes the F-SEC-001 Pact-code injection vector by
185
+ * making the field a clean numeric literal).
186
+ */
187
+ export function buildWrapStoaPactCode(p) {
188
+ const dec = formatDecimalForPact(p.amount);
189
+ return `(${KADENA_NAMESPACE}.TS01-C2.LQD|C_WrapStoa "${p.patron}" "${p.wrapper}" ${dec})`;
190
+ }
191
+ /**
192
+ * Wrap UrStoa — convert native UrStoa → wSTOA. Differs from WrapStoa in
193
+ * the cap the payment key carries (`coin.UR|TRANSFER` instead of
194
+ * `coin.TRANSFER`) — the Pact-code shape is otherwise structurally
195
+ * identical, just a different function name on the same LQD module.
196
+ *
197
+ * (ouronet-ns.TS01-C2.LQD|C_WrapUrStoa <patron> <wrapper> <amount:decimal>)
198
+ */
199
+ export function buildWrapUrStoaPactCode(p) {
200
+ const dec = formatDecimalForPact(p.amount);
201
+ return `(${KADENA_NAMESPACE}.TS01-C2.LQD|C_WrapUrStoa "${p.patron}" "${p.wrapper}" ${dec})`;
202
+ }
203
+ // ─── Unwrap (LQD) — simple + composite-with-account-creation ──────────────────
204
+ //
205
+ // Two-shape builders. The simple shape runs when the user's target k:account
206
+ // already exists on the native chain. The composite shape runs when the
207
+ // target is a brand-new k: account that has to be coin-created in the same
208
+ // atomic Pact expression as the unwrap — needed because the unwrap PUSHES
209
+ // native STOA / UrStoa to the target, which must exist or the transfer
210
+ // aborts. The composite shape requires the call site to additionally
211
+ // `addData("ks", { keys: [<targetPubkey>], pred: "keys-all" })` so the
212
+ // embedded `(read-keyset "ks")` resolves at chain time.
213
+ //
214
+ // Cap structure (signed via the gas-station signer, NOT the patron):
215
+ // - UnwrapStoa: GAS_PAYER + coin.TRANSFER(LIQUIDPOT, target, amount)
216
+ // — the LIQUIDPOT releases native STOA to the target.
217
+ // - UnwrapUrStoa: GAS_PAYER only — no `coin.TRANSFER` needed because the
218
+ // unwrap happens entirely inside the Ouronet UrStoa
219
+ // module (DPTF → DPTF, no native-coin movement).
220
+ //
221
+ // Patron + unwrapper-account guards sign pure (no caps). In strategy.execute
222
+ // terms: `guards: [patronGuard, unwrapperGuard]`, `paymentKey: null`,
223
+ // build closure picks the right Pact-code shape based on a `targetExists`
224
+ // flag, and (when composite) sets `addData("ks", ...)` on the builder
225
+ // before `createTransaction()`.
226
+ /**
227
+ * Unwrap STOA — convert wSTOA → native STOA (target k:account already exists).
228
+ *
229
+ * (ouronet-ns.TS01-C2.LQD|C_UnwrapStoa <patron> <unwrapper> <amount:decimal>)
230
+ */
231
+ export function buildUnwrapStoaPactCode(p) {
232
+ const dec = formatDecimalForPact(p.amount);
233
+ return `(${KADENA_NAMESPACE}.TS01-C2.LQD|C_UnwrapStoa "${p.patron}" "${p.unwrapper}" ${dec})`;
234
+ }
235
+ /**
236
+ * Unwrap STOA — composite shape that creates the target k:account inline
237
+ * (via `coin.C_CreateAccount`) then executes the unwrap, all in one atomic
238
+ * Pact expression. Call site MUST `addData("ks", { keys: [<targetPubkey>],
239
+ * pred: "keys-all" })` on the builder so the embedded `(read-keyset "ks")`
240
+ * resolves at chain time.
241
+ *
242
+ * Composite shape (multi-line for readability — emitted as one string):
243
+ *
244
+ * (namespace "ouronet-ns")
245
+ * (IGNIS.C_Collect <patron> (IGNIS.UDC_CustomCodeCumulator))
246
+ * (let
247
+ * ((wp:string <unwrapper>) (target:string (DALOS.UR_AccountKadena wp)))
248
+ * [(coin.C_CreateAccount target (read-keyset "ks"))
249
+ * (TS01-C2.LQD|C_UnwrapStoa <patron> <unwrapper> <amount>)])
250
+ */
251
+ export function buildUnwrapStoaWithCreateAccountPactCode(p) {
252
+ const dec = formatDecimalForPact(p.amount);
253
+ return (`(namespace "${KADENA_NAMESPACE}")\n` +
254
+ `(IGNIS.C_Collect "${p.patron}" (IGNIS.UDC_CustomCodeCumulator))\n` +
255
+ `(let\n` +
256
+ ` (\n` +
257
+ ` (wp:string "${p.unwrapper}")\n` +
258
+ ` (target:string (DALOS.UR_AccountKadena wp))\n` +
259
+ ` )\n` +
260
+ ` [\n` +
261
+ ` (coin.C_CreateAccount target (read-keyset "ks"))\n` +
262
+ ` (TS01-C2.LQD|C_UnwrapStoa "${p.patron}" "${p.unwrapper}" ${dec})\n` +
263
+ ` ]\n` +
264
+ `)`);
265
+ }
266
+ /**
267
+ * Unwrap UrStoa — convert wURSTOA → native UrStoa (target k:account already exists).
268
+ *
269
+ * (ouronet-ns.TS01-C2.LQD|C_UnwrapUrStoa <patron> <unwrapper> <amount:decimal>)
270
+ */
271
+ export function buildUnwrapUrStoaPactCode(p) {
272
+ const dec = formatDecimalForPact(p.amount);
273
+ return `(${KADENA_NAMESPACE}.TS01-C2.LQD|C_UnwrapUrStoa "${p.patron}" "${p.unwrapper}" ${dec})`;
274
+ }
275
+ /**
276
+ * Unwrap UrStoa — composite shape that creates the target k:account via
277
+ * `coin.C_UR|CreateAccount` (NOT `coin.C_CreateAccount` — UR is a separate
278
+ * coin-module variant for UrStoa accounts) then executes the unwrap.
279
+ * Same `addData("ks", ...)` requirement as `buildUnwrapStoaWithCreateAccountPactCode`.
280
+ */
281
+ export function buildUnwrapUrStoaWithCreateAccountPactCode(p) {
282
+ const dec = formatDecimalForPact(p.amount);
283
+ return (`(namespace "${KADENA_NAMESPACE}")\n` +
284
+ `(IGNIS.C_Collect "${p.patron}" (IGNIS.UDC_CustomCodeCumulator))\n` +
285
+ `(let\n` +
286
+ ` (\n` +
287
+ ` (wp:string "${p.unwrapper}")\n` +
288
+ ` (target:string (DALOS.UR_AccountKadena wp))\n` +
289
+ ` )\n` +
290
+ ` [\n` +
291
+ ` (coin.C_UR|CreateAccount target (read-keyset "ks"))\n` +
292
+ ` (TS01-C2.LQD|C_UnwrapUrStoa "${p.patron}" "${p.unwrapper}" ${dec})\n` +
293
+ ` ]\n` +
294
+ `)`);
295
+ }
296
+ // ─── coin.C_URV family (StoaChain native UrStoa stake / unstake / collect) ───
297
+ //
298
+ // These are PURE StoaChain coin-module operations — no patron, no Ouronet
299
+ // account. The signer is the user's PAYMENT KEY, which carries both the
300
+ // `ouronet-ns.DALOS.GAS_PAYER` cap (so the user pays no gas — Ouronet gas
301
+ // station eats it) AND the `coin.URV|<OP>` cap that authorises the stake /
302
+ // unstake on that payment-key account. In strategy.execute() terms the build
303
+ // closure is: empty guards, `paymentKey` = the payment-key pub, capsKeyPub
304
+ // (selected by `selectCapsSigningKey` as the payment key when no guards
305
+ // compete for it) carries both caps as a single signer.
306
+ /**
307
+ * Stake UrStoa — locks native UrStoa on the user's payment-key account.
308
+ *
309
+ * (coin.C_URV|Stake <payment-key-account:string> <amount:decimal>)
310
+ */
311
+ export function buildStakeUrStoaPactCode(p) {
312
+ const dec = formatDecimalForPact(p.amount);
313
+ return `(coin.C_URV|Stake "${p.paymentKeyAddress}" ${dec})`;
314
+ }
315
+ /**
316
+ * Unstake UrStoa — releases native UrStoa from the user's payment-key
317
+ * stake back to the user's payment-key spendable balance. Symmetric to
318
+ * Stake; the payment key carries `coin.URV|UNSTAKE` (NOT `STAKE`).
319
+ *
320
+ * (coin.C_URV|Unstake <payment-key-account:string> <amount:decimal>)
321
+ */
322
+ export function buildUnstakeUrStoaPactCode(p) {
323
+ const dec = formatDecimalForPact(p.amount);
324
+ return `(coin.C_URV|Unstake "${p.paymentKeyAddress}" ${dec})`;
325
+ }
326
+ /**
327
+ * Collect UrStoa — harvests accrued STOA earnings from the UrStoa Vault to
328
+ * the user's payment-key coin account. Simple path: the payment-key coin
329
+ * account already exists; the payment key carries `coin.URV|COLLECT`.
330
+ *
331
+ * (coin.C_URV|Collect <payment-key-account:string>)
332
+ *
333
+ * For the case where the payment-key coin account does NOT yet exist,
334
+ * see `buildCollectUrStoaWithCreateAccountPactCode` below — it builds the
335
+ * 2-call composite that creates the account first and then collects.
336
+ */
337
+ export function buildCollectUrStoaPactCode(p) {
338
+ return `(coin.C_URV|Collect "${p.paymentKeyAddress}")`;
339
+ }
340
+ /**
341
+ * Collect UrStoa with account-creation — used when the payment-key coin
342
+ * account doesn't yet exist on chain. Emits a 2-call composite Pact body:
343
+ * the create-account call followed by the collect call. The keyset for
344
+ * the new account is read from the "ks" data slot — the consumer is
345
+ * responsible for `.addData("ks", { keys: [pubkey], pred: "keys-all" })`
346
+ * on the transaction builder.
347
+ *
348
+ * (coin.C_CreateAccount <payment-key> (read-keyset "ks"))
349
+ * (coin.C_URV|Collect <payment-key>)
350
+ *
351
+ * Capability set on the build closure is identical to the simple path:
352
+ * GAS_PAYER + `coin.URV|COLLECT` on the payment key. The composite is
353
+ * a Pact-side ordering only — both calls execute in a single transaction.
354
+ */
355
+ export function buildCollectUrStoaWithCreateAccountPactCode(p) {
356
+ return `(coin.C_CreateAccount "${p.paymentKeyAddress}" (read-keyset "ks"))\n(coin.C_URV|Collect "${p.paymentKeyAddress}")`;
357
+ }
358
+ // ─── coin.C_UR family (StoaChain native UrStoa transfer / transmit) ──────────
359
+ //
360
+ // Four Pact-code shapes, selected at runtime by `(receiverExists, isTransferFamily)`:
361
+ //
362
+ // receiverExists isTransferFamily → builder
363
+ // ────────────── ──────────────── ────────────────────────────────────────
364
+ // true true buildNativeUrTransferPactCode
365
+ // true false buildNativeUrTransmitPactCode
366
+ // false true buildNativeUrTransferAnewPactCode
367
+ // false false buildNativeUrTransmitAnewPactCode
368
+ //
369
+ // The Anew variants take a 4th `(read-keyset "ks")` argument — the
370
+ // consumer MUST `addData("ks", { keys: [receiverPubKey], pred: "keys-all" })`
371
+ // on the transaction builder. The non-Anew variants take 3 args (no keyset).
372
+ //
373
+ // All four are signed by the payment key carrying `coin.UR|TRANSFER`
374
+ // (Transfer family) or just `coin.UR` (Transmit family) — the capability
375
+ // shape differs between families but the Pact-code shape only differs
376
+ // in the function name.
377
+ /**
378
+ * Native UR Transfer — receiver-exists + Transfer-family branch.
379
+ *
380
+ * (coin.C_UR|Transfer <sender> <receiver> <amount:decimal>)
381
+ */
382
+ export function buildNativeUrTransferPactCode(p) {
383
+ const dec = formatDecimalForPact(p.amount);
384
+ return `(coin.C_UR|Transfer "${p.sender}" "${p.receiver}" ${dec})`;
385
+ }
386
+ /**
387
+ * Native UR Transmit — receiver-exists + Transmit-family branch.
388
+ *
389
+ * (coin.C_UR|Transmit <sender> <receiver> <amount:decimal>)
390
+ */
391
+ export function buildNativeUrTransmitPactCode(p) {
392
+ const dec = formatDecimalForPact(p.amount);
393
+ return `(coin.C_UR|Transmit "${p.sender}" "${p.receiver}" ${dec})`;
394
+ }
395
+ /**
396
+ * Native UR TransferAnew — receiver-does-not-exist + Transfer-family branch.
397
+ * Reads the receiver keyset from the "ks" data slot; consumer must
398
+ * `addData("ks", { keys: [receiverPubKey], pred: "keys-all" })`.
399
+ *
400
+ * (coin.C_UR|TransferAnew <sender> <receiver> (read-keyset "ks") <amount:decimal>)
401
+ */
402
+ export function buildNativeUrTransferAnewPactCode(p) {
403
+ const dec = formatDecimalForPact(p.amount);
404
+ return `(coin.C_UR|TransferAnew "${p.sender}" "${p.receiver}" (read-keyset "ks") ${dec})`;
405
+ }
406
+ /**
407
+ * Native UR TransmitAnew — receiver-does-not-exist + Transmit-family branch.
408
+ * Same keyset contract as TransferAnew.
409
+ *
410
+ * (coin.C_UR|TransmitAnew <sender> <receiver> (read-keyset "ks") <amount:decimal>)
411
+ */
412
+ export function buildNativeUrTransmitAnewPactCode(p) {
413
+ const dec = formatDecimalForPact(p.amount);
414
+ return `(coin.C_UR|TransmitAnew "${p.sender}" "${p.receiver}" (read-keyset "ks") ${dec})`;
415
+ }
416
+ // ─── TS01-C3.SWP family (Swap — Firestarter, ChangeOwnership) ────────────────
417
+ /**
418
+ * Firestarter — wrap 10 native STOA → 10 wSTOA. One-time, gasless for
419
+ * the user, payment key signs coin.TRANSFER.
420
+ *
421
+ * (ouronet-ns.TS01-C3.SWP|C_Firestarter <firestarter>)
422
+ */
423
+ export function buildFirestarterPactCode(p) {
424
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_Firestarter "${p.firestarter}")`;
425
+ }
426
+ /**
427
+ * ChangeOwnership — transfer ownership of an existing SWP-pair (liquidity
428
+ * pool) from its current pool-owner to a new Ouronet account. Gated by
429
+ * the pool's `can-change-owner` flag (must be true) and signed by the
430
+ * patron + current pool-owner guards.
431
+ *
432
+ * (ouronet-ns.TS01-C3.SWP|C_ChangeOwnership
433
+ * <patron> <swpair> <new-owner>)
434
+ */
435
+ export function buildChangeOwnershipPactCode(p) {
436
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_ChangeOwnership "${p.patron}" "${p.swpair}" "${p.newOwner}")`;
437
+ }
438
+ /**
439
+ * ModifyWeights — set new token weight ratios on a Weighted SWP-pair.
440
+ * Weighted pools only (pool-type "W"). The new weights array length MUST
441
+ * match the pool's token count, each value MUST be a decimal ≤4 fractional
442
+ * digits, and the SUM MUST equal 1 exactly. UI enforces those constraints;
443
+ * the chain enforces them again as a defense.
444
+ *
445
+ * (ouronet-ns.TS01-C3.SWP|C_ModifyWeights
446
+ * <patron> <swpair> <new-weights:[decimal]>)
447
+ *
448
+ * Pact list literal format: `[w1 w2 w3]` — space-separated, square-bracketed,
449
+ * each value formatted via `formatDecimalForPact` (closes F-SEC-001 the
450
+ * same way scalar amounts do).
451
+ */
452
+ export function buildModifyWeightsPactCode(p) {
453
+ const weightList = `[${p.newWeights.map(w => formatDecimalForPact(w)).join(" ")}]`;
454
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_ModifyWeights "${p.patron}" "${p.swpair}" ${weightList})`;
455
+ }
456
+ /**
457
+ * ToggleSwapCapability — flip the SWP-pair's swap-enabled flag (UI label
458
+ * "Swapping"). Boolean MUST be the inverse of `UR_CanSwap` (chain rejects
459
+ * same-value writes). Patron + current pool-owner guards sign pure.
460
+ *
461
+ * (ouronet-ns.TS01-C3.SWP|C_ToggleSwapCapability <patron> <swpair> <toggle:bool>)
462
+ */
463
+ export function buildToggleSwapCapabilityPactCode(p) {
464
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_ToggleSwapCapability "${p.patron}" "${p.swpair}" ${p.toggle})`;
465
+ }
466
+ /**
467
+ * ToggleAddLiquidity — flip the SWP-pair's add-liquidity-enabled flag
468
+ * (UI label "Provisioning"). Boolean MUST be the inverse of `UR_CanAdd`
469
+ * (chain rejects same-value writes). Patron + current pool-owner guards
470
+ * sign pure.
471
+ *
472
+ * (ouronet-ns.TS01-C3.SWP|C_ToggleAddLiquidity <patron> <swpair> <toggle:bool>)
473
+ */
474
+ export function buildToggleAddLiquidityPactCode(p) {
475
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_ToggleAddLiquidity "${p.patron}" "${p.swpair}" ${p.toggle})`;
476
+ }
477
+ /**
478
+ * ModifyCanChangeOwner — flip the `can-change-owner` flag on a SWP-pair.
479
+ * Signed by the patron + current pool-owner guards. The `newBoolean` arg
480
+ * MUST be the inverse of the on-chain current value (the modal computes
481
+ * it automatically; user does not type it). The chain rejects same-value
482
+ * writes, so the new boolean is effectively the only allowed value.
483
+ *
484
+ * (ouronet-ns.TS01-C3.SWP|C_ModifyCanChangeOwner
485
+ * <patron> <swpair> <new-boolean:bool>)
486
+ */
487
+ export function buildModifyCanChangeOwnerPactCode(p) {
488
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_ModifyCanChangeOwner "${p.patron}" "${p.swpair}" ${p.newBoolean})`;
489
+ }
490
+ // ─── TS01-C3.SWP family — liquidity-pool ops (Add / Remove / Fuel) ───────────
491
+ //
492
+ // `inputAmounts` is rendered as `[a1 a2 a3]` decimal-list literal — each
493
+ // amount routed through `formatDecimalForPact` so an integer "5" becomes
494
+ // "5.0" (Pact decimal lexer rejects bare integers in the decimal slot).
495
+ // AddLiquidity emits the full TS01-C3 path; the four "special" variants
496
+ // (Iced / Glacial / Frozen / Sleeping under TS01-CP.SWP) live in
497
+ // `addLiquidityFunctions.executeSpecialAddLiquidity` and are not yet
498
+ // surfaced by `AddLiquidityInterface.tsx` — builders for those will be
499
+ // added when their modals come online.
500
+ /**
501
+ * Add Liquidity — deposit input-amounts into the SWP-pair pool in exchange
502
+ * for LP tokens. `inputAmounts` is a per-pool-token decimal vector.
503
+ *
504
+ * (ouronet-ns.TS01-C3.SWP|C_AddLiquidity
505
+ * <patron> <account> <swpair> <inputAmounts:[decimal]>)
506
+ */
507
+ export function buildAddLiquidityPactCode(p) {
508
+ const decimals = p.inputAmounts.map(a => formatDecimalForPact(a));
509
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_AddLiquidity "${p.patron}" "${p.account}" "${p.swpair}" [${decimals.join(" ")}])`;
510
+ }
511
+ /**
512
+ * Remove Liquidity (Unfold) — burn LP tokens to recover the underlying
513
+ * pool tokens in proportion to the burned LP share. Single `lpAmount`
514
+ * decimal (not a list).
515
+ *
516
+ * (ouronet-ns.TS01-C3.SWP|C_RemoveLiquidity
517
+ * <patron> <account> <swpair> <lp-amount:decimal>)
518
+ */
519
+ export function buildRemoveLiquidityPactCode(p) {
520
+ const dec = formatDecimalForPact(p.lpAmount);
521
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_RemoveLiquidity "${p.patron}" "${p.account}" "${p.swpair}" ${dec})`;
522
+ }
523
+ // ─── TS01-C3.SWP family — swap ops (Single/Multi × With/No Slippage) ─────────
524
+ //
525
+ // Four shape variants; the modal picks one per click based on
526
+ // (1-vs-N inputs, slippage toggle):
527
+ //
528
+ // Single + With → C_SingleSwapWithSlippage (takes (read-msg 'slippage-bounds))
529
+ // Single + No → C_SingleSwapNoSlippage (no slippage arg)
530
+ // Multi + With → C_MultiSwapWithSlippage ([inputIds] [amounts] + slippage)
531
+ // Multi + No → C_MultiSwapNoSlippage ([inputIds] [amounts], no slippage)
532
+ //
533
+ // The two slippage variants pull `slippage-bounds` from the message data
534
+ // — the consumer must `.addData("slippage-bounds", boundsObj)` on the
535
+ // transaction builder; the bounds object itself is fetched separately
536
+ // via `getSlippageBounds(...)` before signing.
537
+ /**
538
+ * Single-input swap WITH slippage protection.
539
+ *
540
+ * (ouronet-ns.TS01-C3.SWP|C_SingleSwapWithSlippage
541
+ * <patron> <account> <swpair> <inputId> <inputAmount:decimal> <outputId> (read-msg 'slippage-bounds))
542
+ */
543
+ export function buildSingleSwapWithSlippagePactCode(p) {
544
+ const dec = formatDecimalForPact(p.inputAmount);
545
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_SingleSwapWithSlippage "${p.patron}" "${p.account}" "${p.swpair}" "${p.inputId}" ${dec} "${p.outputId}" (read-msg 'slippage-bounds))`;
546
+ }
547
+ /**
548
+ * Single-input swap WITHOUT slippage protection.
549
+ *
550
+ * (ouronet-ns.TS01-C3.SWP|C_SingleSwapNoSlippage
551
+ * <patron> <account> <swpair> <inputId> <inputAmount:decimal> <outputId>)
552
+ */
553
+ export function buildSingleSwapNoSlippagePactCode(p) {
554
+ const dec = formatDecimalForPact(p.inputAmount);
555
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_SingleSwapNoSlippage "${p.patron}" "${p.account}" "${p.swpair}" "${p.inputId}" ${dec} "${p.outputId}")`;
556
+ }
557
+ /**
558
+ * Multi-input swap WITH slippage protection. `inputIds` and `inputAmounts`
559
+ * are parallel arrays; each amount applies to the same-position id.
560
+ *
561
+ * (ouronet-ns.TS01-C3.SWP|C_MultiSwapWithSlippage
562
+ * <patron> <account> <swpair> <inputIds:[string]> <inputAmounts:[decimal]> <outputId> (read-msg 'slippage-bounds))
563
+ */
564
+ export function buildMultiSwapWithSlippagePactCode(p) {
565
+ const idList = `[${p.inputIds.map(id => `"${id}"`).join(" ")}]`;
566
+ const amtList = `[${p.inputAmounts.map(a => formatDecimalForPact(a)).join(" ")}]`;
567
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_MultiSwapWithSlippage "${p.patron}" "${p.account}" "${p.swpair}" ${idList} ${amtList} "${p.outputId}" (read-msg 'slippage-bounds))`;
568
+ }
569
+ /**
570
+ * Multi-input swap WITHOUT slippage protection.
571
+ *
572
+ * (ouronet-ns.TS01-C3.SWP|C_MultiSwapNoSlippage
573
+ * <patron> <account> <swpair> <inputIds:[string]> <inputAmounts:[decimal]> <outputId>)
574
+ */
575
+ export function buildMultiSwapNoSlippagePactCode(p) {
576
+ const idList = `[${p.inputIds.map(id => `"${id}"`).join(" ")}]`;
577
+ const amtList = `[${p.inputAmounts.map(a => formatDecimalForPact(a)).join(" ")}]`;
578
+ return `(${KADENA_NAMESPACE}.TS01-C3.SWP|C_MultiSwapNoSlippage "${p.patron}" "${p.account}" "${p.swpair}" ${idList} ${amtList} "${p.outputId}")`;
579
+ }
580
+ // ─── TS02-Cx.DPSF/DPNF family (Token-Set creation) ───────────────────────────
581
+ //
582
+ // Two C_Make variants — SFT (semi-fungible, DPSF, TS02-C1) takes a
583
+ // `how-many-sets` integer; NFT (non-fungible, DPNF, TS02-C2) always
584
+ // creates exactly one set so the arg is omitted. Both take a nonces
585
+ // integer-list `[n1 n2 n3]` and an integer set-class. The nonces are
586
+ // emitted as bare integers — NOT decimals (no .0 padding).
587
+ /**
588
+ * Create Set (SFT — semi-fungible). Bundles selected DPSF nonces into
589
+ * `howManySets` sets of class `setClass`.
590
+ *
591
+ * (ouronet-ns.TS02-C1.DPSF|C_Make
592
+ * <patron> <account> <id> <nonces:[integer]> <set-class:integer> <how-many-sets:integer>)
593
+ */
594
+ export function buildCreateSetPactCode(p) {
595
+ const noncesStr = `[${p.nonces.join(" ")}]`;
596
+ return `(${KADENA_NAMESPACE}.TS02-C1.DPSF|C_Make "${p.patron}" "${p.account}" "${p.tokenId}" ${noncesStr} ${p.setClass} ${p.howManySets})`;
597
+ }
598
+ /**
599
+ * Create Set (NFT — non-fungible). Bundles selected DPNF nonces into a
600
+ * single set of class `setClass`. No `how-many-sets` parameter — NFT
601
+ * sets are always 1×.
602
+ *
603
+ * (ouronet-ns.TS02-C2.DPNF|C_Make
604
+ * <patron> <account> <id> <nonces:[integer]> <set-class:integer>)
605
+ */
606
+ export function buildCreateSetNFTPactCode(p) {
607
+ const noncesStr = `[${p.nonces.join(" ")}]`;
608
+ return `(${KADENA_NAMESPACE}.TS02-C2.DPNF|C_Make "${p.patron}" "${p.account}" "${p.tokenId}" ${noncesStr} ${p.setClass})`;
609
+ }
610
+ // ─── TS01-C1.DALOS family (Smart Ouronet Account mutations) ──────────────────
611
+ /**
612
+ * Rotate Sovereign — change the sovereign account that has primary
613
+ * authority over a Smart Ouronet Account (Σ. prefix).
614
+ *
615
+ * Smart-account auth is `enforce-one` over three branches:
616
+ * (a) the Smart account's own guard,
617
+ * (b) the current sovereign account's guard,
618
+ * (c) the Smart account's governor.
619
+ * Any one branch satisfying its predicate authorises the rotation.
620
+ *
621
+ * (ouronet-ns.TS01-C1.DALOS|C_RotateSovereign
622
+ * <patron> <account> <new-sovereign>)
623
+ *
624
+ * `account` is the Σ. Smart account being modified. `new-sovereign`
625
+ * must be an existing Standard Ouronet Account (Ѻ. prefix); the chain
626
+ * rejects Σ. → Σ. rotations because Smart accounts cannot be
627
+ * sovereigns themselves.
628
+ *
629
+ * Added in v1.6.0.
630
+ */
631
+ export function buildRotateSovereignPactCode(p) {
632
+ return `(${KADENA_NAMESPACE}.TS01-C1.DALOS|C_RotateSovereign "${p.patron}" "${p.account}" "${p.newSovereign}")`;
633
+ }
634
+ /**
635
+ * Rotate the GOVERNOR of a Smart Ouronet Account (Σ. prefix).
636
+ *
637
+ * (ouronet-ns.TS01-C1.DALOS|C_RotateGovernor <patron> <account> <governor-expr>)
638
+ *
639
+ * Unlike the account GUARD — which the chain now restricts to key-based
640
+ * guards (keyset / keyset-ref) — the governor slot is restricted to
641
+ * NON-key-based guards (user / capability / module / pact). The
642
+ * `governorExpr` is therefore a complete inline guard-construction
643
+ * expression authored by the consumer, e.g.
644
+ *
645
+ * (create-user-guard (ouronet-ns.U|G.UEV_Any [ (create-capability-guard ...) ... ]))
646
+ *
647
+ * Because the guard is inline (not read from a data slot), there is NO
648
+ * `.addData("ks", …)` payload — contrast `buildRotateGuardPactCode`'s
649
+ * "define" mode. The builder ONLY interpolates the expression; producing
650
+ * a syntactically valid, non-key-based `governorExpr` is the caller's
651
+ * responsibility (the chain rejects key-based governors).
652
+ *
653
+ * Added in v4.3.3.
654
+ */
655
+ export function buildRotateGovernorPactCode(p) {
656
+ return `(${KADENA_NAMESPACE}.TS01-C1.DALOS|C_RotateGovernor "${p.patron}" "${p.account}" ${p.governorExpr})`;
657
+ }
658
+ /**
659
+ * Wrap a guard `body` expression in one of the five non-key-based guard
660
+ * constructors, producing the inline `governorExpr` that
661
+ * {@link buildRotateGovernorPactCode} interpolates:
662
+ *
663
+ * buildNonKeyGuardExpr({ constructor: "create-user-guard",
664
+ * body: "(ns.UG.UEV_Any (create-capability-guard ...))" })
665
+ * → "(create-user-guard (ns.UG.UEV_Any (create-capability-guard ...)))"
666
+ *
667
+ * `body` is the complete argument expression the constructor receives
668
+ * (parens / brackets / quotes already included — for `create-module-guard`
669
+ * and `create-pact-guard` that is a quoted name string `"name"`). The
670
+ * builder does NOT validate or quote `body`; producing a syntactically
671
+ * valid argument is the caller's responsibility.
672
+ *
673
+ * Added in v4.3.3.
674
+ */
675
+ export function buildNonKeyGuardExpr(p) {
676
+ return `(${p.constructor} ${p.body})`;
677
+ }
678
+ // ─── TS01-C4.CODEX family (StoicTag registry) ────────────────────────────────
679
+ /**
680
+ * Release the StoicTag currently bound to an Ouronet account.
681
+ *
682
+ * (ouronet-ns.TS01-C4.CODEX|C_ReleaseStoicTag <patron> <tag-name>)
683
+ *
684
+ * `tag-name` is the BARE on-chain name (no § sigil — the sigil is a UI-only
685
+ * marker). The chain resolves the account the tag is bound to and enforces
686
+ * that account's ownership, so the consumer MUST sign with the bound account's
687
+ * guard (in addition to the patron). The only cost is IGNIS, 1 per glyph of the
688
+ * tag name; the amount is surfaced by `INFO_ReleaseStoicTag`.
689
+ *
690
+ * Added in v4.3.3.
691
+ */
692
+ export function buildReleaseStoicTagPactCode(p) {
693
+ return `(${KADENA_NAMESPACE}.TS01-C4.CODEX|C_ReleaseStoicTag "${p.patron}" "${p.tagName}")`;
694
+ }
695
+ /**
696
+ * Register (claim) a StoicTag for an Ouronet account.
697
+ *
698
+ * (ouronet-ns.TS01-C4.CODEX|C_RegisterStoicTag <patron> <tag-name> <account-address>)
699
+ *
700
+ * `tag-name` is the BARE on-chain name (DALOS glyphs only, no § sigil).
701
+ * `account-address` is the Ouronet account the tag is being applied to.
702
+ *
703
+ * This costs NATIVE STOA (1 per glyph, less the account's Elite-tier discount),
704
+ * paid by the patron's payment key and split 10/20/30/40 across the protocol
705
+ * receivers returned by `INFO_RegisterStoicTag`. The consumer MUST therefore
706
+ * sign the payment key with `GAS_PAYER` + one `coin.TRANSFER` per split
707
+ * receiver — otherwise the chain rejects the transaction.
708
+ *
709
+ * Added in v4.3.3.
710
+ */
711
+ export function buildRegisterStoicTagPactCode(p) {
712
+ return `(${KADENA_NAMESPACE}.TS01-C4.CODEX|C_RegisterStoicTag "${p.patron}" "${p.tagName}" "${p.accountAddress}")`;
713
+ }
714
+ /**
715
+ * Rotate the GUARD (ownership keyset) of an Ouronet account.
716
+ *
717
+ * (ouronet-ns.TS01-C1.DALOS|C_RotateGuard <patron> <account> <guard-expr> <safe>)
718
+ *
719
+ * The guard-expr is one of two shapes, switched by `mode`:
720
+ * - "define" → `(read-keyset "ks")` Consumer MUST also call
721
+ * `.addData("ks", { keys, pred })`
722
+ * on the transaction builder so
723
+ * the chain can read the keyset.
724
+ * - "existing" → `(keyset-ref-guard "<ref>")` References an on-chain
725
+ * registered keyset; no addData
726
+ * call is needed.
727
+ *
728
+ * The `safe` flag (boolean) is the chain-side "are you sure?" gate — when
729
+ * `true` it enforces extra invariants on the new guard (e.g. that at least
730
+ * one key in the new keyset is held by the account holder). Define mode
731
+ * is always safe; existing mode lets the user opt-in/out.
732
+ *
733
+ * Added in v4.3.0.
734
+ */
735
+ export function buildRotateGuardPactCode(p) {
736
+ const guardExpr = p.mode === "define"
737
+ ? `(read-keyset "ks")`
738
+ : `(keyset-ref-guard "${p.keysetRef ?? ""}")`;
739
+ return `(${KADENA_NAMESPACE}.TS01-C1.DALOS|C_RotateGuard "${p.patron}" "${p.account}" ${guardExpr} ${p.safe})`;
740
+ }
741
+ /**
742
+ * Rotate the Kadena Ledger payment key (= "payment key") of an Ouronet
743
+ * account.
744
+ *
745
+ * (ouronet-ns.TS01-C1.DALOS|C_RotateKadena <patron> <account> <new-payment-key>)
746
+ *
747
+ * Why "RotateKadena" not "RotatePaymentKey": the on-chain Pact function is
748
+ * `C_RotateKadena` — the kadena-ledger payment key is what the on-chain
749
+ * naming refers to. The builder name mirrors the Pact function for grep-
750
+ * ability with chain logs; UI surfaces (e.g. ouronet-codex's
751
+ * `<RotatePaymentKeyModal>`) use the more user-friendly "Payment Key".
752
+ *
753
+ * The consumer is responsible for `.addData("ks", { keys: patronGuard.keys,
754
+ * pred: patronGuard.pred })` and (when patron ≠ account)
755
+ * `.addData("ks-account", { keys: accountGuard.keys, pred: accountGuard.pred })`
756
+ * on the transaction builder. This builder ONLY emits the Pact code.
757
+ *
758
+ * Added in v4.3.0.
759
+ */
760
+ export function buildRotateKadenaPactCode(p) {
761
+ return `(${KADENA_NAMESPACE}.TS01-C1.DALOS|C_RotateKadena "${p.patron}" "${p.account}" "${p.newPaymentKey}")`;
762
+ }
763
+ /**
764
+ * Deploy / activate Standard Ouronet Account. Patronless function — the
765
+ * Pact code does NOT take a patron argument; the deploying CodexPrime
766
+ * Key #0 pays gas and signs the 4× coin.TRANSFER caps that fund the
767
+ * receivers. The guard for the new account is read from the "ks" data
768
+ * slot — consumer must `.addData("ks", { keys: <guardKeys>, pred: <guardPred> })`
769
+ * on the transaction builder.
770
+ *
771
+ * (ouronet-ns.TS01-C1.DALOS|C_DeployStandardAccount
772
+ * <account> (read-keyset "ks") <kadena-address> <public-key>)
773
+ *
774
+ * The 4 coin.TRANSFER capabilities one per kadena-split receiver are NOT
775
+ * part of the Pact code — they're attached at signer level on the
776
+ * gas-payer key, with the receiver list + amount list derived from the
777
+ * INFO call's `kadena-targets` / `kadena-split` fields.
778
+ */
779
+ export function buildDeployStandardAccountPactCode(p) {
780
+ const guardExpr = p.mode === "existing"
781
+ ? `(keyset-ref-guard "${p.keysetRef ?? ""}")`
782
+ : `(read-keyset "ks")`;
783
+ return `(${KADENA_NAMESPACE}.TS01-C1.DALOS|C_DeployStandardAccount "${p.account}" ${guardExpr} "${p.kadenaAddress}" "${p.publicKey}")`;
784
+ }
785
+ /**
786
+ * Build the Pact code for C_DeploySmartAccount — Activate a Smart (Σ.) Ouronet
787
+ * Account.
788
+ *
789
+ * On-chain signature (positional):
790
+ * (ouronet-ns.TS01-C1.DALOS|C_DeploySmartAccount
791
+ * <account> <guard:guard> <kadena> <sovereign> <public>)
792
+ *
793
+ * Identical to the Standard deploy except for ONE extra positional arg —
794
+ * `sovereign` — inserted between `kadena` and `public`. The `guard` arg is the
795
+ * account keyset, passed the same way as Standard via `(read-keyset "ks")`
796
+ * (the consumer attaches the keyset with `addData("ks", { keys, pred })`).
797
+ *
798
+ * `sovereign` is an EXISTING Standard (Ѻ.) Ouronet account that holds the new
799
+ * Smart account's sovereignty — the chain rejects Σ.→Σ. (a smart account can't
800
+ * be its own sovereign).
801
+ *
802
+ * Signers/caps are identical to the Standard deploy: the gas-payer (CodexPrime
803
+ * Key #0) carries DALOS.GAS_PAYER + N coin.TRANSFER (one per `kadena-split`
804
+ * receiver from the INFO call), and the account keyset signs pure. None of that
805
+ * is in the Pact code — it's attached at signer level, exactly as Standard.
806
+ */
807
+ export function buildDeploySmartAccountPactCode(p) {
808
+ const guardExpr = p.mode === "existing"
809
+ ? `(keyset-ref-guard "${p.keysetRef ?? ""}")`
810
+ : `(read-keyset "ks")`;
811
+ return `(${KADENA_NAMESPACE}.TS01-C1.DALOS|C_DeploySmartAccount "${p.account}" ${guardExpr} "${p.kadenaAddress}" "${p.sovereign}" "${p.publicKey}")`;
812
+ }