Skip to content

Commit

Permalink
Add event API (#282)
Browse files Browse the repository at this point in the history
* configure eslint

* fix wallet.ts

* Add event API

* fix wallet exports

* Fix eslint via auto-fix eslint extension command

* Fix Function , Network & Wallet error

* eslint fix

* fix all error given by eslint

* Commented unused variable

* Fix multiple import in extension.ts

* Fix all warning eslint

* Fix provider export

* Fix contract export

* Added Events api for network and account

* update extension.ts

* update keythereum

* Fix events

* acccount creation issue fix

* Fix Network Set API

* removed un used onAccountUpdate function

* rename event

* Removed get list and execute route

* Add List contract api

* function call dropdown fix

* fix return type of function

* fix eslint

* Add Comments for refference

* Fixed typo and logic

* Update TSDoc comments

* Update TSDoc comments

---------

Co-authored-by: Krish-bhardwaj <[email protected]>
Co-authored-by: Aniket Singh <[email protected]>
  • Loading branch information
3 people authored Feb 28, 2023
1 parent e840b0e commit 503ad33
Show file tree
Hide file tree
Showing 31 changed files with 2,242 additions and 1,775 deletions.
6 changes: 5 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ module.exports = {
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
sourceType: 'module',
project: './tsconfig.json'
},
ignorePatterns: ['/build/*', '/node_modules/*'],
rules: {
'@typescript-eslint/explicit-function-return-type': 'warn',
'space-before-function-paren': 'off'
}
}
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,13 @@
}
},
"dependencies": {
"@ethersproject/providers": "^5.7.2",
"@types/keythereum": "^1.2.1",
"@types/randombytes": "^2.0.0",
"@types/underscore": "^1.11.4",
"axios": "^0.27.2",
"bn.js": "^5.2.1",
"eslint": "^8.0.1",
"eslint": "^8.34.0",
"ethers": "^5.6.9",
"keythereum": "^1.2.0",
"number-to-bn": "^1.7.0",
Expand All @@ -192,16 +194,17 @@
"utf8": "^3.0.0"
},
"devDependencies": {
"@types/keythereum": "^1.2.1",
"@types/node": "^18.0.0",
"@types/utf8": "^3.0.1",
"@types/vscode": "^1.38.1",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^5.52.0",
"@typescript-eslint/parser": "^5.52.0",
"eslint-config-standard-with-typescript": "^34.0.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-n": "^15.0.0",
"eslint-plugin-promise": "^6.0.0",
"prettier": "^2.8.4",
"typescript": "*",
"typescript": "^4.9.5",
"vscode": "^1.1.37"
},
"scripts": {
Expand Down
164 changes: 164 additions & 0 deletions src/api/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { ethers, type Wallet, type Contract } from 'ethers'
import { type ExtensionContext } from 'vscode'
import { extractPvtKey, listAddresses } from '../utils/wallet'
import * as vscode from 'vscode'
import {
getNetworkNames,
getSelectedNetConf,
getSelectedProvider
} from '../utils/networks'
import { type ContractABI, type CompiledJSONOutput, type NetworkConfig } from '../types'
import {
getConstructorInputFullPath,
getDeployedFullPath,
getFunctionInputFullPath
} from '../utils/functions'
import { type JsonFragment } from '@ethersproject/abi'

const event: {
network: vscode.EventEmitter<string>
account: vscode.EventEmitter<string>
} = {
network: new vscode.EventEmitter<string>(),
account: new vscode.EventEmitter<string>()
}

// PROVIDER
const providerDefault = (context: ExtensionContext): any => {
return getSelectedProvider(context)
}

const getAvailableNetwork = (): string[] => {
return getNetworkNames()
}

const getNetwork = (context: ExtensionContext): NetworkConfig => {
return getSelectedNetConf(context)
}

const setNetwork = (context: ExtensionContext, network: string): string => {
if (network === null) {
return 'Network parameter not given'
}
if (!getNetworkNames().includes(network)) {
return 'Network not found'
} else {
void context.workspaceState.update('selectedNetwork', network)
return 'Network changed to ' + network
}
}

// WALLETS
const getWallet = async (context: ExtensionContext, account: string): Promise<Wallet> => {
const address: any = await context.workspaceState.get('account')
account = account ?? address
const provider = getSelectedProvider(context)
const privateKey = await extractPvtKey(context.extensionPath, account)
const wallet = new ethers.Wallet(privateKey, provider)
return wallet
}

const listAllWallet = async (context: ExtensionContext): Promise<string[]> => {
const result = await listAddresses(context, context.extensionPath)
return result
}

// CONTRACT

const getContract = async (
context: ExtensionContext,
address: string,
abi: any,
wallet: ethers.Signer
): Promise<Contract> => {
const contract = new ethers.Contract(address, abi, wallet)
return contract
}

const executeContractMethod = async (
contract: any,
method: string,
args: any[]
): Promise<any> => {
const result = await contract[method](...args)
return result
}

const exportABI = async (
context: ExtensionContext,
contractName: string = ''
): Promise<readonly ContractABI[] | readonly JsonFragment[] | undefined> => {
const contracts = context.workspaceState.get('contracts') as Record<string, CompiledJSONOutput>
if (contracts === undefined || Object.keys(contracts).length === 0) return

const contractABIS: readonly ContractABI[] = Object.keys(contracts).map((name) => {
return {
name,
abi: contracts[name].hardhatOutput?.abi
}
})
const contractABI = contractABIS.find(contract => contract.name === contractName)?.abi as readonly JsonFragment[]
if (contractName === '' || contractABI === undefined) return contractABIS
return contractABI
}

const getDeployedContractAddress = async (
context: ExtensionContext,
name: string
): Promise<string | undefined> => {
const contracts = context.workspaceState.get('contracts') as Record<string, CompiledJSONOutput>
if (contracts === undefined || Object.keys(contracts).length === 0) return
for (let i = 0; i < Object.keys(contracts).length; i++) {
const contract: CompiledJSONOutput = contracts[Object.keys(contracts)[i]]
if (contract.name === name) {
const link = getDeployedFullPath(contract)
const json: any = await require(link)
return json.address
}
}
}

const getFunctionInputFile: any = async (
context: ExtensionContext,
name: string
): Promise<object | undefined> => {
const contracts = context.workspaceState.get('contracts') as Record<string, CompiledJSONOutput>
if (contracts === undefined || Object.keys(contracts).length === 0) return

const contract = Object.values(contracts).find(contract => contract.name === name)
if (contract != null) {
const link = getFunctionInputFullPath(contract)
const json = await require(link)
return json
}
}

const getConstructorInputFile = async (
context: ExtensionContext,
name: string
): Promise<object | undefined> => {
const contracts = context.workspaceState.get('contracts') as Record<string, CompiledJSONOutput>
if (contracts === undefined || Object.keys(contracts).length === 0) return
const contract = Object.values(contracts).find(contract => contract.name === name)
if (contract != null) {
const link = getConstructorInputFullPath(contract)
const json = await require(link)
return json
}
}

export {
getNetwork,
setNetwork,
getAvailableNetwork,
providerDefault,
listAllWallet,
getWallet,
getContract,
executeContractMethod,
exportABI,
getDeployedContractAddress,
getFunctionInputFile,
getConstructorInputFile,
event
}
99 changes: 99 additions & 0 deletions src/api/contract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import {
exportABI,
getDeployedContractAddress,
getFunctionInputFile,
getConstructorInputFile
} from './api'
import {
type ExtensionContext
} from 'vscode'
import { type ContractABI } from '../types/api'

import { type JsonFragment } from '@ethersproject/abi'

/**
* Defines the contract API interface.
* @interface
* @property {() => string[]} list Retrieves the list of contracts.
* @property {(name: string) => Promise<readonly ContractABI[] | readonly JsonFragment[] | undefined>} abi Retrieves the abi of the contract.
* @property {(name: string) => Promise<string | undefined>} getContractAddress Retrieves the address of the contract.
* @property {(name: string) => Promise<object | undefined>} getFunctionInput Retrieves the function input of the contract.
* @property {(name: string) => Promise<object | undefined>} getConstructorInput Retrieves the constructor input of the contract.
* @property {(name: string) => Promise<object | undefined>} getConstructorInput Retrieves the constructor input of the contract.
*/
export interface ContractInterface {
list: () => string[]
abi: (name: string) => Promise<readonly ContractABI[] | readonly JsonFragment[] | undefined>
getContractAddress: (name: string) => Promise<string | undefined>
getFunctionInput: (name: string) => Promise<object | undefined>
getConstructorInput: (name: string) => Promise<object | undefined>
}

/**
* Exports contract API.
* Returns a `ContractInterface` object.
* This API provides methods for managing interactions with smart contract files inside Ethcode workspace.
*
* @param {ExtensionContext} context - The `ExtensionContext` object representing the context in which the function is being called.
* @returns {ContractInterface} - The `ContractInterface` object representing the available smart contract management methods.
*/
export function contract (context: ExtensionContext): ContractInterface {
/**
* Returns a list of the compiled contracts loaded in ethcode.
*
* @returns {string[]} - The array of contract names.
*/
function list (): string[] {
const contracts = context.workspaceState.get('contracts') as string[]
if (contracts === undefined || contracts.length === 0) return []
return Object.keys(contracts)
}

/**
* Returns the ABI for the specified contract in ethcode.
*
* @param {string} name - Name of the contract for which to retrieve the ABI.
* @returns {Promise<readonly ContractABI[] | readonly JsonFragment[] | undefined>} - ABI of the specified contract, `undefined` if the ABI cannot be retrieved.
*/
async function abi (contractTitle: string): Promise<readonly ContractABI[] | readonly JsonFragment[] | undefined> {
return await exportABI(context, contractTitle)
}

/**
* Returns the address of the specified contract in ethcode.
*
* @param {string} name - Name of the contract for which to retrieve the address.
* @returns {Promise<string | undefined>} - The address of the specified deployed contract, or undefined if the address cannot be retrieved.
*/
async function getContractAddress (contractTitle: string): Promise<string | undefined> {
return await getDeployedContractAddress(context, contractTitle)
}

/**
* Returns the function input JSON for the specified contract in ethcode.
*
* @param {string} name - Name of the contract for which to retrieve the function input.
* @returns {Promise<object | undefined>} - The function input JSON for the specified contract, or undefined if the input cannot be retrieved.
*/
async function getFunctionInput (contractTitle: string): Promise<object | undefined> {
return getFunctionInputFile(context, contractTitle)
}

/**
* Returns the constructor input file for the specified contract in ethcode .
*
* @param {string} name - Name of the contract for which to retrieve the constructor input.
* @returns {Promise<object | undefined>} - The constructor input object for the specified contract, or undefined if the input cannot be retrieved.
*/
async function getConstructorInput (contractTitle: string): Promise<object | undefined> {
return await getConstructorInputFile(context, contractTitle)
}

return {
list,
abi,
getContractAddress,
getFunctionInput,
getConstructorInput
}
}
39 changes: 39 additions & 0 deletions src/api/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type * as vscode from 'vscode'
import { event } from './api'

/**
* Represents an interface for event emitters of network and account changes.
*/
export interface EventsInterface {
/**
* An event emitter for network changes.
*
* @event
* @type {vscode.EventEmitter<string>}
*/
network: vscode.EventEmitter<string>

/**
* An event emitter for account changes.
*
* @event
* @type {vscode.EventEmitter<string>}
*/
account: vscode.EventEmitter<string>
}

/**
* Returns an object containing event emitters for network and account changes.
*
* @returns {EventsInterface} An object containing event emitters for network and account changes.
*
*/
export function events (): EventsInterface {
const network = event.network
const account = event.account

return {
network,
account
}
}
13 changes: 13 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { status } from './status'
import { wallet } from './wallet'
import { provider } from './provider'
import { contract } from './contract'
import { events } from './events'

export {
events,
status,
wallet,
provider,
contract
}
Loading

0 comments on commit 503ad33

Please sign in to comment.