@algorandfoundation/algokit-utils 7.0.0-beta.1 → 7.0.0-beta.11

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 (360) hide show
  1. package/README.md +3 -25
  2. package/account/account.d.ts +8 -9
  3. package/account/account.js +7 -7
  4. package/account/account.js.map +1 -1
  5. package/account/account.mjs +7 -7
  6. package/account/account.mjs.map +1 -1
  7. package/account/get-account-config-from-environment.d.ts +0 -1
  8. package/account/get-account-config-from-environment.js.map +1 -1
  9. package/account/get-account-config-from-environment.mjs.map +1 -1
  10. package/account/get-account.d.ts +2 -3
  11. package/account/get-account.js +1 -1
  12. package/account/get-account.js.map +1 -1
  13. package/account/get-account.mjs +1 -1
  14. package/account/get-account.mjs.map +1 -1
  15. package/account/get-dispenser-account.d.ts +1 -2
  16. package/account/get-dispenser-account.js +1 -1
  17. package/account/get-dispenser-account.js.map +1 -1
  18. package/account/get-dispenser-account.mjs +1 -1
  19. package/account/get-dispenser-account.mjs.map +1 -1
  20. package/account/index.d.ts +0 -1
  21. package/account/mnemonic-account.d.ts +1 -2
  22. package/account/mnemonic-account.js +1 -1
  23. package/account/mnemonic-account.js.map +1 -1
  24. package/account/mnemonic-account.mjs +1 -1
  25. package/account/mnemonic-account.mjs.map +1 -1
  26. package/amount.d.ts +14 -5
  27. package/amount.js +6 -0
  28. package/amount.js.map +1 -1
  29. package/amount.mjs +6 -0
  30. package/amount.mjs.map +1 -1
  31. package/app-client.d.ts +15 -1
  32. package/app-client.js +15 -0
  33. package/app-client.js.map +1 -1
  34. package/app-client.mjs +15 -0
  35. package/app-client.mjs.map +1 -1
  36. package/app-deploy.d.ts +18 -2
  37. package/app-deploy.js +140 -333
  38. package/app-deploy.js.map +1 -1
  39. package/app-deploy.mjs +143 -336
  40. package/app-deploy.mjs.map +1 -1
  41. package/app.d.ts +39 -3
  42. package/app.js +116 -369
  43. package/app.js.map +1 -1
  44. package/app.mjs +117 -370
  45. package/app.mjs.map +1 -1
  46. package/asset.d.ts +5 -6
  47. package/asset.js +5 -8
  48. package/asset.js.map +1 -1
  49. package/asset.mjs +5 -8
  50. package/asset.mjs.map +1 -1
  51. package/config.d.ts +0 -1
  52. package/config.js.map +1 -1
  53. package/config.mjs.map +1 -1
  54. package/debugging/debugging.d.ts +3 -5
  55. package/debugging/debugging.js +4 -128
  56. package/debugging/debugging.js.map +1 -1
  57. package/debugging/debugging.mjs +4 -109
  58. package/debugging/debugging.mjs.map +1 -1
  59. package/debugging/index.d.ts +0 -2
  60. package/dispenser-client.d.ts +0 -1
  61. package/dispenser-client.js.map +1 -1
  62. package/dispenser-client.mjs.map +1 -1
  63. package/index.d.ts +4 -4
  64. package/index.js +31 -26
  65. package/index.js.map +1 -1
  66. package/index.mjs +4 -4
  67. package/indexer-lookup.d.ts +0 -1
  68. package/indexer-lookup.js.map +1 -1
  69. package/indexer-lookup.mjs.map +1 -1
  70. package/localnet/get-kmd-wallet-account.d.ts +1 -2
  71. package/localnet/get-kmd-wallet-account.js +1 -1
  72. package/localnet/get-kmd-wallet-account.js.map +1 -1
  73. package/localnet/get-kmd-wallet-account.mjs +1 -1
  74. package/localnet/get-kmd-wallet-account.mjs.map +1 -1
  75. package/localnet/get-localnet-dispenser-account.d.ts +1 -2
  76. package/localnet/get-localnet-dispenser-account.js +1 -1
  77. package/localnet/get-localnet-dispenser-account.js.map +1 -1
  78. package/localnet/get-localnet-dispenser-account.mjs +1 -1
  79. package/localnet/get-localnet-dispenser-account.mjs.map +1 -1
  80. package/localnet/get-or-create-kmd-wallet-account.d.ts +1 -2
  81. package/localnet/get-or-create-kmd-wallet-account.js +1 -1
  82. package/localnet/get-or-create-kmd-wallet-account.js.map +1 -1
  83. package/localnet/get-or-create-kmd-wallet-account.mjs +1 -1
  84. package/localnet/get-or-create-kmd-wallet-account.mjs.map +1 -1
  85. package/localnet/index.d.ts +0 -1
  86. package/localnet/is-localnet.d.ts +1 -2
  87. package/localnet/is-localnet.js +1 -1
  88. package/localnet/is-localnet.js.map +1 -1
  89. package/localnet/is-localnet.mjs +1 -1
  90. package/localnet/is-localnet.mjs.map +1 -1
  91. package/network-client.d.ts +2 -3
  92. package/network-client.js +2 -2
  93. package/network-client.js.map +1 -1
  94. package/network-client.mjs +2 -2
  95. package/network-client.mjs.map +1 -1
  96. package/package.json +1 -1
  97. package/testing/_asset.d.ts +0 -1
  98. package/testing/account.d.ts +0 -1
  99. package/testing/account.js.map +1 -1
  100. package/testing/account.mjs.map +1 -1
  101. package/testing/fixtures/algokit-log-capture-fixture.d.ts +0 -1
  102. package/testing/fixtures/algokit-log-capture-fixture.js.map +1 -1
  103. package/testing/fixtures/algokit-log-capture-fixture.mjs.map +1 -1
  104. package/testing/fixtures/algorand-fixture.d.ts +0 -1
  105. package/testing/fixtures/algorand-fixture.js +12 -12
  106. package/testing/fixtures/algorand-fixture.js.map +1 -1
  107. package/testing/fixtures/algorand-fixture.mjs +12 -12
  108. package/testing/fixtures/algorand-fixture.mjs.map +1 -1
  109. package/testing/fixtures/index.d.ts +0 -1
  110. package/testing/index.d.ts +0 -1
  111. package/testing/indexer.d.ts +0 -1
  112. package/testing/indexer.js.map +1 -1
  113. package/testing/indexer.mjs.map +1 -1
  114. package/testing/test-logger.d.ts +0 -1
  115. package/testing/test-logger.js +1 -3
  116. package/testing/test-logger.js.map +1 -1
  117. package/testing/test-logger.mjs +1 -3
  118. package/testing/test-logger.mjs.map +1 -1
  119. package/testing/transaction-logger.d.ts +0 -1
  120. package/testing/transaction-logger.js.map +1 -1
  121. package/testing/transaction-logger.mjs.map +1 -1
  122. package/transaction/index.d.ts +0 -1
  123. package/transaction/legacy-bridge.d.ts +31 -6
  124. package/transaction/legacy-bridge.js +100 -6
  125. package/transaction/legacy-bridge.js.map +1 -1
  126. package/transaction/legacy-bridge.mjs +99 -8
  127. package/transaction/legacy-bridge.mjs.map +1 -1
  128. package/transaction/perform-atomic-transaction-composer-simulate.d.ts +0 -1
  129. package/transaction/perform-atomic-transaction-composer-simulate.js.map +1 -1
  130. package/transaction/perform-atomic-transaction-composer-simulate.mjs.map +1 -1
  131. package/transaction/transaction.d.ts +41 -6
  132. package/transaction/transaction.js +108 -45
  133. package/transaction/transaction.js.map +1 -1
  134. package/transaction/transaction.mjs +108 -46
  135. package/transaction/transaction.mjs.map +1 -1
  136. package/transfer/index.d.ts +0 -1
  137. package/transfer/transfer-algos.d.ts +1 -2
  138. package/transfer/transfer-algos.js +1 -1
  139. package/transfer/transfer-algos.js.map +1 -1
  140. package/transfer/transfer-algos.mjs +1 -1
  141. package/transfer/transfer-algos.mjs.map +1 -1
  142. package/transfer/transfer.d.ts +1 -2
  143. package/transfer/transfer.js +3 -3
  144. package/transfer/transfer.js.map +1 -1
  145. package/transfer/transfer.mjs +3 -3
  146. package/transfer/transfer.mjs.map +1 -1
  147. package/types/account-manager.d.ts +14 -6
  148. package/types/account-manager.js +18 -4
  149. package/types/account-manager.js.map +1 -1
  150. package/types/account-manager.mjs +18 -4
  151. package/types/account-manager.mjs.map +1 -1
  152. package/types/account.d.ts +0 -1
  153. package/types/account.js.map +1 -1
  154. package/types/account.mjs.map +1 -1
  155. package/types/algo-http-client-with-retry.d.ts +0 -1
  156. package/types/algo-http-client-with-retry.js.map +1 -1
  157. package/types/algo-http-client-with-retry.mjs.map +1 -1
  158. package/types/algorand-client-interface.d.ts +28 -0
  159. package/types/algorand-client-interface.js +3 -0
  160. package/types/algorand-client-interface.js.map +1 -0
  161. package/types/algorand-client-interface.mjs +2 -0
  162. package/types/algorand-client-interface.mjs.map +1 -0
  163. package/types/algorand-client-transaction-creator.d.ts +450 -21
  164. package/types/algorand-client-transaction-creator.js +406 -22
  165. package/types/algorand-client-transaction-creator.js.map +1 -1
  166. package/types/algorand-client-transaction-creator.mjs +406 -22
  167. package/types/algorand-client-transaction-creator.mjs.map +1 -1
  168. package/types/algorand-client-transaction-sender.d.ts +758 -33
  169. package/types/algorand-client-transaction-sender.js +444 -14
  170. package/types/algorand-client-transaction-sender.js.map +1 -1
  171. package/types/algorand-client-transaction-sender.mjs +444 -14
  172. package/types/algorand-client-transaction-sender.mjs.map +1 -1
  173. package/types/algorand-client.d.ts +18 -10
  174. package/types/algorand-client.js +23 -10
  175. package/types/algorand-client.js.map +1 -1
  176. package/types/algorand-client.mjs +23 -10
  177. package/types/algorand-client.mjs.map +1 -1
  178. package/types/amount.d.ts +10 -11
  179. package/types/amount.js +7 -7
  180. package/types/amount.js.map +1 -1
  181. package/types/amount.mjs +7 -7
  182. package/types/amount.mjs.map +1 -1
  183. package/types/app-arc56.d.ts +348 -0
  184. package/types/app-arc56.js +184 -0
  185. package/types/app-arc56.js.map +1 -0
  186. package/types/app-arc56.mjs +175 -0
  187. package/types/app-arc56.mjs.map +1 -0
  188. package/types/app-client.d.ts +1496 -9
  189. package/types/app-client.js +903 -21
  190. package/types/app-client.js.map +1 -1
  191. package/types/app-client.mjs +904 -23
  192. package/types/app-client.mjs.map +1 -1
  193. package/types/app-deployer.d.ts +126 -0
  194. package/types/app-deployer.js +354 -0
  195. package/types/app-deployer.js.map +1 -0
  196. package/types/app-deployer.mjs +352 -0
  197. package/types/app-deployer.mjs.map +1 -0
  198. package/types/app-factory.d.ts +846 -0
  199. package/types/app-factory.js +411 -0
  200. package/types/app-factory.js.map +1 -0
  201. package/types/app-factory.mjs +409 -0
  202. package/types/app-factory.mjs.map +1 -0
  203. package/types/app-manager.d.ts +244 -0
  204. package/types/app-manager.js +334 -0
  205. package/types/app-manager.js.map +1 -0
  206. package/types/app-manager.mjs +332 -0
  207. package/types/app-manager.mjs.map +1 -0
  208. package/types/app-spec.d.ts +2 -1
  209. package/types/app-spec.js +121 -0
  210. package/types/app-spec.js.map +1 -1
  211. package/types/app-spec.mjs +120 -0
  212. package/types/app-spec.mjs.map +1 -1
  213. package/types/app.d.ts +53 -13
  214. package/types/app.js +1 -1
  215. package/types/app.js.map +1 -1
  216. package/types/app.mjs +1 -1
  217. package/types/app.mjs.map +1 -1
  218. package/types/asset-manager.d.ts +4 -4
  219. package/types/asset-manager.js +3 -4
  220. package/types/asset-manager.js.map +1 -1
  221. package/types/asset-manager.mjs +3 -4
  222. package/types/asset-manager.mjs.map +1 -1
  223. package/types/asset.d.ts +0 -1
  224. package/types/async-event-emitter.d.ts +23 -0
  225. package/types/async-event-emitter.js +55 -0
  226. package/types/async-event-emitter.js.map +1 -0
  227. package/types/async-event-emitter.mjs +53 -0
  228. package/types/async-event-emitter.mjs.map +1 -0
  229. package/types/client-manager.d.ts +133 -51
  230. package/types/client-manager.js +147 -23
  231. package/types/client-manager.js.map +1 -1
  232. package/types/client-manager.mjs +148 -24
  233. package/types/client-manager.mjs.map +1 -1
  234. package/types/composer.d.ts +232 -49
  235. package/types/composer.js +320 -65
  236. package/types/composer.js.map +1 -1
  237. package/types/composer.mjs +321 -66
  238. package/types/composer.mjs.map +1 -1
  239. package/types/config.d.ts +3 -6
  240. package/types/config.js +5 -44
  241. package/types/config.js.map +1 -1
  242. package/types/config.mjs +5 -27
  243. package/types/config.mjs.map +1 -1
  244. package/types/debugging.d.ts +29 -101
  245. package/types/debugging.js +16 -109
  246. package/types/debugging.js.map +1 -1
  247. package/types/debugging.mjs +12 -107
  248. package/types/debugging.mjs.map +1 -1
  249. package/types/dispenser-client.d.ts +1 -2
  250. package/types/dispenser-client.js +6 -5
  251. package/types/dispenser-client.js.map +1 -1
  252. package/types/dispenser-client.mjs +6 -5
  253. package/types/dispenser-client.mjs.map +1 -1
  254. package/types/expand.d.ts +7 -0
  255. package/types/expand.js +3 -0
  256. package/types/expand.js.map +1 -0
  257. package/types/expand.mjs +2 -0
  258. package/types/expand.mjs.map +1 -0
  259. package/types/indexer.d.ts +0 -1
  260. package/types/indexer.js.map +1 -1
  261. package/types/indexer.mjs.map +1 -1
  262. package/types/kmd-account-manager.d.ts +0 -1
  263. package/types/kmd-account-manager.js +2 -2
  264. package/types/kmd-account-manager.js.map +1 -1
  265. package/types/kmd-account-manager.mjs +2 -2
  266. package/types/kmd-account-manager.mjs.map +1 -1
  267. package/types/logging.d.ts +0 -1
  268. package/types/logging.js.map +1 -1
  269. package/types/logging.mjs.map +1 -1
  270. package/types/logic-error.d.ts +0 -1
  271. package/types/logic-error.js.map +1 -1
  272. package/types/logic-error.mjs.map +1 -1
  273. package/types/network-client.d.ts +13 -1
  274. package/types/network-client.js.map +1 -1
  275. package/types/network-client.mjs.map +1 -1
  276. package/types/testing.d.ts +3 -4
  277. package/types/transaction.d.ts +17 -4
  278. package/types/transfer.d.ts +0 -1
  279. package/types/urlTokenBaseHTTPClient.d.ts +0 -1
  280. package/types/urlTokenBaseHTTPClient.js +1 -1
  281. package/types/urlTokenBaseHTTPClient.js.map +1 -1
  282. package/types/urlTokenBaseHTTPClient.mjs +1 -1
  283. package/types/urlTokenBaseHTTPClient.mjs.map +1 -1
  284. package/util.d.ts +2 -2
  285. package/util.js +11 -10
  286. package/util.js.map +1 -1
  287. package/util.mjs +11 -10
  288. package/util.mjs.map +1 -1
  289. package/account/account.d.ts.map +0 -1
  290. package/account/get-account-config-from-environment.d.ts.map +0 -1
  291. package/account/get-account.d.ts.map +0 -1
  292. package/account/get-dispenser-account.d.ts.map +0 -1
  293. package/account/index.d.ts.map +0 -1
  294. package/account/mnemonic-account.d.ts.map +0 -1
  295. package/amount.d.ts.map +0 -1
  296. package/app-client.d.ts.map +0 -1
  297. package/app-deploy.d.ts.map +0 -1
  298. package/app.d.ts.map +0 -1
  299. package/asset.d.ts.map +0 -1
  300. package/config.d.ts.map +0 -1
  301. package/debugging/debugging.d.ts.map +0 -1
  302. package/debugging/index.d.ts.map +0 -1
  303. package/debugging/simulate-and-persist-response.d.ts +0 -20
  304. package/debugging/simulate-and-persist-response.d.ts.map +0 -1
  305. package/debugging/simulate-and-persist-response.js +0 -108
  306. package/debugging/simulate-and-persist-response.js.map +0 -1
  307. package/debugging/simulate-and-persist-response.mjs +0 -89
  308. package/debugging/simulate-and-persist-response.mjs.map +0 -1
  309. package/dispenser-client.d.ts.map +0 -1
  310. package/index.d.ts.map +0 -1
  311. package/indexer-lookup.d.ts.map +0 -1
  312. package/localnet/get-kmd-wallet-account.d.ts.map +0 -1
  313. package/localnet/get-localnet-dispenser-account.d.ts.map +0 -1
  314. package/localnet/get-or-create-kmd-wallet-account.d.ts.map +0 -1
  315. package/localnet/index.d.ts.map +0 -1
  316. package/localnet/is-localnet.d.ts.map +0 -1
  317. package/network-client.d.ts.map +0 -1
  318. package/testing/_asset.d.ts.map +0 -1
  319. package/testing/account.d.ts.map +0 -1
  320. package/testing/fixtures/algokit-log-capture-fixture.d.ts.map +0 -1
  321. package/testing/fixtures/algorand-fixture.d.ts.map +0 -1
  322. package/testing/fixtures/index.d.ts.map +0 -1
  323. package/testing/index.d.ts.map +0 -1
  324. package/testing/indexer.d.ts.map +0 -1
  325. package/testing/test-logger.d.ts.map +0 -1
  326. package/testing/transaction-logger.d.ts.map +0 -1
  327. package/transaction/index.d.ts.map +0 -1
  328. package/transaction/legacy-bridge.d.ts.map +0 -1
  329. package/transaction/perform-atomic-transaction-composer-simulate.d.ts.map +0 -1
  330. package/transaction/transaction.d.ts.map +0 -1
  331. package/transfer/index.d.ts.map +0 -1
  332. package/transfer/transfer-algos.d.ts.map +0 -1
  333. package/transfer/transfer.d.ts.map +0 -1
  334. package/types/account-manager.d.ts.map +0 -1
  335. package/types/account.d.ts.map +0 -1
  336. package/types/algo-http-client-with-retry.d.ts.map +0 -1
  337. package/types/algorand-client-transaction-creator.d.ts.map +0 -1
  338. package/types/algorand-client-transaction-sender.d.ts.map +0 -1
  339. package/types/algorand-client.d.ts.map +0 -1
  340. package/types/amount.d.ts.map +0 -1
  341. package/types/app-client.d.ts.map +0 -1
  342. package/types/app-spec.d.ts.map +0 -1
  343. package/types/app.d.ts.map +0 -1
  344. package/types/asset-manager.d.ts.map +0 -1
  345. package/types/asset.d.ts.map +0 -1
  346. package/types/client-manager.d.ts.map +0 -1
  347. package/types/composer.d.ts.map +0 -1
  348. package/types/config.d.ts.map +0 -1
  349. package/types/debugging.d.ts.map +0 -1
  350. package/types/dispenser-client.d.ts.map +0 -1
  351. package/types/indexer.d.ts.map +0 -1
  352. package/types/kmd-account-manager.d.ts.map +0 -1
  353. package/types/logging.d.ts.map +0 -1
  354. package/types/logic-error.d.ts.map +0 -1
  355. package/types/network-client.d.ts.map +0 -1
  356. package/types/testing.d.ts.map +0 -1
  357. package/types/transaction.d.ts.map +0 -1
  358. package/types/transfer.d.ts.map +0 -1
  359. package/types/urlTokenBaseHTTPClient.d.ts.map +0 -1
  360. package/util.d.ts.map +0 -1
@@ -5,17 +5,20 @@ var buffer = require('buffer');
5
5
  var app = require('../app.js');
6
6
  var appDeploy = require('../app-deploy.js');
7
7
  var config = require('../config.js');
8
- var debugging = require('../debugging/debugging.js');
9
8
  var legacyBridge = require('../transaction/legacy-bridge.js');
10
9
  var transaction = require('../transaction/transaction.js');
10
+ var util = require('../util.js');
11
11
  var types_app = require('./app.js');
12
- var types_debugging = require('./debugging.js');
12
+ var types_appArc56 = require('./app-arc56.js');
13
+ var types_appSpec = require('./app-spec.js');
14
+ var types_asyncEventEmitter = require('./async-event-emitter.js');
13
15
  var types_logicError = require('./logic-error.js');
14
16
 
15
17
  var ABIMethod = algosdk.ABIMethod;
16
18
  var AtomicTransactionComposer = algosdk.AtomicTransactionComposer;
17
19
  var getApplicationAddress = algosdk.getApplicationAddress;
18
20
  var Indexer = algosdk.Indexer;
21
+ var OnApplicationComplete = algosdk.OnApplicationComplete;
19
22
  var SourceMap = algosdk.SourceMap;
20
23
  /**
21
24
  * Determines deploy time control (UPDATABLE, DELETABLE) value by inspecting application specification
@@ -39,13 +42,865 @@ function getDeployTimeControl(approval, appSpec, templateVariableName, callConfi
39
42
  return !!abiCallConfig && abiCallConfig !== 'NEVER';
40
43
  });
41
44
  }
42
- /** Application client - a class that wraps an ARC-0032 app spec and provides high productivity methods to deploy and call the app */
45
+ /** ARC-56/ARC-32 application client that allows you to manage calls and
46
+ * state for a specific deployed instance of an app (with a known app ID). */
47
+ class AppClient {
48
+ constructor(params) {
49
+ this._appId = params.appId;
50
+ this._appAddress = algosdk.getApplicationAddress(this._appId);
51
+ this._appSpec = AppClient.normaliseAppSpec(params.appSpec);
52
+ this._appName = params.appName ?? this._appSpec.name;
53
+ this._algorand = params.algorand;
54
+ this._defaultSender = params.defaultSender;
55
+ this._defaultSigner = params.defaultSigner;
56
+ this._approvalSourceMap = params.approvalSourceMap;
57
+ this._clearSourceMap = params.clearSourceMap;
58
+ this._localStateMethods = (address) => this.getStateMethods(() => this.getLocalState(address), () => this._appSpec.state.keys.local, () => this._appSpec.state.maps.local);
59
+ this._globalStateMethods = this.getStateMethods(() => this.getGlobalState(), () => this._appSpec.state.keys.global, () => this._appSpec.state.maps.global);
60
+ this._boxStateMethods = this.getBoxMethods();
61
+ this._paramsMethods = {
62
+ ...this.getMethodCallParamsMethods(),
63
+ /** Get parameters to define bare (raw) transactions to the current app */
64
+ bare: this.getBareParamsMethods(),
65
+ };
66
+ this._createTransactionsMethods = {
67
+ ...this.getMethodCallCreateTransactionMethods(),
68
+ /** Get transactions for bare (raw) calls to the current app */
69
+ bare: this.getBareCreateTransactionMethods(),
70
+ };
71
+ this._sendMethods = {
72
+ ...this.getMethodCallSendMethods(),
73
+ /** Send bare (raw) transactions to the current app */
74
+ bare: this.getBareSendMethods(),
75
+ };
76
+ }
77
+ /** Start a new `AlgoKitComposer` transaction group */
78
+ newGroup() {
79
+ return this._algorand.newGroup();
80
+ }
81
+ /**
82
+ * Returns a new `AppClient` client, resolving the app by creator address and name
83
+ * using AlgoKit app deployment semantics (i.e. looking for the app creation transaction note).
84
+ * @param params The parameters to create the app client
85
+ */
86
+ static async fromCreatorAndName(params) {
87
+ const appSpec = AppClient.normaliseAppSpec(params.appSpec);
88
+ const appLookup = params.appLookupCache ?? (await params.algorand.appDeployer.getCreatorAppsByName(params.creatorAddress, params.ignoreCache));
89
+ const appMetadata = appLookup.apps[params.appName ?? appSpec.name];
90
+ if (!appMetadata) {
91
+ throw new Error(`App not found for creator ${params.creatorAddress} and name ${params.appName ?? appSpec.name}`);
92
+ }
93
+ return new AppClient({
94
+ ...params,
95
+ algorand: params.algorand,
96
+ appId: appMetadata.appId,
97
+ });
98
+ }
99
+ /**
100
+ * Returns an `AppClient` instance for the current network based on
101
+ * pre-determined network-specific app IDs specified in the ARC-56 app spec.
102
+ *
103
+ * If no IDs are in the app spec or the network isn't recognised, an error is thrown.
104
+ * @param params The parameters to create the app client
105
+ */
106
+ static async fromNetwork(params) {
107
+ const network = await params.algorand.client.network();
108
+ const appSpec = AppClient.normaliseAppSpec(params.appSpec);
109
+ const networkNames = [network.genesisHash];
110
+ if (network.isLocalNet)
111
+ networkNames.push('localnet');
112
+ if (network.isTestNet)
113
+ networkNames.push('testnet');
114
+ if (network.isMainNet)
115
+ networkNames.push('mainnet');
116
+ const availableAppSpecNetworks = Object.keys(appSpec.networks ?? {});
117
+ const networkIndex = availableAppSpecNetworks.findIndex((n) => networkNames.includes(n));
118
+ if (networkIndex === -1) {
119
+ throw new Error(`No app ID found for network ${JSON.stringify(networkNames)} in the app spec`);
120
+ }
121
+ const appId = BigInt(appSpec.networks[networkIndex].appID);
122
+ return new AppClient({ ...params, appId, appSpec });
123
+ }
124
+ /**
125
+ * Takes a string or parsed JSON object that could be ARC-32 or ARC-56 format and
126
+ * normalises it into a parsed ARC-56 contract object.
127
+ * @param spec The spec to normalise
128
+ * @returns The normalised ARC-56 contract object
129
+ */
130
+ static normaliseAppSpec(spec) {
131
+ const parsedSpec = typeof spec === 'string' ? JSON.parse(spec) : spec;
132
+ const appSpec = 'hints' in parsedSpec ? types_appSpec.arc32ToArc56(parsedSpec) : parsedSpec;
133
+ return appSpec;
134
+ }
135
+ /** The ID of the app instance this client is linked to. */
136
+ get appId() {
137
+ return this._appId;
138
+ }
139
+ /** The app address of the app instance this client is linked to. */
140
+ get appAddress() {
141
+ return this._appAddress;
142
+ }
143
+ /** The name of the app (from the ARC-32 / ARC-56 app spec). */
144
+ get appName() {
145
+ return this._appName;
146
+ }
147
+ /** The ARC-56 app spec being used */
148
+ get appSpec() {
149
+ return this._appSpec;
150
+ }
151
+ /** A reference to the underlying `AlgorandClient` this app client is using. */
152
+ get algorand() {
153
+ return this._algorand;
154
+ }
155
+ /** Get parameters to create transactions for the current app.
156
+ *
157
+ * A good mental model for this is that these parameters represent a deferred transaction creation.
158
+ * @example Create a transaction in the future using Algorand Client
159
+ * ```typescript
160
+ * const myMethodCall = appClient.params.call({method: 'my_method', args: [123, 'hello']})
161
+ * // ...
162
+ * await algorand.send.AppMethodCall(myMethodCall)
163
+ * ```
164
+ * @example Define a nested transaction as an ABI argument
165
+ * ```typescript
166
+ * const myMethodCall = appClient.params.call({method: 'my_method', args: [123, 'hello']})
167
+ * await appClient.send.call({method: 'my_method2', args: [myMethodCall]})
168
+ * ```
169
+ */
170
+ get params() {
171
+ return this._paramsMethods;
172
+ }
173
+ /** Create transactions for the current app */
174
+ get createTransaction() {
175
+ return this._createTransactionsMethods;
176
+ }
177
+ /** Send transactions to the current app */
178
+ get send() {
179
+ return this._sendMethods;
180
+ }
181
+ /** Get state (local, global, box) from the current app */
182
+ get state() {
183
+ return {
184
+ /**
185
+ * Methods to access local state for the current app
186
+ * @param address The address of the account to get the local state for
187
+ */
188
+ local: this._localStateMethods,
189
+ /**
190
+ * Methods to access global state for the current app
191
+ */
192
+ global: this._globalStateMethods,
193
+ /**
194
+ * Methods to access box storage for the current app
195
+ */
196
+ box: this._boxStateMethods,
197
+ };
198
+ }
199
+ /**
200
+ * Funds Algo into the app account for this app.
201
+ *
202
+ * An alias for `appClient.send.fundAppAccount(params)`.
203
+ * @param params The parameters for the funding transaction
204
+ * @returns The result of the funding
205
+ */
206
+ async fundAppAccount(params) {
207
+ return this.send.fundAppAccount(params);
208
+ }
209
+ /**
210
+ * Returns raw global state for the current app.
211
+ * @returns The global state
212
+ */
213
+ async getGlobalState() {
214
+ return await this._algorand.app.getGlobalState(this.appId);
215
+ }
216
+ /**
217
+ * Returns raw local state for the given account address.
218
+ * @param address The address of the account to get the local state for
219
+ * @returns The local state
220
+ */
221
+ async getLocalState(address) {
222
+ return await this._algorand.app.getLocalState(this.appId, address);
223
+ }
224
+ /**
225
+ * Returns the names of all current boxes for the current app.
226
+ * @returns The names of the boxes
227
+ */
228
+ async getBoxNames() {
229
+ return await this._algorand.app.getBoxNames(this.appId);
230
+ }
231
+ /**
232
+ * Returns the value of the given box for the current app.
233
+ * @param name The identifier of the box to return
234
+ * @returns The current box value as a byte array
235
+ */
236
+ async getBoxValue(name) {
237
+ return await this._algorand.app.getBoxValue(this.appId, name);
238
+ }
239
+ /**
240
+ * Returns the value of the given box for the current app.
241
+ * @param name The identifier of the box to return
242
+ * @param type
243
+ * @returns The current box value as a byte array
244
+ */
245
+ async getBoxValueFromABIType(name, type) {
246
+ return await this._algorand.app.getBoxValueFromABIType({
247
+ appId: this.appId,
248
+ boxName: name,
249
+ type,
250
+ });
251
+ }
252
+ /**
253
+ * Returns the values of all current boxes for the current app.
254
+ * Note: This will issue multiple HTTP requests (one per box) and it's not an atomic operation so values may be out of sync.
255
+ * @param filter Optional filter to filter which boxes' values are returned
256
+ * @returns The (name, value) pair of the boxes with values as raw byte arrays
257
+ */
258
+ async getBoxValues(filter) {
259
+ const names = (await this.getBoxNames()).filter(filter ?? ((_) => true));
260
+ const values = await this._algorand.app.getBoxValues(this.appId, names.map((name) => name.nameRaw));
261
+ return names.map((name, i) => ({ name, value: values[i] }));
262
+ }
263
+ /**
264
+ * Returns the values of all current boxes for the current app decoded using an ABI Type.
265
+ * Note: This will issue multiple HTTP requests (one per box) and it's not an atomic operation so values may be out of sync.
266
+ * @param type The ABI type to decode the values with
267
+ * @param filter Optional filter to filter which boxes' values are returned
268
+ * @returns The (name, value) pair of the boxes with values as the ABI Value
269
+ */
270
+ async getBoxValuesFromABIType(type, filter) {
271
+ const names = (await this.getBoxNames()).filter(filter ?? ((_) => true));
272
+ const values = await this._algorand.app.getBoxValuesFromABIType({
273
+ appId: this.appId,
274
+ boxNames: names.map((name) => name.nameRaw),
275
+ type,
276
+ });
277
+ return names.map((name, i) => ({ name, value: values[i] }));
278
+ }
279
+ /**
280
+ * Takes an error that may include a logic error from a call to the current app and re-exposes the
281
+ * error to include source code information via the source map and ARC-56 spec.
282
+ * @param e The error to parse
283
+ * @param isClearStateProgram Whether or not the code was running the clear state program (defaults to approval program)
284
+ * @returns The new error, or if there was no logic error or source map then the wrapped error with source details
285
+ */
286
+ exposeLogicError(e, isClearStateProgram) {
287
+ return AppClient.exposeLogicError(e, this._appSpec, {
288
+ isClearStateProgram,
289
+ approvalSourceMap: this._approvalSourceMap,
290
+ clearSourceMap: this._clearSourceMap,
291
+ });
292
+ }
293
+ /**
294
+ * Export the current source maps for the app.
295
+ * @returns The source maps
296
+ */
297
+ exportSourceMaps() {
298
+ if (!this._approvalSourceMap || !this._clearSourceMap) {
299
+ throw new Error("Unable to export source maps; they haven't been loaded into this client - you need to call create, update, or deploy first");
300
+ }
301
+ return {
302
+ approvalSourceMap: this._approvalSourceMap,
303
+ clearSourceMap: this._clearSourceMap,
304
+ };
305
+ }
306
+ /**
307
+ * Import source maps for the app.
308
+ * @param sourceMaps The source maps to import
309
+ */
310
+ importSourceMaps(sourceMaps) {
311
+ this._approvalSourceMap = new SourceMap(sourceMaps.approvalSourceMap);
312
+ this._clearSourceMap = new SourceMap(sourceMaps.clearSourceMap);
313
+ }
314
+ /**
315
+ * Returns the ABI Method spec for the given method string for the app represented by this application client instance
316
+ * @param methodNameOrSignature The method name or method signature to call if an ABI call is being emitted.
317
+ * e.g. `my_method` or `my_method(unit64,string)bytes`
318
+ * @returns A tuple with: [ARC-56 `Method`, algosdk `ABIMethod`]
319
+ */
320
+ getABIMethod(methodNameOrSignature) {
321
+ return types_appArc56.getArc56Method(methodNameOrSignature, this._appSpec);
322
+ }
323
+ /**
324
+ * Checks for decode errors on the SendAppTransactionResult and maps the return value to the specified type
325
+ * on the ARC-56 method, replacing the `return` property with the decoded type.
326
+ *
327
+ * If the return type is an ARC-56 struct then the struct will be returned.
328
+ *
329
+ * @param result The SendAppTransactionResult to be mapped
330
+ * @param method The method that was called
331
+ * @returns The smart contract response with an updated return value
332
+ */
333
+ async processMethodCallReturn(result, method) {
334
+ const resultValue = await result;
335
+ return { ...resultValue, return: types_appArc56.getArc56ReturnValue(resultValue.return, method, this._appSpec.structs) };
336
+ }
337
+ /**
338
+ * Compiles the approval and clear state programs (if TEAL templates provided),
339
+ * performing any provided deploy-time parameter replacement and stores
340
+ * the source maps.
341
+ *
342
+ * If no TEAL templates provided it will use any byte code provided in the app spec.
343
+ *
344
+ * Will store any generated source maps for later use in debugging.
345
+ */
346
+ async compile(compilation) {
347
+ const result = await AppClient.compile(this._appSpec, this._algorand.app, compilation);
348
+ if (result.compiledApproval) {
349
+ this._approvalSourceMap = result.compiledApproval.sourceMap;
350
+ }
351
+ if (result.compiledClear) {
352
+ this._clearSourceMap = result.compiledClear.sourceMap;
353
+ }
354
+ return result;
355
+ }
356
+ /**
357
+ * Takes an error that may include a logic error from a call to the current app and re-exposes the
358
+ * error to include source code information via the source map and ARC-56 spec.
359
+ * @param e The error to parse
360
+ * @param appSpec The app spec for the app
361
+ * @param details Additional information to inform the error
362
+ * @returns The new error, or if there was no logic error or source map then the wrapped error with source details
363
+ */
364
+ static exposeLogicError(e, appSpec, details) {
365
+ const { isClearStateProgram, approvalSourceMap, clearSourceMap } = details;
366
+ if ((!isClearStateProgram && approvalSourceMap == undefined) || (isClearStateProgram && clearSourceMap == undefined))
367
+ return e;
368
+ const errorDetails = types_logicError.LogicError.parseLogicError(e);
369
+ const errorMessage = (isClearStateProgram ? appSpec.sourceInfo?.clear : appSpec.sourceInfo?.approval)?.find((s) => s?.pc?.includes(errorDetails?.pc ?? -1))?.errorMessage;
370
+ if (errorDetails !== undefined && appSpec.source)
371
+ e = new types_logicError.LogicError(errorDetails, buffer.Buffer.from(isClearStateProgram ? appSpec.source.clear : appSpec.source.approval, 'base64')
372
+ .toString()
373
+ .split('\n'),
374
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
375
+ isClearStateProgram ? clearSourceMap : approvalSourceMap);
376
+ if (errorMessage) {
377
+ const appId = JSON.stringify(e).match(/(?<=app=)\d+/)?.[0] || '';
378
+ const txId = JSON.stringify(e).match(/(?<=transaction )\S+(?=:)/)?.[0];
379
+ const error = new Error(`Runtime error when executing ${appSpec.name} (appId: ${appId}) in transaction ${txId}: ${errorMessage}`);
380
+ error.cause = e;
381
+ return error;
382
+ }
383
+ return e;
384
+ }
385
+ /**
386
+ * Compiles the approval and clear state programs (if TEAL templates provided),
387
+ * performing any provided deploy-time parameter replacement and returns
388
+ * the compiled code and any compilation results (including source maps).
389
+ *
390
+ * If no TEAL templates provided it will use any byte code provided in the app spec.
391
+ *
392
+ * Will store any generated source maps for later use in debugging.
393
+ * @param appSpec The app spec for the app
394
+ * @param compilation Any compilation parameters to use
395
+ */
396
+ static async compile(appSpec, appManager, compilation) {
397
+ const { deployTimeParams, updatable, deletable } = compilation ?? {};
398
+ if (!appSpec.source) {
399
+ if (!appSpec.byteCode?.approval || !appSpec.byteCode?.clear) {
400
+ throw new Error(`Attempt to compile app ${appSpec.name} without source or byteCode`);
401
+ }
402
+ return {
403
+ approvalProgram: buffer.Buffer.from(appSpec.byteCode.approval, 'base64'),
404
+ clearStateProgram: buffer.Buffer.from(appSpec.byteCode.clear, 'base64'),
405
+ };
406
+ }
407
+ const approvalTemplate = buffer.Buffer.from(appSpec.source.approval, 'base64').toString('utf-8');
408
+ const compiledApproval = await appManager.compileTealTemplate(approvalTemplate, deployTimeParams, {
409
+ updatable,
410
+ deletable,
411
+ });
412
+ const clearTemplate = buffer.Buffer.from(appSpec.source.clear, 'base64').toString('utf-8');
413
+ const compiledClear = await appManager.compileTealTemplate(clearTemplate, deployTimeParams);
414
+ if (config.Config.debug) {
415
+ await config.Config.events.emitAsync(types_asyncEventEmitter.EventType.AppCompiled, {
416
+ sources: [
417
+ { compiledTeal: compiledApproval, appName: appSpec.name, fileName: 'approval' },
418
+ { compiledTeal: compiledClear, appName: appSpec.name, fileName: 'clear' },
419
+ ],
420
+ });
421
+ }
422
+ return {
423
+ approvalProgram: compiledApproval.compiledBase64ToBytes,
424
+ compiledApproval,
425
+ clearStateProgram: compiledClear.compiledBase64ToBytes,
426
+ compiledClear,
427
+ };
428
+ }
429
+ /**
430
+ * Returns ABI method arguments ready for a method call params object with default values populated
431
+ * and structs replaced with tuples.
432
+ *
433
+ * It does this by replacing any `undefined` values with the equivalent default value from the given ARC-56 app spec.
434
+ * @param methodNameOrSignature The method name or method signature to call if an ABI call is being emitted.
435
+ * e.g. `my_method` or `my_method(unit64,string)bytes`
436
+ * @param args The arguments to the method with `undefined` for any that should be populated with a default value
437
+ */
438
+ async getABIArgsWithDefaultValues(methodNameOrSignature, args, sender) {
439
+ const m = types_appArc56.getArc56Method(methodNameOrSignature, this._appSpec);
440
+ return await Promise.all(args?.map(async (a, i) => {
441
+ const arg = m.args[i];
442
+ if (a !== undefined) {
443
+ // If a struct then convert to tuple for the underlying call
444
+ return arg.struct && typeof a === 'object' && !Array.isArray(a)
445
+ ? types_appArc56.getABITupleFromABIStruct(a, this._appSpec.structs[arg.struct], this._appSpec.structs)
446
+ : a;
447
+ }
448
+ const defaultValue = arg.defaultValue;
449
+ if (defaultValue) {
450
+ switch (defaultValue.source) {
451
+ case 'literal':
452
+ if (typeof defaultValue.data === 'number')
453
+ return defaultValue.data;
454
+ return types_appArc56.getABIDecodedValue(buffer.Buffer.from(defaultValue.data, 'base64'), m.method.args[i].defaultValue?.type ?? m.method.args[i].type, this._appSpec.structs);
455
+ // todo: When ARC-56 supports ABI calls as default args
456
+ // case 'abi': {
457
+ // const method = this.getABIMethod(defaultValue.data as string)
458
+ // const result = await this.send.call({
459
+ // method: defaultValue.data as string,
460
+ // methodArgs: method.args.map(() => undefined),
461
+ // sender,
462
+ // })
463
+ // return result.return!
464
+ // }
465
+ case 'local':
466
+ case 'global': {
467
+ const state = defaultValue.source === 'global' ? await this.getGlobalState() : await this.getLocalState(sender);
468
+ const value = Object.values(state).find((s) => s.keyBase64 === defaultValue.data);
469
+ if (!value) {
470
+ throw new Error(`Preparing default value for argument ${arg.name ?? `arg${i + 1}`} resulted in the failure: The key '${defaultValue.data}' could not be found in ${defaultValue.source} storage`);
471
+ }
472
+ return 'valueRaw' in value
473
+ ? types_appArc56.getABIDecodedValue(value.valueRaw, m.method.args[i].defaultValue?.type ?? m.method.args[i].type, this._appSpec.structs)
474
+ : value.value;
475
+ }
476
+ case 'box': {
477
+ const value = await this.getBoxValue(buffer.Buffer.from(defaultValue.data, 'base64'));
478
+ return types_appArc56.getABIDecodedValue(value, m.method.args[i].defaultValue?.type ?? m.method.args[i].type, this._appSpec.structs);
479
+ }
480
+ }
481
+ }
482
+ throw new Error(`No value provided for required argument ${arg.name ?? `arg${i + 1}`} in call to method ${m.name}`);
483
+ }) ?? []);
484
+ }
485
+ getBareParamsMethods() {
486
+ return {
487
+ /** Return params for an update call, including deploy-time TEAL template replacements and compilation if provided */
488
+ update: async (params) => {
489
+ return this.getBareParams({
490
+ ...params,
491
+ ...(await this.compile(params)),
492
+ }, OnApplicationComplete.UpdateApplicationOC);
493
+ },
494
+ /** Return params for an opt-in call */
495
+ optIn: (params) => {
496
+ return this.getBareParams(params, OnApplicationComplete.OptInOC);
497
+ },
498
+ /** Return params for a delete call */
499
+ delete: (params) => {
500
+ return this.getBareParams(params, OnApplicationComplete.DeleteApplicationOC);
501
+ },
502
+ /** Return params for a clear state call */
503
+ clearState: (params) => {
504
+ return this.getBareParams(params, OnApplicationComplete.ClearStateOC);
505
+ },
506
+ /** Return params for a close out call */
507
+ closeOut: (params) => {
508
+ return this.getBareParams(params, OnApplicationComplete.CloseOutOC);
509
+ },
510
+ /** Return params for a call (defaults to no-op) */
511
+ call: (params) => {
512
+ return this.getBareParams(params, params?.onComplete ?? OnApplicationComplete.NoOpOC);
513
+ },
514
+ };
515
+ }
516
+ getBareCreateTransactionMethods() {
517
+ return {
518
+ /** Returns a transaction for an update call, including deploy-time TEAL template replacements and compilation if provided */
519
+ update: async (params) => {
520
+ return this._algorand.createTransaction.appUpdate(await this.params.bare.update(params));
521
+ },
522
+ /** Returns a transaction for an opt-in call */
523
+ optIn: (params) => {
524
+ return this._algorand.createTransaction.appCall(this.params.bare.optIn(params));
525
+ },
526
+ /** Returns a transaction for a delete call */
527
+ delete: (params) => {
528
+ return this._algorand.createTransaction.appDelete(this.params.bare.delete(params));
529
+ },
530
+ /** Returns a transaction for a clear state call */
531
+ clearState: (params) => {
532
+ return this._algorand.createTransaction.appCall(this.params.bare.clearState(params));
533
+ },
534
+ /** Returns a transaction for a close out call */
535
+ closeOut: (params) => {
536
+ return this._algorand.createTransaction.appCall(this.params.bare.closeOut(params));
537
+ },
538
+ /** Returns a transaction for a call (defaults to no-op) */
539
+ call: (params) => {
540
+ return this._algorand.createTransaction.appCall(this.params.bare.call(params));
541
+ },
542
+ };
543
+ }
544
+ getBareSendMethods() {
545
+ return {
546
+ /** Signs and sends an update call, including deploy-time TEAL template replacements and compilation if provided */
547
+ update: async (params) => {
548
+ const compiled = await this.compile(params);
549
+ return {
550
+ ...(await this.handleCallErrors(async () => this._algorand.send.appUpdate(await this.params.bare.update(params)))),
551
+ ...compiled,
552
+ };
553
+ },
554
+ /** Signs and sends an opt-in call */
555
+ optIn: (params) => {
556
+ return this.handleCallErrors(() => this._algorand.send.appCall(this.params.bare.optIn(params)));
557
+ },
558
+ /** Signs and sends a delete call */
559
+ delete: (params) => {
560
+ return this.handleCallErrors(() => this._algorand.send.appDelete(this.params.bare.delete(params)));
561
+ },
562
+ /** Signs and sends a clear state call */
563
+ clearState: (params) => {
564
+ return this.handleCallErrors(() => this._algorand.send.appCall(this.params.bare.clearState(params)));
565
+ },
566
+ /** Signs and sends a close out call */
567
+ closeOut: (params) => {
568
+ return this.handleCallErrors(() => this._algorand.send.appCall(this.params.bare.closeOut(params)));
569
+ },
570
+ /** Signs and sends a call (defaults to no-op) */
571
+ call: (params) => {
572
+ return this.handleCallErrors(() => this._algorand.send.appCall(this.params.bare.call(params)));
573
+ },
574
+ };
575
+ }
576
+ getMethodCallParamsMethods() {
577
+ return {
578
+ /** Return params for a payment transaction to fund the app account */
579
+ fundAppAccount: (params) => {
580
+ return {
581
+ ...params,
582
+ sender: this.getSender(params.sender),
583
+ signer: this.getSigner(params.sender, params.signer),
584
+ receiver: this.appAddress,
585
+ };
586
+ },
587
+ /** Return params for an update ABI call, including deploy-time TEAL template replacements and compilation if provided */
588
+ update: async (params) => {
589
+ return (await this.getABIParams({
590
+ ...params,
591
+ ...(await this.compile(params)),
592
+ }, OnApplicationComplete.UpdateApplicationOC));
593
+ },
594
+ /** Return params for an opt-in ABI call */
595
+ optIn: async (params) => {
596
+ return (await this.getABIParams(params, OnApplicationComplete.OptInOC));
597
+ },
598
+ /** Return params for an delete ABI call */
599
+ delete: async (params) => {
600
+ return (await this.getABIParams(params, OnApplicationComplete.DeleteApplicationOC));
601
+ },
602
+ /** Return params for an close out ABI call */
603
+ closeOut: async (params) => {
604
+ return (await this.getABIParams(params, OnApplicationComplete.CloseOutOC));
605
+ },
606
+ /** Return params for an ABI call */
607
+ call: async (params) => {
608
+ return (await this.getABIParams(params, params.onComplete ?? OnApplicationComplete.NoOpOC));
609
+ },
610
+ };
611
+ }
612
+ getMethodCallSendMethods() {
613
+ return {
614
+ /** Sign and send transactions for a payment transaction to fund the app account */
615
+ fundAppAccount: (params) => {
616
+ return this._algorand.send.payment(this.params.fundAppAccount(params));
617
+ },
618
+ /**
619
+ * Sign and send transactions for an update ABI call, including deploy-time TEAL template replacements and compilation if provided
620
+ */
621
+ update: async (params) => {
622
+ const compiled = await this.compile(params);
623
+ return {
624
+ ...(await this.handleCallErrors(async () => this.processMethodCallReturn(this._algorand.send.appUpdateMethodCall(await this.params.update({ ...params })), types_appArc56.getArc56Method(params.method, this._appSpec)))),
625
+ ...compiled,
626
+ };
627
+ },
628
+ /**
629
+ * Sign and send transactions for an opt-in ABI call
630
+ */
631
+ optIn: (params) => {
632
+ return this.handleCallErrors(async () => this.processMethodCallReturn(this._algorand.send.appCallMethodCall(await this.params.optIn(params)), types_appArc56.getArc56Method(params.method, this._appSpec)));
633
+ },
634
+ /**
635
+ * Sign and send transactions for a delete ABI call
636
+ */
637
+ delete: (params) => {
638
+ return this.handleCallErrors(async () => this.processMethodCallReturn(this._algorand.send.appDeleteMethodCall(await this.params.delete(params)), types_appArc56.getArc56Method(params.method, this._appSpec)));
639
+ },
640
+ /**
641
+ * Sign and send transactions for a close out ABI call
642
+ */
643
+ closeOut: (params) => {
644
+ return this.handleCallErrors(async () => this.processMethodCallReturn(this._algorand.send.appCallMethodCall(await this.params.closeOut(params)), types_appArc56.getArc56Method(params.method, this._appSpec)));
645
+ },
646
+ /**
647
+ * Sign and send transactions for a call (defaults to no-op)
648
+ */
649
+ call: async (params) => {
650
+ // Read-only call - do it via simulate
651
+ if (params.onComplete === OnApplicationComplete.NoOpOC ||
652
+ (!params.onComplete && types_appArc56.getArc56Method(params.method, this._appSpec).method.readonly)) {
653
+ const result = await this._algorand
654
+ .newGroup()
655
+ .addAppCallMethodCall(await this.params.call(params))
656
+ .simulate({
657
+ allowUnnamedResources: params.populateAppCallResources ?? true,
658
+ // Simulate calls for a readonly method shouldn't invoke signing
659
+ skipSignatures: true,
660
+ });
661
+ return this.processMethodCallReturn({
662
+ ...result,
663
+ transaction: result.transactions.at(-1),
664
+ confirmation: result.confirmations.at(-1),
665
+ // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
666
+ return: (result.returns?.length ?? 0 > 0) ? result.returns?.at(-1) : undefined,
667
+ }, types_appArc56.getArc56Method(params.method, this._appSpec));
668
+ }
669
+ return this.handleCallErrors(async () => this.processMethodCallReturn(this._algorand.send.appCallMethodCall(await this.params.call(params)), types_appArc56.getArc56Method(params.method, this._appSpec)));
670
+ },
671
+ };
672
+ }
673
+ getMethodCallCreateTransactionMethods() {
674
+ return {
675
+ /** Return transaction for a payment transaction to fund the app account */
676
+ fundAppAccount: (params) => {
677
+ return this._algorand.createTransaction.payment(this.params.fundAppAccount(params));
678
+ },
679
+ /**
680
+ * Return transactions for an update ABI call, including deploy-time TEAL template replacements and compilation if provided
681
+ */
682
+ update: async (params) => {
683
+ return this._algorand.createTransaction.appUpdateMethodCall(await this.params.update(params));
684
+ },
685
+ /**
686
+ * Return transactions for an opt-in ABI call
687
+ */
688
+ optIn: async (params) => {
689
+ return this._algorand.createTransaction.appCallMethodCall(await this.params.optIn(params));
690
+ },
691
+ /**
692
+ * Return transactions for a delete ABI call
693
+ */
694
+ delete: async (params) => {
695
+ return this._algorand.createTransaction.appDeleteMethodCall(await this.params.delete(params));
696
+ },
697
+ /**
698
+ * Return transactions for a close out ABI call
699
+ */
700
+ closeOut: async (params) => {
701
+ return this._algorand.createTransaction.appCallMethodCall(await this.params.closeOut(params));
702
+ },
703
+ /**
704
+ * Return transactions for an ABI call (defaults to no-op)
705
+ */
706
+ call: async (params) => {
707
+ return this._algorand.createTransaction.appCallMethodCall(await this.params.call(params));
708
+ },
709
+ };
710
+ }
711
+ /** Returns the sender for a call, using the provided sender or using the `defaultSender`
712
+ * if none provided and throws an error if neither provided */
713
+ getSender(sender) {
714
+ if (!sender && !this._defaultSender) {
715
+ throw new Error(`No sender provided and no default sender present in app client for call to app ${this._appName}`);
716
+ }
717
+ return sender ?? this._defaultSender;
718
+ }
719
+ /** Returns the signer for a call, using the provided signer or the `defaultSigner`
720
+ * if no signer was provided and the call will use default sender
721
+ * or `undefined` otherwise (so the signer is resolved from `AlgorandClient`) */
722
+ getSigner(sender, signer) {
723
+ return signer ?? (!sender ? this._defaultSigner : undefined);
724
+ }
725
+ getBareParams(params, onComplete) {
726
+ return {
727
+ ...params,
728
+ appId: this._appId,
729
+ sender: this.getSender(params?.sender),
730
+ signer: this.getSigner(params?.sender, params?.signer),
731
+ onComplete,
732
+ };
733
+ }
734
+ async getABIParams(params, onComplete) {
735
+ const sender = this.getSender(params.sender);
736
+ const method = types_appArc56.getArc56Method(params.method, this._appSpec);
737
+ const args = await this.getABIArgsWithDefaultValues(params.method, params.args, sender);
738
+ return {
739
+ ...params,
740
+ appId: this._appId,
741
+ sender: sender,
742
+ signer: this.getSigner(params.sender, params.signer),
743
+ method,
744
+ onComplete,
745
+ args,
746
+ };
747
+ }
748
+ /** Make the given call and catch any errors, augmenting with debugging information before re-throwing. */
749
+ async handleCallErrors(call) {
750
+ try {
751
+ return await call();
752
+ }
753
+ catch (e) {
754
+ throw this.exposeLogicError(e);
755
+ }
756
+ }
757
+ getBoxMethods() {
758
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
759
+ const that = this;
760
+ const stateMethods = {
761
+ /**
762
+ * Returns all single-key state values in a record keyed by the key name and the value a decoded ABI value.
763
+ */
764
+ getAll: async () => {
765
+ return Object.fromEntries(await Promise.all(Object.keys(that._appSpec.state.keys.box).map(async (key) => [key, await stateMethods.getValue(key)])));
766
+ },
767
+ /**
768
+ * Returns a single state value for the current app with the value a decoded ABI value.
769
+ * @param name The name of the state value to retrieve the value for
770
+ * @returns
771
+ */
772
+ getValue: async (name) => {
773
+ const metadata = that._appSpec.state.keys.box[name];
774
+ const value = await that.getBoxValue(buffer.Buffer.from(metadata.key, 'base64'));
775
+ return types_appArc56.getABIDecodedValue(value, metadata.valueType, that._appSpec.structs);
776
+ },
777
+ /**
778
+ *
779
+ * @param mapName The name of the map to read from
780
+ * @param key The key within the map (without any map prefix) as either a Buffer with the bytes or a value
781
+ * that will be converted to bytes by encoding it using the specified ABI key type
782
+ * in the ARC-56 spec
783
+ */
784
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
785
+ getMapValue: async (mapName, key) => {
786
+ const metadata = that._appSpec.state.maps.box[mapName];
787
+ const prefix = buffer.Buffer.from(metadata.prefix ?? '', 'base64');
788
+ const encodedKey = buffer.Buffer.concat([prefix, types_appArc56.getABIEncodedValue(key, metadata.keyType, that._appSpec.structs)]);
789
+ const base64Key = buffer.Buffer.from(encodedKey).toString('base64');
790
+ const value = await that.getBoxValue(buffer.Buffer.from(base64Key, 'base64'));
791
+ return types_appArc56.getABIDecodedValue(value, metadata.valueType, that._appSpec.structs);
792
+ },
793
+ /**
794
+ *
795
+ * @param mapName The name of the map to read from
796
+ * @param key The key within the map as either a Buffer with the bytes or a value
797
+ * that will be converted to bytes by encoding it using the specified ABI key type
798
+ * in the ARC-56 spec
799
+ * @param appState
800
+ */
801
+ getMap: async (mapName) => {
802
+ const metadata = that._appSpec.state.maps.box[mapName];
803
+ const prefix = buffer.Buffer.from(metadata.prefix ?? '', 'base64');
804
+ const boxNames = await that.getBoxNames();
805
+ return new Map(await Promise.all(boxNames
806
+ .filter((b) => util.binaryStartsWith(b.nameRaw, prefix))
807
+ .map(async (b) => {
808
+ const encodedKey = buffer.Buffer.concat([prefix, b.nameRaw]);
809
+ const base64Key = buffer.Buffer.from(encodedKey).toString('base64');
810
+ return [
811
+ types_appArc56.getABIDecodedValue(b.nameRaw.slice(prefix.length), metadata.keyType, that._appSpec.structs),
812
+ types_appArc56.getABIDecodedValue(await that.getBoxValue(buffer.Buffer.from(base64Key, 'base64')), metadata.valueType, that._appSpec.structs),
813
+ ];
814
+ })));
815
+ },
816
+ };
817
+ return stateMethods;
818
+ }
819
+ getStateMethods(stateGetter, keyGetter, mapGetter) {
820
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
821
+ const that = this;
822
+ const stateMethods = {
823
+ /**
824
+ * Returns all single-key state values in a record keyed by the key name and the value a decoded ABI value.
825
+ */
826
+ getAll: async () => {
827
+ const appState = await stateGetter();
828
+ return Object.fromEntries(await Promise.all(Object.keys(keyGetter()).map(async (key) => [key, await stateMethods.getValue(key, appState)])));
829
+ },
830
+ /**
831
+ * Returns a single state value for the current app with the value a decoded ABI value.
832
+ * @param name The name of the state value to retrieve the value for
833
+ * @param appState Optional cached value of the current state
834
+ * @returns
835
+ */
836
+ getValue: async (name, appState) => {
837
+ const state = Object.values(appState ?? (await stateGetter()));
838
+ const metadata = keyGetter()[name];
839
+ const value = state.find((s) => s.keyBase64 === metadata.key);
840
+ if (value && 'valueRaw' in value) {
841
+ return types_appArc56.getABIDecodedValue(value.valueRaw, metadata.valueType, that._appSpec.structs);
842
+ }
843
+ return value?.value;
844
+ },
845
+ /**
846
+ * Returns a single value from the given map for the current app with the value a decoded ABI value.
847
+ * @param mapName The name of the map to read from
848
+ * @param key The key within the map (without any map prefix) as either a Buffer with the bytes or a value
849
+ * that will be converted to bytes by encoding it using the specified ABI key type
850
+ * in the ARC-56 spec
851
+ * @param appState Optional cached value of the current state
852
+ */
853
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
854
+ getMapValue: async (mapName, key, appState) => {
855
+ const state = Object.values(appState ?? (await stateGetter()));
856
+ const metadata = mapGetter()[mapName];
857
+ const prefix = buffer.Buffer.from(metadata.prefix ?? '', 'base64');
858
+ const encodedKey = buffer.Buffer.concat([prefix, types_appArc56.getABIEncodedValue(key, metadata.keyType, that._appSpec.structs)]);
859
+ const base64Key = buffer.Buffer.from(encodedKey).toString('base64');
860
+ const value = state.find((s) => s.keyBase64 === base64Key);
861
+ if (value && 'valueRaw' in value) {
862
+ return types_appArc56.getABIDecodedValue(value.valueRaw, metadata.valueType, that._appSpec.structs);
863
+ }
864
+ return value?.value;
865
+ },
866
+ /**
867
+ * Returns all map values for the given map.
868
+ * @param mapName The name of the map to read from
869
+ * @param appState Optional cached value of the current state
870
+ * @returns A map of all key-value pairs in the map as a `Record<string, ABIValue>`
871
+ */
872
+ getMap: async (mapName) => {
873
+ const state = Object.values(await stateGetter());
874
+ const metadata = mapGetter()[mapName];
875
+ const prefix = buffer.Buffer.from(metadata.prefix ?? '', 'base64');
876
+ return new Map(state
877
+ .filter((s) => util.binaryStartsWith(s.keyRaw, prefix))
878
+ .map((s) => {
879
+ const key = s.keyRaw.slice(prefix.length);
880
+ return [
881
+ types_appArc56.getABIDecodedValue(key, metadata.keyType, this._appSpec.structs),
882
+ types_appArc56.getABIDecodedValue('valueRaw' in s ? s.valueRaw : s.value, metadata.valueType, this._appSpec.structs),
883
+ ];
884
+ }));
885
+ },
886
+ };
887
+ return stateMethods;
888
+ }
889
+ }
890
+ /**
891
+ * @deprecated Use `AppClient` instead e.g. via `algorand.client.getAppClientById` or
892
+ * `algorand.client.getAppClientByCreatorAndName`.
893
+ * If you want to `create` or `deploy` then use `AppFactory` e.g. via `algorand.client.getAppFactory`,
894
+ * which will in turn give you an `AppClient` instance against the created/deployed app to make other calls.
895
+ *
896
+ * Application client - a class that wraps an ARC-0032 app spec and provides high productivity methods to deploy and call the app */
43
897
  class ApplicationClient {
44
- // todo: process ABI args as needed to make them nicer to deal with like beaker-ts
45
- // todo: support readonly, noop method calls
46
- // todo: find create, update, delete, etc. methods from app spec and call them by default
47
- // todo: intelligent version management when deploying
48
898
  /**
899
+ * @deprecated Use `AppClient` instead e.g. via `algorand.client.getAppClientById` or
900
+ * `algorand.client.getAppClientByCreatorAndName`.
901
+ * If you want to `create` or `deploy` then use `AppFactory` e.g. via `algorand.client.getAppFactory`,
902
+ * which will in turn give you an `AppClient` instance against the created/deployed app to make other calls.
903
+ *
49
904
  * Create a new ApplicationClient instance
50
905
  * @param appDetails The details of the app
51
906
  * @param algod An algod instance
@@ -80,9 +935,11 @@ class ApplicationClient {
80
935
  this.params = params;
81
936
  }
82
937
  /**
83
- * Compiles the approval and clear programs and sets up the source map.
938
+ * @deprecated Use `AppClient.compile()` instead.
939
+ *
940
+ * Compiles the approval and clear state programs and sets up the source map.
84
941
  * @param compilation The deploy-time parameters for the compilation
85
- * @returns The compiled approval and clear programs
942
+ * @returns The compiled approval and clear state programs
86
943
  */
87
944
  async compile(compilation) {
88
945
  const { deployTimeParams, updatable, deletable } = compilation ?? {};
@@ -97,15 +954,12 @@ class ApplicationClient {
97
954
  const clear = appDeploy.performTemplateSubstitution(clearTemplate, deployTimeParams ?? this.deployTimeParams);
98
955
  const clearCompiled = await app.compileTeal(clear, this.algod);
99
956
  this._clearSourceMap = clearCompiled?.sourceMap;
100
- if (config.Config.debug && config.Config.projectRoot) {
101
- debugging.persistSourceMaps({
957
+ if (config.Config.debug) {
958
+ await config.Config.events.emitAsync(types_asyncEventEmitter.EventType.AppCompiled, {
102
959
  sources: [
103
- types_debugging.PersistSourceMapInput.fromCompiledTeal(approvalCompiled, this._appName, 'approval.teal'),
104
- types_debugging.PersistSourceMapInput.fromCompiledTeal(clearCompiled, this._appName, 'clear.teal'),
960
+ { compiledTeal: approvalCompiled, appName: this._appName, fileName: 'approval' },
961
+ { compiledTeal: clearCompiled, appName: this._appName, fileName: 'clear' },
105
962
  ],
106
- projectRoot: config.Config.projectRoot,
107
- client: this.algod,
108
- withSources: true,
109
963
  });
110
964
  }
111
965
  return { approvalCompiled, clearCompiled };
@@ -132,6 +986,8 @@ class ApplicationClient {
132
986
  this._clearSourceMap = new SourceMap(sourceMaps.clearSourceMap);
133
987
  }
134
988
  /**
989
+ * @deprecated Use `deploy` from an `AppFactory` instance instead.
990
+ *
135
991
  * Idempotently deploy (create, update/delete if changed) an app against the given name via the given creator account, including deploy-time template placeholder substitutions.
136
992
  *
137
993
  * 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
@@ -217,6 +1073,8 @@ class ApplicationClient {
217
1073
  }
218
1074
  }
219
1075
  /**
1076
+ * @deprecated Use `create` from an `AppFactory` instance instead.
1077
+ *
220
1078
  * Creates a smart contract app, returns the details of the created app.
221
1079
  * @param create The parameters to create the app with
222
1080
  * @returns The details of the created app, or the transaction to create it if `skipSending` and the compilation result
@@ -261,6 +1119,8 @@ class ApplicationClient {
261
1119
  }
262
1120
  }
263
1121
  /**
1122
+ * @deprecated Use `appClient.send.update` or `appClient.createTransaction.update` from an `AppClient` instance instead.
1123
+ *
264
1124
  * Updates the smart contract app.
265
1125
  * @param update The parameters to update the app with
266
1126
  * @returns The transaction send result and the compilation result
@@ -293,6 +1153,8 @@ class ApplicationClient {
293
1153
  }
294
1154
  }
295
1155
  /**
1156
+ * @deprecated Use `appClient.send.call` or `appClient.createTransaction.call` from an `AppClient` instance instead.
1157
+ *
296
1158
  * Issues a no_op (normal) call to the app.
297
1159
  * @param call The call details.
298
1160
  * @returns The result of the call
@@ -307,7 +1169,7 @@ class ApplicationClient {
307
1169
  !call.sendParams?.atc &&
308
1170
  // The method is readonly
309
1171
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
310
- this.appSpec.hints[app.getABIMethodSignature(this.getABIMethod(call.method))].read_only) {
1172
+ this.appSpec.hints[this.getABIMethodSignature(this.getABIMethod(call.method))].read_only) {
311
1173
  const atc = new AtomicTransactionComposer();
312
1174
  await this.callOfType({ ...call, sendParams: { ...call.sendParams, atc } }, 'no_op');
313
1175
  const result = await atc.simulate(this.algod);
@@ -326,6 +1188,8 @@ class ApplicationClient {
326
1188
  return await this.callOfType(call, 'no_op');
327
1189
  }
328
1190
  /**
1191
+ * @deprecated Use `appClient.send.optIn` or `appClient.createTransaction.optIn` from an `AppClient` instance instead.
1192
+ *
329
1193
  * Issues a opt_in call to the app.
330
1194
  * @param call The call details.
331
1195
  * @returns The result of the call
@@ -334,6 +1198,8 @@ class ApplicationClient {
334
1198
  return await this.callOfType(call, 'opt_in');
335
1199
  }
336
1200
  /**
1201
+ * @deprecated Use `appClient.send.closeOut` or `appClient.createTransaction.closeOut` from an `AppClient` instance instead.
1202
+ *
337
1203
  * Issues a close_out call to the app.
338
1204
  * @param call The call details.
339
1205
  * @returns The result of the call
@@ -342,6 +1208,8 @@ class ApplicationClient {
342
1208
  return await this.callOfType(call, 'close_out');
343
1209
  }
344
1210
  /**
1211
+ * @deprecated Use `appClient.send.clearState` or `appClient.createTransaction.clearState` from an `AppClient` instance instead.
1212
+ *
345
1213
  * Issues a clear_state call to the app.
346
1214
  * @param call The call details.
347
1215
  * @returns The result of the call
@@ -350,6 +1218,8 @@ class ApplicationClient {
350
1218
  return await this.callOfType(call, 'clear_state');
351
1219
  }
352
1220
  /**
1221
+ * @deprecated Use `appClient.send.delete` or `appClient.createTransaction.delete` from an `AppClient` instance instead.
1222
+ *
353
1223
  * Issues a delete_application call to the app.
354
1224
  * @param call The call details.
355
1225
  * @returns The result of the call
@@ -358,6 +1228,8 @@ class ApplicationClient {
358
1228
  return await this.callOfType(call, 'delete_application');
359
1229
  }
360
1230
  /**
1231
+ * @deprecated Use `appClient.send.call` or `appClient.createTransaction.call` from an `AppClient` instance instead.
1232
+ *
361
1233
  * Issues a call to the app with the given call type.
362
1234
  * @param call The call details.
363
1235
  * @param callType The call type
@@ -500,6 +1372,8 @@ class ApplicationClient {
500
1372
  })));
501
1373
  }
502
1374
  /**
1375
+ * @deprecated Use `appClient.params.*` from an `AppClient` instance instead.
1376
+ *
503
1377
  * Returns the arguments for an app call for the given ABI method or raw method specification.
504
1378
  * @param args The call args specific to this application client
505
1379
  * @param sender The sender of this call. Will be used to fetch any default argument values if applicable
@@ -514,7 +1388,7 @@ class ApplicationClient {
514
1388
  if (!abiMethod) {
515
1389
  throw new Error(`Attempt to call ABI method ${args.method}, but it wasn't found`);
516
1390
  }
517
- const methodSignature = app.getABIMethodSignature(abiMethod);
1391
+ const methodSignature = this.getABIMethodSignature(abiMethod);
518
1392
  return {
519
1393
  ...args,
520
1394
  method: abiMethod,
@@ -531,7 +1405,7 @@ class ApplicationClient {
531
1405
  case 'abi-method': {
532
1406
  const method = defaultValueStrategy.data;
533
1407
  const result = await this.callOfType({
534
- method: app.getABIMethodSignature(method),
1408
+ method: this.getABIMethodSignature(method),
535
1409
  methodArgs: method.args.map(() => undefined),
536
1410
  sender,
537
1411
  }, 'no_op');
@@ -557,6 +1431,8 @@ class ApplicationClient {
557
1431
  }
558
1432
  }
559
1433
  /**
1434
+ * @deprecated Use `appClient.getABIMethod` instead.
1435
+ *
560
1436
  * Returns the ABI Method parameters for the given method name string for the app represented by this application client instance
561
1437
  * @param method Either the name of the method or the ABI method spec definition string
562
1438
  * @returns The ABI method params for the given method
@@ -566,12 +1442,12 @@ class ApplicationClient {
566
1442
  const methods = this.appSpec.contract.methods.filter((m) => m.name === method);
567
1443
  if (methods.length > 1) {
568
1444
  throw new Error(`Received a call to method ${method} in contract ${this._appName}, but this resolved to multiple methods; please pass in an ABI signature instead: ${methods
569
- .map(app.getABIMethodSignature)
1445
+ .map(this.getABIMethodSignature)
570
1446
  .join(', ')}`);
571
1447
  }
572
1448
  return methods[0];
573
1449
  }
574
- return this.appSpec.contract.methods.find((m) => app.getABIMethodSignature(m) === method);
1450
+ return this.appSpec.contract.methods.find((m) => this.getABIMethodSignature(m) === method);
575
1451
  }
576
1452
  /**
577
1453
  * Returns the ABI Method for the given method name string for the app represented by this application client instance
@@ -583,6 +1459,8 @@ class ApplicationClient {
583
1459
  return methodParams ? new ABIMethod(methodParams) : undefined;
584
1460
  }
585
1461
  /**
1462
+ * @deprecated Use `appClient.appId` and `appClient.appAddress` from an `AppClient` instance instead.
1463
+ *
586
1464
  * Gets the reference information for the current application instance.
587
1465
  * `appId` will be 0 if it can't find an app.
588
1466
  * @returns The app reference, or if deployed using the `deploy` method, the app metadata too
@@ -628,7 +1506,11 @@ class ApplicationClient {
628
1506
  else
629
1507
  return e;
630
1508
  }
1509
+ getABIMethodSignature(method) {
1510
+ return 'getSignature' in method ? method.getSignature() : new ABIMethod(method).getSignature();
1511
+ }
631
1512
  }
632
1513
 
1514
+ exports.AppClient = AppClient;
633
1515
  exports.ApplicationClient = ApplicationClient;
634
1516
  //# sourceMappingURL=app-client.js.map