Implement AI-powered Web3 agent platform with CI/CD and Copilot integration#3
Implement AI-powered Web3 agent platform with CI/CD and Copilot integration#3
Conversation
- Set up TypeScript project with proper configuration - Add GitHub Copilot instructions and configuration - Implement CI/CD pipeline with GitHub Actions - Create AI agent framework with LangChain integration - Add Web3 provider service with ethers.js - Add blockchain analysis and smart contract agents - Create comprehensive documentation - Add testing infrastructure with Jest - Configure ESLint for code quality Co-authored-by: lippytm <65956507+lippytm@users.noreply.github.com>
Co-authored-by: lippytm <65956507+lippytm@users.noreply.github.com>
- Add .js extensions to test imports for ES modules - Fix main module detection to handle file paths correctly Co-authored-by: lippytm <65956507+lippytm@users.noreply.github.com>
- Fix main module detection using pathToFileURL - Update TypeScript module to ES2022 for consistency - Configure Jest with proper ES module support using ts-jest/presets/default-esm Co-authored-by: lippytm <65956507+lippytm@users.noreply.github.com>
- Add workflow-level permissions with contents: read - Add job-level permissions for all jobs - Add security-events: write for security-scan job Co-authored-by: lippytm <65956507+lippytm@users.noreply.github.com>
Co-authored-by: lippytm <65956507+lippytm@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR bootstraps an empty repository into a TypeScript-based “Web3 AI agent platform” with LangChain/OpenAI agents, an ethers.js Web3 provider wrapper, CI/CD via GitHub Actions, and supporting documentation.
Changes:
- Added TypeScript source for AI agents (
BaseAgent,BlockchainAnalysisAgent,SmartContractAgent) and aWeb3Providerwrapper around ethers.js. - Added project tooling: TypeScript/Jest/ESLint config, npm scripts, basic unit tests, and GitHub Actions CI workflow.
- Added developer documentation and GitHub Copilot repository instructions.
Reviewed changes
Copilot reviewed 21 out of 24 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | TypeScript compiler configuration for ESM build output. |
| src/web3/provider.ts | Ethers-based provider wrapper for common chain queries and utilities. |
| src/utils/logger.ts | Lightweight console logger abstraction. |
| src/utils/config.ts | Environment-based configuration loading/validation. |
| src/types/index.ts | Shared types for agent tasks/responses and Web3 query/request shapes. |
| src/index.ts | Library entrypoint and runnable main module bootstrap. |
| src/agents/base.ts | Core LangChain/OpenAI agent execution wrapper. |
| src/agents/blockchain-analysis.ts | Agent for address/gas analysis built on Web3Provider. |
| src/agents/smart-contract.ts | Agent for contract analysis and parameter suggestions. |
| src/tests/logger.test.ts | Unit tests for logger behavior. |
| src/tests/config.test.ts | Unit tests for config load/validation behavior. |
| package.json | Node/TS project manifest, scripts, and dependencies. |
| jest.config.js | Jest + ts-jest configuration for ESM TypeScript tests. |
| docs/CI_CD.md | Documentation of CI/CD workflow stages and setup. |
| docs/AI_FEATURES.md | Documentation of agent capabilities and best practices. |
| SUMMARY.md | High-level implementation summary of repo bootstrap. |
| README.md | Primary project documentation (setup, usage, CI/CD, Copilot). |
| EXAMPLES.md | Usage examples for providers and agents. |
| CONTRIBUTING.md | Contributor workflow and guidelines. |
| .gitignore | Node/TS and environment artifact ignores. |
| .github/workflows/ci.yml | GitHub Actions pipeline for lint/test/build/security scan. |
| .github/copilot-instructions.md | Repository-specific Copilot guidance. |
| .eslintrc.json | ESLint configuration for TypeScript linting. |
| .env.example | Example environment configuration template. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
There was a problem hiding this comment.
This workflow uses npm ci, but the repository does not include a package-lock.json. npm ci will fail without a lockfile, breaking the test job.
Either commit a lockfile (recommended) or switch this step to npm install.
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
There was a problem hiding this comment.
This workflow uses npm ci, but the repository does not include a package-lock.json. npm ci will fail without a lockfile, breaking the build job.
Either commit a lockfile (recommended) or switch this step to npm install.
| private chainId: number; | ||
|
|
||
| constructor(rpcUrl: string, chainId: number) { | ||
| this.provider = new ethers.JsonRpcProvider(rpcUrl); | ||
| this.chainId = chainId; |
There was a problem hiding this comment.
chainId is stored but never used to configure the underlying ethers provider. This can also trigger @typescript-eslint/no-unused-vars on the private field, failing lint.
Either pass chainId into the ethers.JsonRpcProvider constructor (so the provider is network-pinned) or remove the field if it’s not needed.
| private chainId: number; | |
| constructor(rpcUrl: string, chainId: number) { | |
| this.provider = new ethers.JsonRpcProvider(rpcUrl); | |
| this.chainId = chainId; | |
| constructor(rpcUrl: string, chainId: number) { | |
| this.provider = new ethers.JsonRpcProvider(rpcUrl); |
| @@ -0,0 +1,48 @@ | |||
| import { logger, LogLevel } from '../utils/logger.js'; | |||
There was a problem hiding this comment.
LogLevel is imported but never used, which will fail the configured @typescript-eslint/no-unused-vars rule.
Remove the unused import (or use it to set the logger level within the test).
| import { logger, LogLevel } from '../utils/logger.js'; | |
| import { logger } from '../utils/logger.js'; |
| it('should log debug messages', () => { | ||
| logger.debug('Test debug message'); | ||
| expect(consoleSpy.debug).toHaveBeenCalledWith('[DEBUG] Test debug message'); |
There was a problem hiding this comment.
This test expects debug logs to be emitted, but the exported logger instance defaults to LogLevel.INFO, so logger.debug(...) should be a no-op and console.debug will not be called.
To make this test valid, either (a) allow the logger level to be configured in tests (e.g., export the Logger class or add a setter) and set it to DEBUG, or (b) change the expectation to reflect the default INFO behavior.
| it('should log debug messages', () => { | |
| logger.debug('Test debug message'); | |
| expect(consoleSpy.debug).toHaveBeenCalledWith('[DEBUG] Test debug message'); | |
| it('should not log debug messages when level is INFO by default', () => { | |
| logger.debug('Test debug message'); | |
| expect(consoleSpy.debug).not.toHaveBeenCalled(); |
| case 'transaction': | ||
| if (!query.txHash) throw new Error('Transaction hash required'); | ||
| return this.getTransaction(query.txHash); | ||
|
|
There was a problem hiding this comment.
BlockchainQuery.type includes 'contract', but executeQuery does not handle it and will throw Unsupported query type: contract. This is a functional mismatch between the public type and implementation.
Either implement the 'contract' branch (using contractAddress/method/params) or remove 'contract' from the BlockchainQuery union so callers can’t request an unsupported query.
| case 'contract': | |
| if (!('contractAddress' in query) || !query.contractAddress) { | |
| throw new Error('Contract address required for contract query'); | |
| } | |
| if (!('abi' in query) || !query.abi) { | |
| throw new Error('Contract ABI required for contract query'); | |
| } | |
| if (!('method' in query) || !query.method) { | |
| throw new Error('Contract method required for contract query'); | |
| } | |
| // Normalize params to an array | |
| const params = Array.isArray((query as any).params) | |
| ? (query as any).params | |
| : ((query as any).params != null ? [(query as any).params] : []); | |
| const contract = new ethers.Contract(query.contractAddress as string, (query as any).abi, this.provider); | |
| // Dynamically call the specified method with provided params | |
| const contractAny = contract as any; | |
| if (typeof contractAny[query.method] !== 'function') { | |
| throw new Error(`Method ${String(query.method)} not found on contract`); | |
| } | |
| return contractAny[query.method](...params); | |
| "lint": "eslint src/**/*.ts", | ||
| "lint:fix": "eslint src/**/*.ts --fix", |
There was a problem hiding this comment.
The lint script runs ESLint on src/**/*.ts, which includes *.test.ts files under src/__tests__. However, parserOptions.project points at tsconfig.json, and that tsconfig excludes **/*.test.ts, which commonly causes @typescript-eslint/parser to error that the file is not included in the project.
Either adjust the lint globs to exclude tests, or add a separate tsconfig.eslint.json that includes tests and reference that from ESLint.
| "lint": "eslint src/**/*.ts", | |
| "lint:fix": "eslint src/**/*.ts --fix", | |
| "lint": "eslint src/**/*.ts --ignore-pattern '**/*.test.ts'", | |
| "lint:fix": "eslint src/**/*.ts --ignore-pattern '**/*.test.ts' --fix", |
| "langchain": "^0.1.0", | ||
| "web3": "^4.3.0" |
There was a problem hiding this comment.
web3 is listed as a runtime dependency but appears unused in the TypeScript sources. Keeping unused Web3 libraries increases install size and supply-chain surface area.
Consider removing web3 from dependencies unless it’s needed for upcoming work.
| "langchain": "^0.1.0", | |
| "web3": "^4.3.0" | |
| "langchain": "^0.1.0" |
|
|
||
| if (!isDemoMode) { | ||
| // Initialize AI agents | ||
| const blockchainAgent = new BlockchainAnalysisAgent(config.openaiApiKey, web3Provider, config.openaiModel); |
There was a problem hiding this comment.
Unused variable blockchainAgent.
| const blockchainAgent = new BlockchainAnalysisAgent(config.openaiApiKey, web3Provider, config.openaiModel); | |
| new BlockchainAnalysisAgent(config.openaiApiKey, web3Provider, config.openaiModel); |
| if (!isDemoMode) { | ||
| // Initialize AI agents | ||
| const blockchainAgent = new BlockchainAnalysisAgent(config.openaiApiKey, web3Provider, config.openaiModel); | ||
| const contractAgent = new SmartContractAgent(config.openaiApiKey, config.openaiModel); |
There was a problem hiding this comment.
Unused variable contractAgent.
| const contractAgent = new SmartContractAgent(config.openaiApiKey, config.openaiModel); |
Transforms empty repository into production-ready Web3 AI platform with LangChain agents, automated workflows, and developer tooling.
AI Agent Framework
BaseAgentfoundation with extensible task execution and context managementBlockchainAnalysisAgentfor on-chain analysis (addresses, gas prices, transaction patterns)SmartContractAgentfor contract interaction and security assessmentWeb3Providerservice wrapping ethers.js v6 for multi-chain EVM operationsCI/CD Pipeline
GitHub Actions workflow with:
GitHub Copilot Configuration
.github/copilot-instructions.mddefines:TypeScript Infrastructure
ts-jest/presets/default-esmfor proper ESM supportpathToFileURLfor correct URL comparisonDocumentation
Original prompt
This pull request was created as a result of the following prompt from Copilot chat.
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.