Skip to content
This repository was archived by the owner on Mar 11, 2024. It is now read-only.
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,7 @@
"@truffle/config": "1.3.38",
"@truffle/debug-utils": "^6.0.26",
"@truffle/debugger": "^10.0.14",
"@truffle/environment": "^0.2.130",
"@truffle/fetch-and-compile": "^0.5.19",
"@truffle/resolver": "^9.0.4",
"@truffle/workflow-compile": "^4.0.36",
Expand Down
11 changes: 10 additions & 1 deletion src/commands/DebuggerCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,16 @@ export namespace DebuggerCommands {
txHash = txHashSelection.detail || txHashSelection.label;
}

await startDebugging({txHash, workingDirectory, providerUrl, disableFetchExternal: false});
// Sets the parameters for the debug session
const args = {
txHash,
workingDirectory,
providerUrl,
disableFetchExternal: false,
};

// Starts the debugger
await startDebugging(args);
}
}

Expand Down
13 changes: 5 additions & 8 deletions src/debugAdapter/contracts/contractHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// Licensed under the MIT license.

import Compiler from '@truffle/workflow-compile';
import Config from '@truffle/config';
import {Compilations} from '@truffle/codec';
import path from 'path';
import {Source} from '@truffle/compile-common';
import TruffleConfig from '@truffle/config';

/**
* Represents the return from the compilation of contracts.
Expand All @@ -25,14 +25,11 @@ export type ContractData = {
* This function compiles all contracts and returns an object with
* mapped file sources and builds (shim).
*
* @param workingDirectory The workspace path where the truffle project is located.
* @returns A object (ContractData) with the mapped source files and
* @param config The truffle configuration file.
* @returns A object (ContractData) Environmentwith the mapped source files and
* the contract compilations (shim).
*/
export async function prepareContracts(workingDirectory: any): Promise<ContractData> {
// Retreives the truffle configuration file
const config = Config.detect({workingDirectory: workingDirectory});

export async function prepareContracts(config: TruffleConfig): Promise<ContractData> {
// Sets the properties for the compilation
config.all = true;
config.quiet = true;
Expand All @@ -42,7 +39,7 @@ export async function prepareContracts(workingDirectory: any): Promise<ContractD
const shimCompilations = Compilations.Utils.shimCompilations(compilations);

// Retrieves sources path so the debug can open them
const mappedSources = await getContractSourcePath(workingDirectory, compilations[0].sources);
const mappedSources = await getContractSourcePath(config.working_directory, compilations[0].sources);

// Return the ContractData object
return {
Expand Down
6 changes: 5 additions & 1 deletion src/debugAdapter/debugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,11 @@ export class SolidityDebugSession extends LoggingDebugSession {
await this.sendErrorIfFailed(response, async () => {
validateRequiredArg(args.txHash, `txHash`);
validateRequiredArg(args.workingDirectory, `workingDirectory`);
validateRequiredArg(args.providerUrl, `providerUrl`);

// Validate if both network and providerUrl are not set
if (!args.network && !args.providerUrl) {
throw new Error(`network or providerUrl must be specified to initiate the Truffle Debugger`);
}

if (args.disableFetchExternal === undefined) {
args.disableFetchExternal = false;
Expand Down
5 changes: 5 additions & 0 deletions src/debugAdapter/models/debuggerTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ export namespace DebuggerTypes {
*/
providerUrl?: string;

/**
* Network name of the Ethereum network to connect to.
*/
network?: string;

/**
* When set, do not try to fetch external contract sources when debugging a forked network instance.
* When the network is not being forked, this flag is ignored.
Expand Down
71 changes: 42 additions & 29 deletions src/debugAdapter/runtimeInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ import {ICallInfo} from './models/ICallInfo';
import {IInstruction} from './models/IInstruction';
import {mkdirpSync, writeFileSync} from 'fs-extra';
import {fetchAndCompileForDebugger} from '@truffle/fetch-and-compile';
import {LocalNetworkNode, LocalProject} from '@/Models/TreeItems';
import {getChainId} from '@/functions/explorer';
import {TreeManager} from '@/services/tree/TreeManager';
import {ItemType} from '@/Models';
import Config from '@truffle/config';
import {Environment} from '@truffle/environment';
import * as os from 'os';
import * as path from 'path';

Expand Down Expand Up @@ -138,16 +136,25 @@ export default class RuntimeInterface extends EventEmitter {
* @returns
*/
public async attach(args: Required<DebuggerTypes.DebugArgs>): Promise<void> {
// Retreives the truffle configuration file
const config = Config.detect({workingDirectory: args.workingDirectory});

// Validate the network parameter
RuntimeInterface.validateNetwork(config, args);

// Retreives the environment configuration
await Environment.detect(config);

// Gets the contracts compilation
const result = await prepareContracts(args.workingDirectory);
const result = await prepareContracts(config);

// Sets the properties to use during the debugger process
this._mappedSources = result.mappedSources;
const networkId = args.disableFetchExternal ? undefined : this.getNetworkId(args.providerUrl);
const networkId = args.disableFetchExternal ? undefined : config.network_id;

// Sets the truffle debugger options
const options: truffleDebugger.DebuggerOptions = {
provider: args.providerUrl,
provider: config.provider,
compilations: result.shimCompilations,
lightMode: networkId !== undefined,
};
Expand Down Expand Up @@ -194,28 +201,6 @@ export default class RuntimeInterface extends EventEmitter {
}
}

/**
* Retrieves the chain id of the `providerUrl`.
*
* @param providerUrl the url to get chain id from.
* @returns the chain id of the given `providerUrl`.
*/
private getNetworkId(providerUrl: string) {
const services = TreeManager.getItem(ItemType.LOCAL_SERVICE);

if (!services || !services.getChildren()) {
return undefined;
}

const projects = services.getChildren() as LocalProject[];
const project = projects.find((project) => {
const network = project.getChildren().at(0) as LocalNetworkNode;
return `${network.url.protocol}//${network.url.host}` === providerUrl;
});

return project ? getChainId(project.options.forkedNetwork) : undefined;
}

Comment on lines -197 to -218
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great! By removing all the TreeManager related code within the Debugger we make it less brittle.

public currentLine(): DebuggerTypes.IFrame {
this.validateSession();
const currentLocation = this._session!.view(this._selectors.controller.current.location);
Expand Down Expand Up @@ -295,4 +280,32 @@ export default class RuntimeInterface extends EventEmitter {
throw new Error('Debug session is undefined');
}
}

/**
* Validate if the network parameter was set. Case the network is empty,
* a temp network is created to generate a provider url
*
* @param config Represents the truffle configuration file.
* @param args Represents the arguments needed to initiate a new Truffle `DebugSession` request.
* @returns
*/
private static validateNetwork(config: Config, args: Required<DebuggerTypes.DebugArgs>): void {
if (args.providerUrl) {
// Adds a temporary network to get the provider url
config.network = 'temp_network';
config.networks.temp_network = {
url: args.providerUrl,
network_id: '*',
};
return;
}

// Check if the network exists inside the Truffle configuration file
if (!config.networks.hasOwnProperty(args.network)) {
throw new Error(`Network '${args.network}' does not exist in your Truffle configuration file.`);
}

// Sets the network to get the provider url
config.network = args.network;
}
}
10 changes: 10 additions & 0 deletions src/debugAdapter/types/@truffle/environment.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) Consensys Software Inc. All rights reserved.
// Licensed under the MIT license.

declare module '@truffle/environment' {
import TruffleConfig from '@truffle/config';
export class Environment {
static async detect(config: TruffleConfig): Promise<void>;
}
export {Environment};
}
1 change: 1 addition & 0 deletions src/helpers/uriHandlerController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class UriHandlerController implements UriHandler {
txHash: searchParams.get('txHash') ?? undefined,
workingDirectory: searchParams.get('workingDirectory') ?? undefined,
providerUrl: searchParams.get('providerUrl') ?? undefined,
network: searchParams.get('network') ?? undefined,
disableFetchExternal: !!searchParams.get('disableFetchExternal'),
};

Expand Down
22 changes: 19 additions & 3 deletions test/debugAdapter/runtimeInterface.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// Copyright (c) Consensys Software Inc. All rights reserved.
// Licensed under the MIT license.

import TruffleConfig from '@truffle/config';
import truffleDebugger from '@truffle/debugger';
import {Environment} from '@truffle/environment';
import assert from 'assert';
import sinon from 'sinon';
import * as contractHelpers from '../../src/debugAdapter/contracts/contractHelpers';
import RuntimeInterface from '../../src/debugAdapter/runtimeInterface';
import {referenceConfiguration} from '../testData/truffleConfigTestdata';

describe('RuntimeInterface unit tests', () => {
let runtimeInterface: RuntimeInterface;
Expand All @@ -27,13 +30,16 @@ describe('RuntimeInterface unit tests', () => {
return {};
};
const sessionMock = buildSessionMock(sessionSelectorView);
sinon.stub(RuntimeInterface.prototype, 'generateSession' as any).resolves(sessionMock);
const currentDebugLine = {column: 1, file: contractSourcePathMock, line: 1};

sinon.stub(TruffleConfig, 'detect' as any).returns(referenceConfiguration);
sinon.stub(Environment, 'detect' as any).returns(referenceConfiguration);
sinon.stub(RuntimeInterface.prototype, 'generateSession' as any).resolves(sessionMock);
sinon.stub(RuntimeInterface.prototype, 'currentLine').returns({column: 1, file: contractSourcePathMock, line: 1});

// Act
runtimeInterface = await initMockRuntime();
const callStack = await runtimeInterface.callStack();
const callStack = runtimeInterface.callStack();

// Assert
assert.strictEqual(
Expand All @@ -56,7 +62,11 @@ describe('RuntimeInterface unit tests', () => {
return {};
};
const sessionMock = buildSessionMock(sessionSelectorView);

sinon.stub(TruffleConfig, 'detect' as any).returns(referenceConfiguration);
sinon.stub(Environment, 'detect' as any).returns(referenceConfiguration);
sinon.stub(RuntimeInterface.prototype, 'generateSession' as any).resolves(sessionMock);

// Act
runtimeInterface = await initMockRuntime();

Expand All @@ -82,7 +92,13 @@ const baseSessionMock: truffleDebugger.Session = {

async function initMockRuntime() {
const runtimeInterface = new RuntimeInterface();
const args = {txHash: '', workingDirectory: '', providerUrl: '', disableFetchExternal: false};
const args = {
txHash: '',
workingDirectory: '',
providerUrl: 'http://127.0.0.1:8545',
network: 'development',
disableFetchExternal: false,
};
await runtimeInterface.attach(args);
return runtimeInterface;
}
Expand Down
4 changes: 4 additions & 0 deletions test/testData/truffleConfigTestdata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ export const referenceConfiguration = {
},
},
],
provider: {
host: 'localhost',
},
network_id: 1,
};

export const testModuleWithoutDirectories = {
Expand Down
Loading