Skip to content

Commit

Permalink
Merge pull request #1 from ubq-testing/development
Browse files Browse the repository at this point in the history
feat: permit module
  • Loading branch information
whilefoo authored Mar 27, 2024
2 parents 03466ad + bc419ab commit bcde7a0
Show file tree
Hide file tree
Showing 43 changed files with 5,639 additions and 388 deletions.
27 changes: 25 additions & 2 deletions .cspell.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
{
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
"version": "0.2",
"ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log"],
"ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log", "supabase"],
"useGitignore": true,
"language": "en",
"words": ["dataurl", "devpool", "outdir", "servedir"],
"dictionaries": ["typescript", "node", "software-terms"],
"import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"],
"ignoreRegExpList": ["[0-9a-fA-F]{6}"]
"ignoreRegExpList": ["[0-9a-fA-F]{6}"],
"ignoreWords": [
"keccak",
"mult",
"ensname",
"supabase",
"scalarmult",
"URLSAFE",
"Gddm",
"Njbl",
"knip",
"jiggery",
"pokery",
"URLSAFE2",
"Mult",
"WXDAI",
"ubiquibot",
"Supabase",
"supabase",
"libsodium",
"Libsodium",
"ciphertext",
"tweetnacl"
]
}
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
MY_SECRET="MY_SECRET"
X25519_PRIVATE_KEY=
NFT_MINTER_PRIVATE_KEY=
SUPABASE_URL=
SUPABASE_ANON_KEY=
31 changes: 0 additions & 31 deletions .github/workflows/cloudflare-deploy.yml

This file was deleted.

61 changes: 61 additions & 0 deletions .github/workflows/compute.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Permit Generation

on:
workflow_dispatch:
inputs:
stateId:
required: true
eventName:
required: true
eventPayload:
required: true
settings:
required: true
authToken:
required: true
ref:
required: true

jobs:
run:
runs-on: ubuntu-latest
permissions: write-all

steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20.10.0"

- name: Install dependencies
run: yarn

- name: Generate Permit
run: npx tsx ./src/index.ts
id: permit
env:
STATE_ID: ${{ github.event.inputs.stateId }}
EVENT_NAME: ${{ github.event.inputs.eventName }}
EVENT_PAYLOAD: ${{ github.event.inputs.eventPayload }}
SETTINGS: ${{ github.event.inputs.settings }}
AUTH_TOKEN: ${{ github.event.inputs.authToken }}
REF: ${{ github.event.inputs.ref }}

- name: Return Permit To The Kernel
uses: actions/github-script@v7
with:
script: |
const permitStr = '${{ steps.permit.outputs.result }}';
const permitObj = JSON.parse(permitStr);
await github.rest.repos.createDispatchEvent({
owner: "${{ github.repository }}".split("/")[0],
repo: "${{ github.repository }}".split("/")[1],
event_type: "return_data_to_ubiquibot_kernel",
client_payload: {
state_id: "${{ inputs.stateId }}",
output: JSON.stringify(permitObj),
},
});
34 changes: 34 additions & 0 deletions .github/workflows/jest-testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Run Jest testing suite
on:
workflow_dispatch:
pull_request_target:
types: [opened, synchronize]

env:
NODE_ENV: "test"

jobs:
testing:
permissions: write-all
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: "20.10.0"
- uses: actions/checkout@master
with:
fetch-depth: 0
- name: Build & Run test suite
run: |
npm i -g bun
bun install
bun test | tee ./coverage.txt && exit ${PIPESTATUS[0]}
- name: Jest Coverage Comment
# Ensures this step is run even on previous step failure (e.g. test failed)
if: always()
uses: MishaKav/jest-coverage-comment@main
with:
coverage-summary-path: coverage/coverage-summary.json
junitxml-path: junit.xml
junitxml-title: JUnit
coverage-path: ./coverage.txt
30 changes: 30 additions & 0 deletions .github/workflows/knip.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Knip

on:
pull_request:

permissions: write-all

jobs:
run-knip:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20.10.0

- name: Install toolchain
run: yarn install

- name: Report knip results to pull request
uses: Codex-/knip-reporter@v2
with:
verbose: true
comment_id: ${{ github.workflow }}-reporter
command_script_name: knip-ci
annotations: true
ignore_results: false
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ node_modules
.yarn
.pnp.cjs
.pnp.loader.mjs
.env
static/dist
.env
/coverage
junit.xml
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,42 @@
The input should be an array of permit descriptors:

```typescript
type PermitGenerationInput {
type PermitGenerationInput {
username: string;
amount: string;
address: string;
task: GitHubIssue | null;
task: GitHubIssue | null;
transfer: boolean;
evmPrivateKeyEncrypted: string;
}[]
```

###### Remarks

Mixed feelings on the following:

- `task` - Payments can possibly be for any reason from any plugin developer in our ecosystem, but in the foreseeable future (for V1) I think that they should be associated with a GitHub issue, or nothing.
- `transfer` - For automatically transferring the funds vs generating a permit. If we have access to the private key, we have the ability to make a transfer on their behalf.
- `task` - Payments can possibly be for any reason from any plugin developer in our ecosystem, but in the foreseeable future (for V1) I think that they should be associated with a GitHub issue, or nothing.
- `transfer` - For automatically transferring the funds vs generating a permit. If we have access to the private key, we have the ability to make a transfer on their behalf.

General remarks:

- `evmPrivateKeyEncrypted` - I researched GitHub App permissions and its a boolean for all organization secrets or none; or all repository secrets or none. I think that partners may be weary to share ALL secrets so perhaps it makes sense to proceed with the `X25519` `evmPrivateKeyEncrypted` system.

### Processing
### Processing

###### Data validation

1. Look up the GitHub global user ID (number) that corresponds with the username. Check if a user ID exists (does the user exist?), otherwise log an error and proceed. [^2^]
1. Look up the registered wallet address of the user from our database. [^3^]
3. Parse the amount and see if its a valid number.
4. ~~Look up the address on chain to see if a token exists there. If not, throw an error.~~
5. Verify that the `task.id` exists on GitHub. If not, throw an error. If it is `null` then skip this validation.
6. Record all the results in our database. `public.permits`
1. Look up the registered wallet address of the user from our database. [^3^]
1. Parse the amount and see if its a valid number.
1. ~~Look up the address on chain to see if a token exists there. If not, throw an error.~~
1. Verify that the `task.id` exists on GitHub. If not, throw an error. If it is `null` then skip this validation.
1. Record all the results in our database. `public.permits`

### Return

Return value should just be an array of generated permits. A seperate module can convert them into URLs for pay.ubq.fi.
Return value should just be an array of generated permits. A separate module can convert them into URLs for pay.ubq.fi.

[^1^]: I put a lot of thought into this and unless the plugins can hack X25519 encryption I think its fine for them to attempt brute forcing etc. In exhange its simpler infrastucture vs only accepting requests from the kernel (which seems more secure, but for V1 perhaps unnecessary.)
[^2^]: We pass in the username for enhanced developer experience for plugin development. I believe it will be much easier to use GitHub usernames and let the system do the lookup.
[^1^]: I put a lot of thought into this and unless the plugins can hack X25519 encryption I think its fine for them to attempt brute forcing etc. In exchange its simpler infrastructure vs only accepting requests from the kernel (which seems more secure, but for V1 perhaps unnecessary.)
[^2^]: We pass in the username for enhanced developer experience for plugin development. I believe it will be much easier to use GitHub usernames and let the system do the lookup.
[^3^]: Mixed feelings on this lookup because it does not self encapsulate this module well. We already have an optional database write for the permit record, but this plugin WILL break if there is a database issue for reading the user's registered wallet, which can make testing and development more difficult here. The alternative is to pass in the user's wallet here, but then the kernel (or another plugin) needs to look up their wallet address (this seems like the better approach.)
12 changes: 12 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { JestConfigWithTsJest } from "ts-jest";

module.exports = {
preset: "ts-jest",
testEnvironment: "node",
roots: ["./tests"],
coveragePathIgnorePatterns: ["node_modules", "mocks"],
collectCoverage: true,
coverageReporters: ["json", "lcov", "text", "clover", "json-summary"],
reporters: ["default", "jest-junit"],
coverageDirectory: "coverage",
} as JestConfigWithTsJest;
11 changes: 11 additions & 0 deletions knip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { KnipConfig } from "knip";

const config: KnipConfig = {
entry: ["build/index.ts"],
project: ["src/**/*.ts"],
ignore: ["src/types/config.ts"],
ignoreExportsUsedInFile: true,
ignoreDependencies: [],
};

export default config;
71 changes: 49 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "ts-template",
"name": "@ubiquibot/permit-generation",
"version": "1.0.0",
"description": "Template repository with TypeScript support.",
"main": "build/index.ts",
"main": "src/worker.ts",
"author": "Ubiquity DAO",
"license": "MIT",
"engines": {
Expand All @@ -15,7 +15,11 @@
"format:lint": "eslint --fix .",
"format:prettier": "prettier --write .",
"format:cspell": "cspell **/*",
"prepare": "husky install"
"knip": "knip",
"knip-ci": "knip --no-exit-code --reporter json",
"prepare": "husky install",
"worker": "wrangler dev --port 8789",
"test": "jest"
},
"keywords": [
"typescript",
Expand All @@ -25,30 +29,53 @@
"open-source"
],
"dependencies": {
"dotenv": "^16.3.1"
"@octokit/webhooks-types": "^7.3.1",
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0",
"@octokit/rest": "^20.0.2",
"@octokit/webhooks": "^13.1.0",
"@supabase/supabase-js": "^2.39.7",
"@sinclair/typebox": "^0.32.5",
"@uniswap/permit2-sdk": "^1.2.0",
"blake2b": "^2.1.4",
"decimal.js": "^10.4.3",
"dotenv": "^16.4.4",
"ethers": "^5.7.2",
"libsodium-wrappers": "^0.7.13",
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1"
},
"devDependencies": {
"@commitlint/cli": "^18.4.3",
"@commitlint/config-conventional": "^18.4.3",
"@cloudflare/workers-types": "^4.20240117.0",
"@commitlint/cli": "^18.6.1",
"@commitlint/config-conventional": "^18.6.2",
"@cspell/dict-node": "^4.0.3",
"@cspell/dict-software-terms": "^3.3.17",
"@cspell/dict-software-terms": "^3.3.18",
"@cspell/dict-typescript": "^3.1.2",
"@types/node": "^20.10.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"cspell": "^8.3.2",
"esbuild": "^0.19.8",
"eslint": "^8.54.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-sonarjs": "^0.23.0",
"husky": "^8.0.3",
"knip": "^3.3.0",
"lint-staged": "^15.1.0",
"@octokit/types": "^12.6.0",
"@types/libsodium-wrappers": "^0.7.8",
"@types/jest": "29.5.12",
"@types/node": "^20.11.19",
"@typescript-eslint/eslint-plugin": "^7.0.1",
"@typescript-eslint/parser": "^7.0.1",
"cspell": "^8.4.0",
"esbuild": "^0.20.1",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-sonarjs": "^0.24.0",
"husky": "^9.0.11",
"jest": "29.7.0",
"jest-junit": "16.0.0",
"knip": "^5.0.1",
"lint-staged": "^15.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^3.1.0",
"tsx": "^4.6.0",
"typescript": "^5.3.2"
"prettier": "^3.2.5",
"ts-jest": "29.1.2",
"ts-node": "10.9.2",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"wrangler": "^3.23.0"
},
"lint-staged": {
"*.ts": [
Expand Down
Loading

0 comments on commit bcde7a0

Please sign in to comment.