Skip to content

Commit

Permalink
Merge pull request #1 from LIT-Protocol/LIT-2504
Browse files Browse the repository at this point in the history
LIT-2504 - Implement scheduled tasks - Capacity NFT top-up
  • Loading branch information
MaximusHaximus authored Mar 29, 2024
2 parents 91d8a38 + ce041be commit 3527b72
Show file tree
Hide file tree
Showing 65 changed files with 9,258 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ root = true
[*]
end_of_line = lf
insert_final_newline = true
max_line_length = 120
max_line_length = 100
indent_style = space
indent_size = 2
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
MONGO_PASSWORD=1234567890
MONGO_SERVER=exampleserver.mongodb.net
MONGO_USER=dev
MONGO_DB_NAME=dev_task_db
NFT_MINTER_KEY=1234567890123456789012345678901234
NFT_MINTER_ADDRESS=0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
RECIPIENT_LIST_URL=https://example.com/location/of/json_file.json
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
node_modules
81 changes: 81 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Eslint config applies to all packages - except each package must define mocha-specific overrides
* due to complexity in identifying dependencies and their sources from parent package.json files
*/
module.exports = {
root: true,
env: { node: true },
parserOptions: {
project: './tsconfig.json',
},
plugins: ['import', 'chai-friendly', 'sort-destructure-keys', 'sort-keys-plus'],
overrides: [
{
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
extends: [
'eslint:recommended',
'airbnb-base',
'airbnb-typescript/base',
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:chai-friendly/recommended',
'plugin:typescript-sort-keys/recommended',
'prettier',
],
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
'import/internal-regex': '^@lit-protocol/',
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/extensions': ['.js', '.jsx', '.ts', '.tsx'],
},
rules: {
'no-console': 'error',
'import/prefer-default-export': ['off'],
'import/no-default-export': ['error'],
'import/no-relative-packages': ['error'],
'import/no-duplicates': ['error'],
'import/no-unresolved': ['error'],
'import/order': [
'error',
{
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
'newlines-between': 'always',
groups: [
'builtin',
'external',
'internal',
['sibling', 'parent', 'index'],
'object',
'type',
],
},
],
'typescript-sort-keys/interface': 'error',
'typescript-sort-keys/string-enum': 'error',
'sort-keys-plus/sort-keys': [
'error',
'asc',
{
caseSensitive: false,
natural: true,
minKeys: 2,
allowLineSeparatedGroups: true,
allCaps: 'first',
shorthand: 'first',
},
],
'sort-destructure-keys/sort-destructure-keys': ['error', { caseSensitive: false }],
'class-methods-use-this': ['off'],
},
},
],
};
13 changes: 8 additions & 5 deletions .github/workflows/pr_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,25 @@ jobs:
- name: Install PNPM
uses: pnpm/action-setup@v2
with:
version: 6.32.9
version: 8.15.5
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
node-version-file: '.nvmrc'
cache: 'pnpm'
- name: Install project dependencies
run: pnpm install
- name: Build packages - for Typescript workspace references
run: pnpm build
- name: Lint
run: pnpm lint
- name: Validate Recipients JSON format
run: pnpm ci_validate

tests:
needs: 'lint'
name: 'Tests'
Expand All @@ -41,19 +44,19 @@ jobs:
- name: Install PNPM
uses: pnpm/action-setup@v2
with:
version: 6.32.9
version: 8.15.5
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
node-version-file: '.nvmrc'
cache: 'pnpm'
- name: Install project dependencies
run: pnpm install
- name: Build packages - for Typescript workspace references
run: pnpm build
- name: Lint
- name: Tests
run: pnpm test
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
dist
/packages/**/dist
node_modules

# dotEnv files should not be committed
.env*
!.env.vault

# IDE config
/.idea
/.vscode
Expand Down
5 changes: 5 additions & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh
if ! head -1 "$1" | grep -qE "^(feat|fix|chore|docs|test|style|refactor|perf|build|ci|revert)(\(.+?\))?: .{1,}$"; then
echo "Aborting commit. Your commit message must match https://www.conventionalcommits.org/en/v1.0.0/" >&2
exit 1
fi
2 changes: 2 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pnpm lint-staged
pnpm validate
4 changes: 4 additions & 0 deletions .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"*.{ts,tsx,cjs,js}": ["prettier --write", "eslint --fix"],
"*.json,md": ["prettier --write"]
}
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/node_modules
/packages/**/dist
/packages/**/node_modules
pnpm-lock.yaml
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"plugins": ["./node_modules/prettier-plugin-jsdoc/dist/index.js"],
"trailingComma": "es5",
"singleQuote": true,
"semi": true
}
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
worker: pnpm start
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# 🔥 LIT Scheduled Tasks 🔧

This repo provides scaffolding for running internal scheduled tasks on a CRON-like schedule.

## ❌ Installation

Packages in this repository are currently not published to NPM; it is expected to be deployed as a worker to Heroku.

## 🎮 Usage

#### To prepare for either production usage or local development, you must install dependencies and build the packages.

```zsh
pnpm install && pnpm build
```

#### For local development:

Note that local development uses `dotenvx` to load necessary environment vars from a `.env` file which must be located in the root directory of the repository to be loaded.

```zsh
pnpm dev
```

#### For production:

Note that [all environment variables](.env.example) for the worker process must be defined in the host environment. Production does not use `dotenvx`.

```zsh
pnpm start
```

## 📦 Packages

| Package | Purpose |
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| [lit-task-client](packages/lit-task-client/README.md) | Load and validate mongo credentials from env in a type-safe way, and produce a task client Agenda instance |
| [lit-task-auto-top-up](packages/lit-task-auto-top-up/README.md) | Task to mint capacity credit NFTs for a list of recipient addresses defined in JSON at a configured URL |

## 💻 Development

The repository is a mono-repo leveraging `pnpm` as the package manager, using `pnpm workspaces`. It requires Node v18+, it is recommended that you use `nvm` to select the correct node version via the included `.nvmrc` file.

- Clone the repository
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
- Install dependencies by executing `pnpm install` in the root of the repo
- Build all packages by executing `pnpm build` in the root of the repo
- Currently, you must manually rebuild packages that are referenced locally using `workspace:*` references after making changes, until `unbuild stub` issues with Typescript have been resolved. Reference issue: https://github.com/unjs/unbuild/issues/370
7 changes: 7 additions & 0 deletions bin/validateJSONRecipients.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { recipientDetailSchema } from 'lit-task-auto-top-up';
// eslint-disable-next-line import/no-extraneous-dependencies
import { z } from 'zod';

import recipientList from '../worker/recipient_list.json' assert { type: 'json' };

z.array(recipientDetailSchema).parse(recipientList);
63 changes: 63 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"name": "lit-scheduled-tasks",
"private": true,
"version": "1.0.0",
"description": "Scheduled tasks for LIT Protocol",
"homepage": "https://github.com/LIT-protocol/lit-scheduled-tasks",
"engines": {
"node": "^18.19.1",
"pnpm": "8.15.5"
},
"type": "module",
"scripts": {
"build": "pnpm -r run build && pnpm tsc",
"lint": "pnpm eslint .",
"clean": "pnpm exec rm -Rf node_modules dist && pnpm --parallel -r run clean",
"test": "pnpm -r run test",
"dev": "pnpm build && pnpm dotenvx run -- node ./dist/worker/worker_test_run_now.js",
"start": "pnpm build && node ./dist/worker/worker.js",
"prepare": "husky",
"ci_validate": "node ./dist/bin/validateJSONRecipients.js",
"validate": "pnpm tsc && node ./dist/bin/validateJSONRecipients.js"
},
"packageManager": "[email protected]",
"keywords": [],
"author": "Daryl Collins <[email protected]>",
"license": "ISC",
"devDependencies": {
"@dotenvx/dotenvx": "^0.26.0",
"@tsconfig/node18": "^18.2.2",
"@types/chai": "^4.3.14",
"@types/lodash": "^4.17.0",
"@types/mocha": "^10.0.6",
"@types/node": "^20.11.30",
"@types/verror": "^1.10.10",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"chai": "^5.1.0",
"eslint": "^8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-chai-friendly": "^0.7.4",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-sort-destructure-keys": "^1.5.0",
"eslint-plugin-sort-keys-plus": "^1.4.0",
"eslint-plugin-typescript-sort-keys": "^3.2.0",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"mocha": "^10.3.0",
"prettier": "^3.2.5",
"prettier-plugin-jsdoc": "^1.3.0",
"tsx": "^4.7.1",
"typescript": "^5.4.3",
"unbuild": "^2.0.0",
"zod": "^3.22.4"
},
"dependencies": {
"consola": "^3.2.3",
"lit-task-auto-top-up": "workspace:*",
"lit-task-client": "workspace:*",
"lodash": "^4.17.21"
}
}
3 changes: 3 additions & 0 deletions packages/lit-task-auto-top-up/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NFT_MINTER_KEY=1234567890123456789012345678901234
NFT_MINTER_ADDRESS=0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
RECIPIENT_LIST_URL=https://example.com/location/of/json_file.json
2 changes: 2 additions & 0 deletions packages/lit-task-auto-top-up/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
node_modules
6 changes: 6 additions & 0 deletions packages/lit-task-auto-top-up/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
parserOptions: {
tsconfigRootDir: __dirname,
},
extends: ['../../.eslintrc.cjs'],
};
6 changes: 6 additions & 0 deletions packages/lit-task-auto-top-up/.mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"require": ["tsx"],
"extensions": ["ts", "tsx"],
"spec": ["tests/**/*.ts"],
"watch-files": ["src", "tests/**/*.ts"]
}
22 changes: 22 additions & 0 deletions packages/lit-task-auto-top-up/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# 🔥 Auto Top-up Task 🔧

Mint [Capacity Credit NFTs](https://developer.litprotocol.com/v3/sdk/capacity-credits) to a list of recipients on a schedule.

### Usage

- This module is designed to be used with `lit-task-client`
- Recipients are loaded from a URL by the task when it executes. See `recipientDetailSchema` exported `zod` schema for format of recipients.
- See [.env.example](.env.example) file for required ENV vars for this task.

### Exports

| Name | Purpose |
| ------------------------- | --------------------------------------------------------------------------------------------- |
| **taskName** | Used to identify the name of the task for Agenda |
| **getConfig** | Method that loads required configuration for this task in a type-safe way from process.env |
| **TaskHandler** | Class that receives Config from `getConfig()` and exposes `handleTask(job: AgendaJob)` method |
| **recipientDetailSchema** | `zod` schema for validating JSON entries describing recipients of capacity NFTs |

### Development

See [root README](../../README.md) for development details
Loading

0 comments on commit 3527b72

Please sign in to comment.