diff --git a/packages/ethernaut-optigov/src/internal/agora/Agora.js b/packages/ethernaut-optigov/src/internal/agora/Agora.js index e3430f0..985259d 100644 --- a/packages/ethernaut-optigov/src/internal/agora/Agora.js +++ b/packages/ethernaut-optigov/src/internal/agora/Agora.js @@ -1,35 +1,62 @@ const axios = require('axios') -const debug = require('ethernaut-common/src/ui/debug') const EthernautCliError = require('ethernaut-common/src/error/error') -const Auth = require('./Auth') -const Projects = require('./Projects') +const debug = require('ethernaut-common/src/ui/debug') const API_BASE_URL = 'https://vote.optimism.io/api/v1' const AGORA_API_KEY = process.env.AGORA_API_KEY class Agora { constructor() { - this.auth = new Auth(this) - this.projects = new Projects(this) + this.apiKey = AGORA_API_KEY + this.apiBaseUrl = API_BASE_URL + this.bearerToken = null } - async getSpec() { - try { - const response = await axios.get(`${API_BASE_URL}/spec`, { - headers: { - Authorization: `Bearer ${AGORA_API_KEY}`, - }, - }) + // Axios instance setup + createAxiosInstance() { + const headers = { + Authorization: this.bearerToken + ? `Bearer ${this.bearerToken}` + : `Bearer ${this.apiKey}`, + } - debug.log(`Spec: ${response.data}`, 'ethernaut-optigov') - return response.data - } catch (error) { + return axios.create({ + baseURL: this.apiBaseUrl, + headers, + }) + } + + // Handle common API errors + handleError(error) { + if (error.response) { + throw new EthernautCliError( + 'ethernaut-optigov', + `Http status error: ${error.response.data}`, + ) + } else { throw new EthernautCliError( 'ethernaut-optigov', `Http status error: ${error.message}`, ) } } + + // common method for getting API spec + async getSpec() { + try { + const axiosInstance = this.createAxiosInstance() + const response = await axiosInstance.get('/spec') + debug.log(`Spec: ${response.data}`, 'ethernaut-optigov') + return response.data + } catch (error) { + this.handleError(error) + } + } + + // Set the bearer token after authentication + setBearerToken(token) { + this.bearerToken = token + } } module.exports = Agora diff --git a/packages/ethernaut-optigov/src/internal/agora/Auth.js b/packages/ethernaut-optigov/src/internal/agora/Auth.js index a25d4e8..fdfe73a 100644 --- a/packages/ethernaut-optigov/src/internal/agora/Auth.js +++ b/packages/ethernaut-optigov/src/internal/agora/Auth.js @@ -1,62 +1,38 @@ -const axios = require('axios') const debug = require('ethernaut-common/src/ui/debug') -const EthernautCliError = require('ethernaut-common/src/error/error') class Auth { constructor(agora) { this.agora = agora } - // Get a nonce from the Agora API async getNonce() { try { - const response = await axios.get(`${this.agora.API_BASE_URL}/auth/nonce`) - + const axiosInstance = this.agora.createAxiosInstance() + const response = await axiosInstance.get('/auth/nonce') debug.log(`Nonce: ${response.data.nonce}`, 'ethernaut-optigov') - return response.data + return response.data.nonce } catch (error) { - throw new EthernautCliError( - 'ethernaut-optigov', - `Http status error: ${error.message}`, - ) + this.agora.handleError(error) } } - // Authenticate with the Agora API async authenticateWithAgora(message, signature, nonce) { try { - const response = await axios.post( - `${this.agora.API_BASE_URL}/auth/verify`, - { - message, - signature, - nonce, - }, - { - headers: { - 'Content-Type': 'application/json', - }, - }, - ) + const axiosInstance = this.agora.createAxiosInstance() + const response = await axiosInstance.post('/auth/verify', { + message, + signature, + nonce, + }) debug.log('Auth Response Status:', response.status) - // save the Bearer token - this.bearerToken = response.data.access_token + + // Set the Bearer token for future requests + this.agora.setBearerToken(response.data.access_token) + return response.data.access_token } catch (error) { - if (error.response) { - // Server responded with a status other than 2xx - throw new EthernautCliError( - 'ethernaut-optigov', - `Http status error: ${error.response.data}`, - ) - } else { - // Other errors (e.g., network issue) - throw new EthernautCliError( - 'ethernaut-optigov', - `Http status error: ${error.message}`, - ) - } + this.agora.handleError(error) } } } diff --git a/packages/ethernaut-optigov/src/internal/agora/Projects.js b/packages/ethernaut-optigov/src/internal/agora/Projects.js index 53544f8..c068122 100644 --- a/packages/ethernaut-optigov/src/internal/agora/Projects.js +++ b/packages/ethernaut-optigov/src/internal/agora/Projects.js @@ -1,6 +1,4 @@ -const axios = require('axios') const debug = require('ethernaut-common/src/ui/debug') -const EthernautCliError = require('ethernaut-common/src/error/error') class Projects { constructor(agora) { @@ -8,49 +6,37 @@ class Projects { } async getLatestRound() { - // TODO: Implement this - return 5 + return 5 // Placeholder, you can implement this logic } - async projects({ limit, offset } = { limit: 10, offset: 0 }) { + async getProjects({ limit = 10, offset = 0 } = {}) { try { - const response = await axios.get( - `${this.agora.API_BASE_URL}/projects?limit=${limit}&?offset=${offset}`, - { - headers: { - Authorization: `Bearer ${this.agora.AGORA_API_KEY}`, - }, - }, - ) + const axiosInstance = this.agora.createAxiosInstance() + const response = await axiosInstance.get('/projects', { + params: { limit, offset }, + }) debug.log(`Projects: ${response.data}`, 'ethernaut-optigov') return response.data.data } catch (error) { - throw new EthernautCliError( - 'ethernaut-optigov', - `Http status error: ${error.message}`, - ) + this.agora.handleError(error) } } - async roundProjects({ roundId, limit = 10, offset = 0 }) { + async getRoundProjects({ roundId, limit = 10, offset = 0 }) { try { - const response = await axios.get( - `${this.agora.API_BASE_URL}/retrofunding/rounds/${roundId}/projects?limit=${limit}&offset=${offset}`, + const axiosInstance = this.agora.createAxiosInstance() + const response = await axiosInstance.get( + `/retrofunding/rounds/${roundId}/projects`, { - headers: { - Authorization: `Bearer ${this.apiKey}`, - }, + params: { limit, offset }, }, ) debug.log(`Round Projects: ${response.data}`, 'ethernaut-optigov') return response.data.data } catch (error) { - throw new EthernautCliError( - 'ethernaut-optigov', - `Http status error: ${error.message}`, - ) + this.agora.handleError(error) } } } diff --git a/packages/ethernaut-optigov/src/tasks/Projects.js b/packages/ethernaut-optigov/src/tasks/Projects.js index 3356737..e4feaaf 100644 --- a/packages/ethernaut-optigov/src/tasks/Projects.js +++ b/packages/ethernaut-optigov/src/tasks/Projects.js @@ -1,5 +1,6 @@ const types = require('ethernaut-common/src/validation/types') const output = require('ethernaut-common/src/ui/output') +const Projects = require('../internal/agora/Projects') const Agora = require('../internal/agora/Agora') require('../scopes/optigov') @@ -27,17 +28,11 @@ require('../scopes/optigov') ) .setAction(async ({ round, name, category }) => { try { - const agora = new Agora() + const projects = await getProjects(round) - let roundId - if (round === 'latest') roundId = agora.projects.getLatestRound() - else if (round === 'any') roundId = undefined + const filteredProjects = filterProjects(projects, name, category) - let projects = await getProjects(agora, roundId) - - projects = filterProjects(projects, name, category) - - return output.resultBox(printProjects(projects), 'Projects') + return output.resultBox(printProjects(filteredProjects), 'Projects') } catch (err) { return output.errorBox(err) } @@ -72,10 +67,19 @@ function printProjects(projects) { return strs.join('\n\n') } -async function getProjects(agora, roundId) { - if (roundId === undefined) { - return await agora.projects.projects() +async function getProjects(round) { + const agora = new Agora() + const projects = new Projects(agora) + + let roundId + + if (round === 'latest') { + roundId = await projects.getLatestRound() + } + + if (!roundId) { + return await projects.getProjects() } - return await agora.projects.roundProjects({ roundId }) + return await projects.getRoundProjects({ roundId }) } diff --git a/packages/ethernaut-optigov/src/tasks/login.js b/packages/ethernaut-optigov/src/tasks/login.js index 9674c3c..b45d22f 100644 --- a/packages/ethernaut-optigov/src/tasks/login.js +++ b/packages/ethernaut-optigov/src/tasks/login.js @@ -1,7 +1,8 @@ -const Auth = require('../internal/agora/Auth') const output = require('ethernaut-common/src/ui/output') const { createSiweMessage } = require('../internal/Siwe') const EthernautCliError = require('ethernaut-common/src/error/error') +const Auth = require('../internal/agora/Auth') +const Agora = require('../internal/agora/Agora') require('../scopes/optigov') .task( @@ -24,7 +25,8 @@ require('../scopes/optigov') 'ethernaut-optigov', ) - const auth = new Auth() + const agora = new Agora() + const auth = new Auth(agora) const statement = 'Log in to Agoras RetroPGF API with SIWE.' const nonce = await auth.getNonce()