Skip to content

Commit

Permalink
Add ethernaut-optigov pluguin and login task
Browse files Browse the repository at this point in the history
  • Loading branch information
luisvid committed Oct 8, 2024
1 parent 90a1ecf commit 138f1c2
Show file tree
Hide file tree
Showing 13 changed files with 415 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/ethernaut-cli/hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require('ethernaut-challenges')
require('ethernaut-ui')
require('ethernaut-oso')
require('ethernaut-ai-ui')
require('ethernaut-optigov')

async function main() {
const txt = figlet.textSync('ethernaut-cli', { font: 'Graffiti' })
Expand Down
47 changes: 47 additions & 0 deletions packages/ethernaut-optigov/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ethernaut-optigov

Tasks for interacting the Optimism retroactive public goods funding rounds (RetroPGF)

## What

This plugin enables seamless interaction with Optimism’s Retroactive Public Goods Funding (RetroPGF) rounds. It allows users to access data on rounds, projects, and votes, streamlining participation and analysis within the Optimism ecosystem. Perfect for tracking funding and engaging with the RetroPGF process.

## Installation

```bash
npm install ethernaut-optigov
```

Import the plugin in your `hardhat.config.js`:

```js
require('ethernaut-optigov')
```

Or if you are using TypeScript, in your `hardhat.config.ts`:

```ts
import 'ethernaut-optigov'
```

## Required plugins

This plugin doesn't depend on any other plugins.

## Tasks

This plugin adds the tasks listed below.

- login Logs in to the Agora RetroPGF API with SIWE (Sign in with Ethereum)

## Environment extensions

This plugin doesn't extend the hre.

## Configuration

This plugin doesn't add any fields to the hardhat configuration file.

## Usage

Just install it and all tasks will be available with `npx hardhat <task> <params>`
31 changes: 31 additions & 0 deletions packages/ethernaut-optigov/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "ethernaut-optigov",
"version": "1.0.0",
"description": "Tasks for interacting the Optimism Agora retroactive public goods funding rounds (RetroPGF)",
"main": "src/index.js",
"scripts": {
"build": "npm run install:test",
"compile": "echo 'No compile step'",
"install:test": "cd test/fixture-projects/basic-project && npm install",
"test": "nyc --nycrc-path ../../.nycrc.json mocha --config ../../.mocharc.json"
},
"author": "Alejandro Santander",
"license": "ISC",
"peerDependencies": {
"hardhat": "^2.22.2"
},
"devDependencies": {
"hardhat": "^2.22.2",
"mocha": "^10.4.0",
"nyc": "^15.1.0",
"nyc-report-lcov-absolute": "^1.0.0"
},
"dependencies": {
"siwe": "^2.3.2"
},
"directories": {
"test": "test"
},
"keywords": [],
"gitHead": "5ffea95c7b8186e6365da19d189a79f09a78d475"
}
11 changes: 11 additions & 0 deletions packages/ethernaut-optigov/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { extendEnvironment } = require('hardhat/config')
const requireAll = require('ethernaut-common/src/io/require-all')
const spinner = require('ethernaut-common/src/ui/spinner')
const output = require('ethernaut-common/src/ui/output')

requireAll(__dirname, 'tasks')

extendEnvironment((hre) => {
spinner.enable(!hre.hardhatArguments.verbose)
output.setErrorVerbose(hre.hardhatArguments.verbose)
})
22 changes: 22 additions & 0 deletions packages/ethernaut-optigov/src/internal/Siwe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { SiweMessage } = require('siwe')

const domain = 'com.ethernaut.cli'
const uri = 'https://github.com/eternauta1337/ethernaut-cli'

function createSiweMessage(address, statement, nonce) {
const siweMessage = new SiweMessage({
domain,
address,
statement,
uri,
version: '1',
chainId: '1 ',
nonce,
})

return siweMessage.prepareMessage()
}

module.exports = {
createSiweMessage,
}
63 changes: 63 additions & 0 deletions packages/ethernaut-optigov/src/internal/agora/Auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const axios = require('axios')
const debug = require('ethernaut-common/src/ui/debug')
const EthernautCliError = require('ethernaut-common/src/error/error')
const API_BASE_URL = 'https://vote.optimism.io/api/v1'

class Auth {
constructor() {}

// Get a nonce from the Agora API
async getNonce() {
try {
const response = await axios.get(`${API_BASE_URL}/auth/nonce`)

debug.log(`Nonce: ${response.data.nonce}`, 'ethernaut-optigov')
return response.data
} catch (error) {
throw new EthernautCliError(
'ethernaut-optigov',
`Http status error: ${error.message}`,
)
}
}

// Authenticate with the Agora API
async authenticateWithAgora(message, signature, nonce) {
try {
const response = await axios.post(
`${API_BASE_URL}/auth/verify`,
{
message,
signature,
nonce,
},
{
headers: {
'Content-Type': 'application/json',
},
},
)

debug.log('Auth Response Status:', response.status)
// save the Bearer token
this.bearerToken = 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}`,
)
}
}
}
}

module.exports = Auth
4 changes: 4 additions & 0 deletions packages/ethernaut-optigov/src/scopes/optigov.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const { scope } = require('hardhat/config')
const { description } = require('../../package.json')

module.exports = scope('optigov', description)
43 changes: 43 additions & 0 deletions packages/ethernaut-optigov/src/tasks/login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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')

require('../scopes/optigov')
.task(
'login',
'Logs in to the Agora RetroPGF API with SIWE (Sign in with Ethereum)',
)
.setAction(async (_, hre) => {
try {
const signers = await hre.ethers.getSigners()
if (signers.length === 0) {
throw new EthernautCliError(
'ethernaut-optigov',
'No signers available - If you are using the ethernaut-cli, please add one with `ethernaut wallet create`',
)
}
const signer = signers[0]
output.info(
`Logging in with address: ${signer.address}`,
'ethernaut-optigov',
)

const auth = new Auth()

const statement = 'Log in to Agoras RetroPGF API with SIWE.'
const nonce = await auth.getNonce()
const preparedMessage = createSiweMessage(
signer.address,
statement,
nonce,
)
const signature = await signer.signMessage(preparedMessage)

await auth.authenticateWithAgora(preparedMessage, signature, nonce)

return output.resultBox(`Logged in with address: ${signer.address})`)
} catch (err) {
return output.errorBox(err)
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type import('hardhat/config').HardhatUserConfig */
require('@nomicfoundation/hardhat-ethers')
require('../../../src/index')
require('../../../../ethernaut-ui/src/index')

module.exports = {
solidity: '0.8.24',
defaultNetwork: 'localhost',
}
Loading

0 comments on commit 138f1c2

Please sign in to comment.