Skip to content

Commit

Permalink
feat: initial working code
Browse files Browse the repository at this point in the history
  • Loading branch information
NotPeopling2day committed Sep 14, 2023
1 parent 0467611 commit 43503ec
Show file tree
Hide file tree
Showing 20 changed files with 617 additions and 2 deletions.
37 changes: 37 additions & 0 deletions .github/release-drafter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name-template: '$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'

categories:
- title: 'Features'
labels:
- 'feat'
- title: 'Bug Fixes'
labels:
- 'fix'
- title: 'Other updates'
labels:
- 'refactor'
- 'chore'
- 'docs'

change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.

version-resolver:
major:
labels:
- 'major'
minor:
labels:
- 'minor'
patch:
labels:
- 'patch'
default: patch

template: |
## Changes
$CHANGES
Special thanks to: $CONTRIBUTORS
27 changes: 27 additions & 0 deletions .github/workflows/commitlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
on: push

name: Commit Message

# NOTE: Skip check on PR so as not to confuse contributors
# NOTE: Also install a PR title checker so we don't mess up merges
jobs:
check:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.10"

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install commitizen
- name: Check commit history
run: cz check --rev-range $(git rev-list --all --reverse | head -1)..HEAD
17 changes: 17 additions & 0 deletions .github/workflows/draft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Release Drafter

on:
push:
branches:
- main

jobs:
update-draft:
runs-on: ubuntu-latest
steps:
# Drafts your next Release notes as Pull Requests are merged into "main"
- uses: release-drafter/release-drafter@v5
with:
disable-autolabeler: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 changes: 30 additions & 0 deletions .github/workflows/prtitle.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: PR Title

on:
pull_request_target:
types:
- opened
- edited
- synchronize

jobs:
check:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.10"

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install commitizen
- name: Check PR Title
env:
TITLE: ${{ github.event.pull_request.title }}
run: cz check --message "$TITLE"
89 changes: 89 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
on: ["push", "pull_request"]

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

name: Test

concurrency:
# Cancel older, in-progress jobs from the same PR, same workflow.
# use run_id if the job is triggered by a push to ensure
# push-triggered jobs to not get canceled.
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
linting:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.10"

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r dev-requirements.txt
- name: Run Black
run: black --check .

- name: Run isort
run: isort --check-only .

- name: Run flake8
run: flake8 .

- name: Run mdformat
run: mdformat . --check

type-check:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.10"

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r dev-requirements.txt
- name: Run MyPy
run: mypy .

functional:
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, macos-latest] # eventually add `windows-latest`
python-version: [3.8, 3.9, "3.10", "3.11"]

env:
GETH_VERSION: 1.12.0

steps:
- uses: actions/checkout@v3

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run Tests
run: pytest

1 change: 1 addition & 0 deletions .mdformat.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
number = true
36 changes: 36 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
hooks:
- id: check-yaml

- repo: https://github.com/pre-commit/mirrors-isort
rev: v5.10.1
hooks:
- id: isort

- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
name: black

- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.991
hooks:
- id: mypy
additional_dependencies: [types-setuptools, pydantic==1.10.4]

- repo: https://github.com/executablebooks/mdformat
rev: 0.7.14
hooks:
- id: mdformat
additional_dependencies: [mdformat-gfm, mdformat-frontmatter]

default_language_version:
python: python3
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
# hosted-compiler-new
Hosted compiler for working with Vyper files
# Overview

**Vyper Compiler** is a tool used to help [Remix Online IDE](https://remix-project.org/) compile Vyper contracts.

Vyper Compiler is built by [ApeWorX LTD](https://www.apeworx.io/).

If you have any questions please ask in our discord [ApeWorX Discord server](https://discord.gg/apeworx).

## Documentation

The compiler is built with Ape and fastAPI. It has multiple routes to engage the compiler in different parts of your journey to compiler the contract.


## Quickstart with local contracts

To show that it works. Clone this repo and deploy the local host server with `uvicorn main:app --reload`

Using the post route: Upload the contract file and version number of vyper.

Wait for it compile and while you wait, you can use the temporary directory name is the task ID to check the status of it.

Once it says success, you can use the `get compiled artifact` route and return the manifest of the contract.
6 changes: 6 additions & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-r requirements.txt
black
flake8
isort
mdformat
mypy
121 changes: 121 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import os
import tempfile
from enum import Enum
from pathlib import Path
from typing import Dict, List, Optional

from ape import config
from ethpm_types import PackageManifest
from fastapi import BackgroundTasks, FastAPI, HTTPException, Query, UploadFile
from pydantic import BaseModel

PackageManifest.update_forward_refs()
app = FastAPI()


class TaskStatus(Enum):
PENDING = "PENDING"
SUCCESS = "SUCCESS"
FAILED = "FAILED"


class Task(BaseModel):
id: str
status: TaskStatus = TaskStatus.PENDING
exceptions: List[str] = []
manifest: Optional[PackageManifest] = None


# global db
tasks: Dict[str, Task] = {}


def is_supported_language(filename):
# Add your supported languages here (Vyper)
supported_languages = [".vy"]
_, file_extension = os.path.splitext(filename)
return file_extension.lower() in supported_languages


@app.post("/compile/")
async def create_compilation_task(
background_tasks: BackgroundTasks,
files: List[UploadFile],
vyper_version: str = Query(
default=None,
title="Vyper version",
description="Vyper version to use for compilation",
),
) -> Task:
# Create a temporary directory for the project
project_root = Path(tempfile.mkdtemp(""))

# Create a contracts directory
contracts_dir = project_root / "contracts"
contracts_dir.mkdir()

# add request contracts in temp directory
for file in files:
if not is_supported_language(file.filename):
raise HTTPException(
status_code=400,
detail=f"Unsupported language for file {file.filename}",
)

content = (await file.read()).decode("utf-8")
(project_root / "contracts" / file.filename).write_text(content) # type: ignore [operator]

task_id = project_root.name

tasks[task_id] = Task(id=task_id)

# Run the compilation task in the background using TaskIQ
background_tasks.add_task(compile_project, task_id, project_root, vyper_version)

return tasks[task_id]


# NOTE: PackageManifest model fails during validation, temp workaround
@app.get("/compile/{task_id}", response_model=None)
async def get_compilation_task(task_id: str) -> Task:
if task_id not in tasks:
raise HTTPException(status_code=404, detail=f"Task id {task_id} not found.")
return tasks[task_id]


@app.get("/status/{task_id}")
async def get_task_status(task_id: str) -> TaskStatus:
if task_id not in tasks:
raise HTTPException(status_code=404, detail=f"Task id {task_id} not found.")
return tasks[task_id].status


@app.get("/exceptions/{task_id}")
async def get_task_exceptions(task_id: str) -> List[str]:
if task_id not in tasks:
raise HTTPException(status_code=404, detail=f"Task id {task_id} not found.")
return tasks[task_id].exceptions


# NOTE: PackageManifest model fails during validation, temp workaround
@app.get("/compiled_artifact/{task_id}", response_model=None)
async def get_compiled_artifact(task_id: str) -> PackageManifest:
if task_id not in tasks:
raise HTTPException(status_code=404, detail=f"Task id {task_id} not found.")
if tasks[task_id].status is not TaskStatus.SUCCESS:
raise HTTPException(status_code=404, detail="Task is not completed with Success status.")

return tasks[task_id].manifest # type: ignore [return-value]


async def compile_project(task_id: str, project_root: Path, vyper_version: str):
try:
# compiles the project
with config.using_project(project_root) as project:
tasks[task_id].manifest = project.extract_manifest()
except Exception as e:
tasks[task_id].status = TaskStatus.FAILED
tasks[task_id].exceptions.append(str(e))

if not tasks[task_id].exceptions:
tasks[task_id].status = TaskStatus.SUCCESS
Loading

0 comments on commit 43503ec

Please sign in to comment.