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

feat: debugger package implementation #1

Merged
merged 10 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 8 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
14 changes: 1 addition & 13 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,7 @@ jobs:
pipx install algokit
algokit localnet start
npx --yes wait-on tcp:4001 -t 30000
audit-script: |
npm run audit
pull_request_debug_package:
uses: makerxstudio/shared-config/.github/workflows/node-ci.yml@main
with:
node-version: 18.x
working-directory: ./debug-utils
run-commit-lint: true
run-build: true
pre-test-script: |
pipx install algokit
algokit localnet start
npx --yes wait-on tcp:4001 -t 30000
npm install --no-package-lock
audit-script: |
npm run audit
check_docs:
Expand Down
2 changes: 0 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,3 @@ coverage
.idea
# don't format auto generated code docs
docs/code
# don't format test contract artifacts
tests/example-contracts/**/*.json
73 changes: 46 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,73 @@
# AlgoKit TypeScript Utilities
# AlgoKit TypeScript AVM Debugging Utilities

A set of core Algorand utilities written in TypeScript and released via npm that make it easier to build solutions on Algorand. This project is part of [AlgoKit](https://github.com/algorandfoundation/algokit-cli).
An optional addon package for [algokit-utils-ts](https://github.com/algorandfoundation/algokit-utils-ts) that provides **node** specific utilities that automatically gather artifacts required for instantiating [AlgoKit AVM VSCode Debugger Extension](https://github.com/algorandfoundation/algokit-avm-vscode-debugger). This project is part of [AlgoKit](https://github.com/algorandfoundation/algokit-cli).

The goal of this library is to provide intuitive, productive utility functions that make it easier, quicker and safer to build applications on Algorand. Largely these functions wrap the underlying Algorand SDK, but provide a higher level interface with sensible defaults and capabilities for common tasks.
Note: [Python's version of algokit-utils](https://github.com/algorandfoundation/algokit-utils-py) contains the same functionality without requiring a separate package install. Consider using that if you are building your AlgoKit project in Python.

Note: If you prefer Python there's an equivalent [Python utility library](https://github.com/algorandfoundation/algokit-utils-py).

[Install](#install) | [Documentation](docs/README.md)
[Install](#install) | [Documentation](docs/code/README.md)

## Install

This library can be installed from NPM using your favourite npm client, e.g.:

```
npm install @algorandfoundation/algokit-utils
npm install @algorandfoundation/algokit-utils-debug
```

Then to import it:
Then to import it and activate `utils-ts` debugging:

```typescript
import { AlgorandClient, Config } from '@algorandfoundation/algokit-utils'
import { Config } from '@algorandfoundation/algokit-utils'
import { registerDebugHandlers } from '@algorandfoundation/algokit-utils-debug'

Config.configure({
debug: true,
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved
traceAll: true, // optional, defaults to false, ignoring simulate on successfull transactions.
projectRoot: '/path/to/project/root', // if ignored, will try to find the project root automatically by for 'ALGOKIT_PROJECT_ROOT' environment variable or checking filesystem recursively
traceBufferSizeMb: 256, // optional, defaults to 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.
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved
maxSearchDepth: 10, // optional, defaults to 10. 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. Ignored if `projectRoot` is provided directly or via `ALGOKIT_PROJECT_ROOT` environment variable.
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved
})
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved
registerDebugHandlers() // IMPORTANT: must be called before any transactions are submitted.
```

See [usage](./docs/README.md#usage) for more.
See [code documentation](./docs/code/README.md) for more details.

## Guiding principles
## Overview

This library follows the [Guiding Principles of AlgoKit](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles).
This library provides three main functions for debugging Algorand smart contracts:

1. `registerDebugEventHandlers`: The primary function users need to call. It sets up listeners for debugging events emitted by `algokit-utils-ts` (see [AsyncEventEmitter](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/docs/capabilities/event-emitter.md) docs for more details). Must be called before submitting transactions and enabling debug mode in the `algokit-utils-ts` config.

2. `writeTealDebugSourceMaps`: Generates and persists AlgoKit AVM Debugger-compliant sourcemaps. It processes an array of `PersistSourceMapInput` objects, which can contain either raw TEAL or pre-compiled TEAL from algokit.

3. `writeAVMDebugTrace`: Simulates atomic transactions and saves the simulation response as an AlgoKit AVM Debugger-compliant JSON file. It uses the provided `AtomicTransactionComposer` and `Algodv2` client for simulation.

### Default artifact folders

## NextJS compatibility
- `{ALGOKIT_PROJECT_ROOT}/.algokit/sources/*`: The folder containing the TEAL source maps and raw TEAL files.
- `{ALGOKIT_PROJECT_ROOT}/debug_traces`: The folder containing the AVM debug traces.

`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:
> Note, TEAL source maps are suffixed with `.tok.map` | `.teal.map` file extension, while Algorand Python source maps are suffixed with `.puya.map`.

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

The trace files generated 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`
```

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):
Where:

- `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.

- getServerSideProps
- getStaticProps
- getStaticPaths
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.

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.
## Guiding principles

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

## Contributing

Expand Down
Binary file added algorandfoundation-algokit-utils-0.1.0.tgz
Binary file not shown.
58 changes: 58 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# AlgoKit TypeScript AVM Debugging Utilities
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved

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.
aorumbayev marked this conversation as resolved.
Show resolved Hide resolved

## Install

This library can be installed from NPM using your favourite npm client, e.g.:

```
npm install @algorandfoundation/algokit-utils-debug
```

Then to import it and activate `utils-ts` debugging:

```typescript
import { Config } from '@algorandfoundation/algokit-utils'
import { registerDebugHandlers } from '@algorandfoundation/algokit-utils-debug'

Config.configure({
debug: true,
traceAll: true, // optional, defaults to ignoring simulate on successfull transactions.
})
registerDebugHandlers() // must be called before any transactions are submitted.
```

##

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 by for 'ALGOKIT_PROJECT_ROOT' environment variable or checking filesystem recursively
})
```

### 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`
```

Where:

- `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.

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.
89 changes: 86 additions & 3 deletions docs/code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,90 @@

## Table of contents

### Modules
### Functions

- [index](modules/index.md)
- [types/debugging](modules/types_debugging.md)
- [registerDebugEventHandlers](README.md#registerdebugeventhandlers)
- [writeAVMDebugTrace](README.md#writeavmdebugtrace)
- [writeTealDebugSourceMaps](README.md#writetealdebugsourcemaps)

## Functions

### registerDebugEventHandlers

▸ **registerDebugEventHandlers**(): `void`

Registers event handlers for debugging events in Algorand development.

This function sets up handlers for the following events:
- 'TxnGroupSimulated': Calls the `writeAVMDebugTrace` function to generate and persist an AVM debug trace.
- 'AppCompiled': Calls the `writeTealDebugSourceMaps` function to generate and persist TEAL source maps.

These handlers help in debugging Algorand smart contracts by providing detailed traces and source maps.

#### Returns

`void`

#### Defined in

[index.ts:17](https://github.com/algorandfoundation/algokit-utils-ts-debug/blob/main/src/index.ts#L17)

___

### writeAVMDebugTrace

▸ **writeAVMDebugTrace**(`input`): `Promise`\<`void`\>

Generates an AVM debug trace from the provided simulation response and persists it to a file.

#### Parameters

| Name | Type | Description |
| :------ | :------ | :------ |
| `input` | `AVMTracesEventData` | The AVMTracesEventData containing the simulation response and other relevant information. |

#### Returns

`Promise`\<`void`\>

An object containing the output file path and the trace content as a string.

**`Example`**

```ts
const eventData: AVMTracesEventData = {
simulateResponse: // ... simulation response object
};

const result = await writeAVMDebugTrace(eventData);
console.log(`Debug trace saved to: ${result.outputPath}`);
console.log(`Trace content: ${result.traceContent}`);
```

#### Defined in

[debugging/writeAVMDebugTrace.ts:20](https://github.com/algorandfoundation/algokit-utils-ts-debug/blob/main/src/debugging/writeAVMDebugTrace.ts#L20)

___

### writeTealDebugSourceMaps

▸ **writeTealDebugSourceMaps**(`input`): `Promise`\<`void`\>

Generates a source map for the given Teal source code.

#### Parameters

| Name | Type |
| :------ | :------ |
| `input` | `TealSourcesDebugEventData` |

#### Returns

`Promise`\<`void`\>

A promise that resolves when the source map has been generated.

#### Defined in

[debugging/writeTealDebugSourceMaps.ts:36](https://github.com/algorandfoundation/algokit-utils-ts-debug/blob/main/src/debugging/writeTealDebugSourceMaps.ts#L36)
94 changes: 0 additions & 94 deletions docs/code/classes/types_debugging.AVMDebuggerSourceMap.md

This file was deleted.

Loading
Loading