@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,604 +1,592 @@
1
- import algosdk, { Address } from 'algosdk';
2
- import { Config } from '../config.mjs';
3
- import { memoize, calculateFundAmount } from '../util.mjs';
4
- import { SigningAccount, MultisigAccount, DISPENSER_ACCOUNT } from './account.mjs';
5
- import { AlgoAmount } from './amount.mjs';
6
- import { TransactionComposer } from './composer.mjs';
7
- import { KmdAccountManager } from './kmd-account-manager.mjs';
8
-
1
+ import { Config } from "../config.mjs";
2
+ import { calculateFundAmount, memoize } from "../util.mjs";
3
+ import { DISPENSER_ACCOUNT, MultisigAccount, SigningAccount } from "./account.mjs";
4
+ import { AlgoAmount } from "./amount.mjs";
5
+ import { TransactionComposer } from "./composer.mjs";
6
+ import { KmdAccountManager } from "./kmd-account-manager.mjs";
7
+ import algosdk, { Address } from "algosdk";
8
+ //#region src/types/account-manager.ts
9
9
  var LogicSigAccount = algosdk.LogicSigAccount;
10
- const address = (address) => (typeof address === 'string' ? Address.fromString(address) : address);
10
+ const address = (address) => typeof address === "string" ? Address.fromString(address) : address;
11
11
  /**
12
- * Returns a `TransactionSigner` for the given account that can sign a transaction.
13
- * This function has memoization, so will return the same transaction signer for a given account.
14
- * @param account An account that can sign a transaction
15
- * @returns A transaction signer
16
- * @example
17
- * ```typescript
18
- * const signer = getAccountTransactionSigner(account)
19
- * ```
20
- */
21
- const getAccountTransactionSigner = memoize(function (account) {
22
- return 'signer' in account
23
- ? account.signer
24
- : 'lsig' in account
25
- ? algosdk.makeLogicSigAccountTransactionSigner(account)
26
- : algosdk.makeBasicAccountTransactionSigner(account);
12
+ * Returns a `TransactionSigner` for the given account that can sign a transaction.
13
+ * This function has memoization, so will return the same transaction signer for a given account.
14
+ * @param account An account that can sign a transaction
15
+ * @returns A transaction signer
16
+ * @example
17
+ * ```typescript
18
+ * const signer = getAccountTransactionSigner(account)
19
+ * ```
20
+ */
21
+ const getAccountTransactionSigner = memoize(function(account) {
22
+ return "signer" in account ? account.signer : "lsig" in account ? algosdk.makeLogicSigAccountTransactionSigner(account) : algosdk.makeBasicAccountTransactionSigner(account);
27
23
  });
28
24
  /** Creates and keeps track of signing accounts that can sign transactions for a sending address. */
29
- class AccountManager {
30
- /**
31
- * Create a new account manager.
32
- * @param clientManager The ClientManager client to use for algod and kmd clients
33
- * @example Create a new account manager
34
- * ```typescript
35
- * const accountManager = new AccountManager(clientManager)
36
- * ```
37
- */
38
- constructor(clientManager) {
39
- this._accounts = {};
40
- this._clientManager = clientManager;
41
- this._kmdAccountManager = new KmdAccountManager(clientManager);
42
- }
43
- _getComposer(getSuggestedParams) {
44
- return new TransactionComposer({
45
- algod: this._clientManager.algod,
46
- getSigner: this.getSigner.bind(this),
47
- getSuggestedParams: getSuggestedParams ?? (() => this._clientManager.algod.getTransactionParams().do()),
48
- });
49
- }
50
- /**
51
- * KMD account manager that allows you to easily get and create accounts using KMD.
52
- * @returns The `KmdAccountManager` instance.
53
- * @example
54
- * ```typescript
55
- * const kmdManager = accountManager.kmd;
56
- * ```
57
- */
58
- get kmd() {
59
- return this._kmdAccountManager;
60
- }
61
- /**
62
- * Sets the default signer to use if no other signer is specified.
63
- *
64
- * If this isn't set an a transaction needs signing for a given sender
65
- * then an error will be thrown from `getSigner` / `getAccount`.
66
- * @param signer The signer to use, either a `TransactionSigner` or a `TransactionSignerAccount`
67
- * @example
68
- * ```typescript
69
- * const signer = accountManager.random() // Can be anything that returns a `algosdk.TransactionSigner` or `TransactionSignerAccount`
70
- * accountManager.setDefaultSigner(signer)
71
- *
72
- * // When signing a transaction, if there is no signer registered for the sender then the default signer will be used
73
- * const signer = accountManager.getSigner("SENDERADDRESS")
74
- * ```
75
- * @returns The `AccountManager` so method calls can be chained
76
- */
77
- setDefaultSigner(signer) {
78
- this._defaultSigner = 'signer' in signer ? signer.signer : signer;
79
- return this;
80
- }
81
- /**
82
- * Records the given account (that can sign) against the address of the provided account for later
83
- * retrieval and returns a `TransactionSignerAccount` along with the original account in an `account` property.
84
- */
85
- signerAccount(account) {
86
- const signer = getAccountTransactionSigner(account);
87
- const acc = {
88
- addr: 'addr' in account ? account.addr : account.address(),
89
- signer: signer,
90
- };
91
- this._accounts[acc.addr.toString()] = acc;
92
- const addressWithAccount = Address.fromString(acc.addr.toString());
93
- addressWithAccount.account = account;
94
- addressWithAccount.addr = acc.addr;
95
- addressWithAccount.signer = signer;
96
- return addressWithAccount;
97
- }
98
- /**
99
- * Tracks the given account for later signing.
100
- *
101
- * Note: If you are generating accounts via the various methods on `AccountManager`
102
- * (like `random`, `fromMnemonic`, `logicsig`, etc.) then they automatically get tracked.
103
- * @param account The account to register, which can be a `TransactionSignerAccount` or
104
- * a `algosdk.Account`, `algosdk.LogicSigAccount`, `SigningAccount` or `MultisigAccount`
105
- * @example
106
- * ```typescript
107
- * const accountManager = new AccountManager(clientManager)
108
- * .setSignerFromAccount(algosdk.generateAccount())
109
- * .setSignerFromAccount(new algosdk.LogicSigAccount(program, args))
110
- * .setSignerFromAccount(new SigningAccount(mnemonic, sender))
111
- * .setSignerFromAccount(new MultisigAccount({version: 1, threshold: 1, addrs: ["ADDRESS1...", "ADDRESS2..."]}, [account1, account2]))
112
- * .setSignerFromAccount({addr: "SENDERADDRESS", signer: transactionSigner})
113
- * ```
114
- * @returns The `AccountManager` instance for method chaining
115
- */
116
- setSignerFromAccount(account) {
117
- this.signerAccount(account);
118
- return this;
119
- }
120
- /**
121
- * Tracks the given `algosdk.TransactionSigner` against the given sender address for later signing.
122
- * @param sender The sender address to use this signer for
123
- * @param signer The `algosdk.TransactionSigner` to sign transactions with for the given sender
124
- * @example
125
- * ```typescript
126
- * const accountManager = new AccountManager(clientManager)
127
- * .setSigner("SENDERADDRESS", transactionSigner)
128
- * ```
129
- * @returns The `AccountManager` instance for method chaining
130
- */
131
- setSigner(sender, signer) {
132
- this._accounts[address(sender).toString()] = { addr: address(sender), signer };
133
- return this;
134
- }
135
- /**
136
- * Takes all registered signers from the given `AccountManager` and adds them to this `AccountManager`.
137
- *
138
- * This is useful for situations where you have multiple contexts you are building accounts in such as unit tests.
139
- * @param anotherAccountManager Another account manager with signers registered
140
- * @param overwriteExisting Whether or not to overwrite any signers that have the same sender address with the ones in the other account manager or not (default: true)
141
- * @returns The `AccountManager` instance for method chaining
142
- * @example
143
- * ```typescript
144
- * accountManager2.setSigners(accountManager1);
145
- * ```
146
- */
147
- setSigners(anotherAccountManager, overwriteExisting = true) {
148
- this._accounts = overwriteExisting
149
- ? { ...this._accounts, ...anotherAccountManager._accounts }
150
- : { ...anotherAccountManager._accounts, ...this._accounts };
151
- return this;
152
- }
153
- /**
154
- * Returns the `TransactionSigner` for the given sender address, ready to sign a transaction for that sender.
155
- *
156
- * If no signer has been registered for that address then the default signer is used if registered and
157
- * if not then an error is thrown.
158
- *
159
- * @param sender The sender address
160
- * @example
161
- * ```typescript
162
- * const signer = accountManager.getSigner("SENDERADDRESS")
163
- * ```
164
- * @returns The `TransactionSigner` or throws an error if not found and no default signer is set
165
- */
166
- getSigner(sender) {
167
- const signer = this._accounts[address(sender).toString()]?.signer ?? this._defaultSigner;
168
- if (!signer)
169
- throw new Error(`No signer found for address ${sender}`);
170
- return signer;
171
- }
172
- /**
173
- * Returns the `TransactionSignerAccount` for the given sender address.
174
- *
175
- * If no signer has been registered for that address then an error is thrown.
176
- * @param sender The sender address
177
- * @example
178
- * ```typescript
179
- * const sender = accountManager.random()
180
- * // ...
181
- * // Returns the `TransactionSignerAccount` for `sender` that has previously been registered
182
- * const account = accountManager.getAccount(sender)
183
- * ```
184
- * @returns The `TransactionSignerAccount` or throws an error if not found
185
- */
186
- getAccount(sender) {
187
- const account = this._accounts[address(sender).toString()];
188
- if (!account)
189
- throw new Error(`No signer found for address ${sender}`);
190
- return account;
191
- }
192
- /**
193
- * Returns the given sender account's current status, balance and spendable amounts.
194
- *
195
- * [Response data schema details](https://dev.algorand.co/reference/rest-apis/algod/#accountinformation)
196
- * @example
197
- * ```typescript
198
- * const address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA";
199
- * const accountInfo = await accountManager.getInformation(address);
200
- * ```
201
- *
202
- * @param sender The account / address to look up
203
- * @returns The account information
204
- */
205
- async getInformation(sender) {
206
- const { round, lastHeartbeat = undefined, lastProposed = undefined, address, ...account } = await this._clientManager.algod.accountInformation(sender).do();
207
- return {
208
- ...account,
209
- // None of the Number types can practically overflow 2^53
210
- address: Address.fromString(address),
211
- balance: AlgoAmount.MicroAlgo(Number(account.amount)),
212
- amountWithoutPendingRewards: AlgoAmount.MicroAlgo(Number(account.amountWithoutPendingRewards)),
213
- minBalance: AlgoAmount.MicroAlgo(Number(account.minBalance)),
214
- pendingRewards: AlgoAmount.MicroAlgo(Number(account.pendingRewards)),
215
- rewards: AlgoAmount.MicroAlgo(Number(account.rewards)),
216
- validAsOfRound: BigInt(round),
217
- totalAppsOptedIn: Number(account.totalAppsOptedIn),
218
- totalAssetsOptedIn: Number(account.totalAssetsOptedIn),
219
- totalCreatedApps: Number(account.totalCreatedApps),
220
- totalCreatedAssets: Number(account.totalCreatedAssets),
221
- appsTotalExtraPages: account.appsTotalExtraPages !== undefined ? Number(account.appsTotalExtraPages) : undefined,
222
- rewardBase: account.rewardBase !== undefined ? Number(account.rewardBase) : undefined,
223
- totalBoxBytes: account.totalBoxBytes !== undefined ? Number(account.totalBoxBytes) : undefined,
224
- totalBoxes: account.totalBoxes !== undefined ? Number(account.totalBoxes) : undefined,
225
- lastHeartbeatRound: lastHeartbeat !== undefined ? BigInt(lastHeartbeat) : undefined,
226
- lastProposedRound: lastProposed !== undefined ? BigInt(lastProposed) : undefined,
227
- };
228
- }
229
- /**
230
- * Tracks and returns an Algorand account with secret key loaded (i.e. that can sign transactions) by taking the mnemonic secret.
231
- *
232
- * @example
233
- * ```typescript
234
- * const account = accountManager.fromMnemonic("mnemonic secret ...")
235
- * const rekeyedAccount = accountManager.fromMnemonic("mnemonic secret ...", "SENDERADDRESS...")
236
- * ```
237
- * @param mnemonicSecret The mnemonic secret representing the private key of an account; **Note: Be careful how the mnemonic is handled**,
238
- * never commit it into source control and ideally load it from the environment (ideally via a secret storage service) rather than the file system.
239
- * @param sender The optional sender address to use this signer for (aka a rekeyed account)
240
- * @returns The account
241
- */
242
- fromMnemonic(mnemonicSecret, sender) {
243
- const account = algosdk.mnemonicToSecretKey(mnemonicSecret);
244
- return this.signerAccount(new SigningAccount(account, sender));
245
- }
246
- /**
247
- * Tracks and returns an Algorand account that is a rekeyed version of the given account to a new sender.
248
- *
249
- * @example
250
- * ```typescript
251
- * const account = accountManager.fromMnemonic("mnemonic secret ...")
252
- * const rekeyedAccount = accountManager.rekeyed(account, "SENDERADDRESS...")
253
- * ```
254
- * @param account The account to use as the signer for this new rekeyed account
255
- * @param sender The sender address to use as the new sender
256
- * @returns The account
257
- */
258
- rekeyed(sender, account) {
259
- return this.signerAccount({ addr: address(sender), signer: account.signer });
260
- }
261
- /**
262
- * Tracks and returns an Algorand account with private key loaded by convention from environment variables based on the given name identifier.
263
- *
264
- * Note: This function expects to run in a Node.js environment.
265
- *
266
- * ## Convention:
267
- * * **Non-LocalNet:** will load process.env['\{NAME\}_MNEMONIC'] as a mnemonic secret; **Note: Be careful how the mnemonic is handled**,
268
- * never commit it into source control and ideally load it via a secret storage service rather than the file system.
269
- * If process.env['\{NAME\}_SENDER'] is defined then it will use that for the sender address (i.e. to support rekeyed accounts)
270
- * * **LocalNet:** will load the account from a KMD wallet called \{NAME\} and if that wallet doesn't exist it will create it and fund the account for you
271
- *
272
- * This allows you to write code that will work seamlessly in production and local development (LocalNet) without manual config locally (including when you reset the LocalNet).
273
- *
274
- * @example Default
275
- *
276
- * If you have a mnemonic secret loaded into `process.env.MY_ACCOUNT_MNEMONIC` then you can call the following to get that private key loaded into an account object:
277
- * ```typescript
278
- * const account = await accountManager.fromEnvironment('MY_ACCOUNT')
279
- * ```
280
- *
281
- * If that code runs against LocalNet then a wallet called `MY_ACCOUNT` will automatically be created with an account that is automatically funded with 1000 (default) ALGO from the default LocalNet dispenser.
282
- * If not running against LocalNet then it will use proces.env.MY_ACCOUNT_MNEMONIC as the private key and (if present) process.env.MY_ACCOUNT_SENDER as the sender address.
283
- *
284
- * @param name The name identifier of the account
285
- * @param fundWith The optional amount to fund the account with when it gets created (when targeting LocalNet), if not specified then 1000 ALGO will be funded from the dispenser account
286
- * @returns The account
287
- */
288
- async fromEnvironment(name, fundWith) {
289
- if (!process || !process.env) {
290
- throw new Error('Attempt to get account with private key from a non Node.js context; this is not supported!');
291
- }
292
- const accountMnemonic = process.env[`${name.toUpperCase()}_MNEMONIC`];
293
- const sender = process.env[`${name.toUpperCase()}_SENDER`];
294
- if (accountMnemonic) {
295
- const signer = algosdk.mnemonicToSecretKey(accountMnemonic);
296
- return this.signerAccount(new SigningAccount(signer, sender));
297
- }
298
- if (await this._clientManager.isLocalNet()) {
299
- const account = await this._kmdAccountManager.getOrCreateWalletAccount(name, fundWith);
300
- return this.signerAccount(account.account);
301
- }
302
- throw new Error(`Missing environment variable ${name.toUpperCase()}_MNEMONIC when looking for account ${name}`);
303
- }
304
- /**
305
- * Tracks and returns an Algorand account with private key loaded from the given KMD wallet (identified by name).
306
- *
307
- * @param name The name of the wallet to retrieve an account from
308
- * @param predicate An optional filter to use to find the account (otherwise it will return a random account from the wallet)
309
- * @param sender The optional sender address to use this signer for (aka a rekeyed account)
310
- * @example Get default funded account in a LocalNet
311
- *
312
- * ```typescript
313
- * const defaultDispenserAccount = await accountManager.fromKmd('unencrypted-default-wallet',
314
- * a => a.status !== 'Offline' && a.amount > 1_000_000_000
315
- * )
316
- * ```
317
- * @returns The account
318
- */
319
- async fromKmd(name,
320
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
321
- predicate, sender) {
322
- const account = await this._kmdAccountManager.getWalletAccount(name, predicate, sender);
323
- if (!account)
324
- throw new Error(`Unable to find KMD account ${name}${predicate ? ' with predicate' : ''}`);
325
- return this.signerAccount(account.account);
326
- }
327
- /**
328
- * Tracks and returns an account that supports partial or full multisig signing.
329
- *
330
- * @example
331
- * ```typescript
332
- * const account = accountManager.multisig({version: 1, threshold: 1, addrs: ["ADDRESS1...", "ADDRESS2..."]},
333
- * [(await accountManager.fromEnvironment('ACCOUNT1')).account])
334
- * ```
335
- * @param multisigParams The parameters that define the multisig account
336
- * @param signingAccounts The signers that are currently present
337
- * @returns A multisig account wrapper
338
- */
339
- multisig(multisigParams, signingAccounts) {
340
- return this.signerAccount(new MultisigAccount(multisigParams, signingAccounts));
341
- }
342
- /**
343
- * Tracks and returns an account that represents a logic signature.
344
- *
345
- * @example
346
- * ```typescript
347
- * const account = accountManager.logicsig(program, [new Uint8Array(3, ...)])
348
- * ```
349
- * @param program The bytes that make up the compiled logic signature
350
- * @param args The (binary) arguments to pass into the logic signature
351
- * @returns A logic signature account wrapper
352
- */
353
- logicsig(program, args) {
354
- return this.signerAccount(new LogicSigAccount(program, args));
355
- }
356
- /**
357
- * Tracks and returns a new, random Algorand account with secret key loaded.
358
- *
359
- * @example
360
- * ```typescript
361
- * const account = accountManager.random()
362
- * ```
363
- * @returns The account
364
- */
365
- random() {
366
- return this.signerAccount(algosdk.generateAccount());
367
- }
368
- /**
369
- * Returns an account (with private key loaded) that can act as a dispenser from
370
- * environment variables, or against default LocalNet if no environment variables present.
371
- *
372
- * Note: requires a Node.js environment to execute.
373
- *
374
- * If present, it will load the account mnemonic stored in process.env.DISPENSER_MNEMONIC and optionally
375
- * process.env.DISPENSER_SENDER if it's a rekeyed account.
376
- *
377
- * @example
378
- * ```typescript
379
- * const account = await accountManager.dispenserFromEnvironment()
380
- * ```
381
- *
382
- * @returns The account
383
- */
384
- async dispenserFromEnvironment() {
385
- if (!process || !process.env) {
386
- throw new Error('Attempt to get dispenser from environment from a non Node.js context; this is not supported!');
387
- }
388
- return process.env[`${DISPENSER_ACCOUNT.toUpperCase()}_MNEMONIC`]
389
- ? await this.fromEnvironment(DISPENSER_ACCOUNT)
390
- : await this.localNetDispenser();
391
- }
392
- /**
393
- * Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).
394
- *
395
- * @example
396
- * ```typescript
397
- * const account = await accountManager.localNetDispenser()
398
- * ```
399
- * @returns The account
400
- */
401
- async localNetDispenser() {
402
- const dispenser = await this._kmdAccountManager.getLocalNetDispenserAccount();
403
- return this.signerAccount(dispenser.account);
404
- }
405
- /**
406
- * Rekey an account to a new address.
407
- *
408
- * **Note:** Please be careful with this function and be sure to read the [official rekey guidance](https://dev.algorand.co/concepts/accounts/rekeying).
409
- *
410
- * @param account The account to rekey
411
- * @param rekeyTo The account address or signing account of the account that will be used to authorise transactions for the rekeyed account going forward.
412
- * If a signing account is provided that will now be tracked as the signer for `account` in this `AccountManager`
413
- * @param options Any parameters to control the transaction or execution of the transaction
414
- *
415
- * @example Basic example (with string addresses)
416
- * ```typescript
417
- * await accountManager.rekeyAccount({account: "ACCOUNTADDRESS", rekeyTo: "NEWADDRESS"})
418
- * ```
419
- * @example Basic example (with signer accounts)
420
- * ```typescript
421
- * await accountManager.rekeyAccount({account: account1, rekeyTo: newSignerAccount})
422
- * ```
423
- * @example Advanced example
424
- * ```typescript
425
- * await accountManager.rekeyAccount({
426
- * account: "ACCOUNTADDRESS",
427
- * rekeyTo: "NEWADDRESS",
428
- * lease: 'lease',
429
- * note: 'note',
430
- * firstValidRound: 1000n,
431
- * validityWindow: 10,
432
- * extraFee: (1000).microAlgo(),
433
- * staticFee: (1000).microAlgo(),
434
- * // Max fee doesn't make sense with extraFee AND staticFee
435
- * // already specified, but here for completeness
436
- * maxFee: (3000).microAlgo(),
437
- * maxRoundsToWaitForConfirmation: 5,
438
- * suppressLog: true,
439
- * })
440
- * ```
441
- * @returns The result of the transaction and the transaction that was sent
442
- */
443
- async rekeyAccount(account, rekeyTo, options) {
444
- const result = await this._getComposer()
445
- .addPayment({
446
- ...options,
447
- sender: address(account),
448
- receiver: address(account),
449
- amount: AlgoAmount.MicroAlgo(0),
450
- rekeyTo: address(typeof rekeyTo === 'object' && 'addr' in rekeyTo ? rekeyTo.addr : rekeyTo),
451
- })
452
- .send(options);
453
- // If the rekey is a signing account set it as the signer for this account
454
- if (typeof rekeyTo === 'object' && 'addr' in rekeyTo) {
455
- this.rekeyed(account, rekeyTo);
456
- }
457
- Config.getLogger(options?.suppressLog).info(`Rekeyed ${account} to ${rekeyTo} via transaction ${result.txIds.at(-1)}`);
458
- return { ...result, transaction: result.transactions.at(-1), confirmation: result.confirmations.at(-1) };
459
- }
460
- async _getEnsureFundedAmount(sender, minSpendingBalance, minFundingIncrement) {
461
- const accountInfo = await this.getInformation(sender);
462
- const currentSpendingBalance = accountInfo.balance.microAlgo - accountInfo.minBalance.microAlgo;
463
- const amountFunded = calculateFundAmount(minSpendingBalance.microAlgo, currentSpendingBalance, minFundingIncrement?.microAlgo ?? 0n);
464
- return amountFunded === null ? undefined : AlgoAmount.MicroAlgo(amountFunded);
465
- }
466
- /**
467
- * Funds a given account using a dispenser account as a funding source such that
468
- * the given account has a certain amount of Algo free to spend (accounting for
469
- * Algo locked in minimum balance requirement).
470
- *
471
- * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr
472
- *
473
- * @param accountToFund The account to fund
474
- * @param dispenserAccount The account to use as a dispenser funding source
475
- * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)
476
- * @param options Optional parameters to control the funding increment, transaction or execution of the transaction
477
- * @example Example using AlgorandClient
478
- * ```typescript
479
- * // Basic example
480
- * await accountManager.ensureFunded("ACCOUNTADDRESS", "DISPENSERADDRESS", algokit.algo(1))
481
- * // With configuration
482
- * await accountManager.ensureFunded("ACCOUNTADDRESS", "DISPENSERADDRESS", algokit.algo(1),
483
- * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }
484
- * )
485
- * ```
486
- * @returns
487
- * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.
488
- * - `undefined` if no funds were needed.
489
- */
490
- async ensureFunded(accountToFund, dispenserAccount, minSpendingBalance, options) {
491
- const addressToFund = address(accountToFund);
492
- const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement);
493
- if (!amountFunded)
494
- return undefined;
495
- const result = await this._getComposer()
496
- .addPayment({
497
- ...options,
498
- sender: address(dispenserAccount),
499
- receiver: addressToFund,
500
- amount: amountFunded,
501
- })
502
- .send(options);
503
- return {
504
- ...result,
505
- transaction: result.transactions[0],
506
- confirmation: result.confirmations[0],
507
- transactionId: result.txIds[0],
508
- amountFunded: amountFunded,
509
- };
510
- }
511
- /**
512
- * Funds a given account using a dispenser account retrieved from the environment,
513
- * per the `dispenserFromEnvironment` method, as a funding source such that
514
- * the given account has a certain amount of Algo free to spend (accounting for
515
- * Algo locked in minimum balance requirement).
516
- *
517
- * **Note:** requires a Node.js environment to execute.
518
- *
519
- * The dispenser account is retrieved from the account mnemonic stored in
520
- * process.env.DISPENSER_MNEMONIC and optionally process.env.DISPENSER_SENDER
521
- * if it's a rekeyed account, or against default LocalNet if no environment variables present.
522
- *
523
- * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr
524
- *
525
- * @param accountToFund The account to fund
526
- * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)
527
- * @param options Optional parameters to control the funding increment, transaction or execution of the transaction
528
- * @example Example using AlgorandClient
529
- * ```typescript
530
- * // Basic example
531
- * await accountManager.ensureFundedFromEnvironment("ACCOUNTADDRESS", algokit.algo(1))
532
- * // With configuration
533
- * await accountManager.ensureFundedFromEnvironment("ACCOUNTADDRESS", algokit.algo(1),
534
- * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }
535
- * )
536
- * ```
537
- * @returns
538
- * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.
539
- * - `undefined` if no funds were needed.
540
- */
541
- async ensureFundedFromEnvironment(accountToFund, minSpendingBalance, options) {
542
- const addressToFund = address(accountToFund);
543
- const dispenserAccount = await this.dispenserFromEnvironment();
544
- const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement);
545
- if (!amountFunded)
546
- return undefined;
547
- const result = await this._getComposer()
548
- .addPayment({
549
- ...options,
550
- sender: dispenserAccount,
551
- receiver: addressToFund,
552
- amount: amountFunded,
553
- })
554
- .send(options);
555
- return {
556
- ...result,
557
- transaction: result.transactions[0],
558
- confirmation: result.confirmations[0],
559
- transactionId: result.txIds[0],
560
- amountFunded: amountFunded,
561
- };
562
- }
563
- /**
564
- * Funds a given account using the TestNet Dispenser API as a funding source such that
565
- * the account has a certain amount of Algo free to spend (accounting for Algo locked
566
- * in minimum balance requirement).
567
- *
568
- * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr
569
- *
570
- * @param accountToFund The account to fund
571
- * @param dispenserClient The TestNet dispenser funding client
572
- * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)
573
- * @param options Optional parameters to control the funding increment, transaction or execution of the transaction
574
- * @example Example using AlgorandClient
575
- * ```typescript
576
- * // Basic example
577
- * await accountManager.ensureFundedFromTestNetDispenserApi("ACCOUNTADDRESS", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1))
578
- * // With configuration
579
- * await accountManager.ensureFundedFromTestNetDispenserApi("ACCOUNTADDRESS", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1),
580
- * { minFundingIncrement: algokit.algo(2) }
581
- * )
582
- * ```
583
- * @returns
584
- * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.
585
- * - `undefined` if no funds were needed.
586
- */
587
- async ensureFundedFromTestNetDispenserApi(accountToFund, dispenserClient, minSpendingBalance, options) {
588
- if (!(await this._clientManager.isTestNet())) {
589
- throw new Error('Attempt to fund using TestNet dispenser API on non TestNet network.');
590
- }
591
- const addressToFund = address(accountToFund);
592
- const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement);
593
- if (!amountFunded)
594
- return undefined;
595
- const result = await dispenserClient.fund(addressToFund, amountFunded.microAlgo);
596
- return {
597
- amountFunded: AlgoAmount.MicroAlgo(result.amount),
598
- transactionId: result.txId,
599
- };
600
- }
601
- }
602
-
25
+ var AccountManager = class {
26
+ _clientManager;
27
+ _kmdAccountManager;
28
+ _accounts = {};
29
+ _defaultSigner;
30
+ /**
31
+ * Create a new account manager.
32
+ * @param clientManager The ClientManager client to use for algod and kmd clients
33
+ * @example Create a new account manager
34
+ * ```typescript
35
+ * const accountManager = new AccountManager(clientManager)
36
+ * ```
37
+ */
38
+ constructor(clientManager) {
39
+ this._clientManager = clientManager;
40
+ this._kmdAccountManager = new KmdAccountManager(clientManager);
41
+ }
42
+ _getComposer(getSuggestedParams) {
43
+ return new TransactionComposer({
44
+ algod: this._clientManager.algod,
45
+ getSigner: this.getSigner.bind(this),
46
+ getSuggestedParams: getSuggestedParams ?? (() => this._clientManager.algod.getTransactionParams().do())
47
+ });
48
+ }
49
+ /**
50
+ * KMD account manager that allows you to easily get and create accounts using KMD.
51
+ * @returns The `KmdAccountManager` instance.
52
+ * @example
53
+ * ```typescript
54
+ * const kmdManager = accountManager.kmd;
55
+ * ```
56
+ */
57
+ get kmd() {
58
+ return this._kmdAccountManager;
59
+ }
60
+ /**
61
+ * Sets the default signer to use if no other signer is specified.
62
+ *
63
+ * If this isn't set an a transaction needs signing for a given sender
64
+ * then an error will be thrown from `getSigner` / `getAccount`.
65
+ * @param signer The signer to use, either a `TransactionSigner` or a `TransactionSignerAccount`
66
+ * @example
67
+ * ```typescript
68
+ * const signer = accountManager.random() // Can be anything that returns a `algosdk.TransactionSigner` or `TransactionSignerAccount`
69
+ * accountManager.setDefaultSigner(signer)
70
+ *
71
+ * // When signing a transaction, if there is no signer registered for the sender then the default signer will be used
72
+ * const signer = accountManager.getSigner("SENDERADDRESS")
73
+ * ```
74
+ * @returns The `AccountManager` so method calls can be chained
75
+ */
76
+ setDefaultSigner(signer) {
77
+ this._defaultSigner = "signer" in signer ? signer.signer : signer;
78
+ return this;
79
+ }
80
+ /**
81
+ * Records the given account (that can sign) against the address of the provided account for later
82
+ * retrieval and returns a `TransactionSignerAccount` along with the original account in an `account` property.
83
+ */
84
+ signerAccount(account) {
85
+ const signer = getAccountTransactionSigner(account);
86
+ const acc = {
87
+ addr: "addr" in account ? account.addr : account.address(),
88
+ signer
89
+ };
90
+ this._accounts[acc.addr.toString()] = acc;
91
+ const addressWithAccount = Address.fromString(acc.addr.toString());
92
+ addressWithAccount.account = account;
93
+ addressWithAccount.addr = acc.addr;
94
+ addressWithAccount.signer = signer;
95
+ return addressWithAccount;
96
+ }
97
+ /**
98
+ * Tracks the given account for later signing.
99
+ *
100
+ * Note: If you are generating accounts via the various methods on `AccountManager`
101
+ * (like `random`, `fromMnemonic`, `logicsig`, etc.) then they automatically get tracked.
102
+ * @param account The account to register, which can be a `TransactionSignerAccount` or
103
+ * a `algosdk.Account`, `algosdk.LogicSigAccount`, `SigningAccount` or `MultisigAccount`
104
+ * @example
105
+ * ```typescript
106
+ * const accountManager = new AccountManager(clientManager)
107
+ * .setSignerFromAccount(algosdk.generateAccount())
108
+ * .setSignerFromAccount(new algosdk.LogicSigAccount(program, args))
109
+ * .setSignerFromAccount(new SigningAccount(mnemonic, sender))
110
+ * .setSignerFromAccount(new MultisigAccount({version: 1, threshold: 1, addrs: ["ADDRESS1...", "ADDRESS2..."]}, [account1, account2]))
111
+ * .setSignerFromAccount({addr: "SENDERADDRESS", signer: transactionSigner})
112
+ * ```
113
+ * @returns The `AccountManager` instance for method chaining
114
+ */
115
+ setSignerFromAccount(account) {
116
+ this.signerAccount(account);
117
+ return this;
118
+ }
119
+ /**
120
+ * Tracks the given `algosdk.TransactionSigner` against the given sender address for later signing.
121
+ * @param sender The sender address to use this signer for
122
+ * @param signer The `algosdk.TransactionSigner` to sign transactions with for the given sender
123
+ * @example
124
+ * ```typescript
125
+ * const accountManager = new AccountManager(clientManager)
126
+ * .setSigner("SENDERADDRESS", transactionSigner)
127
+ * ```
128
+ * @returns The `AccountManager` instance for method chaining
129
+ */
130
+ setSigner(sender, signer) {
131
+ this._accounts[address(sender).toString()] = {
132
+ addr: address(sender),
133
+ signer
134
+ };
135
+ return this;
136
+ }
137
+ /**
138
+ * Takes all registered signers from the given `AccountManager` and adds them to this `AccountManager`.
139
+ *
140
+ * This is useful for situations where you have multiple contexts you are building accounts in such as unit tests.
141
+ * @param anotherAccountManager Another account manager with signers registered
142
+ * @param overwriteExisting Whether or not to overwrite any signers that have the same sender address with the ones in the other account manager or not (default: true)
143
+ * @returns The `AccountManager` instance for method chaining
144
+ * @example
145
+ * ```typescript
146
+ * accountManager2.setSigners(accountManager1);
147
+ * ```
148
+ */
149
+ setSigners(anotherAccountManager, overwriteExisting = true) {
150
+ this._accounts = overwriteExisting ? {
151
+ ...this._accounts,
152
+ ...anotherAccountManager._accounts
153
+ } : {
154
+ ...anotherAccountManager._accounts,
155
+ ...this._accounts
156
+ };
157
+ return this;
158
+ }
159
+ /**
160
+ * Returns the `TransactionSigner` for the given sender address, ready to sign a transaction for that sender.
161
+ *
162
+ * If no signer has been registered for that address then the default signer is used if registered and
163
+ * if not then an error is thrown.
164
+ *
165
+ * @param sender The sender address
166
+ * @example
167
+ * ```typescript
168
+ * const signer = accountManager.getSigner("SENDERADDRESS")
169
+ * ```
170
+ * @returns The `TransactionSigner` or throws an error if not found and no default signer is set
171
+ */
172
+ getSigner(sender) {
173
+ const signer = this._accounts[address(sender).toString()]?.signer ?? this._defaultSigner;
174
+ if (!signer) throw new Error(`No signer found for address ${sender}`);
175
+ return signer;
176
+ }
177
+ /**
178
+ * Returns the `TransactionSignerAccount` for the given sender address.
179
+ *
180
+ * If no signer has been registered for that address then an error is thrown.
181
+ * @param sender The sender address
182
+ * @example
183
+ * ```typescript
184
+ * const sender = accountManager.random()
185
+ * // ...
186
+ * // Returns the `TransactionSignerAccount` for `sender` that has previously been registered
187
+ * const account = accountManager.getAccount(sender)
188
+ * ```
189
+ * @returns The `TransactionSignerAccount` or throws an error if not found
190
+ */
191
+ getAccount(sender) {
192
+ const account = this._accounts[address(sender).toString()];
193
+ if (!account) throw new Error(`No signer found for address ${sender}`);
194
+ return account;
195
+ }
196
+ /**
197
+ * Returns the given sender account's current status, balance and spendable amounts.
198
+ *
199
+ * [Response data schema details](https://dev.algorand.co/reference/rest-api/algod/operations/accountinformation/)
200
+ * @example
201
+ * ```typescript
202
+ * const address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA";
203
+ * const accountInfo = await accountManager.getInformation(address);
204
+ * ```
205
+ *
206
+ * @param sender The account / address to look up
207
+ * @returns The account information
208
+ */
209
+ async getInformation(sender) {
210
+ const { round, lastHeartbeat = void 0, lastProposed = void 0, address, ...account } = await this._clientManager.algod.accountInformation(sender).do();
211
+ return {
212
+ ...account,
213
+ address: Address.fromString(address),
214
+ balance: AlgoAmount.MicroAlgo(Number(account.amount)),
215
+ amountWithoutPendingRewards: AlgoAmount.MicroAlgo(Number(account.amountWithoutPendingRewards)),
216
+ minBalance: AlgoAmount.MicroAlgo(Number(account.minBalance)),
217
+ pendingRewards: AlgoAmount.MicroAlgo(Number(account.pendingRewards)),
218
+ rewards: AlgoAmount.MicroAlgo(Number(account.rewards)),
219
+ validAsOfRound: BigInt(round),
220
+ totalAppsOptedIn: Number(account.totalAppsOptedIn),
221
+ totalAssetsOptedIn: Number(account.totalAssetsOptedIn),
222
+ totalCreatedApps: Number(account.totalCreatedApps),
223
+ totalCreatedAssets: Number(account.totalCreatedAssets),
224
+ appsTotalExtraPages: account.appsTotalExtraPages !== void 0 ? Number(account.appsTotalExtraPages) : void 0,
225
+ rewardBase: account.rewardBase !== void 0 ? Number(account.rewardBase) : void 0,
226
+ totalBoxBytes: account.totalBoxBytes !== void 0 ? Number(account.totalBoxBytes) : void 0,
227
+ totalBoxes: account.totalBoxes !== void 0 ? Number(account.totalBoxes) : void 0,
228
+ lastHeartbeatRound: lastHeartbeat !== void 0 ? BigInt(lastHeartbeat) : void 0,
229
+ lastProposedRound: lastProposed !== void 0 ? BigInt(lastProposed) : void 0
230
+ };
231
+ }
232
+ /**
233
+ * Tracks and returns an Algorand account with secret key loaded (i.e. that can sign transactions) by taking the mnemonic secret.
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * const account = accountManager.fromMnemonic("mnemonic secret ...")
238
+ * const rekeyedAccount = accountManager.fromMnemonic("mnemonic secret ...", "SENDERADDRESS...")
239
+ * ```
240
+ * @param mnemonicSecret The mnemonic secret representing the private key of an account; **Note: Be careful how the mnemonic is handled**,
241
+ * never commit it into source control and ideally load it from the environment (ideally via a secret storage service) rather than the file system.
242
+ * @param sender The optional sender address to use this signer for (aka a rekeyed account)
243
+ * @returns The account
244
+ */
245
+ fromMnemonic(mnemonicSecret, sender) {
246
+ const account = algosdk.mnemonicToSecretKey(mnemonicSecret);
247
+ return this.signerAccount(new SigningAccount(account, sender));
248
+ }
249
+ /**
250
+ * Tracks and returns an Algorand account that is a rekeyed version of the given account to a new sender.
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const account = accountManager.fromMnemonic("mnemonic secret ...")
255
+ * const rekeyedAccount = accountManager.rekeyed(account, "SENDERADDRESS...")
256
+ * ```
257
+ * @param account The account to use as the signer for this new rekeyed account
258
+ * @param sender The sender address to use as the new sender
259
+ * @returns The account
260
+ */
261
+ rekeyed(sender, account) {
262
+ return this.signerAccount({
263
+ addr: address(sender),
264
+ signer: account.signer
265
+ });
266
+ }
267
+ /**
268
+ * Tracks and returns an Algorand account with private key loaded by convention from environment variables based on the given name identifier.
269
+ *
270
+ * Note: This function expects to run in a Node.js environment.
271
+ *
272
+ * ## Convention:
273
+ * * **Non-LocalNet:** will load process.env['\{NAME\}_MNEMONIC'] as a mnemonic secret; **Note: Be careful how the mnemonic is handled**,
274
+ * never commit it into source control and ideally load it via a secret storage service rather than the file system.
275
+ * If process.env['\{NAME\}_SENDER'] is defined then it will use that for the sender address (i.e. to support rekeyed accounts)
276
+ * * **LocalNet:** will load the account from a KMD wallet called \{NAME\} and if that wallet doesn't exist it will create it and fund the account for you
277
+ *
278
+ * This allows you to write code that will work seamlessly in production and local development (LocalNet) without manual config locally (including when you reset the LocalNet).
279
+ *
280
+ * @example Default
281
+ *
282
+ * If you have a mnemonic secret loaded into `process.env.MY_ACCOUNT_MNEMONIC` then you can call the following to get that private key loaded into an account object:
283
+ * ```typescript
284
+ * const account = await accountManager.fromEnvironment('MY_ACCOUNT')
285
+ * ```
286
+ *
287
+ * If that code runs against LocalNet then a wallet called `MY_ACCOUNT` will automatically be created with an account that is automatically funded with 1000 (default) ALGO from the default LocalNet dispenser.
288
+ * If not running against LocalNet then it will use proces.env.MY_ACCOUNT_MNEMONIC as the private key and (if present) process.env.MY_ACCOUNT_SENDER as the sender address.
289
+ *
290
+ * @param name The name identifier of the account
291
+ * @param fundWith The optional amount to fund the account with when it gets created (when targeting LocalNet), if not specified then 1000 ALGO will be funded from the dispenser account
292
+ * @returns The account
293
+ */
294
+ async fromEnvironment(name, fundWith) {
295
+ if (!process || !process.env) throw new Error("Attempt to get account with private key from a non Node.js context; this is not supported!");
296
+ const accountMnemonic = process.env[`${name.toUpperCase()}_MNEMONIC`];
297
+ const sender = process.env[`${name.toUpperCase()}_SENDER`];
298
+ if (accountMnemonic) {
299
+ const signer = algosdk.mnemonicToSecretKey(accountMnemonic);
300
+ return this.signerAccount(new SigningAccount(signer, sender));
301
+ }
302
+ if (await this._clientManager.isLocalNet()) {
303
+ const account = await this._kmdAccountManager.getOrCreateWalletAccount(name, fundWith);
304
+ return this.signerAccount(account.account);
305
+ }
306
+ throw new Error(`Missing environment variable ${name.toUpperCase()}_MNEMONIC when looking for account ${name}`);
307
+ }
308
+ /**
309
+ * Tracks and returns an Algorand account with private key loaded from the given KMD wallet (identified by name).
310
+ *
311
+ * @param name The name of the wallet to retrieve an account from
312
+ * @param predicate An optional filter to use to find the account (otherwise it will return a random account from the wallet)
313
+ * @param sender The optional sender address to use this signer for (aka a rekeyed account)
314
+ * @example Get default funded account in a LocalNet
315
+ *
316
+ * ```typescript
317
+ * const defaultDispenserAccount = await accountManager.fromKmd('unencrypted-default-wallet',
318
+ * a => a.status !== 'Offline' && a.amount > 1_000_000_000
319
+ * )
320
+ * ```
321
+ * @returns The account
322
+ */
323
+ async fromKmd(name, predicate, sender) {
324
+ const account = await this._kmdAccountManager.getWalletAccount(name, predicate, sender);
325
+ if (!account) throw new Error(`Unable to find KMD account ${name}${predicate ? " with predicate" : ""}`);
326
+ return this.signerAccount(account.account);
327
+ }
328
+ /**
329
+ * Tracks and returns an account that supports partial or full multisig signing.
330
+ *
331
+ * @example
332
+ * ```typescript
333
+ * const account = accountManager.multisig({version: 1, threshold: 1, addrs: ["ADDRESS1...", "ADDRESS2..."]},
334
+ * [(await accountManager.fromEnvironment('ACCOUNT1')).account])
335
+ * ```
336
+ * @param multisigParams The parameters that define the multisig account
337
+ * @param signingAccounts The signers that are currently present
338
+ * @returns A multisig account wrapper
339
+ */
340
+ multisig(multisigParams, signingAccounts) {
341
+ return this.signerAccount(new MultisigAccount(multisigParams, signingAccounts));
342
+ }
343
+ /**
344
+ * Tracks and returns an account that represents a logic signature.
345
+ *
346
+ * @example
347
+ * ```typescript
348
+ * const account = accountManager.logicsig(program, [new Uint8Array(3, ...)])
349
+ * ```
350
+ * @param program The bytes that make up the compiled logic signature
351
+ * @param args The (binary) arguments to pass into the logic signature
352
+ * @returns A logic signature account wrapper
353
+ */
354
+ logicsig(program, args) {
355
+ return this.signerAccount(new LogicSigAccount(program, args));
356
+ }
357
+ /**
358
+ * Tracks and returns a new, random Algorand account with secret key loaded.
359
+ *
360
+ * @example
361
+ * ```typescript
362
+ * const account = accountManager.random()
363
+ * ```
364
+ * @returns The account
365
+ */
366
+ random() {
367
+ return this.signerAccount(algosdk.generateAccount());
368
+ }
369
+ /**
370
+ * Returns an account (with private key loaded) that can act as a dispenser from
371
+ * environment variables, or against default LocalNet if no environment variables present.
372
+ *
373
+ * Note: requires a Node.js environment to execute.
374
+ *
375
+ * If present, it will load the account mnemonic stored in process.env.DISPENSER_MNEMONIC and optionally
376
+ * process.env.DISPENSER_SENDER if it's a rekeyed account.
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * const account = await accountManager.dispenserFromEnvironment()
381
+ * ```
382
+ *
383
+ * @returns The account
384
+ */
385
+ async dispenserFromEnvironment() {
386
+ if (!process || !process.env) throw new Error("Attempt to get dispenser from environment from a non Node.js context; this is not supported!");
387
+ return process.env[`${"DISPENSER".toUpperCase()}_MNEMONIC`] ? await this.fromEnvironment(DISPENSER_ACCOUNT) : await this.localNetDispenser();
388
+ }
389
+ /**
390
+ * Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).
391
+ *
392
+ * @example
393
+ * ```typescript
394
+ * const account = await accountManager.localNetDispenser()
395
+ * ```
396
+ * @returns The account
397
+ */
398
+ async localNetDispenser() {
399
+ const dispenser = await this._kmdAccountManager.getLocalNetDispenserAccount();
400
+ return this.signerAccount(dispenser.account);
401
+ }
402
+ /**
403
+ * Rekey an account to a new address.
404
+ *
405
+ * **Note:** Please be careful with this function and be sure to read the [official rekey guidance](https://dev.algorand.co/concepts/accounts/rekeying).
406
+ *
407
+ * @param account The account to rekey
408
+ * @param rekeyTo The account address or signing account of the account that will be used to authorise transactions for the rekeyed account going forward.
409
+ * If a signing account is provided that will now be tracked as the signer for `account` in this `AccountManager`
410
+ * @param options Any parameters to control the transaction or execution of the transaction
411
+ *
412
+ * @example Basic example (with string addresses)
413
+ * ```typescript
414
+ * await accountManager.rekeyAccount({account: "ACCOUNTADDRESS", rekeyTo: "NEWADDRESS"})
415
+ * ```
416
+ * @example Basic example (with signer accounts)
417
+ * ```typescript
418
+ * await accountManager.rekeyAccount({account: account1, rekeyTo: newSignerAccount})
419
+ * ```
420
+ * @example Advanced example
421
+ * ```typescript
422
+ * await accountManager.rekeyAccount({
423
+ * account: "ACCOUNTADDRESS",
424
+ * rekeyTo: "NEWADDRESS",
425
+ * lease: 'lease',
426
+ * note: 'note',
427
+ * firstValidRound: 1000n,
428
+ * validityWindow: 10,
429
+ * extraFee: (1000).microAlgo(),
430
+ * staticFee: (1000).microAlgo(),
431
+ * // Max fee doesn't make sense with extraFee AND staticFee
432
+ * // already specified, but here for completeness
433
+ * maxFee: (3000).microAlgo(),
434
+ * maxRoundsToWaitForConfirmation: 5,
435
+ * suppressLog: true,
436
+ * })
437
+ * ```
438
+ * @returns The result of the transaction and the transaction that was sent
439
+ */
440
+ async rekeyAccount(account, rekeyTo, options) {
441
+ const result = await this._getComposer().addPayment({
442
+ ...options,
443
+ sender: address(account),
444
+ receiver: address(account),
445
+ amount: AlgoAmount.MicroAlgo(0),
446
+ rekeyTo: address(typeof rekeyTo === "object" && "addr" in rekeyTo ? rekeyTo.addr : rekeyTo)
447
+ }).send(options);
448
+ if (typeof rekeyTo === "object" && "addr" in rekeyTo) this.rekeyed(account, rekeyTo);
449
+ Config.getLogger(options?.suppressLog).info(`Rekeyed ${account} to ${rekeyTo} via transaction ${result.txIds.at(-1)}`);
450
+ return {
451
+ ...result,
452
+ transaction: result.transactions.at(-1),
453
+ confirmation: result.confirmations.at(-1)
454
+ };
455
+ }
456
+ async _getEnsureFundedAmount(sender, minSpendingBalance, minFundingIncrement) {
457
+ const accountInfo = await this.getInformation(sender);
458
+ const currentSpendingBalance = accountInfo.balance.microAlgo - accountInfo.minBalance.microAlgo;
459
+ const amountFunded = calculateFundAmount(minSpendingBalance.microAlgo, currentSpendingBalance, minFundingIncrement?.microAlgo ?? 0n);
460
+ return amountFunded === null ? void 0 : AlgoAmount.MicroAlgo(amountFunded);
461
+ }
462
+ /**
463
+ * Funds a given account using a dispenser account as a funding source such that
464
+ * the given account has a certain amount of Algo free to spend (accounting for
465
+ * Algo locked in minimum balance requirement).
466
+ *
467
+ * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr
468
+ *
469
+ * @param accountToFund The account to fund
470
+ * @param dispenserAccount The account to use as a dispenser funding source
471
+ * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)
472
+ * @param options Optional parameters to control the funding increment, transaction or execution of the transaction
473
+ * @example Example using AlgorandClient
474
+ * ```typescript
475
+ * // Basic example
476
+ * await accountManager.ensureFunded("ACCOUNTADDRESS", "DISPENSERADDRESS", algokit.algo(1))
477
+ * // With configuration
478
+ * await accountManager.ensureFunded("ACCOUNTADDRESS", "DISPENSERADDRESS", algokit.algo(1),
479
+ * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }
480
+ * )
481
+ * ```
482
+ * @returns
483
+ * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.
484
+ * - `undefined` if no funds were needed.
485
+ */
486
+ async ensureFunded(accountToFund, dispenserAccount, minSpendingBalance, options) {
487
+ const addressToFund = address(accountToFund);
488
+ const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement);
489
+ if (!amountFunded) return void 0;
490
+ const result = await this._getComposer().addPayment({
491
+ ...options,
492
+ sender: address(dispenserAccount),
493
+ receiver: addressToFund,
494
+ amount: amountFunded
495
+ }).send(options);
496
+ return {
497
+ ...result,
498
+ transaction: result.transactions[0],
499
+ confirmation: result.confirmations[0],
500
+ transactionId: result.txIds[0],
501
+ amountFunded
502
+ };
503
+ }
504
+ /**
505
+ * Funds a given account using a dispenser account retrieved from the environment,
506
+ * per the `dispenserFromEnvironment` method, as a funding source such that
507
+ * the given account has a certain amount of Algo free to spend (accounting for
508
+ * Algo locked in minimum balance requirement).
509
+ *
510
+ * **Note:** requires a Node.js environment to execute.
511
+ *
512
+ * The dispenser account is retrieved from the account mnemonic stored in
513
+ * process.env.DISPENSER_MNEMONIC and optionally process.env.DISPENSER_SENDER
514
+ * if it's a rekeyed account, or against default LocalNet if no environment variables present.
515
+ *
516
+ * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr
517
+ *
518
+ * @param accountToFund The account to fund
519
+ * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)
520
+ * @param options Optional parameters to control the funding increment, transaction or execution of the transaction
521
+ * @example Example using AlgorandClient
522
+ * ```typescript
523
+ * // Basic example
524
+ * await accountManager.ensureFundedFromEnvironment("ACCOUNTADDRESS", algokit.algo(1))
525
+ * // With configuration
526
+ * await accountManager.ensureFundedFromEnvironment("ACCOUNTADDRESS", algokit.algo(1),
527
+ * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }
528
+ * )
529
+ * ```
530
+ * @returns
531
+ * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.
532
+ * - `undefined` if no funds were needed.
533
+ */
534
+ async ensureFundedFromEnvironment(accountToFund, minSpendingBalance, options) {
535
+ const addressToFund = address(accountToFund);
536
+ const dispenserAccount = await this.dispenserFromEnvironment();
537
+ const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement);
538
+ if (!amountFunded) return void 0;
539
+ const result = await this._getComposer().addPayment({
540
+ ...options,
541
+ sender: dispenserAccount,
542
+ receiver: addressToFund,
543
+ amount: amountFunded
544
+ }).send(options);
545
+ return {
546
+ ...result,
547
+ transaction: result.transactions[0],
548
+ confirmation: result.confirmations[0],
549
+ transactionId: result.txIds[0],
550
+ amountFunded
551
+ };
552
+ }
553
+ /**
554
+ * Funds a given account using the TestNet Dispenser API as a funding source such that
555
+ * the account has a certain amount of Algo free to spend (accounting for Algo locked
556
+ * in minimum balance requirement).
557
+ *
558
+ * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr
559
+ *
560
+ * @param accountToFund The account to fund
561
+ * @param dispenserClient The TestNet dispenser funding client
562
+ * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)
563
+ * @param options Optional parameters to control the funding increment, transaction or execution of the transaction
564
+ * @example Example using AlgorandClient
565
+ * ```typescript
566
+ * // Basic example
567
+ * await accountManager.ensureFundedFromTestNetDispenserApi("ACCOUNTADDRESS", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1))
568
+ * // With configuration
569
+ * await accountManager.ensureFundedFromTestNetDispenserApi("ACCOUNTADDRESS", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1),
570
+ * { minFundingIncrement: algokit.algo(2) }
571
+ * )
572
+ * ```
573
+ * @returns
574
+ * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.
575
+ * - `undefined` if no funds were needed.
576
+ */
577
+ async ensureFundedFromTestNetDispenserApi(accountToFund, dispenserClient, minSpendingBalance, options) {
578
+ if (!await this._clientManager.isTestNet()) throw new Error("Attempt to fund using TestNet dispenser API on non TestNet network.");
579
+ const addressToFund = address(accountToFund);
580
+ const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement);
581
+ if (!amountFunded) return void 0;
582
+ const result = await dispenserClient.fund(addressToFund, amountFunded.microAlgo);
583
+ return {
584
+ amountFunded: AlgoAmount.MicroAlgo(result.amount),
585
+ transactionId: result.txId
586
+ };
587
+ }
588
+ };
589
+ //#endregion
603
590
  export { AccountManager, getAccountTransactionSigner };
604
- //# sourceMappingURL=account-manager.mjs.map
591
+
592
+ //# sourceMappingURL=account-manager.mjs.map