diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..647982b
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,30 @@
+# Use node alpine image as the base image
+FROM node:alpine
+# Set working directory in the container
+WORKDIR /app
+
+# Copy package.json and package-lock.json to the working directory
+COPY package*.json ./
+# Install dependencies
+RUN npm install
+RUN npm run build
+
+
+# Copy the env file
+COPY .env .
+
+# # Copy the env.txt file
+# COPY env.txt ./
+
+# # Create .env file and copy its content from env.txt
+# RUN touch .env && \
+# cat env.txt > .env
+
+# Copy the rest of the application files
+COPY . .
+
+# Expose port 3000 (assuming your application runs on this port)
+EXPOSE 3000
+
+# Command to run the application
+CMD ["npm", "run" , "dev"]
diff --git a/README.md b/README.md
index e375d46..323fcbc 100644
--- a/README.md
+++ b/README.md
@@ -53,27 +53,61 @@ A robust and secure REST API for interacting with Ionic Protocol across multiple
npm run dev
```
-## 📚 API Endpoints
+## 📚 API Documentation
-### Supply Assets
+### Swagger UI
+Access our interactive API documentation at `/api-docs` to:
+- Explore all available endpoints
+- Test API calls directly from your browser
+- View request/response schemas
+- Download OpenAPI specification
+
+### Available Endpoints
+
+
+Supply Assets
+
+```http
POST /beta/v0/ionic/supply/:chain
+```
Supply assets to an Ionic pool.
+
-### Withdraw Assets
+
+Withdraw Assets
+
+```http
POST /beta/v0/ionic/withdraw/:chain
+```
Withdraw your supplied assets.
+
+
+
+Borrow Assets
-### Borrow Assets
+```http
POST /beta/v0/ionic/borrow/:chain
+```
Borrow assets from a pool.
+
-### Repay Loan
+
+Repay Loan
+
+```http
POST /beta/v0/ionic/repay/:chain
+```
Repay your borrowed assets.
+
+
+
+Get Pool Address
-### Get Pool Address
-GET /beta/v0/ionic/pool-address/:chain/:asset
-Retrieve the pool address for a specific asset.
+```http
+GET /beta/v0/ionic/market-address/:chain/:asset
+```
+Retrieve the Market address for a specific asset.
+
## 🛠️ Tech Stack
@@ -96,6 +130,10 @@ This API implements several security measures:
Contributions are welcome! Please feel free to submit a Pull Request.
+## 📄 License
+
+This project is licensed under the MIT License - see the LICENSE file for details.
+
## ⚡ Performance
- Optimized for high throughput
diff --git a/package-lock.json b/package-lock.json
index ea69fa2..228de95 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,12 +13,16 @@
"dotenv": "^16.4.7",
"express": "^4.18.2",
"helmet": "^7.1.0",
+ "swagger-jsdoc": "^6.2.8",
+ "swagger-ui-express": "^5.0.1",
"viem": "^2.0.0"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/node": "^20.0.0",
+ "@types/swagger-jsdoc": "^6.0.4",
+ "@types/swagger-ui-express": "^4.1.7",
"ts-node-dev": "^2.0.0",
"typescript": "^5.0.0"
}
@@ -29,6 +33,50 @@
"integrity": "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==",
"license": "MIT"
},
+ "node_modules/@apidevtools/json-schema-ref-parser": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz",
+ "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jsdevtools/ono": "^7.1.3",
+ "@types/json-schema": "^7.0.6",
+ "call-me-maybe": "^1.0.1",
+ "js-yaml": "^4.1.0"
+ }
+ },
+ "node_modules/@apidevtools/openapi-schemas": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz",
+ "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@apidevtools/swagger-methods": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
+ "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
+ "license": "MIT"
+ },
+ "node_modules/@apidevtools/swagger-parser": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
+ "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
+ "license": "MIT",
+ "dependencies": {
+ "@apidevtools/json-schema-ref-parser": "^9.0.6",
+ "@apidevtools/openapi-schemas": "^2.0.4",
+ "@apidevtools/swagger-methods": "^3.0.2",
+ "@jsdevtools/ono": "^7.1.3",
+ "call-me-maybe": "^1.0.1",
+ "z-schema": "^5.0.1"
+ },
+ "peerDependencies": {
+ "openapi-types": ">=7"
+ }
+ },
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@@ -70,6 +118,12 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
+ "node_modules/@jsdevtools/ono": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
+ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
+ "license": "MIT"
+ },
"node_modules/@noble/curves": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz",
@@ -109,6 +163,13 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/@scarf/scarf": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
+ "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0"
+ },
"node_modules/@scure/base": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz",
@@ -311,6 +372,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "license": "MIT"
+ },
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
@@ -384,6 +451,24 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/swagger-jsdoc": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz",
+ "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/swagger-ui-express": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.7.tgz",
+ "integrity": "sha512-ovLM9dNincXkzH4YwyYpll75vhzPBlWx6La89wwvYH7mHjVpf0X0K/vR/aUM7SRxmr5tt9z7E5XJcjQ46q+S3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/express": "*",
+ "@types/serve-static": "*"
+ }
+ },
"node_modules/@types/ws": {
"version": "8.5.13",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
@@ -474,6 +559,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -484,7 +575,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true,
"license": "MIT"
},
"node_modules/binary-extensions": {
@@ -528,7 +618,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@@ -593,6 +682,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/call-me-maybe": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
+ "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
+ "license": "MIT"
+ },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -618,11 +713,19 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/commander": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
+ "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true,
"license": "MIT"
},
"node_modules/content-disposition": {
@@ -719,6 +822,18 @@
"node": ">=0.3.1"
}
},
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/dotenv": {
"version": "16.4.7",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
@@ -806,6 +921,15 @@
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -920,7 +1044,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true,
"license": "ISC"
},
"node_modules/fsevents": {
@@ -1097,7 +1220,6 @@
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "dev": true,
"license": "ISC",
"dependencies": {
"once": "^1.3.0",
@@ -1196,6 +1318,36 @@
"ws": "*"
}
},
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.mergewith": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
+ "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
+ "license": "MIT"
+ },
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@@ -1276,7 +1428,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
@@ -1370,12 +1521,18 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
+ "node_modules/openapi-types": {
+ "version": "12.1.3",
+ "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
+ "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/ox": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/ox/-/ox-0.6.0.tgz",
@@ -1418,7 +1575,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -1771,6 +1927,83 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/swagger-jsdoc": {
+ "version": "6.2.8",
+ "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz",
+ "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==",
+ "license": "MIT",
+ "dependencies": {
+ "commander": "6.2.0",
+ "doctrine": "3.0.0",
+ "glob": "7.1.6",
+ "lodash.mergewith": "^4.6.2",
+ "swagger-parser": "^10.0.3",
+ "yaml": "2.0.0-1"
+ },
+ "bin": {
+ "swagger-jsdoc": "bin/swagger-jsdoc.js"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/swagger-jsdoc/node_modules/glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/swagger-parser": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
+ "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
+ "license": "MIT",
+ "dependencies": {
+ "@apidevtools/swagger-parser": "10.0.3"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/swagger-ui-dist": {
+ "version": "5.18.2",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.18.2.tgz",
+ "integrity": "sha512-J+y4mCw/zXh1FOj5wGJvnAajq6XgHOyywsa9yITmwxIlJbMqITq3gYRZHaeqLVH/eV/HOPphE6NjF+nbSNC5Zw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@scarf/scarf": "=1.4.0"
+ }
+ },
+ "node_modules/swagger-ui-express": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz",
+ "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==",
+ "license": "MIT",
+ "dependencies": {
+ "swagger-ui-dist": ">=5.0.0"
+ },
+ "engines": {
+ "node": ">= v0.10.32"
+ },
+ "peerDependencies": {
+ "express": ">=4.0.0 || >=5.0.0-beta"
+ }
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -1959,6 +2192,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/validator": {
+ "version": "13.12.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
+ "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -2035,7 +2277,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true,
"license": "ISC"
},
"node_modules/ws": {
@@ -2069,6 +2310,15 @@
"node": ">=0.4"
}
},
+ "node_modules/yaml": {
+ "version": "2.0.0-1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz",
+ "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
@@ -2078,6 +2328,36 @@
"engines": {
"node": ">=6"
}
+ },
+ "node_modules/z-schema": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
+ "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash.get": "^4.4.2",
+ "lodash.isequal": "^4.5.0",
+ "validator": "^13.7.0"
+ },
+ "bin": {
+ "z-schema": "bin/z-schema"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "commander": "^9.4.1"
+ }
+ },
+ "node_modules/z-schema/node_modules/commander": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
}
}
}
diff --git a/package.json b/package.json
index 0a9a72b..0b65fe2 100644
--- a/package.json
+++ b/package.json
@@ -14,12 +14,16 @@
"dotenv": "^16.4.7",
"express": "^4.18.2",
"helmet": "^7.1.0",
+ "swagger-jsdoc": "^6.2.8",
+ "swagger-ui-express": "^5.0.1",
"viem": "^2.0.0"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/node": "^20.0.0",
+ "@types/swagger-jsdoc": "^6.0.4",
+ "@types/swagger-ui-express": "^4.1.7",
"ts-node-dev": "^2.0.0",
"typescript": "^5.0.0"
}
diff --git a/src/routes/ionic/index.ts b/src/routes/ionic/index.ts
index c0f3020..e6fe8bf 100644
--- a/src/routes/ionic/index.ts
+++ b/src/routes/ionic/index.ts
@@ -10,6 +10,7 @@ import { getChainConfig } from '../../utils/chains';
import { IonicPoolABI } from '../../abis/IonicPool';
import { createClient } from '@supabase/supabase-js';
import dotenv from 'dotenv';
+import swaggerRouter from './swagger';
dotenv.config();
@@ -53,7 +54,7 @@ async function getAssetPoolAddress(
): Promise {
try {
const { data, error } = await supabase
- .from('asset_master_data')
+ .from('asset_master_data_test2')
.select('ctoken_address')
.eq('chain_id', getChainId(chain))
.eq('underlying_symbol', asset);
@@ -245,7 +246,7 @@ router.post('/beta/v0/ionic/repay/:chain', async (req, res) => {
});
// Pool address endpoint
-router.get('/beta/v0/ionic/pool-address/:chain/:asset', async (req, res) => {
+router.get('/beta/v0/ionic/market-address/:chain/:asset', async (req, res) => {
try {
const { chain, asset } = req.params;
@@ -264,4 +265,5 @@ router.get('/beta/v0/ionic/pool-address/:chain/:asset', async (req, res) => {
}
});
+router.use(swaggerRouter);
export default router;
\ No newline at end of file
diff --git a/src/routes/ionic/supply.txt b/src/routes/ionic/supply.txt
deleted file mode 100644
index d100216..0000000
--- a/src/routes/ionic/supply.txt
+++ /dev/null
@@ -1,91 +0,0 @@
-import { Router } from 'express';
-import {
- createPublicClient,
- http,
- parseEther,
- encodeFunctionData,
- Address
-} from 'viem';
-import { getChainConfig } from '../../utils/chains';
-import { IonicPoolABI } from '../../abis/IonicPool';
-
-const router = Router();
-
-// Custom type for supported chains
-type SupportedChain = "optimism" | "base" | "mode";
-
-// Helper function to convert BigInt values to strings recursively
-const serializeBigInts = (obj: any): any => {
- if (typeof obj === 'bigint') {
- return obj.toString();
- }
- if (Array.isArray(obj)) {
- return obj.map(serializeBigInts);
- }
- if (obj && typeof obj === 'object') {
- return Object.fromEntries(
- Object.entries(obj).map(([key, value]) => [key, serializeBigInts(value)])
- );
- }
- return obj;
-};
-
-router.post('/beta/v0/ionic/supply/:chain', async (req, res) => {
- try {
- const { chain } = req.params;
- const {
- account, // User's address
- amount, // Amount to supply
- to // Pool address
- } = req.body;
-
- // Type assertion for chain parameter
- const chainConfig = getChainConfig(chain as SupportedChain);
-
- // Create public client
- const publicClient = createPublicClient({
- chain: chainConfig,
- transport: http()
- });
-
- // Encode the mint function data
- const data = encodeFunctionData({
- abi: IonicPoolABI,
- functionName: 'mint',
- args: [parseEther(amount)]
- });
-
- // First simulate the transaction
- const simulation = await publicClient.simulateContract({
- account: account as Address,
- address: to as Address,
- abi: IonicPoolABI,
- functionName: 'mint',
- args: [parseEther(amount)]
- });
-
- // Then prepare the transaction
- const tx = await publicClient.prepareTransactionRequest({
- account: account as Address,
- data,
- to: to as Address
- });
-
- // Serialize and return both
- const serializedTx = serializeBigInts(tx);
- return res.json({
- success: true,
- transaction: serializedTx,
- hash: simulation.result
- });
-
- } catch (error: any) {
- console.error('Supply error:', error);
- return res.status(500).json({
- success: false,
- error: error.message
- });
- }
-});
-
-export default router;
\ No newline at end of file
diff --git a/src/routes/ionic/swagger.ts b/src/routes/ionic/swagger.ts
new file mode 100644
index 0000000..78ffe59
--- /dev/null
+++ b/src/routes/ionic/swagger.ts
@@ -0,0 +1,294 @@
+import { Router } from 'express';
+import swaggerJsdoc from 'swagger-jsdoc';
+import swaggerUi from 'swagger-ui-express';
+
+const options = {
+ definition: {
+ openapi: '3.0.0',
+ info: {
+ title: 'Ionic API',
+ version: '0.1.0',
+ description: 'API for interacting with Ionic Protocol pools',
+ },
+ components: {
+ schemas: {
+ TransactionRequest: {
+ type: 'object',
+ properties: {
+ success: { type: 'boolean' },
+ transactionRequest: {
+ type: 'object',
+ properties: {
+ to: { type: 'string' },
+ data: { type: 'string' },
+ from: { type: 'string' },
+ value: { type: 'string', nullable: true },
+ },
+ },
+ },
+ },
+ Error: {
+ type: 'object',
+ properties: {
+ success: { type: 'boolean' },
+ error: { type: 'string' },
+ },
+ },
+ },
+ },
+ paths: {
+ '/beta/v0/ionic/supply/{chain}': {
+ post: {
+ tags: ['Ionic Operations'],
+ summary: 'Supply assets to an Ionic pool',
+ parameters: [
+ {
+ name: 'chain',
+ in: 'path',
+ required: true,
+ schema: {
+ type: 'string',
+ enum: ['optimism', 'base', 'mode', 'bob', 'fraxtal', 'lisk', 'ink', 'superseed', 'worldchain', 'swell', 'soneium', 'ozeantest', 'camptest'],
+ },
+ },
+ ],
+ requestBody: {
+ required: true,
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'object',
+ required: ['account', 'amount', 'asset'],
+ properties: {
+ account: { type: 'string' },
+ amount: { type: 'string' },
+ asset: { type: 'string' },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: 'Successful operation',
+ content: {
+ 'application/json': {
+ schema: { $ref: '#/components/schemas/TransactionRequest' },
+ },
+ },
+ },
+ 400: {
+ description: 'Invalid input',
+ content: {
+ 'application/json': {
+ schema: { $ref: '#/components/schemas/Error' },
+ },
+ },
+ },
+ },
+ },
+ },
+ '/beta/v0/ionic/withdraw/{chain}': {
+ post: {
+ tags: ['Ionic Operations'],
+ summary: 'Withdraw assets from an Ionic pool',
+ parameters: [
+ {
+ name: 'chain',
+ in: 'path',
+ required: true,
+ schema: {
+ type: 'string',
+ enum: ['optimism', 'base', 'mode', 'bob', 'fraxtal', 'lisk', 'ink', 'superseed', 'worldchain', 'swell', 'soneium', 'ozeantest', 'camptest'],
+ },
+ },
+ ],
+ requestBody: {
+ required: true,
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'object',
+ required: ['account', 'amount', 'asset'],
+ properties: {
+ account: { type: 'string' },
+ amount: { type: 'string' },
+ asset: { type: 'string' },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: 'Successful operation',
+ content: {
+ 'application/json': {
+ schema: { $ref: '#/components/schemas/TransactionRequest' },
+ },
+ },
+ },
+ 400: {
+ description: 'Invalid input',
+ content: {
+ 'application/json': {
+ schema: { $ref: '#/components/schemas/Error' },
+ },
+ },
+ },
+ },
+ },
+ },
+ '/beta/v0/ionic/borrow/{chain}': {
+ post: {
+ tags: ['Ionic Operations'],
+ summary: 'Borrow assets from an Ionic pool',
+ parameters: [
+ {
+ name: 'chain',
+ in: 'path',
+ required: true,
+ schema: {
+ type: 'string',
+ enum: ['optimism', 'base', 'mode', 'bob', 'fraxtal', 'lisk', 'ink', 'superseed', 'worldchain', 'swell', 'soneium', 'ozeantest', 'camptest'],
+ },
+ },
+ ],
+ requestBody: {
+ required: true,
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'object',
+ required: ['account', 'amount', 'asset'],
+ properties: {
+ account: { type: 'string' },
+ amount: { type: 'string' },
+ asset: { type: 'string' },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: 'Successful operation',
+ content: {
+ 'application/json': {
+ schema: { $ref: '#/components/schemas/TransactionRequest' },
+ },
+ },
+ },
+ 400: {
+ description: 'Invalid input',
+ content: {
+ 'application/json': {
+ schema: { $ref: '#/components/schemas/Error' },
+ },
+ },
+ },
+ },
+ },
+ },
+ '/beta/v0/ionic/repay/{chain}': {
+ post: {
+ tags: ['Ionic Operations'],
+ summary: 'Repay borrowed assets to an Ionic pool',
+ parameters: [
+ {
+ name: 'chain',
+ in: 'path',
+ required: true,
+ schema: {
+ type: 'string',
+ enum: ['optimism', 'base', 'mode', 'bob', 'fraxtal', 'lisk', 'ink', 'superseed', 'worldchain', 'swell', 'soneium', 'ozeantest', 'camptest'],
+ },
+ },
+ ],
+ requestBody: {
+ required: true,
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'object',
+ required: ['account', 'amount', 'asset'],
+ properties: {
+ account: { type: 'string' },
+ amount: { type: 'string' },
+ asset: { type: 'string' },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: 'Successful operation',
+ content: {
+ 'application/json': {
+ schema: { $ref: '#/components/schemas/TransactionRequest' },
+ },
+ },
+ },
+ 400: {
+ description: 'Invalid input',
+ content: {
+ 'application/json': {
+ schema: { $ref: '#/components/schemas/Error' },
+ },
+ },
+ },
+ },
+ },
+ },
+ '/beta/v0/ionic/market-address/{chain}/{asset}': {
+ get: {
+ tags: ['Pool Information'],
+ summary: 'Get pool address for a specific asset',
+ parameters: [
+ {
+ name: 'chain',
+ in: 'path',
+ required: true,
+ schema: {
+ type: 'string',
+ enum: ['optimism', 'base', 'mode', 'bob', 'fraxtal', 'lisk', 'ink', 'superseed', 'worldchain', 'swell', 'soneium', 'ozeantest', 'camptest'],
+ },
+ },
+ {
+ name: 'asset',
+ in: 'path',
+ required: true,
+ schema: { type: 'string' },
+ },
+ ],
+ responses: {
+ 200: {
+ description: 'Successful operation',
+ content: {
+ 'application/json': {
+ schema: {
+ type: 'object',
+ properties: {
+ success: { type: 'boolean' },
+ poolAddress: { type: 'string' },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ apis: ['./src/routes/ionic/index.ts'], // Path to the API routes
+};
+
+const specs = swaggerJsdoc(options);
+
+const router = Router();
+router.use('/api-docs', swaggerUi.serve);
+router.get('/api-docs', swaggerUi.setup(specs));
+
+export default router;
\ No newline at end of file