Skip to content

Commit

Permalink
fix: filename generation and match timestamp format on utils-py
Browse files Browse the repository at this point in the history
  • Loading branch information
aorumbayev committed Oct 30, 2024
1 parent 605d0ca commit 553d81a
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 16 deletions.
2 changes: 1 addition & 1 deletion docs/code/functions/writeAVMDebugTrace.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ 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)
[debugging/writeAVMDebugTrace.ts:65](https://github.com/algorandfoundation/algokit-utils-ts-debug/blob/main/src/debugging/writeAVMDebugTrace.ts#L65)
46 changes: 45 additions & 1 deletion src/debugging/writeAVMDebugTrace.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { Config, EventType, performAtomicTransactionComposerSimulate } from '@al
import { algorandFixture } from '@algorandfoundation/algokit-utils/testing'
import { describe, expect, test } from '@jest/globals'
import algosdk, { makeEmptyTransactionSigner } from 'algosdk'
import { SimulateResponse } from 'algosdk/dist/types/client/v2/algod/models/types'
import * as fs from 'fs/promises'
import * as os from 'os'
import * as path from 'path'
import { DEBUG_TRACES_DIR } from '../constants'
import { registerDebugEventHandlers } from '../index'
import { generateDebugTraceFilename } from './writeAVMDebugTrace'

describe('simulateAndPersistResponse tests', () => {
describe('writeAVMDebugTrace tests', () => {
const localnet = algorandFixture()

beforeAll(async () => {
Expand Down Expand Up @@ -45,3 +47,45 @@ describe('simulateAndPersistResponse tests', () => {
jest.restoreAllMocks()
})
})

describe('generateDebugTraceFilename', () => {
const TEST_CASES: Array<[string, object, string]> = [
[
'single payment transaction',
{
lastRound: 1000,
txnGroups: [
{
txnResults: [{ txnResult: { txn: { txn: { type: 'pay' } } } }],
},
],
},
'1pay',
],
[
'multiple transaction types',
{
lastRound: 1000,
txnGroups: [
{
txnResults: [
{ txnResult: { txn: { txn: { type: 'pay' } } } },
{ txnResult: { txn: { txn: { type: 'pay' } } } },
{ txnResult: { txn: { txn: { type: 'axfer' } } } },
{ txnResult: { txn: { txn: { type: 'appl' } } } },
{ txnResult: { txn: { txn: { type: 'appl' } } } },
{ txnResult: { txn: { txn: { type: 'appl' } } } },
],
},
],
},
'2pay_1axfer_3appl',
],
]

test.each(TEST_CASES)('%s', (testName, mockResponse, expectedPattern) => {
const timestamp = '20230101_120000'
const filename = generateDebugTraceFilename(mockResponse as SimulateResponse, timestamp)
expect(filename).toBe(`${timestamp}_lr${(mockResponse as SimulateResponse).lastRound}_${expectedPattern}.trace.avm.json`)
})
})
62 changes: 48 additions & 14 deletions src/debugging/writeAVMDebugTrace.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,52 @@
import { AVMTracesEventData } from '@algorandfoundation/algokit-utils'
import { SimulateResponse } from 'algosdk/dist/types/client/v2/algod/models/types'
import { DEBUG_TRACES_DIR } from '../constants'
import { getProjectRoot, joinPaths, writeToFile } from '../utils'

type TxnTypeCount = {
type: string
count: number
}

/**
* Formats a date to YYYYMMDD_HHMMSS in UTC, equivalent to algokit-utils-py format:
* datetime.now(tz=timezone.utc).strftime("%Y%m%d_%H%M%S")
*/
export function formatTimestampUTC(date: Date): string {
// Get UTC components
const year = date.getUTCFullYear()
const month = String(date.getUTCMonth() + 1).padStart(2, '0') // Months are zero-based
const day = String(date.getUTCDate()).padStart(2, '0')
const hours = String(date.getUTCHours()).padStart(2, '0')
const minutes = String(date.getUTCMinutes()).padStart(2, '0')
const seconds = String(date.getUTCSeconds()).padStart(2, '0')

// Format the datetime string
return `${year}${month}${day}_${hours}${minutes}${seconds}`
}

export function generateDebugTraceFilename(simulateResponse: SimulateResponse, timestamp: string): string {
const txnGroups = simulateResponse.txnGroups
const txnTypesCount = txnGroups.reduce((acc: Map<string, TxnTypeCount>, txnGroup) => {
txnGroup.txnResults.forEach(({ txnResult }) => {
const { type } = txnResult.txn.txn
if (!acc.has(type)) {
acc.set(type, { type, count: 0 })
}
const entry = acc.get(type)!
entry.count++
})
return acc
}, new Map())

const txnTypesStr = Array.from(txnTypesCount.values())
.map(({ count, type }) => `${count}${type}`)
.join('_')

const lastRound = simulateResponse.lastRound
return `${timestamp}_lr${lastRound}_${txnTypesStr}.trace.avm.json`
}

/**
* Generates an AVM debug trace from the provided simulation response and persists it to a file.
*
Expand All @@ -20,22 +65,11 @@ import { getProjectRoot, joinPaths, writeToFile } from '../utils'
export async function writeAVMDebugTrace(input: AVMTracesEventData): Promise<void> {
try {
const simulateResponse = input.simulateResponse
const txnGroups = simulateResponse.txnGroups
const projectRoot = await getProjectRoot()

const txnTypesCount = txnGroups.reduce((acc: Record<string, number>, txnGroup) => {
const txnType = txnGroup.txnResults[0].txnResult.txn.txn.type
acc[txnType] = (acc[txnType] || 0) + 1
return acc
}, {})

const txnTypesStr = Object.entries(txnTypesCount)
.map(([type, count]) => `${count}${type}`)
.join('_')

const timestamp = new Date().toISOString().replace(/[:.]/g, '')
const timestamp = formatTimestampUTC(new Date())
const outputRootDir = joinPaths(projectRoot, DEBUG_TRACES_DIR)
const outputFilePath = joinPaths(outputRootDir, `${timestamp}_${txnTypesStr}.trace.avm.json`)
const filename = generateDebugTraceFilename(simulateResponse, timestamp)
const outputFilePath = joinPaths(outputRootDir, filename)

await writeToFile(outputFilePath, JSON.stringify(simulateResponse.get_obj_for_encoding(), null, 2))
} catch (error) {
Expand Down

0 comments on commit 553d81a

Please sign in to comment.