@algorandfoundation/algokit-utils 7.0.1 → 7.1.0

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 (49) hide show
  1. package/package.json +1 -1
  2. package/testing/fixtures/algorand-fixture.d.ts +19 -19
  3. package/testing/fixtures/algorand-fixture.js +7 -4
  4. package/testing/fixtures/algorand-fixture.js.map +1 -1
  5. package/testing/fixtures/algorand-fixture.mjs +7 -4
  6. package/testing/fixtures/algorand-fixture.mjs.map +1 -1
  7. package/testing/test-logger.js +7 -5
  8. package/testing/test-logger.js.map +1 -1
  9. package/testing/test-logger.mjs +7 -5
  10. package/testing/test-logger.mjs.map +1 -1
  11. package/testing/transaction-logger.js +4 -1
  12. package/testing/transaction-logger.js.map +1 -1
  13. package/testing/transaction-logger.mjs +4 -1
  14. package/testing/transaction-logger.mjs.map +1 -1
  15. package/transaction/transaction.js +4 -4
  16. package/transaction/transaction.js.map +1 -1
  17. package/transaction/transaction.mjs +5 -5
  18. package/transaction/transaction.mjs.map +1 -1
  19. package/types/algorand-client-transaction-sender.js +7 -1
  20. package/types/algorand-client-transaction-sender.js.map +1 -1
  21. package/types/algorand-client-transaction-sender.mjs +7 -1
  22. package/types/algorand-client-transaction-sender.mjs.map +1 -1
  23. package/types/app-client.d.ts +10 -6
  24. package/types/app-client.js +3 -3
  25. package/types/app-client.js.map +1 -1
  26. package/types/app-client.mjs +4 -4
  27. package/types/app-client.mjs.map +1 -1
  28. package/types/app-manager.d.ts +2 -2
  29. package/types/app-manager.js +2 -1
  30. package/types/app-manager.js.map +1 -1
  31. package/types/app-manager.mjs +2 -1
  32. package/types/app-manager.mjs.map +1 -1
  33. package/types/composer.js +2 -1
  34. package/types/composer.js.map +1 -1
  35. package/types/composer.mjs +2 -1
  36. package/types/composer.mjs.map +1 -1
  37. package/types/dispenser-client.js +3 -1
  38. package/types/dispenser-client.js.map +1 -1
  39. package/types/dispenser-client.mjs +3 -1
  40. package/types/dispenser-client.mjs.map +1 -1
  41. package/types/indexer.d.ts +47 -0
  42. package/types/indexer.js.map +1 -1
  43. package/types/indexer.mjs.map +1 -1
  44. package/types/testing.d.ts +44 -2
  45. package/util.d.ts +2 -0
  46. package/util.js +16 -0
  47. package/util.js.map +1 -1
  48. package/util.mjs +15 -1
  49. package/util.mjs.map +1 -1
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "**"
7
7
  ],
8
8
  "name": "@algorandfoundation/algokit-utils",
9
- "version": "7.0.1",
9
+ "version": "7.1.0",
10
10
  "private": false,
11
11
  "description": "A set of core Algorand utilities written in TypeScript and released via npm that make it easier to build solutions on Algorand.",
12
12
  "author": "Algorand Foundation",
@@ -8,29 +8,41 @@ import { AlgorandFixture, AlgorandFixtureConfig } from '../../types/testing';
8
8
  * and/or kmd (or their respective config) if you want to test against
9
9
  * an explicitly defined network.
10
10
  *
11
- * @example No config
11
+ * @example No config (per-test isolation)
12
12
  * ```typescript
13
- * const algorand = algorandFixture()
13
+ * const fixture = algorandFixture()
14
14
  *
15
- * beforeEach(algorand.beforeEach, 10_000)
15
+ * beforeEach(fixture.newScope, 10_000)
16
16
  *
17
17
  * test('My test', async () => {
18
- * const {algod, indexer, testAccount, ...} = algorand.context
18
+ * const {algod, indexer, testAccount, ...} = fixture.context
19
+ * // test things...
20
+ * })
21
+ * ```
22
+ *
23
+ * @example No config (test suite isolation)
24
+ * ```typescript
25
+ * const fixture = algorandFixture()
26
+ *
27
+ * beforeAll(fixture.newScope, 10_000)
28
+ *
29
+ * test('My test', async () => {
30
+ * const {algod, indexer, testAccount, ...} = fixture.context
19
31
  * // test things...
20
32
  * })
21
33
  * ```
22
34
  *
23
35
  * @example With config
24
36
  * ```typescript
25
- * const algorand = algorandFixture({
37
+ * const fixture = algorandFixture({
26
38
  * algod: new Algodv2('localhost', 12345, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
27
39
  * // ...
28
40
  * })
29
41
  *
30
- * beforeEach(algorand.beforeEach, 10_000)
42
+ * beforeEach(fixture.newScope, 10_000)
31
43
  *
32
44
  * test('My test', async () => {
33
- * const {algod, indexer, testAccount, ...} = algorand.context
45
+ * const {algod, indexer, testAccount, ...} = fixture.context
34
46
  * // test things...
35
47
  * })
36
48
  * ```
@@ -48,18 +60,6 @@ export declare function algorandFixture(fixtureConfig?: AlgorandFixtureConfig):
48
60
  * a default LocalNet instance, but you can pass in an algod, indexer
49
61
  * and/or kmd if you want to test against an explicitly defined network.
50
62
  *
51
- * @example
52
- * ```typescript
53
- * const algorand = algorandFixture(undefined, getConfigFromEnvOrDefaults())
54
- *
55
- * beforeEach(algorand.beforeEach, 10_000)
56
- *
57
- * test('My test', async () => {
58
- * const {algod, indexer, testAccount, ...} = algorand.context
59
- * // test things...
60
- * })
61
- * ```
62
- *
63
63
  * @param fixtureConfig The fixture configuration
64
64
  * @param config The fixture configuration
65
65
  * @returns The fixture
@@ -19,13 +19,13 @@ function algorandFixture(fixtureConfig, config$1) {
19
19
  const kmd = fixtureConfig.kmd ?? types_clientManager.ClientManager.getKmdClient(fixtureConfig.kmdConfig);
20
20
  let context;
21
21
  let algorand;
22
- const beforeEach = async () => {
22
+ const newScope = async () => {
23
23
  config.Config.configure({ debug: true });
24
24
  const transactionLogger$1 = new transactionLogger.TransactionLogger();
25
25
  const transactionLoggerAlgod = transactionLogger$1.capture(algod);
26
- algorand = types_algorandClient.AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer: indexer$1, kmd });
26
+ algorand = types_algorandClient.AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer: indexer$1, kmd }).setSuggestedParamsCacheTimeout(0);
27
27
  const acc = await account.getTestAccount({ initialFunds: fixtureConfig?.testAccountFunding ?? amount.algos(10), suppressLog: true }, algorand);
28
- algorand.setSignerFromAccount(acc).setSuggestedParamsCacheTimeout(0);
28
+ algorand.setSignerFromAccount(acc);
29
29
  // If running against LocalNet we are likely in dev mode and we need to set a much higher validity window
30
30
  // otherwise we are more likely to get invalid transactions.
31
31
  if (await algorand.client.isLocalNet()) {
@@ -50,12 +50,15 @@ function algorandFixture(fixtureConfig, config$1) {
50
50
  };
51
51
  return {
52
52
  get context() {
53
+ if (!context)
54
+ throw new Error('Context not initialised; make sure to call fixture.newScope() before accessing context.');
53
55
  return context;
54
56
  },
55
57
  get algorand() {
56
58
  return algorand;
57
59
  },
58
- beforeEach,
60
+ beforeEach: newScope,
61
+ newScope,
59
62
  };
60
63
  }
61
64
 
@@ -1 +1 @@
1
- {"version":3,"file":"algorand-fixture.js","sources":["../../../src/testing/fixtures/algorand-fixture.ts"],"sourcesContent":["import { algos, Config, lookupTransactionById } from '../../'\nimport { AlgorandClient } from '../../types/algorand-client'\nimport { ClientManager } from '../../types/client-manager'\nimport { AlgoConfig } from '../../types/network-client'\nimport { AlgorandFixture, AlgorandFixtureConfig, AlgorandTestAutomationContext, GetTestAccountParams } from '../../types/testing'\nimport { getTestAccount } from '../account'\nimport { runWhenIndexerCaughtUp } from '../indexer'\nimport { TransactionLogger } from '../transaction-logger'\n\n/**\n * Creates a test fixture for automated testing against Algorand.\n * By default it tests against an environment variable specified client\n * if the standard environment variables are specified, otherwise against\n * a default LocalNet instance, but you can pass in an algod, indexer\n * and/or kmd (or their respective config) if you want to test against\n * an explicitly defined network.\n *\n * @example No config\n * ```typescript\n * const algorand = algorandFixture()\n *\n * beforeEach(algorand.beforeEach, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = algorand.context\n * // test things...\n * })\n * ```\n *\n * @example With config\n * ```typescript\n * const algorand = algorandFixture({\n * algod: new Algodv2('localhost', 12345, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),\n * // ...\n * })\n *\n * beforeEach(algorand.beforeEach, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = algorand.context\n * // test things...\n * })\n * ```\n *\n * @param fixtureConfig The fixture configuration\n * @returns The fixture\n */\nexport function algorandFixture(fixtureConfig?: AlgorandFixtureConfig): AlgorandFixture\n\n/**\n * @deprecated Config can be passed in directly to fixture config now.\n *\n * Creates a test fixture for automated testing against Algorand.\n * By default it tests against an environment variable specified client\n * if the standard environment variables are specified, otherwise against\n * a default LocalNet instance, but you can pass in an algod, indexer\n * and/or kmd if you want to test against an explicitly defined network.\n *\n * @example\n * ```typescript\n * const algorand = algorandFixture(undefined, getConfigFromEnvOrDefaults())\n *\n * beforeEach(algorand.beforeEach, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = algorand.context\n * // test things...\n * })\n * ```\n *\n * @param fixtureConfig The fixture configuration\n * @param config The fixture configuration\n * @returns The fixture\n */\nexport function algorandFixture(fixtureConfig: AlgorandFixtureConfig | undefined, config: AlgoConfig): AlgorandFixture\n\nexport function algorandFixture(fixtureConfig?: AlgorandFixtureConfig, config?: AlgoConfig): AlgorandFixture {\n fixtureConfig = { ...fixtureConfig, ...config }\n if (!fixtureConfig.algod || !fixtureConfig.indexer || !fixtureConfig.kmd) {\n fixtureConfig = { ...ClientManager.getConfigFromEnvironmentOrLocalNet(), ...fixtureConfig }\n }\n\n const algod = fixtureConfig.algod ?? ClientManager.getAlgodClient(fixtureConfig.algodConfig!)\n const indexer = fixtureConfig.indexer ?? ClientManager.getIndexerClient(fixtureConfig.indexerConfig!)\n const kmd = fixtureConfig.kmd ?? ClientManager.getKmdClient(fixtureConfig.kmdConfig!)\n let context: AlgorandTestAutomationContext\n let algorand: AlgorandClient\n\n const beforeEach = async () => {\n Config.configure({ debug: true })\n const transactionLogger = new TransactionLogger()\n const transactionLoggerAlgod = transactionLogger.capture(algod)\n algorand = AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer, kmd })\n const acc = await getTestAccount({ initialFunds: fixtureConfig?.testAccountFunding ?? algos(10), suppressLog: true }, algorand)\n algorand.setSignerFromAccount(acc).setSuggestedParamsCacheTimeout(0)\n // If running against LocalNet we are likely in dev mode and we need to set a much higher validity window\n // otherwise we are more likely to get invalid transactions.\n if (await algorand.client.isLocalNet()) {\n algorand.setDefaultValidityWindow(1000)\n }\n const testAccount = { ...acc, signer: algorand.account.getSigner(acc.addr) }\n context = {\n algorand,\n algod: transactionLoggerAlgod,\n indexer: indexer,\n kmd: kmd,\n testAccount,\n generateAccount: async (params: GetTestAccountParams) => {\n const account = await getTestAccount(params, algorand)\n algorand.setSignerFromAccount(account)\n return { ...account, signer: algorand.account.getSigner(account.addr) }\n },\n transactionLogger: transactionLogger,\n waitForIndexer: () => transactionLogger.waitForIndexer(indexer),\n waitForIndexerTransaction: (transactionId: string) => runWhenIndexerCaughtUp(() => lookupTransactionById(transactionId, indexer)),\n }\n }\n\n return {\n get context() {\n return context\n },\n get algorand() {\n return algorand\n },\n beforeEach,\n }\n}\n"],"names":["config","ClientManager","indexer","Config","transactionLogger","TransactionLogger","AlgorandClient","getTestAccount","algos","account","runWhenIndexerCaughtUp","lookupTransactionById"],"mappings":";;;;;;;;;;;AA4EgB,SAAA,eAAe,CAAC,aAAqC,EAAEA,QAAmB,EAAA;IACxF,aAAa,GAAG,EAAE,GAAG,aAAa,EAAE,GAAGA,QAAM,EAAE;AAC/C,IAAA,IAAI,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE;QACxE,aAAa,GAAG,EAAE,GAAGC,iCAAa,CAAC,kCAAkC,EAAE,EAAE,GAAG,aAAa,EAAE;;AAG7F,IAAA,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,IAAIA,iCAAa,CAAC,cAAc,CAAC,aAAa,CAAC,WAAY,CAAC;AAC7F,IAAA,MAAMC,SAAO,GAAG,aAAa,CAAC,OAAO,IAAID,iCAAa,CAAC,gBAAgB,CAAC,aAAa,CAAC,aAAc,CAAC;AACrG,IAAA,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,IAAIA,iCAAa,CAAC,YAAY,CAAC,aAAa,CAAC,SAAU,CAAC;AACrF,IAAA,IAAI,OAAsC;AAC1C,IAAA,IAAI,QAAwB;AAE5B,IAAA,MAAM,UAAU,GAAG,YAAW;QAC5BE,aAAM,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACjC,QAAA,MAAMC,mBAAiB,GAAG,IAAIC,mCAAiB,EAAE;QACjD,MAAM,sBAAsB,GAAGD,mBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC;AAC/D,QAAA,QAAQ,GAAGE,mCAAc,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,sBAAsB,WAAEJ,SAAO,EAAE,GAAG,EAAE,CAAC;QACtF,MAAM,GAAG,GAAG,MAAMK,sBAAc,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,IAAIC,YAAK,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC;QAC/H,QAAQ,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC;;;QAGpE,IAAI,MAAM,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE;AACtC,YAAA,QAAQ,CAAC,wBAAwB,CAAC,IAAI,CAAC;;AAEzC,QAAA,MAAM,WAAW,GAAG,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC5E,QAAA,OAAO,GAAG;YACR,QAAQ;AACR,YAAA,KAAK,EAAE,sBAAsB;AAC7B,YAAA,OAAO,EAAEN,SAAO;AAChB,YAAA,GAAG,EAAE,GAAG;YACR,WAAW;AACX,YAAA,eAAe,EAAE,OAAO,MAA4B,KAAI;gBACtD,MAAMO,SAAO,GAAG,MAAMF,sBAAc,CAAC,MAAM,EAAE,QAAQ,CAAC;AACtD,gBAAA,QAAQ,CAAC,oBAAoB,CAACE,SAAO,CAAC;AACtC,gBAAA,OAAO,EAAE,GAAGA,SAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS,CAACA,SAAO,CAAC,IAAI,CAAC,EAAE;aACxE;AACD,YAAA,iBAAiB,EAAEL,mBAAiB;YACpC,cAAc,EAAE,MAAMA,mBAAiB,CAAC,cAAc,CAACF,SAAO,CAAC;AAC/D,YAAA,yBAAyB,EAAE,CAAC,aAAqB,KAAKQ,8BAAsB,CAAC,MAAMC,mCAAqB,CAAC,aAAa,EAAET,SAAO,CAAC,CAAC;SAClI;AACH,KAAC;IAED,OAAO;AACL,QAAA,IAAI,OAAO,GAAA;AACT,YAAA,OAAO,OAAO;SACf;AACD,QAAA,IAAI,QAAQ,GAAA;AACV,YAAA,OAAO,QAAQ;SAChB;QACD,UAAU;KACX;AACH;;;;"}
1
+ {"version":3,"file":"algorand-fixture.js","sources":["../../../src/testing/fixtures/algorand-fixture.ts"],"sourcesContent":["import { algos, Config, lookupTransactionById } from '../../'\nimport { AlgorandClient } from '../../types/algorand-client'\nimport { ClientManager } from '../../types/client-manager'\nimport { AlgoConfig } from '../../types/network-client'\nimport { AlgorandFixture, AlgorandFixtureConfig, AlgorandTestAutomationContext, GetTestAccountParams } from '../../types/testing'\nimport { getTestAccount } from '../account'\nimport { runWhenIndexerCaughtUp } from '../indexer'\nimport { TransactionLogger } from '../transaction-logger'\n\n/**\n * Creates a test fixture for automated testing against Algorand.\n * By default it tests against an environment variable specified client\n * if the standard environment variables are specified, otherwise against\n * a default LocalNet instance, but you can pass in an algod, indexer\n * and/or kmd (or their respective config) if you want to test against\n * an explicitly defined network.\n *\n * @example No config (per-test isolation)\n * ```typescript\n * const fixture = algorandFixture()\n *\n * beforeEach(fixture.newScope, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = fixture.context\n * // test things...\n * })\n * ```\n *\n * @example No config (test suite isolation)\n * ```typescript\n * const fixture = algorandFixture()\n *\n * beforeAll(fixture.newScope, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = fixture.context\n * // test things...\n * })\n * ```\n *\n * @example With config\n * ```typescript\n * const fixture = algorandFixture({\n * algod: new Algodv2('localhost', 12345, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),\n * // ...\n * })\n *\n * beforeEach(fixture.newScope, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = fixture.context\n * // test things...\n * })\n * ```\n *\n * @param fixtureConfig The fixture configuration\n * @returns The fixture\n */\nexport function algorandFixture(fixtureConfig?: AlgorandFixtureConfig): AlgorandFixture\n\n/**\n * @deprecated Config can be passed in directly to fixture config now.\n *\n * Creates a test fixture for automated testing against Algorand.\n * By default it tests against an environment variable specified client\n * if the standard environment variables are specified, otherwise against\n * a default LocalNet instance, but you can pass in an algod, indexer\n * and/or kmd if you want to test against an explicitly defined network.\n *\n * @param fixtureConfig The fixture configuration\n * @param config The fixture configuration\n * @returns The fixture\n */\nexport function algorandFixture(fixtureConfig: AlgorandFixtureConfig | undefined, config: AlgoConfig): AlgorandFixture\n\nexport function algorandFixture(fixtureConfig?: AlgorandFixtureConfig, config?: AlgoConfig): AlgorandFixture {\n fixtureConfig = { ...fixtureConfig, ...config }\n if (!fixtureConfig.algod || !fixtureConfig.indexer || !fixtureConfig.kmd) {\n fixtureConfig = { ...ClientManager.getConfigFromEnvironmentOrLocalNet(), ...fixtureConfig }\n }\n\n const algod = fixtureConfig.algod ?? ClientManager.getAlgodClient(fixtureConfig.algodConfig!)\n const indexer = fixtureConfig.indexer ?? ClientManager.getIndexerClient(fixtureConfig.indexerConfig!)\n const kmd = fixtureConfig.kmd ?? ClientManager.getKmdClient(fixtureConfig.kmdConfig!)\n let context: AlgorandTestAutomationContext\n let algorand: AlgorandClient\n\n const newScope = async () => {\n Config.configure({ debug: true })\n const transactionLogger = new TransactionLogger()\n const transactionLoggerAlgod = transactionLogger.capture(algod)\n algorand = AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer, kmd }).setSuggestedParamsCacheTimeout(0)\n\n const acc = await getTestAccount({ initialFunds: fixtureConfig?.testAccountFunding ?? algos(10), suppressLog: true }, algorand)\n algorand.setSignerFromAccount(acc)\n // If running against LocalNet we are likely in dev mode and we need to set a much higher validity window\n // otherwise we are more likely to get invalid transactions.\n if (await algorand.client.isLocalNet()) {\n algorand.setDefaultValidityWindow(1000)\n }\n const testAccount = { ...acc, signer: algorand.account.getSigner(acc.addr) }\n context = {\n algorand,\n algod: transactionLoggerAlgod,\n indexer: indexer,\n kmd: kmd,\n testAccount,\n generateAccount: async (params: GetTestAccountParams) => {\n const account = await getTestAccount(params, algorand)\n algorand.setSignerFromAccount(account)\n return { ...account, signer: algorand.account.getSigner(account.addr) }\n },\n transactionLogger: transactionLogger,\n waitForIndexer: () => transactionLogger.waitForIndexer(indexer),\n waitForIndexerTransaction: (transactionId: string) => runWhenIndexerCaughtUp(() => lookupTransactionById(transactionId, indexer)),\n }\n }\n\n return {\n get context() {\n if (!context) throw new Error('Context not initialised; make sure to call fixture.newScope() before accessing context.')\n return context\n },\n get algorand() {\n return algorand\n },\n beforeEach: newScope,\n newScope,\n }\n}\n"],"names":["config","ClientManager","indexer","Config","transactionLogger","TransactionLogger","AlgorandClient","getTestAccount","algos","account","runWhenIndexerCaughtUp","lookupTransactionById"],"mappings":"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"}
@@ -17,13 +17,13 @@ function algorandFixture(fixtureConfig, config) {
17
17
  const kmd = fixtureConfig.kmd ?? ClientManager.getKmdClient(fixtureConfig.kmdConfig);
18
18
  let context;
19
19
  let algorand;
20
- const beforeEach = async () => {
20
+ const newScope = async () => {
21
21
  Config.configure({ debug: true });
22
22
  const transactionLogger = new TransactionLogger();
23
23
  const transactionLoggerAlgod = transactionLogger.capture(algod);
24
- algorand = AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer, kmd });
24
+ algorand = AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer, kmd }).setSuggestedParamsCacheTimeout(0);
25
25
  const acc = await getTestAccount({ initialFunds: fixtureConfig?.testAccountFunding ?? algos(10), suppressLog: true }, algorand);
26
- algorand.setSignerFromAccount(acc).setSuggestedParamsCacheTimeout(0);
26
+ algorand.setSignerFromAccount(acc);
27
27
  // If running against LocalNet we are likely in dev mode and we need to set a much higher validity window
28
28
  // otherwise we are more likely to get invalid transactions.
29
29
  if (await algorand.client.isLocalNet()) {
@@ -48,12 +48,15 @@ function algorandFixture(fixtureConfig, config) {
48
48
  };
49
49
  return {
50
50
  get context() {
51
+ if (!context)
52
+ throw new Error('Context not initialised; make sure to call fixture.newScope() before accessing context.');
51
53
  return context;
52
54
  },
53
55
  get algorand() {
54
56
  return algorand;
55
57
  },
56
- beforeEach,
58
+ beforeEach: newScope,
59
+ newScope,
57
60
  };
58
61
  }
59
62
 
@@ -1 +1 @@
1
- {"version":3,"file":"algorand-fixture.mjs","sources":["../../../src/testing/fixtures/algorand-fixture.ts"],"sourcesContent":["import { algos, Config, lookupTransactionById } from '../../'\nimport { AlgorandClient } from '../../types/algorand-client'\nimport { ClientManager } from '../../types/client-manager'\nimport { AlgoConfig } from '../../types/network-client'\nimport { AlgorandFixture, AlgorandFixtureConfig, AlgorandTestAutomationContext, GetTestAccountParams } from '../../types/testing'\nimport { getTestAccount } from '../account'\nimport { runWhenIndexerCaughtUp } from '../indexer'\nimport { TransactionLogger } from '../transaction-logger'\n\n/**\n * Creates a test fixture for automated testing against Algorand.\n * By default it tests against an environment variable specified client\n * if the standard environment variables are specified, otherwise against\n * a default LocalNet instance, but you can pass in an algod, indexer\n * and/or kmd (or their respective config) if you want to test against\n * an explicitly defined network.\n *\n * @example No config\n * ```typescript\n * const algorand = algorandFixture()\n *\n * beforeEach(algorand.beforeEach, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = algorand.context\n * // test things...\n * })\n * ```\n *\n * @example With config\n * ```typescript\n * const algorand = algorandFixture({\n * algod: new Algodv2('localhost', 12345, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),\n * // ...\n * })\n *\n * beforeEach(algorand.beforeEach, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = algorand.context\n * // test things...\n * })\n * ```\n *\n * @param fixtureConfig The fixture configuration\n * @returns The fixture\n */\nexport function algorandFixture(fixtureConfig?: AlgorandFixtureConfig): AlgorandFixture\n\n/**\n * @deprecated Config can be passed in directly to fixture config now.\n *\n * Creates a test fixture for automated testing against Algorand.\n * By default it tests against an environment variable specified client\n * if the standard environment variables are specified, otherwise against\n * a default LocalNet instance, but you can pass in an algod, indexer\n * and/or kmd if you want to test against an explicitly defined network.\n *\n * @example\n * ```typescript\n * const algorand = algorandFixture(undefined, getConfigFromEnvOrDefaults())\n *\n * beforeEach(algorand.beforeEach, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = algorand.context\n * // test things...\n * })\n * ```\n *\n * @param fixtureConfig The fixture configuration\n * @param config The fixture configuration\n * @returns The fixture\n */\nexport function algorandFixture(fixtureConfig: AlgorandFixtureConfig | undefined, config: AlgoConfig): AlgorandFixture\n\nexport function algorandFixture(fixtureConfig?: AlgorandFixtureConfig, config?: AlgoConfig): AlgorandFixture {\n fixtureConfig = { ...fixtureConfig, ...config }\n if (!fixtureConfig.algod || !fixtureConfig.indexer || !fixtureConfig.kmd) {\n fixtureConfig = { ...ClientManager.getConfigFromEnvironmentOrLocalNet(), ...fixtureConfig }\n }\n\n const algod = fixtureConfig.algod ?? ClientManager.getAlgodClient(fixtureConfig.algodConfig!)\n const indexer = fixtureConfig.indexer ?? ClientManager.getIndexerClient(fixtureConfig.indexerConfig!)\n const kmd = fixtureConfig.kmd ?? ClientManager.getKmdClient(fixtureConfig.kmdConfig!)\n let context: AlgorandTestAutomationContext\n let algorand: AlgorandClient\n\n const beforeEach = async () => {\n Config.configure({ debug: true })\n const transactionLogger = new TransactionLogger()\n const transactionLoggerAlgod = transactionLogger.capture(algod)\n algorand = AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer, kmd })\n const acc = await getTestAccount({ initialFunds: fixtureConfig?.testAccountFunding ?? algos(10), suppressLog: true }, algorand)\n algorand.setSignerFromAccount(acc).setSuggestedParamsCacheTimeout(0)\n // If running against LocalNet we are likely in dev mode and we need to set a much higher validity window\n // otherwise we are more likely to get invalid transactions.\n if (await algorand.client.isLocalNet()) {\n algorand.setDefaultValidityWindow(1000)\n }\n const testAccount = { ...acc, signer: algorand.account.getSigner(acc.addr) }\n context = {\n algorand,\n algod: transactionLoggerAlgod,\n indexer: indexer,\n kmd: kmd,\n testAccount,\n generateAccount: async (params: GetTestAccountParams) => {\n const account = await getTestAccount(params, algorand)\n algorand.setSignerFromAccount(account)\n return { ...account, signer: algorand.account.getSigner(account.addr) }\n },\n transactionLogger: transactionLogger,\n waitForIndexer: () => transactionLogger.waitForIndexer(indexer),\n waitForIndexerTransaction: (transactionId: string) => runWhenIndexerCaughtUp(() => lookupTransactionById(transactionId, indexer)),\n }\n }\n\n return {\n get context() {\n return context\n },\n get algorand() {\n return algorand\n },\n beforeEach,\n }\n}\n"],"names":[],"mappings":";;;;;;;;;AA4EgB,SAAA,eAAe,CAAC,aAAqC,EAAE,MAAmB,EAAA;IACxF,aAAa,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE;AAC/C,IAAA,IAAI,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE;QACxE,aAAa,GAAG,EAAE,GAAG,aAAa,CAAC,kCAAkC,EAAE,EAAE,GAAG,aAAa,EAAE;;AAG7F,IAAA,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,cAAc,CAAC,aAAa,CAAC,WAAY,CAAC;AAC7F,IAAA,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,aAAa,CAAC,gBAAgB,CAAC,aAAa,CAAC,aAAc,CAAC;AACrG,IAAA,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,IAAI,aAAa,CAAC,YAAY,CAAC,aAAa,CAAC,SAAU,CAAC;AACrF,IAAA,IAAI,OAAsC;AAC1C,IAAA,IAAI,QAAwB;AAE5B,IAAA,MAAM,UAAU,GAAG,YAAW;QAC5B,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACjC,QAAA,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAE;QACjD,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC;AAC/D,QAAA,QAAQ,GAAG,cAAc,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC;QAC/H,QAAQ,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC;;;QAGpE,IAAI,MAAM,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE;AACtC,YAAA,QAAQ,CAAC,wBAAwB,CAAC,IAAI,CAAC;;AAEzC,QAAA,MAAM,WAAW,GAAG,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC5E,QAAA,OAAO,GAAG;YACR,QAAQ;AACR,YAAA,KAAK,EAAE,sBAAsB;AAC7B,YAAA,OAAO,EAAE,OAAO;AAChB,YAAA,GAAG,EAAE,GAAG;YACR,WAAW;AACX,YAAA,eAAe,EAAE,OAAO,MAA4B,KAAI;gBACtD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC;AACtD,gBAAA,QAAQ,CAAC,oBAAoB,CAAC,OAAO,CAAC;AACtC,gBAAA,OAAO,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;aACxE;AACD,YAAA,iBAAiB,EAAE,iBAAiB;YACpC,cAAc,EAAE,MAAM,iBAAiB,CAAC,cAAc,CAAC,OAAO,CAAC;AAC/D,YAAA,yBAAyB,EAAE,CAAC,aAAqB,KAAK,sBAAsB,CAAC,MAAM,qBAAqB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;SAClI;AACH,KAAC;IAED,OAAO;AACL,QAAA,IAAI,OAAO,GAAA;AACT,YAAA,OAAO,OAAO;SACf;AACD,QAAA,IAAI,QAAQ,GAAA;AACV,YAAA,OAAO,QAAQ;SAChB;QACD,UAAU;KACX;AACH;;;;"}
1
+ {"version":3,"file":"algorand-fixture.mjs","sources":["../../../src/testing/fixtures/algorand-fixture.ts"],"sourcesContent":["import { algos, Config, lookupTransactionById } from '../../'\nimport { AlgorandClient } from '../../types/algorand-client'\nimport { ClientManager } from '../../types/client-manager'\nimport { AlgoConfig } from '../../types/network-client'\nimport { AlgorandFixture, AlgorandFixtureConfig, AlgorandTestAutomationContext, GetTestAccountParams } from '../../types/testing'\nimport { getTestAccount } from '../account'\nimport { runWhenIndexerCaughtUp } from '../indexer'\nimport { TransactionLogger } from '../transaction-logger'\n\n/**\n * Creates a test fixture for automated testing against Algorand.\n * By default it tests against an environment variable specified client\n * if the standard environment variables are specified, otherwise against\n * a default LocalNet instance, but you can pass in an algod, indexer\n * and/or kmd (or their respective config) if you want to test against\n * an explicitly defined network.\n *\n * @example No config (per-test isolation)\n * ```typescript\n * const fixture = algorandFixture()\n *\n * beforeEach(fixture.newScope, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = fixture.context\n * // test things...\n * })\n * ```\n *\n * @example No config (test suite isolation)\n * ```typescript\n * const fixture = algorandFixture()\n *\n * beforeAll(fixture.newScope, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = fixture.context\n * // test things...\n * })\n * ```\n *\n * @example With config\n * ```typescript\n * const fixture = algorandFixture({\n * algod: new Algodv2('localhost', 12345, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),\n * // ...\n * })\n *\n * beforeEach(fixture.newScope, 10_000)\n *\n * test('My test', async () => {\n * const {algod, indexer, testAccount, ...} = fixture.context\n * // test things...\n * })\n * ```\n *\n * @param fixtureConfig The fixture configuration\n * @returns The fixture\n */\nexport function algorandFixture(fixtureConfig?: AlgorandFixtureConfig): AlgorandFixture\n\n/**\n * @deprecated Config can be passed in directly to fixture config now.\n *\n * Creates a test fixture for automated testing against Algorand.\n * By default it tests against an environment variable specified client\n * if the standard environment variables are specified, otherwise against\n * a default LocalNet instance, but you can pass in an algod, indexer\n * and/or kmd if you want to test against an explicitly defined network.\n *\n * @param fixtureConfig The fixture configuration\n * @param config The fixture configuration\n * @returns The fixture\n */\nexport function algorandFixture(fixtureConfig: AlgorandFixtureConfig | undefined, config: AlgoConfig): AlgorandFixture\n\nexport function algorandFixture(fixtureConfig?: AlgorandFixtureConfig, config?: AlgoConfig): AlgorandFixture {\n fixtureConfig = { ...fixtureConfig, ...config }\n if (!fixtureConfig.algod || !fixtureConfig.indexer || !fixtureConfig.kmd) {\n fixtureConfig = { ...ClientManager.getConfigFromEnvironmentOrLocalNet(), ...fixtureConfig }\n }\n\n const algod = fixtureConfig.algod ?? ClientManager.getAlgodClient(fixtureConfig.algodConfig!)\n const indexer = fixtureConfig.indexer ?? ClientManager.getIndexerClient(fixtureConfig.indexerConfig!)\n const kmd = fixtureConfig.kmd ?? ClientManager.getKmdClient(fixtureConfig.kmdConfig!)\n let context: AlgorandTestAutomationContext\n let algorand: AlgorandClient\n\n const newScope = async () => {\n Config.configure({ debug: true })\n const transactionLogger = new TransactionLogger()\n const transactionLoggerAlgod = transactionLogger.capture(algod)\n algorand = AlgorandClient.fromClients({ algod: transactionLoggerAlgod, indexer, kmd }).setSuggestedParamsCacheTimeout(0)\n\n const acc = await getTestAccount({ initialFunds: fixtureConfig?.testAccountFunding ?? algos(10), suppressLog: true }, algorand)\n algorand.setSignerFromAccount(acc)\n // If running against LocalNet we are likely in dev mode and we need to set a much higher validity window\n // otherwise we are more likely to get invalid transactions.\n if (await algorand.client.isLocalNet()) {\n algorand.setDefaultValidityWindow(1000)\n }\n const testAccount = { ...acc, signer: algorand.account.getSigner(acc.addr) }\n context = {\n algorand,\n algod: transactionLoggerAlgod,\n indexer: indexer,\n kmd: kmd,\n testAccount,\n generateAccount: async (params: GetTestAccountParams) => {\n const account = await getTestAccount(params, algorand)\n algorand.setSignerFromAccount(account)\n return { ...account, signer: algorand.account.getSigner(account.addr) }\n },\n transactionLogger: transactionLogger,\n waitForIndexer: () => transactionLogger.waitForIndexer(indexer),\n waitForIndexerTransaction: (transactionId: string) => runWhenIndexerCaughtUp(() => lookupTransactionById(transactionId, indexer)),\n }\n }\n\n return {\n get context() {\n if (!context) throw new Error('Context not initialised; make sure to call fixture.newScope() before accessing context.')\n return context\n },\n get algorand() {\n return algorand\n },\n beforeEach: newScope,\n newScope,\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var util = require('../util.js');
4
+
3
5
  /** Exposes an AlgoKit logger which captures log messages, while wrapping an original logger.
4
6
  * This is useful for automated testing.
5
7
  */
@@ -46,23 +48,23 @@ class TestLogger {
46
48
  }
47
49
  error(message, ...optionalParams) {
48
50
  this.originalLogger?.error(message, ...optionalParams);
49
- this.logs.push(`ERROR: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
51
+ this.logs.push(`ERROR: ${message}${optionalParams.length ? ` | ${util.asJson(optionalParams)}` : ''}`);
50
52
  }
51
53
  warn(message, ...optionalParams) {
52
54
  this.originalLogger?.warn(message, ...optionalParams);
53
- this.logs.push(`WARN: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
55
+ this.logs.push(`WARN: ${message}${optionalParams.length ? ` | ${util.asJson(optionalParams)}` : ''}`);
54
56
  }
55
57
  info(message, ...optionalParams) {
56
58
  this.originalLogger?.info(message, ...optionalParams);
57
- this.logs.push(`INFO: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
59
+ this.logs.push(`INFO: ${message}${optionalParams.length ? ` | ${util.asJson(optionalParams)}` : ''}`);
58
60
  }
59
61
  verbose(message, ...optionalParams) {
60
62
  this.originalLogger?.verbose(message, ...optionalParams);
61
- this.logs.push(`VERBOSE: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
63
+ this.logs.push(`VERBOSE: ${message}${optionalParams.length ? ` | ${util.asJson(optionalParams)}` : ''}`);
62
64
  }
63
65
  debug(message, ...optionalParams) {
64
66
  this.originalLogger?.debug(message, ...optionalParams);
65
- this.logs.push(`DEBUG: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
67
+ this.logs.push(`DEBUG: ${message}${optionalParams.length ? ` | ${util.asJson(optionalParams)}` : ''}`);
66
68
  }
67
69
  }
68
70
 
@@ -1 +1 @@
1
- {"version":3,"file":"test-logger.js","sources":["../../src/testing/test-logger.ts"],"sourcesContent":["import { Logger } from '../types/logging'\nimport { LogSnapshotConfig } from '../types/testing'\n\n/** Exposes an AlgoKit logger which captures log messages, while wrapping an original logger.\n * This is useful for automated testing.\n */\nexport class TestLogger implements Logger {\n private originalLogger: Logger | undefined\n private logs: string[]\n\n /**\n * Create a new test logger that wraps the given logger if provided.\n * @param originalLogger The optional original logger to wrap.\n */\n constructor(originalLogger?: Logger) {\n this.originalLogger = originalLogger\n this.logs = []\n }\n\n /** Returns all logs captured thus far. */\n get capturedLogs(): string[] {\n return this.logs\n }\n\n /** Clears all logs captured so far. */\n clear() {\n this.logs = []\n }\n\n /**\n * Returns a captured log snapshot.\n * This helps ensure that the provided configuration items won't appear\n * with random values in the log snapshot, but rather will get substituted with predictable ids.\n *\n * https://jestjs.io/docs/snapshot-testing#2-tests-should-be-deterministic\n *\n * @example Jest Example\n * ```typescript\n * const logger = new TestLogger()\n * ...\n * expect(logger.getLogSnapshot()).toMatchSnapshot()\n * ```\n * @param config The snapshot configuration\n * @returns The snapshotted logs.\n */\n getLogSnapshot(config?: LogSnapshotConfig) {\n const { transactions: transactionIds, accounts, apps } = config ?? {}\n let snapshot = this.capturedLogs.join('\\n')\n transactionIds?.forEach(\n (txn, id) => (snapshot = snapshot.replace(new RegExp(typeof txn === 'string' ? txn : txn.txID(), 'g'), `TXID_${id + 1}`)),\n )\n accounts?.forEach(\n (sender, id) =>\n (snapshot = snapshot.replace(\n new RegExp(typeof sender === 'string' ? sender : 'addr' in sender ? sender.addr : sender.address(), 'g'),\n `ACCOUNT_${id + 1}`,\n )),\n )\n apps?.forEach((app, id) => (snapshot = snapshot.replace(new RegExp(`\\\\b${app.toString()}\\\\b(?! bytes)`, 'g'), `APP_${id + 1}`)))\n return snapshot\n }\n\n error(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.error(message, ...optionalParams)\n this.logs.push(`ERROR: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n warn(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.warn(message, ...optionalParams)\n this.logs.push(`WARN: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n info(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.info(message, ...optionalParams)\n this.logs.push(`INFO: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n verbose(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.verbose(message, ...optionalParams)\n this.logs.push(`VERBOSE: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n debug(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.debug(message, ...optionalParams)\n this.logs.push(`DEBUG: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-logger.js","sources":["../../src/testing/test-logger.ts"],"sourcesContent":["import { Logger } from '../types/logging'\nimport { LogSnapshotConfig } from '../types/testing'\nimport { asJson } from '../util'\n\n/** Exposes an AlgoKit logger which captures log messages, while wrapping an original logger.\n * This is useful for automated testing.\n */\nexport class TestLogger implements Logger {\n private originalLogger: Logger | undefined\n private logs: string[]\n\n /**\n * Create a new test logger that wraps the given logger if provided.\n * @param originalLogger The optional original logger to wrap.\n */\n constructor(originalLogger?: Logger) {\n this.originalLogger = originalLogger\n this.logs = []\n }\n\n /** Returns all logs captured thus far. */\n get capturedLogs(): string[] {\n return this.logs\n }\n\n /** Clears all logs captured so far. */\n clear() {\n this.logs = []\n }\n\n /**\n * Returns a captured log snapshot.\n * This helps ensure that the provided configuration items won't appear\n * with random values in the log snapshot, but rather will get substituted with predictable ids.\n *\n * https://jestjs.io/docs/snapshot-testing#2-tests-should-be-deterministic\n *\n * @example Jest Example\n * ```typescript\n * const logger = new TestLogger()\n * ...\n * expect(logger.getLogSnapshot()).toMatchSnapshot()\n * ```\n * @param config The snapshot configuration\n * @returns The snapshotted logs.\n */\n getLogSnapshot(config?: LogSnapshotConfig) {\n const { transactions: transactionIds, accounts, apps } = config ?? {}\n let snapshot = this.capturedLogs.join('\\n')\n transactionIds?.forEach(\n (txn, id) => (snapshot = snapshot.replace(new RegExp(typeof txn === 'string' ? txn : txn.txID(), 'g'), `TXID_${id + 1}`)),\n )\n accounts?.forEach(\n (sender, id) =>\n (snapshot = snapshot.replace(\n new RegExp(typeof sender === 'string' ? sender : 'addr' in sender ? sender.addr : sender.address(), 'g'),\n `ACCOUNT_${id + 1}`,\n )),\n )\n apps?.forEach((app, id) => (snapshot = snapshot.replace(new RegExp(`\\\\b${app.toString()}\\\\b(?! bytes)`, 'g'), `APP_${id + 1}`)))\n return snapshot\n }\n\n error(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.error(message, ...optionalParams)\n this.logs.push(`ERROR: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n warn(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.warn(message, ...optionalParams)\n this.logs.push(`WARN: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n info(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.info(message, ...optionalParams)\n this.logs.push(`INFO: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n verbose(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.verbose(message, ...optionalParams)\n this.logs.push(`VERBOSE: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n debug(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.debug(message, ...optionalParams)\n this.logs.push(`DEBUG: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n}\n"],"names":["asJson"],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { asJson } from '../util.mjs';
2
+
1
3
  /** Exposes an AlgoKit logger which captures log messages, while wrapping an original logger.
2
4
  * This is useful for automated testing.
3
5
  */
@@ -44,23 +46,23 @@ class TestLogger {
44
46
  }
45
47
  error(message, ...optionalParams) {
46
48
  this.originalLogger?.error(message, ...optionalParams);
47
- this.logs.push(`ERROR: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
49
+ this.logs.push(`ERROR: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`);
48
50
  }
49
51
  warn(message, ...optionalParams) {
50
52
  this.originalLogger?.warn(message, ...optionalParams);
51
- this.logs.push(`WARN: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
53
+ this.logs.push(`WARN: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`);
52
54
  }
53
55
  info(message, ...optionalParams) {
54
56
  this.originalLogger?.info(message, ...optionalParams);
55
- this.logs.push(`INFO: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
57
+ this.logs.push(`INFO: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`);
56
58
  }
57
59
  verbose(message, ...optionalParams) {
58
60
  this.originalLogger?.verbose(message, ...optionalParams);
59
- this.logs.push(`VERBOSE: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
61
+ this.logs.push(`VERBOSE: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`);
60
62
  }
61
63
  debug(message, ...optionalParams) {
62
64
  this.originalLogger?.debug(message, ...optionalParams);
63
- this.logs.push(`DEBUG: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`);
65
+ this.logs.push(`DEBUG: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`);
64
66
  }
65
67
  }
66
68
 
@@ -1 +1 @@
1
- {"version":3,"file":"test-logger.mjs","sources":["../../src/testing/test-logger.ts"],"sourcesContent":["import { Logger } from '../types/logging'\nimport { LogSnapshotConfig } from '../types/testing'\n\n/** Exposes an AlgoKit logger which captures log messages, while wrapping an original logger.\n * This is useful for automated testing.\n */\nexport class TestLogger implements Logger {\n private originalLogger: Logger | undefined\n private logs: string[]\n\n /**\n * Create a new test logger that wraps the given logger if provided.\n * @param originalLogger The optional original logger to wrap.\n */\n constructor(originalLogger?: Logger) {\n this.originalLogger = originalLogger\n this.logs = []\n }\n\n /** Returns all logs captured thus far. */\n get capturedLogs(): string[] {\n return this.logs\n }\n\n /** Clears all logs captured so far. */\n clear() {\n this.logs = []\n }\n\n /**\n * Returns a captured log snapshot.\n * This helps ensure that the provided configuration items won't appear\n * with random values in the log snapshot, but rather will get substituted with predictable ids.\n *\n * https://jestjs.io/docs/snapshot-testing#2-tests-should-be-deterministic\n *\n * @example Jest Example\n * ```typescript\n * const logger = new TestLogger()\n * ...\n * expect(logger.getLogSnapshot()).toMatchSnapshot()\n * ```\n * @param config The snapshot configuration\n * @returns The snapshotted logs.\n */\n getLogSnapshot(config?: LogSnapshotConfig) {\n const { transactions: transactionIds, accounts, apps } = config ?? {}\n let snapshot = this.capturedLogs.join('\\n')\n transactionIds?.forEach(\n (txn, id) => (snapshot = snapshot.replace(new RegExp(typeof txn === 'string' ? txn : txn.txID(), 'g'), `TXID_${id + 1}`)),\n )\n accounts?.forEach(\n (sender, id) =>\n (snapshot = snapshot.replace(\n new RegExp(typeof sender === 'string' ? sender : 'addr' in sender ? sender.addr : sender.address(), 'g'),\n `ACCOUNT_${id + 1}`,\n )),\n )\n apps?.forEach((app, id) => (snapshot = snapshot.replace(new RegExp(`\\\\b${app.toString()}\\\\b(?! bytes)`, 'g'), `APP_${id + 1}`)))\n return snapshot\n }\n\n error(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.error(message, ...optionalParams)\n this.logs.push(`ERROR: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n warn(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.warn(message, ...optionalParams)\n this.logs.push(`WARN: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n info(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.info(message, ...optionalParams)\n this.logs.push(`INFO: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n verbose(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.verbose(message, ...optionalParams)\n this.logs.push(`VERBOSE: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n debug(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.debug(message, ...optionalParams)\n this.logs.push(`DEBUG: ${message}${optionalParams.length ? ` | ${JSON.stringify(optionalParams)}` : ''}`)\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-logger.mjs","sources":["../../src/testing/test-logger.ts"],"sourcesContent":["import { Logger } from '../types/logging'\nimport { LogSnapshotConfig } from '../types/testing'\nimport { asJson } from '../util'\n\n/** Exposes an AlgoKit logger which captures log messages, while wrapping an original logger.\n * This is useful for automated testing.\n */\nexport class TestLogger implements Logger {\n private originalLogger: Logger | undefined\n private logs: string[]\n\n /**\n * Create a new test logger that wraps the given logger if provided.\n * @param originalLogger The optional original logger to wrap.\n */\n constructor(originalLogger?: Logger) {\n this.originalLogger = originalLogger\n this.logs = []\n }\n\n /** Returns all logs captured thus far. */\n get capturedLogs(): string[] {\n return this.logs\n }\n\n /** Clears all logs captured so far. */\n clear() {\n this.logs = []\n }\n\n /**\n * Returns a captured log snapshot.\n * This helps ensure that the provided configuration items won't appear\n * with random values in the log snapshot, but rather will get substituted with predictable ids.\n *\n * https://jestjs.io/docs/snapshot-testing#2-tests-should-be-deterministic\n *\n * @example Jest Example\n * ```typescript\n * const logger = new TestLogger()\n * ...\n * expect(logger.getLogSnapshot()).toMatchSnapshot()\n * ```\n * @param config The snapshot configuration\n * @returns The snapshotted logs.\n */\n getLogSnapshot(config?: LogSnapshotConfig) {\n const { transactions: transactionIds, accounts, apps } = config ?? {}\n let snapshot = this.capturedLogs.join('\\n')\n transactionIds?.forEach(\n (txn, id) => (snapshot = snapshot.replace(new RegExp(typeof txn === 'string' ? txn : txn.txID(), 'g'), `TXID_${id + 1}`)),\n )\n accounts?.forEach(\n (sender, id) =>\n (snapshot = snapshot.replace(\n new RegExp(typeof sender === 'string' ? sender : 'addr' in sender ? sender.addr : sender.address(), 'g'),\n `ACCOUNT_${id + 1}`,\n )),\n )\n apps?.forEach((app, id) => (snapshot = snapshot.replace(new RegExp(`\\\\b${app.toString()}\\\\b(?! bytes)`, 'g'), `APP_${id + 1}`)))\n return snapshot\n }\n\n error(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.error(message, ...optionalParams)\n this.logs.push(`ERROR: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n warn(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.warn(message, ...optionalParams)\n this.logs.push(`WARN: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n info(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.info(message, ...optionalParams)\n this.logs.push(`INFO: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n verbose(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.verbose(message, ...optionalParams)\n this.logs.push(`VERBOSE: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n debug(message: string, ...optionalParams: unknown[]): void {\n this.originalLogger?.debug(message, ...optionalParams)\n this.logs.push(`DEBUG: ${message}${optionalParams.length ? ` | ${asJson(optionalParams)}` : ''}`)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -49,7 +49,10 @@ class TransactionLogger {
49
49
  }
50
50
  /** Wait until all logged transactions IDs appear in the given `Indexer`. */
51
51
  async waitForIndexer(indexer$1) {
52
- await Promise.all(this._sentTransactionIds.map((txnId) => indexer.runWhenIndexerCaughtUp(() => indexer$1.lookupTransactionByID(txnId).do())));
52
+ if (this._sentTransactionIds.length === 0)
53
+ return;
54
+ const lastTxId = this._sentTransactionIds[this._sentTransactionIds.length - 1];
55
+ await indexer.runWhenIndexerCaughtUp(() => indexer$1.lookupTransactionByID(lastTxId).do());
53
56
  }
54
57
  }
55
58
  class TransactionLoggingAlgodv2ProxyHandler {
@@ -1 +1 @@
1
- {"version":3,"file":"transaction-logger.js","sources":["../../src/testing/transaction-logger.ts"],"sourcesContent":["import algosdk from 'algosdk'\nimport { runWhenIndexerCaughtUp } from './indexer'\nimport Algodv2 = algosdk.Algodv2\nimport decodeSignedTransaction = algosdk.decodeSignedTransaction\nimport Indexer = algosdk.Indexer\n\n/**\n * Allows you to keep track of Algorand transaction IDs by wrapping an `Algodv2` in a proxy.\n * Useful for automated tests.\n */\nexport class TransactionLogger {\n private _sentTransactionIds: string[] = []\n\n /**\n * The list of transaction IDs that has been logged thus far.\n */\n get sentTransactionIds(): Readonly<string[]> {\n return this._sentTransactionIds\n }\n\n /**\n * Clear all logged IDs.\n */\n clear() {\n this._sentTransactionIds = []\n }\n\n /**\n * The method that captures raw transactions and stores the transaction IDs.\n */\n logRawTransaction(signedTransactions: Uint8Array | Uint8Array[]) {\n if (Array.isArray(signedTransactions)) {\n for (const stxn of signedTransactions) {\n const decoded = decodeSignedTransaction(stxn)\n this._sentTransactionIds.push(decoded.txn.txID())\n }\n } else {\n const decoded = decodeSignedTransaction(signedTransactions)\n this._sentTransactionIds.push(decoded.txn.txID())\n }\n }\n\n /** Return a proxy that wraps the given Algodv2 with this transaction logger.\n *\n * @param algod The `Algodv2` to wrap\n * @returns The wrapped `Algodv2`, any transactions sent using this algod instance will be logged by this transaction logger\n */\n capture(algod: Algodv2): Algodv2 {\n return new Proxy<Algodv2>(algod, new TransactionLoggingAlgodv2ProxyHandler(this))\n }\n\n /** Wait until all logged transactions IDs appear in the given `Indexer`. */\n async waitForIndexer(indexer: Indexer) {\n await Promise.all(this._sentTransactionIds.map((txnId) => runWhenIndexerCaughtUp(() => indexer.lookupTransactionByID(txnId).do())))\n }\n}\n\nclass TransactionLoggingAlgodv2ProxyHandler implements ProxyHandler<Algodv2> {\n private transactionLogger: TransactionLogger\n\n constructor(transactionLogger: TransactionLogger) {\n this.transactionLogger = transactionLogger\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n get(target: Algodv2, property: string | symbol, receiver: any) {\n if (property === 'sendRawTransaction') {\n return (stxOrStxs: Uint8Array | Uint8Array[]) => {\n this.transactionLogger.logRawTransaction(stxOrStxs)\n return target[property].call(receiver, stxOrStxs)\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (target as any)[property]\n }\n}\n"],"names":["indexer","runWhenIndexerCaughtUp"],"mappings":";;;;;AAGA,IAAO,uBAAuB,GAAG,OAAO,CAAC,uBAAuB;AAGhE;;;AAGG;MACU,iBAAiB,CAAA;AAA9B,IAAA,WAAA,GAAA;QACU,IAAmB,CAAA,mBAAA,GAAa,EAAE;;AAE1C;;AAEG;AACH,IAAA,IAAI,kBAAkB,GAAA;QACpB,OAAO,IAAI,CAAC,mBAAmB;;AAGjC;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,mBAAmB,GAAG,EAAE;;AAG/B;;AAEG;AACH,IAAA,iBAAiB,CAAC,kBAA6C,EAAA;AAC7D,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE;AACrC,YAAA,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE;AACrC,gBAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC;AAC7C,gBAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;aAE9C;AACL,YAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,kBAAkB,CAAC;AAC3D,YAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;AAIrD;;;;AAIG;AACH,IAAA,OAAO,CAAC,KAAc,EAAA;QACpB,OAAO,IAAI,KAAK,CAAU,KAAK,EAAE,IAAI,qCAAqC,CAAC,IAAI,CAAC,CAAC;;;IAInF,MAAM,cAAc,CAACA,SAAgB,EAAA;AACnC,QAAA,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAKC,8BAAsB,CAAC,MAAMD,SAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;;AAEtI;AAED,MAAM,qCAAqC,CAAA;AAGzC,IAAA,WAAA,CAAY,iBAAoC,EAAA;AAC9C,QAAA,IAAI,CAAC,iBAAiB,GAAG,iBAAiB;;;AAI5C,IAAA,GAAG,CAAC,MAAe,EAAE,QAAyB,EAAE,QAAa,EAAA;AAC3D,QAAA,IAAI,QAAQ,KAAK,oBAAoB,EAAE;YACrC,OAAO,CAAC,SAAoC,KAAI;AAC9C,gBAAA,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,SAAS,CAAC;gBACnD,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;AACnD,aAAC;;;AAGH,QAAA,OAAQ,MAAc,CAAC,QAAQ,CAAC;;AAEnC;;;;"}
1
+ {"version":3,"file":"transaction-logger.js","sources":["../../src/testing/transaction-logger.ts"],"sourcesContent":["import algosdk from 'algosdk'\nimport { runWhenIndexerCaughtUp } from './indexer'\nimport Algodv2 = algosdk.Algodv2\nimport decodeSignedTransaction = algosdk.decodeSignedTransaction\nimport Indexer = algosdk.Indexer\n\n/**\n * Allows you to keep track of Algorand transaction IDs by wrapping an `Algodv2` in a proxy.\n * Useful for automated tests.\n */\nexport class TransactionLogger {\n private _sentTransactionIds: string[] = []\n\n /**\n * The list of transaction IDs that has been logged thus far.\n */\n get sentTransactionIds(): Readonly<string[]> {\n return this._sentTransactionIds\n }\n\n /**\n * Clear all logged IDs.\n */\n clear() {\n this._sentTransactionIds = []\n }\n\n /**\n * The method that captures raw transactions and stores the transaction IDs.\n */\n logRawTransaction(signedTransactions: Uint8Array | Uint8Array[]) {\n if (Array.isArray(signedTransactions)) {\n for (const stxn of signedTransactions) {\n const decoded = decodeSignedTransaction(stxn)\n this._sentTransactionIds.push(decoded.txn.txID())\n }\n } else {\n const decoded = decodeSignedTransaction(signedTransactions)\n this._sentTransactionIds.push(decoded.txn.txID())\n }\n }\n\n /** Return a proxy that wraps the given Algodv2 with this transaction logger.\n *\n * @param algod The `Algodv2` to wrap\n * @returns The wrapped `Algodv2`, any transactions sent using this algod instance will be logged by this transaction logger\n */\n capture(algod: Algodv2): Algodv2 {\n return new Proxy<Algodv2>(algod, new TransactionLoggingAlgodv2ProxyHandler(this))\n }\n\n /** Wait until all logged transactions IDs appear in the given `Indexer`. */\n async waitForIndexer(indexer: Indexer) {\n if (this._sentTransactionIds.length === 0) return\n const lastTxId = this._sentTransactionIds[this._sentTransactionIds.length - 1]\n await runWhenIndexerCaughtUp(() => indexer.lookupTransactionByID(lastTxId).do())\n }\n}\n\nclass TransactionLoggingAlgodv2ProxyHandler implements ProxyHandler<Algodv2> {\n private transactionLogger: TransactionLogger\n\n constructor(transactionLogger: TransactionLogger) {\n this.transactionLogger = transactionLogger\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n get(target: Algodv2, property: string | symbol, receiver: any) {\n if (property === 'sendRawTransaction') {\n return (stxOrStxs: Uint8Array | Uint8Array[]) => {\n this.transactionLogger.logRawTransaction(stxOrStxs)\n return target[property].call(receiver, stxOrStxs)\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (target as any)[property]\n }\n}\n"],"names":["indexer","runWhenIndexerCaughtUp"],"mappings":";;;;;AAGA,IAAO,uBAAuB,GAAG,OAAO,CAAC,uBAAuB;AAGhE;;;AAGG;MACU,iBAAiB,CAAA;AAA9B,IAAA,WAAA,GAAA;QACU,IAAmB,CAAA,mBAAA,GAAa,EAAE;;AAE1C;;AAEG;AACH,IAAA,IAAI,kBAAkB,GAAA;QACpB,OAAO,IAAI,CAAC,mBAAmB;;AAGjC;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,mBAAmB,GAAG,EAAE;;AAG/B;;AAEG;AACH,IAAA,iBAAiB,CAAC,kBAA6C,EAAA;AAC7D,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE;AACrC,YAAA,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE;AACrC,gBAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC;AAC7C,gBAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;aAE9C;AACL,YAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,kBAAkB,CAAC;AAC3D,YAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;AAIrD;;;;AAIG;AACH,IAAA,OAAO,CAAC,KAAc,EAAA;QACpB,OAAO,IAAI,KAAK,CAAU,KAAK,EAAE,IAAI,qCAAqC,CAAC,IAAI,CAAC,CAAC;;;IAInF,MAAM,cAAc,CAACA,SAAgB,EAAA;AACnC,QAAA,IAAI,IAAI,CAAC,mBAAmB,CAAC,MAAM,KAAK,CAAC;YAAE;AAC3C,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9E,QAAA,MAAMC,8BAAsB,CAAC,MAAMD,SAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC;;AAEnF;AAED,MAAM,qCAAqC,CAAA;AAGzC,IAAA,WAAA,CAAY,iBAAoC,EAAA;AAC9C,QAAA,IAAI,CAAC,iBAAiB,GAAG,iBAAiB;;;AAI5C,IAAA,GAAG,CAAC,MAAe,EAAE,QAAyB,EAAE,QAAa,EAAA;AAC3D,QAAA,IAAI,QAAQ,KAAK,oBAAoB,EAAE;YACrC,OAAO,CAAC,SAAoC,KAAI;AAC9C,gBAAA,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,SAAS,CAAC;gBACnD,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;AACnD,aAAC;;;AAGH,QAAA,OAAQ,MAAc,CAAC,QAAQ,CAAC;;AAEnC;;;;"}
@@ -47,7 +47,10 @@ class TransactionLogger {
47
47
  }
48
48
  /** Wait until all logged transactions IDs appear in the given `Indexer`. */
49
49
  async waitForIndexer(indexer) {
50
- await Promise.all(this._sentTransactionIds.map((txnId) => runWhenIndexerCaughtUp(() => indexer.lookupTransactionByID(txnId).do())));
50
+ if (this._sentTransactionIds.length === 0)
51
+ return;
52
+ const lastTxId = this._sentTransactionIds[this._sentTransactionIds.length - 1];
53
+ await runWhenIndexerCaughtUp(() => indexer.lookupTransactionByID(lastTxId).do());
51
54
  }
52
55
  }
53
56
  class TransactionLoggingAlgodv2ProxyHandler {
@@ -1 +1 @@
1
- {"version":3,"file":"transaction-logger.mjs","sources":["../../src/testing/transaction-logger.ts"],"sourcesContent":["import algosdk from 'algosdk'\nimport { runWhenIndexerCaughtUp } from './indexer'\nimport Algodv2 = algosdk.Algodv2\nimport decodeSignedTransaction = algosdk.decodeSignedTransaction\nimport Indexer = algosdk.Indexer\n\n/**\n * Allows you to keep track of Algorand transaction IDs by wrapping an `Algodv2` in a proxy.\n * Useful for automated tests.\n */\nexport class TransactionLogger {\n private _sentTransactionIds: string[] = []\n\n /**\n * The list of transaction IDs that has been logged thus far.\n */\n get sentTransactionIds(): Readonly<string[]> {\n return this._sentTransactionIds\n }\n\n /**\n * Clear all logged IDs.\n */\n clear() {\n this._sentTransactionIds = []\n }\n\n /**\n * The method that captures raw transactions and stores the transaction IDs.\n */\n logRawTransaction(signedTransactions: Uint8Array | Uint8Array[]) {\n if (Array.isArray(signedTransactions)) {\n for (const stxn of signedTransactions) {\n const decoded = decodeSignedTransaction(stxn)\n this._sentTransactionIds.push(decoded.txn.txID())\n }\n } else {\n const decoded = decodeSignedTransaction(signedTransactions)\n this._sentTransactionIds.push(decoded.txn.txID())\n }\n }\n\n /** Return a proxy that wraps the given Algodv2 with this transaction logger.\n *\n * @param algod The `Algodv2` to wrap\n * @returns The wrapped `Algodv2`, any transactions sent using this algod instance will be logged by this transaction logger\n */\n capture(algod: Algodv2): Algodv2 {\n return new Proxy<Algodv2>(algod, new TransactionLoggingAlgodv2ProxyHandler(this))\n }\n\n /** Wait until all logged transactions IDs appear in the given `Indexer`. */\n async waitForIndexer(indexer: Indexer) {\n await Promise.all(this._sentTransactionIds.map((txnId) => runWhenIndexerCaughtUp(() => indexer.lookupTransactionByID(txnId).do())))\n }\n}\n\nclass TransactionLoggingAlgodv2ProxyHandler implements ProxyHandler<Algodv2> {\n private transactionLogger: TransactionLogger\n\n constructor(transactionLogger: TransactionLogger) {\n this.transactionLogger = transactionLogger\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n get(target: Algodv2, property: string | symbol, receiver: any) {\n if (property === 'sendRawTransaction') {\n return (stxOrStxs: Uint8Array | Uint8Array[]) => {\n this.transactionLogger.logRawTransaction(stxOrStxs)\n return target[property].call(receiver, stxOrStxs)\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (target as any)[property]\n }\n}\n"],"names":[],"mappings":";;;AAGA,IAAO,uBAAuB,GAAG,OAAO,CAAC,uBAAuB;AAGhE;;;AAGG;MACU,iBAAiB,CAAA;AAA9B,IAAA,WAAA,GAAA;QACU,IAAmB,CAAA,mBAAA,GAAa,EAAE;;AAE1C;;AAEG;AACH,IAAA,IAAI,kBAAkB,GAAA;QACpB,OAAO,IAAI,CAAC,mBAAmB;;AAGjC;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,mBAAmB,GAAG,EAAE;;AAG/B;;AAEG;AACH,IAAA,iBAAiB,CAAC,kBAA6C,EAAA;AAC7D,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE;AACrC,YAAA,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE;AACrC,gBAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC;AAC7C,gBAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;aAE9C;AACL,YAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,kBAAkB,CAAC;AAC3D,YAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;AAIrD;;;;AAIG;AACH,IAAA,OAAO,CAAC,KAAc,EAAA;QACpB,OAAO,IAAI,KAAK,CAAU,KAAK,EAAE,IAAI,qCAAqC,CAAC,IAAI,CAAC,CAAC;;;IAInF,MAAM,cAAc,CAAC,OAAgB,EAAA;AACnC,QAAA,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,sBAAsB,CAAC,MAAM,OAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;;AAEtI;AAED,MAAM,qCAAqC,CAAA;AAGzC,IAAA,WAAA,CAAY,iBAAoC,EAAA;AAC9C,QAAA,IAAI,CAAC,iBAAiB,GAAG,iBAAiB;;;AAI5C,IAAA,GAAG,CAAC,MAAe,EAAE,QAAyB,EAAE,QAAa,EAAA;AAC3D,QAAA,IAAI,QAAQ,KAAK,oBAAoB,EAAE;YACrC,OAAO,CAAC,SAAoC,KAAI;AAC9C,gBAAA,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,SAAS,CAAC;gBACnD,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;AACnD,aAAC;;;AAGH,QAAA,OAAQ,MAAc,CAAC,QAAQ,CAAC;;AAEnC;;;;"}
1
+ {"version":3,"file":"transaction-logger.mjs","sources":["../../src/testing/transaction-logger.ts"],"sourcesContent":["import algosdk from 'algosdk'\nimport { runWhenIndexerCaughtUp } from './indexer'\nimport Algodv2 = algosdk.Algodv2\nimport decodeSignedTransaction = algosdk.decodeSignedTransaction\nimport Indexer = algosdk.Indexer\n\n/**\n * Allows you to keep track of Algorand transaction IDs by wrapping an `Algodv2` in a proxy.\n * Useful for automated tests.\n */\nexport class TransactionLogger {\n private _sentTransactionIds: string[] = []\n\n /**\n * The list of transaction IDs that has been logged thus far.\n */\n get sentTransactionIds(): Readonly<string[]> {\n return this._sentTransactionIds\n }\n\n /**\n * Clear all logged IDs.\n */\n clear() {\n this._sentTransactionIds = []\n }\n\n /**\n * The method that captures raw transactions and stores the transaction IDs.\n */\n logRawTransaction(signedTransactions: Uint8Array | Uint8Array[]) {\n if (Array.isArray(signedTransactions)) {\n for (const stxn of signedTransactions) {\n const decoded = decodeSignedTransaction(stxn)\n this._sentTransactionIds.push(decoded.txn.txID())\n }\n } else {\n const decoded = decodeSignedTransaction(signedTransactions)\n this._sentTransactionIds.push(decoded.txn.txID())\n }\n }\n\n /** Return a proxy that wraps the given Algodv2 with this transaction logger.\n *\n * @param algod The `Algodv2` to wrap\n * @returns The wrapped `Algodv2`, any transactions sent using this algod instance will be logged by this transaction logger\n */\n capture(algod: Algodv2): Algodv2 {\n return new Proxy<Algodv2>(algod, new TransactionLoggingAlgodv2ProxyHandler(this))\n }\n\n /** Wait until all logged transactions IDs appear in the given `Indexer`. */\n async waitForIndexer(indexer: Indexer) {\n if (this._sentTransactionIds.length === 0) return\n const lastTxId = this._sentTransactionIds[this._sentTransactionIds.length - 1]\n await runWhenIndexerCaughtUp(() => indexer.lookupTransactionByID(lastTxId).do())\n }\n}\n\nclass TransactionLoggingAlgodv2ProxyHandler implements ProxyHandler<Algodv2> {\n private transactionLogger: TransactionLogger\n\n constructor(transactionLogger: TransactionLogger) {\n this.transactionLogger = transactionLogger\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n get(target: Algodv2, property: string | symbol, receiver: any) {\n if (property === 'sendRawTransaction') {\n return (stxOrStxs: Uint8Array | Uint8Array[]) => {\n this.transactionLogger.logRawTransaction(stxOrStxs)\n return target[property].call(receiver, stxOrStxs)\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (target as any)[property]\n }\n}\n"],"names":[],"mappings":";;;AAGA,IAAO,uBAAuB,GAAG,OAAO,CAAC,uBAAuB;AAGhE;;;AAGG;MACU,iBAAiB,CAAA;AAA9B,IAAA,WAAA,GAAA;QACU,IAAmB,CAAA,mBAAA,GAAa,EAAE;;AAE1C;;AAEG;AACH,IAAA,IAAI,kBAAkB,GAAA;QACpB,OAAO,IAAI,CAAC,mBAAmB;;AAGjC;;AAEG;IACH,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,mBAAmB,GAAG,EAAE;;AAG/B;;AAEG;AACH,IAAA,iBAAiB,CAAC,kBAA6C,EAAA;AAC7D,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE;AACrC,YAAA,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE;AACrC,gBAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC;AAC7C,gBAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;aAE9C;AACL,YAAA,MAAM,OAAO,GAAG,uBAAuB,CAAC,kBAAkB,CAAC;AAC3D,YAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;AAIrD;;;;AAIG;AACH,IAAA,OAAO,CAAC,KAAc,EAAA;QACpB,OAAO,IAAI,KAAK,CAAU,KAAK,EAAE,IAAI,qCAAqC,CAAC,IAAI,CAAC,CAAC;;;IAInF,MAAM,cAAc,CAAC,OAAgB,EAAA;AACnC,QAAA,IAAI,IAAI,CAAC,mBAAmB,CAAC,MAAM,KAAK,CAAC;YAAE;AAC3C,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9E,QAAA,MAAM,sBAAsB,CAAC,MAAM,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC;;AAEnF;AAED,MAAM,qCAAqC,CAAA;AAGzC,IAAA,WAAA,CAAY,iBAAoC,EAAA;AAC9C,QAAA,IAAI,CAAC,iBAAiB,GAAG,iBAAiB;;;AAI5C,IAAA,GAAG,CAAC,MAAe,EAAE,QAAyB,EAAE,QAAa,EAAA;AAC3D,QAAA,IAAI,QAAQ,KAAK,oBAAoB,EAAE;YACrC,OAAO,CAAC,SAAoC,KAAI;AAC9C,gBAAA,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,SAAS,CAAC;gBACnD,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;AACnD,aAAC;;;AAGH,QAAA,OAAQ,MAAc,CAAC,QAAQ,CAAC;;AAEnC;;;;"}
@@ -35,12 +35,12 @@ function encodeTransactionNote(note) {
35
35
  return note;
36
36
  }
37
37
  else if (typeof note === 'object' && 'dAppName' in note) {
38
- const arc2Payload = `${note.dAppName}:${note.format}${typeof note.data === 'string' ? note.data : JSON.stringify(note.data)}`;
38
+ const arc2Payload = `${note.dAppName}:${note.format}${typeof note.data === 'string' ? note.data : util.asJson(note.data)}`;
39
39
  const encoder = new TextEncoder();
40
40
  return encoder.encode(arc2Payload);
41
41
  }
42
42
  else {
43
- const n = typeof note === 'string' ? note : JSON.stringify(note);
43
+ const n = typeof note === 'string' ? note : util.asJson(note);
44
44
  const encoder = new TextEncoder();
45
45
  return encoder.encode(n);
46
46
  }
@@ -313,8 +313,8 @@ async function populateAppCallResources(atc, algod) {
313
313
  t.txn.appForeignApps?.map((a) => algosdk.getApplicationAddress(a)).includes(account) ||
314
314
  // account is available since it's in one of the fields
315
315
  Object.values(t.txn)
316
- .map((f) => JSON.stringify(f))
317
- .includes(JSON.stringify(algosdk.decodeAddress(account))));
316
+ .map((f) => util.asJson(f))
317
+ .includes(util.asJson(algosdk.decodeAddress(account))));
318
318
  });
319
319
  if (txnIndex > -1) {
320
320
  if (type === 'assetHolding') {