@algorandfoundation/algokit-utils 10.0.0-alpha.31 → 10.0.0-alpha.32

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 (318) hide show
  1. package/account-manager.d.ts +448 -0
  2. package/account-manager.js +623 -0
  3. package/account-manager.js.map +1 -0
  4. package/account-manager.mjs +620 -0
  5. package/account-manager.mjs.map +1 -0
  6. package/account.d.ts +156 -0
  7. package/account.js +10 -0
  8. package/account.js.map +1 -0
  9. package/account.mjs +9 -0
  10. package/account.mjs.map +1 -0
  11. package/algorand-client-transaction-creator.d.ts +1103 -0
  12. package/algorand-client-transaction-creator.js +735 -0
  13. package/algorand-client-transaction-creator.js.map +1 -0
  14. package/algorand-client-transaction-creator.mjs +734 -0
  15. package/algorand-client-transaction-creator.mjs.map +1 -0
  16. package/algorand-client-transaction-sender.d.ts +1317 -0
  17. package/algorand-client-transaction-sender.js +933 -0
  18. package/algorand-client-transaction-sender.js.map +1 -0
  19. package/algorand-client-transaction-sender.mjs +932 -0
  20. package/algorand-client-transaction-sender.mjs.map +1 -0
  21. package/algorand-client.d.ts +246 -0
  22. package/algorand-client.js +325 -0
  23. package/algorand-client.js.map +1 -0
  24. package/algorand-client.mjs +325 -0
  25. package/algorand-client.mjs.map +1 -0
  26. package/amount.d.ts +46 -3
  27. package/amount.js +92 -13
  28. package/amount.js.map +1 -1
  29. package/amount.mjs +80 -3
  30. package/amount.mjs.map +1 -1
  31. package/app-client.d.ts +2130 -0
  32. package/app-client.js +909 -0
  33. package/app-client.js.map +1 -0
  34. package/app-client.mjs +908 -0
  35. package/app-client.mjs.map +1 -0
  36. package/app-deployer.d.ts +166 -0
  37. package/app-deployer.js +353 -0
  38. package/app-deployer.js.map +1 -0
  39. package/app-deployer.mjs +353 -0
  40. package/app-deployer.mjs.map +1 -0
  41. package/app-factory.d.ts +965 -0
  42. package/app-factory.js +448 -0
  43. package/app-factory.js.map +1 -0
  44. package/app-factory.mjs +448 -0
  45. package/app-factory.mjs.map +1 -0
  46. package/app-manager.d.ts +323 -0
  47. package/app-manager.js +468 -0
  48. package/app-manager.js.map +1 -0
  49. package/app-manager.mjs +468 -0
  50. package/app-manager.mjs.map +1 -0
  51. package/app-spec.d.ts +203 -0
  52. package/app-spec.js +137 -0
  53. package/app-spec.js.map +1 -0
  54. package/app-spec.mjs +137 -0
  55. package/app-spec.mjs.map +1 -0
  56. package/app.d.ts +257 -0
  57. package/app.js +49 -0
  58. package/app.js.map +1 -0
  59. package/app.mjs +42 -0
  60. package/app.mjs.map +1 -0
  61. package/asset-manager.d.ts +212 -0
  62. package/asset-manager.js +166 -0
  63. package/asset-manager.js.map +1 -0
  64. package/asset-manager.mjs +166 -0
  65. package/asset-manager.mjs.map +1 -0
  66. package/async-event-emitter.d.ts +16 -0
  67. package/async-event-emitter.js +38 -0
  68. package/async-event-emitter.js.map +1 -0
  69. package/async-event-emitter.mjs +37 -0
  70. package/async-event-emitter.mjs.map +1 -0
  71. package/client-manager.d.ts +475 -0
  72. package/client-manager.js +616 -0
  73. package/client-manager.js.map +1 -0
  74. package/client-manager.mjs +616 -0
  75. package/client-manager.mjs.map +1 -0
  76. package/composer.d.ts +947 -0
  77. package/composer.js +1584 -0
  78. package/composer.js.map +1 -0
  79. package/composer.mjs +1583 -0
  80. package/composer.mjs.map +1 -0
  81. package/config.d.ts +1 -1
  82. package/config.js +2 -2
  83. package/config.js.map +1 -1
  84. package/config.mjs +1 -1
  85. package/config.mjs.map +1 -1
  86. package/debugging.d.ts +47 -0
  87. package/debugging.js +20 -0
  88. package/debugging.js.map +1 -0
  89. package/debugging.mjs +15 -0
  90. package/debugging.mjs.map +1 -0
  91. package/dispenser-client.d.ts +90 -0
  92. package/dispenser-client.js +127 -0
  93. package/dispenser-client.js.map +1 -0
  94. package/dispenser-client.mjs +127 -0
  95. package/dispenser-client.mjs.map +1 -0
  96. package/expand.d.ts +2 -0
  97. package/expand.js +0 -0
  98. package/expand.mjs +0 -0
  99. package/index.d.ts +6 -5
  100. package/index.js +4 -3
  101. package/index.mjs +5 -5
  102. package/indexer-client/indexer-lookup.d.ts +1 -1
  103. package/indexer-client/indexer-lookup.js.map +1 -1
  104. package/indexer-client/indexer-lookup.mjs.map +1 -1
  105. package/indexer.d.ts +40 -0
  106. package/indexer.js +38 -0
  107. package/indexer.js.map +1 -0
  108. package/indexer.mjs +35 -0
  109. package/indexer.mjs.map +1 -0
  110. package/instance-of.d.ts +8 -0
  111. package/kmd-account-manager.d.ts +74 -0
  112. package/kmd-account-manager.js +167 -0
  113. package/kmd-account-manager.js.map +1 -0
  114. package/kmd-account-manager.mjs +165 -0
  115. package/kmd-account-manager.mjs.map +1 -0
  116. package/lifecycle-events.d.ts +14 -0
  117. package/lifecycle-events.js +11 -0
  118. package/lifecycle-events.js.map +1 -0
  119. package/lifecycle-events.mjs +10 -0
  120. package/lifecycle-events.mjs.map +1 -0
  121. package/logging.d.ts +13 -0
  122. package/logging.js +47 -0
  123. package/logging.js.map +1 -0
  124. package/logging.mjs +42 -0
  125. package/logging.mjs.map +1 -0
  126. package/logic-error.d.ts +39 -0
  127. package/logic-error.js +54 -0
  128. package/logic-error.js.map +1 -0
  129. package/logic-error.mjs +53 -0
  130. package/logic-error.mjs.map +1 -0
  131. package/network-client.d.ts +43 -0
  132. package/network-client.js +14 -0
  133. package/network-client.js.map +1 -0
  134. package/network-client.mjs +13 -0
  135. package/network-client.mjs.map +1 -0
  136. package/package.json +11 -1
  137. package/testing/account.d.ts +2 -2
  138. package/testing/account.js +1 -1
  139. package/testing/account.js.map +1 -1
  140. package/testing/account.mjs +1 -1
  141. package/testing/account.mjs.map +1 -1
  142. package/testing/fixtures/algokit-log-capture-fixture.d.ts +1 -1
  143. package/testing/fixtures/algokit-log-capture-fixture.js.map +1 -1
  144. package/testing/fixtures/algokit-log-capture-fixture.mjs.map +1 -1
  145. package/testing/fixtures/algorand-fixture.d.ts +2 -2
  146. package/testing/fixtures/algorand-fixture.js +2 -2
  147. package/testing/fixtures/algorand-fixture.js.map +1 -1
  148. package/testing/fixtures/algorand-fixture.mjs +2 -2
  149. package/testing/fixtures/algorand-fixture.mjs.map +1 -1
  150. package/testing/index.d.ts +2 -1
  151. package/testing/test-logger.d.ts +1 -1
  152. package/testing/test-logger.js.map +1 -1
  153. package/testing/test-logger.mjs.map +1 -1
  154. package/testing/types.d.ts +156 -0
  155. package/transaction/index.d.ts +4 -0
  156. package/transaction/index.js +9 -0
  157. package/transaction/index.mjs +4 -0
  158. package/transaction/perform-transaction-composer-simulate.d.ts +1 -1
  159. package/transaction/perform-transaction-composer-simulate.js.map +1 -1
  160. package/transaction/perform-transaction-composer-simulate.mjs.map +1 -1
  161. package/transaction/transaction.d.ts +2 -2
  162. package/transaction/transaction.js.map +1 -1
  163. package/transaction/transaction.mjs.map +1 -1
  164. package/transaction/types.d.ts +133 -0
  165. package/transactions/app-call.d.ts +1 -1
  166. package/transactions/app-call.js +1 -1
  167. package/transactions/app-call.js.map +1 -1
  168. package/transactions/app-call.mjs +1 -1
  169. package/transactions/app-call.mjs.map +1 -1
  170. package/transactions/common.d.ts +1 -1
  171. package/transactions/common.js.map +1 -1
  172. package/transactions/common.mjs.map +1 -1
  173. package/transactions/method-call.d.ts +1 -1
  174. package/transactions/method-call.js +1 -1
  175. package/transactions/method-call.js.map +1 -1
  176. package/transactions/method-call.mjs +1 -1
  177. package/transactions/method-call.mjs.map +1 -1
  178. package/transactions/payment.d.ts +1 -1
  179. package/transactions/payment.js.map +1 -1
  180. package/transactions/payment.mjs.map +1 -1
  181. package/types/account-manager.d.ts +11 -442
  182. package/types/account-manager.js +5 -616
  183. package/types/account-manager.js.map +1 -1
  184. package/types/account-manager.mjs +5 -614
  185. package/types/account-manager.mjs.map +1 -1
  186. package/types/account.d.ts +8 -150
  187. package/types/account.js +3 -4
  188. package/types/account.js.map +1 -1
  189. package/types/account.mjs +4 -4
  190. package/types/account.mjs.map +1 -1
  191. package/types/algorand-client-transaction-creator.d.ts +5 -1098
  192. package/types/algorand-client-transaction-creator.js +3 -729
  193. package/types/algorand-client-transaction-creator.js.map +1 -1
  194. package/types/algorand-client-transaction-creator.mjs +4 -729
  195. package/types/algorand-client-transaction-creator.mjs.map +1 -1
  196. package/types/algorand-client-transaction-sender.d.ts +5 -1312
  197. package/types/algorand-client-transaction-sender.js +3 -927
  198. package/types/algorand-client-transaction-sender.js.map +1 -1
  199. package/types/algorand-client-transaction-sender.mjs +3 -926
  200. package/types/algorand-client-transaction-sender.mjs.map +1 -1
  201. package/types/algorand-client.d.ts +5 -241
  202. package/types/algorand-client.js +3 -319
  203. package/types/algorand-client.js.map +1 -1
  204. package/types/algorand-client.mjs +3 -319
  205. package/types/algorand-client.mjs.map +1 -1
  206. package/types/amount.d.ts +6 -45
  207. package/types/amount.js +3 -79
  208. package/types/amount.js.map +1 -1
  209. package/types/amount.mjs +4 -79
  210. package/types/amount.mjs.map +1 -1
  211. package/types/app-client.d.ts +75 -2125
  212. package/types/app-client.js +3 -903
  213. package/types/app-client.js.map +1 -1
  214. package/types/app-client.mjs +3 -902
  215. package/types/app-client.mjs.map +1 -1
  216. package/types/app-deployer.d.ts +21 -161
  217. package/types/app-deployer.js +3 -347
  218. package/types/app-deployer.js.map +1 -1
  219. package/types/app-deployer.mjs +3 -347
  220. package/types/app-deployer.mjs.map +1 -1
  221. package/types/app-factory.d.ts +21 -960
  222. package/types/app-factory.js +3 -442
  223. package/types/app-factory.js.map +1 -1
  224. package/types/app-factory.mjs +3 -442
  225. package/types/app-factory.mjs.map +1 -1
  226. package/types/app-manager.d.ts +15 -318
  227. package/types/app-manager.js +3 -462
  228. package/types/app-manager.js.map +1 -1
  229. package/types/app-manager.mjs +3 -462
  230. package/types/app-manager.mjs.map +1 -1
  231. package/types/app-spec.d.ts +39 -198
  232. package/types/app-spec.js +3 -131
  233. package/types/app-spec.js.map +1 -1
  234. package/types/app-spec.mjs +3 -131
  235. package/types/app-spec.mjs.map +1 -1
  236. package/types/app.d.ts +62 -247
  237. package/types/app.js +15 -37
  238. package/types/app.js.map +1 -1
  239. package/types/app.mjs +16 -37
  240. package/types/app.mjs.map +1 -1
  241. package/types/asset-manager.d.ts +9 -207
  242. package/types/asset-manager.js +3 -160
  243. package/types/asset-manager.js.map +1 -1
  244. package/types/asset-manager.mjs +3 -160
  245. package/types/asset-manager.mjs.map +1 -1
  246. package/types/async-event-emitter.d.ts +7 -11
  247. package/types/async-event-emitter.js +3 -32
  248. package/types/async-event-emitter.js.map +1 -1
  249. package/types/async-event-emitter.mjs +4 -32
  250. package/types/async-event-emitter.mjs.map +1 -1
  251. package/types/client-manager.d.ts +27 -470
  252. package/types/client-manager.js +3 -610
  253. package/types/client-manager.js.map +1 -1
  254. package/types/client-manager.mjs +3 -610
  255. package/types/client-manager.mjs.map +1 -1
  256. package/types/composer.d.ts +79 -943
  257. package/types/composer.js +3 -1578
  258. package/types/composer.js.map +1 -1
  259. package/types/composer.mjs +3 -1577
  260. package/types/composer.mjs.map +1 -1
  261. package/types/config.d.ts +7 -52
  262. package/types/config.js +3 -74
  263. package/types/config.js.map +1 -1
  264. package/types/config.mjs +3 -74
  265. package/types/config.mjs.map +1 -1
  266. package/types/debugging.d.ts +12 -37
  267. package/types/debugging.js +11 -10
  268. package/types/debugging.js.map +1 -1
  269. package/types/debugging.mjs +12 -10
  270. package/types/debugging.mjs.map +1 -1
  271. package/types/dispenser-client.d.ts +11 -85
  272. package/types/dispenser-client.js +3 -121
  273. package/types/dispenser-client.js.map +1 -1
  274. package/types/dispenser-client.mjs +3 -121
  275. package/types/dispenser-client.mjs.map +1 -1
  276. package/types/expand.d.ts +8 -2
  277. package/types/indexer.d.ts +16 -36
  278. package/types/indexer.js +7 -30
  279. package/types/indexer.js.map +1 -1
  280. package/types/indexer.mjs +8 -30
  281. package/types/indexer.mjs.map +1 -1
  282. package/types/instance-of.d.ts +4 -4
  283. package/types/kmd-account-manager.d.ts +5 -69
  284. package/types/kmd-account-manager.js +3 -161
  285. package/types/kmd-account-manager.js.map +1 -1
  286. package/types/kmd-account-manager.mjs +3 -159
  287. package/types/kmd-account-manager.mjs.map +1 -1
  288. package/types/lifecycle-events.d.ts +7 -9
  289. package/types/lifecycle-events.js +3 -5
  290. package/types/lifecycle-events.js.map +1 -1
  291. package/types/lifecycle-events.mjs +4 -5
  292. package/types/lifecycle-events.mjs.map +1 -1
  293. package/types/logging.d.ts +14 -9
  294. package/types/logging.js +11 -37
  295. package/types/logging.js.map +1 -1
  296. package/types/logging.mjs +12 -37
  297. package/types/logging.mjs.map +1 -1
  298. package/types/logic-error.d.ts +8 -35
  299. package/types/logic-error.js +3 -48
  300. package/types/logic-error.js.map +1 -1
  301. package/types/logic-error.mjs +4 -48
  302. package/types/logic-error.mjs.map +1 -1
  303. package/types/network-client.d.ts +10 -39
  304. package/types/network-client.js +3 -8
  305. package/types/network-client.js.map +1 -1
  306. package/types/network-client.mjs +4 -8
  307. package/types/network-client.mjs.map +1 -1
  308. package/types/testing.d.ts +13 -151
  309. package/types/transaction.d.ts +33 -128
  310. package/updatable-config.d.ts +57 -0
  311. package/updatable-config.js +80 -0
  312. package/updatable-config.js.map +1 -0
  313. package/updatable-config.mjs +80 -0
  314. package/updatable-config.mjs.map +1 -0
  315. package/util.js +1 -1
  316. package/util.js.map +1 -1
  317. package/util.mjs +1 -1
  318. package/util.mjs.map +1 -1
package/composer.mjs ADDED
@@ -0,0 +1,1583 @@
1
+ import { EMPTY_SIGNATURE, MAX_TRANSACTION_GROUP_SIZE } from "./packages/common/src/constants.mjs";
2
+ import { AlgoAmount } from "./amount.mjs";
3
+ import { Config } from "./config.mjs";
4
+ import { asJson } from "./util.mjs";
5
+ import { waitForConfirmation } from "./transaction/transaction.mjs";
6
+ import { OnApplicationComplete } from "./packages/transact/src/transactions/app-call.mjs";
7
+ import { TransactionType } from "./packages/transact/src/transactions/transaction-type.mjs";
8
+ import { Transaction, assignFee, calculateFee, decodeTransaction, encodeTransactionRaw, groupTransactions, validateTransaction } from "./packages/transact/src/transactions/transaction.mjs";
9
+ import { decodeSignedTransactions } from "./packages/transact/src/transactions/signed-transaction.mjs";
10
+ import { makeEmptyTransactionSigner } from "./packages/transact/src/signer.mjs";
11
+ import { AppManager } from "./app-manager.mjs";
12
+ import { buildAppCall, buildAppCreate, buildAppUpdate, populateGroupResources, populateTransactionResources } from "./transactions/app-call.mjs";
13
+ import { buildAssetOptIn, buildAssetOptOut, buildAssetTransfer } from "./transactions/asset-transfer.mjs";
14
+ import { EventType } from "./lifecycle-events.mjs";
15
+ import { genesisIdIsLocalNet } from "./network-client.mjs";
16
+ import { buildAssetConfig, buildAssetCreate, buildAssetDestroy, buildAssetFreeze } from "./transactions/asset-config.mjs";
17
+ import { FeeDelta, FeePriority, calculateInnerFeeDelta } from "./transactions/fee-coverage.mjs";
18
+ import { buildKeyReg } from "./transactions/key-registration.mjs";
19
+ import { buildAppCallMethodCall, buildAppCreateMethodCall, buildAppUpdateMethodCall, extractComposerTransactionsFromAppMethodCallParams, processAppMethodCallArgs } from "./transactions/method-call.mjs";
20
+ import { buildPayment } from "./transactions/payment.mjs";
21
+ import { Buffer } from "buffer";
22
+
23
+ //#region src/composer.ts
24
+ var InvalidErrorTransformerValue = class extends Error {
25
+ constructor(originalError, value) {
26
+ super(`An error transformer returned a non-error value: ${value}. The original error before any transformation: ${originalError}`);
27
+ }
28
+ };
29
+ var ErrorTransformerError = class extends Error {
30
+ constructor(originalError, cause) {
31
+ super(`An error transformer threw an error: ${cause}. The original error before any transformation: ${originalError} `, { cause });
32
+ }
33
+ };
34
+ /** TransactionComposer helps you compose and execute transactions as a transaction group. */
35
+ var TransactionComposer = class TransactionComposer {
36
+ /** Transactions that have not yet been composed */
37
+ txns = [];
38
+ /** The algod client used by the composer. */
39
+ algod;
40
+ /** An async function that will return suggested params for the transaction. */
41
+ getSuggestedParams;
42
+ /** A function that takes in an address and return a signer function for that address. */
43
+ getSigner;
44
+ /** The default transaction validity window */
45
+ defaultValidityWindow = 10n;
46
+ /** Whether the validity window was explicitly set on construction */
47
+ defaultValidityWindowIsExplicit = false;
48
+ appManager;
49
+ errorTransformers;
50
+ composerConfig;
51
+ transactionsWithSigners;
52
+ signedTransactions;
53
+ rawBuildTransactions;
54
+ async transformError(originalError) {
55
+ if (!(originalError instanceof Error)) return originalError;
56
+ let transformedError = originalError;
57
+ for (const transformer of this.errorTransformers) try {
58
+ transformedError = await transformer(transformedError);
59
+ if (!(transformedError instanceof Error)) return new InvalidErrorTransformerValue(originalError, transformedError);
60
+ } catch (errorFromTransformer) {
61
+ return new ErrorTransformerError(originalError, errorFromTransformer);
62
+ }
63
+ return transformedError;
64
+ }
65
+ validateReferenceParams(params) {
66
+ if (params.accessReferences && params.accessReferences.length > 0 && (params.appReferences && params.appReferences.length > 0 || params.assetReferences && params.assetReferences.length > 0 || params.boxReferences && params.boxReferences.length > 0)) throw new Error("Cannot specify both `accessReferences` and reference arrays (`appReferences`, `assetReferences`, `boxReferences`).");
67
+ }
68
+ /**
69
+ * Create a `TransactionComposer`.
70
+ * @param params The configuration for this composer
71
+ * @returns The `TransactionComposer` instance
72
+ */
73
+ constructor(params) {
74
+ this.algod = params.algod;
75
+ const defaultGetSuggestedParams = () => params.algod.suggestedParams();
76
+ this.getSuggestedParams = params.getSuggestedParams ?? defaultGetSuggestedParams;
77
+ this.getSigner = params.getSigner;
78
+ this.defaultValidityWindow = params.defaultValidityWindow ?? this.defaultValidityWindow;
79
+ this.defaultValidityWindowIsExplicit = params.defaultValidityWindow !== void 0;
80
+ this.appManager = params.appManager ?? new AppManager(params.algod);
81
+ this.errorTransformers = params.errorTransformers ?? [];
82
+ this.composerConfig = params.composerConfig ?? {
83
+ coverAppCallInnerTransactionFees: false,
84
+ populateAppCallResources: true
85
+ };
86
+ }
87
+ cloneTransaction(txn) {
88
+ switch (txn.type) {
89
+ case "pay": return {
90
+ type: "pay",
91
+ data: { ...txn.data }
92
+ };
93
+ case "assetCreate": return {
94
+ type: "assetCreate",
95
+ data: { ...txn.data }
96
+ };
97
+ case "assetConfig": return {
98
+ type: "assetConfig",
99
+ data: { ...txn.data }
100
+ };
101
+ case "assetFreeze": return {
102
+ type: "assetFreeze",
103
+ data: { ...txn.data }
104
+ };
105
+ case "assetDestroy": return {
106
+ type: "assetDestroy",
107
+ data: { ...txn.data }
108
+ };
109
+ case "assetTransfer": return {
110
+ type: "assetTransfer",
111
+ data: { ...txn.data }
112
+ };
113
+ case "assetOptIn": return {
114
+ type: "assetOptIn",
115
+ data: { ...txn.data }
116
+ };
117
+ case "assetOptOut": return {
118
+ type: "assetOptOut",
119
+ data: { ...txn.data }
120
+ };
121
+ case "appCall": return {
122
+ type: "appCall",
123
+ data: { ...txn.data }
124
+ };
125
+ case "keyReg": return {
126
+ type: "keyReg",
127
+ data: { ...txn.data }
128
+ };
129
+ case "txn": {
130
+ const { txn: transaction, signer, maxFee } = txn.data;
131
+ const clonedTxn = decodeTransaction(encodeTransactionRaw(transaction));
132
+ delete clonedTxn.group;
133
+ return {
134
+ type: "txn",
135
+ data: {
136
+ txn: clonedTxn,
137
+ signer,
138
+ maxFee
139
+ }
140
+ };
141
+ }
142
+ case "asyncTxn": {
143
+ const { txn: txnPromise, signer, maxFee } = txn.data;
144
+ return {
145
+ type: "asyncTxn",
146
+ data: {
147
+ txn: txnPromise.then((resolvedTxn) => {
148
+ const clonedTxn = decodeTransaction(encodeTransactionRaw(resolvedTxn));
149
+ delete clonedTxn.group;
150
+ return clonedTxn;
151
+ }),
152
+ signer,
153
+ maxFee
154
+ }
155
+ };
156
+ }
157
+ case "methodCall": return {
158
+ type: "methodCall",
159
+ data: { ...txn.data }
160
+ };
161
+ }
162
+ }
163
+ push(...txns) {
164
+ if (this.transactionsWithSigners) throw new Error("Cannot add new transactions after building");
165
+ if (this.txns.length + txns.length > MAX_TRANSACTION_GROUP_SIZE) throw new Error(`Adding ${txns.length} transaction(s) would exceed the maximum group size. Current: ${this.txns.length}, Maximum: ${MAX_TRANSACTION_GROUP_SIZE}`);
166
+ this.txns.push(...txns);
167
+ }
168
+ clone(composerConfig) {
169
+ const newComposer = new TransactionComposer({
170
+ algod: this.algod,
171
+ getSuggestedParams: this.getSuggestedParams,
172
+ getSigner: this.getSigner,
173
+ defaultValidityWindow: this.defaultValidityWindow,
174
+ appManager: this.appManager,
175
+ errorTransformers: this.errorTransformers,
176
+ composerConfig: {
177
+ ...this.composerConfig,
178
+ ...composerConfig
179
+ }
180
+ });
181
+ this.txns.forEach((txn) => {
182
+ newComposer.txns.push(this.cloneTransaction(txn));
183
+ });
184
+ newComposer.defaultValidityWindowIsExplicit = this.defaultValidityWindowIsExplicit;
185
+ return newComposer;
186
+ }
187
+ /**
188
+ * Register a function that will be used to transform an error caught when simulating or executing
189
+ *
190
+ * @returns The composer so you can chain method calls
191
+ */
192
+ registerErrorTransformer(transformer) {
193
+ this.errorTransformers.push(transformer);
194
+ return this;
195
+ }
196
+ /**
197
+ * Add a pre-built transaction to the transaction group.
198
+ * @param transaction The pre-built transaction
199
+ * @param signer Optional signer override for the transaction
200
+ * @returns The composer so you can chain method calls
201
+ * @example
202
+ * ```typescript
203
+ * composer.addTransaction(txn)
204
+ * ```
205
+ */
206
+ addTransaction(transaction, signer) {
207
+ if (transaction.group) throw new Error("Cannot add a transaction to the composer because it is already in a group");
208
+ validateTransaction(transaction);
209
+ this.push({
210
+ data: {
211
+ txn: transaction,
212
+ signer: signer ?? this.getSigner(transaction.sender)
213
+ },
214
+ type: "txn"
215
+ });
216
+ return this;
217
+ }
218
+ /**
219
+ * Add another transaction composer to the current transaction composer.
220
+ * The transaction params of the input transaction composer will be added.
221
+ * If the input transaction composer is updated, it won't affect the current transaction composer.
222
+ * @param composer The transaction composer to add
223
+ * @returns The composer so you can chain method calls
224
+ * @example
225
+ * ```typescript
226
+ * const innerComposer = algorand.newGroup()
227
+ * .addPayment({ sender: 'SENDER', receiver: 'RECEIVER', amount: (1).algo() })
228
+ * .addPayment({ sender: 'SENDER', receiver: 'RECEIVER', amount: (2).algo() })
229
+ *
230
+ * composer.addTransactionComposer(innerComposer)
231
+ * ```
232
+ */
233
+ addTransactionComposer(composer) {
234
+ const clonedTxns = composer.txns.map((txn) => this.cloneTransaction(txn));
235
+ this.push(...clonedTxns);
236
+ return this;
237
+ }
238
+ /**
239
+ * Add a payment transaction to the transaction group.
240
+ * @param params The payment transaction parameters
241
+ * @returns The composer so you can chain method calls
242
+ * @example Basic example
243
+ * ```typescript
244
+ * composer.addPayment({
245
+ * sender: 'SENDERADDRESS',
246
+ * receiver: 'RECEIVERADDRESS',
247
+ * amount: (4).algo(),
248
+ * })
249
+ * ```
250
+ * @example Advanced example
251
+ * ```typescript
252
+ * composer.addPayment({
253
+ * amount: (4).algo(),
254
+ * receiver: 'RECEIVERADDRESS',
255
+ * sender: 'SENDERADDRESS',
256
+ * closeRemainderTo: 'CLOSEREMAINDERTOADDRESS',
257
+ * lease: 'lease',
258
+ * note: 'note',
259
+ * // Use this with caution, it's generally better to use algorand.account.rekeyAccount
260
+ * rekeyTo: 'REKEYTOADDRESS',
261
+ * // You wouldn't normally set this field
262
+ * firstValidRound: 1000n,
263
+ * validityWindow: 10,
264
+ * extraFee: (1000).microAlgo(),
265
+ * staticFee: (1000).microAlgo(),
266
+ * // Max fee doesn't make sense with extraFee AND staticFee
267
+ * // already specified, but here for completeness
268
+ * maxFee: (3000).microAlgo(),
269
+ * })
270
+ */
271
+ addPayment(params) {
272
+ this.push({
273
+ data: params,
274
+ type: "pay"
275
+ });
276
+ return this;
277
+ }
278
+ /**
279
+ * Add an asset create transaction to the transaction group.
280
+ * @param params The asset create transaction parameters
281
+ * @returns The composer so you can chain method calls
282
+ * @example Basic example
283
+ * ```typescript
284
+ * composer.addAssetCreate({ sender: "CREATORADDRESS", total: 100n})
285
+ * ```
286
+ * @example Advanced example
287
+ * ```typescript
288
+ * composer.addAssetCreate({
289
+ * sender: 'CREATORADDRESS',
290
+ * total: 100n,
291
+ * decimals: 2,
292
+ * assetName: 'asset',
293
+ * unitName: 'unit',
294
+ * url: 'url',
295
+ * metadataHash: 'metadataHash',
296
+ * defaultFrozen: false,
297
+ * manager: 'MANAGERADDRESS',
298
+ * reserve: 'RESERVEADDRESS',
299
+ * freeze: 'FREEZEADDRESS',
300
+ * clawback: 'CLAWBACKADDRESS',
301
+ * lease: 'lease',
302
+ * note: 'note',
303
+ * // You wouldn't normally set this field
304
+ * firstValidRound: 1000n,
305
+ * validityWindow: 10,
306
+ * extraFee: (1000).microAlgo(),
307
+ * staticFee: (1000).microAlgo(),
308
+ * // Max fee doesn't make sense with extraFee AND staticFee
309
+ * // already specified, but here for completeness
310
+ * maxFee: (3000).microAlgo(),
311
+ * })
312
+ */
313
+ addAssetCreate(params) {
314
+ this.push({
315
+ data: params,
316
+ type: "assetCreate"
317
+ });
318
+ return this;
319
+ }
320
+ /**
321
+ * Add an asset config transaction to the transaction group.
322
+ * @param params The asset config transaction parameters
323
+ * @returns The composer so you can chain method calls
324
+ * @example Basic example
325
+ * ```typescript
326
+ * composer.addAssetConfig({ sender: "MANAGERADDRESS", assetId: 123456n, manager: "MANAGERADDRESS" })
327
+ * ```
328
+ * @example Advanced example
329
+ * ```typescript
330
+ * composer.addAssetConfig({
331
+ * sender: 'MANAGERADDRESS',
332
+ * assetId: 123456n,
333
+ * manager: 'MANAGERADDRESS',
334
+ * reserve: 'RESERVEADDRESS',
335
+ * freeze: 'FREEZEADDRESS',
336
+ * clawback: 'CLAWBACKADDRESS',
337
+ * lease: 'lease',
338
+ * note: 'note',
339
+ * // You wouldn't normally set this field
340
+ * firstValidRound: 1000n,
341
+ * validityWindow: 10,
342
+ * extraFee: (1000).microAlgo(),
343
+ * staticFee: (1000).microAlgo(),
344
+ * // Max fee doesn't make sense with extraFee AND staticFee
345
+ * // already specified, but here for completeness
346
+ * maxFee: (3000).microAlgo(),
347
+ * })
348
+ */
349
+ addAssetConfig(params) {
350
+ this.push({
351
+ data: params,
352
+ type: "assetConfig"
353
+ });
354
+ return this;
355
+ }
356
+ /**
357
+ * Add an asset freeze transaction to the transaction group.
358
+ * @param params The asset freeze transaction parameters
359
+ * @returns The composer so you can chain method calls
360
+ * @example Basic example
361
+ * ```typescript
362
+ * composer.addAssetFreeze({ sender: "MANAGERADDRESS", assetId: 123456n, account: "ACCOUNTADDRESS", frozen: true })
363
+ * ```
364
+ * @example Advanced example
365
+ * ```typescript
366
+ * composer.addAssetFreeze({
367
+ * sender: 'MANAGERADDRESS',
368
+ * assetId: 123456n,
369
+ * account: 'ACCOUNTADDRESS',
370
+ * frozen: true,
371
+ * lease: 'lease',
372
+ * note: 'note',
373
+ * // You wouldn't normally set this field
374
+ * firstValidRound: 1000n,
375
+ * validityWindow: 10,
376
+ * extraFee: (1000).microAlgo(),
377
+ * staticFee: (1000).microAlgo(),
378
+ * // Max fee doesn't make sense with extraFee AND staticFee
379
+ * // already specified, but here for completeness
380
+ * maxFee: (3000).microAlgo(),
381
+ * })
382
+ * ```
383
+ */
384
+ addAssetFreeze(params) {
385
+ this.push({
386
+ data: params,
387
+ type: "assetFreeze"
388
+ });
389
+ return this;
390
+ }
391
+ /**
392
+ * Add an asset destroy transaction to the transaction group.
393
+ * @param params The asset destroy transaction parameters
394
+ * @returns The composer so you can chain method calls
395
+ * @example Basic example
396
+ * ```typescript
397
+ * composer.addAssetDestroy({ sender: "MANAGERADDRESS", assetId: 123456n })
398
+ * ```
399
+ * @example Advanced example
400
+ * ```typescript
401
+ * composer.addAssetDestroy({
402
+ * sender: 'MANAGERADDRESS',
403
+ * assetId: 123456n,
404
+ * lease: 'lease',
405
+ * note: 'note',
406
+ * // You wouldn't normally set this field
407
+ * firstValidRound: 1000n,
408
+ * validityWindow: 10,
409
+ * extraFee: (1000).microAlgo(),
410
+ * staticFee: (1000).microAlgo(),
411
+ * // Max fee doesn't make sense with extraFee AND staticFee
412
+ * // already specified, but here for completeness
413
+ * maxFee: (3000).microAlgo(),
414
+ * })
415
+ * ```
416
+ */
417
+ addAssetDestroy(params) {
418
+ this.push({
419
+ data: params,
420
+ type: "assetDestroy"
421
+ });
422
+ return this;
423
+ }
424
+ /**
425
+ * Add an asset transfer transaction to the transaction group.
426
+ * @param params The asset transfer transaction parameters
427
+ * @returns The composer so you can chain method calls
428
+ * @example Basic example
429
+ * ```typescript
430
+ * composer.addAssetTransfer({ sender: "HOLDERADDRESS", assetId: 123456n, amount: 1n, receiver: "RECEIVERADDRESS" })
431
+ * ```
432
+ * @example Advanced example (with clawback)
433
+ * ```typescript
434
+ * composer.addAssetTransfer({
435
+ * sender: 'CLAWBACKADDRESS',
436
+ * assetId: 123456n,
437
+ * amount: 1n,
438
+ * receiver: 'RECEIVERADDRESS',
439
+ * clawbackTarget: 'HOLDERADDRESS',
440
+ * // This field needs to be used with caution
441
+ * closeAssetTo: 'ADDRESSTOCLOSETO'
442
+ * lease: 'lease',
443
+ * note: 'note',
444
+ * // You wouldn't normally set this field
445
+ * firstValidRound: 1000n,
446
+ * validityWindow: 10,
447
+ * extraFee: (1000).microAlgo(),
448
+ * staticFee: (1000).microAlgo(),
449
+ * // Max fee doesn't make sense with extraFee AND staticFee
450
+ * // already specified, but here for completeness
451
+ * maxFee: (3000).microAlgo(),
452
+ * })
453
+ * ```
454
+ */
455
+ addAssetTransfer(params) {
456
+ this.push({
457
+ data: params,
458
+ type: "assetTransfer"
459
+ });
460
+ return this;
461
+ }
462
+ /**
463
+ * Add an asset opt-in transaction to the transaction group.
464
+ * @param params The asset opt-in transaction parameters
465
+ * @returns The composer so you can chain method calls
466
+ * @example Basic example
467
+ * ```typescript
468
+ * composer.addAssetOptIn({ sender: "SENDERADDRESS", assetId: 123456n })
469
+ * ```
470
+ * @example Advanced example
471
+ * ```typescript
472
+ * composer.addAssetOptIn({
473
+ * sender: 'SENDERADDRESS',
474
+ * assetId: 123456n,
475
+ * lease: 'lease',
476
+ * note: 'note',
477
+ * // You wouldn't normally set this field
478
+ * firstValidRound: 1000n,
479
+ * validityWindow: 10,
480
+ * extraFee: (1000).microAlgo(),
481
+ * staticFee: (1000).microAlgo(),
482
+ * // Max fee doesn't make sense with extraFee AND staticFee
483
+ * // already specified, but here for completeness
484
+ * maxFee: (3000).microAlgo(),
485
+ * })
486
+ * ```
487
+ */
488
+ addAssetOptIn(params) {
489
+ this.push({
490
+ data: params,
491
+ type: "assetOptIn"
492
+ });
493
+ return this;
494
+ }
495
+ /**
496
+ * Add an asset opt-out transaction to the transaction group.
497
+ * @param params The asset opt-out transaction parameters
498
+ * @returns The composer so you can chain method calls
499
+ * @example Basic example (without creator, will be retrieved from algod)
500
+ * ```typescript
501
+ * composer.addAssetOptOut({ sender: "SENDERADDRESS", assetId: 123456n, ensureZeroBalance: true })
502
+ * ```
503
+ * @example Basic example (with creator)
504
+ * ```typescript
505
+ * composer.addAssetOptOut({ sender: "SENDERADDRESS", creator: "CREATORADDRESS", assetId: 123456n, ensureZeroBalance: true })
506
+ * ```
507
+ * @example Advanced example
508
+ * ```typescript
509
+ * composer.addAssetOptOut({
510
+ * sender: 'SENDERADDRESS',
511
+ * assetId: 123456n,
512
+ * creator: 'CREATORADDRESS',
513
+ * ensureZeroBalance: true,
514
+ * lease: 'lease',
515
+ * note: 'note',
516
+ * // You wouldn't normally set this field
517
+ * firstValidRound: 1000n,
518
+ * validityWindow: 10,
519
+ * extraFee: (1000).microAlgo(),
520
+ * staticFee: (1000).microAlgo(),
521
+ * // Max fee doesn't make sense with extraFee AND staticFee
522
+ * // already specified, but here for completeness
523
+ * maxFee: (3000).microAlgo(),
524
+ * })
525
+ * ```
526
+ */
527
+ addAssetOptOut(params) {
528
+ this.push({
529
+ data: params,
530
+ type: "assetOptOut"
531
+ });
532
+ return this;
533
+ }
534
+ /**
535
+ * Add an application create transaction to the transaction group.
536
+ *
537
+ * Note: we recommend using app clients to make it easier to make app calls.
538
+ * @param params The application create transaction parameters
539
+ * @returns The composer so you can chain method calls
540
+ * @example Basic example
541
+ * ```typescript
542
+ * composer.addAppCreate({ sender: 'CREATORADDRESS', approvalProgram: 'TEALCODE', clearStateProgram: 'TEALCODE' })
543
+ * ```
544
+ * @example Advanced example
545
+ * ```typescript
546
+ * composer.addAppCreate({
547
+ * sender: 'CREATORADDRESS',
548
+ * approvalProgram: "TEALCODE",
549
+ * clearStateProgram: "TEALCODE",
550
+ * schema: {
551
+ * globalInts: 1,
552
+ * globalByteSlices: 2,
553
+ * localInts: 3,
554
+ * localByteSlices: 4
555
+ * },
556
+ * extraProgramPages: 1,
557
+ * onComplete: OnApplicationComplete.OptIn,
558
+ * args: [new Uint8Array(1, 2, 3, 4)]
559
+ * accountReferences: ["ACCOUNT_1"]
560
+ * appReferences: [123n, 1234n]
561
+ * assetReferences: [12345n]
562
+ * boxReferences: ["box1", {appId: 1234n, name: "box2"}]
563
+ * accessReferences: [{ appId: 1234n }]
564
+ * lease: 'lease',
565
+ * note: 'note',
566
+ * // You wouldn't normally set this field
567
+ * firstValidRound: 1000n,
568
+ * validityWindow: 10,
569
+ * extraFee: (1000).microAlgo(),
570
+ * staticFee: (1000).microAlgo(),
571
+ * // Max fee doesn't make sense with extraFee AND staticFee
572
+ * // already specified, but here for completeness
573
+ * maxFee: (3000).microAlgo(),
574
+ * rejectVersion: 1,
575
+ * // Signer only needed if you want to provide one,
576
+ * // generally you'd register it with AlgorandClient
577
+ * // against the sender and not need to pass it in
578
+ * signer: transactionSigner,
579
+ * maxRoundsToWaitForConfirmation: 5,
580
+ * suppressLog: true,
581
+ *})
582
+ * ```
583
+ */
584
+ addAppCreate(params) {
585
+ this.validateReferenceParams(params);
586
+ this.push({
587
+ data: params,
588
+ type: "appCall"
589
+ });
590
+ return this;
591
+ }
592
+ /**
593
+ * Add an application update transaction to the transaction group.
594
+ *
595
+ * Note: we recommend using app clients to make it easier to make app calls.
596
+ * @param params The application update transaction parameters
597
+ * @returns The composer so you can chain method calls
598
+ * @example Basic example
599
+ * ```typescript
600
+ * composer.addAppUpdate({ sender: 'CREATORADDRESS', approvalProgram: 'TEALCODE', clearStateProgram: 'TEALCODE' })
601
+ * ```
602
+ * @example Advanced example
603
+ * ```typescript
604
+ * composer.addAppUpdate({
605
+ * sender: 'CREATORADDRESS',
606
+ * approvalProgram: "TEALCODE",
607
+ * clearStateProgram: "TEALCODE",
608
+ * onComplete: OnApplicationComplete.UpdateApplication,
609
+ * args: [new Uint8Array(1, 2, 3, 4)]
610
+ * accountReferences: ["ACCOUNT_1"]
611
+ * appReferences: [123n, 1234n]
612
+ * assetReferences: [12345n]
613
+ * boxReferences: ["box1", {appId: 1234n, name: "box2"}]
614
+ * accessReferences: [{ appId: 1234n }]
615
+ * lease: 'lease',
616
+ * note: 'note',
617
+ * // You wouldn't normally set this field
618
+ * firstValidRound: 1000n,
619
+ * validityWindow: 10,
620
+ * extraFee: (1000).microAlgo(),
621
+ * staticFee: (1000).microAlgo(),
622
+ * // Max fee doesn't make sense with extraFee AND staticFee
623
+ * // already specified, but here for completeness
624
+ * maxFee: (3000).microAlgo(),
625
+ * rejectVersion: 1,
626
+ *})
627
+ * ```
628
+ */
629
+ addAppUpdate(params) {
630
+ this.validateReferenceParams(params);
631
+ this.push({
632
+ data: {
633
+ ...params,
634
+ onComplete: OnApplicationComplete.UpdateApplication
635
+ },
636
+ type: "appCall"
637
+ });
638
+ return this;
639
+ }
640
+ /**
641
+ * Add an application delete transaction to the transaction group.
642
+ *
643
+ * Note: we recommend using app clients to make it easier to make app calls.
644
+ * @param params The application delete transaction parameters
645
+ * @returns The composer so you can chain method calls
646
+ * @example Basic example
647
+ * ```typescript
648
+ * composer.addAppDelete({ sender: 'CREATORADDRESS' })
649
+ * ```
650
+ * @example Advanced example
651
+ * ```typescript
652
+ * composer.addAppDelete({
653
+ * sender: 'CREATORADDRESS',
654
+ * onComplete: OnApplicationComplete.DeleteApplication,
655
+ * args: [new Uint8Array(1, 2, 3, 4)]
656
+ * accountReferences: ["ACCOUNT_1"]
657
+ * appReferences: [123n, 1234n]
658
+ * assetReferences: [12345n]
659
+ * boxReferences: ["box1", {appId: 1234n, name: "box2"}]
660
+ * accessReferences: [{ appId: 1234n }]
661
+ * lease: 'lease',
662
+ * note: 'note',
663
+ * // You wouldn't normally set this field
664
+ * firstValidRound: 1000n,
665
+ * validityWindow: 10,
666
+ * extraFee: (1000).microAlgo(),
667
+ * staticFee: (1000).microAlgo(),
668
+ * // Max fee doesn't make sense with extraFee AND staticFee
669
+ * // already specified, but here for completeness
670
+ * maxFee: (3000).microAlgo(),
671
+ * rejectVersion: 1,
672
+ *})
673
+ * ```
674
+ */
675
+ addAppDelete(params) {
676
+ this.validateReferenceParams(params);
677
+ this.push({
678
+ data: {
679
+ ...params,
680
+ onComplete: OnApplicationComplete.DeleteApplication
681
+ },
682
+ type: "appCall"
683
+ });
684
+ return this;
685
+ }
686
+ /**
687
+ * Add an application call transaction to the transaction group.
688
+ *
689
+ * If you want to create or update an app use `addAppCreate` or `addAppUpdate`.
690
+ *
691
+ * Note: we recommend using app clients to make it easier to make app calls.
692
+ * @param params The application call transaction parameters
693
+ * @returns The composer so you can chain method calls
694
+ * @example Basic example
695
+ * ```typescript
696
+ * composer.addAppCall({ sender: 'CREATORADDRESS' })
697
+ * ```
698
+ * @example Advanced example
699
+ * ```typescript
700
+ * composer.addAppCall({
701
+ * sender: 'CREATORADDRESS',
702
+ * onComplete: OnApplicationComplete.OptIn,
703
+ * args: [new Uint8Array(1, 2, 3, 4)]
704
+ * accountReferences: ["ACCOUNT_1"]
705
+ * appReferences: [123n, 1234n]
706
+ * assetReferences: [12345n]
707
+ * boxReferences: ["box1", {appId: 1234n, name: "box2"}]
708
+ * accessReferences: [{ appId: 1234n }]
709
+ * lease: 'lease',
710
+ * note: 'note',
711
+ * // You wouldn't normally set this field
712
+ * firstValidRound: 1000n,
713
+ * validityWindow: 10,
714
+ * extraFee: (1000).microAlgo(),
715
+ * staticFee: (1000).microAlgo(),
716
+ * // Max fee doesn't make sense with extraFee AND staticFee
717
+ * // already specified, but here for completeness
718
+ * maxFee: (3000).microAlgo(),
719
+ * rejectVersion: 1,
720
+ *})
721
+ * ```
722
+ */
723
+ addAppCall(params) {
724
+ this.validateReferenceParams(params);
725
+ this.push({
726
+ data: params,
727
+ type: "appCall"
728
+ });
729
+ return this;
730
+ }
731
+ /**
732
+ * Add an ABI method create application call transaction to the transaction group.
733
+ *
734
+ * Note: we recommend using app clients to make it easier to make app calls.
735
+ * @param params The ABI create method application call transaction parameters
736
+ * @returns The composer so you can chain method calls
737
+ * @example Basic example
738
+ * ```typescript
739
+ * const method = new ABIMethod({
740
+ * name: 'method',
741
+ * args: [{ name: 'arg1', type: 'string' }],
742
+ * returns: { type: 'string' },
743
+ * })
744
+ * composer.addAppCreateMethodCall({ sender: 'CREATORADDRESS', approvalProgram: 'TEALCODE', clearStateProgram: 'TEALCODE', method: method, args: ["arg1_value"] })
745
+ * ```
746
+ * @example Advanced example
747
+ * ```typescript
748
+ * const method = new ABIMethod({
749
+ * name: 'method',
750
+ * args: [{ name: 'arg1', type: 'string' }],
751
+ * returns: { type: 'string' },
752
+ * })
753
+ * composer.addAppCreateMethodCall({
754
+ * sender: 'CREATORADDRESS',
755
+ * method: method,
756
+ * args: ["arg1_value"],
757
+ * approvalProgram: "TEALCODE",
758
+ * clearStateProgram: "TEALCODE",
759
+ * schema: {
760
+ * globalInts: 1,
761
+ * globalByteSlices: 2,
762
+ * localInts: 3,
763
+ * localByteSlices: 4
764
+ * },
765
+ * extraProgramPages: 1,
766
+ * onComplete: OnApplicationComplete.OptIn,
767
+ * args: [new Uint8Array(1, 2, 3, 4)]
768
+ * accountReferences: ["ACCOUNT_1"]
769
+ * appReferences: [123n, 1234n]
770
+ * assetReferences: [12345n]
771
+ * boxReferences: ["box1", {appId: 1234n, name: "box2"}]
772
+ * accessReferences: [{ appId: 1234n }]
773
+ * lease: 'lease',
774
+ * note: 'note',
775
+ * // You wouldn't normally set this field
776
+ * firstValidRound: 1000n,
777
+ * validityWindow: 10,
778
+ * extraFee: (1000).microAlgo(),
779
+ * staticFee: (1000).microAlgo(),
780
+ * // Max fee doesn't make sense with extraFee AND staticFee
781
+ * // already specified, but here for completeness
782
+ * maxFee: (3000).microAlgo(),
783
+ * rejectVersion: 1,
784
+ *})
785
+ * ```
786
+ */
787
+ addAppCreateMethodCall(params) {
788
+ this.validateReferenceParams(params);
789
+ const txnArgs = extractComposerTransactionsFromAppMethodCallParams(params);
790
+ this.push(...txnArgs, {
791
+ data: {
792
+ ...params,
793
+ args: processAppMethodCallArgs(params.args)
794
+ },
795
+ type: "methodCall"
796
+ });
797
+ return this;
798
+ }
799
+ /**
800
+ * Add an ABI method update application call transaction to the transaction group.
801
+ *
802
+ * Note: we recommend using app clients to make it easier to make app calls.
803
+ * @param params The ABI update method application call transaction parameters
804
+ * @returns The composer so you can chain method calls
805
+ * @example Basic example
806
+ * ```typescript
807
+ * const method = new ABIMethod({
808
+ * name: 'method',
809
+ * args: [{ name: 'arg1', type: 'string' }],
810
+ * returns: { type: 'string' },
811
+ * })
812
+ * composer.addAppUpdateMethodCall({ sender: 'CREATORADDRESS', approvalProgram: 'TEALCODE', clearStateProgram: 'TEALCODE', method: method, args: ["arg1_value"] })
813
+ * ```
814
+ * @example Advanced example
815
+ * ```typescript
816
+ * const method = new ABIMethod({
817
+ * name: 'method',
818
+ * args: [{ name: 'arg1', type: 'string' }],
819
+ * returns: { type: 'string' },
820
+ * })
821
+ * composer.addAppUpdateMethodCall({
822
+ * sender: 'CREATORADDRESS',
823
+ * method: method,
824
+ * args: ["arg1_value"],
825
+ * approvalProgram: "TEALCODE",
826
+ * clearStateProgram: "TEALCODE",
827
+ * onComplete: OnApplicationComplete.UpdateApplication,
828
+ * args: [new Uint8Array(1, 2, 3, 4)]
829
+ * accountReferences: ["ACCOUNT_1"]
830
+ * appReferences: [123n, 1234n]
831
+ * assetReferences: [12345n]
832
+ * boxReferences: ["box1", {appId: 1234n, name: "box2"}]
833
+ * accessReferences: [{ appId: 1234n }]
834
+ * lease: 'lease',
835
+ * note: 'note',
836
+ * // You wouldn't normally set this field
837
+ * firstValidRound: 1000n,
838
+ * validityWindow: 10,
839
+ * extraFee: (1000).microAlgo(),
840
+ * staticFee: (1000).microAlgo(),
841
+ * // Max fee doesn't make sense with extraFee AND staticFee
842
+ * // already specified, but here for completeness
843
+ * maxFee: (3000).microAlgo(),
844
+ * rejectVersion: 1,
845
+ *})
846
+ * ```
847
+ */
848
+ addAppUpdateMethodCall(params) {
849
+ this.validateReferenceParams(params);
850
+ const txnArgs = extractComposerTransactionsFromAppMethodCallParams(params);
851
+ this.push(...txnArgs, {
852
+ data: {
853
+ ...params,
854
+ args: processAppMethodCallArgs(params.args),
855
+ onComplete: OnApplicationComplete.UpdateApplication
856
+ },
857
+ type: "methodCall"
858
+ });
859
+ return this;
860
+ }
861
+ /**
862
+ * Add an ABI method delete application call transaction to the transaction group.
863
+ *
864
+ * Note: we recommend using app clients to make it easier to make app calls.
865
+ * @param params The ABI delete method application call transaction parameters
866
+ * @returns The composer so you can chain method calls
867
+ * @example Basic example
868
+ * ```typescript
869
+ * const method = new ABIMethod({
870
+ * name: 'method',
871
+ * args: [{ name: 'arg1', type: 'string' }],
872
+ * returns: { type: 'string' },
873
+ * })
874
+ * composer.addAppDeleteMethodCall({ sender: 'CREATORADDRESS', method: method, args: ["arg1_value"] })
875
+ * ```
876
+ * @example Advanced example
877
+ * ```typescript
878
+ * const method = new ABIMethod({
879
+ * name: 'method',
880
+ * args: [{ name: 'arg1', type: 'string' }],
881
+ * returns: { type: 'string' },
882
+ * })
883
+ * composer.addAppDeleteMethodCall({
884
+ * sender: 'CREATORADDRESS',
885
+ * method: method,
886
+ * args: ["arg1_value"],
887
+ * onComplete: OnApplicationComplete.DeleteApplication,
888
+ * args: [new Uint8Array(1, 2, 3, 4)]
889
+ * accountReferences: ["ACCOUNT_1"]
890
+ * appReferences: [123n, 1234n]
891
+ * assetReferences: [12345n]
892
+ * boxReferences: ["box1", {appId: 1234n, name: "box2"}]
893
+ * accessReferences: [{ appId: 1234n }]
894
+ * lease: 'lease',
895
+ * note: 'note',
896
+ * // You wouldn't normally set this field
897
+ * firstValidRound: 1000n,
898
+ * validityWindow: 10,
899
+ * extraFee: (1000).microAlgo(),
900
+ * staticFee: (1000).microAlgo(),
901
+ * // Max fee doesn't make sense with extraFee AND staticFee
902
+ * // already specified, but here for completeness
903
+ * maxFee: (3000).microAlgo(),
904
+ * rejectVersion: 1,
905
+ *})
906
+ * ```
907
+ */
908
+ addAppDeleteMethodCall(params) {
909
+ this.validateReferenceParams(params);
910
+ const txnArgs = extractComposerTransactionsFromAppMethodCallParams(params);
911
+ this.push(...txnArgs, {
912
+ data: {
913
+ ...params,
914
+ args: processAppMethodCallArgs(params.args),
915
+ onComplete: OnApplicationComplete.DeleteApplication
916
+ },
917
+ type: "methodCall"
918
+ });
919
+ return this;
920
+ }
921
+ /**
922
+ * Add a non-create/non-update ABI method application call transaction to the transaction group.
923
+ *
924
+ * Note: we recommend using app clients to make it easier to make app calls.
925
+ * @param params The ABI method application call transaction parameters
926
+ * @returns The composer so you can chain method calls
927
+ * @example Basic example
928
+ * ```typescript
929
+ * const method = new ABIMethod({
930
+ * name: 'method',
931
+ * args: [{ name: 'arg1', type: 'string' }],
932
+ * returns: { type: 'string' },
933
+ * })
934
+ * composer.addAppCallMethodCall({ sender: 'CREATORADDRESS', method: method, args: ["arg1_value"] })
935
+ * ```
936
+ * @example Advanced example
937
+ * ```typescript
938
+ * const method = new ABIMethod({
939
+ * name: 'method',
940
+ * args: [{ name: 'arg1', type: 'string' }],
941
+ * returns: { type: 'string' },
942
+ * })
943
+ * composer.addAppCallMethodCall({
944
+ * sender: 'CREATORADDRESS',
945
+ * method: method,
946
+ * args: ["arg1_value"],
947
+ * onComplete: OnApplicationComplete.OptIn,
948
+ * args: [new Uint8Array(1, 2, 3, 4)]
949
+ * accountReferences: ["ACCOUNT_1"]
950
+ * appReferences: [123n, 1234n]
951
+ * assetReferences: [12345n]
952
+ * boxReferences: ["box1", {appId: 1234n, name: "box2"}]
953
+ * accessReferences: [{ appId: 1234n }]
954
+ * lease: 'lease',
955
+ * note: 'note',
956
+ * // You wouldn't normally set this field
957
+ * firstValidRound: 1000n,
958
+ * validityWindow: 10,
959
+ * extraFee: (1000).microAlgo(),
960
+ * staticFee: (1000).microAlgo(),
961
+ * // Max fee doesn't make sense with extraFee AND staticFee
962
+ * // already specified, but here for completeness
963
+ * maxFee: (3000).microAlgo(),
964
+ * rejectVersion: 1,
965
+ *})
966
+ * ```
967
+ */
968
+ addAppCallMethodCall(params) {
969
+ this.validateReferenceParams(params);
970
+ const txnArgs = extractComposerTransactionsFromAppMethodCallParams(params);
971
+ this.push(...txnArgs, {
972
+ data: {
973
+ ...params,
974
+ args: processAppMethodCallArgs(params.args)
975
+ },
976
+ type: "methodCall"
977
+ });
978
+ return this;
979
+ }
980
+ /**
981
+ * Add an online key registration transaction to the transaction group.
982
+ * @param params The online key registration transaction parameters
983
+ * @returns The composer so you can chain method calls
984
+ * @example Basic example
985
+ * ```typescript
986
+ * composer.addOnlineKeyRegistration({
987
+ * sender: 'SENDERADDRESS',
988
+ * voteKey: Uint8Array.from(Buffer.from("voteKeyBase64", 'base64')),
989
+ * selectionKey: Uint8Array.from(Buffer.from("selectionKeyBase64", 'base64')),
990
+ * stateProofKey: Uint8Array.from(Buffer.from("stateProofKeyBase64", 'base64')),
991
+ * voteFirst: 1n,
992
+ * voteLast: 1000n,
993
+ * voteKeyDilution: 1n,
994
+ * })
995
+ * ```
996
+ * @example Advanced example
997
+ * ```typescript
998
+ * composer.addOnlineKeyRegistration({
999
+ * sender: 'SENDERADDRESS',
1000
+ * voteKey: Uint8Array.from(Buffer.from("voteKeyBase64", 'base64')),
1001
+ * selectionKey: Uint8Array.from(Buffer.from("selectionKeyBase64", 'base64')),
1002
+ * stateProofKey: Uint8Array.from(Buffer.from("stateProofKeyBase64", 'base64')),
1003
+ * voteFirst: 1n,
1004
+ * voteLast: 1000n,
1005
+ * voteKeyDilution: 1n,
1006
+ * lease: 'lease',
1007
+ * note: 'note',
1008
+ * // Use this with caution, it's generally better to use algorand.account.rekeyAccount
1009
+ * rekeyTo: 'REKEYTOADDRESS',
1010
+ * // You wouldn't normally set this field
1011
+ * firstValidRound: 1000n,
1012
+ * validityWindow: 10,
1013
+ * extraFee: (1000).microAlgo(),
1014
+ * staticFee: (1000).microAlgo(),
1015
+ * // Max fee doesn't make sense with extraFee AND staticFee
1016
+ * // already specified, but here for completeness
1017
+ * maxFee: (3000).microAlgo(),
1018
+ * })
1019
+ * ```
1020
+ */
1021
+ addOnlineKeyRegistration(params) {
1022
+ this.push({
1023
+ data: params,
1024
+ type: "keyReg"
1025
+ });
1026
+ return this;
1027
+ }
1028
+ /**
1029
+ * Add an offline key registration transaction to the transaction group.
1030
+ * @param params The offline key registration transaction parameters
1031
+ * @returns The composer so you can chain method calls
1032
+ * @example Basic example
1033
+ * ```typescript
1034
+ * composer.addOfflineKeyRegistration({
1035
+ * sender: 'SENDERADDRESS',
1036
+ * })
1037
+ * ```
1038
+ * @example Advanced example
1039
+ * ```typescript
1040
+ * composer.addOfflineKeyRegistration({
1041
+ * sender: 'SENDERADDRESS',
1042
+ * lease: 'lease',
1043
+ * note: 'note',
1044
+ * // Use this with caution, it's generally better to use algorand.account.rekeyAccount
1045
+ * rekeyTo: 'REKEYTOADDRESS',
1046
+ * // You wouldn't normally set this field
1047
+ * firstValidRound: 1000n,
1048
+ * validityWindow: 10,
1049
+ * extraFee: (1000).microAlgo(),
1050
+ * staticFee: (1000).microAlgo(),
1051
+ * // Max fee doesn't make sense with extraFee AND staticFee
1052
+ * // already specified, but here for completeness
1053
+ * maxFee: (3000).microAlgo(),
1054
+ * })
1055
+ * ```
1056
+ */
1057
+ addOfflineKeyRegistration(params) {
1058
+ this.push({
1059
+ data: params,
1060
+ type: "keyReg"
1061
+ });
1062
+ return this;
1063
+ }
1064
+ /**
1065
+ * Get the number of transactions currently added to this composer.
1066
+ * @returns The number of transactions currently added to this composer
1067
+ */
1068
+ count() {
1069
+ return this.txns.length;
1070
+ }
1071
+ /**
1072
+ * Build the transaction composer.
1073
+ *
1074
+ * This method performs resource population and inner transaction fee coverage if these options are set in the composer.
1075
+ *
1076
+ * Once this method is called, no further transactions will be able to be added.
1077
+ * You can safely call this method multiple times to get the same result.
1078
+ * @returns The built transaction composer, the transactions and any corresponding method calls
1079
+ * @example
1080
+ * ```typescript
1081
+ * const { transactions, methodCalls } = await composer.build()
1082
+ * ```
1083
+ */
1084
+ async build() {
1085
+ if (!this.transactionsWithSigners) {
1086
+ const suggestedParams = await this.getSuggestedParams();
1087
+ const builtTransactions = await this._buildTransactions(suggestedParams);
1088
+ this.rawBuildTransactions = builtTransactions.transactions.map((txn) => new Transaction({ ...txn }));
1089
+ const groupAnalysis = (this.composerConfig.coverAppCallInnerTransactionFees || this.composerConfig.populateAppCallResources) && builtTransactions.transactions.some((txn) => txn.type === TransactionType.AppCall) ? await this.analyzeGroupRequirements(builtTransactions.transactions, suggestedParams, this.composerConfig) : void 0;
1090
+ this.populateTransactionAndGroupResources(builtTransactions.transactions, groupAnalysis);
1091
+ this.transactionsWithSigners = builtTransactions.transactions.map((txn, index) => {
1092
+ return {
1093
+ txn,
1094
+ signer: builtTransactions.signers.get(index) ?? this.getSigner(txn.sender)
1095
+ };
1096
+ });
1097
+ }
1098
+ const methodCalls = /* @__PURE__ */ new Map();
1099
+ this.txns.forEach((txn, index) => {
1100
+ if (txn.type === "methodCall") methodCalls.set(index, txn.data.method);
1101
+ });
1102
+ return {
1103
+ transactions: this.transactionsWithSigners,
1104
+ methodCalls
1105
+ };
1106
+ }
1107
+ async _buildTransactions(suggestedParams) {
1108
+ const defaultValidityWindow = !this.defaultValidityWindowIsExplicit && genesisIdIsLocalNet(suggestedParams.genesisId ?? "unknown") ? 1000n : this.defaultValidityWindow;
1109
+ const signers = /* @__PURE__ */ new Map();
1110
+ const transactions = new Array();
1111
+ let transactionIndex = 0;
1112
+ for (const ctxn of this.txns) if (ctxn.type === "txn") {
1113
+ validateTransaction(ctxn.data.txn);
1114
+ transactions.push(ctxn.data.txn);
1115
+ if (ctxn.data.signer) signers.set(transactionIndex, ctxn.data.signer);
1116
+ transactionIndex++;
1117
+ } else if (ctxn.type === "asyncTxn") {
1118
+ const transaction = await ctxn.data.txn;
1119
+ validateTransaction(transaction);
1120
+ transactions.push(transaction);
1121
+ if (ctxn.data.signer) signers.set(transactionIndex, ctxn.data.signer);
1122
+ transactionIndex++;
1123
+ } else {
1124
+ let transaction;
1125
+ switch (ctxn.type) {
1126
+ case "pay":
1127
+ transaction = buildPayment(ctxn.data, suggestedParams, defaultValidityWindow);
1128
+ break;
1129
+ case "assetCreate":
1130
+ transaction = buildAssetCreate(ctxn.data, suggestedParams, defaultValidityWindow);
1131
+ break;
1132
+ case "assetConfig":
1133
+ transaction = buildAssetConfig(ctxn.data, suggestedParams, defaultValidityWindow);
1134
+ break;
1135
+ case "assetFreeze":
1136
+ transaction = buildAssetFreeze(ctxn.data, suggestedParams, defaultValidityWindow);
1137
+ break;
1138
+ case "assetDestroy":
1139
+ transaction = buildAssetDestroy(ctxn.data, suggestedParams, defaultValidityWindow);
1140
+ break;
1141
+ case "assetTransfer":
1142
+ transaction = buildAssetTransfer(ctxn.data, suggestedParams, defaultValidityWindow);
1143
+ break;
1144
+ case "assetOptIn":
1145
+ transaction = buildAssetOptIn(ctxn.data, suggestedParams, defaultValidityWindow);
1146
+ break;
1147
+ case "assetOptOut":
1148
+ transaction = buildAssetOptOut(ctxn.data, suggestedParams, defaultValidityWindow);
1149
+ break;
1150
+ case "appCall":
1151
+ if (ctxn.data.appId === void 0 || ctxn.data.appId === 0) transaction = await buildAppCreate(ctxn.data, this.appManager, suggestedParams, defaultValidityWindow);
1152
+ else if ("approvalProgram" in ctxn.data && "clearStateProgram" in ctxn.data) transaction = await buildAppUpdate(ctxn.data, this.appManager, suggestedParams, defaultValidityWindow);
1153
+ else transaction = buildAppCall(ctxn.data, suggestedParams, defaultValidityWindow);
1154
+ break;
1155
+ case "keyReg":
1156
+ transaction = buildKeyReg(ctxn.data, suggestedParams, defaultValidityWindow);
1157
+ break;
1158
+ case "methodCall":
1159
+ if (ctxn.data.appId === void 0 || ctxn.data.appId === 0) transaction = await buildAppCreateMethodCall(ctxn.data, this.appManager, suggestedParams, defaultValidityWindow);
1160
+ else if ("approvalProgram" in ctxn.data && "clearStateProgram" in ctxn.data) transaction = await buildAppUpdateMethodCall(ctxn.data, this.appManager, suggestedParams, defaultValidityWindow);
1161
+ else transaction = await buildAppCallMethodCall(ctxn.data, suggestedParams, defaultValidityWindow);
1162
+ break;
1163
+ default: throw new Error(`Unsupported transaction type: ${ctxn.type}`);
1164
+ }
1165
+ if (transaction.fee === void 0) transaction = assignFee(transaction, {
1166
+ feePerByte: suggestedParams.fee,
1167
+ minFee: suggestedParams.minFee,
1168
+ extraFee: ctxn.data.extraFee?.microAlgos,
1169
+ maxFee: ctxn.data.maxFee?.microAlgos
1170
+ });
1171
+ validateTransaction(transaction);
1172
+ transactions.push(transaction);
1173
+ if (ctxn.data.signer) {
1174
+ const signer = "signer" in ctxn.data.signer ? ctxn.data.signer.signer : ctxn.data.signer;
1175
+ signers.set(transactionIndex, signer);
1176
+ }
1177
+ transactionIndex++;
1178
+ }
1179
+ if (transactions.length > MAX_TRANSACTION_GROUP_SIZE) throw new Error(`Transaction group size ${transactions.length} exceeds the maximum limit of ${MAX_TRANSACTION_GROUP_SIZE}`);
1180
+ const methodCalls = /* @__PURE__ */ new Map();
1181
+ this.txns.forEach((txn, index) => {
1182
+ if (txn.type === "methodCall") methodCalls.set(index, txn.data.method);
1183
+ });
1184
+ return {
1185
+ transactions,
1186
+ methodCalls,
1187
+ signers
1188
+ };
1189
+ }
1190
+ /**
1191
+ * Builds all transactions in the composer and returns them along with method calls and signers.
1192
+ *
1193
+ * Note: This method only builds the transactions as-is without resource population or automatic grouping.
1194
+ * Use this when you need the raw transactions.
1195
+ * @returns An object containing the array of built transactions, method calls, and signers
1196
+ * @example
1197
+ * ```typescript
1198
+ * const { transactions, methodCalls, signers } = await composer.buildTransactions()
1199
+ * ```
1200
+ */
1201
+ async buildTransactions() {
1202
+ const suggestedParams = await this.getSuggestedParams();
1203
+ const buildResult = await this._buildTransactions(suggestedParams);
1204
+ return {
1205
+ ...buildResult,
1206
+ transactions: buildResult.transactions
1207
+ };
1208
+ }
1209
+ populateTransactionAndGroupResources(transactions, groupAnalysis) {
1210
+ if (groupAnalysis) {
1211
+ let surplusGroupFees = 0n;
1212
+ const transactionAnalysis = [];
1213
+ groupAnalysis.transactions.forEach((txnAnalysis, groupIndex) => {
1214
+ if (txnAnalysis.requiredFeeDelta && FeeDelta.isSurplus(txnAnalysis.requiredFeeDelta)) surplusGroupFees += FeeDelta.amount(txnAnalysis.requiredFeeDelta);
1215
+ const ctxn = this.txns[groupIndex];
1216
+ const txn = transactions[groupIndex];
1217
+ const logicalMaxFee = getLogicalMaxFee(ctxn);
1218
+ const isImmutableFee = logicalMaxFee !== void 0 && logicalMaxFee === (txn.fee || 0n);
1219
+ let priority = FeePriority.Covered;
1220
+ if (txnAnalysis.requiredFeeDelta && FeeDelta.isDeficit(txnAnalysis.requiredFeeDelta)) {
1221
+ const deficitAmount = FeeDelta.amount(txnAnalysis.requiredFeeDelta);
1222
+ if (isImmutableFee || txn.type !== TransactionType.AppCall) priority = FeePriority.ImmutableDeficit(deficitAmount);
1223
+ else priority = FeePriority.ModifiableDeficit(deficitAmount);
1224
+ }
1225
+ transactionAnalysis.push({
1226
+ groupIndex,
1227
+ requiredFeeDelta: txnAnalysis.requiredFeeDelta,
1228
+ priority,
1229
+ unnamedResourcesAccessed: txnAnalysis.unnamedResourcesAccessed
1230
+ });
1231
+ });
1232
+ transactionAnalysis.sort((a, b) => b.priority.compare(a.priority));
1233
+ const indexesWithAccessReferences = [];
1234
+ for (const { groupIndex, requiredFeeDelta, unnamedResourcesAccessed } of transactionAnalysis) {
1235
+ if (requiredFeeDelta && FeeDelta.isDeficit(requiredFeeDelta)) {
1236
+ const deficitAmount = FeeDelta.amount(requiredFeeDelta);
1237
+ let additionalFeeDelta;
1238
+ if (surplusGroupFees === 0n) additionalFeeDelta = requiredFeeDelta;
1239
+ else if (surplusGroupFees >= deficitAmount) surplusGroupFees -= deficitAmount;
1240
+ else {
1241
+ additionalFeeDelta = FeeDelta.fromBigInt(deficitAmount - surplusGroupFees);
1242
+ surplusGroupFees = 0n;
1243
+ }
1244
+ if (additionalFeeDelta && FeeDelta.isDeficit(additionalFeeDelta)) {
1245
+ const additionalDeficitAmount = FeeDelta.amount(additionalFeeDelta);
1246
+ if (transactions[groupIndex].type === TransactionType.AppCall) {
1247
+ const transactionFee = (transactions[groupIndex].fee || 0n) + additionalDeficitAmount;
1248
+ const logicalMaxFee = getLogicalMaxFee(this.txns[groupIndex]);
1249
+ if (!logicalMaxFee || transactionFee > logicalMaxFee) throw new Error(`Calculated transaction fee ${transactionFee} µALGO is greater than max of ${logicalMaxFee ?? 0n} for transaction ${groupIndex}`);
1250
+ transactions[groupIndex].fee = transactionFee;
1251
+ } else throw new Error(`An additional fee of ${additionalDeficitAmount} µALGO is required for non app call transaction ${groupIndex}`);
1252
+ }
1253
+ }
1254
+ if (unnamedResourcesAccessed && transactions[groupIndex].type === TransactionType.AppCall) if (!(transactions[groupIndex].appCall?.accessReferences && transactions[groupIndex].appCall?.accessReferences?.length)) populateTransactionResources(transactions[groupIndex], unnamedResourcesAccessed, groupIndex);
1255
+ else indexesWithAccessReferences.push(groupIndex);
1256
+ }
1257
+ if (indexesWithAccessReferences.length > 0) Config.logger.warn(`Resource population will be skipped for transaction indexes ${indexesWithAccessReferences.join(", ")} as they use access references.`);
1258
+ if (groupAnalysis.unnamedResourcesAccessed) populateGroupResources(transactions, groupAnalysis.unnamedResourcesAccessed);
1259
+ }
1260
+ if (transactions.length > 1) {
1261
+ const groupedTransactions = groupTransactions(transactions);
1262
+ transactions.forEach((t) => t.group = groupedTransactions[0].group);
1263
+ return transactions;
1264
+ } else return transactions;
1265
+ }
1266
+ async analyzeGroupRequirements(transactions, suggestedParams, analysisParams) {
1267
+ const appCallIndexesWithoutMaxFees = [];
1268
+ let transactionsToSimulate = transactions.map((txn, groupIndex) => {
1269
+ const ctxn = this.txns[groupIndex];
1270
+ const params = { ...txn };
1271
+ delete params.group;
1272
+ if (analysisParams.coverAppCallInnerTransactionFees && txn.type === TransactionType.AppCall) {
1273
+ const logicalMaxFee = getLogicalMaxFee(ctxn);
1274
+ if (logicalMaxFee !== void 0) params.fee = logicalMaxFee;
1275
+ else appCallIndexesWithoutMaxFees.push(groupIndex);
1276
+ }
1277
+ return new Transaction(params);
1278
+ });
1279
+ if (transactionsToSimulate.length > 1) transactionsToSimulate = groupTransactions(transactionsToSimulate);
1280
+ if (analysisParams.coverAppCallInnerTransactionFees && appCallIndexesWithoutMaxFees.length > 0) throw new Error(`Please provide a maxFee for each app call transaction when coverAppCallInnerTransactionFees is enabled. Required for transaction ${appCallIndexesWithoutMaxFees.join(", ")}`);
1281
+ const simulateRequest = {
1282
+ txnGroups: [{ txns: transactionsToSimulate.map((txn) => ({
1283
+ txn,
1284
+ sig: EMPTY_SIGNATURE
1285
+ })) }],
1286
+ allowUnnamedResources: true,
1287
+ allowEmptySignatures: true,
1288
+ fixSigners: true,
1289
+ allowMoreLogging: true,
1290
+ execTraceConfig: {
1291
+ enable: true,
1292
+ scratchChange: true,
1293
+ stackChange: true,
1294
+ stateChange: true
1295
+ }
1296
+ };
1297
+ const groupResponse = (await this.algod.simulateTransactions(simulateRequest)).txnGroups[0];
1298
+ if (groupResponse.failureMessage) {
1299
+ if (analysisParams.coverAppCallInnerTransactionFees && groupResponse.failureMessage.includes("fee too small")) throw new Error("Fees were too small to resolve execution info via simulate. You may need to increase an app call transaction maxFee.");
1300
+ throw new Error(`Error resolving execution info via simulate in transaction ${groupResponse.failedAt?.join(", ")}: ${groupResponse.failureMessage}`);
1301
+ }
1302
+ const txnAnalysisResults = groupResponse.txnResults.map((simulateTxnResult, groupIndex) => {
1303
+ const btxn = transactions[groupIndex];
1304
+ let requiredFeeDelta;
1305
+ if (analysisParams.coverAppCallInnerTransactionFees) {
1306
+ const minTxnFee = calculateFee(btxn, {
1307
+ feePerByte: suggestedParams.fee,
1308
+ minFee: suggestedParams.minFee
1309
+ });
1310
+ const txnFeeDelta = FeeDelta.fromBigInt(minTxnFee - (btxn.fee ?? 0n));
1311
+ if (btxn.type === TransactionType.AppCall) {
1312
+ const innerTxnsFeeDelta = calculateInnerFeeDelta(simulateTxnResult.txnResult.innerTxns, suggestedParams.minFee);
1313
+ requiredFeeDelta = FeeDelta.fromBigInt((innerTxnsFeeDelta ? FeeDelta.toBigInt(innerTxnsFeeDelta) : 0n) + (txnFeeDelta ? FeeDelta.toBigInt(txnFeeDelta) : 0n));
1314
+ } else requiredFeeDelta = txnFeeDelta;
1315
+ }
1316
+ return {
1317
+ requiredFeeDelta,
1318
+ unnamedResourcesAccessed: analysisParams.populateAppCallResources ? simulateTxnResult.unnamedResourcesAccessed : void 0
1319
+ };
1320
+ });
1321
+ const sortedResources = groupResponse.unnamedResourcesAccessed;
1322
+ const compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
1323
+ if (sortedResources) {
1324
+ sortedResources.accounts?.sort((a, b) => compare(a.toString(), b.toString()));
1325
+ sortedResources.assets?.sort(compare);
1326
+ sortedResources.apps?.sort(compare);
1327
+ sortedResources.boxes?.sort((a, b) => {
1328
+ return compare(`${a.appId}-${a.name}`, `${b.appId}-${b.name}`);
1329
+ });
1330
+ sortedResources.appLocals?.sort((a, b) => {
1331
+ return compare(`${a.appId}-${a.address}`, `${b.appId}-${b.address}`);
1332
+ });
1333
+ sortedResources.assetHoldings?.sort((a, b) => {
1334
+ return compare(`${a.assetId}-${a.address}`, `${b.assetId}-${b.address}`);
1335
+ });
1336
+ }
1337
+ return {
1338
+ transactions: txnAnalysisResults,
1339
+ unnamedResourcesAccessed: analysisParams.populateAppCallResources ? sortedResources : void 0
1340
+ };
1341
+ }
1342
+ /**
1343
+ * Rebuild the group, discarding any previously built transactions.
1344
+ * This will potentially cause new signers and suggested params to be used if the callbacks return a new value compared to the first build.
1345
+ * @returns The newly built transaction composer and the transactions
1346
+ * @example
1347
+ * ```typescript
1348
+ * const { atc, transactions, methodCalls } = await composer.rebuild()
1349
+ * ```
1350
+ */
1351
+ async rebuild() {
1352
+ this.reset();
1353
+ return await this.build();
1354
+ }
1355
+ reset() {
1356
+ this.signedTransactions = void 0;
1357
+ this.transactionsWithSigners = void 0;
1358
+ }
1359
+ /**
1360
+ * Compose the transaction group and send it to the network.
1361
+ * @param params The parameters to control execution with
1362
+ * @returns The execution result
1363
+ * @example
1364
+ * ```typescript
1365
+ * const result = await composer.send()
1366
+ * ```
1367
+ */
1368
+ async send(params) {
1369
+ const effectiveConfig = {
1370
+ coverAppCallInnerTransactionFees: params?.coverAppCallInnerTransactionFees ?? this.composerConfig.coverAppCallInnerTransactionFees,
1371
+ populateAppCallResources: params?.populateAppCallResources ?? this.composerConfig.populateAppCallResources
1372
+ };
1373
+ if (this.composerConfig.coverAppCallInnerTransactionFees !== effectiveConfig.coverAppCallInnerTransactionFees || this.composerConfig.populateAppCallResources !== effectiveConfig.populateAppCallResources) {
1374
+ this.composerConfig = effectiveConfig;
1375
+ this.reset();
1376
+ }
1377
+ try {
1378
+ await this.gatherSignatures();
1379
+ if (!this.transactionsWithSigners || this.transactionsWithSigners.length === 0 || !this.signedTransactions || this.signedTransactions.length === 0) throw new Error("No transactions available");
1380
+ const transactionsToSend = this.transactionsWithSigners.map((stxn) => stxn.txn);
1381
+ const transactionIds = transactionsToSend.map((txn) => txn.txId());
1382
+ if (transactionsToSend.length > 1) {
1383
+ const groupId = transactionsToSend[0].group ? Buffer.from(transactionsToSend[0].group).toString("base64") : "";
1384
+ Config.getLogger(params?.suppressLog).verbose(`Sending group of ${transactionsToSend.length} transactions (${groupId})`, { transactionsToSend });
1385
+ Config.getLogger(params?.suppressLog).debug(`Transaction IDs (${groupId})`, transactionIds);
1386
+ }
1387
+ if (Config.debug && Config.traceAll) await this.simulate({
1388
+ allowEmptySignatures: true,
1389
+ fixSigners: true,
1390
+ allowMoreLogging: true,
1391
+ execTraceConfig: {
1392
+ enable: true,
1393
+ scratchChange: true,
1394
+ stackChange: true,
1395
+ stateChange: true
1396
+ },
1397
+ resultOnFailure: true
1398
+ });
1399
+ const group = this.transactionsWithSigners[0].txn.group;
1400
+ let waitRounds = params?.maxRoundsToWaitForConfirmation;
1401
+ if (waitRounds === void 0) {
1402
+ const firstRound = (await this.getSuggestedParams()).firstValid;
1403
+ const lastRound = this.transactionsWithSigners.reduce((max, txn) => txn.txn.lastValid > max ? txn.txn.lastValid : max, 0n);
1404
+ waitRounds = Number(lastRound - firstRound) + 1;
1405
+ }
1406
+ await this.algod.sendRawTransaction(this.signedTransactions);
1407
+ if (transactionsToSend.length > 1 && group) Config.getLogger(params?.suppressLog).verbose(`Group transaction (${Buffer.from(group).toString("base64")}) sent with ${transactionsToSend.length} transactions`);
1408
+ else Config.getLogger(params?.suppressLog).verbose(`Sent transaction ID ${transactionsToSend[0].txId()} ${transactionsToSend[0].type} from ${transactionsToSend[0].sender}`);
1409
+ let confirmations = new Array();
1410
+ if (params?.maxRoundsToWaitForConfirmation !== 0) confirmations = await Promise.all(transactionIds.map(async (id) => await waitForConfirmation(id, waitRounds, this.algod)));
1411
+ const abiReturns = this.parseAbiReturnValues(confirmations);
1412
+ return {
1413
+ groupId: group ? Buffer.from(group).toString("base64") : void 0,
1414
+ transactions: transactionsToSend,
1415
+ txIds: transactionIds,
1416
+ returns: abiReturns,
1417
+ confirmations
1418
+ };
1419
+ } catch (originalError) {
1420
+ const errorMessage = originalError.body?.message ?? originalError.message ?? "Received error executing Transaction Composer";
1421
+ const err = new Error(errorMessage);
1422
+ err.cause = originalError;
1423
+ if (typeof originalError === "object") err.name = originalError.name;
1424
+ let sentTransactions;
1425
+ if (this.transactionsWithSigners) sentTransactions = this.transactionsWithSigners.map((t) => t.txn);
1426
+ else if (this.rawBuildTransactions) sentTransactions = this.rawBuildTransactions.length > 1 ? groupTransactions(this.rawBuildTransactions) : this.rawBuildTransactions;
1427
+ if (Config.debug && typeof originalError === "object" && sentTransactions) {
1428
+ err.traces = [];
1429
+ Config.getLogger(params?.suppressLog).error("Received error executing Transaction Composer and debug flag enabled; attempting simulation to get more information", err);
1430
+ const transactionsWithEmptySigners = sentTransactions.map((txn) => ({
1431
+ txn,
1432
+ signer: makeEmptyTransactionSigner()
1433
+ }));
1434
+ const signedTransactions = decodeSignedTransactions(await this.signTransactions(transactionsWithEmptySigners));
1435
+ const simulateResponse = await this.algod.simulateTransactions({
1436
+ txnGroups: [{ txns: signedTransactions }],
1437
+ allowEmptySignatures: true,
1438
+ fixSigners: true,
1439
+ allowMoreLogging: true,
1440
+ execTraceConfig: {
1441
+ enable: true,
1442
+ scratchChange: true,
1443
+ stackChange: true,
1444
+ stateChange: true
1445
+ }
1446
+ });
1447
+ if (Config.debug && !Config.traceAll) await Config.events.emitAsync(EventType.TxnGroupSimulated, { simulateResponse });
1448
+ if (simulateResponse && simulateResponse.txnGroups[0].failedAt) for (const txn of simulateResponse.txnGroups[0].txnResults) err.traces.push({
1449
+ trace: txn.execTrace,
1450
+ appBudget: txn.appBudgetConsumed,
1451
+ logicSigBudget: txn.logicSigBudgetConsumed,
1452
+ logs: txn.txnResult.logs,
1453
+ message: simulateResponse.txnGroups[0].failureMessage
1454
+ });
1455
+ } else Config.getLogger(params?.suppressLog).error("Received error executing Transaction Composer, for more information enable the debug flag", err);
1456
+ err.sentTransactions = sentTransactions ?? [];
1457
+ throw await this.transformError(err);
1458
+ }
1459
+ }
1460
+ async simulate(options) {
1461
+ const { skipSignatures = false, resultOnFailure = false, ...rawOptions } = options ?? {};
1462
+ if (skipSignatures) {
1463
+ rawOptions.allowEmptySignatures = true;
1464
+ rawOptions.fixSigners = true;
1465
+ }
1466
+ let transactionsWithSigner;
1467
+ if (!this.transactionsWithSigners) {
1468
+ const builtTransactions = await this.buildTransactions();
1469
+ transactionsWithSigner = (builtTransactions.transactions.length > 1 ? groupTransactions(builtTransactions.transactions) : builtTransactions.transactions).map((txn, index) => ({
1470
+ txn,
1471
+ signer: skipSignatures ? makeEmptyTransactionSigner() : builtTransactions.signers.get(index) ?? makeEmptyTransactionSigner()
1472
+ }));
1473
+ } else transactionsWithSigner = this.transactionsWithSigners.map((e) => ({
1474
+ txn: e.txn,
1475
+ signer: skipSignatures ? makeEmptyTransactionSigner() : e.signer
1476
+ }));
1477
+ const transactions = transactionsWithSigner.map((e) => e.txn);
1478
+ const simulateRequest = {
1479
+ txnGroups: [{ txns: decodeSignedTransactions(await this.signTransactions(transactionsWithSigner)) }],
1480
+ ...rawOptions,
1481
+ ...Config.debug ? {
1482
+ allowEmptySignatures: true,
1483
+ fixSigners: true,
1484
+ allowMoreLogging: true,
1485
+ execTraceConfig: {
1486
+ enable: true,
1487
+ scratchChange: true,
1488
+ stackChange: true,
1489
+ stateChange: true
1490
+ }
1491
+ } : void 0
1492
+ };
1493
+ const simulateResponse = await this.algod.simulateTransactions(simulateRequest);
1494
+ const simulateResult = simulateResponse.txnGroups[0];
1495
+ if (simulateResult?.failureMessage && !resultOnFailure) {
1496
+ const errorMessage = `Transaction failed at transaction(s) ${simulateResult.failedAt?.join(", ") || "unknown"} in the group. ${simulateResult.failureMessage}`;
1497
+ const error = new Error(errorMessage);
1498
+ if (Config.debug) await Config.events.emitAsync(EventType.TxnGroupSimulated, { simulateResponse });
1499
+ throw await this.transformError(error);
1500
+ }
1501
+ if (Config.debug && Config.traceAll) await Config.events.emitAsync(EventType.TxnGroupSimulated, { simulateResponse });
1502
+ const abiReturns = this.parseAbiReturnValues(simulateResult.txnResults.map((t) => t.txnResult));
1503
+ return {
1504
+ confirmations: simulateResult.txnResults.map((t) => t.txnResult),
1505
+ transactions,
1506
+ txIds: transactions.map((t) => t.txId()),
1507
+ groupId: Buffer.from(transactions[0].group ?? new Uint8Array()).toString("base64"),
1508
+ simulateResponse,
1509
+ returns: abiReturns
1510
+ };
1511
+ }
1512
+ /**
1513
+ * Create an encoded transaction note that follows the ARC-2 spec.
1514
+ *
1515
+ * https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0002.md
1516
+ * @param note The ARC-2 transaction note data
1517
+ * @returns The binary encoded transaction note
1518
+ */
1519
+ static arc2Note(note) {
1520
+ const arc2Payload = `${note.dAppName}:${note.format}${typeof note.data === "string" ? note.data : asJson(note.data)}`;
1521
+ return new TextEncoder().encode(arc2Payload);
1522
+ }
1523
+ async gatherSignatures() {
1524
+ if (this.signedTransactions) return this.signedTransactions;
1525
+ await this.build();
1526
+ if (!this.transactionsWithSigners || this.transactionsWithSigners.length === 0) throw new Error("No transactions available to sign");
1527
+ this.signedTransactions = await this.signTransactions(this.transactionsWithSigners);
1528
+ return this.signedTransactions;
1529
+ }
1530
+ async signTransactions(transactionsWithSigners) {
1531
+ if (transactionsWithSigners.length === 0) throw new Error("No transactions available to sign");
1532
+ const transactions = transactionsWithSigners.map((txnWithSigner) => txnWithSigner.txn);
1533
+ const signerGroups = /* @__PURE__ */ new Map();
1534
+ transactionsWithSigners.forEach(({ signer }, index) => {
1535
+ const indexes = signerGroups.get(signer) ?? [];
1536
+ indexes.push(index);
1537
+ signerGroups.set(signer, indexes);
1538
+ });
1539
+ const signerEntries = Array.from(signerGroups);
1540
+ const signedGroups = await Promise.all(signerEntries.map(([signer, indexes]) => signer(transactions, indexes)));
1541
+ const encodedSignedTransactions = new Array(transactionsWithSigners.length).fill(null);
1542
+ signerEntries.forEach(([, indexes], signerIndex) => {
1543
+ const stxs = signedGroups[signerIndex];
1544
+ indexes.forEach((txIndex, stxIndex) => {
1545
+ encodedSignedTransactions[txIndex] = stxs[stxIndex] ?? null;
1546
+ });
1547
+ });
1548
+ const unsignedIndexes = encodedSignedTransactions.map((stxn, index) => stxn == null ? index : null).filter((index) => index !== null);
1549
+ if (unsignedIndexes.length > 0) throw new Error(`Transactions at indexes [${unsignedIndexes.join(", ")}] were not signed`);
1550
+ return encodedSignedTransactions;
1551
+ }
1552
+ parseAbiReturnValues(confirmations) {
1553
+ const abiReturns = new Array();
1554
+ for (let i = 0; i < confirmations.length; i++) {
1555
+ const confirmation = confirmations[i];
1556
+ const txn = this.txns[i];
1557
+ if (txn?.type !== "methodCall") continue;
1558
+ const abiReturn = AppManager.getABIReturn(confirmation, txn.data.method);
1559
+ if (abiReturn !== void 0) abiReturns.push(abiReturn);
1560
+ }
1561
+ return abiReturns;
1562
+ }
1563
+ setMaxFees(maxFees) {
1564
+ maxFees.forEach((_, index) => {
1565
+ if (index > this.txns.length - 1) throw new Error(`Index ${index} is out of range. The composer only contains ${this.txns.length} transactions`);
1566
+ });
1567
+ maxFees.forEach((maxFee, index) => {
1568
+ this.txns[index].data.maxFee = new AlgoAmount({ microAlgos: maxFee.microAlgos });
1569
+ });
1570
+ }
1571
+ };
1572
+ /** Get the logical maximum fee based on staticFee and maxFee */
1573
+ function getLogicalMaxFee(ctxn) {
1574
+ if (ctxn.type === "txn" || ctxn.type === "asyncTxn") return;
1575
+ const maxFee = ctxn.data.maxFee;
1576
+ const staticFee = ctxn.data.staticFee;
1577
+ if (maxFee !== void 0 && (staticFee === void 0 || maxFee.microAlgos > staticFee.microAlgos)) return maxFee.microAlgos;
1578
+ return staticFee?.microAlgos;
1579
+ }
1580
+
1581
+ //#endregion
1582
+ export { TransactionComposer };
1583
+ //# sourceMappingURL=composer.mjs.map