-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add CLI command to list transactions for a given deployment
- Loading branch information
Showing
23 changed files
with
7,318 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import type { ArtifactResolver } from "./types/artifact"; | ||
|
||
import { IgnitionError } from "./errors"; | ||
import { FileDeploymentLoader } from "./internal/deployment-loader/file-deployment-loader"; | ||
import { ERRORS } from "./internal/errors-list"; | ||
import { | ||
getExecutionOrder, | ||
loadDeploymentState, | ||
} from "./internal/execution/deployment-state-helpers"; | ||
import { ExecutionResultType } from "./internal/execution/types/execution-result"; | ||
import { | ||
ExecutionSateType, | ||
type CallExecutionState, | ||
type DeploymentExecutionState, | ||
type ExecutionState, | ||
type SendDataExecutionState, | ||
} from "./internal/execution/types/execution-state"; | ||
import { | ||
type Transaction, | ||
TransactionReceiptStatus, | ||
} from "./internal/execution/types/jsonrpc"; | ||
import { assertIgnitionInvariant } from "./internal/utils/assertions"; | ||
import { | ||
type ListTransactionsResult, | ||
TransactionStatus, | ||
} from "./types/list-transactions"; | ||
|
||
/** | ||
* Returns the transactions associated with a deployment. | ||
* | ||
* @param deploymentDir - the directory of the deployment to get the transactions of | ||
* @param artifactResolver - the artifact resolver to use when loading artifacts | ||
* for a future | ||
* | ||
* @beta | ||
*/ | ||
export async function listTransactions( | ||
deploymentDir: string, | ||
_artifactResolver: Omit<ArtifactResolver, "getBuildInfo"> | ||
): Promise<ListTransactionsResult> { | ||
const deploymentLoader = new FileDeploymentLoader(deploymentDir); | ||
|
||
const deploymentState = await loadDeploymentState(deploymentLoader); | ||
|
||
if (deploymentState === undefined) { | ||
throw new IgnitionError(ERRORS.LIST_TRANSACTIONS.UNINITIALIZED_DEPLOYMENT, { | ||
deploymentDir, | ||
}); | ||
} | ||
|
||
const executionOrder = await getExecutionOrder(deploymentLoader); | ||
const transactions: ListTransactionsResult = []; | ||
|
||
for (const futureId of executionOrder) { | ||
const exState = deploymentState.executionStates[futureId]; | ||
|
||
if (!doesSendTransactions(exState)) { | ||
continue; | ||
} | ||
|
||
for (const networkInteraction of exState.networkInteractions) { | ||
assertIgnitionInvariant( | ||
networkInteraction.type === "ONCHAIN_INTERACTION", | ||
"Expected network interaction to be an onchain interaction" | ||
); | ||
|
||
for (const transaction of networkInteraction.transactions) { | ||
switch (exState.type) { | ||
case ExecutionSateType.DEPLOYMENT_EXECUTION_STATE: { | ||
transactions.push({ | ||
type: exState.type, | ||
from: exState.from, | ||
txHash: transaction.hash, | ||
status: getTransactionStatus(transaction), | ||
name: exState.contractName, | ||
address: | ||
transaction.receipt?.status === TransactionReceiptStatus.SUCCESS | ||
? exState.result?.type === ExecutionResultType.SUCCESS | ||
? exState.result.address | ||
: undefined | ||
: undefined, | ||
params: exState.constructorArgs, | ||
value: networkInteraction.value, | ||
}); | ||
|
||
break; | ||
} | ||
case ExecutionSateType.CALL_EXECUTION_STATE: { | ||
transactions.push({ | ||
type: exState.type, | ||
from: exState.from, | ||
txHash: transaction.hash, | ||
status: getTransactionStatus(transaction), | ||
name: exState.functionName, | ||
to: networkInteraction.to, | ||
params: exState.args, | ||
value: networkInteraction.value, | ||
}); | ||
|
||
break; | ||
} | ||
case ExecutionSateType.SEND_DATA_EXECUTION_STATE: { | ||
transactions.push({ | ||
type: exState.type, | ||
from: exState.from, | ||
txHash: transaction.hash, | ||
status: getTransactionStatus(transaction), | ||
to: networkInteraction.to, | ||
value: networkInteraction.value, | ||
}); | ||
|
||
break; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return transactions; | ||
} | ||
|
||
function doesSendTransactions( | ||
exState: ExecutionState | ||
): exState is | ||
| DeploymentExecutionState | ||
| CallExecutionState | ||
| SendDataExecutionState { | ||
return ( | ||
exState.type === ExecutionSateType.DEPLOYMENT_EXECUTION_STATE || | ||
exState.type === ExecutionSateType.CALL_EXECUTION_STATE || | ||
exState.type === ExecutionSateType.SEND_DATA_EXECUTION_STATE | ||
); | ||
} | ||
|
||
function getTransactionStatus(transaction: Transaction): TransactionStatus { | ||
const status = | ||
transaction.receipt === undefined | ||
? TransactionStatus.DROPPED | ||
: transaction.receipt.status === TransactionReceiptStatus.SUCCESS | ||
? TransactionStatus.SUCCESS | ||
: TransactionStatus.FAILURE; | ||
|
||
return status; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import type { SolidityParameterType } from "./module"; | ||
|
||
/** | ||
* The status of a transaction. | ||
* | ||
* @beta | ||
*/ | ||
export enum TransactionStatus { | ||
SUCCESS = "SUCCESS", | ||
FAILURE = "FAILURE", | ||
DROPPED = "DROPPED", | ||
} | ||
|
||
/** | ||
* The information of a transaction. | ||
* | ||
* @beta | ||
*/ | ||
export interface TransactionInfo { | ||
type: string; | ||
status: TransactionStatus; | ||
txHash: string; | ||
from: string; | ||
to?: string; | ||
name?: string; // can be contract name, function name, or undefined, depending on the type | ||
address?: string; | ||
params?: SolidityParameterType[]; | ||
value?: bigint; | ||
} | ||
|
||
/** | ||
* An array of transaction information. | ||
* | ||
* @beta | ||
*/ | ||
export type ListTransactionsResult = TransactionInfo[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { assert } from "chai"; | ||
import path from "path"; | ||
|
||
import { | ||
listTransactions, | ||
ListTransactionsResult, | ||
TransactionStatus, | ||
} from "../src"; | ||
|
||
import { setupMockArtifactResolver } from "./helpers"; | ||
|
||
describe("listTransactions", () => { | ||
it("should return the transactions associated with a deployment", async () => { | ||
const expected: ListTransactionsResult = [ | ||
{ | ||
type: "DEPLOYMENT_EXECUTION_STATE", | ||
from: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", | ||
txHash: | ||
"0x65c7c0850d014fe44aced2249b3b3523c3a29e5e40b6388b6d84b28c0345b9e1", | ||
status: TransactionStatus.SUCCESS, | ||
name: "BasicContract", | ||
address: "0x74e720c9B362ae3A65fF356ad62866511486BBBc", | ||
params: ["0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"], | ||
value: 0n, | ||
}, | ||
{ | ||
type: "DEPLOYMENT_EXECUTION_STATE", | ||
from: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", | ||
txHash: | ||
"0xee331a69f69646d8b551a1ee6514760763cb7b1c332dadb2f0d05c730e554a28", | ||
status: TransactionStatus.SUCCESS, | ||
name: "BasicLibrary", | ||
address: "0x1c947344BA932fC7f3D622600dA0199520A67EFd", | ||
params: [], | ||
value: 0n, | ||
}, | ||
{ | ||
type: "DEPLOYMENT_EXECUTION_STATE", | ||
from: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", | ||
txHash: | ||
"0x6f06b87969f7543887e7cda4b0cf82426b6712a57c915593adf2dd6168f9f283", | ||
status: TransactionStatus.SUCCESS, | ||
name: "BasicLibrary", | ||
address: "0xBdAce15b3211019E272418B8014971c1cefbC8f0", | ||
params: [], | ||
value: 0n, | ||
}, | ||
{ | ||
type: "CALL_EXECUTION_STATE", | ||
from: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", | ||
txHash: | ||
"0xb7b49d16087ab6351e26b2358ae211e5dac335441f323a28c6c26f0bc0c3a0a3", | ||
status: TransactionStatus.SUCCESS, | ||
name: "basicFunction", | ||
to: "0x74e720c9B362ae3A65fF356ad62866511486BBBc", | ||
params: [40], | ||
value: 0n, | ||
}, | ||
{ | ||
type: "DEPLOYMENT_EXECUTION_STATE", | ||
from: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", | ||
txHash: | ||
"0x7542503401d0ad31f0c8de576c8d524535538c25050bd20f77562ecab25c4c8d", | ||
status: TransactionStatus.SUCCESS, | ||
name: "ContractWithLibrary", | ||
address: "0xD369D9aB22D85C2A12bEabc0B581a419789E3755", | ||
params: [], | ||
value: 0n, | ||
}, | ||
{ | ||
type: "SEND_DATA_EXECUTION_STATE", | ||
from: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", | ||
txHash: | ||
"0x2870c7d9f84122caba3739be0dc2246343a87d1b216b57002654b3bd413fe8e2", | ||
status: TransactionStatus.SUCCESS, | ||
to: "0x74e720c9B362ae3A65fF356ad62866511486BBBc", | ||
value: 123n, | ||
}, | ||
]; | ||
|
||
const deploymentDir = path.join( | ||
__dirname, | ||
"mocks", | ||
"listTransactions", | ||
"success" | ||
); | ||
|
||
const artifactResolver = setupMockArtifactResolver(); | ||
|
||
const result = await listTransactions(deploymentDir, artifactResolver); | ||
|
||
assert.deepEqual(result, expected); | ||
}); | ||
|
||
it("should throw an error if the deployment is not initialized", async () => { | ||
const artifactResolver = setupMockArtifactResolver(); | ||
|
||
await assert.isRejected( | ||
listTransactions("fake", artifactResolver), | ||
/IGN1200: Cannot list transactions for nonexistant deployment at fake/ | ||
); | ||
}); | ||
}); |
4 changes: 4 additions & 0 deletions
4
.../core/test/mocks/listTransactions/success/artifacts/CompleteModule#BasicContract.dbg.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"_format": "hh-sol-dbg-1", | ||
"buildInfo": "../build-info/0957b2d8bc1fe22551b79ef37cafc10a.json" | ||
} |
Oops, something went wrong.