From fa39f307f04ac1262b8fd7d80032bbe9ad7905cb Mon Sep 17 00:00:00 2001 From: Chris Maree Date: Mon, 22 Mar 2021 08:35:57 +0200 Subject: [PATCH] feat(cloud-functions): initial simple cloud functions for calculating UMA TVL and fetching KPI options recipients (#2697) * Added cloud functions package Signed-off-by: Christopher Maree * Added serverless functions Signed-off-by: Christopher Maree * Added yarn lock Signed-off-by: Christopher Maree * removed lock files Signed-off-by: Christopher Maree * Added readme file Signed-off-by: Christopher Maree * Added cashing solution to tvl Signed-off-by: Christopher Maree * Updated README.md Signed-off-by: Christopher Maree * Updated Signed-off-by: Christopher Maree * Updated for cors Signed-off-by: Christopher Maree * Updated cors logig Signed-off-by: Christopher Maree * Added private Signed-off-by: Christopher Maree --- lerna.json | 2 +- package.json | 2 +- packages/cloud-functions/README.md | 13 +++++++++ .../merkle-distributor-helper/index.js | 25 +++++++++++++++++ .../merkle-distributor-helper/package.json | 8 ++++++ .../uma-tvl-calculator/index.js | 27 +++++++++++++++++++ .../uma-tvl-calculator/package.json | 9 +++++++ .../cloud-functions/uma-tvl-fetcher/index.js | 20 ++++++++++++++ .../uma-tvl-fetcher/package.json | 8 ++++++ 9 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 packages/cloud-functions/README.md create mode 100644 packages/cloud-functions/merkle-distributor-helper/index.js create mode 100644 packages/cloud-functions/merkle-distributor-helper/package.json create mode 100644 packages/cloud-functions/uma-tvl-calculator/index.js create mode 100644 packages/cloud-functions/uma-tvl-calculator/package.json create mode 100644 packages/cloud-functions/uma-tvl-fetcher/index.js create mode 100644 packages/cloud-functions/uma-tvl-fetcher/package.json diff --git a/lerna.json b/lerna.json index bcdca04159..3b56dfffde 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "packages": ["packages/*"], + "packages": ["packages/**"], "npmClient": "yarn", "useWorkspaces": true, "version": "independent" diff --git a/package.json b/package.json index a27c417851..d8edbda38f 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,6 @@ "*.{js,ts,tsx}": "eslint --cache --fix" }, "workspaces": [ - "packages/*" + "packages/**" ] } diff --git a/packages/cloud-functions/README.md b/packages/cloud-functions/README.md new file mode 100644 index 0000000000..e44ce23c24 --- /dev/null +++ b/packages/cloud-functions/README.md @@ -0,0 +1,13 @@ +# @uma/merkle-distributor + +This package contains a number of serverless functions used to wrap core UMA logic in a serverless consumable format. + +## Key packages included: + +1. `uma-tvl-calculator` wraps the `merkle-distributor-helper` package's `calculateCurrentTvl` method to create a simple interface for computing the current UMA TVL. Once the TVL is calculated, this method will store it within GCP data store with the Key being the computation timestamp. This should be run by a cron job to ensure the data store always has the most up to data information. +2. `uma-tvl-fetcher` pulls data from GCP data store to quickly return the most recent TVL. +3. `Merkle-distributor-helper` wraps the the `merkle-distributor-helper` package's `getClaimsForAddress` method to create a simple interface to fetch claims for a particular address. + +## Using these functions + +These serverless functions are designed to work in any serverless framework. They are used by UMA within GCP cloud functions but they should work equally well within Vercel's serverless, AWS Lambda or any other serverless framework of your choosing. diff --git a/packages/cloud-functions/merkle-distributor-helper/index.js b/packages/cloud-functions/merkle-distributor-helper/index.js new file mode 100644 index 0000000000..b839b7e001 --- /dev/null +++ b/packages/cloud-functions/merkle-distributor-helper/index.js @@ -0,0 +1,25 @@ +const { getClaimsForAddress } = require("@uma/merkle-distributor"); + +exports.getClaimsForAddress = async (req, res) => { + try { + res.set("Access-Control-Allow-Origin", "*"); + if (req.method === "OPTIONS") { + res.set("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS"); + res.set("Access-Control-Allow-Headers", "Content-Type"); + res.status(204).send(""); + } else { + const body = req.body; + ["merkleDistributorAddress", "claimerAddress", "chainId"].forEach(requiredKey => { + if (!Object.keys(body).includes(requiredKey)) + throw "Missing key in req body! required: merkleDistributorAddress, claimerAddress, chainId"; + }); + + const claims = await getClaimsForAddress(body.merkleDistributorAddress, body.claimerAddress, body.chainId); + console.log(`Fetched claims for ${JSON.stringify(body)}. Claims: ${JSON.stringify(claims)}`); + res.status(200).send(claims); + } + } catch (e) { + console.error(e); + res.status(500).send({ message: "Error in fetching claims", error: e instanceof Error ? e.message : e }); + } +}; diff --git a/packages/cloud-functions/merkle-distributor-helper/package.json b/packages/cloud-functions/merkle-distributor-helper/package.json new file mode 100644 index 0000000000..ba50a32a91 --- /dev/null +++ b/packages/cloud-functions/merkle-distributor-helper/package.json @@ -0,0 +1,8 @@ +{ + "name": "merkle-distributor-helper", + "version": "0.0.1", + "dependencies": { + "@uma/merkle-distributor": "npm:@uma/merkle-distributor@1.0.4" + }, + "private": true +} diff --git a/packages/cloud-functions/uma-tvl-calculator/index.js b/packages/cloud-functions/uma-tvl-calculator/index.js new file mode 100644 index 0000000000..5e0439fcea --- /dev/null +++ b/packages/cloud-functions/uma-tvl-calculator/index.js @@ -0,0 +1,27 @@ +const { Datastore } = require("@google-cloud/datastore"); +const datastore = new Datastore(); + +const { calculateCurrentTvl } = require("@uma/merkle-distributor"); + +exports.calculateCurrentTvl = async (req, res) => { + try { + const tvl = await calculateCurrentTvl(); + + const currentTime = Math.round(new Date().getTime() / 1000); + const key = datastore.key(["UmaTvl", currentTime]); + const dataBlob = { + key: key, + data: { + tvl: tvl.currentTvl, + created: currentTime + } + }; + await datastore.save(dataBlob); + + console.log(`Fetched and saved current TVL: ${JSON.stringify(tvl)}`); + res.status(200).send(tvl); + } catch (e) { + console.error(e); + res.status(500).send({ message: "Error in fetching and saving TVL", error: e instanceof Error ? e.message : e }); + } +}; diff --git a/packages/cloud-functions/uma-tvl-calculator/package.json b/packages/cloud-functions/uma-tvl-calculator/package.json new file mode 100644 index 0000000000..527b793a09 --- /dev/null +++ b/packages/cloud-functions/uma-tvl-calculator/package.json @@ -0,0 +1,9 @@ +{ + "name": "uma-tvl-calculator", + "version": "0.0.1", + "dependencies": { + "@uma/merkle-distributor": "npm:@uma/merkle-distributor@1.0.3", + "@google-cloud/datastore": "^6.3.1" + }, + "private": true +} diff --git a/packages/cloud-functions/uma-tvl-fetcher/index.js b/packages/cloud-functions/uma-tvl-fetcher/index.js new file mode 100644 index 0000000000..1b4542abea --- /dev/null +++ b/packages/cloud-functions/uma-tvl-fetcher/index.js @@ -0,0 +1,20 @@ +const { Datastore } = require("@google-cloud/datastore"); +const datastore = new Datastore(); + +exports.fetchLatestTvl = async (req, res) => { + try { + res.set("Access-Control-Allow-Origin", "*"); + const [result] = await datastore.runQuery( + datastore + .createQuery("UmaTvl") + .order("created", { descending: true }) + .limit(1) + ); + const responseObject = { currentTvl: result[0].tvl, currentTime: result[0].created }; + console.log(`Fetched TVL from data store: ${JSON.stringify(responseObject)}`); + res.status(200).send(responseObject); + } catch (e) { + console.error(e); + res.status(500).send({ message: "Error in fetching TVL", error: e instanceof Error ? e.message : e }); + } +}; diff --git a/packages/cloud-functions/uma-tvl-fetcher/package.json b/packages/cloud-functions/uma-tvl-fetcher/package.json new file mode 100644 index 0000000000..27724844f5 --- /dev/null +++ b/packages/cloud-functions/uma-tvl-fetcher/package.json @@ -0,0 +1,8 @@ +{ + "name": "uma-tvl-fetcher", + "version": "0.0.1", + "dependencies": { + "@google-cloud/datastore": "^6.3.1" + }, + "private": true +}