@algorandfoundation/algokit-utils 9.2.0 → 9.2.1-beta.2

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 (340) hide show
  1. package/_virtual/_rolldown/runtime.js +33 -0
  2. package/_virtual/_rolldown/runtime.mjs +13 -0
  3. package/account/account.d.ts +25 -30
  4. package/account/account.js +151 -146
  5. package/account/account.js.map +1 -1
  6. package/account/account.mjs +149 -144
  7. package/account/account.mjs.map +1 -1
  8. package/account/get-account-config-from-environment.d.ts +7 -2
  9. package/account/get-account-config-from-environment.js +19 -21
  10. package/account/get-account-config-from-environment.js.map +1 -1
  11. package/account/get-account-config-from-environment.mjs +19 -19
  12. package/account/get-account-config-from-environment.mjs.map +1 -1
  13. package/account/get-account.d.ts +14 -12
  14. package/account/get-account.js +56 -59
  15. package/account/get-account.js.map +1 -1
  16. package/account/get-account.mjs +56 -57
  17. package/account/get-account.mjs.map +1 -1
  18. package/account/get-dispenser-account.d.ts +9 -5
  19. package/account/get-dispenser-account.js +20 -18
  20. package/account/get-dispenser-account.js.map +1 -1
  21. package/account/get-dispenser-account.mjs +20 -16
  22. package/account/get-dispenser-account.mjs.map +1 -1
  23. package/account/mnemonic-account.d.ts +7 -3
  24. package/account/mnemonic-account.js +17 -17
  25. package/account/mnemonic-account.js.map +1 -1
  26. package/account/mnemonic-account.mjs +15 -15
  27. package/account/mnemonic-account.mjs.map +1 -1
  28. package/amount.d.ts +40 -35
  29. package/amount.js +33 -34
  30. package/amount.js.map +1 -1
  31. package/amount.mjs +33 -32
  32. package/amount.mjs.map +1 -1
  33. package/app-client.d.ts +10 -6
  34. package/app-client.js +91 -86
  35. package/app-client.js.map +1 -1
  36. package/app-client.mjs +91 -84
  37. package/app-client.mjs.map +1 -1
  38. package/app-deploy.d.ts +26 -24
  39. package/app-deploy.js +235 -253
  40. package/app-deploy.js.map +1 -1
  41. package/app-deploy.mjs +233 -251
  42. package/app-deploy.mjs.map +1 -1
  43. package/app.d.ts +45 -46
  44. package/app.js +253 -271
  45. package/app.js.map +1 -1
  46. package/app.mjs +249 -267
  47. package/app.mjs.map +1 -1
  48. package/asset.d.ts +16 -12
  49. package/asset.js +116 -122
  50. package/asset.js.map +1 -1
  51. package/asset.mjs +116 -120
  52. package/asset.mjs.map +1 -1
  53. package/config.d.ts +7 -2
  54. package/config.js +5 -7
  55. package/config.js.map +1 -1
  56. package/config.mjs +5 -4
  57. package/config.mjs.map +1 -1
  58. package/debugging/debugging.d.ts +5 -1
  59. package/debugging/debugging.js +11 -11
  60. package/debugging/debugging.js.map +1 -1
  61. package/debugging/debugging.mjs +11 -9
  62. package/debugging/debugging.mjs.map +1 -1
  63. package/dispenser-client.d.ts +7 -2
  64. package/dispenser-client.js +23 -24
  65. package/dispenser-client.js.map +1 -1
  66. package/dispenser-client.mjs +23 -22
  67. package/dispenser-client.mjs.map +1 -1
  68. package/index.d.ts +27 -18
  69. package/index.js +140 -143
  70. package/index.mjs +27 -29
  71. package/indexer-lookup.d.ts +18 -11
  72. package/indexer-lookup.js +112 -120
  73. package/indexer-lookup.js.map +1 -1
  74. package/indexer-lookup.mjs +105 -118
  75. package/indexer-lookup.mjs.map +1 -1
  76. package/localnet/get-kmd-wallet-account.d.ts +9 -7
  77. package/localnet/get-kmd-wallet-account.js +28 -26
  78. package/localnet/get-kmd-wallet-account.js.map +1 -1
  79. package/localnet/get-kmd-wallet-account.mjs +28 -24
  80. package/localnet/get-kmd-wallet-account.mjs.map +1 -1
  81. package/localnet/get-localnet-dispenser-account.d.ts +7 -5
  82. package/localnet/get-localnet-dispenser-account.js +17 -15
  83. package/localnet/get-localnet-dispenser-account.js.map +1 -1
  84. package/localnet/get-localnet-dispenser-account.mjs +17 -13
  85. package/localnet/get-localnet-dispenser-account.mjs.map +1 -1
  86. package/localnet/get-or-create-kmd-wallet-account.d.ts +10 -8
  87. package/localnet/get-or-create-kmd-wallet-account.js +28 -26
  88. package/localnet/get-or-create-kmd-wallet-account.js.map +1 -1
  89. package/localnet/get-or-create-kmd-wallet-account.mjs +28 -24
  90. package/localnet/get-or-create-kmd-wallet-account.mjs.map +1 -1
  91. package/localnet/is-localnet.d.ts +7 -3
  92. package/localnet/is-localnet.js +9 -10
  93. package/localnet/is-localnet.js.map +1 -1
  94. package/localnet/is-localnet.mjs +9 -8
  95. package/localnet/is-localnet.mjs.map +1 -1
  96. package/network-client.d.ts +17 -15
  97. package/network-client.js +115 -116
  98. package/network-client.js.map +1 -1
  99. package/network-client.mjs +115 -114
  100. package/network-client.mjs.map +1 -1
  101. package/package.json +12 -3
  102. package/testing/account.d.ts +11 -9
  103. package/testing/account.js +31 -33
  104. package/testing/account.js.map +1 -1
  105. package/testing/account.mjs +29 -31
  106. package/testing/account.mjs.map +1 -1
  107. package/testing/fixtures/algokit-log-capture-fixture.d.ts +7 -2
  108. package/testing/fixtures/algokit-log-capture-fixture.js +36 -41
  109. package/testing/fixtures/algokit-log-capture-fixture.js.map +1 -1
  110. package/testing/fixtures/algokit-log-capture-fixture.mjs +36 -39
  111. package/testing/fixtures/algokit-log-capture-fixture.mjs.map +1 -1
  112. package/testing/fixtures/algorand-fixture.d.ts +9 -4
  113. package/testing/fixtures/algorand-fixture.js +67 -62
  114. package/testing/fixtures/algorand-fixture.js.map +1 -1
  115. package/testing/fixtures/algorand-fixture.mjs +66 -59
  116. package/testing/fixtures/algorand-fixture.mjs.map +1 -1
  117. package/testing/index.d.ts +7 -5
  118. package/testing/index.js +13 -18
  119. package/testing/index.mjs +7 -7
  120. package/testing/indexer.d.ts +5 -1
  121. package/testing/indexer.js +28 -37
  122. package/testing/indexer.js.map +1 -1
  123. package/testing/indexer.mjs +28 -35
  124. package/testing/indexer.mjs.map +1 -1
  125. package/testing/test-logger.d.ts +41 -36
  126. package/testing/test-logger.js +71 -76
  127. package/testing/test-logger.js.map +1 -1
  128. package/testing/test-logger.mjs +71 -74
  129. package/testing/test-logger.mjs.map +1 -1
  130. package/testing/transaction-logger.d.ts +30 -27
  131. package/testing/transaction-logger.js +77 -93
  132. package/testing/transaction-logger.js.map +1 -1
  133. package/testing/transaction-logger.mjs +74 -90
  134. package/testing/transaction-logger.mjs.map +1 -1
  135. package/transaction/legacy-bridge.js +100 -111
  136. package/transaction/legacy-bridge.js.map +1 -1
  137. package/transaction/legacy-bridge.mjs +97 -108
  138. package/transaction/legacy-bridge.mjs.map +1 -1
  139. package/transaction/perform-atomic-transaction-composer-simulate.d.ts +7 -5
  140. package/transaction/perform-atomic-transaction-composer-simulate.js +31 -36
  141. package/transaction/perform-atomic-transaction-composer-simulate.js.map +1 -1
  142. package/transaction/perform-atomic-transaction-composer-simulate.mjs +28 -33
  143. package/transaction/perform-atomic-transaction-composer-simulate.mjs.map +1 -1
  144. package/transaction/transaction.d.ts +34 -35
  145. package/transaction/transaction.js +716 -914
  146. package/transaction/transaction.js.map +1 -1
  147. package/transaction/transaction.mjs +713 -911
  148. package/transaction/transaction.mjs.map +1 -1
  149. package/transfer/transfer-algos.d.ts +9 -5
  150. package/transfer/transfer-algos.js +26 -27
  151. package/transfer/transfer-algos.js.map +1 -1
  152. package/transfer/transfer-algos.mjs +26 -25
  153. package/transfer/transfer-algos.mjs.map +1 -1
  154. package/transfer/transfer.d.ts +11 -8
  155. package/transfer/transfer.js +94 -100
  156. package/transfer/transfer.js.map +1 -1
  157. package/transfer/transfer.mjs +94 -98
  158. package/transfer/transfer.mjs.map +1 -1
  159. package/types/account-manager.d.ts +432 -429
  160. package/types/account-manager.js +591 -602
  161. package/types/account-manager.js.map +1 -1
  162. package/types/account-manager.mjs +587 -599
  163. package/types/account-manager.mjs.map +1 -1
  164. package/types/account.d.ts +192 -202
  165. package/types/account.js +91 -88
  166. package/types/account.js.map +1 -1
  167. package/types/account.mjs +88 -86
  168. package/types/account.mjs.map +1 -1
  169. package/types/algo-http-client-with-retry.d.ts +15 -10
  170. package/types/algo-http-client-with-retry.js +70 -92
  171. package/types/algo-http-client-with-retry.js.map +1 -1
  172. package/types/algo-http-client-with-retry.mjs +69 -90
  173. package/types/algo-http-client-with-retry.mjs.map +1 -1
  174. package/types/algorand-client-transaction-creator.d.ts +778 -771
  175. package/types/algorand-client-transaction-creator.js +733 -732
  176. package/types/algorand-client-transaction-creator.js.map +1 -1
  177. package/types/algorand-client-transaction-creator.mjs +732 -730
  178. package/types/algorand-client-transaction-creator.mjs.map +1 -1
  179. package/types/algorand-client-transaction-sender.d.ts +1090 -1360
  180. package/types/algorand-client-transaction-sender.js +930 -961
  181. package/types/algorand-client-transaction-sender.js.map +1 -1
  182. package/types/algorand-client-transaction-sender.mjs +927 -959
  183. package/types/algorand-client-transaction-sender.mjs.map +1 -1
  184. package/types/algorand-client.d.ts +239 -236
  185. package/types/algorand-client.js +322 -320
  186. package/types/algorand-client.js.map +1 -1
  187. package/types/algorand-client.mjs +321 -318
  188. package/types/algorand-client.mjs.map +1 -1
  189. package/types/amount.d.ts +47 -43
  190. package/types/amount.js +66 -70
  191. package/types/amount.js.map +1 -1
  192. package/types/amount.mjs +63 -68
  193. package/types/amount.mjs.map +1 -1
  194. package/types/app-arc56.d.ts +235 -272
  195. package/types/app-arc56.js +124 -170
  196. package/types/app-arc56.js.map +1 -1
  197. package/types/app-arc56.mjs +121 -168
  198. package/types/app-arc56.mjs.map +1 -1
  199. package/types/app-client.d.ts +1128 -2009
  200. package/types/app-client.js +1633 -1791
  201. package/types/app-client.js.map +1 -1
  202. package/types/app-client.mjs +1624 -1783
  203. package/types/app-client.mjs.map +1 -1
  204. package/types/app-deployer.d.ts +139 -141
  205. package/types/app-deployer.js +344 -384
  206. package/types/app-deployer.js.map +1 -1
  207. package/types/app-deployer.mjs +341 -382
  208. package/types/app-deployer.mjs.map +1 -1
  209. package/types/app-factory.d.ts +762 -932
  210. package/types/app-factory.js +496 -488
  211. package/types/app-factory.js.map +1 -1
  212. package/types/app-factory.mjs +491 -484
  213. package/types/app-factory.mjs.map +1 -1
  214. package/types/app-manager.d.ts +304 -310
  215. package/types/app-manager.js +422 -475
  216. package/types/app-manager.js.map +1 -1
  217. package/types/app-manager.mjs +419 -473
  218. package/types/app-manager.mjs.map +1 -1
  219. package/types/app-spec.d.ts +118 -117
  220. package/types/app-spec.js +125 -135
  221. package/types/app-spec.js.map +1 -1
  222. package/types/app-spec.mjs +121 -132
  223. package/types/app-spec.mjs.map +1 -1
  224. package/types/app.d.ts +229 -241
  225. package/types/app.js +36 -28
  226. package/types/app.js.map +1 -1
  227. package/types/app.mjs +33 -26
  228. package/types/app.mjs.map +1 -1
  229. package/types/asset-manager.d.ts +204 -199
  230. package/types/asset-manager.js +165 -174
  231. package/types/asset-manager.js.map +1 -1
  232. package/types/asset-manager.mjs +164 -172
  233. package/types/asset-manager.mjs.map +1 -1
  234. package/types/asset.d.ts +95 -91
  235. package/types/asset.js +0 -3
  236. package/types/asset.mjs +0 -2
  237. package/types/async-event-emitter.d.ts +18 -13
  238. package/types/async-event-emitter.js +37 -49
  239. package/types/async-event-emitter.js.map +1 -1
  240. package/types/async-event-emitter.mjs +36 -47
  241. package/types/async-event-emitter.mjs.map +1 -1
  242. package/types/client-manager.d.ts +453 -451
  243. package/types/client-manager.js +602 -598
  244. package/types/client-manager.js.map +1 -1
  245. package/types/client-manager.mjs +597 -594
  246. package/types/client-manager.mjs.map +1 -1
  247. package/types/composer.d.ts +1211 -1258
  248. package/types/composer.js +1436 -1498
  249. package/types/composer.js.map +1 -1
  250. package/types/composer.mjs +1430 -1493
  251. package/types/composer.mjs.map +1 -1
  252. package/types/config.d.ts +53 -48
  253. package/types/config.js +78 -77
  254. package/types/config.js.map +1 -1
  255. package/types/config.mjs +77 -75
  256. package/types/config.mjs.map +1 -1
  257. package/types/debugging.d.ts +25 -23
  258. package/types/debugging.js +9 -11
  259. package/types/debugging.js.map +1 -1
  260. package/types/debugging.mjs +8 -9
  261. package/types/debugging.mjs.map +1 -1
  262. package/types/dispenser-client.d.ts +57 -52
  263. package/types/dispenser-client.js +120 -141
  264. package/types/dispenser-client.js.map +1 -1
  265. package/types/dispenser-client.mjs +119 -139
  266. package/types/dispenser-client.mjs.map +1 -1
  267. package/types/expand.d.ts +5 -3
  268. package/types/expand.js +0 -3
  269. package/types/expand.mjs +0 -2
  270. package/types/indexer.d.ts +104 -100
  271. package/types/indexer.js +36 -31
  272. package/types/indexer.js.map +1 -1
  273. package/types/indexer.mjs +32 -30
  274. package/types/indexer.mjs.map +1 -1
  275. package/types/instance-of.d.ts +5 -3
  276. package/types/instance-of.js +0 -3
  277. package/types/instance-of.mjs +0 -2
  278. package/types/kmd-account-manager.d.ts +75 -70
  279. package/types/kmd-account-manager.js +150 -184
  280. package/types/kmd-account-manager.js.map +1 -1
  281. package/types/kmd-account-manager.mjs +147 -182
  282. package/types/kmd-account-manager.mjs.map +1 -1
  283. package/types/lifecycle-events.d.ts +13 -8
  284. package/types/lifecycle-events.js +10 -7
  285. package/types/lifecycle-events.js.map +1 -1
  286. package/types/lifecycle-events.mjs +9 -7
  287. package/types/lifecycle-events.mjs.map +1 -1
  288. package/types/logging.d.ts +15 -11
  289. package/types/logging.js +30 -31
  290. package/types/logging.js.map +1 -1
  291. package/types/logging.mjs +29 -29
  292. package/types/logging.mjs.map +1 -1
  293. package/types/logic-error.d.ts +33 -29
  294. package/types/logic-error.js +50 -49
  295. package/types/logic-error.js.map +1 -1
  296. package/types/logic-error.mjs +49 -47
  297. package/types/logic-error.mjs.map +1 -1
  298. package/types/network-client.d.ts +32 -27
  299. package/types/network-client.js +10 -9
  300. package/types/network-client.js.map +1 -1
  301. package/types/network-client.mjs +9 -7
  302. package/types/network-client.mjs.map +1 -1
  303. package/types/testing.d.ts +131 -132
  304. package/types/testing.js +0 -3
  305. package/types/testing.mjs +0 -2
  306. package/types/transaction.d.ts +110 -110
  307. package/types/transaction.js +0 -3
  308. package/types/transaction.mjs +0 -2
  309. package/types/transfer.d.ts +70 -66
  310. package/types/transfer.js +0 -3
  311. package/types/transfer.mjs +0 -2
  312. package/util.js +73 -118
  313. package/util.js.map +1 -1
  314. package/util.mjs +73 -116
  315. package/util.mjs.map +1 -1
  316. package/account/index.d.ts +0 -5
  317. package/debugging/index.d.ts +0 -1
  318. package/index.js.map +0 -1
  319. package/index.mjs.map +0 -1
  320. package/localnet/index.d.ts +0 -4
  321. package/testing/_asset.d.ts +0 -3
  322. package/testing/fixtures/index.d.ts +0 -2
  323. package/testing/index.js.map +0 -1
  324. package/testing/index.mjs.map +0 -1
  325. package/transaction/index.d.ts +0 -2
  326. package/transaction/legacy-bridge.d.ts +0 -35
  327. package/transfer/index.d.ts +0 -2
  328. package/types/asset.js.map +0 -1
  329. package/types/asset.mjs.map +0 -1
  330. package/types/expand.js.map +0 -1
  331. package/types/expand.mjs.map +0 -1
  332. package/types/instance-of.js.map +0 -1
  333. package/types/instance-of.mjs.map +0 -1
  334. package/types/testing.js.map +0 -1
  335. package/types/testing.mjs.map +0 -1
  336. package/types/transaction.js.map +0 -1
  337. package/types/transaction.mjs.map +0 -1
  338. package/types/transfer.js.map +0 -1
  339. package/types/transfer.mjs.map +0 -1
  340. package/util.d.ts +0 -48
@@ -1,386 +1,346 @@
1
- 'use strict';
2
-
3
- var algosdk = require('algosdk');
4
- var config = require('../config.js');
5
- var indexerLookup = require('../indexer-lookup.js');
6
- var util = require('../util.js');
7
- var types_app = require('./app.js');
8
- var types_composer = require('./composer.js');
9
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.js");
3
+ const require_config = require("../config.js");
4
+ const require_app = require("./app.js");
5
+ const require_util = require("../util.js");
6
+ const require_composer = require("./composer.js");
7
+ const require_indexer_lookup = require("../indexer-lookup.js");
8
+ let algosdk = require("algosdk");
9
+ algosdk = require_runtime.__toESM(algosdk);
10
+ //#region src/types/app-deployer.ts
10
11
  /** Allows management of deployment and deployment metadata of applications. */
11
- class AppDeployer {
12
- /**
13
- * Creates an `AppManager`
14
- * @param appManager An `AppManager` instance
15
- * @param transactionSender An `AlgorandClientTransactionSender` instance
16
- * @param indexer An optional indexer instance; supply if you want to indexer to look up app metadata
17
- * @example
18
- * ```ts
19
- * const deployer = new AppDeployer(appManager, transactionSender, indexer)
20
- * ```
21
- */
22
- constructor(appManager, transactionSender, indexer) {
23
- this._appLookups = new Map();
24
- this._appManager = appManager;
25
- this._transactionSender = transactionSender;
26
- this._indexer = indexer;
27
- }
28
- /**
29
- * Idempotently deploy (create if not exists, update if changed) an app against the given name for the given creator account, including deploy-time TEAL template placeholder substitutions (if specified).
30
- *
31
- * To understand the architecture decisions behind this functionality please see https://github.com/algorandfoundation/algokit-cli/blob/main/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md
32
- *
33
- * **Note:** When using the return from this function be sure to check `operationPerformed` to get access to various return properties like `transaction`, `confirmation` and `deleteResult`.
34
- *
35
- * **Note:** if there is a breaking state schema change to an existing app (and `onSchemaBreak` is set to `'replace'`) the existing app will be deleted and re-created.
36
- *
37
- * **Note:** if there is an update (different TEAL code) to an existing app (and `onUpdate` is set to `'replace'`) the existing app will be deleted and re-created.
38
- * @param deployment The arguments to control the app deployment
39
- * @returns The result of the deployment
40
- * @example
41
- * ```ts
42
- * const deployResult = await deployer.deploy({
43
- * createParams: {
44
- * sender: 'SENDER_ADDRESS',
45
- * approvalProgram: 'APPROVAL PROGRAM',
46
- * clearStateProgram: 'CLEAR PROGRAM',
47
- * schema: {
48
- * globalByteSlices: 0,
49
- * globalInts: 0,
50
- * localByteSlices: 0,
51
- * localInts: 0
52
- * }
53
- * },
54
- * updateParams: {
55
- * sender: 'SENDER_ADDRESS'
56
- * },
57
- * deleteParams: {
58
- * sender: 'SENDER_ADDRESS'
59
- * },
60
- * metadata: { name: 'my_app', version: '2.0', updatable: false, deletable: false },
61
- * onSchemaBreak: 'append',
62
- * onUpdate: 'append'
63
- * })
64
- * ```
65
- */
66
- async deploy(deployment) {
67
- const { metadata, deployTimeParams, onSchemaBreak, onUpdate, createParams, updateParams, deleteParams, existingDeployments, ignoreCache, ...sendParams } = deployment;
68
- // Set creation note
69
- createParams.note = updateParams.note = types_composer.TransactionComposer.arc2Note({
70
- dAppName: types_app.APP_DEPLOY_NOTE_DAPP,
71
- data: metadata,
72
- format: 'j',
73
- });
74
- // Check for required fields
75
- if (existingDeployments && existingDeployments.creator.toString() !== createParams.sender.toString()) {
76
- throw new Error(`Received invalid existingDeployments value for creator ${existingDeployments.creator} when attempting to deploy for creator ${createParams.sender}`);
77
- }
78
- if (!existingDeployments && !this._indexer) {
79
- throw new Error(`Didn't receive an indexer client when this AppManager was created, but also didn't receive an existingDeployments cache - one of them must be provided`);
80
- }
81
- config.Config.getLogger(sendParams?.suppressLog).info(`Idempotently deploying app "${metadata.name}" from creator ${createParams.sender} using ${createParams.approvalProgram.length} bytes of ${typeof createParams.approvalProgram === 'string' ? 'teal code' : 'AVM bytecode'} and ${createParams.clearStateProgram.length} bytes of ${typeof createParams.approvalProgram === 'string' ? 'teal code' : 'AVM bytecode'}`);
82
- // Compile code if required
83
- const compiledApproval = typeof createParams.approvalProgram === 'string'
84
- ? await this._appManager.compileTealTemplate(createParams.approvalProgram, deployTimeParams, metadata)
85
- : undefined;
86
- const approvalProgram = compiledApproval ? compiledApproval.compiledBase64ToBytes : createParams.approvalProgram;
87
- const compiledClear = typeof createParams.clearStateProgram === 'string'
88
- ? await this._appManager.compileTealTemplate(createParams.clearStateProgram, deployTimeParams)
89
- : undefined;
90
- const clearStateProgram = compiledClear ? compiledClear.compiledBase64ToBytes : createParams.clearStateProgram;
91
- // Define routines for create, update, and replace
92
- const createApp = async () => {
93
- const result = await ('method' in createParams
94
- ? this._transactionSender.appCreateMethodCall({ ...createParams, approvalProgram, clearStateProgram, ...sendParams })
95
- : this._transactionSender.appCreate({ ...createParams, approvalProgram, clearStateProgram, ...sendParams }));
96
- const appMetadata = {
97
- appId: result.appId,
98
- appAddress: result.appAddress,
99
- ...metadata,
100
- createdMetadata: metadata,
101
- createdRound: BigInt(result.confirmation.confirmedRound),
102
- updatedRound: BigInt(result.confirmation.confirmedRound),
103
- deleted: false,
104
- };
105
- this.updateAppLookup(createParams.sender, appMetadata);
106
- return {
107
- operationPerformed: 'create',
108
- compiledApproval,
109
- compiledClear,
110
- ...result,
111
- ...appMetadata,
112
- };
113
- };
114
- const updateApp = async (existingApp) => {
115
- config.Config.getLogger(sendParams?.suppressLog).info(`Updating existing ${metadata.name} app for ${createParams.sender} to version ${metadata.version}.`);
116
- const result = await ('method' in updateParams
117
- ? this._transactionSender.appUpdateMethodCall({
118
- appId: existingApp.appId,
119
- approvalProgram,
120
- clearStateProgram,
121
- ...updateParams,
122
- ...sendParams,
123
- })
124
- : this._transactionSender.appUpdate({
125
- appId: existingApp.appId,
126
- approvalProgram,
127
- clearStateProgram,
128
- ...updateParams,
129
- ...sendParams,
130
- }));
131
- const appMetadata = {
132
- appId: existingApp.appId,
133
- appAddress: existingApp.appAddress,
134
- createdMetadata: existingApp.createdMetadata,
135
- createdRound: existingApp.createdRound,
136
- updatedRound: BigInt(result.confirmation.confirmedRound),
137
- ...metadata,
138
- deleted: false,
139
- };
140
- this.updateAppLookup(createParams.sender, appMetadata);
141
- return {
142
- operationPerformed: 'update',
143
- compiledApproval,
144
- compiledClear,
145
- ...result,
146
- ...appMetadata,
147
- };
148
- };
149
- const replaceApp = async (existingApp) => {
150
- config.Config.getLogger(sendParams?.suppressLog).info(`Deploying a new ${metadata.name} app for ${createParams.sender}; deploying app with version ${metadata.version}.`);
151
- config.Config.getLogger(sendParams?.suppressLog).warn(`Deleting existing ${metadata.name} app with id ${existingApp.appId} from ${deleteParams.sender} account.`);
152
- const composer = this._transactionSender.newGroup();
153
- if ('method' in createParams) {
154
- composer.addAppCreateMethodCall({ ...createParams, approvalProgram, clearStateProgram });
155
- }
156
- else {
157
- composer.addAppCreate({ ...createParams, approvalProgram, clearStateProgram });
158
- }
159
- const createIndex = await composer.count();
160
- if ('method' in deleteParams) {
161
- composer.addAppDeleteMethodCall({ appId: existingApp.appId, ...deleteParams });
162
- }
163
- else {
164
- composer.addAppDelete({ appId: existingApp.appId, ...deleteParams });
165
- }
166
- const result = await composer.send({ ...sendParams });
167
- const confirmation = result.confirmations.at(createIndex - 1);
168
- const transaction = result.transactions.at(createIndex - 1);
169
- const deleteTransaction = result.transactions.at(-1);
170
- config.Config.getLogger(sendParams?.suppressLog).warn(`Sent transactions ${transaction.txID()} to create app with id ${confirmation.applicationIndex} and ${deleteTransaction.txID()} to delete app with id ${existingApp.appId} from ${createParams.sender} account.`);
171
- const appMetadata = {
172
- appId: BigInt(confirmation.applicationIndex),
173
- appAddress: algosdk.getApplicationAddress(confirmation.applicationIndex),
174
- ...metadata,
175
- createdMetadata: metadata,
176
- createdRound: BigInt(confirmation.confirmedRound),
177
- updatedRound: BigInt(confirmation.confirmedRound),
178
- deleted: false,
179
- };
180
- this.updateAppLookup(createParams.sender, appMetadata);
181
- return {
182
- operationPerformed: 'replace',
183
- ...result,
184
- compiledApproval,
185
- compiledClear,
186
- transaction,
187
- confirmation,
188
- return: 'method' in createParams ? result.returns?.[0] : undefined,
189
- deleteReturn: 'method' in deleteParams ? result.returns?.at(-1) : undefined,
190
- ...appMetadata,
191
- deleteResult: { transaction: deleteTransaction, confirmation: result.confirmations.at(-1) },
192
- };
193
- };
194
- // Lookup existing app metadata
195
- const apps = existingDeployments ?? (await this.getCreatorAppsByName(createParams.sender, ignoreCache));
196
- const existingApp = apps.apps[metadata.name];
197
- if (!existingApp || existingApp.deleted) {
198
- config.Config.getLogger(sendParams?.suppressLog).info(`App ${metadata.name} not found in apps created by ${createParams.sender}; deploying app with version ${metadata.version}.`);
199
- return await createApp();
200
- }
201
- config.Config.getLogger(sendParams?.suppressLog).info(`Existing app ${metadata.name} found by creator ${createParams.sender}, with app id ${existingApp.appId} and version ${existingApp.version}.`);
202
- const existingAppRecord = await this._appManager.getById(existingApp.appId);
203
- const existingApproval = Buffer.from(existingAppRecord.approvalProgram).toString('base64');
204
- const existingClear = Buffer.from(existingAppRecord.clearStateProgram).toString('base64');
205
- const extraPages = existingAppRecord.extraProgramPages ?? 0;
206
- const newApprovalBytes = Buffer.from(approvalProgram);
207
- const newClearBytes = Buffer.from(clearStateProgram);
208
- const newApproval = newApprovalBytes.toString('base64');
209
- const newClear = newClearBytes.toString('base64');
210
- const newExtraPages = util.calculateExtraProgramPages(newApprovalBytes, newClearBytes);
211
- // Check for changes
212
- const isUpdate = newApproval !== existingApproval || newClear !== existingClear;
213
- const isSchemaBreak = existingAppRecord.localInts < (createParams.schema?.localInts ?? 0) ||
214
- existingAppRecord.globalInts < (createParams.schema?.globalInts ?? 0) ||
215
- existingAppRecord.localByteSlices < (createParams.schema?.localByteSlices ?? 0) ||
216
- existingAppRecord.globalByteSlices < (createParams.schema?.globalByteSlices ?? 0) ||
217
- extraPages < newExtraPages;
218
- if (isSchemaBreak) {
219
- config.Config.getLogger(sendParams?.suppressLog).warn(`Detected a breaking app schema change in app ${existingApp.appId}:`, {
220
- from: {
221
- globalInts: existingAppRecord.globalInts,
222
- globalByteSlices: existingAppRecord.globalByteSlices,
223
- localInts: existingAppRecord.localInts,
224
- localByteSlices: existingAppRecord.localByteSlices,
225
- extraProgramPages: extraPages,
226
- },
227
- to: { ...createParams.schema, extraProgramPages: newExtraPages },
228
- });
229
- if (onSchemaBreak === undefined || onSchemaBreak === 'fail' || onSchemaBreak === types_app.OnSchemaBreak.Fail) {
230
- throw new Error('Schema break detected and onSchemaBreak=OnSchemaBreak.Fail, stopping deployment. ' +
231
- 'If you want to try deleting and recreating the app then ' +
232
- 're-run with onSchemaBreak=OnSchemaBreak.ReplaceApp');
233
- }
234
- if (onSchemaBreak === 'append' || onSchemaBreak === types_app.OnSchemaBreak.AppendApp) {
235
- config.Config.getLogger(sendParams?.suppressLog).info('onSchemaBreak=AppendApp, will attempt to create a new app');
236
- return await createApp();
237
- }
238
- if (existingApp.deletable) {
239
- config.Config.getLogger(sendParams?.suppressLog).info('App is deletable and onSchemaBreak=ReplaceApp, will attempt to create new app and delete old app');
240
- }
241
- else {
242
- config.Config.getLogger(sendParams?.suppressLog).info('App is not deletable but onSchemaBreak=ReplaceApp, will attempt to delete app, delete will most likely fail');
243
- }
244
- return await replaceApp(existingApp);
245
- }
246
- if (isUpdate) {
247
- config.Config.getLogger(sendParams?.suppressLog).info(`Detected a TEAL update in app ${existingApp.appId} for creator ${createParams.sender}`);
248
- if (onUpdate === undefined || onUpdate === 'fail' || onUpdate === types_app.OnUpdate.Fail) {
249
- throw new Error('Update detected and onUpdate=Fail, stopping deployment. Try a different onUpdate value to not fail.');
250
- }
251
- if (onUpdate === 'append' || onUpdate === types_app.OnUpdate.AppendApp) {
252
- config.Config.getLogger(sendParams?.suppressLog).info('onUpdate=AppendApp, will attempt to create a new app');
253
- return await createApp();
254
- }
255
- if (onUpdate === 'update' || onUpdate === types_app.OnUpdate.UpdateApp) {
256
- if (existingApp.updatable) {
257
- config.Config.getLogger(sendParams?.suppressLog).info(`App is updatable and onUpdate=UpdateApp, updating app...`);
258
- }
259
- else {
260
- config.Config.getLogger(sendParams?.suppressLog).warn(`App is not updatable but onUpdate=UpdateApp, will attempt to update app, update will most likely fail`);
261
- }
262
- return await updateApp(existingApp);
263
- }
264
- if (onUpdate === 'replace' || onUpdate === types_app.OnUpdate.ReplaceApp) {
265
- if (existingApp.deletable) {
266
- config.Config.getLogger(sendParams?.suppressLog).warn('App is deletable and onUpdate=ReplaceApp, creating new app and deleting old app...');
267
- }
268
- else {
269
- config.Config.getLogger(sendParams?.suppressLog).warn('App is not deletable and onUpdate=ReplaceApp, will attempt to create new app and delete old app, delete will most likely fail');
270
- }
271
- return await replaceApp(existingApp);
272
- }
273
- }
274
- config.Config.getLogger(sendParams?.suppressLog).debug('No detected changes in app, nothing to do.');
275
- return { ...existingApp, operationPerformed: 'nothing' };
276
- }
277
- updateAppLookup(sender, appMetadata) {
278
- const s = typeof sender === 'string' ? sender : sender.toString();
279
- const lookup = this._appLookups.get(s);
280
- if (!lookup) {
281
- this._appLookups.set(s, { creator: algosdk.Address.fromString(s), apps: { [appMetadata.name]: appMetadata } });
282
- }
283
- else {
284
- lookup.apps[appMetadata.name] = appMetadata;
285
- }
286
- }
287
- /**
288
- * Returns a lookup of name => app metadata (id, address, ...metadata) for all apps created by the given account that have
289
- * an [ARC-2](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0002.md) `AppDeployNote` as the transaction
290
- * note of the app creation transaction.
291
- *
292
- * This function caches the result for the given creator account so that subsequent calls will not require an indexer lookup.
293
- *
294
- * If the `AppManager` instance wasn't created with an indexer client, this function will throw an error.
295
- *
296
- * @param creatorAddress The address of the account that is the creator of the apps you want to search for
297
- * @param ignoreCache Whether or not to ignore the cache and force a lookup, default: use the cache
298
- * @returns A name-based lookup of the app metadata
299
- * @example
300
- * ```ts
301
- * const result = await deployer.getCreatorAppsByName(creator)
302
- */
303
- async getCreatorAppsByName(creatorAddress, ignoreCache) {
304
- const appLookup = {};
305
- const address = typeof creatorAddress === 'string' ? creatorAddress : creatorAddress.toString();
306
- if (!ignoreCache && this._appLookups.has(address)) {
307
- return this._appLookups.get(address);
308
- }
309
- if (!this._indexer) {
310
- throw new Error(`Didn't receive an indexer client when this AppManager was created, but received a call to getCreatorApps`);
311
- }
312
- // Extract all apps that account created
313
- const createdApps = (await indexerLookup.lookupAccountCreatedApplicationByAddress(this._indexer, creatorAddress))
314
- .map((a) => {
315
- return { id: a.id, createdAtRound: a.createdAtRound, deleted: a.deleted };
316
- })
317
- .sort((a, b) => Number(a.createdAtRound - b.createdAtRound));
318
- // For each app that account created (in parallel)...
319
- const apps = await Promise.all(createdApps.map(async (createdApp) => {
320
- // Find any app transactions for that app in the round it was created (should always just be a single creation transaction)
321
- const appTransactions = await indexerLookup.searchTransactions(this._indexer, (s) => s
322
- .minRound(createdApp.createdAtRound)
323
- .txType(algosdk.TransactionType.appl)
324
- .applicationID(Number(createdApp.id))
325
- .address(creatorAddress)
326
- .addressRole('sender')
327
- .notePrefix(Buffer.from(types_app.APP_DEPLOY_NOTE_DAPP).toString('base64')));
328
- // Triple check the transaction is intact by filtering for the one we want:
329
- // * application-id is 0 when the app is first created
330
- // * also verify the sender to prevent a potential security risk
331
- const appCreationTransaction = appTransactions.transactions.filter((t) => t.applicationTransaction?.applicationId === 0n && t.sender.toString() === creatorAddress.toString())[0];
332
- const latestAppUpdateTransaction = appTransactions.transactions
333
- .filter((t) => t.sender.toString() === creatorAddress.toString())
334
- .sort((a, b) => a.confirmedRound === b.confirmedRound
335
- ? (b.intraRoundOffset - a.intraRoundOffset) / 10
336
- : Number(b.confirmedRound - a.confirmedRound))[0];
337
- if (!appCreationTransaction?.note)
338
- // No note; ignoring
339
- return null;
340
- return { createdApp, appCreationTransaction, latestAppUpdateTransaction };
341
- }));
342
- apps
343
- .filter((a) => a !== null)
344
- .forEach((a) => {
345
- const { createdApp, appCreationTransaction, latestAppUpdateTransaction } = a;
346
- const parseNote = (note) => {
347
- if (!note) {
348
- // No note; ignoring...
349
- return;
350
- }
351
- if (!note.startsWith(`${types_app.APP_DEPLOY_NOTE_DAPP}:j{`))
352
- // Clearly not APP_DEPLOY JSON; ignoring...
353
- return;
354
- return JSON.parse(note.substring(types_app.APP_DEPLOY_NOTE_DAPP.length + 2));
355
- };
356
- try {
357
- const creationNote = parseNote(appCreationTransaction.note ? Buffer.from(appCreationTransaction.note).toString('utf-8') : undefined);
358
- const updateNote = parseNote(latestAppUpdateTransaction.note ? Buffer.from(latestAppUpdateTransaction.note).toString('utf-8') : undefined);
359
- if (creationNote?.name) {
360
- appLookup[creationNote.name] = {
361
- appId: createdApp.id,
362
- appAddress: algosdk.getApplicationAddress(createdApp.id),
363
- createdMetadata: creationNote,
364
- createdRound: appCreationTransaction.confirmedRound ?? 0n,
365
- ...(updateNote ?? creationNote),
366
- updatedRound: latestAppUpdateTransaction?.confirmedRound ?? 0n,
367
- deleted: createdApp.deleted ?? false,
368
- };
369
- }
370
- }
371
- catch (e) {
372
- config.Config.logger.warn(`Received error trying to retrieve app with ${createdApp.id} for creator ${creatorAddress}; failing silently`, e);
373
- return;
374
- }
375
- });
376
- const lookup = {
377
- creator: typeof creatorAddress === 'string' ? algosdk.Address.fromString(creatorAddress) : creatorAddress,
378
- apps: appLookup,
379
- };
380
- this._appLookups.set(creatorAddress.toString(), lookup);
381
- return lookup;
382
- }
383
- }
384
-
12
+ var AppDeployer = class {
13
+ _appManager;
14
+ _transactionSender;
15
+ _indexer;
16
+ _appLookups = /* @__PURE__ */ new Map();
17
+ /**
18
+ * Creates an `AppManager`
19
+ * @param appManager An `AppManager` instance
20
+ * @param transactionSender An `AlgorandClientTransactionSender` instance
21
+ * @param indexer An optional indexer instance; supply if you want to indexer to look up app metadata
22
+ * @example
23
+ * ```ts
24
+ * const deployer = new AppDeployer(appManager, transactionSender, indexer)
25
+ * ```
26
+ */
27
+ constructor(appManager, transactionSender, indexer) {
28
+ this._appManager = appManager;
29
+ this._transactionSender = transactionSender;
30
+ this._indexer = indexer;
31
+ }
32
+ /**
33
+ * Idempotently deploy (create if not exists, update if changed) an app against the given name for the given creator account, including deploy-time TEAL template placeholder substitutions (if specified).
34
+ *
35
+ * To understand the architecture decisions behind this functionality please see https://github.com/algorandfoundation/algokit-cli/blob/main/docs/src/content/docs/architecture-decisions/2023-01-12_smart-contract-deployment.md
36
+ *
37
+ * **Note:** When using the return from this function be sure to check `operationPerformed` to get access to various return properties like `transaction`, `confirmation` and `deleteResult`.
38
+ *
39
+ * **Note:** if there is a breaking state schema change to an existing app (and `onSchemaBreak` is set to `'replace'`) the existing app will be deleted and re-created.
40
+ *
41
+ * **Note:** if there is an update (different TEAL code) to an existing app (and `onUpdate` is set to `'replace'`) the existing app will be deleted and re-created.
42
+ * @param deployment The arguments to control the app deployment
43
+ * @returns The result of the deployment
44
+ * @example
45
+ * ```ts
46
+ * const deployResult = await deployer.deploy({
47
+ * createParams: {
48
+ * sender: 'SENDER_ADDRESS',
49
+ * approvalProgram: 'APPROVAL PROGRAM',
50
+ * clearStateProgram: 'CLEAR PROGRAM',
51
+ * schema: {
52
+ * globalByteSlices: 0,
53
+ * globalInts: 0,
54
+ * localByteSlices: 0,
55
+ * localInts: 0
56
+ * }
57
+ * },
58
+ * updateParams: {
59
+ * sender: 'SENDER_ADDRESS'
60
+ * },
61
+ * deleteParams: {
62
+ * sender: 'SENDER_ADDRESS'
63
+ * },
64
+ * metadata: { name: 'my_app', version: '2.0', updatable: false, deletable: false },
65
+ * onSchemaBreak: 'append',
66
+ * onUpdate: 'append'
67
+ * })
68
+ * ```
69
+ */
70
+ async deploy(deployment) {
71
+ const { metadata, deployTimeParams, onSchemaBreak, onUpdate, createParams, updateParams, deleteParams, existingDeployments, ignoreCache, ...sendParams } = deployment;
72
+ createParams.note = updateParams.note = require_composer.TransactionComposer.arc2Note({
73
+ dAppName: require_app.APP_DEPLOY_NOTE_DAPP,
74
+ data: metadata,
75
+ format: "j"
76
+ });
77
+ if (existingDeployments && existingDeployments.creator.toString() !== createParams.sender.toString()) throw new Error(`Received invalid existingDeployments value for creator ${existingDeployments.creator} when attempting to deploy for creator ${createParams.sender}`);
78
+ if (!existingDeployments && !this._indexer) throw new Error(`Didn't receive an indexer client when this AppManager was created, but also didn't receive an existingDeployments cache - one of them must be provided`);
79
+ require_config.Config.getLogger(sendParams?.suppressLog).info(`Idempotently deploying app "${metadata.name}" from creator ${createParams.sender} using ${createParams.approvalProgram.length} bytes of ${typeof createParams.approvalProgram === "string" ? "teal code" : "AVM bytecode"} and ${createParams.clearStateProgram.length} bytes of ${typeof createParams.approvalProgram === "string" ? "teal code" : "AVM bytecode"}`);
80
+ const compiledApproval = typeof createParams.approvalProgram === "string" ? await this._appManager.compileTealTemplate(createParams.approvalProgram, deployTimeParams, metadata) : void 0;
81
+ const approvalProgram = compiledApproval ? compiledApproval.compiledBase64ToBytes : createParams.approvalProgram;
82
+ const compiledClear = typeof createParams.clearStateProgram === "string" ? await this._appManager.compileTealTemplate(createParams.clearStateProgram, deployTimeParams) : void 0;
83
+ const clearStateProgram = compiledClear ? compiledClear.compiledBase64ToBytes : createParams.clearStateProgram;
84
+ const createApp = async () => {
85
+ const result = await ("method" in createParams ? this._transactionSender.appCreateMethodCall({
86
+ ...createParams,
87
+ approvalProgram,
88
+ clearStateProgram,
89
+ ...sendParams
90
+ }) : this._transactionSender.appCreate({
91
+ ...createParams,
92
+ approvalProgram,
93
+ clearStateProgram,
94
+ ...sendParams
95
+ }));
96
+ const appMetadata = {
97
+ appId: result.appId,
98
+ appAddress: result.appAddress,
99
+ ...metadata,
100
+ createdMetadata: metadata,
101
+ createdRound: BigInt(result.confirmation.confirmedRound),
102
+ updatedRound: BigInt(result.confirmation.confirmedRound),
103
+ deleted: false
104
+ };
105
+ this.updateAppLookup(createParams.sender, appMetadata);
106
+ return {
107
+ operationPerformed: "create",
108
+ compiledApproval,
109
+ compiledClear,
110
+ ...result,
111
+ ...appMetadata
112
+ };
113
+ };
114
+ const updateApp = async (existingApp) => {
115
+ require_config.Config.getLogger(sendParams?.suppressLog).info(`Updating existing ${metadata.name} app for ${createParams.sender} to version ${metadata.version}.`);
116
+ const result = await ("method" in updateParams ? this._transactionSender.appUpdateMethodCall({
117
+ appId: existingApp.appId,
118
+ approvalProgram,
119
+ clearStateProgram,
120
+ ...updateParams,
121
+ ...sendParams
122
+ }) : this._transactionSender.appUpdate({
123
+ appId: existingApp.appId,
124
+ approvalProgram,
125
+ clearStateProgram,
126
+ ...updateParams,
127
+ ...sendParams
128
+ }));
129
+ const appMetadata = {
130
+ appId: existingApp.appId,
131
+ appAddress: existingApp.appAddress,
132
+ createdMetadata: existingApp.createdMetadata,
133
+ createdRound: existingApp.createdRound,
134
+ updatedRound: BigInt(result.confirmation.confirmedRound),
135
+ ...metadata,
136
+ deleted: false
137
+ };
138
+ this.updateAppLookup(createParams.sender, appMetadata);
139
+ return {
140
+ operationPerformed: "update",
141
+ compiledApproval,
142
+ compiledClear,
143
+ ...result,
144
+ ...appMetadata
145
+ };
146
+ };
147
+ const replaceApp = async (existingApp) => {
148
+ require_config.Config.getLogger(sendParams?.suppressLog).info(`Deploying a new ${metadata.name} app for ${createParams.sender}; deploying app with version ${metadata.version}.`);
149
+ require_config.Config.getLogger(sendParams?.suppressLog).warn(`Deleting existing ${metadata.name} app with id ${existingApp.appId} from ${deleteParams.sender} account.`);
150
+ const composer = this._transactionSender.newGroup();
151
+ if ("method" in createParams) composer.addAppCreateMethodCall({
152
+ ...createParams,
153
+ approvalProgram,
154
+ clearStateProgram
155
+ });
156
+ else composer.addAppCreate({
157
+ ...createParams,
158
+ approvalProgram,
159
+ clearStateProgram
160
+ });
161
+ const createIndex = await composer.count();
162
+ if ("method" in deleteParams) composer.addAppDeleteMethodCall({
163
+ appId: existingApp.appId,
164
+ ...deleteParams
165
+ });
166
+ else composer.addAppDelete({
167
+ appId: existingApp.appId,
168
+ ...deleteParams
169
+ });
170
+ const result = await composer.send({ ...sendParams });
171
+ const confirmation = result.confirmations.at(createIndex - 1);
172
+ const transaction = result.transactions.at(createIndex - 1);
173
+ const deleteTransaction = result.transactions.at(-1);
174
+ require_config.Config.getLogger(sendParams?.suppressLog).warn(`Sent transactions ${transaction.txID()} to create app with id ${confirmation.applicationIndex} and ${deleteTransaction.txID()} to delete app with id ${existingApp.appId} from ${createParams.sender} account.`);
175
+ const appMetadata = {
176
+ appId: BigInt(confirmation.applicationIndex),
177
+ appAddress: algosdk.default.getApplicationAddress(confirmation.applicationIndex),
178
+ ...metadata,
179
+ createdMetadata: metadata,
180
+ createdRound: BigInt(confirmation.confirmedRound),
181
+ updatedRound: BigInt(confirmation.confirmedRound),
182
+ deleted: false
183
+ };
184
+ this.updateAppLookup(createParams.sender, appMetadata);
185
+ return {
186
+ operationPerformed: "replace",
187
+ ...result,
188
+ compiledApproval,
189
+ compiledClear,
190
+ transaction,
191
+ confirmation,
192
+ return: "method" in createParams ? result.returns?.[0] : void 0,
193
+ deleteReturn: "method" in deleteParams ? result.returns?.at(-1) : void 0,
194
+ ...appMetadata,
195
+ deleteResult: {
196
+ transaction: deleteTransaction,
197
+ confirmation: result.confirmations.at(-1)
198
+ }
199
+ };
200
+ };
201
+ const existingApp = (existingDeployments ?? await this.getCreatorAppsByName(createParams.sender, ignoreCache)).apps[metadata.name];
202
+ if (!existingApp || existingApp.deleted) {
203
+ require_config.Config.getLogger(sendParams?.suppressLog).info(`App ${metadata.name} not found in apps created by ${createParams.sender}; deploying app with version ${metadata.version}.`);
204
+ return await createApp();
205
+ }
206
+ require_config.Config.getLogger(sendParams?.suppressLog).info(`Existing app ${metadata.name} found by creator ${createParams.sender}, with app id ${existingApp.appId} and version ${existingApp.version}.`);
207
+ const existingAppRecord = await this._appManager.getById(existingApp.appId);
208
+ const existingApproval = Buffer.from(existingAppRecord.approvalProgram).toString("base64");
209
+ const existingClear = Buffer.from(existingAppRecord.clearStateProgram).toString("base64");
210
+ const extraPages = existingAppRecord.extraProgramPages ?? 0;
211
+ const newApprovalBytes = Buffer.from(approvalProgram);
212
+ const newClearBytes = Buffer.from(clearStateProgram);
213
+ const newApproval = newApprovalBytes.toString("base64");
214
+ const newClear = newClearBytes.toString("base64");
215
+ const newExtraPages = require_util.calculateExtraProgramPages(newApprovalBytes, newClearBytes);
216
+ const isUpdate = newApproval !== existingApproval || newClear !== existingClear;
217
+ if (existingAppRecord.localInts < (createParams.schema?.localInts ?? 0) || existingAppRecord.globalInts < (createParams.schema?.globalInts ?? 0) || existingAppRecord.localByteSlices < (createParams.schema?.localByteSlices ?? 0) || existingAppRecord.globalByteSlices < (createParams.schema?.globalByteSlices ?? 0) || extraPages < newExtraPages) {
218
+ require_config.Config.getLogger(sendParams?.suppressLog).warn(`Detected a breaking app schema change in app ${existingApp.appId}:`, {
219
+ from: {
220
+ globalInts: existingAppRecord.globalInts,
221
+ globalByteSlices: existingAppRecord.globalByteSlices,
222
+ localInts: existingAppRecord.localInts,
223
+ localByteSlices: existingAppRecord.localByteSlices,
224
+ extraProgramPages: extraPages
225
+ },
226
+ to: {
227
+ ...createParams.schema,
228
+ extraProgramPages: newExtraPages
229
+ }
230
+ });
231
+ if (onSchemaBreak === void 0 || onSchemaBreak === "fail" || onSchemaBreak === 0) throw new Error("Schema break detected and onSchemaBreak=OnSchemaBreak.Fail, stopping deployment. If you want to try deleting and recreating the app then re-run with onSchemaBreak=OnSchemaBreak.ReplaceApp");
232
+ if (onSchemaBreak === "append" || onSchemaBreak === 2) {
233
+ require_config.Config.getLogger(sendParams?.suppressLog).info("onSchemaBreak=AppendApp, will attempt to create a new app");
234
+ return await createApp();
235
+ }
236
+ if (existingApp.deletable) require_config.Config.getLogger(sendParams?.suppressLog).info("App is deletable and onSchemaBreak=ReplaceApp, will attempt to create new app and delete old app");
237
+ else require_config.Config.getLogger(sendParams?.suppressLog).info("App is not deletable but onSchemaBreak=ReplaceApp, will attempt to delete app, delete will most likely fail");
238
+ return await replaceApp(existingApp);
239
+ }
240
+ if (isUpdate) {
241
+ require_config.Config.getLogger(sendParams?.suppressLog).info(`Detected a TEAL update in app ${existingApp.appId} for creator ${createParams.sender}`);
242
+ if (onUpdate === void 0 || onUpdate === "fail" || onUpdate === 0) throw new Error("Update detected and onUpdate=Fail, stopping deployment. Try a different onUpdate value to not fail.");
243
+ if (onUpdate === "append" || onUpdate === 3) {
244
+ require_config.Config.getLogger(sendParams?.suppressLog).info("onUpdate=AppendApp, will attempt to create a new app");
245
+ return await createApp();
246
+ }
247
+ if (onUpdate === "update" || onUpdate === 1) {
248
+ if (existingApp.updatable) require_config.Config.getLogger(sendParams?.suppressLog).info(`App is updatable and onUpdate=UpdateApp, updating app...`);
249
+ else require_config.Config.getLogger(sendParams?.suppressLog).warn(`App is not updatable but onUpdate=UpdateApp, will attempt to update app, update will most likely fail`);
250
+ return await updateApp(existingApp);
251
+ }
252
+ if (onUpdate === "replace" || onUpdate === 2) {
253
+ if (existingApp.deletable) require_config.Config.getLogger(sendParams?.suppressLog).warn("App is deletable and onUpdate=ReplaceApp, creating new app and deleting old app...");
254
+ else require_config.Config.getLogger(sendParams?.suppressLog).warn("App is not deletable and onUpdate=ReplaceApp, will attempt to create new app and delete old app, delete will most likely fail");
255
+ return await replaceApp(existingApp);
256
+ }
257
+ }
258
+ require_config.Config.getLogger(sendParams?.suppressLog).debug("No detected changes in app, nothing to do.");
259
+ return {
260
+ ...existingApp,
261
+ operationPerformed: "nothing"
262
+ };
263
+ }
264
+ updateAppLookup(sender, appMetadata) {
265
+ const s = typeof sender === "string" ? sender : sender.toString();
266
+ const lookup = this._appLookups.get(s);
267
+ if (!lookup) this._appLookups.set(s, {
268
+ creator: algosdk.Address.fromString(s),
269
+ apps: { [appMetadata.name]: appMetadata }
270
+ });
271
+ else lookup.apps[appMetadata.name] = appMetadata;
272
+ }
273
+ /**
274
+ * Returns a lookup of name => app metadata (id, address, ...metadata) for all apps created by the given account that have
275
+ * an [ARC-2](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0002.md) `AppDeployNote` as the transaction
276
+ * note of the app creation transaction.
277
+ *
278
+ * This function caches the result for the given creator account so that subsequent calls will not require an indexer lookup.
279
+ *
280
+ * If the `AppManager` instance wasn't created with an indexer client, this function will throw an error.
281
+ *
282
+ * @param creatorAddress The address of the account that is the creator of the apps you want to search for
283
+ * @param ignoreCache Whether or not to ignore the cache and force a lookup, default: use the cache
284
+ * @returns A name-based lookup of the app metadata
285
+ * @example
286
+ * ```ts
287
+ * const result = await deployer.getCreatorAppsByName(creator)
288
+ */
289
+ async getCreatorAppsByName(creatorAddress, ignoreCache) {
290
+ const appLookup = {};
291
+ const address = typeof creatorAddress === "string" ? creatorAddress : creatorAddress.toString();
292
+ if (!ignoreCache && this._appLookups.has(address)) return this._appLookups.get(address);
293
+ if (!this._indexer) throw new Error(`Didn't receive an indexer client when this AppManager was created, but received a call to getCreatorApps`);
294
+ const createdApps = (await require_indexer_lookup.lookupAccountCreatedApplicationByAddress(this._indexer, creatorAddress)).map((a) => {
295
+ return {
296
+ id: a.id,
297
+ createdAtRound: a.createdAtRound,
298
+ deleted: a.deleted
299
+ };
300
+ }).sort((a, b) => Number(a.createdAtRound - b.createdAtRound));
301
+ (await Promise.all(createdApps.map(async (createdApp) => {
302
+ const appTransactions = await require_indexer_lookup.searchTransactions(this._indexer, (s) => s.minRound(createdApp.createdAtRound).txType(algosdk.default.TransactionType.appl).applicationID(Number(createdApp.id)).address(creatorAddress).addressRole("sender").notePrefix(Buffer.from(require_app.APP_DEPLOY_NOTE_DAPP).toString("base64")));
303
+ const appCreationTransaction = appTransactions.transactions.filter((t) => t.applicationTransaction?.applicationId === 0n && t.sender.toString() === creatorAddress.toString())[0];
304
+ const latestAppUpdateTransaction = appTransactions.transactions.filter((t) => t.sender.toString() === creatorAddress.toString()).sort((a, b) => a.confirmedRound === b.confirmedRound ? (b.intraRoundOffset - a.intraRoundOffset) / 10 : Number(b.confirmedRound - a.confirmedRound))[0];
305
+ if (!appCreationTransaction?.note) return null;
306
+ return {
307
+ createdApp,
308
+ appCreationTransaction,
309
+ latestAppUpdateTransaction
310
+ };
311
+ }))).filter((a) => a !== null).forEach((a) => {
312
+ const { createdApp, appCreationTransaction, latestAppUpdateTransaction } = a;
313
+ const parseNote = (note) => {
314
+ if (!note) return;
315
+ if (!note.startsWith(`ALGOKIT_DEPLOYER:j{`)) return;
316
+ return JSON.parse(note.substring(require_app.APP_DEPLOY_NOTE_DAPP.length + 2));
317
+ };
318
+ try {
319
+ const creationNote = parseNote(appCreationTransaction.note ? Buffer.from(appCreationTransaction.note).toString("utf-8") : void 0);
320
+ const updateNote = parseNote(latestAppUpdateTransaction.note ? Buffer.from(latestAppUpdateTransaction.note).toString("utf-8") : void 0);
321
+ if (creationNote?.name) appLookup[creationNote.name] = {
322
+ appId: createdApp.id,
323
+ appAddress: algosdk.default.getApplicationAddress(createdApp.id),
324
+ createdMetadata: creationNote,
325
+ createdRound: appCreationTransaction.confirmedRound ?? 0n,
326
+ ...updateNote ?? creationNote,
327
+ updatedRound: latestAppUpdateTransaction?.confirmedRound ?? 0n,
328
+ deleted: createdApp.deleted ?? false
329
+ };
330
+ } catch (e) {
331
+ require_config.Config.logger.warn(`Received error trying to retrieve app with ${createdApp.id} for creator ${creatorAddress}; failing silently`, e);
332
+ return;
333
+ }
334
+ });
335
+ const lookup = {
336
+ creator: typeof creatorAddress === "string" ? algosdk.Address.fromString(creatorAddress) : creatorAddress,
337
+ apps: appLookup
338
+ };
339
+ this._appLookups.set(creatorAddress.toString(), lookup);
340
+ return lookup;
341
+ }
342
+ };
343
+ //#endregion
385
344
  exports.AppDeployer = AppDeployer;
386
- //# sourceMappingURL=app-deployer.js.map
345
+
346
+ //# sourceMappingURL=app-deployer.js.map