Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: prereqs for puya debugging support #315

Merged
merged 15 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,6 @@ See [usage](./docs/README.md#usage) for more.

This library follows the [Guiding Principles of AlgoKit](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles).

## NextJS compatibility

`algokit-utils-ts` has a set of `node` specific utilities used for simplifying aggregation of artifacts for [AlgoKit VSCode Debugger Extension](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). Which causes Next.js based projects to fail on `fs` module not found. To fix this issue, you can add the following to your `next.config.js` file:

```js
webpack: (config, { isServer }) => {
// Fix for Module not found: Can't resolve 'fs'
if (!isServer) {
config.resolve.fallback.fs = false;
}
return config;
},
```

The root cause is due to the fact that, unlike many frameworks, Next.js allows you to import server-only (Node.js APIs that don't work in a browser) code into your page files. When Next.js builds your project, it removes server only code from your client-side bundle by checking which code exists inside one any of the following built-in methods (code splitting):

- getServerSideProps
- getStaticProps
- getStaticPaths

The Module not found: can't resolve 'xyz' error happens when you try to use server only code outside of these methods. Despite `algokit-utils` lazy loading the node specific code dynamically, Next.js does not seem to correctly identify whether a dynamic import is specific to server or client side. Hence the above fix disables the fallback for `fs` module so it ignores polyfilling it on client side.

## Contributing

This is an open source project managed by the Algorand Foundation. See the [AlgoKit contributing page](https://github.com/algorandfoundation/algokit-cli/blob/main/CONTRIBUTING.md) to learn about making improvements.
Expand Down
Binary file added algorandfoundation-algokit-utils-debug-0.1.0.tgz
Binary file not shown.
42 changes: 5 additions & 37 deletions docs/capabilities/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@ The AlgoKit TypeScript Utilities package provides a set of debugging tools that

## Configuration

The `config.ts` file contains the `UpdatableConfig` class which manages and updates configuration settings for the AlgoKit project. The class has the following attributes:

- `debug`: Indicates whether debug mode is enabled.
- `projectRoot`: The path to the project root directory. Can be ignored if you are using `algokit-utils` inside an `algokit` compliant project (containing `.algokit.toml` file). For non algokit compliant projects, simply provide the path to the folder where you want to store sourcemaps and traces to be used with [`AlgoKit AVM Debugger`](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). Alternatively you can also set the value via the `ALGOKIT_PROJECT_ROOT` environment variable.
- `traceAll`: Indicates whether to trace all operations. Defaults to false, this means that when debug mode is enabled, any (or all) application client calls performed via `algokit-utils` will store responses from `simulate` endpoint. These files are called traces, and can be used with [AlgoKit AVM Debugger](https://marketplace.visualstudio.com/items?itemName=algorandfoundation.algokit-avm-vscode-debugger) to debug TEAL source codes, and a large variety of transaction types in the atomic groups. Default behaviour will perform persistence of traces only on scenarios where any of the transaction groups emitted by an ApplicationClient or `sendAtomicTransactionComposer` method fails.
- `traceBufferSizeMb`: The size of the trace buffer in megabytes. By default uses 256 megabytes. When output folder containing debug trace files exceedes the size, oldest files are removed to optimize for storage consumption. This is useful when you are running a long running application and want to keep the trace files for debugging purposes but also be mindful of storage consumption.
- `maxSearchDepth`: The maximum depth to search for a an `algokit` config file. By default it will traverse at most `10` folders searching for `.algokit.toml` file which will be used to determine algokit compliant project root path.

The `configure` method can be used to set these attributes.
The `config.ts` file contains the `UpdatableConfig` class which manages and updates configuration settings for the AlgoKit project.

To enable debug mode in your project you can configure it as follows:

Expand All @@ -25,34 +17,10 @@ Config.configure({

## Debugging Utilities

Debugging utilities can be used to simplify gathering artifacts to be used with [AlgoKit AVM Debugger](https://github.com/algorandfoundation/algokit-avm-vscode-debugger) in non algokit compliant projects. The following methods are provided:

- `persistSourceMaps`: This method persists the sourcemaps for the given sources as AlgoKit AVM Debugger compliant artifacts. It accepts an array of `PersistSourceMapInput` objects. Each object can either contain `rawTeal`, in which case the function will execute a compile to obtain byte code, or it can accept an object of type `CompiledTeal` provided by algokit, which is used for source codes that have already been compiled and contain the traces. It also accepts the root directory of the project, an `Algodv2` client to perform the compilation, and a boolean indicating whether to include the source files in the output.
- `simulateAndPersistResponse`: This method simulates the atomic transactions using the provided `AtomicTransactionComposer` object and `Algodv2` object, and persists the simulation response to an AlgoKit AVM Debugger compliant JSON file. It accepts the `AtomicTransactionComposer` with transaction(s) loaded, an `Algodv2` client to perform the simulation, the root directory of the project, and the buffer size in megabytes.

To enable debug mode with extra trace persistence for AVM VSCode Debugger, you can configure it as follows:

```ts
import { Config } from '@algorandfoundation/algokit-utils'
Config.configure({
debug: true,
traceAll: true, // if ignored, will only trace failed atomic transactions and application client calls
projectRoot: '/path/to/project/root', // if ignored, will try to find the project root automatically
})
```

### Trace filename format

The trace files are named in a specific format to provide useful information about the transactions they contain. The format is as follows:

```ts
;`${timestamp}_lr${lastRound}_${transactionTypes}.trace.avm.json`
```
Refer to the [algokit-utils-ts-debug](https://github.com/algorandfoundation/algokit-utils-ts-debug) for more details on how to activate the addon package with `algokit-utils` in your project.

Where:
> Note: Config also contains a set flags that affect behaviour of [algokit-utils-ts-debug](https://github.com/algorandfoundation/algokit-utils-ts-debug). Those include `projectRoot`, `traceAll`, `traceBufferSizeMb`, and `maxSearchDepth`. Refer to addon package documentation for details.
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved

- `timestamp`: The time when the trace file was created, in ISO 8601 format, with colons and periods removed.
- `lastRound`: The last round when the simulation was performed.
- `transactionTypes`: A string representing the types and counts of transactions in the atomic group. Each transaction type is represented as `${count}#${type}`, and different transaction types are separated by underscores.
### Why debug utilities are in a separate package?
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved

For example, a trace file might be named `20220301T123456Z_lr1000_2#pay_1#axfer.trace.avm.json`, indicating that the trace file was created at `2022-03-01T12:34:56Z`, the last round was `1000`, and the atomic group contained 2 payment transactions and 1 asset transfer transaction.
To keep the `algokit-utils-ts` package lean and isomporphic, the debugging utilities are located in a separate package. This eliminates various error cases with bundlers (e.g. `webpack`, `esbuild`) when building for the browser.
99 changes: 99 additions & 0 deletions docs/capabilities/event-emitter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Event Emitter

The Event Emitter is a capability provided by AlgoKit Utils that allows for asynchronous event handling. It provides a flexible mechanism for emitting and listening to custom events, which can be particularly useful for debugging and extending functionality not available in the `algokit-utils-ts` package.
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved

## `AsyncEventEmitter`

The [`AsyncEventEmitter`](../code/classes/types_async_event_emitter.AsyncEventEmitter.md) is a class that manages asynchronous event emission and subscription.

To use the `AsyncEventEmitter`, you can import it directly:

```typescript
import { AsyncEventEmitter } from '@algorandfoundation/algokit-utils/types/async-event-emitter'

const emitter = new AsyncEventEmitter()
```

## Event Types

The `EventType` enum defines the built-in event types:

```typescript
enum EventType {
TxnGroupSimulated = 'TxnGroupSimulated',
AppCompiled = 'AppCompiled',
}
```

These events are primarily used for debugging purposes and are handled by the [`algokit-utils-ts-debug`](https://github.com/algorandfoundation/algokit-utils-ts-debug) package. However, the `AsyncEventEmitter` is designed to be generic and can be extended to handle custom event types as well.

## Emitting Events
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved

To emit an event, use the `emitAsync` method:

```typescript
await emitter.emitAsync(EventType.AppCompiled, compilationData)
```

## Listening to Events

There are two ways to listen to events:

### Using `on`

The `on` method adds a listener that will be called every time the specified event is emitted:

```typescript
emitter.on(EventType.AppCompiled, async (data) => {
console.log('App compiled:', data)
})
```

### Using `once`

The `once` method adds a listener that will be called only once for the specified event:

```typescript
emitter.once(EventType.TxnGroupSimulated, async (data) => {
console.log('Transaction group simulated:', data)
})
```

## Removing Listeners

To remove a listener, use the `removeListener` or `off` method:

```typescript
const listener = async (data) => {
console.log('Event received:', data)
}

emitter.on(EventType.AppCompiled, listener)

// Later, when you want to remove the listener:
emitter.removeListener(EventType.AppCompiled, listener)
// or
emitter.off(EventType.AppCompiled, listener)
```

## Custom Events

While the current implementation primarily focuses on debugging events, the `AsyncEventEmitter` is designed to be extensible. You can emit and listen to custom events by using string keys:

```typescript
emitter.on('customEvent', async (data) => {
console.log('Custom event received:', data)
})

await emitter.emitAsync('customEvent', { foo: 'bar' })
```

## Integration with `algokit-utils-ts-debug`

The events emitted by `AsyncEventEmitter` are particularly useful when used in conjunction with the `algokit-utils-ts-debug` package. This package listens for these events and persists relevant debugging information to the user's AlgoKit project filesystem, facilitating integration with the AVM debugger extension.

## Extending Functionality

The `AsyncEventEmitter` can serve as a foundation for building custom AlgoKit Utils extensions. By listening to the activity events emitted by the utils-ts package, you can create additional functionality tailored to your specific needs.

If you have suggestions for new event types or additional functionality, please open a PR or submit an issue on the AlgoKit Utils GitHub repository.
2 changes: 2 additions & 0 deletions docs/code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
- [types/app-spec](modules/types_app_spec.md)
- [types/asset](modules/types_asset.md)
- [types/asset-manager](modules/types_asset_manager.md)
- [types/async-event-emitter](modules/types_async_event_emitter.md)
- [types/async-event-emitter.spec](modules/types_async_event_emitter_spec.md)
- [types/client-manager](modules/types_client_manager.md)
- [types/client-manager.spec](modules/types_client_manager_spec.md)
- [types/composer](modules/types_composer.md)
Expand Down
Loading
Loading