Repository: pcaversaccio/snekmate (language: python)

Issue:
🫡 Release Version `0.0.1`
- [x] Final review of the repository & push a final gas snapshot
- [x] Add "Installation" to `README`; add `npm` and `PyPI` markdown badges; add release date to `CHANGELOG`
- [x] Prepare `package.json`
- [x] Prepare `PyPI` release
- [x] Make Test `PyPI` release
- [x] Publish GitHub release
- [x] Publish `npm` release
- [x] Publish `PyPI` release
- [x] Close milestone `0.0.1`


Discussion / hints:

Fix patch:
diff --git a/.gas-snapshot b/.gas-snapshot
index 1fa3facc..6416d665 100644
--- a/.gas-snapshot
+++ b/.gas-snapshot
@@ -167,11 +167,11 @@ ERC1155Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 49312, ~:
 ERC1155Test:testFuzzSafeBatchTransferFromByApprovedOperator(address,address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 226308, ~: 226270)
 ERC1155Test:testFuzzSafeBatchTransferFromEOAReceiver(address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 191164, ~: 191139)
 ERC1155Test:testFuzzSafeBatchTransferFromNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 572169, ~: 572179)
-ERC1155Test:testFuzzSafeBatchTransferFromWithData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 572696, ~: 572277)
+ERC1155Test:testFuzzSafeBatchTransferFromWithData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 572692, ~: 572277)
 ERC1155Test:testFuzzSafeMintBatchEOAReceiver(address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 153564, ~: 153557)
 ERC1155Test:testFuzzSafeMintBatchNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 528841, ~: 528851)
 ERC1155Test:testFuzzSafeMintBatchNonMinter(address) (runs: 256, μ: 41249, ~: 41249)
-ERC1155Test:testFuzzSafeMintBatchWithData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 529274, ~: 529055)
+ERC1155Test:testFuzzSafeMintBatchWithData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 529272, ~: 529055)
 ERC1155Test:testFuzzSafeMintEOAReceiver(address,address,uint256,uint256,uint256,uint256,bytes) (runs: 256, μ: 146764, ~: 146739)
 ERC1155Test:testFuzzSafeMintNoData(address,uint256,uint256,uint256,uint256) (runs: 256, μ: 523047, ~: 523057)
 ERC1155Test:testFuzzSafeMintNonMinter(address) (runs: 256, μ: 33621, ~: 33621)
diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml
new file mode 100644
index 00000000..633c1690
--- /dev/null
+++ b/.github/workflows/publish-npm.yml
@@ -0,0 +1,46 @@
+name: 📦 Publish 🐍 snekmate to npm
+
+on:
+  release:
+    types: [published]
+
+jobs:
+  publish:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os:
+          - ubuntu-latest
+        node_version:
+          - 16
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+
+      - name: Get Yarn cache directory path
+        id: yarn-cache-dir-path
+        run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
+
+      - name: Restore Yarn cache
+        uses: actions/cache@v3
+        id: yarn-cache
+        with:
+          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
+          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
+          restore-keys: |
+            ${{ runner.os }}-yarn-
+
+      - name: Setup .npmrc file to publish to npm
+        uses: actions/setup-node@v3
+        with:
+          node-version: ${{ matrix.node_version }}
+          registry-url: "https://registry.npmjs.org"
+
+      - name: Install Yarn project with a clean slate
+        run: yarn install --prefer-offline --frozen-lockfile
+
+      - name: Publish to npm
+        run: yarn publish
+        env:
+          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml
new file mode 100644
index 00000000..1dde516b
--- /dev/null
+++ b/.github/workflows/publish-pypi.yml
@@ -0,0 +1,46 @@
+name: 📦 Publish 🐍 snekmate to PyPI
+
+on:
+  release:
+    types: [published]
+
+jobs:
+  build-n-publish:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os:
+          - ubuntu-latest
+        python-version:
+          - "3.10"
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+
+      - name: Setup Python
+        uses: actions/setup-python@v4
+        with:
+          python-version: ${{ matrix.python-version }}
+
+      - name: Install pypa/build
+        run: >-
+          python -m
+          pip install
+          build
+          --user
+
+      - name: Build a binary wheel and a source tarball
+        run: >-
+          python -m
+          build
+          --sdist
+          --wheel
+          --outdir dist/
+          .
+
+      - name: Publish to PyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          user: __token__
+          password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/.gitignore b/.gitignore
index f1556dad..b434334c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,3 +47,7 @@ yarn-error.log*
 bin
 cache
 out
+
+# Python build files
+dist
+*.egg-info
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cce328ac..18e5016a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
 # 🕓 Changelog
 
-## `0.0.1` (Unreleased)
+## `0.0.1` (06-03-2023)
 
 ### New Features
 
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 00000000..14c5d291
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,2 @@
+include LICENSE README.md CHANGELOG.md pyproject.toml
+graft src
diff --git a/README.md b/README.md
index c25889ad..06527dcd 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
 
 [![Test smart contracts](https://github.com/pcaversaccio/snekmate/actions/workflows/test-contracts.yml/badge.svg)](https://github.com/pcaversaccio/snekmate/actions/workflows/test-contracts.yml)
 [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
+[![npm package](https://img.shields.io/npm/v/snekmate.svg)](https://www.npmjs.com/package/snekmate)
+[![PyPI package](https://img.shields.io/pypi/v/snekmate?color=blue)](https://pypi.org/project/snekmate)
 
 **State-of-the-art**, **highly opinionated**, **hyper-optimised**, and **secure** 🐍Vyper smart contract building blocks.
 
@@ -34,6 +36,40 @@ src
    ├─ Multicall — "Multicall Functions"
 ```
 
+## 🎛 Installation
+
+We offer three convenient ways to install the 🐍 snekmate contracts:
+
+### 1️⃣ Foundry
+
+You can install 🐍 snekmate via submodules using [Foundry](https://github.com/foundry-rs/foundry) with:
+
+```bash
+forge install pcaversaccio/snekmate
+```
+
+### 2️⃣ PyPI
+
+You can install 🐍 snekmate from [PyPI](https://pypi.org/project/snekmate) with:
+
+```bash
+pip install snekmate
+```
+
+### 3️⃣ npm
+
+You can install 🐍 snekmate from [npm](https://www.npmjs.com/package/snekmate) with:
+
+```bash
+npm install --save-dev snekmate
+```
+
+Or if you are using [Yarn](https://classic.yarnpkg.com):
+
+```bash
+yarn add --dev snekmate
+```
+
 ## 👩🏼‍⚖️ Tests
 
 This repository contains [Foundry](https://github.com/foundry-rs/foundry)-based unit tests, property-based tests (i.e. fuzzing), and invariant tests for all contracts, if applicable. All tests are run as part of the CI pipeline [`test-contracts`](./.github/workflows/test-contracts.yml).
diff --git a/package.json b/package.json
index c6d11ed2..925d93e1 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,8 @@
   "name": "snekmate",
   "version": "0.0.1",
   "description": "State-of-the-art, highly opinionated, hyper-optimised, and secure Vyper smart contract building blocks.",
+  "author": "Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>",
+  "license": "AGPL-3.0",
   "keywords": [
     "security",
     "library",
@@ -19,8 +21,6 @@
   "bugs": {
     "url": "https://github.com/pcaversaccio/snekmate/issues"
   },
-  "author": "Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>",
-  "license": "AGPL-3.0",
   "scripts": {
     "prettier:check": "prettier -c **/*.{md,sol,js,json,yml}",
     "prettier:fix": "prettier -w **/*.{md,sol,js,json,yml}",
@@ -29,6 +29,12 @@
     "lint:check": "yarn prettier:check && yarn solhint:check && eslint --ext .js .",
     "lint:fix": "yarn prettier:fix && yarn solhint:fix && eslint --ext .js . --fix"
   },
+  "files": [
+    "src/**/*.vy",
+    "LICENSE",
+    "README.md",
+    "CHANGELOG.md"
+  ],
   "devDependencies": {
     "@openzeppelin/merkle-tree": "^1.0.2",
     "eslint": "^8.35.0",
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..ba076623
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,29 @@
+[project]
+name = "snekmate"
+version = "0.0.1"
+description = "State-of-the-art, highly opinionated, hyper-optimised, and secure Vyper smart contract building blocks."
+readme = {file = "README.md", content-type = "text/markdown"}
+requires-python = ">=3.6"
+license = {text = "AGPL-3.0 License"}
+keywords = ["security", "library", "ethereum", "smart-contracts", "evm", "vyper", "vyper-contracts"]
+authors = [
+  {name = "Pascal Marco Caversaccio", email = "pascal.caversaccio@hotmail.ch"},
+]
+maintainers = [
+  {name = "Pascal Marco Caversaccio", email = "pascal.caversaccio@hotmail.ch"},
+]
+classifiers = [
+  "Development Status :: 5 - Production/Stable",
+  "License :: OSI Approved :: GNU Affero General Public License v3",
+  "Operating System :: POSIX :: Linux",
+  "Operating System :: Microsoft :: Windows",
+  "Operating System :: MacOS",
+]
+dependencies = [
+  "vyper>=3.7",
+]
+
+[project.urls]
+Homepage = "https://github.com/pcaversaccio/snekmate#readme"
+GitHub = "https://github.com/pcaversaccio/snekmate"
+Changelog = "https://github.com/pcaversaccio/snekmate/blob/main/CHANGELOG.md"


Test patch:
diff --git a/.github/workflows/publish-test-pypi.yml b/.github/workflows/publish-test-pypi.yml
new file mode 100644
index 00000000..f6e6fb0b
--- /dev/null
+++ b/.github/workflows/publish-test-pypi.yml
@@ -0,0 +1,45 @@
+name: 📦 Publish 🐍 snekmate to TestPyPI
+
+on: [workflow_dispatch]
+
+jobs:
+  build-n-publish:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os:
+          - ubuntu-latest
+        python-version:
+          - "3.10"
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+
+      - name: Setup Python
+        uses: actions/setup-python@v4
+        with:
+          python-version: ${{ matrix.python-version }}
+
+      - name: Install pypa/build
+        run: >-
+          python -m
+          pip install
+          build
+          --user
+
+      - name: Build a binary wheel and a source tarball
+        run: >-
+          python -m
+          build
+          --sdist
+          --wheel
+          --outdir dist/
+          .
+
+      - name: Publish to TestPyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          user: __token__
+          password: ${{ secrets.TEST_PYPI_API_TOKEN }}
+          repository_url: https://test.pypi.org/legacy/