@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,463 @@
1
+ import { Pact } from "@stoachain/kadena-stoic-legacy/client";
2
+ import { getFailoverClient, withFailover } from "@stoachain/stoa-core/network";
3
+ import { KADENA_NETWORK, getPactUrl, STOA_AUTONOMIC_OURONETGASSTATION, KADENA_NAMESPACE } from "../constants/index.js";
4
+ import { GAS_PRICE_MIN_ANU, anuToStoa } from "@stoachain/stoa-core/gas";
5
+ import { pactRead } from "@stoachain/stoa-core/reads";
6
+ import { safeCreationTime, formatDecimalForPact } from "@stoachain/stoa-core/pact";
7
+ /**
8
+ * Get KDA balance for an account on a specific chain.
9
+ * exists=false means the account row does not exist on that chain (not just zero balance).
10
+ */
11
+ export async function getBalanceOnChain(account, chainId, tier = "T1") {
12
+ try {
13
+ const pactCode = `(coin.get-balance "${account}")`;
14
+ const response = await pactRead(pactCode, {
15
+ pactUrl: getPactUrl(chainId),
16
+ chainId,
17
+ tier,
18
+ });
19
+ if (!response?.result || response.result.status === "failure") {
20
+ return { balance: "0", exists: false };
21
+ }
22
+ const data = response.result.data;
23
+ let balance = "0";
24
+ if (data) {
25
+ if (typeof data === "string") {
26
+ balance = data;
27
+ }
28
+ else if (typeof data === "number") {
29
+ balance = data.toString();
30
+ }
31
+ else if (typeof data === "object" && data.decimal) {
32
+ balance = data.decimal;
33
+ }
34
+ else if (typeof data === "object" && data.int) {
35
+ balance = data.int;
36
+ }
37
+ }
38
+ return { balance, exists: true };
39
+ }
40
+ catch (error) {
41
+ return {
42
+ balance: "0",
43
+ exists: false,
44
+ error: error instanceof Error ? error.message : "Failed to fetch balance",
45
+ };
46
+ }
47
+ }
48
+ /**
49
+ * Build a cross-chain transfer transaction (step 1)
50
+ * This creates a transaction that needs to be signed and submitted
51
+ */
52
+ export function buildCrossChainTransfer(params) {
53
+ const { sender, receiver, receiverGuard, amount, sourceChain, targetChain, senderPublicKey, } = params;
54
+ // v3.2.1: replaced `parseFloat(amount).toFixed(12)` with the validated
55
+ // formatter to close audit finding F-BUG-003. The old form silently
56
+ // truncated precision on values past float64's ~15-17 significant digits
57
+ // (a 20-digit-fractional KDA amount would lose ~5 digits of precision)
58
+ // and silently rounded inputs that exceeded 12 decimals. The formatter
59
+ // preserves arbitrary precision (truncates at 24 decimals by default) and
60
+ // throws on malformed input rather than producing "NaN" downstream.
61
+ const formattedAmount = formatDecimalForPact(amount);
62
+ const receiverKeysetName = `receiver-guard-${Date.now()}`;
63
+ const transaction = Pact.builder
64
+ .execution(`(coin.transfer-crosschain "${sender}" "${receiver}" (read-keyset "${receiverKeysetName}") "${targetChain}" ${formattedAmount})`)
65
+ .addData(receiverKeysetName, receiverGuard)
66
+ .addSigner(senderPublicKey, (withCapability) => [
67
+ withCapability("coin.TRANSFER_XCHAIN", sender, receiver, {
68
+ decimal: formattedAmount,
69
+ }, targetChain),
70
+ withCapability("coin.GAS"),
71
+ ])
72
+ .setMeta({
73
+ chainId: sourceChain,
74
+ senderAccount: sender,
75
+ // v3.2.3: added `creationTime: safeCreationTime()` to close audit
76
+ // finding F-BUG-002. The v2.3.0 audit consolidated `safeCreationTime()`
77
+ // (returns `Date.now()/1000 - 30`) precisely so client-side clock drift
78
+ // doesn't trigger chain-side "creation time too far in the future"
79
+ // rejections; without this field, `@kadena/client` falls back to the
80
+ // raw current time and any consumer with a clock slightly ahead of
81
+ // node time gets sporadic submit failures. This was the lone builder
82
+ // in interactions/* that omitted the helper after the v2.3.0 sweep —
83
+ // every other setMeta block (including `buildCTransferAcross` two
84
+ // functions below) already includes it.
85
+ creationTime: safeCreationTime(),
86
+ gasLimit: 2500,
87
+ gasPrice: 0.00000001,
88
+ ttl: 28800,
89
+ })
90
+ .setNetworkId(KADENA_NETWORK)
91
+ .createTransaction();
92
+ return transaction;
93
+ }
94
+ /**
95
+ * Build a coin.C_TransferAcross transaction (step 0 of cross-chain transfer).
96
+ *
97
+ * Chain 0: Gas paid by Ouronet Gas Station (DALOS.GAS_PAYER).
98
+ * Other chains: Gas paid by kadena-xchain-gas (unsigned).
99
+ */
100
+ export function buildCTransferAcross(params) {
101
+ const { sender, receiver, receiverGuard, amount, sourceChain, targetChain, senderPublicKey, gasStationPublicKey, } = params;
102
+ const keysetName = `receiver-guard-${Date.now()}`;
103
+ const pactCode = `(coin.C_TransferAcross "${sender}" "${receiver}" (read-keyset "${keysetName}") "${targetChain}" ${amount})`;
104
+ if (sourceChain === "0") {
105
+ // Chain 0: Gas Station pays via DALOS.GAS_PAYER
106
+ if (!gasStationPublicKey) {
107
+ throw new Error("gasStationPublicKey is required for chain 0 transfers");
108
+ }
109
+ return Pact.builder
110
+ .execution(pactCode)
111
+ .addData(keysetName, receiverGuard)
112
+ .addSigner(gasStationPublicKey, (w) => [
113
+ w(`${KADENA_NAMESPACE}.DALOS.GAS_PAYER`, "", { int: 0 }, { decimal: "0.0" }),
114
+ ])
115
+ .addSigner(senderPublicKey, (w) => [
116
+ w("coin.TRANSFER_XCHAIN", sender, receiver, { decimal: amount }, targetChain),
117
+ ])
118
+ .setMeta({
119
+ chainId: "0",
120
+ senderAccount: STOA_AUTONOMIC_OURONETGASSTATION,
121
+ creationTime: safeCreationTime(),
122
+ gasLimit: 2500,
123
+ gasPrice: anuToStoa(GAS_PRICE_MIN_ANU),
124
+ ttl: 28800,
125
+ })
126
+ .setNetworkId(KADENA_NETWORK)
127
+ .createTransaction();
128
+ }
129
+ else {
130
+ // Non-chain-0: kadena-xchain-gas pays gas.
131
+ // Its guard uses coin.gas-only (no signature needed) BUT requires:
132
+ // - gasPrice <= 0.00000001
133
+ // - gasLimit <= 850
134
+ // No signer needed for gas — only sender signs TRANSFER_XCHAIN cap.
135
+ return Pact.builder
136
+ .execution(pactCode)
137
+ .addData(keysetName, receiverGuard)
138
+ .addSigner(senderPublicKey, (w) => [
139
+ w("coin.TRANSFER_XCHAIN", sender, receiver, { decimal: amount }, targetChain),
140
+ ])
141
+ .setMeta({
142
+ chainId: sourceChain,
143
+ senderAccount: "kadena-xchain-gas",
144
+ gasLimit: 850, // must be ≤ 850 for kadena-xchain-gas guard
145
+ gasPrice: 0.00000001, // must be ≤ 0.00000001 for kadena-xchain-gas guard
146
+ ttl: 28800,
147
+ })
148
+ .setNetworkId(KADENA_NETWORK)
149
+ .createTransaction();
150
+ }
151
+ }
152
+ /**
153
+ * Submit a cross-chain transfer and get the request key.
154
+ *
155
+ * Resolves to the chainweb `ITransactionDescriptor` (request key + chain id +
156
+ * network id) for the submitted transaction. Caller is responsible for
157
+ * persisting the descriptor — it's the only handle for `pollTransactionStatus`,
158
+ * `fetchSpvProof`, and `submitContinuation` later in the cross-chain flow.
159
+ *
160
+ * **Error contract** (closes audit finding F-ERR-001 — v3.2.3):
161
+ *
162
+ * Unlike its sibling `pollTransactionStatus` (which catches errors and
163
+ * returns `{ status: "pending", error: ... }` — the codebase's discriminated-
164
+ * union convention), this function deliberately propagates errors rather
165
+ * than swallowing them. A failed submit is not a transient state to poll
166
+ * past — it means the transaction did NOT land on chain, and the caller's
167
+ * UI must surface that as a hard failure (refund the user's escrowed gas
168
+ * estimate, present a retry button, etc.). Wrapping the throw in an
169
+ * envelope would mask the failure.
170
+ *
171
+ * @throws {SigningError} with `code: "TIMEOUT"` if the underlying
172
+ * `submit()` exceeds the per-tier deadline (default 60s for submit).
173
+ * See `runWithTimeout` in `src/network/failoverClient.ts`.
174
+ * @throws {Error} On network failure that survives both the primary and
175
+ * fallback node attempts. Both errors propagate verbatim from
176
+ * `getFailoverClient`'s submit method — the caller's catch block
177
+ * should distinguish via `error instanceof SigningError && error.code === "TIMEOUT"`.
178
+ */
179
+ export async function submitCrossChainTransfer(signedTransaction, sourceChain) {
180
+ const { submit } = getFailoverClient(sourceChain);
181
+ return await submit(signedTransaction);
182
+ }
183
+ /**
184
+ * Poll for transaction status on source chain
185
+ */
186
+ export async function pollTransactionStatus(requestKey, chainId) {
187
+ try {
188
+ const { pollOne } = getFailoverClient(chainId);
189
+ const result = await pollOne({ requestKey, chainId: chainId, networkId: KADENA_NETWORK });
190
+ if (!result) {
191
+ return { status: "pending" };
192
+ }
193
+ if (result.result.status === "failure") {
194
+ return {
195
+ status: "failure",
196
+ error: result.result.error?.message || "Transaction failed",
197
+ result,
198
+ };
199
+ }
200
+ // Check if this is a defpact with continuation info
201
+ const continuation = result.continuation ? {
202
+ pactId: result.continuation.pactId,
203
+ step: result.continuation.step,
204
+ stepHasRollback: result.continuation.stepHasRollback,
205
+ } : undefined;
206
+ return {
207
+ status: "success",
208
+ continuation,
209
+ result,
210
+ };
211
+ }
212
+ catch (error) {
213
+ return {
214
+ status: "pending",
215
+ error: error instanceof Error ? error.message : "Unknown error",
216
+ };
217
+ }
218
+ }
219
+ /**
220
+ * Default per-attempt timeout for `fetchSpvProof` in milliseconds. Picked to
221
+ * be longer than the chainweb dirty-read default (15s) since SPV proof
222
+ * generation may pull from disk on the node, but short enough that a wedged
223
+ * primary node doesn't hang the consumer's retry loop. The `pollSpvProof`
224
+ * outer loop adds its own retry budget on top of this per-attempt cap.
225
+ *
226
+ * Added in v3.2.3 to close audit finding F-BUG-004.
227
+ */
228
+ const SPV_PROOF_TIMEOUT_MS = 30000;
229
+ /**
230
+ * Fetch SPV proof for a cross-chain transfer.
231
+ *
232
+ * Requires waiting for block finality (~100-120 seconds). The on-chain
233
+ * proof becomes available a few blocks after the source-chain submit
234
+ * commits; before that, the chainweb node returns `400 not available`.
235
+ *
236
+ * v3.2.3 (closes audit finding F-BUG-004): wrapped in `withFailover` and
237
+ * `AbortSignal.timeout(SPV_PROOF_TIMEOUT_MS)`. Pre-v3.2.3, this was the
238
+ * only chain-RPC function in the entire codebase that called raw `fetch()`
239
+ * without either guard:
240
+ *
241
+ * - No `AbortController`: a wedged primary node (slow, not erroring)
242
+ * would hang the `await fetch(...)` indefinitely. The outer
243
+ * `pollSpvProof` retry loop never advanced because each attempt
244
+ * awaited the hung fetch.
245
+ *
246
+ * - No `withFailover`: even if the primary node returned an error or
247
+ * timed out, traffic stayed pinned to the primary; the consumer's
248
+ * subsequent attempts hit the same wedged node forever.
249
+ *
250
+ * - Combined consequence: the user's KDA was committed to
251
+ * `kadena-xchain-gas` escrow on the source chain (step 1 succeeded),
252
+ * but step 2's SPV proof retrieval hung silently with the UI showing
253
+ * a perpetual "Waiting for SPV proof..." spinner and no recovery
254
+ * path. This is the highest-impact bug surfaced by the 2026-05-05
255
+ * audit.
256
+ *
257
+ * Post-v3.2.3 behaviour: each attempt has a hard 30s deadline; on timeout
258
+ * (or any network-class error on the primary node), `withFailover`
259
+ * switches to the fallback node and retries once. The outer
260
+ * `pollSpvProof` loop then re-invokes this function after the configured
261
+ * `delayMs` (default 5s), so a stuck primary surfaces as ~30s of
262
+ * waiting, then automatic fallback, then continued polling — never an
263
+ * infinite hang.
264
+ */
265
+ export async function fetchSpvProof(requestKey, sourceChain, targetChain) {
266
+ try {
267
+ const response = await withFailover((baseUrl) => fetch(`${baseUrl}/chain/${sourceChain}/pact/spv`, {
268
+ method: "POST",
269
+ headers: { "Content-Type": "application/json" },
270
+ body: JSON.stringify({
271
+ requestKey,
272
+ targetChainId: targetChain,
273
+ }),
274
+ signal: AbortSignal.timeout(SPV_PROOF_TIMEOUT_MS),
275
+ }));
276
+ if (!response.ok) {
277
+ const errorText = await response.text();
278
+ // Chainweb returns 400 "not available" while the proof is still being
279
+ // generated (pre-finality). pollSpvProof's outer loop translates this
280
+ // into "wait and try again" — pass null + descriptive error.
281
+ if (response.status === 400 && errorText.includes("not available")) {
282
+ return { proof: null, error: "SPV proof not ready yet. Please wait for block confirmation." };
283
+ }
284
+ return { proof: null, error: `Failed to fetch SPV proof: ${errorText}` };
285
+ }
286
+ const proof = await response.text();
287
+ // Remove quotes if present (API returns JSON string)
288
+ const cleanProof = proof.replace(/^"|"$/g, "");
289
+ return { proof: cleanProof };
290
+ }
291
+ catch (error) {
292
+ // AbortError surfaces here when the 30s timeout fires. withFailover
293
+ // will already have retried on fallback by this point — if BOTH primary
294
+ // and fallback timed out (or otherwise failed), the error propagates
295
+ // out as the standard `{ proof: null, error }` shape so the polling
296
+ // loop above can decide whether to retry the whole sequence.
297
+ const message = error instanceof Error
298
+ ? (error.name === "TimeoutError" || error.name === "AbortError"
299
+ ? `SPV proof fetch timed out after ${SPV_PROOF_TIMEOUT_MS}ms (both primary and fallback nodes)`
300
+ : error.message)
301
+ : "Failed to fetch SPV proof";
302
+ return {
303
+ proof: null,
304
+ error: message,
305
+ };
306
+ }
307
+ }
308
+ /**
309
+ * Poll for SPV proof with retry logic
310
+ * Will retry until proof is available or max attempts reached
311
+ */
312
+ export async function pollSpvProof(requestKey, sourceChain, targetChain, maxAttempts = 30, delayMs = 5000, onProgress) {
313
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
314
+ onProgress?.(attempt, maxAttempts);
315
+ const result = await fetchSpvProof(requestKey, sourceChain, targetChain);
316
+ if (result.proof) {
317
+ return result;
318
+ }
319
+ if (attempt < maxAttempts) {
320
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
321
+ }
322
+ }
323
+ return { proof: null, error: "Timeout waiting for SPV proof" };
324
+ }
325
+ /**
326
+ * Build a continuation transaction for step 2 of cross-chain transfer
327
+ * This can be executed by anyone - no signature required from original sender
328
+ */
329
+ export function buildContinuationTransaction(pactId, proof, targetChain, gasPayerAccount = "kadena-xchain-gas") {
330
+ const transaction = Pact.builder
331
+ .continuation({
332
+ pactId,
333
+ rollback: false,
334
+ step: 1,
335
+ proof,
336
+ })
337
+ .setMeta({
338
+ chainId: targetChain,
339
+ senderAccount: gasPayerAccount,
340
+ gasLimit: 850,
341
+ gasPrice: 0.00000001,
342
+ ttl: 28800,
343
+ })
344
+ .setNetworkId(KADENA_NETWORK)
345
+ .createTransaction();
346
+ return transaction;
347
+ }
348
+ /**
349
+ * Submit a continuation transaction.
350
+ *
351
+ * Note: for the public gas station path (chain 0 + DALOS.GAS_PAYER), no
352
+ * signature is needed — the caller passes the unsigned `transaction`
353
+ * directly. For user-paid-gas paths the transaction MUST be signed before
354
+ * this function is called; the function itself does not sign.
355
+ *
356
+ * **Error contract** (closes audit finding F-ERR-001 — v3.2.3): same
357
+ * propagating-throw pattern as `submitCrossChainTransfer`. A failed
358
+ * continuation submit is a hard failure, not a transient state — surface
359
+ * to the user, don't swallow.
360
+ *
361
+ * @throws {SigningError} with `code: "TIMEOUT"` if `submit()` exceeds
362
+ * the per-tier deadline.
363
+ * @throws {Error} On network failure surviving both primary and fallback
364
+ * node attempts.
365
+ */
366
+ export async function submitContinuation(transaction, targetChain) {
367
+ const { submit } = getFailoverClient(targetChain);
368
+ return await submit(transaction);
369
+ }
370
+ /**
371
+ * Listen for transaction completion (long-poll for chainweb inclusion).
372
+ *
373
+ * Resolves to the chainweb command-result envelope when the transaction
374
+ * is included in a block (~30-180s on mainnet depending on block density).
375
+ *
376
+ * **Error contract** (closes audit finding F-ERR-001 — v3.2.3): a thrown
377
+ * error from this function is **NOT** a definitive failure. The chainweb
378
+ * `listen` endpoint times out after a per-tier deadline (default 180s,
379
+ * approximately 6 Kadena blocks); if the deadline fires, the transaction
380
+ * may still complete on chain — it just hasn't been included yet by the
381
+ * time this function gives up. Callers should treat a `SigningError(code:
382
+ * "TIMEOUT")` from this function as `status: "pending"` (poll again
383
+ * later via `pollTransactionStatus`), NOT as `status: "failed"` (do not
384
+ * retry the submit; it would double-pay gas for a transaction that may
385
+ * already be confirmed). This is the exact pattern that audit finding
386
+ * F-ERR-014 surfaced for the multi-step add-liquidity flow before that
387
+ * surface was deleted in v3.2.2.
388
+ *
389
+ * @throws {SigningError} with `code: "TIMEOUT"` if `listen()` exceeds
390
+ * the 180s deadline. **Treat as pending, not failed.**
391
+ * @throws {Error} On network failure surviving both primary and fallback
392
+ * node attempts.
393
+ */
394
+ export async function listenForCompletion(requestKey, chainId) {
395
+ const { listen } = getFailoverClient(chainId);
396
+ return await listen({ requestKey, chainId: chainId, networkId: KADENA_NETWORK });
397
+ }
398
+ /**
399
+ * Simulate a Pact code execution to check if it will succeed.
400
+ *
401
+ * Public-API break (v1.8): the first parameter is now the raw Pact code string
402
+ * rather than a built transaction. Consumers that previously held the built
403
+ * transaction now hold the pact-code string they fed into `.execution(...)`.
404
+ */
405
+ export async function simulateTransaction(pactCode, chainId) {
406
+ try {
407
+ const result = await pactRead(pactCode, {
408
+ pactUrl: getPactUrl(chainId),
409
+ chainId,
410
+ tier: "T2",
411
+ });
412
+ if (result.result.status === "failure") {
413
+ return {
414
+ success: false,
415
+ error: result.result.error?.message || "Simulation failed",
416
+ result,
417
+ };
418
+ }
419
+ return {
420
+ success: true,
421
+ result,
422
+ gas: result.gas,
423
+ };
424
+ }
425
+ catch (error) {
426
+ return {
427
+ success: false,
428
+ error: error instanceof Error ? error.message : "Simulation failed",
429
+ };
430
+ }
431
+ }
432
+ /**
433
+ * Get pending cross-chain transfers for an account
434
+ * Checks for continuation status
435
+ */
436
+ export async function getContinuationStatus(requestKey, sourceChain) {
437
+ try {
438
+ const status = await pollTransactionStatus(requestKey, sourceChain);
439
+ if (status.status === "not-found") {
440
+ return { exists: false, completed: false, error: "Transaction not found" };
441
+ }
442
+ if (status.status === "failure") {
443
+ return { exists: true, completed: false, error: status.error };
444
+ }
445
+ if (status.continuation) {
446
+ return {
447
+ exists: true,
448
+ completed: false,
449
+ pactId: status.continuation.pactId,
450
+ step: status.continuation.step,
451
+ };
452
+ }
453
+ // If no continuation info, transaction might be complete
454
+ return { exists: true, completed: true };
455
+ }
456
+ catch (error) {
457
+ return {
458
+ exists: false,
459
+ completed: false,
460
+ error: error instanceof Error ? error.message : "Unknown error",
461
+ };
462
+ }
463
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * dexAcquisitionPoolFunctions.ts
3
+ *
4
+ * Acquisition Pool (AP) entity — placeholder file.
5
+ *
6
+ * The Acquisition Pool is one of Ouronet's seven entity types per the locked
7
+ * taxonomy (TF, OF, Collectables [Semi+Non Fungibles], ASP, SWP, AP). Its Pact
8
+ * module is **pending deployment** — chain-call functions for read/execute
9
+ * surfaces will be added to this file once the AP Pact module ships.
10
+ *
11
+ * This placeholder anchors the AP entity in the entity-oriented file layout so
12
+ * downstream consumers (OuronetUI, AncientHolder HUB) can see the entity exists
13
+ * in the taxonomy even though no chain calls are wired yet.
14
+ *
15
+ * See the v4.2.0 integration guide (Phase 8) for the seven-entity taxonomy
16
+ * documentation and AP-specific roadmap notes.
17
+ */
18
+ export {};
@@ -0,0 +1,18 @@
1
+ /**
2
+ * dexAcquisitionPoolFunctions.ts
3
+ *
4
+ * Acquisition Pool (AP) entity — placeholder file.
5
+ *
6
+ * The Acquisition Pool is one of Ouronet's seven entity types per the locked
7
+ * taxonomy (TF, OF, Collectables [Semi+Non Fungibles], ASP, SWP, AP). Its Pact
8
+ * module is **pending deployment** — chain-call functions for read/execute
9
+ * surfaces will be added to this file once the AP Pact module ships.
10
+ *
11
+ * This placeholder anchors the AP entity in the entity-oriented file layout so
12
+ * downstream consumers (OuronetUI, AncientHolder HUB) can see the entity exists
13
+ * in the taxonomy even though no chain calls are wired yet.
14
+ *
15
+ * See the v4.2.0 integration guide (Phase 8) for the seven-entity taxonomy
16
+ * documentation and AP-specific roadmap notes.
17
+ */
18
+ export {};
@@ -0,0 +1,28 @@
1
+ /**
2
+ * dexCollectablesFunctions.ts
3
+ * Collectables (Semi + Non Fungibles) entity reads — header, entries, nonce data, sets, filters, button state.
4
+ */
5
+ import type { CollectablesHeaderData, CollectableEntryData, NonceData, SetDefinition, CollectablesButtonState } from "./dexTypes.js";
6
+ export declare function getCollectablesHeader(account: string): Promise<CollectablesHeaderData | null>;
7
+ export declare function getSemifungibleEntries(account: string, dpdcIds: string[]): Promise<(CollectableEntryData | null)[]>;
8
+ export declare function getNonfungibleEntries(account: string, dpdcIds: string[]): Promise<(CollectableEntryData | null)[]>;
9
+ export declare function getCollectableNonceData(dpdcId: string, isSFT: boolean, nonces: number[]): Promise<NonceData[]>;
10
+ export declare function getCollectableNonceSupply(dpdcId: string, isSFT: boolean, nonce: number): Promise<number>;
11
+ /**
12
+ * Batched per-account per-nonce supplies (DPDC.UR_AccountNoncesSupplies).
13
+ * Replaces the per-nonce UR_NonceSupply loop with a single read for N nonces.
14
+ */
15
+ export declare function getAccountNoncesSupplies(account: string, dpdcId: string, isSFT: boolean, nonces: number[]): Promise<number[]>;
16
+ export declare function getCollectableSets(dpdcId: string, isSFT: boolean): Promise<SetDefinition[]>;
17
+ /**
18
+ * Filter wallet nonces by nonce class for composite set positions.
19
+ * Returns only the nonces that match the given class.
20
+ */
21
+ export declare function filterNoncesByClass(dpdcId: string, isSFT: boolean, nonces: number[], nonceClass: number): Promise<number[]>;
22
+ /**
23
+ * Batched filter-nonces-by-classes (URC_0025a_FilterNoncesByClasses).
24
+ * One network call returns one filtered nonce list per class, in order.
25
+ * Replaces N per-position calls to filterNoncesByClass.
26
+ */
27
+ export declare function filterNoncesByClasses(dpdcId: string, isSFT: boolean, nonces: number[], nonceClasses: number[]): Promise<number[][]>;
28
+ export declare function getCollectablesButtonState(account: string, dpdcId: string, isSFT: boolean, selectedNonces: number[]): Promise<CollectablesButtonState | null>;