Skip to content

Commit

Permalink
Add transaction trace utility function (#264)
Browse files Browse the repository at this point in the history
* [skip ci]
  • Loading branch information
Nathan-SL committed Dec 6, 2022
1 parent ee977a8 commit 507f160
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
- [ ] Rebased to the last commit of the target branch (or merged it into my branch)
- [ ] Documented the changes
- [ ] If `src/type-extensions.ts` was changed, updated the line number referencing this file in the `## API` section of README.md
- [ ] Updated the `test` directory (with a test case consisting of `network.json`, `hardhat.config.ts`, `check.sh`)
- [ ] Updated the `test` directory (with a test case consisting of `network.json`, `hardhat.config.ts`, `check.ts`)
- [ ] Linked issues which this PR resolves
- [ ] Created a PR to the `plugin` branch of [`starknet-hardhat-example`](https://github.com/Shard-Labs/starknet-hardhat-example):
- < EXAMPLE_REPO_PR_URL > <!-- paste here if applicable -->
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ it("should return transaction data and transaction receipt", async function () {

const receipt = await starknet.getTransactionReceipt(txHash);
const decodedEvents = contract.decodeEvents(receipt.events);

const txTrace = await starknet.getTransactionTrace(txHash);
// decodedEvents contains hex data array converted to a structured object
// { name: "increase_balance_called", data: { current_balance: 0n, amount: 10n } }
});
Expand Down
20 changes: 19 additions & 1 deletion src/extend-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from "./types";
import { Account, ArgentAccount, OpenZeppelinAccount } from "./account";
import { checkArtifactExists, findPath, getAccountPath } from "./utils";
import { Transaction, TransactionReceipt } from "./starknet-types";
import { Transaction, TransactionReceipt, TransactionTrace } from "./starknet-types";

export async function getContractFactoryUtil(hre: HardhatRuntimeEnvironment, contractPath: string) {
const artifactsPath = hre.config.paths.starknetArtifacts;
Expand Down Expand Up @@ -173,6 +173,24 @@ export async function getTransactionReceiptUtil(
return txReceipt;
}

export async function getTransactionTraceUtil(
txHash: string,
hre: HardhatRuntimeEnvironment
): Promise<TransactionTrace> {
const executed = await hre.starknetWrapper.getTransactionTrace({
feederGatewayUrl: hre.config.starknet.networkUrl,
gatewayUrl: hre.config.starknet.networkUrl,
hash: txHash
});

if (executed.statusCode) {
const msg = `Could not get the transaction trace. Error: ${executed.stderr.toString()}`;
throw new StarknetPluginError(msg);
}
const txTrace = JSON.parse(executed.stdout.toString()) as TransactionTrace;
return txTrace;
}

export async function getBlockUtil(
hre: HardhatRuntimeEnvironment,
identifier?: BlockIdentifier
Expand Down
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ import {
getWalletUtil,
shortStringToBigIntUtil,
getBlockUtil,
getNonceUtil
getNonceUtil,
getTransactionTraceUtil
} from "./extend-utils";
import { DevnetUtils } from "./devnet-utils";
import { ExternalServer } from "./external-server";
Expand Down Expand Up @@ -296,6 +297,11 @@ extendEnvironment((hre) => {
return txReceipt;
},

getTransactionTrace: async (txHash) => {
const txTrace = await getTransactionTraceUtil(txHash, hre);
return txTrace;
},

getBlock: async (identifier) => {
const block = await getBlockUtil(hre, identifier);
return block;
Expand Down
28 changes: 28 additions & 0 deletions src/starknet-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,34 @@ export interface Transaction {
transaction_index: number;
}

export interface OrderedMessage {
order: number;
to_address: string;
payload: number[];
}

export interface FunctionInvocation {
call_type: string;
calldata: string[];
caller_address: string;
class_hash: string;
contract_address: string;
entry_point_type: string;
events: Event[];
execution_resources: ExecutionResources;
internal_calls: FunctionInvocation[];
messages: OrderedMessage[];
result: string[];
selector: string;
}

export interface TransactionTrace {
function_invocation?: FunctionInvocation;
signature: string[];
validate_invocation?: FunctionInvocation;
fee_transfer_invocation?: FunctionInvocation;
}

export interface Block {
block_hash: string;
parent_block_hash: string;
Expand Down
23 changes: 23 additions & 0 deletions src/starknet-wrappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ export abstract class StarknetWrapper {

public abstract getTxStatus(options: TxHashQueryWrapperOptions): Promise<ProcessResult>;

public abstract getTransactionTrace(options: TxHashQueryWrapperOptions): Promise<ProcessResult>;

protected prepareDeployAccountOptions(options: DeployAccountWrapperOptions): string[] {
const prepared = [
"deploy_account",
Expand Down Expand Up @@ -489,6 +491,18 @@ export class DockerWrapper extends StarknetWrapper {
return executed;
}

public async getTransactionTrace(options: TxHashQueryWrapperOptions): Promise<ProcessResult> {
options.gatewayUrl = adaptUrl(options.gatewayUrl);
options.feederGatewayUrl = adaptUrl(options.feederGatewayUrl);
const preparedOptions = this.prepareTxQueryOptions(
"get_transaction_trace",
options
);

const executed = this.execute("starknet", preparedOptions);
return executed;
}

public async getBlock(options: BlockQueryWrapperOptions): Promise<ProcessResult> {
options.gatewayUrl = adaptUrl(options.gatewayUrl);
options.feederGatewayUrl = adaptUrl(options.feederGatewayUrl);
Expand Down Expand Up @@ -577,6 +591,15 @@ export class VenvWrapper extends StarknetWrapper {
return executed;
}

public async getTransactionTrace(options: TxHashQueryWrapperOptions): Promise<ProcessResult> {
const preparedOptions = this.prepareTxQueryOptions(
"get_transaction_trace",
options
);
const executed = await this.execute("starknet", preparedOptions);
return executed;
}

public async getBlock(options: BlockQueryWrapperOptions): Promise<ProcessResult> {
const preparedOptions = this.prepareBlockQueryOptions(options);
const executed = await this.execute("starknet", preparedOptions);
Expand Down
11 changes: 10 additions & 1 deletion src/type-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
PredeployedAccount
} from "./devnet-utils";
import { Account, ArgentAccount, OpenZeppelinAccount } from "./account";
import { Transaction, TransactionReceipt, Block } from "./starknet-types";
import { Transaction, TransactionReceipt, Block, TransactionTrace } from "./starknet-types";
import { HardhatNetworkConfig, NetworkConfig } from "hardhat/types/config";
import { StarknetChainId } from "starknet/constants";

Expand Down Expand Up @@ -107,6 +107,7 @@ type AccountType = Account;
type OpenZeppelinAccountType = OpenZeppelinAccount;
type ArgentAccountType = ArgentAccount;
type TransactionReceiptType = TransactionReceipt;
type TransactionTraceType = TransactionTrace;
type TransactionType = Transaction;
type BlockType = Block;

Expand Down Expand Up @@ -263,6 +264,13 @@ declare module "hardhat/types/runtime" {

getTransactionReceipt: (txHash: string) => Promise<TransactionReceipt>;

/**
* Returns execution information in a nested structure of calls.
* @param txHash the transaction hash
* @returns the transaction trace
*/
getTransactionTrace: (txHash: string) => Promise<TransactionTrace>;

/**
* Returns an entire block and the transactions contained within it.
* @param identifier optional block identifier (by block number or hash). To query the latest block, remove the identifier.
Expand All @@ -289,5 +297,6 @@ declare module "hardhat/types/runtime" {
type ArgentAccount = ArgentAccountType;
type Transaction = TransactionType;
type TransactionReceipt = TransactionReceiptType;
type TransactionTrace = TransactionTraceType;
type Block = BlockType;
}
15 changes: 8 additions & 7 deletions test/configuration-tests/with-networks/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ execution = hardhatStarknetTest("--no-compile test/contract-factory-test.ts".spl
assertContains(execution.stderr, expected);
console.log("Success");

console.log("Testing with alpha-goerli2 config network");
process.env.NETWORK = "alpha-goerli2";
hardhatStarknetDeploy(
"starknet-artifacts/contracts/contract.cairo --starknet-network alpha-goerli2 --inputs 10".split(
" "
)
);
console.log("Testing deployment with alpha-goerli2 config network is temporarily disabled.");
// console.log("Testing with alpha-goerli2 config network");
// process.env.NETWORK = "alpha-goerli2";
// hardhatStarknetDeploy(
// "starknet-artifacts/contracts/contract.cairo --starknet-network alpha-goerli2 --inputs 10".split(
// " "
// )
// );
4 changes: 4 additions & 0 deletions test/general-tests/transaction-trace/check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { hardhatStarknetCompile, hardhatStarknetTest } from "../../utils/cli-functions";

hardhatStarknetCompile(["contracts/contract.cairo"]);
hardhatStarknetTest("--no-compile test/transaction-trace-test.ts".split(" "));
13 changes: 13 additions & 0 deletions test/general-tests/transaction-trace/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import "@shardlabs/starknet-hardhat-plugin";

module.exports = {
solidity: "0.6.12",
starknet: {
network: process.env.NETWORK
},
networks: {
devnet: {
url: "http://127.0.0.1:5050"
}
}
};
4 changes: 4 additions & 0 deletions test/general-tests/transaction-trace/network.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "../../network.schema",
"devnet": true
}

0 comments on commit 507f160

Please sign in to comment.