Skip to content

Commit

Permalink
Merge pull request #27 from algorandfoundation/trace-in-error
Browse files Browse the repository at this point in the history
feat(transaction): Adding dryrun traces to error to give more control
  • Loading branch information
robdmoore authored Apr 17, 2023
2 parents 2dcdcfd + 2606784 commit 272de16
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 44 deletions.
22 changes: 11 additions & 11 deletions docs/code/classes/types_logic_error.LogicError.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Error.constructor

#### Defined in

[src/types/logic-error.ts:49](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L49)
[src/types/logic-error.ts:54](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L54)

## Properties

Expand All @@ -67,7 +67,7 @@ Error.constructor

#### Defined in

[src/types/logic-error.ts:37](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L37)
[src/types/logic-error.ts:42](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L42)

___

Expand All @@ -77,7 +77,7 @@ ___

#### Defined in

[src/types/logic-error.ts:39](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L39)
[src/types/logic-error.ts:44](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L44)

___

Expand Down Expand Up @@ -115,7 +115,7 @@ ___

#### Defined in

[src/types/logic-error.ts:38](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L38)
[src/types/logic-error.ts:43](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L43)

___

Expand All @@ -129,7 +129,7 @@ Error.stack

#### Defined in

[src/types/logic-error.ts:41](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L41)
[src/types/logic-error.ts:46](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L46)

___

Expand All @@ -139,7 +139,7 @@ ___

#### Defined in

[src/types/logic-error.ts:40](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L40)
[src/types/logic-error.ts:45](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L45)

___

Expand Down Expand Up @@ -221,15 +221,15 @@ ___

### parseLogicError

`Static` **parseLogicError**(`errorMessage`): `undefined` \| [`LogicErrorDetails`](../interfaces/types_logic_error.LogicErrorDetails.md)
`Static` **parseLogicError**(`error`): `undefined` \| [`LogicErrorDetails`](../interfaces/types_logic_error.LogicErrorDetails.md)

Takes an error message and parses out the details of any logic errors in there.

#### Parameters

| Name | Type | Description |
| :------ | :------ | :------ |
| `errorMessage` | `string` | The error message to parse |
| Name | Type |
| :------ | :------ |
| `error` | `any` |

#### Returns

Expand All @@ -239,4 +239,4 @@ The logic error details if any, or undefined

#### Defined in

[src/types/logic-error.ts:25](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L25)
[src/types/logic-error.ts:28](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L28)
13 changes: 13 additions & 0 deletions docs/code/interfaces/types_logic_error.LogicErrorDetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Details about a smart contract logic error
- [desc](types_logic_error.LogicErrorDetails.md#desc)
- [msg](types_logic_error.LogicErrorDetails.md#msg)
- [pc](types_logic_error.LogicErrorDetails.md#pc)
- [traces](types_logic_error.LogicErrorDetails.md#traces)
- [txId](types_logic_error.LogicErrorDetails.md#txid)

## Properties
Expand Down Expand Up @@ -53,6 +54,18 @@ The program counter where the error was

___

### traces

**traces**: `Record`<`string`, `unknown`\>[]

Any trace information included in the error

#### Defined in

[src/types/logic-error.ts:18](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/types/logic-error.ts#L18)

___

### txId

**txId**: `string`
Expand Down
14 changes: 7 additions & 7 deletions docs/code/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ the estimated rate.

#### Defined in

[src/transaction.ts:334](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L334)
[src/transaction.ts:333](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L333)

___

Expand Down Expand Up @@ -226,7 +226,7 @@ Allows for control of fees on a

#### Defined in

[src/transaction.ts:357](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L357)
[src/transaction.ts:356](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L356)

___

Expand Down Expand Up @@ -1072,7 +1072,7 @@ The array of transactions with signers

#### Defined in

[src/transaction.ts:389](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L389)
[src/transaction.ts:388](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L388)

___

Expand Down Expand Up @@ -1385,7 +1385,7 @@ The suggested transaction parameters

#### Defined in

[src/transaction.ts:380](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L380)
[src/transaction.ts:379](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L379)

___

Expand Down Expand Up @@ -1618,7 +1618,7 @@ The dryrun result

#### Defined in

[src/transaction.ts:224](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L224)
[src/transaction.ts:223](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L223)

___

Expand Down Expand Up @@ -1837,7 +1837,7 @@ An object with transaction IDs, transactions, group transaction ID (`groupTransa

#### Defined in

[src/transaction.ts:242](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L242)
[src/transaction.ts:241](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L241)

___

Expand Down Expand Up @@ -2001,4 +2001,4 @@ Pending transaction information

#### Defined in

[src/transaction.ts:287](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L287)
[src/transaction.ts:286](https://github.com/algorandfoundation/algokit-utils-ts/blob/main/src/transaction.ts#L286)
9 changes: 4 additions & 5 deletions src/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,17 +192,16 @@ export const sendAtomicTransactionComposer = async function (atcSend: AtomicTran
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
if (Config.debug) {
if (Config.debug && typeof e === 'object') {
e.traces = []
Config.logger.debug(
'Received error executing Atomic Transaction Composer and debug flag enabled; attempting dry run to get more information',
)
const dryrun = await performAtomicTransactionComposerDryrun(atc, algod)
if (dryrun.error) {
Config.logger.error('Received the following error when attempting a dryrun of failed transaction(s)', { error: dryrun.error })
}

for (const txn of dryrun.txns) {
if (txn.appCallRejected()) {
Config.logger.error(`Received the following application error when executing dry run of transaction`, {
e.traces.push({
trace: txn.appTrace(),
cost: txn.cost,
logs: txn.logs,
Expand Down
5 changes: 2 additions & 3 deletions src/types/__snapshots__/application-client.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`application-client Errors Display nice error messages when there is a logic error 3`] = `
exports[`application-client Errors Display nice error messages when there is a logic error 4`] = `
"INFO: Idempotently deploying app "TestingApp" from creator ACCOUNT_1 using 932 bytes of teal code and 4 bytes of teal code
INFO: App TestingApp not found in apps created by ACCOUNT_1; deploying app with version 1.0.
INFO: Sent transaction ID TXID_1 appl from ACCOUNT_1
DEBUG: Created app APP_1 from creator ACCOUNT_1
DEBUG: Received error executing Atomic Transaction Composer and debug flag enabled; attempting dry run to get more information
ERROR: Received the following application error when executing dry run of transaction | [{"trace":"pc# |ln# |source |scratch |stack\\n1 |1 |intcblock 0 1 10 5 1 1 | |[]\\n9 |2 |bytecblock 0x 0x151f7c75 | |[]\\n17 |3 |txn NumAppArgs | |[]\\n19 |4 |intc_0 // 0 | |[1]\\n20 |5 |== | |[1, 0]\\n21 |6 |bnz label1 | |[0]\\n24 |7 |txna ApplicationArgs 0 | |[]\\n27 |8 |pushbytes 0xf17e80a5 // 0xf17e... | |[0x44d0da0d]\\n33 |9 |== | |[0x44d0da0d, 0xf17e80a5]\\n34 |10 |bnz label2 | |[0]\\n37 |11 |txna ApplicationArgs 0 | |[]\\n40 |12 |pushbytes 0x0a92a81e // 0x0a92... | |[0x44d0da0d]\\n46 |13 |== | |[0x44d0da0d, 0x0a92a81e]\\n47 |14 |bnz label3 | |[0]\\n50 |15 |txna ApplicationArgs 0 | |[]\\n53 |16 |pushbytes 0xa4cf8dea // 0xa4cf... | |[0x44d0da0d]\\n59 |17 |== | |[0x44d0da0d, 0xa4cf8dea]\\n60 |18 |bnz label4 | |[0]\\n63 |19 |txna ApplicationArgs 0 | |[]\\n66 |20 |pushbytes 0xcec2834a // 0xcec2... | |[0x44d0da0d]\\n72 |21 |== | |[0x44d0da0d, 0xcec2834a]\\n73 |22 |bnz label5 | |[0]\\n76 |23 |txna ApplicationArgs 0 | |[]\\n79 |24 |pushbytes 0xa4b4a230 // 0xa4b4... | |[0x44d0da0d]\\n85 |25 |== | |[0x44d0da0d, 0xa4b4a230]\\n86 |26 |bnz label6 | |[0]\\n89 |27 |txna ApplicationArgs 0 | |[]\\n92 |28 |pushbytes 0x44d0da0d // 0x44d0... | |[0x44d0da0d]\\n98 |29 |== | |[0x44d0da0d, 0x44d0da0d]\\n99 |30 |bnz label7 | |[1]\\n246 |115 |txn OnCompletion | |[]\\n248 |116 |intc_0 // 0 | |[0]\\n249 |117 |== | |[0, 0]\\n250 |118 |txn ApplicationID | |[1]\\n252 |119 |intc_0 // 0 | |[1, APP_1]\\n253 |120 |!= | |[1, APP_1, 0]\\n254 |121 |&& | |[1, 1]\\n255 |122 |assert | |[1]\\n256 |123 |callsub label16 | |[]\\n779 |399 |proto 0 0 | |[]\\n782 |400 |intc_0 // 0 | |[]\\n783 |401 |assert | |[0]\\n783 |401 |!! assert failed pc=783 !! | |[0]\\n"}]"
DEBUG: Received error executing Atomic Transaction Composer and debug flag enabled; attempting dry run to get more information"
`;
85 changes: 69 additions & 16 deletions src/types/application-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,23 +445,76 @@ describe('application-client', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
expect(e.toString().replace(/transaction [A-Z0-9]{52}/, 'transaction {TX_ID}')).toMatchInlineSnapshot(`
"Error: assert failed pc=783. at:416. Network request error. Received status 400 (Bad Request): TransactionPool.Remember: transaction {TX_ID}: logic eval error: assert failed pc=783. Details: pc=783, opcodes=proto 0 0
intc_0 // 0
assert
"
`)
"Error: assert failed pc=783. at:416. Network request error. Received status 400 (Bad Request): TransactionPool.Remember: transaction {TX_ID}: logic eval error: assert failed pc=783. Details: pc=783, opcodes=proto 0 0
intc_0 // 0
assert
"
`)
expect(e.stack).toMatchInlineSnapshot(`
"// error
error_6:
proto 0 0
intc_0 // 0
// Deliberate error
assert <--- Error
retsub
// create
create_7:"
`)
"// error
error_6:
proto 0 0
intc_0 // 0
// Deliberate error
assert <--- Error
retsub
// create
create_7:"
`)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
e.led.traces[0].trace = e.led.traces[0].trace!.replace(new RegExp(`${app.appId}(]|,)`, 'g'), '{APP_ID}$1')
expect(e.led.traces[0]).toMatchInlineSnapshot(`
{
"cost": undefined,
"logs": undefined,
"trace": "pc# |ln# |source |scratch |stack
1 |1 |intcblock 0 1 10 5 1 1 | |[]
9 |2 |bytecblock 0x 0x151f7c75 | |[]
17 |3 |txn NumAppArgs | |[]
19 |4 |intc_0 // 0 | |[1]
20 |5 |== | |[1, 0]
21 |6 |bnz label1 | |[0]
24 |7 |txna ApplicationArgs 0 | |[]
27 |8 |pushbytes 0xf17e80a5 // 0xf17e... | |[0x44d0da0d]
33 |9 |== | |[0x44d0da0d, 0xf17e80a5]
34 |10 |bnz label2 | |[0]
37 |11 |txna ApplicationArgs 0 | |[]
40 |12 |pushbytes 0x0a92a81e // 0x0a92... | |[0x44d0da0d]
46 |13 |== | |[0x44d0da0d, 0x0a92a81e]
47 |14 |bnz label3 | |[0]
50 |15 |txna ApplicationArgs 0 | |[]
53 |16 |pushbytes 0xa4cf8dea // 0xa4cf... | |[0x44d0da0d]
59 |17 |== | |[0x44d0da0d, 0xa4cf8dea]
60 |18 |bnz label4 | |[0]
63 |19 |txna ApplicationArgs 0 | |[]
66 |20 |pushbytes 0xcec2834a // 0xcec2... | |[0x44d0da0d]
72 |21 |== | |[0x44d0da0d, 0xcec2834a]
73 |22 |bnz label5 | |[0]
76 |23 |txna ApplicationArgs 0 | |[]
79 |24 |pushbytes 0xa4b4a230 // 0xa4b4... | |[0x44d0da0d]
85 |25 |== | |[0x44d0da0d, 0xa4b4a230]
86 |26 |bnz label6 | |[0]
89 |27 |txna ApplicationArgs 0 | |[]
92 |28 |pushbytes 0x44d0da0d // 0x44d0... | |[0x44d0da0d]
98 |29 |== | |[0x44d0da0d, 0x44d0da0d]
99 |30 |bnz label7 | |[1]
246 |115 |txn OnCompletion | |[]
248 |116 |intc_0 // 0 | |[0]
249 |117 |== | |[0, 0]
250 |118 |txn ApplicationID | |[1]
252 |119 |intc_0 // 0 | |[1, {APP_ID}]
253 |120 |!= | |[1, {APP_ID}, 0]
254 |121 |&& | |[1, 1]
255 |122 |assert | |[1]
256 |123 |callsub label16 | |[]
779 |399 |proto 0 0 | |[]
782 |400 |intc_0 // 0 | |[]
783 |401 |assert | |[0]
783 |401 |!! assert failed pc=783 !! | |[0]
",
}
`)
}

expect(
Expand Down
2 changes: 1 addition & 1 deletion src/types/application-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ export class ApplicationClient {
exposeLogicError(e: Error, isClear?: boolean): Error {
if ((!isClear && this._approvalSourceMap == undefined) || (isClear && this._clearSourceMap == undefined)) return e

const errorDetails = LogicError.parseLogicError(e.message)
const errorDetails = LogicError.parseLogicError(e)

if (errorDetails !== undefined)
return new LogicError(
Expand Down
7 changes: 6 additions & 1 deletion src/types/logic-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export interface LogicErrorDetails {
msg: string
/** The full error description */
desc: string
/** Any trace information included in the error */
traces: Record<string, unknown>[]
}

/** Wraps key functionality around processing logic errors */
Expand All @@ -22,7 +24,9 @@ export class LogicError extends Error {
* @param errorMessage The error message to parse
* @returns The logic error details if any, or undefined
*/
static parseLogicError(errorMessage: string): LogicErrorDetails | undefined {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static parseLogicError(error: any): LogicErrorDetails | undefined {
const errorMessage = error.message
const res = LOGIC_ERROR.exec(errorMessage)
if (res === null || res.length <= 3) return undefined

Expand All @@ -31,6 +35,7 @@ export class LogicError extends Error {
msg: res[2],
desc: errorMessage,
pc: parseInt(res[3] ? res[3] : '0'),
traces: error.traces,
} as LogicErrorDetails
}

Expand Down

0 comments on commit 272de16

Please sign in to comment.