Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: npm package #7

Merged
merged 21 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6587b1b
chore: fixed yarn command
gentlementlegen Apr 3, 2024
f743a24
feat: package generation and publish
gentlementlegen Apr 4, 2024
628cb59
feat: rollup for package bundling
gentlementlegen Apr 4, 2024
ccea075
chore: method overload for erc 20 permit
gentlementlegen Apr 5, 2024
07ce892
Merge branch 'generate-erc20-permit' into feat/npm-package
gentlementlegen Apr 5, 2024
2f6be75
chore: method overload for ERC721 permits generation
gentlementlegen Apr 5, 2024
f15d6b6
v1.0.1
gentlementlegen Apr 5, 2024
e12709d
Merge branch 'development' into feat/npm-package
gentlementlegen Apr 7, 2024
6e82814
chore: updated package.json
gentlementlegen Apr 7, 2024
311ac9a
Merge branch 'development' into feat/npm-package
gentlementlegen Apr 7, 2024
2be290c
chore: export generatePayourPermit function
gentlementlegen Apr 8, 2024
48e6816
Merge branch 'development' into feat/npm-package
gitcoindev Apr 8, 2024
f764feb
chore: update yarn.lock after rebase
gitcoindev Apr 8, 2024
417e044
Merge branch 'development' into feat/npm-package
gentlementlegen Apr 8, 2024
4e647fa
Merge remote-tracking branch 'origin/feat/npm-package' into feat/npm-…
gentlementlegen Apr 8, 2024
dc7f36d
chore: upgraded action imports for publish-package.yml
gentlementlegen Apr 8, 2024
240f0a7
chore: fix issues reported by knip and update actions to v4
gitcoindev Apr 8, 2024
f44c861
chore: update knip fixes, add types/jest
gitcoindev Apr 8, 2024
0b392fe
chore: changed jest tests to trigger on pull_request not pull_request…
gentlementlegen Apr 8, 2024
a230c4f
test: explicitly import describe and expect from @jest/globals
gitcoindev Apr 8, 2024
1585826
chore: fixed test mock values
gentlementlegen Apr 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/jest-testing.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Run Jest testing suite
on:
workflow_dispatch:
pull_request_target:
pull_request:
types: [opened, synchronize]

env:
Expand Down
28 changes: 28 additions & 0 deletions .github/workflows/publish-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Publish Package

on:
workflow_dispatch:
push:
branches:
- main

jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: google-github-actions/release-please-action@v4
with:
release-type: node
package-name: "@ubiquibot/permit-generation"
default-branch: main
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20.10.0'
registry-url: https://registry.npmjs.org/
- run: |
yarn install --immutable --immutable-cache --check-cache
yarn pack
yarn publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ node_modules
.env
static/dist
/coverage
junit.xml
junit.xml
dist
3 changes: 2 additions & 1 deletion knip.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { KnipConfig } from "knip";

const config: KnipConfig = {
entry: ["build/index.ts"],
entry: ["src/main.ts"],
project: ["src/**/*.ts"],
ignore: [],
ignoreBinaries: ["publish"],
ignoreExportsUsedInFile: true,
ignoreDependencies: ["ts-node"],
jest: {
Expand Down
26 changes: 22 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"name": "@ubiquibot/permit-generation",
"version": "1.0.0",
"description": "Template repository with TypeScript support.",
"main": "src/index.ts",
"description": "ECR20 / ECR721 permit generation for automated payments.",
"author": "Ubiquity DAO",
"license": "MIT",
"engines": {
Expand All @@ -16,7 +15,8 @@
"knip": "knip",
"knip-ci": "knip --no-exit-code --reporter json",
"prepare": "husky install",
"test": "jest"
"test": "jest",
"build": "rollup -c"
},
"keywords": [
"typescript",
Expand All @@ -43,6 +43,13 @@
"@cspell/dict-node": "^4.0.3",
"@cspell/dict-software-terms": "^3.3.18",
"@cspell/dict-typescript": "^3.1.2",
"@jest/globals": "29.7.0",
"@jest/types": "29.6.3",
"@rollup/plugin-commonjs": "25.0.7",
"@rollup/plugin-json": "6.1.0",
"@rollup/plugin-node-resolve": "15.2.3",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-yaml": "4.1.2",
"@types/libsodium-wrappers": "^0.7.8",
"@types/node": "^20.11.19",
"@typescript-eslint/eslint-plugin": "^7.0.1",
Expand All @@ -57,6 +64,9 @@
"lint-staged": "^15.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^3.2.5",
"rollup": "4.14.0",
"rollup-plugin-dts-bundle-generator": "1.4.0",
"rollup-plugin-typescript2": "0.36.0",
"ts-jest": "29.1.2",
"ts-node": "10.9.2",
"tsx": "^4.7.1",
Expand All @@ -75,5 +85,13 @@
"extends": [
"@commitlint/config-conventional"
]
}
},
"files": [
"dist/*",
"README.md",
"package.json"
],
"module": "dist/index.esm.js",
"main": "dist/index.js",
"typings": "dist/index.d.ts"
}
16 changes: 16 additions & 0 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import typescript from "rollup-plugin-typescript2";
import yaml from "@rollup/plugin-yaml";
import { generateDtsBundle } from "rollup-plugin-dts-bundle-generator";
import nodeResolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import json from "@rollup/plugin-json";
import terser from "@rollup/plugin-terser";

export default {
input: "src/index.ts",
output: {
dir: "dist",
format: "cjs",
},
plugins: [nodeResolve(), commonjs(), typescript(), yaml(), json(), generateDtsBundle(), terser()],
};
92 changes: 64 additions & 28 deletions src/handlers/generate-erc20-permit.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,77 @@
import { PERMIT2_ADDRESS, PermitTransferFrom, SignatureTransfer } from "@uniswap/permit2-sdk";
import { ethers, keccak256, MaxInt256, parseUnits, toUtf8Bytes } from "ethers";
import { Context } from "../types/context";
import { Context, Logger } from "../types/context";
import { Permit } from "../types/permits";
import { decryptKeys } from "../utils/keys";
import { getPayoutConfigByNetworkId } from "../utils/payoutConfigByNetworkId";

export async function generateErc20PermitSignature(context: Context, username: string, amount: number): Promise<Permit> {
const config = context.config;
const logger = context.logger;
const { evmNetworkId, evmPrivateEncrypted } = config;
const { user, wallet } = context.adapters.supabase;
export async function generateErc20PermitSignature(
username: string,
amount: number,
evmNetworkId: number,
evmPrivateEncrypted: string,
userId: number,
walletAddress: string,
issueId: number,
logger: Logger
): Promise<Permit>;
export async function generateErc20PermitSignature(username: string, amount: number, context: Context): Promise<Permit>;
export async function generateErc20PermitSignature(
username: string,
amount: number,
contextOrNetworkId: Context | number,
gitcoindev marked this conversation as resolved.
Show resolved Hide resolved
evmPrivateEncrypted?: string,
userId?: number,
walletAddress?: string,
issueId?: number,
logger?: Logger
): Promise<Permit> {
let _logger: Logger;
let _userId: number;
let _walletAddress: string;
let _issueId: number;
let _evmNetworkId: number;
let _evmPrivateEncrypted: string;

const userId = await user.getUserIdByUsername(username);
const walletAddress = await wallet.getWalletByUserId(userId);
let issueId: string;
if ("issue" in context.payload) {
issueId = context.payload.issue.id.toString();
} else if ("pull_request" in context.payload) {
issueId = context.payload.pull_request.id.toString();
if (typeof contextOrNetworkId === "number") {
_logger = logger as Logger;
_userId = userId as number;
_walletAddress = walletAddress as string;
_evmNetworkId = contextOrNetworkId;
_evmPrivateEncrypted = evmPrivateEncrypted as string;
_issueId = issueId as number;
} else {
throw new Error("Issue Id is missing");
const config = contextOrNetworkId.config;
_logger = contextOrNetworkId.logger;
const { evmNetworkId, evmPrivateEncrypted } = config;
const { user, wallet } = contextOrNetworkId.adapters.supabase;
_userId = await user.getUserIdByUsername(username);
_walletAddress = await wallet.getWalletByUserId(_userId);
_evmNetworkId = evmNetworkId;
_evmPrivateEncrypted = evmPrivateEncrypted;
if ("issue" in contextOrNetworkId.payload) {
_issueId = contextOrNetworkId.payload.issue.id;
} else if ("pull_request" in contextOrNetworkId.payload) {
_issueId = contextOrNetworkId.payload.pull_request.id;
} else {
throw new Error("Issue Id is missing");
}
}

if (!userId) {
if (!_userId) {
throw new Error("User was not found");
}
if (!walletAddress) {
if (!_walletAddress) {
const errorMessage = "ERC20 Permit generation error: Wallet not found";
logger.error(errorMessage);
_logger.error(errorMessage);
throw new Error(errorMessage);
}

const { rpc, token, decimals } = getPayoutConfigByNetworkId(evmNetworkId);
const { privateKey } = await decryptKeys(evmPrivateEncrypted);
const { rpc, token, decimals } = getPayoutConfigByNetworkId(_evmNetworkId);
const { privateKey } = await decryptKeys(_evmPrivateEncrypted);
if (!privateKey) {
const errorMessage = "Private key is not defined";
logger.fatal(errorMessage);
_logger.fatal(errorMessage);
throw new Error(errorMessage);
}

Expand All @@ -44,26 +80,26 @@ export async function generateErc20PermitSignature(context: Context, username: s
try {
provider = new ethers.JsonRpcProvider(rpc);
} catch (error) {
throw logger.debug("Failed to instantiate provider", error);
throw _logger.debug("Failed to instantiate provider", error);
}

try {
adminWallet = new ethers.Wallet(privateKey, provider);
} catch (error) {
throw logger.debug("Failed to instantiate wallet", error);
throw _logger.debug("Failed to instantiate wallet", error);
}

const permitTransferFromData: PermitTransferFrom = {
permitted: {
token: token,
amount: parseUnits(amount.toString(), decimals),
},
spender: walletAddress,
nonce: BigInt(keccak256(toUtf8Bytes(`${userId}-${issueId}`))),
spender: _walletAddress,
nonce: BigInt(keccak256(toUtf8Bytes(`${_userId}-${_issueId}`))),
deadline: MaxInt256,
};

const { domain, types, values } = SignatureTransfer.getPermitData(permitTransferFromData, PERMIT2_ADDRESS, evmNetworkId);
const { domain, types, values } = SignatureTransfer.getPermitData(permitTransferFromData, PERMIT2_ADDRESS, _evmNetworkId);

const signature = await adminWallet
.signTypedData(
Expand All @@ -79,7 +115,7 @@ export async function generateErc20PermitSignature(context: Context, username: s
)
.catch((error) => {
const errorMessage = `Failed to sign typed data ${error}`;
logger.error(errorMessage);
_logger.error(errorMessage);
throw new Error(errorMessage);
});

Expand All @@ -92,10 +128,10 @@ export async function generateErc20PermitSignature(context: Context, username: s
amount: permitTransferFromData.permitted.amount.toString(),
owner: adminWallet.address,
signature: signature,
networkId: evmNetworkId,
networkId: _evmNetworkId,
};

logger.info("Generated ERC20 permit2 signature", erc20Permit);
_logger.info("Generated ERC20 permit2 signature", erc20Permit);

return erc20Permit;
}
Loading
Loading