diff --git a/.eslintrc b/.eslintrc
index f827c32e0..2540a9997 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -21,12 +21,20 @@
"@typescript-eslint"
],
"rules": {
+ "indent": ["error", 2],
"semi": ["error", "never"],
+ "quotes": ["error", "double"],
"vue/multi-word-component-names": "off",
- "quotes": ["error", "single"]
+ "max-len": ["error", { "code": 120, "ignoreStrings": true, "comments":300, "ignoreTemplateLiterals": true }],
+ "space-before-blocks": ["error", "always"],
+ "object-curly-spacing": ["error", "always"],
+ "space-in-parens": ["error", "never"],
+ "keyword-spacing": ["error", { "before": true, "after": true }],
+ "array-element-newline": ["error", { "minItems": 3 }]
},
"ignorePatterns": [
- "lib",
+ "contracts/**/scripts/resources",
+ "scripts/**/resources",
"cdk.out",
"*.js"
]
diff --git a/apps/docs/scripts/docgen.ts b/apps/docs/scripts/docgen.ts
index 394253889..2215a3c94 100644
--- a/apps/docs/scripts/docgen.ts
+++ b/apps/docs/scripts/docgen.ts
@@ -1,16 +1,16 @@
-import fs from 'fs'
-import { run } from '@casimir/shell'
+import fs from "fs"
+import { run } from "@casimir/shell"
void async function () {
- const referenceDir = `${process.cwd()}/src/reference`
- const solidityTemplateDir = `${process.cwd()}/templates/solidity`
- await run(`DOCS_OUTPUT_DIR=${referenceDir} DOCS_TEMPLATE_DIR=${solidityTemplateDir} npm run docgen --workspace @casimir/ethereum`)
+ const referenceDir = `${process.cwd()}/src/reference`
+ const solidityTemplateDir = `${process.cwd()}/templates/solidity`
+ await run(`DOCS_OUTPUT_DIR=${referenceDir} DOCS_TEMPLATE_DIR=${solidityTemplateDir} npm run docgen --workspace @casimir/ethereum`)
- const casimirOperatorReadmeUrl = 'https://raw.githubusercontent.com/consensusnetworks/casimir-operator/master/README.md'
- const casimirOperatorReadme = await fetch(casimirOperatorReadmeUrl)
- const casimirOperatorReadmeText = await casimirOperatorReadme.text()
+ const casimirOperatorReadmeUrl = "https://raw.githubusercontent.com/consensusnetworks/casimir-operator/master/README.md"
+ const casimirOperatorReadme = await fetch(casimirOperatorReadmeUrl)
+ const casimirOperatorReadmeText = await casimirOperatorReadme.text()
- const partsDir = `${process.cwd()}/src/parts`
- if (!fs.existsSync(partsDir)) fs.mkdirSync(partsDir)
- fs.writeFileSync(`${partsDir}/casimir-operator-README.md`, casimirOperatorReadmeText)
+ const partsDir = `${process.cwd()}/src/parts`
+ if (!fs.existsSync(partsDir)) fs.mkdirSync(partsDir)
+ fs.writeFileSync(`${partsDir}/casimir-operator-README.md`, casimirOperatorReadmeText)
}()
\ No newline at end of file
diff --git a/apps/docs/templates/solidity/helpers.ts b/apps/docs/templates/solidity/helpers.ts
index b890bf57a..77c54b9a1 100644
--- a/apps/docs/templates/solidity/helpers.ts
+++ b/apps/docs/templates/solidity/helpers.ts
@@ -1,3 +1,3 @@
export function notInternal(visibility: string) {
- return visibility !== 'internal'
+ return visibility !== "internal"
}
\ No newline at end of file
diff --git a/apps/landing/src/App.vue b/apps/landing/src/App.vue
index 623dcac89..1117cf53b 100644
--- a/apps/landing/src/App.vue
+++ b/apps/landing/src/App.vue
@@ -1,6 +1,6 @@
diff --git a/apps/landing/src/composables/QuestionsAndAnswers.ts b/apps/landing/src/composables/QuestionsAndAnswers.ts
index afbc9e6a1..c0d958ecc 100644
--- a/apps/landing/src/composables/QuestionsAndAnswers.ts
+++ b/apps/landing/src/composables/QuestionsAndAnswers.ts
@@ -1,109 +1,109 @@
-import { onMounted, onUnmounted, readonly, ref } from 'vue'
+import { onMounted, onUnmounted, readonly, ref } from "vue"
const initializeComposable = ref(false)
const questionsAndAnswers = ref([
- {
- question: 'What’s the minimum I can stake?',
- answer: 'There is no minimum! However, there is a point at which gas fees make very small amounts staked not worth it.',
- link: ''
- },
- {
- question: 'How are rewards generated?',
- answer: 'Rewards are generated natively on the Ethereum beacon chain as if you were solo staking. Casimir pools users’ ETH into 32 ETH pools and builds a validator group of 4 operators using Distributed Validator Technology. Rewards are distributed to the users’ proportionate to their share of the 32 ETH in the pool. More information on how staking works here. Additionally, MEV and any other block rewards will be shared across validators. ',
- link: 'https://ethereum.org/en/staking/#:~:text=Rewards%20are%20given%20for%20actions,keeps%20the%20chain%20running%20securely.'
- },
- {
- question: 'How does Casimir work? What does it mean to create an account?',
- answer: 'Casimir utilizes distributed validator technology to pool users’ ETH into 32 ETH pools that are distributed across four node operators. Individual users (stakers) are able to maintain custody of their ETH because of our use of distributed key generation (DKG). Rewards are managed through Casimir’s open source manager contract and distributed back to users in native ETH proportionate to their share of the 32 ETH in the pool. ',
- link: 'https://github.com/RockX-SG/rockx-dkg-cli'
- },
- {
- question: 'What are the advantages of staking with Casimir over other protocols?',
- answer: 'Casimir is a first of its kind pooled staking solution that allows users to stake any amount of ETH while maintaining custody of their ethereum and receiving rewards in native ETH (not a secondary liquid staking token). Staking with Casimir gives you the flexibility and ease of use of a liquid staking protocol with the decentralization benefits of solo staking, the reward upside of solo staking and additional security because your stake is distributed across multiple validators (DVT). Additionally, because you are staking native ETH, you will be able to use solutions, like Eigenlayer, that liquid stakers are limited in their ability to access.',
- link: ''
- },
- {
- question: 'What are the risks?',
- answer: ' There is an inherent risk that Casimir could contain a smart contract vulnerability or bug. The Casimir code is open-sourced, audited, and covered by a bug bounty program to minimize this risk. To mitigate smart contract risks, all of the core Casimir contracts are audited. Validators/operators risk penalties, with up to 100% of staked funds at risk if validators/operators fail. To minimize this risk, Casimir utilizes Distributed Validator Technology (DVT) so that failure of a validator/operator will not result in slashed or lost funds.',
- link: ''
- },
- {
- question: 'Who is behind Casimir? Are the smart contracts audited and open source?',
- answer: 'Casimir is being built by Consensus Networks, a US based team who have been active in crypto for several years. The team were early node operators in many PoS protocols and have been awarded grants from both Web3 and government grants for the development of digital asset management tools.',
- link: ''
- },
- {
- question: 'What is Distributed Validator Technology (DVT)?',
- answer: 'DVT supports Ethereum’s validation layer by distributing validator operations to the network’s multiple non-trusting nodes (a.k.a Operators). Clusters of operator nodes operate validators on behalf of the staker and simultaneously help solve the fundamental issues of centralization, redundancy, and security that exist within Ethereum’s PoS consensus.',
- link: 'https://ssv.network/glossary/#operator'
- },
- {
- question: 'Why don’t you use a Liquid Staking Derivative or Token (LSD or LST)?',
- answer: 'There are inherent risks with LSDs, most significantly counterparty risk. Since the LSD is functionally an IOU, if the issuer of the LSD were to become insolvent, the user’s ETH could be lost forever.',
- link: ''
- },
- {
- question: 'Are there ways I can use my staked ETH for additional yield?',
- answer: 'Yes, although Casimir is not launching an LSD, there are opportunities for stakers to provide their native staked ETH to be used as a liquidity provider (to support a DAO, for example). Additionally, we will be onboarding restaking mechanisms like Eigenlayer that will allow users to natively restake their ETH to maximize their APR, if desired.',
- link: ''
- },
- {
- question: 'Am I giving up custody of my staked ETH?',
- answer: 'No! You will always be able to withdraw your staked ETH from your smart contract.',
- link: ''
- },
- {
- question: 'How frequently do I get my rewards? ',
- answer: 'Rewards will be distributed as they are awarded by the Ethereum protocol, at least daily.',
- link: ''
- },
- {
- question: 'Where are my rewards distributed, is there a secondary token?',
- answer: 'Your rewards will be distributed to your wallet, there is no need to deal with the hassle of swapping a token to get your rewards.',
- link: ''
- },
- {
- question: 'What Wallets are supported?',
- answer: 'Today we support Metamask, Wallet Connect, Trezor, Ledger, Trust Wallet and Coinbase Wallet.',
- link: ''
- },
- {
- question: 'Is there a lockup period or waiting period for withdrawals? ',
- answer: 'Since you are staking native ETH, there may be a wait time for a validator to exit to receive your withdrawal. If you desire a quicker exit, we will soon be launching a native ETH liquidity pool for those who wish for an instant withdrawal.',
- link: ''
- },
- {
- question: 'Where is my stake going, who is running the validators?',
- answer: 'Casimir is launching with a small set of validators but will soon open a permissionless set so that anyone can join for a small (1ETH) collateral. Validator performance is monitored by a decentralized oracle network to ensure performance and validator performance specs are made available and used in evaluation for the selection of validator operators.',
- link: ''
- },
- {
- question: 'What is the fee?',
- answer: 'There is a small fee, paid for by part of the block rewards to cover validator and other network payments to ensure Casimir keeps running.',
- link: ''
- },
- {
- question: 'Can I run a validator?',
- answer: 'If you have the technical ability and desire, you soon will be able to run a validator as part of our protocol. Today we are launching with a smaller set of white listed validators but will soon start opening to a permissionless set. Join our Discord for the latest updates.',
- link: ''
- },
+ {
+ question: "What’s the minimum I can stake?",
+ answer: "There is no minimum! However, there is a point at which gas fees make very small amounts staked not worth it.",
+ link: ""
+ },
+ {
+ question: "How are rewards generated?",
+ answer: "Rewards are generated natively on the Ethereum beacon chain as if you were solo staking. Casimir pools users’ ETH into 32 ETH pools and builds a validator group of 4 operators using Distributed Validator Technology. Rewards are distributed to the users’ proportionate to their share of the 32 ETH in the pool. More information on how staking works here. Additionally, MEV and any other block rewards will be shared across validators. ",
+ link: "https://ethereum.org/en/staking/#:~:text=Rewards%20are%20given%20for%20actions,keeps%20the%20chain%20running%20securely."
+ },
+ {
+ question: "How does Casimir work? What does it mean to create an account?",
+ answer: "Casimir utilizes distributed validator technology to pool users’ ETH into 32 ETH pools that are distributed across four node operators. Individual users (stakers) are able to maintain custody of their ETH because of our use of distributed key generation (DKG). Rewards are managed through Casimir’s open source manager contract and distributed back to users in native ETH proportionate to their share of the 32 ETH in the pool. ",
+ link: "https://github.com/RockX-SG/rockx-dkg-cli"
+ },
+ {
+ question: "What are the advantages of staking with Casimir over other protocols?",
+ answer: "Casimir is a first of its kind pooled staking solution that allows users to stake any amount of ETH while maintaining custody of their ethereum and receiving rewards in native ETH (not a secondary liquid staking token). Staking with Casimir gives you the flexibility and ease of use of a liquid staking protocol with the decentralization benefits of solo staking, the reward upside of solo staking and additional security because your stake is distributed across multiple validators (DVT). Additionally, because you are staking native ETH, you will be able to use solutions, like Eigenlayer, that liquid stakers are limited in their ability to access.",
+ link: ""
+ },
+ {
+ question: "What are the risks?",
+ answer: " There is an inherent risk that Casimir could contain a smart contract vulnerability or bug. The Casimir code is open-sourced, audited, and covered by a bug bounty program to minimize this risk. To mitigate smart contract risks, all of the core Casimir contracts are audited. Validators/operators risk penalties, with up to 100% of staked funds at risk if validators/operators fail. To minimize this risk, Casimir utilizes Distributed Validator Technology (DVT) so that failure of a validator/operator will not result in slashed or lost funds.",
+ link: ""
+ },
+ {
+ question: "Who is behind Casimir? Are the smart contracts audited and open source?",
+ answer: "Casimir is being built by Consensus Networks, a US based team who have been active in crypto for several years. The team were early node operators in many PoS protocols and have been awarded grants from both Web3 and government grants for the development of digital asset management tools.",
+ link: ""
+ },
+ {
+ question: "What is Distributed Validator Technology (DVT)?",
+ answer: "DVT supports Ethereum’s validation layer by distributing validator operations to the network’s multiple non-trusting nodes (a.k.a Operators). Clusters of operator nodes operate validators on behalf of the staker and simultaneously help solve the fundamental issues of centralization, redundancy, and security that exist within Ethereum’s PoS consensus.",
+ link: "https://ssv.network/glossary/#operator"
+ },
+ {
+ question: "Why don’t you use a Liquid Staking Derivative or Token (LSD or LST)?",
+ answer: "There are inherent risks with LSDs, most significantly counterparty risk. Since the LSD is functionally an IOU, if the issuer of the LSD were to become insolvent, the user’s ETH could be lost forever.",
+ link: ""
+ },
+ {
+ question: "Are there ways I can use my staked ETH for additional yield?",
+ answer: "Yes, although Casimir is not launching an LSD, there are opportunities for stakers to provide their native staked ETH to be used as a liquidity provider (to support a DAO, for example). Additionally, we will be onboarding restaking mechanisms like Eigenlayer that will allow users to natively restake their ETH to maximize their APR, if desired.",
+ link: ""
+ },
+ {
+ question: "Am I giving up custody of my staked ETH?",
+ answer: "No! You will always be able to withdraw your staked ETH from your smart contract.",
+ link: ""
+ },
+ {
+ question: "How frequently do I get my rewards? ",
+ answer: "Rewards will be distributed as they are awarded by the Ethereum protocol, at least daily.",
+ link: ""
+ },
+ {
+ question: "Where are my rewards distributed, is there a secondary token?",
+ answer: "Your rewards will be distributed to your wallet, there is no need to deal with the hassle of swapping a token to get your rewards.",
+ link: ""
+ },
+ {
+ question: "What Wallets are supported?",
+ answer: "Today we support Metamask, Wallet Connect, Trezor, Ledger, Trust Wallet and Coinbase Wallet.",
+ link: ""
+ },
+ {
+ question: "Is there a lockup period or waiting period for withdrawals? ",
+ answer: "Since you are staking native ETH, there may be a wait time for a validator to exit to receive your withdrawal. If you desire a quicker exit, we will soon be launching a native ETH liquidity pool for those who wish for an instant withdrawal.",
+ link: ""
+ },
+ {
+ question: "Where is my stake going, who is running the validators?",
+ answer: "Casimir is launching with a small set of validators but will soon open a permissionless set so that anyone can join for a small (1ETH) collateral. Validator performance is monitored by a decentralized oracle network to ensure performance and validator performance specs are made available and used in evaluation for the selection of validator operators.",
+ link: ""
+ },
+ {
+ question: "What is the fee?",
+ answer: "There is a small fee, paid for by part of the block rewards to cover validator and other network payments to ensure Casimir keeps running.",
+ link: ""
+ },
+ {
+ question: "Can I run a validator?",
+ answer: "If you have the technical ability and desire, you soon will be able to run a validator as part of our protocol. Today we are launching with a smaller set of white listed validators but will soon start opening to a permissionless set. Join our Discord for the latest updates.",
+ link: ""
+ },
])
export default function useQuestionsAndAnswers() {
- onMounted(() => {
- if(!initializeComposable.value){
- initializeComposable.value = true
- }
+ onMounted(() => {
+ if (!initializeComposable.value) {
+ initializeComposable.value = true
+ }
- })
+ })
- onUnmounted(() =>{
- initializeComposable.value = false
- })
+ onUnmounted(() =>{
+ initializeComposable.value = false
+ })
- return {
- questionsAndAnswers: readonly(questionsAndAnswers),
- }
+ return {
+ questionsAndAnswers: readonly(questionsAndAnswers),
+ }
}
\ No newline at end of file
diff --git a/apps/landing/src/composables/blog.ts b/apps/landing/src/composables/blog.ts
index 9533d241d..9d2f7349f 100644
--- a/apps/landing/src/composables/blog.ts
+++ b/apps/landing/src/composables/blog.ts
@@ -1,60 +1,60 @@
-import { onMounted, onUnmounted, readonly, ref } from 'vue'
-import snarkdown from 'snarkdown'
-import { Article } from '@casimir/types'
+import { onMounted, onUnmounted, readonly, ref } from "vue"
+import snarkdown from "snarkdown"
+import { Article } from "@casimir/types"
const initializeComposable = ref(false)
-const blogUrl = import.meta.env.PUBLIC_BLOG_URL || 'http://localhost:4001'
+const blogUrl = import.meta.env.PUBLIC_BLOG_URL || "http://localhost:4001"
const articles = ref([] as Article[])
const loadingArticles = ref(true)
export default function useBlog() {
- async function getArticleContent(itemId: string) {
- const response = await fetch(`${blogUrl}/articles/${itemId}`)
- const json = await response.json()
- const md = snarkdown(json.content)
- return md
- }
-
- onMounted(async () => {
- if (!initializeComposable.value) {
- loadingArticles.value = true
- try {
- const response = await fetch(`${blogUrl}/articles`)
- const jsonList = await response.json()
- const articleList = []
-
- for (let i = 0; i < jsonList.length; i++) {
- const title = jsonList[i].title
- const content = await getArticleContent(jsonList[i].id)
- const timestamp = jsonList[i].publishedAt
- const id = jsonList[i].id
- articleList.push({
- title: title,
- content: content,
- timestamp: timestamp,
- type: 'Blog',
- id: id,
- })
- }
-
- articles.value = articleList
- loadingArticles.value = false
- } catch (error) {
- console.log('Error fetching articles', error)
- loadingArticles.value = false
- }
-
- initializeComposable.value = true
+ async function getArticleContent(itemId: string) {
+ const response = await fetch(`${blogUrl}/articles/${itemId}`)
+ const json = await response.json()
+ const md = snarkdown(json.content)
+ return md
+ }
+
+ onMounted(async () => {
+ if (!initializeComposable.value) {
+ loadingArticles.value = true
+ try {
+ const response = await fetch(`${blogUrl}/articles`)
+ const jsonList = await response.json()
+ const articleList = []
+
+ for (let i = 0; i < jsonList.length; i++) {
+ const title = jsonList[i].title
+ const content = await getArticleContent(jsonList[i].id)
+ const timestamp = jsonList[i].publishedAt
+ const id = jsonList[i].id
+ articleList.push({
+ title: title,
+ content: content,
+ timestamp: timestamp,
+ type: "Blog",
+ id: id,
+ })
}
- })
- onUnmounted(() => {
- initializeComposable.value = false
- })
+ articles.value = articleList
+ loadingArticles.value = false
+ } catch (error) {
+ console.log("Error fetching articles", error)
+ loadingArticles.value = false
+ }
- return {
- articles: readonly(articles),
- loadingArticles: readonly(loadingArticles),
+ initializeComposable.value = true
}
+ })
+
+ onUnmounted(() => {
+ initializeComposable.value = false
+ })
+
+ return {
+ articles: readonly(articles),
+ loadingArticles: readonly(loadingArticles),
+ }
}
diff --git a/apps/landing/src/composables/roadmapItems.ts b/apps/landing/src/composables/roadmapItems.ts
index 996394bf3..340c8f693 100644
--- a/apps/landing/src/composables/roadmapItems.ts
+++ b/apps/landing/src/composables/roadmapItems.ts
@@ -1,4 +1,4 @@
-import { onMounted, onUnmounted, readonly, ref } from 'vue'
+import { onMounted, onUnmounted, readonly, ref } from "vue"
const initializeComposable = ref(false)
@@ -12,53 +12,53 @@ const casimirRoadmapLocation = ref(2)
// Liquid withdrawal pools: native ETH pool launched for users who want instant unstaking
const roadmapItems = ref([
- {
- step: 1,
- title: 'Internal Testnet',
- description: 'Deploy and test beta version.'
- },
- {
- step: 2,
- title: 'Goerli Launch',
- description: 'Launch publicly for Goerli Testnet. Coming Soon!!'
- },
- {
- step: 3,
- title: 'Mainnet Beta',
- description: 'Launch with Mainnet and selected validator set.'
- },
- {
- step: 4,
- title: 'Full Mainnet',
- description: 'Launch with permissionless validators on Mainnet.'
- },
- {
- step: 5,
- title: 'Eigenlayer Restaking',
- description: 'Integrate with Eigenlayer to enable native restaking and eigenpod creation. '
- },
- {
- step: 6,
- title: 'Liquid Withdrawl Pools',
- description: 'Launch with native ETH pools to allow users instant unstaking if desired.'
- },
+ {
+ step: 1,
+ title: "Internal Testnet",
+ description: "Deploy and test beta version."
+ },
+ {
+ step: 2,
+ title: "Goerli Launch",
+ description: "Launch publicly for Goerli Testnet. Coming Soon!!"
+ },
+ {
+ step: 3,
+ title: "Mainnet Beta",
+ description: "Launch with Mainnet and selected validator set."
+ },
+ {
+ step: 4,
+ title: "Full Mainnet",
+ description: "Launch with permissionless validators on Mainnet."
+ },
+ {
+ step: 5,
+ title: "Eigenlayer Restaking",
+ description: "Integrate with Eigenlayer to enable native restaking and eigenpod creation. "
+ },
+ {
+ step: 6,
+ title: "Liquid Withdrawl Pools",
+ description: "Launch with native ETH pools to allow users instant unstaking if desired."
+ },
])
export default function useRoadmap() {
- onMounted(() => {
- if(!initializeComposable.value){
- initializeComposable.value = true
- }
+ onMounted(() => {
+ if (!initializeComposable.value) {
+ initializeComposable.value = true
+ }
- })
+ })
- onUnmounted(() =>{
- initializeComposable.value = false
- })
+ onUnmounted(() =>{
+ initializeComposable.value = false
+ })
- return {
- roadmapItems: readonly(roadmapItems),
- casimirRoadmapLocation: readonly(casimirRoadmapLocation),
- }
+ return {
+ roadmapItems: readonly(roadmapItems),
+ casimirRoadmapLocation: readonly(casimirRoadmapLocation),
+ }
}
\ No newline at end of file
diff --git a/apps/landing/src/composables/router.ts b/apps/landing/src/composables/router.ts
index 962428b3e..47f469f00 100644
--- a/apps/landing/src/composables/router.ts
+++ b/apps/landing/src/composables/router.ts
@@ -1,36 +1,36 @@
-import { createWebHistory, createRouter } from 'vue-router'
-import Landing from '@/pages/landing/Landing.vue'
-import Changelog from '@/pages/changelog/Changelog.vue'
-import Blog from '@/pages/blog/Blog.vue'
-import Article from '@/pages/blog/components/Article.vue'
+import { createWebHistory, createRouter } from "vue-router"
+import Landing from "@/pages/landing/Landing.vue"
+import Changelog from "@/pages/changelog/Changelog.vue"
+import Blog from "@/pages/blog/Blog.vue"
+import Article from "@/pages/blog/components/Article.vue"
const routes = [
- {
- path: '/',
- name: Landing,
- component: Landing,
- },
- {
- path: '/blog',
- name: Blog,
- component: Blog,
- },
- {
- path: '/blog/:id',
- component: Article,
- children: [{ path: '', name: Article, component: Article }],
- },
- {
- path: '/changelog',
- name: Changelog,
- component: Changelog,
- },
+ {
+ path: "/",
+ name: Landing,
+ component: Landing,
+ },
+ {
+ path: "/blog",
+ name: Blog,
+ component: Blog,
+ },
+ {
+ path: "/blog/:id",
+ component: Article,
+ children: [{ path: "", name: Article, component: Article }],
+ },
+ {
+ path: "/changelog",
+ name: Changelog,
+ component: Changelog,
+ },
]
const router = createRouter({
- history: createWebHistory(),
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- routes,
+ history: createWebHistory(),
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ routes,
})
export default router
diff --git a/apps/landing/src/env.d.ts b/apps/landing/src/env.d.ts
index be15b0dcb..7bb571c3b 100644
--- a/apps/landing/src/env.d.ts
+++ b/apps/landing/src/env.d.ts
@@ -4,10 +4,10 @@
import {
SendMessagesCommandOutput,
UpdateEndpointCommandOutput
-} from '@aws-sdk/client-pinpoint'
+} from "@aws-sdk/client-pinpoint"
-declare module '*.vue' {
- import type { DefineComponent } from 'vue'
+declare module "*.vue" {
+ import type { DefineComponent } from "vue"
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
diff --git a/apps/landing/src/main.ts b/apps/landing/src/main.ts
index ac6149a2a..c17af52f7 100644
--- a/apps/landing/src/main.ts
+++ b/apps/landing/src/main.ts
@@ -1,8 +1,8 @@
-import { createApp } from 'vue'
-import App from '@/App.vue'
-import '@/index.css'
-import router from './composables/router'
+import { createApp } from "vue"
+import App from "@/App.vue"
+import "@/index.css"
+import router from "./composables/router"
const app = createApp(App)
app.use(router)
-app.mount('#app')
+app.mount("#app")
diff --git a/apps/landing/src/pages/blog/Blog.vue b/apps/landing/src/pages/blog/Blog.vue
index 2b7c1de81..db5302b4c 100644
--- a/apps/landing/src/pages/blog/Blog.vue
+++ b/apps/landing/src/pages/blog/Blog.vue
@@ -1,12 +1,12 @@
diff --git a/apps/landing/src/pages/blog/components/Article.vue b/apps/landing/src/pages/blog/components/Article.vue
index 7749ff227..ca726b3be 100644
--- a/apps/landing/src/pages/blog/components/Article.vue
+++ b/apps/landing/src/pages/blog/components/Article.vue
@@ -1,39 +1,39 @@
diff --git a/apps/landing/src/pages/changelog/Changelog.vue b/apps/landing/src/pages/changelog/Changelog.vue
index 0c5b6bfab..f6474b7fe 100644
--- a/apps/landing/src/pages/changelog/Changelog.vue
+++ b/apps/landing/src/pages/changelog/Changelog.vue
@@ -1,8 +1,8 @@
diff --git a/apps/web/src/components/Carousel.vue b/apps/web/src/components/Carousel.vue
index b6139db12..935e7824f 100644
--- a/apps/web/src/components/Carousel.vue
+++ b/apps/web/src/components/Carousel.vue
@@ -1,12 +1,12 @@
diff --git a/apps/web/src/components/ConnectWalletsFlow.vue b/apps/web/src/components/ConnectWalletsFlow.vue
index 5f74534bc..adc94bf8d 100644
--- a/apps/web/src/components/ConnectWalletsFlow.vue
+++ b/apps/web/src/components/ConnectWalletsFlow.vue
@@ -1,27 +1,27 @@
diff --git a/apps/web/src/components/USDAmount.vue b/apps/web/src/components/USDAmount.vue
index 570fbabd1..a610f1af6 100644
--- a/apps/web/src/components/USDAmount.vue
+++ b/apps/web/src/components/USDAmount.vue
@@ -1,7 +1,7 @@
diff --git a/apps/web/src/components/charts/LineChartJS.vue b/apps/web/src/components/charts/LineChartJS.vue
index 4727b9924..7403b3a39 100644
--- a/apps/web/src/components/charts/LineChartJS.vue
+++ b/apps/web/src/components/charts/LineChartJS.vue
@@ -1,142 +1,142 @@
diff --git a/apps/web/src/composables/analytics.ts b/apps/web/src/composables/analytics.ts
index f891311e7..511c0cf05 100644
--- a/apps/web/src/composables/analytics.ts
+++ b/apps/web/src/composables/analytics.ts
@@ -1,7 +1,7 @@
-import { readonly, ref } from 'vue'
-import { UserAnalyticsData } from '@casimir/types'
-import useEnvironment from '@/composables/environment'
-import useTxData from '../mockData/mock_transaction_data'
+import { readonly, ref } from "vue"
+import { UserAnalyticsData } from "@casimir/types"
+import useEnvironment from "@/composables/environment"
+import useTxData from "../mockData/mock_transaction_data"
const { usersUrl } = useEnvironment()
const { mockData, txData } = useTxData()
@@ -9,217 +9,228 @@ const loadingInitializeAnalytics = ref(false)
const loadingInitializeAnalyticsError = ref(false)
export default function useAnalytics() {
- const finishedComputingUerAnalytics = ref(false)
- const rawUserAnalytics = ref(null)
- const userAnalytics = ref({
- oneMonth: {
- labels: [],
- data: []
- },
- sixMonth: {
- labels: [],
- data: []
- },
- oneYear: {
- labels: [],
- data: []
- },
- historical: {
- labels: [],
- data: []
- }
+ const finishedComputingUerAnalytics = ref(false)
+ const rawUserAnalytics = ref(null)
+ const userAnalytics = ref({
+ oneMonth: {
+ labels: [],
+ data: []
+ },
+ sixMonth: {
+ labels: [],
+ data: []
+ },
+ oneYear: {
+ labels: [],
+ data: []
+ },
+ historical: {
+ labels: [],
+ data: []
+ }
+ })
+
+ function computeUserAnalytics() {
+ finishedComputingUerAnalytics.value = false
+ const sortedTransactions = rawUserAnalytics.value.sort((a: any, b: any) => {
+ new Date(a.receivedAt).getTime() - new Date(b.receivedAt).getTime()
})
- function computeUserAnalytics() {
- finishedComputingUerAnalytics.value = false
- const sortedTransactions = rawUserAnalytics.value.sort((a: any, b: any) => {
- new Date(a.receivedAt).getTime() - new Date(b.receivedAt).getTime()
- })
-
- let earliest: any = null
- const latest: any = new Date().getTime()
- const oneYear = new Date().getTime() - 31536000000
- const sixMonths = new Date().getTime() - 15768000000
- const oneMonth = new Date().getTime() - 2628000000
- sortedTransactions.forEach((tx: any) => {
- const receivedAt = new Date(tx.receivedAt)
- if (!earliest) earliest = receivedAt.getTime()
- if (receivedAt.getTime() < earliest) earliest = receivedAt.getTime()
- })
- const historicalInterval = (latest - earliest) / 11
-
- sortedTransactions.forEach((tx: any) => {
- const { receivedAt, walletAddress, walletBalance } = tx
- /* Historical */
- let historicalDataIndex = userAnalytics.value.historical.data.findIndex((obj: any) => obj.walletAddress === walletAddress)
- if (historicalDataIndex === -1) {
- const dataLength = userAnalytics.value.historical.data.push({ walletAddress, walletBalance: Array(12).fill(0) })
- historicalDataIndex = dataLength - 1
- }
- // Determine which interval the receivedAt falls into
- const intervalIndex = Math.floor((new Date(receivedAt).getTime() - earliest) / historicalInterval)
- // Set the value of the intervalIndex to the walletBalance
- userAnalytics.value.historical.data[historicalDataIndex].walletBalance[intervalIndex] = walletBalance
-
- /* One Year */
- if (new Date(receivedAt).getTime() > oneYear) {
- let oneYearDataIndex = userAnalytics.value.oneYear.data.findIndex((obj: any) => obj.walletAddress === walletAddress)
- if (oneYearDataIndex === -1) {
- const dataLength = userAnalytics.value.oneYear.data.push({ walletAddress, walletBalance: Array(12).fill(0) })
- oneYearDataIndex = dataLength - 1
- }
- const monthsAgo = (new Date().getFullYear() - new Date(receivedAt).getFullYear()) * 12 + (new Date().getMonth() - new Date(receivedAt).getMonth())
- const intervalIndex = 11 - monthsAgo
- userAnalytics.value.oneYear.data[oneYearDataIndex].walletBalance[intervalIndex] = walletBalance
- }
-
- /* Six Months */
- if (new Date(receivedAt).getTime() > sixMonths) {
- let sixMonthDataIndex = userAnalytics.value.sixMonth.data.findIndex((obj: any) => obj.walletAddress === walletAddress)
- if (sixMonthDataIndex === -1) {
- const dataLength = userAnalytics.value.sixMonth.data.push({ walletAddress, walletBalance: Array(6).fill(0) })
- sixMonthDataIndex = dataLength - 1
- }
- const monthsAgo = (new Date().getFullYear() - new Date(receivedAt).getFullYear()) * 12 + (new Date().getMonth() - new Date(receivedAt).getMonth())
- const intervalIndex = 5 - monthsAgo
- userAnalytics.value.sixMonth.data[sixMonthDataIndex].walletBalance[intervalIndex] = walletBalance
- }
-
- /* One Month */
- if (new Date(receivedAt).getTime() > oneMonth) {
- let oneMonthDataIndex = userAnalytics.value.oneMonth.data.findIndex((obj: any) => obj.walletAddress === walletAddress)
- if (oneMonthDataIndex === -1) {
- const dataLength = userAnalytics.value.oneMonth.data.push({ walletAddress, walletBalance: Array(30).fill(0) })
- oneMonthDataIndex = dataLength - 1
- }
- const daysAgo = Math.floor((new Date().getTime() - new Date(receivedAt).getTime()) / 86400000)
- const intervalIndex = 29 - daysAgo
- userAnalytics.value.oneMonth.data[oneMonthDataIndex].walletBalance[intervalIndex] = walletBalance
- }
- })
-
- const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
-
- // Set the historical labels array to the interval labels
- let previousMonth: any = null
- userAnalytics.value.historical.labels = Array(12).fill(0).map((_, i) => {
- const date = new Date(earliest + (historicalInterval * i))
- const currentMonth = date.getMonth()
- if (!previousMonth) {
- previousMonth = currentMonth
- return date.getMonth() === 0 ? `${date.getFullYear()} ${months[date.getMonth()]} ${date.getDate()}` : `${months[date.getMonth()]} ${date.getDate()}`
- } else if (currentMonth < previousMonth) {
- previousMonth = currentMonth
- return `${date.getFullYear()} ${months[date.getMonth()]} ${date.getDate()}`
- } else {
- previousMonth = currentMonth
- return `${months[date.getMonth()]} ${date.getDate()}`
- }
- })
-
- // Set the oneYear labels array to the interval labels
- userAnalytics.value.oneYear.labels = Array(12).fill(0).map((_, i) => {
- const date = new Date (new Date().setDate(1))
- const monthIndex = new Date(date.setMonth(date.getMonth() - (11 - i)))
- return `${months[monthIndex.getMonth()]} ${monthIndex.getFullYear()}`
- })
-
- // Set the sixMonth labels array to the interval labels
- userAnalytics.value.sixMonth.labels = Array(6).fill(0).map((_, i) => {
- const date = new Date (new Date().setDate(1))
- const monthIndex = new Date(date.setMonth(date.getMonth() - (5 - i)))
- return `${months[monthIndex.getMonth()]} ${monthIndex.getFullYear()}`
- })
-
- // Set the oneMonth labels array to the interval labels
- userAnalytics.value.oneMonth.labels = []
- for (let i = 30; i > 0; i--) {
- const date = new Date().getTime() - ((i - 1) * 86400000)
- userAnalytics.value.oneMonth.labels.push(`${new Date(date).getMonth() + 1}/${new Date(date).getDate()}`)
+ let earliest: any = null
+ const latest: any = new Date().getTime()
+ const oneYear = new Date().getTime() - 31536000000
+ const sixMonths = new Date().getTime() - 15768000000
+ const oneMonth = new Date().getTime() - 2628000000
+ sortedTransactions.forEach((tx: any) => {
+ const receivedAt = new Date(tx.receivedAt)
+ if (!earliest) earliest = receivedAt.getTime()
+ if (receivedAt.getTime() < earliest) earliest = receivedAt.getTime()
+ })
+ const historicalInterval = (latest - earliest) / 11
+
+ sortedTransactions.forEach((tx: any) => {
+ const { receivedAt, walletAddress, walletBalance } = tx
+ /* Historical */
+ let historicalDataIndex = userAnalytics.value.historical.data.findIndex((obj: any) => obj.walletAddress === walletAddress)
+ if (historicalDataIndex === -1) {
+ const dataLength = userAnalytics.value.historical.data.push({ walletAddress, walletBalance: Array(12).fill(0) })
+ historicalDataIndex = dataLength - 1
+ }
+ // Determine which interval the receivedAt falls into
+ const intervalIndex = Math.floor((new Date(receivedAt).getTime() - earliest) / historicalInterval)
+ // Set the value of the intervalIndex to the walletBalance
+ userAnalytics.value.historical.data[historicalDataIndex].walletBalance[intervalIndex] = walletBalance
+
+ /* One Year */
+ if (new Date(receivedAt).getTime() > oneYear) {
+ let oneYearDataIndex = userAnalytics.value.oneYear.data.findIndex((obj: any) => obj.walletAddress === walletAddress)
+ if (oneYearDataIndex === -1) {
+ const dataLength = userAnalytics.value.oneYear.data.push({ walletAddress, walletBalance: Array(12).fill(0) })
+ oneYearDataIndex = dataLength - 1
}
- // userAnalytics.value = result
- finishedComputingUerAnalytics.value = true
- }
-
- async function getUserAnalytics() {
- try {
- const requestOptions = {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json'
- }
- }
- // TODO: Re-enable this when athena is ready
- // const response = await fetch(`${usersUrl}/analytics`, requestOptions)
- // const { error, message, data: athenaData } = await response.json()
- // console.log('data from analytics :>> ', data)
- // userAnalytics.value = athenaData
- // if (error) throw new Error(`Error in getUserAnalytics: ${message}`)
-
- // TODO: Get events, actions, and contract data from the API
- // Then format the data to be used in the charts (see computeUserAnalytics) and give to Steve.
-
- // We get the user's analytics (wallet balance) data here.
- mockData()
- const data = txData.value
-
- // TODO: Pass data from above when the API / data is ready
- rawUserAnalytics.value = data
-
- // This compute's the user's wallet balance over time
- computeUserAnalytics()
- // return { error, message, data }
- return { data }
- } catch (error: any) {
- throw new Error(error.message || 'Error getting user analytics')
+ const monthsAgo = (new Date().getFullYear() - new Date(receivedAt).getFullYear()) * 12 + (new Date().getMonth() - new Date(receivedAt).getMonth())
+ const intervalIndex = 11 - monthsAgo
+ userAnalytics.value.oneYear.data[oneYearDataIndex].walletBalance[intervalIndex] = walletBalance
+ }
+
+ /* Six Months */
+ if (new Date(receivedAt).getTime() > sixMonths) {
+ let sixMonthDataIndex = userAnalytics.value.sixMonth.data.findIndex((obj: any) => obj.walletAddress === walletAddress)
+ if (sixMonthDataIndex === -1) {
+ const dataLength = userAnalytics.value.sixMonth.data.push({ walletAddress, walletBalance: Array(6).fill(0) })
+ sixMonthDataIndex = dataLength - 1
}
- }
+ const monthsAgo = (new Date().getFullYear() - new Date(receivedAt).getFullYear()) * 12 + (new Date().getMonth() - new Date(receivedAt).getMonth())
+ const intervalIndex = 5 - monthsAgo
+ userAnalytics.value.sixMonth.data[sixMonthDataIndex].walletBalance[intervalIndex] = walletBalance
+ }
+
+ /* One Month */
+ if (new Date(receivedAt).getTime() > oneMonth) {
+ let oneMonthDataIndex = userAnalytics.value.oneMonth.data.findIndex((obj: any) => obj.walletAddress === walletAddress)
+ if (oneMonthDataIndex === -1) {
+ const dataLength = userAnalytics.value.oneMonth.data.push({ walletAddress, walletBalance: Array(30).fill(0) })
+ oneMonthDataIndex = dataLength - 1
+ }
+ const daysAgo = Math.floor((new Date().getTime() - new Date(receivedAt).getTime()) / 86400000)
+ const intervalIndex = 29 - daysAgo
+ userAnalytics.value.oneMonth.data[oneMonthDataIndex].walletBalance[intervalIndex] = walletBalance
+ }
+ })
- async function updateAnalytics() {
- await getUserAnalytics()
- }
+ const months = ["Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"]
+
+ // Set the historical labels array to the interval labels
+ let previousMonth: any = null
+ userAnalytics.value.historical.labels = Array(12).fill(0).map((_, i) => {
+ const date = new Date(earliest + (historicalInterval * i))
+ const currentMonth = date.getMonth()
+ if (!previousMonth) {
+ previousMonth = currentMonth
+ return date.getMonth() === 0 ? `${date.getFullYear()} ${months[date.getMonth()]} ${date.getDate()}` : `${months[date.getMonth()]} ${date.getDate()}`
+ } else if (currentMonth < previousMonth) {
+ previousMonth = currentMonth
+ return `${date.getFullYear()} ${months[date.getMonth()]} ${date.getDate()}`
+ } else {
+ previousMonth = currentMonth
+ return `${months[date.getMonth()]} ${date.getDate()}`
+ }
+ })
- async function initializeAnalyticsComposable() {
- try {
- loadingInitializeAnalytics.value = true
- resetUserAnalytics()
- await getUserAnalytics()
- loadingInitializeAnalytics.value = false
- } catch (error) {
- loadingInitializeAnalyticsError.value = true
- loadingInitializeAnalytics.value = false
- throw new Error('Error initializing analytics')
- }
- }
+ // Set the oneYear labels array to the interval labels
+ userAnalytics.value.oneYear.labels = Array(12).fill(0).map((_, i) => {
+ const date = new Date (new Date().setDate(1))
+ const monthIndex = new Date(date.setMonth(date.getMonth() - (11 - i)))
+ return `${months[monthIndex.getMonth()]} ${monthIndex.getFullYear()}`
+ })
- function resetUserAnalytics() {
- userAnalytics.value = {
- oneMonth: {
- labels: [],
- data: []
- },
- sixMonth: {
- labels: [],
- data: []
- },
- oneYear: {
- labels: [],
- data: []
- },
- historical: {
- labels: [],
- data: []
- }
+ // Set the sixMonth labels array to the interval labels
+ userAnalytics.value.sixMonth.labels = Array(6).fill(0).map((_, i) => {
+ const date = new Date (new Date().setDate(1))
+ const monthIndex = new Date(date.setMonth(date.getMonth() - (5 - i)))
+ return `${months[monthIndex.getMonth()]} ${monthIndex.getFullYear()}`
+ })
+
+ // Set the oneMonth labels array to the interval labels
+ userAnalytics.value.oneMonth.labels = []
+ for (let i = 30; i > 0; i--) {
+ const date = new Date().getTime() - ((i - 1) * 86400000)
+ userAnalytics.value.oneMonth.labels.push(`${new Date(date).getMonth() + 1}/${new Date(date).getDate()}`)
+ }
+ // userAnalytics.value = result
+ finishedComputingUerAnalytics.value = true
+ }
+
+ async function getUserAnalytics() {
+ try {
+ const requestOptions = {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json"
}
+ }
+ // TODO: Re-enable this when athena is ready
+ // const response = await fetch(`${usersUrl}/analytics`, requestOptions)
+ // const { error, message, data: athenaData } = await response.json()
+ // console.log('data from analytics :>> ', data)
+ // userAnalytics.value = athenaData
+ // if (error) throw new Error(`Error in getUserAnalytics: ${message}`)
+
+ // TODO: Get events, actions, and contract data from the API
+ // Then format the data to be used in the charts (see computeUserAnalytics) and give to Steve.
+
+ // We get the user's analytics (wallet balance) data here.
+ mockData()
+ const data = txData.value
+
+ // TODO: Pass data from above when the API / data is ready
+ rawUserAnalytics.value = data
+
+ // This compute's the user's wallet balance over time
+ computeUserAnalytics()
+ // return { error, message, data }
+ return { data }
+ } catch (error: any) {
+ throw new Error(error.message || "Error getting user analytics")
}
-
- return {
- finishedComputingUerAnalytics: readonly(finishedComputingUerAnalytics),
- loadingInitializeAnalytics: readonly(loadingInitializeAnalytics),
- loadingInitializeAnalyticsError: readonly(loadingInitializeAnalyticsError),
- rawUserAnalytics,
- userAnalytics: readonly(userAnalytics),
- initializeAnalyticsComposable,
- updateAnalytics,
+ }
+
+ async function updateAnalytics() {
+ await getUserAnalytics()
+ }
+
+ async function initializeAnalyticsComposable() {
+ try {
+ loadingInitializeAnalytics.value = true
+ resetUserAnalytics()
+ await getUserAnalytics()
+ loadingInitializeAnalytics.value = false
+ } catch (error) {
+ loadingInitializeAnalyticsError.value = true
+ loadingInitializeAnalytics.value = false
+ throw new Error("Error initializing analytics")
+ }
+ }
+
+ function resetUserAnalytics() {
+ userAnalytics.value = {
+ oneMonth: {
+ labels: [],
+ data: []
+ },
+ sixMonth: {
+ labels: [],
+ data: []
+ },
+ oneYear: {
+ labels: [],
+ data: []
+ },
+ historical: {
+ labels: [],
+ data: []
+ }
}
+ }
+
+ return {
+ finishedComputingUerAnalytics: readonly(finishedComputingUerAnalytics),
+ loadingInitializeAnalytics: readonly(loadingInitializeAnalytics),
+ loadingInitializeAnalyticsError: readonly(loadingInitializeAnalyticsError),
+ rawUserAnalytics,
+ userAnalytics: readonly(userAnalytics),
+ initializeAnalyticsComposable,
+ updateAnalytics,
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/auth.ts b/apps/web/src/composables/auth.ts
index 39c2896a7..b65bf8edd 100644
--- a/apps/web/src/composables/auth.ts
+++ b/apps/web/src/composables/auth.ts
@@ -1,18 +1,18 @@
-import * as Session from 'supertokens-web-js/recipe/session'
-import { onMounted, onUnmounted, readonly, ref } from 'vue'
-import useEnvironment from '@/composables/environment'
-import useEthers from '@/composables/ethers'
-import useLedger from '@/composables/ledger'
-import useTrezor from '@/composables/trezor'
-import useUser from '@/composables/user'
-import useWalletConnect from '@/composables/walletConnectV2'
+import * as Session from "supertokens-web-js/recipe/session"
+import { onMounted, onUnmounted, readonly, ref } from "vue"
+import useEnvironment from "@/composables/environment"
+import useEthers from "@/composables/ethers"
+import useLedger from "@/composables/ledger"
+import useTrezor from "@/composables/trezor"
+import useUser from "@/composables/user"
+import useWalletConnect from "@/composables/walletConnectV2"
import {
Account,
ApiResponse,
LoginCredentials,
ProviderString,
UserAuthState,
-} from '@casimir/types'
+} from "@casimir/types"
const { usersUrl } = useEnvironment()
const { browserProvidersList, detectActiveEthersWalletAddress, loginWithEthers } =
@@ -48,19 +48,19 @@ export default function useAuth() {
account?.walletProvider === provider &&
account?.currency === currency
)
- if (userAccountExists) return 'Account already exists for this user'
+ if (userAccountExists) return "Account already exists for this user"
const account = {
userId: user?.value?.id,
address: address.toLowerCase() as string,
- currency: currency || 'ETH',
+ currency: currency || "ETH",
ownerAddress: user?.value?.address.toLowerCase() as string,
walletProvider: provider,
}
const requestOptions = {
- method: 'POST',
+ method: "POST",
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
body: JSON.stringify({ account, id: user?.value?.id }),
}
@@ -72,11 +72,11 @@ export default function useAuth() {
)
const { error, message, data: updatedUser } = await response.json()
if (error)
- throw new Error(message || 'There was an error adding the account')
+ throw new Error(message || "There was an error adding the account")
setUser(updatedUser)
return { error, message, data: updatedUser }
} catch (error: any) {
- throw new Error(error.message || 'Error adding account')
+ throw new Error(error.message || "Error adding account")
}
}
@@ -85,7 +85,7 @@ export default function useAuth() {
return await detectActiveEthersWalletAddress(providerString)
} else {
alert(
- 'detectActiveWalletAddress not yet implemented for this wallet provider'
+ "detectActiveWalletAddress not yet implemented for this wallet provider"
)
}
}
@@ -93,9 +93,9 @@ export default function useAuth() {
async function getUser() {
try {
const requestOptions = {
- method: 'GET',
+ method: "GET",
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
}
const response = await fetch(`${usersUrl}/user`, requestOptions)
@@ -103,7 +103,7 @@ export default function useAuth() {
if (error) throw new Error(error)
await setUser(retrievedUser)
} catch (error: any) {
- throw new Error('Error getting user from API route')
+ throw new Error("Error getting user from API route")
}
}
@@ -113,9 +113,9 @@ export default function useAuth() {
): Promise {
try {
const requestOptions = {
- method: 'GET',
+ method: "GET",
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
}
const response = await fetch(
@@ -126,7 +126,7 @@ export default function useAuth() {
if (error) throw new Error(message)
return { error, message, data }
} catch (error: any) {
- throw new Error(error.message || 'Error checking if primary user exists')
+ throw new Error(error.message || "Error checking if primary user exists")
}
}
@@ -140,7 +140,7 @@ export default function useAuth() {
const addressExistsOnUser = user.value?.accounts?.some(
(account: Account | any) => account?.address === address
)
- if (addressExistsOnUser) return 'Address already exists on this account'
+ if (addressExistsOnUser) return "Address already exists on this account"
// Check if it exists as a primary address of a different user
const {
@@ -148,7 +148,7 @@ export default function useAuth() {
} = await checkIfPrimaryUserExists(provider as ProviderString, address)
// If yes, ask user if they want to add it as a secondary to this account or if they want to log in with that account
if (sameAddress) {
- return 'Address already exists as a primary address on another account'
+ return "Address already exists as a primary address on another account"
// If they want to add to account, addAccountToUser
// If they don't want to add to their account, cancel (or log them out and log in with other account)
} else {
@@ -156,12 +156,12 @@ export default function useAuth() {
const { data: accountsIfSecondaryAddress } = await checkIfSecondaryAddress(address)
// If yes, alert user that it already exists as a secondary address on another account and ask if they want to add it as a secondary to this account
if (accountsIfSecondaryAddress.length) {
- console.log('accountsIfSecondaryAddress :>> ', accountsIfSecondaryAddress)
- return 'Address already exists as a secondary address on another account'
+ console.log("accountsIfSecondaryAddress :>> ", accountsIfSecondaryAddress)
+ return "Address already exists as a secondary address on another account"
} else {
// If no, addAccountToUser
await addAccountToUser(loginCredentials)
- return 'Successfully added account to user'
+ return "Successfully added account to user"
}
}
} else {
@@ -169,29 +169,29 @@ export default function useAuth() {
const { data: { sameAddress, walletProvider } } = await checkIfPrimaryUserExists(provider as ProviderString, address)
if (sameAddress) {
await loginWithProvider(loginCredentials as LoginCredentials)
- return 'Successfully logged in'
+ return "Successfully logged in"
}
// Then check if address is being used as a secondary account by another user
const { data: accountsIfSecondaryAddress } =
await checkIfSecondaryAddress(address)
- console.log('accountsIfSecondaryAddress :>> ', accountsIfSecondaryAddress)
+ console.log("accountsIfSecondaryAddress :>> ", accountsIfSecondaryAddress)
if (accountsIfSecondaryAddress.length) {
- return 'Address already exists as a secondary address on another account'
+ return "Address already exists as a secondary address on another account"
}
// Handle user interaction (do they want to sign in with another account?)
// If yes, log out (and/or log them in with the other account)
// If no, cancel/do nothing
- const hardwareWallet = provider === 'Ledger' || provider === 'Trezor'
+ const hardwareWallet = provider === "Ledger" || provider === "Trezor"
const browserWallet = browserProvidersList.includes(
provider as ProviderString
)
if (hardwareWallet) {
await loginWithProvider(loginCredentials as LoginCredentials)
await getUser()
- return 'Successfully logged in'
+ return "Successfully logged in"
} else if (browserWallet) {
const activeAddress = await detectActiveWalletAddress(
provider as ProviderString
@@ -200,41 +200,41 @@ export default function useAuth() {
await loginWithProvider({
provider: provider as ProviderString,
address,
- currency: 'ETH',
+ currency: "ETH",
})
- return 'Successfully logged in'
+ return "Successfully logged in"
} else {
- return 'Selected address is not active address in wallet'
+ return "Selected address is not active address in wallet"
}
} else {
- return 'Error in userAuthState'
+ return "Error in userAuthState"
}
}
} catch (error: any) {
- return 'Error in userAuthState'
+ return "Error in userAuthState"
}
}
async function loginWithSecondaryAddress(loginCredentials: LoginCredentials) {
const { address, provider } = loginCredentials
try {
- const hardwareWallet = provider === 'Ledger' || provider === 'Trezor'
+ const hardwareWallet = provider === "Ledger" || provider === "Trezor"
const browserWallet = browserProvidersList.includes(provider as ProviderString)
if (hardwareWallet) {
await loginWithProvider(loginCredentials as LoginCredentials)
await getUser()
- return 'Successfully created account and logged in'
+ return "Successfully created account and logged in"
} else if (browserWallet) {
const activeAddress = await detectActiveWalletAddress(provider as ProviderString)
if (activeAddress === address) {
- await loginWithProvider({ provider: provider as ProviderString, address,currency: 'ETH' })
- return 'Successfully created account and logged in'
+ await loginWithProvider({ provider: provider as ProviderString, address,currency: "ETH" })
+ return "Successfully created account and logged in"
} else {
- return 'Selected address is not active address in wallet'
+ return "Selected address is not active address in wallet"
}
}
- } catch(err) {
- return 'Error in userAuthState'
+ } catch (err) {
+ return "Error in userAuthState"
}
}
@@ -243,9 +243,9 @@ export default function useAuth() {
): Promise {
try {
const requestOptions = {
- method: 'GET',
+ method: "GET",
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
}
const response = await fetch(
@@ -256,7 +256,7 @@ export default function useAuth() {
if (error) throw new Error(message)
return { error, message, data }
} catch (error: any) {
- throw new Error(error.message || 'Error checking if secondary address')
+ throw new Error(error.message || "Error checking if secondary address")
}
}
@@ -272,18 +272,18 @@ export default function useAuth() {
try {
if (browserProvidersList.includes(provider)) {
await loginWithEthers(loginCredentials)
- } else if (provider === 'Ledger') {
+ } else if (provider === "Ledger") {
await loginWithLedger(loginCredentials)
- } else if (provider === 'Trezor') {
+ } else if (provider === "Trezor") {
await loginWithTrezor(loginCredentials)
- } else if (provider === 'WalletConnect') {
+ } else if (provider === "WalletConnect") {
await loginWithWalletConnectV2(loginCredentials)
} else {
- console.log('Sign up not yet supported for this wallet provider')
+ console.log("Sign up not yet supported for this wallet provider")
}
await getUser()
} catch (error: any) {
- throw new Error(error.message || 'There was an error logging in')
+ throw new Error(error.message || "There was an error logging in")
}
}
@@ -296,7 +296,7 @@ export default function useAuth() {
loadingSessionLogout.value = false
} catch (error) {
loadingSessionLogoutError.value = true
- console.log('Error logging out user :>> ', error)
+ console.log("Error logging out user :>> ", error)
loadingSessionLogout.value = false
}
// TODO: Fix bug that doesn't allow you to log in without refreshing page after a user logs out
@@ -315,7 +315,7 @@ export default function useAuth() {
loadingSessionLogin.value = false
} catch (error) {
loadingSessionLoginError.value = true
- console.log('error getting user :>> ', error)
+ console.log("error getting user :>> ", error)
loadingSessionLogin.value = false
}
}
@@ -356,9 +356,9 @@ export default function useAuth() {
async function updatePrimaryAddress(updatedAddress: string) {
const userId = user?.value?.id
const requestOptions = {
- method: 'PUT',
+ method: "PUT",
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
body: JSON.stringify({ userId, updatedAddress }),
}
diff --git a/apps/web/src/composables/breakdownMetrics.ts b/apps/web/src/composables/breakdownMetrics.ts
index 28b747315..ba91a5314 100644
--- a/apps/web/src/composables/breakdownMetrics.ts
+++ b/apps/web/src/composables/breakdownMetrics.ts
@@ -1,12 +1,12 @@
-import { readonly, ref, onMounted, watch } from 'vue'
-import { ethers } from 'ethers'
-import { Account, BreakdownAmount, BreakdownString, ContractEventsByAddress, UserWithAccountsAndOperators } from '@casimir/types'
-import useContracts from '@/composables/contracts'
-import useEnvironment from '@/composables/environment'
-import useFormat from '@/composables/format'
-import usePrice from '@/composables/price'
-import useUser from '@/composables/user'
-import { CasimirManager } from '@casimir/ethereum/build/@types'
+import { readonly, ref, onMounted, watch } from "vue"
+import { ethers } from "ethers"
+import { Account, BreakdownAmount, BreakdownString, ContractEventsByAddress, UserWithAccountsAndOperators } from "@casimir/types"
+import useContracts from "@/composables/contracts"
+import useEnvironment from "@/composables/environment"
+import useFormat from "@/composables/format"
+import usePrice from "@/composables/price"
+import useUser from "@/composables/user"
+import { CasimirManager } from "@casimir/ethereum/build/@types"
const { getContracts } = useContracts()
const { provider } = useEnvironment()
@@ -22,291 +22,291 @@ let baseManager: CasimirManager
let eigenManager: CasimirManager
export default function useBreakdownMetrics() {
- onMounted(() => {
- if (user.value) initializeBreakdownMetricsComposable()
- else uninitializeBreakdownMetricsComposable()
- })
+ onMounted(() => {
+ if (user.value) initializeBreakdownMetricsComposable()
+ else uninitializeBreakdownMetricsComposable()
+ })
- watch(user, async () => {
- if (user.value) initializeBreakdownMetricsComposable()
- else uninitializeBreakdownMetricsComposable()
- })
+ watch(user, async () => {
+ if (user.value) initializeBreakdownMetricsComposable()
+ else uninitializeBreakdownMetricsComposable()
+ })
- const currentStaked = ref({
- eth: '0 ETH',
- usd: '$0.00'
- })
+ const currentStaked = ref({
+ eth: "0 ETH",
+ usd: "$0.00"
+ })
- const stakingRewards = ref({
- eth: '0 ETH',
- usd: '$0.00'
- })
+ const stakingRewards = ref({
+ eth: "0 ETH",
+ usd: "$0.00"
+ })
- const totalWalletBalance = ref({
- eth: '0 ETH',
- usd: '$0.00'
- })
+ const totalWalletBalance = ref({
+ eth: "0 ETH",
+ usd: "$0.00"
+ })
- async function getAllTimeStakingRewards() : Promise {
- try {
- /* Get User's Current Stake */
- const addresses = (user.value as UserWithAccountsAndOperators).accounts.map((account: Account) => account.address) as string[]
- const currentUserStakePromises = [] as Array>
- addresses.forEach(address => currentUserStakePromises.push((baseManager as CasimirManager).getUserStake(address)))
- addresses.forEach(address => currentUserStakePromises.push((eigenManager as CasimirManager).getUserStake(address)))
- const settledCurrentUserStakePromises = await Promise.allSettled(currentUserStakePromises) as Array>
- const currentUserStake = settledCurrentUserStakePromises.filter(result => result.status === 'fulfilled').map(result => result.value)
- const currentUserStakeSum = currentUserStake.reduce((acc, curr) => acc.add(curr), ethers.BigNumber.from(0))
- const currentUserStakeETH = parseFloat(ethers.utils.formatEther(currentUserStakeSum))
+ async function getAllTimeStakingRewards() : Promise {
+ try {
+ /* Get User's Current Stake */
+ const addresses = (user.value as UserWithAccountsAndOperators).accounts.map((account: Account) => account.address) as string[]
+ const currentUserStakePromises = [] as Array>
+ addresses.forEach(address => currentUserStakePromises.push((baseManager as CasimirManager).getUserStake(address)))
+ addresses.forEach(address => currentUserStakePromises.push((eigenManager as CasimirManager).getUserStake(address)))
+ const settledCurrentUserStakePromises = await Promise.allSettled(currentUserStakePromises) as Array>
+ const currentUserStake = settledCurrentUserStakePromises.filter(result => result.status === "fulfilled").map(result => result.value)
+ const currentUserStakeSum = currentUserStake.reduce((acc, curr) => acc.add(curr), ethers.BigNumber.from(0))
+ const currentUserStakeETH = parseFloat(ethers.utils.formatEther(currentUserStakeSum))
- /* Get User's All Time Deposits and Withdrawals */
- const userEventTotalsPromises = [] as Array>
- addresses.forEach(address => {userEventTotalsPromises.push(getContractEventsTotalsByAddress(address, baseManager))})
- addresses.forEach(address => {userEventTotalsPromises.push(getContractEventsTotalsByAddress(address, eigenManager))})
- const userEventTotals = await Promise.all(userEventTotalsPromises) as Array
- const userEventTotalsSum = userEventTotals.reduce((acc, curr) => {
- const { StakeDeposited, WithdrawalInitiated, WithdrawalRequested, WithdrawalFulfilled } = curr
- return {
- StakeDeposited: acc.StakeDeposited + (StakeDeposited || 0),
- WithdrawalInitiated: acc.WithdrawalInitiated + (WithdrawalInitiated || 0),
- WithdrawalRequested: acc.WithdrawalRequested + (WithdrawalRequested || 0),
- WithdrawalFulfilled: acc.WithdrawalFulfilled + (WithdrawalFulfilled || 0)
- }
- }, { StakeDeposited: 0, WithdrawalInitiated: 0, WithdrawalRequested: 0, WithdrawalFulfilled: 0 } as { StakeDeposited: number; WithdrawalInitiated: number, WithdrawalRequested: number, WithdrawalFulfilled: number })
+ /* Get User's All Time Deposits and Withdrawals */
+ const userEventTotalsPromises = [] as Array>
+ addresses.forEach(address => {userEventTotalsPromises.push(getContractEventsTotalsByAddress(address, baseManager))})
+ addresses.forEach(address => {userEventTotalsPromises.push(getContractEventsTotalsByAddress(address, eigenManager))})
+ const userEventTotals = await Promise.all(userEventTotalsPromises) as Array
+ const userEventTotalsSum = userEventTotals.reduce((acc, curr) => {
+ const { StakeDeposited, WithdrawalInitiated, WithdrawalRequested, WithdrawalFulfilled } = curr
+ return {
+ StakeDeposited: acc.StakeDeposited + (StakeDeposited || 0),
+ WithdrawalInitiated: acc.WithdrawalInitiated + (WithdrawalInitiated || 0),
+ WithdrawalRequested: acc.WithdrawalRequested + (WithdrawalRequested || 0),
+ WithdrawalFulfilled: acc.WithdrawalFulfilled + (WithdrawalFulfilled || 0)
+ }
+ }, { StakeDeposited: 0, WithdrawalInitiated: 0, WithdrawalRequested: 0, WithdrawalFulfilled: 0 } as { StakeDeposited: number; WithdrawalInitiated: number, WithdrawalRequested: number, WithdrawalFulfilled: number })
- const stakedDepositedETH = userEventTotalsSum.StakeDeposited
- const withdrawalInitiatedETH = userEventTotalsSum.WithdrawalInitiated
- const withdrawalRequestedETH = userEventTotalsSum.WithdrawalRequested
- const withdrawalFulfilledETH = userEventTotalsSum.WithdrawalFulfilled
+ const stakedDepositedETH = userEventTotalsSum.StakeDeposited
+ const withdrawalInitiatedETH = userEventTotalsSum.WithdrawalInitiated
+ const withdrawalRequestedETH = userEventTotalsSum.WithdrawalRequested
+ const withdrawalFulfilledETH = userEventTotalsSum.WithdrawalFulfilled
- /* Get User's All Time Rewards */
- const currentUserStakeMinusEvents = currentUserStakeETH - stakedDepositedETH + ((withdrawalInitiatedETH) + (withdrawalRequestedETH) + (withdrawalFulfilledETH))
+ /* Get User's All Time Rewards */
+ const currentUserStakeMinusEvents = currentUserStakeETH - stakedDepositedETH + ((withdrawalInitiatedETH) + (withdrawalRequestedETH) + (withdrawalFulfilledETH))
- return {
- eth: `${formatNumber(currentUserStakeMinusEvents)} ETH`,
- usd: `$${formatNumber(currentUserStakeMinusEvents * (await getCurrentPrice({ coin: 'ETH', currency: 'USD' })))}`
- }
- } catch (err) {
- console.error(`There was an error in getAllTimeStakingRewards: ${err}`)
- return {
- eth: '0 ETH',
- usd: '$ 0.00'
- }
- }
+ return {
+ eth: `${formatNumber(currentUserStakeMinusEvents)} ETH`,
+ usd: `$${formatNumber(currentUserStakeMinusEvents * (await getCurrentPrice({ coin: "ETH", currency: "USD" })))}`
+ }
+ } catch (err) {
+ console.error(`There was an error in getAllTimeStakingRewards: ${err}`)
+ return {
+ eth: "0 ETH",
+ usd: "$ 0.00"
+ }
}
+ }
- async function getContractEventsTotalsByAddress(address: string, manager: CasimirManager) : Promise {
- try {
- const eventList = [
- 'StakeDeposited',
- 'StakeRebalanced',
- 'WithdrawalInitiated',
- 'WithdrawalRequested',
- 'WithdrawalFulfilled'
- ]
- const eventFilters = eventList.map(event => {
- if (event === 'StakeRebalanced') return (manager as CasimirManager).filters[event]()
- return ((manager as CasimirManager).filters as any)[event](address)
- })
+ async function getContractEventsTotalsByAddress(address: string, manager: CasimirManager) : Promise {
+ try {
+ const eventList = [
+ "StakeDeposited",
+ "StakeRebalanced",
+ "WithdrawalInitiated",
+ "WithdrawalRequested",
+ "WithdrawalFulfilled"
+ ]
+ const eventFilters = eventList.map(event => {
+ if (event === "StakeRebalanced") return (manager as CasimirManager).filters[event]()
+ return ((manager as CasimirManager).filters as any)[event](address)
+ })
- // const items = (await Promise.all(eventFilters.map(async eventFilter => await (manager as CasimirManager).queryFilter(eventFilter, 0, 'latest'))))
- // Use Promise.allSettled to avoid errors when a filter returns no results
- const items = (await Promise.allSettled(eventFilters.map(async eventFilter => await (manager as CasimirManager).queryFilter(eventFilter, 0, 'latest')))).map(result => result.status === 'fulfilled' ? result.value : [])
+ // const items = (await Promise.all(eventFilters.map(async eventFilter => await (manager as CasimirManager).queryFilter(eventFilter, 0, 'latest'))))
+ // Use Promise.allSettled to avoid errors when a filter returns no results
+ const items = (await Promise.allSettled(eventFilters.map(async eventFilter => await (manager as CasimirManager).queryFilter(eventFilter, 0, "latest")))).map(result => result.status === "fulfilled" ? result.value : [])
- const userEventTotals = eventList.reduce((acc, event) => {
- acc[event] = 0
- return acc
- }, {} as { [key: string]: number })
+ const userEventTotals = eventList.reduce((acc, event) => {
+ acc[event] = 0
+ return acc
+ }, {} as { [key: string]: number })
- for (const item of items) {
- for (const action of item) {
- const { args, event } = action
- const { amount } = args
- const amountInEth = parseFloat(ethers.utils.formatEther(amount))
- userEventTotals[event as string] += amountInEth
- }
- }
- return userEventTotals as ContractEventsByAddress
- } catch (err) {
- console.error(`There was an error in getContractEventsTotalsByAddress: ${err}`)
- return {
- StakeDeposited: 0,
- StakeRebalanced: 0,
- WithdrawalInitiated: 0,
- WithdrawalRequested: 0,
- WithdrawalFulfilled: 0
- }
+ for (const item of items) {
+ for (const action of item) {
+ const { args, event } = action
+ const { amount } = args
+ const amountInEth = parseFloat(ethers.utils.formatEther(amount))
+ userEventTotals[event as string] += amountInEth
}
+ }
+ return userEventTotals as ContractEventsByAddress
+ } catch (err) {
+ console.error(`There was an error in getContractEventsTotalsByAddress: ${err}`)
+ return {
+ StakeDeposited: 0,
+ StakeRebalanced: 0,
+ WithdrawalInitiated: 0,
+ WithdrawalRequested: 0,
+ WithdrawalFulfilled: 0
+ }
}
+ }
- async function getCurrentStaked(): Promise {
- const addresses = (user.value as UserWithAccountsAndOperators).accounts.map((account: Account) => account.address) as string[]
- try {
- const baseManagerPromises = addresses.map((address) => (baseManager as CasimirManager).getUserStake(address))
- const eigenManagerPromises = addresses.map((address) => (eigenManager as CasimirManager).getUserStake(address))
- const promises = [...baseManagerPromises, ...eigenManagerPromises]
- const settledPromises = await Promise.allSettled(promises) as Array>
- const currentStaked = settledPromises
- .filter((result) => result.status === 'fulfilled')
- .map((result) => result.value)
+ async function getCurrentStaked(): Promise {
+ const addresses = (user.value as UserWithAccountsAndOperators).accounts.map((account: Account) => account.address) as string[]
+ try {
+ const baseManagerPromises = addresses.map((address) => (baseManager as CasimirManager).getUserStake(address))
+ const eigenManagerPromises = addresses.map((address) => (eigenManager as CasimirManager).getUserStake(address))
+ const promises = [...baseManagerPromises, ...eigenManagerPromises]
+ const settledPromises = await Promise.allSettled(promises) as Array>
+ const currentStaked = settledPromises
+ .filter((result) => result.status === "fulfilled")
+ .map((result) => result.value)
- const totalStaked = currentStaked.reduce((accumulator, currentValue) => accumulator.add(currentValue), ethers.BigNumber.from(0))
- const totalStakedUSD = parseFloat(ethers.utils.formatEther(totalStaked)) * (await getCurrentPrice({ coin: 'ETH', currency: 'USD' }))
- const totalStakedETH = parseFloat(ethers.utils.formatEther(totalStaked))
- const formattedTotalStakedUSD = formatNumber(totalStakedUSD)
- const formattedTotalStakedETH = formatNumber(totalStakedETH)
- return {
- eth: formattedTotalStakedETH + ' ETH',
- usd: '$ ' + formattedTotalStakedUSD
- }
- } catch (error) {
- console.log('Error occurred while fetching stake:', error)
- return {
- eth: '0ETH',
- usd: '$0.00'
- }
- }
+ const totalStaked = currentStaked.reduce((accumulator, currentValue) => accumulator.add(currentValue), ethers.BigNumber.from(0))
+ const totalStakedUSD = parseFloat(ethers.utils.formatEther(totalStaked)) * (await getCurrentPrice({ coin: "ETH", currency: "USD" }))
+ const totalStakedETH = parseFloat(ethers.utils.formatEther(totalStaked))
+ const formattedTotalStakedUSD = formatNumber(totalStakedUSD)
+ const formattedTotalStakedETH = formatNumber(totalStakedETH)
+ return {
+ eth: formattedTotalStakedETH + " ETH",
+ usd: "$ " + formattedTotalStakedUSD
+ }
+ } catch (error) {
+ console.log("Error occurred while fetching stake:", error)
+ return {
+ eth: "0ETH",
+ usd: "$0.00"
+ }
}
+ }
- async function getEthersBalance(address: string) : Promise {
- const balance = await provider.getBalance(address)
- return parseFloat(ethers.utils.formatEther(balance))
- }
+ async function getEthersBalance(address: string) : Promise {
+ const balance = await provider.getBalance(address)
+ return parseFloat(ethers.utils.formatEther(balance))
+ }
- async function getTotalWalletBalance() : Promise {
- const promises = [] as Array>
- const addresses = (user.value as UserWithAccountsAndOperators).accounts.map((account: Account) => account.address) as string[]
- addresses.forEach((address) => { promises.push(getEthersBalance(address)) })
- const totalWalletBalance = (await Promise.all(promises)).reduce((acc, curr) => acc + curr, 0)
- const totalWalletBalanceUSD = totalWalletBalance * (await getCurrentPrice({ coin: 'ETH', currency: 'USD' }))
- const formattedTotalWalletBalance = formatNumber(totalWalletBalance)
- const formattedTotalWalletBalanceUSD = formatNumber(totalWalletBalanceUSD)
- return {
- eth: formattedTotalWalletBalance + ' ETH',
- usd: '$ ' + formattedTotalWalletBalanceUSD
- }
+ async function getTotalWalletBalance() : Promise {
+ const promises = [] as Array>
+ const addresses = (user.value as UserWithAccountsAndOperators).accounts.map((account: Account) => account.address) as string[]
+ addresses.forEach((address) => { promises.push(getEthersBalance(address)) })
+ const totalWalletBalance = (await Promise.all(promises)).reduce((acc, curr) => acc + curr, 0)
+ const totalWalletBalanceUSD = totalWalletBalance * (await getCurrentPrice({ coin: "ETH", currency: "USD" }))
+ const formattedTotalWalletBalance = formatNumber(totalWalletBalance)
+ const formattedTotalWalletBalanceUSD = formatNumber(totalWalletBalanceUSD)
+ return {
+ eth: formattedTotalWalletBalance + " ETH",
+ usd: "$ " + formattedTotalWalletBalanceUSD
}
+ }
- async function refreshBreakdown() {
- try {
- setBreakdownValue({ name: 'currentStaked', ...await getCurrentStaked() })
- setBreakdownValue({ name: 'totalWalletBalance', ...await getTotalWalletBalance() })
- setBreakdownValue({ name: 'stakingRewardsEarned', ...await getAllTimeStakingRewards() })
- } catch (err) {
- console.log(`There was an error in refreshBreakdown: ${err}`)
- }
+ async function refreshBreakdown() {
+ try {
+ setBreakdownValue({ name: "currentStaked", ...await getCurrentStaked() })
+ setBreakdownValue({ name: "totalWalletBalance", ...await getTotalWalletBalance() })
+ setBreakdownValue({ name: "stakingRewardsEarned", ...await getAllTimeStakingRewards() })
+ } catch (err) {
+ console.log(`There was an error in refreshBreakdown: ${err}`)
}
+ }
- function setBreakdownValue({ name, eth, usd }: { name: BreakdownString, eth: string, usd: string}) {
- switch (name) {
- case 'currentStaked':
- currentStaked.value = {
- eth,
- usd
- }
- break
- case 'totalWalletBalance':
- totalWalletBalance.value = {
- eth,
- usd
- }
- break
- case 'stakingRewardsEarned':
- stakingRewards.value = {
- eth,
- usd
- }
- break
- }
+ function setBreakdownValue({ name, eth, usd }: { name: BreakdownString, eth: string, usd: string}) {
+ switch (name) {
+ case "currentStaked":
+ currentStaked.value = {
+ eth,
+ usd
+ }
+ break
+ case "totalWalletBalance":
+ totalWalletBalance.value = {
+ eth,
+ usd
+ }
+ break
+ case "stakingRewardsEarned":
+ stakingRewards.value = {
+ eth,
+ usd
+ }
+ break
}
+ }
- function listenForContractEvents() {
- stopListeningForContractEvents() // Clear old listeners
- try {
- (baseManager as CasimirManager).on('StakeDeposited', stakeDepositedListener);
- (baseManager as CasimirManager).on('StakeRebalanced', stakeRebalancedListener);
- (baseManager as CasimirManager).on('WithdrawalInitiated', withdrawalInitiatedListener);
- (eigenManager as CasimirManager).on('StakeDeposited', stakeDepositedListener);
- (eigenManager as CasimirManager).on('StakeRebalanced', stakeRebalancedListener);
- (eigenManager as CasimirManager).on('WithdrawalInitiated', withdrawalInitiatedListener)
- } catch (err) {
- console.log(`There was an error in listenForContractEvents: ${err}`)
- }
+ function listenForContractEvents() {
+ stopListeningForContractEvents() // Clear old listeners
+ try {
+ (baseManager as CasimirManager).on("StakeDeposited", stakeDepositedListener);
+ (baseManager as CasimirManager).on("StakeRebalanced", stakeRebalancedListener);
+ (baseManager as CasimirManager).on("WithdrawalInitiated", withdrawalInitiatedListener);
+ (eigenManager as CasimirManager).on("StakeDeposited", stakeDepositedListener);
+ (eigenManager as CasimirManager).on("StakeRebalanced", stakeRebalancedListener);
+ (eigenManager as CasimirManager).on("WithdrawalInitiated", withdrawalInitiatedListener)
+ } catch (err) {
+ console.log(`There was an error in listenForContractEvents: ${err}`)
}
+ }
- function stopListeningForContractEvents() {
- (baseManager as CasimirManager).removeListener('StakeDeposited', stakeDepositedListener);
- (baseManager as CasimirManager).removeListener('StakeRebalanced', stakeRebalancedListener);
- (baseManager as CasimirManager).removeListener('WithdrawalInitiated', withdrawalInitiatedListener);
- (eigenManager as CasimirManager).removeListener('StakeDeposited', stakeDepositedListener);
- (eigenManager as CasimirManager).removeListener('StakeRebalanced', stakeRebalancedListener);
- (eigenManager as CasimirManager).removeListener('WithdrawalInitiated', withdrawalInitiatedListener)
- }
+ function stopListeningForContractEvents() {
+ (baseManager as CasimirManager).removeListener("StakeDeposited", stakeDepositedListener);
+ (baseManager as CasimirManager).removeListener("StakeRebalanced", stakeRebalancedListener);
+ (baseManager as CasimirManager).removeListener("WithdrawalInitiated", withdrawalInitiatedListener);
+ (eigenManager as CasimirManager).removeListener("StakeDeposited", stakeDepositedListener);
+ (eigenManager as CasimirManager).removeListener("StakeRebalanced", stakeRebalancedListener);
+ (eigenManager as CasimirManager).removeListener("WithdrawalInitiated", withdrawalInitiatedListener)
+ }
- const stakeDepositedListener = async () => await refreshBreakdown()
- const stakeRebalancedListener = async () => await refreshBreakdown()
- const withdrawalInitiatedListener = async () => await refreshBreakdown()
+ const stakeDepositedListener = async () => await refreshBreakdown()
+ const stakeRebalancedListener = async () => await refreshBreakdown()
+ const withdrawalInitiatedListener = async () => await refreshBreakdown()
- async function blockListener(blockNumber: number) {
- if (!user.value) return
- if (import.meta.env.MODE === 'development') console.log('blockNumber :>> ', blockNumber)
- const addresses = (user.value as UserWithAccountsAndOperators).accounts.map((account: Account) => account.address) as string[]
- const block = await provider.getBlockWithTransactions(blockNumber)
+ async function blockListener(blockNumber: number) {
+ if (!user.value) return
+ if (import.meta.env.MODE === "development") console.log("blockNumber :>> ", blockNumber)
+ const addresses = (user.value as UserWithAccountsAndOperators).accounts.map((account: Account) => account.address) as string[]
+ const block = await provider.getBlockWithTransactions(blockNumber)
- const txs = block.transactions.map(async (tx: any) => {
- if (addresses.includes(tx.from.toLowerCase())) {
- try {
- // const response = (manager as CasimirManager).interface.parseTransaction({ data: tx.data })
- // console.log('response :>> ', response)
- await refreshBreakdown()
- } catch (error) {
- console.error('Error parsing transaction:', error)
- }
- }
- })
-
- await Promise.all(txs)
- }
-
- async function initializeBreakdownMetricsComposable(){
- if (isInitialized.value) return
- const { baseManager: baseManagerFromContracts, eigenManager: eigenManagerFromContracts } = await getContracts()
- baseManager = baseManagerFromContracts
- eigenManager = eigenManagerFromContracts
-
+ const txs = block.transactions.map(async (tx: any) => {
+ if (addresses.includes(tx.from.toLowerCase())) {
try {
- loadingInitializeBreakdownMetrics.value = true
- provider.removeAllListeners('block')
- provider.on('block', blockListener as ethers.providers.Listener)
- listenForContractEvents()
- await refreshBreakdown()
- loadingInitializeBreakdownMetrics.value = false
- isInitialized.value = true
+ // const response = (manager as CasimirManager).interface.parseTransaction({ data: tx.data })
+ // console.log('response :>> ', response)
+ await refreshBreakdown()
} catch (error) {
- loadingInitializeBreakdownMetricsError.value = true
- console.log('Error initializing breakdown metrics :>> ', error)
- loadingInitializeBreakdownMetrics.value = false
+ console.error("Error parsing transaction:", error)
}
- }
+ }
+ })
+
+ await Promise.all(txs)
+ }
+
+ async function initializeBreakdownMetricsComposable() {
+ if (isInitialized.value) return
+ const { baseManager: baseManagerFromContracts, eigenManager: eigenManagerFromContracts } = await getContracts()
+ baseManager = baseManagerFromContracts
+ eigenManager = eigenManagerFromContracts
- async function uninitializeBreakdownMetricsComposable(){
- const { baseManager: baseManagerFromContracts, eigenManager: eigenManagerFromContracts } = await getContracts()
- baseManager = baseManagerFromContracts
- eigenManager = eigenManagerFromContracts
- provider.removeAllListeners('block')
- stopListeningForContractEvents()
- isInitialized.value = false
+ try {
+ loadingInitializeBreakdownMetrics.value = true
+ provider.removeAllListeners("block")
+ provider.on("block", blockListener as ethers.providers.Listener)
+ listenForContractEvents()
+ await refreshBreakdown()
+ loadingInitializeBreakdownMetrics.value = false
+ isInitialized.value = true
+ } catch (error) {
+ loadingInitializeBreakdownMetricsError.value = true
+ console.log("Error initializing breakdown metrics :>> ", error)
+ loadingInitializeBreakdownMetrics.value = false
}
+ }
+
+ async function uninitializeBreakdownMetricsComposable() {
+ const { baseManager: baseManagerFromContracts, eigenManager: eigenManagerFromContracts } = await getContracts()
+ baseManager = baseManagerFromContracts
+ eigenManager = eigenManagerFromContracts
+ provider.removeAllListeners("block")
+ stopListeningForContractEvents()
+ isInitialized.value = false
+ }
- return {
- currentStaked: readonly(currentStaked),
- loadingInitializeBreakdownMetrics: readonly(loadingInitializeBreakdownMetrics),
- loadingInitializeBreakdownMetricsError: readonly(loadingInitializeBreakdownMetricsError),
- stakingRewards: readonly(stakingRewards),
- totalWalletBalance: readonly(totalWalletBalance),
- initializeBreakdownMetricsComposable,
- uninitializeBreakdownMetricsComposable
- }
+ return {
+ currentStaked: readonly(currentStaked),
+ loadingInitializeBreakdownMetrics: readonly(loadingInitializeBreakdownMetrics),
+ loadingInitializeBreakdownMetricsError: readonly(loadingInitializeBreakdownMetricsError),
+ stakingRewards: readonly(stakingRewards),
+ totalWalletBalance: readonly(totalWalletBalance),
+ initializeBreakdownMetricsComposable,
+ uninitializeBreakdownMetricsComposable
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/contracts.ts b/apps/web/src/composables/contracts.ts
index 2a9702975..08b5b20b0 100644
--- a/apps/web/src/composables/contracts.ts
+++ b/apps/web/src/composables/contracts.ts
@@ -1,38 +1,38 @@
-import { ethers } from 'ethers'
-import useEnvironment from '@/composables/environment'
-import { ManagerConfig } from '@casimir/types'
-import { CasimirManager, CasimirRegistry, CasimirViews } from '@casimir/ethereum/build/@types'
-import ICasimirManagerAbi from '@casimir/ethereum/build/abi/ICasimirManager.json'
-import ICasimirRegistryAbi from '@casimir/ethereum/build/abi/ICasimirRegistry.json'
-import ICasimirViewsAbi from '@casimir/ethereum/build/abi/ICasimirViews.json'
+import { ethers } from "ethers"
+import useEnvironment from "@/composables/environment"
+import { ManagerConfig } from "@casimir/types"
+import { CasimirManager, CasimirRegistry, CasimirViews } from "@casimir/ethereum/build/@types"
+import ICasimirManagerAbi from "@casimir/ethereum/build/abi/ICasimirManager.json"
+import ICasimirRegistryAbi from "@casimir/ethereum/build/abi/ICasimirRegistry.json"
+import ICasimirViewsAbi from "@casimir/ethereum/build/abi/ICasimirViews.json"
const { provider, factory } = useEnvironment()
export default function useContracts() {
- async function getContracts() {
- const [baseManagerConfig, eigenManagerConfig] = await Promise.all((await factory.getManagerIds()).map(async (id: number) => {
- return await factory.getManagerConfig(id)
- }))
+ async function getContracts() {
+ const [baseManagerConfig, eigenManagerConfig] = await Promise.all((await factory.getManagerIds()).map(async (id: number) => {
+ return await factory.getManagerConfig(id)
+ }))
- const baseManager = new ethers.Contract(baseManagerConfig.managerAddress, ICasimirManagerAbi, provider) as CasimirManager
- const baseRegistry = new ethers.Contract(baseManagerConfig.registryAddress, ICasimirRegistryAbi, provider) as CasimirRegistry
- const baseViews = new ethers.Contract(baseManagerConfig.viewsAddress, ICasimirViewsAbi, provider) as CasimirViews
+ const baseManager = new ethers.Contract(baseManagerConfig.managerAddress, ICasimirManagerAbi, provider) as CasimirManager
+ const baseRegistry = new ethers.Contract(baseManagerConfig.registryAddress, ICasimirRegistryAbi, provider) as CasimirRegistry
+ const baseViews = new ethers.Contract(baseManagerConfig.viewsAddress, ICasimirViewsAbi, provider) as CasimirViews
- const eigenManager = new ethers.Contract(eigenManagerConfig?.managerAddress || ethers.constants.AddressZero, ICasimirManagerAbi, provider) as CasimirManager
- const eigenRegistry = new ethers.Contract(eigenManagerConfig?.registryAddress || ethers.constants.AddressZero, ICasimirRegistryAbi, provider) as CasimirRegistry
- const eigenViews = new ethers.Contract(eigenManagerConfig?.viewsAddress || ethers.constants.AddressZero, ICasimirViewsAbi, provider) as CasimirViews
-
- return {
- baseManager,
- baseRegistry,
- baseViews,
- eigenManager,
- eigenRegistry,
- eigenViews
- }
- }
+ const eigenManager = new ethers.Contract(eigenManagerConfig?.managerAddress || ethers.constants.AddressZero, ICasimirManagerAbi, provider) as CasimirManager
+ const eigenRegistry = new ethers.Contract(eigenManagerConfig?.registryAddress || ethers.constants.AddressZero, ICasimirRegistryAbi, provider) as CasimirRegistry
+ const eigenViews = new ethers.Contract(eigenManagerConfig?.viewsAddress || ethers.constants.AddressZero, ICasimirViewsAbi, provider) as CasimirViews
return {
- getContracts
+ baseManager,
+ baseRegistry,
+ baseViews,
+ eigenManager,
+ eigenRegistry,
+ eigenViews
}
+ }
+
+ return {
+ getContracts
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/environment.ts b/apps/web/src/composables/environment.ts
index 9a0c9d251..b8e99ba6d 100644
--- a/apps/web/src/composables/environment.ts
+++ b/apps/web/src/composables/environment.ts
@@ -1,22 +1,22 @@
-import { ethers } from 'ethers'
-import { CasimirFactory } from '@casimir/ethereum/build/@types'
-import ICasimirFactoryAbi from '@casimir/ethereum/build/abi/ICasimirFactory.json'
+import { ethers } from "ethers"
+import { CasimirFactory } from "@casimir/ethereum/build/@types"
+import ICasimirFactoryAbi from "@casimir/ethereum/build/abi/ICasimirFactory.json"
/* Browser environment */
const domain = window.location.host
const origin = window.location.origin
/* Ethereum environment */
-const ethereumUrl = import.meta.env.PUBLIC_ETHEREUM_RPC_URL || 'http://127.0.0.1:8545'
+const ethereumUrl = import.meta.env.PUBLIC_ETHEREUM_RPC_URL || "http://127.0.0.1:8545"
const provider = new ethers.providers.JsonRpcProvider(ethereumUrl)
/* Casimir environment */
-const docsUrl = import.meta.env.PUBLIC_DOCS_URL || 'https://docs.dev.casimir.co'
-const usersUrl = import.meta.env.PUBLIC_USERS_URL || 'http://localhost:4000'
+const docsUrl = import.meta.env.PUBLIC_DOCS_URL || "https://docs.dev.casimir.co"
+const usersUrl = import.meta.env.PUBLIC_USERS_URL || "http://localhost:4000"
const walletConnectProjectId = import.meta.env.PUBLIC_WALLET_CONNECT_PROJECT_ID
/** Network */
-const requiredNetwork: '1' | '5' = origin.includes('localhost') ? '5' : origin.includes('app.dev') ? '5' : '1'
+const requiredNetwork: "1" | "5" = origin.includes("localhost") ? "5" : origin.includes("app.dev") ? "5" : "1"
/* Addresses */
const factoryAddress = import.meta.env.PUBLIC_FACTORY_ADDRESS
@@ -25,28 +25,28 @@ const ssvNetworkAddress = import.meta.env.PUBLIC_SSV_NETWORK_ADDRESS
const ssvViewsAddress = import.meta.env.PUBLIC_SSV_VIEWS_ADDRESS
/* API Keys */
-const cryptoCompareApiKey = import.meta.env.PUBLIC_CRYPTO_COMPARE_API_KEY || ''
+const cryptoCompareApiKey = import.meta.env.PUBLIC_CRYPTO_COMPARE_API_KEY || ""
/* Emulators */
-const ledgerType = import.meta.env.PUBLIC_SPECULOS_URL ? 'speculos' : 'usb'
-const speculosUrl = import.meta.env.PUBLIC_SPECULOS_URL ? 'http://localhost:5001' : ''
+const ledgerType = import.meta.env.PUBLIC_SPECULOS_URL ? "speculos" : "usb"
+const speculosUrl = import.meta.env.PUBLIC_SPECULOS_URL ? "http://localhost:5001" : ""
export default function useEnvironment() {
- return {
- domain,
- cryptoCompareApiKey,
- ethereumUrl,
- factory,
- provider,
- origin,
- ledgerType,
- requiredNetwork,
- speculosUrl,
- ssvNetworkAddress,
- ssvViewsAddress,
- docsUrl,
- usersUrl,
- walletConnectProjectId
- }
+ return {
+ domain,
+ cryptoCompareApiKey,
+ ethereumUrl,
+ factory,
+ provider,
+ origin,
+ ledgerType,
+ requiredNetwork,
+ speculosUrl,
+ ssvNetworkAddress,
+ ssvViewsAddress,
+ docsUrl,
+ usersUrl,
+ walletConnectProjectId
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/ethers.ts b/apps/web/src/composables/ethers.ts
index 260f0b3e3..e2f0494b4 100644
--- a/apps/web/src/composables/ethers.ts
+++ b/apps/web/src/composables/ethers.ts
@@ -1,10 +1,10 @@
-import { ethers } from 'ethers'
-import { CryptoAddress, EthersProvider } from '@casimir/types'
-import { TransactionRequest } from '@casimir/types'
-import { GasEstimate, LoginCredentials, MessageRequest, ProviderString } from '@casimir/types'
-import useEnvironment from '@/composables/environment'
-import useSiwe from '@/composables/siwe'
-import useWallets from '@/composables/wallets'
+import { ethers } from "ethers"
+import { CryptoAddress, EthersProvider } from "@casimir/types"
+import { TransactionRequest } from "@casimir/types"
+import { GasEstimate, LoginCredentials, MessageRequest, ProviderString } from "@casimir/types"
+import useEnvironment from "@/composables/environment"
+import useSiwe from "@/composables/siwe"
+import useWallets from "@/composables/wallets"
interface ethereumWindow extends Window {
ethereum: any;
@@ -19,28 +19,28 @@ const { installedWallets } = useWallets()
export default function useEthers() {
const browserProvidersList = [
- 'BraveWallet',
- 'CoinbaseWallet',
- 'MetaMask',
- 'OkxWallet',
- 'TrustWallet'
+ "BraveWallet",
+ "CoinbaseWallet",
+ "MetaMask",
+ "OkxWallet",
+ "TrustWallet"
]
async function detectActiveEthersWalletAddress(providerString: ProviderString): Promise {
const provider = getBrowserProvider(providerString)
try {
if (provider) {
- const accounts = await provider.request({ method: 'eth_accounts' })
+ const accounts = await provider.request({ method: "eth_accounts" })
if (accounts.length > 0) {
return accounts[0] as string
}
- return ''
+ return ""
} else {
- return ''
+ return ""
}
- } catch(err) {
- console.error('There was an error in detectActiveEthersWalletAddress :>> ', err)
- return ''
+ } catch (err) {
+ console.error("There was an error in detectActiveEthersWalletAddress :>> ", err)
+ return ""
}
}
@@ -48,27 +48,27 @@ export default function useEthers() {
try {
const { ethereum } = window
const isInstalled = installedWallets.value.includes(providerString)
- if (providerString === 'CoinbaseWallet') {
- if (!ethereum.providerMap && isInstalled) return alert('TrustWallet or another wallet may be interfering with CoinbaseWallet. Please disable other wallets and try again.')
+ if (providerString === "CoinbaseWallet") {
+ if (!ethereum.providerMap && isInstalled) return alert("TrustWallet or another wallet may be interfering with CoinbaseWallet. Please disable other wallets and try again.")
if (ethereum?.providerMap) return ethereum.providerMap.get(providerString)
- else window.open('https://www.coinbase.com/wallet/downloads', '_blank')
- } else if (providerString === 'MetaMask') {
- if (ethereum.providerMap && ethereum.providerMap.get('MetaMask')) {
+ else window.open("https://www.coinbase.com/wallet/downloads", "_blank")
+ } else if (providerString === "MetaMask") {
+ if (ethereum.providerMap && ethereum.providerMap.get("MetaMask")) {
return ethereum?.providerMap?.get(providerString) || undefined
} else if (ethereum.isMetaMask) {
return ethereum
} else {
- window.open('https://metamask.io/download.html', '_blank')
+ window.open("https://metamask.io/download.html", "_blank")
}
- } else if (providerString === 'BraveWallet') {
+ } else if (providerString === "BraveWallet") {
return getBraveWallet()
- } else if (providerString === 'TrustWallet') {
+ } else if (providerString === "TrustWallet") {
return getTrustWallet()
- } else if (providerString === 'OkxWallet') {
+ } else if (providerString === "OkxWallet") {
return getOkxWallet()
}
- } catch(err) {
- console.error('There was an error in getBrowserProvider :>> ', err)
+ } catch (err) {
+ console.error("There was an error in getBrowserProvider :>> ", err)
}
}
@@ -81,10 +81,10 @@ export default function useEthers() {
const provider = new ethers.providers.JsonRpcProvider(rpcUrl)
const gasPrice = await provider.getFeeData() as ethers.providers.FeeData
const { maxFeePerGas, maxPriorityFeePerGas } = gasPrice
- const maxFeePerGasInWei = maxFeePerGas ? ethers.utils.parseEther(maxFeePerGas.toString()) : '0'
- const maxPriorityFeePerGasInWei = maxPriorityFeePerGas ? ethers.utils.parseEther(maxPriorityFeePerGas.toString()) : '0'
- if (maxFeePerGasInWei === '0') throw new Error('maxFeePerGasInWei is zero')
- if (maxPriorityFeePerGasInWei === '0') throw new Error('maxPriorityFeePerGasInWei is zero')
+ const maxFeePerGasInWei = maxFeePerGas ? ethers.utils.parseEther(maxFeePerGas.toString()) : "0"
+ const maxPriorityFeePerGasInWei = maxPriorityFeePerGas ? ethers.utils.parseEther(maxPriorityFeePerGas.toString()) : "0"
+ if (maxFeePerGasInWei === "0") throw new Error("maxFeePerGasInWei is zero")
+ if (maxPriorityFeePerGasInWei === "0") throw new Error("maxPriorityFeePerGasInWei is zero")
const { to, from, value } = unsignedTransaction
const tx = {
@@ -106,10 +106,10 @@ export default function useEthers() {
fee: feeInEth
}
} catch (err) {
- console.error('There was an error in estimateGasFee :>> ', err)
+ console.error("There was an error in estimateGasFee :>> ", err)
return {
- gasLimit: '0',
- fee: '0'
+ gasLimit: "0",
+ fee: "0"
}
}
}
@@ -133,10 +133,10 @@ export default function useEthers() {
fee: feeInEth
}
} catch (err) {
- console.error('There was an error in estimateGasFee :>> ', err)
+ console.error("There was an error in estimateGasFee :>> ", err)
return {
- gasLimit: '0',
- fee: '0'
+ gasLimit: "0",
+ fee: "0"
}
}
}
@@ -144,7 +144,7 @@ export default function useEthers() {
async function getEthersAddressesWithBalances (providerString: ProviderString): Promise {
const provider = getBrowserProvider(providerString)
if (provider) {
- const addresses = await provider.request({ method: 'eth_requestAccounts' })
+ const addresses = await provider.request({ method: "eth_requestAccounts" })
const addressesWithBalance: CryptoAddress[] = []
for (const address of addresses) {
const balance = (await getEthersBalance(address)).toString()
@@ -153,7 +153,7 @@ export default function useEthers() {
}
return addressesWithBalance
} else {
- throw new Error('Provider not yet connected to this dapp. Please connect and try again.')
+ throw new Error("Provider not yet connected to this dapp. Please connect and try again.")
}
}
@@ -196,12 +196,12 @@ export default function useEthers() {
return maxAfterFees
}
- async function loginWithEthers(loginCredentials: LoginCredentials): Promise{
+ async function loginWithEthers(loginCredentials: LoginCredentials): Promise {
const { provider, address, currency } = loginCredentials
const browserProvider = getBrowserProvider(provider)
const web3Provider: ethers.providers.Web3Provider = new ethers.providers.Web3Provider(browserProvider as EthersProvider)
try {
- const message = await createSiweMessage(address, 'Sign in with Ethereum to the app.')
+ const message = await createSiweMessage(address, "Sign in with Ethereum to the app.")
const signer = web3Provider.getSigner()
const signedMessage = await signer.signMessage(message)
await signInWithEthereum({
@@ -231,7 +231,7 @@ export default function useEthers() {
const requiredBalance = parseFloat(value) + parseFloat(fee)
const balance = await getEthersBalance(from)
if (balance < requiredBalance) {
- throw new Error('Insufficient balance')
+ throw new Error("Insufficient balance")
}
console.log(`Sending ${value} ETH to ${to} with estimated ${fee} ETH in fees using ~${gasLimit.toString()} in gas.`)
return await signer.sendTransaction(tx)
@@ -263,7 +263,7 @@ function getBraveWallet() {
if (ethereum?.isBraveWallet) {
return ethereum
} else {
- window.open('https://brave.com/download/', '_blank')
+ window.open("https://brave.com/download/", "_blank")
}
}
@@ -282,81 +282,81 @@ function getTrustWallet() {
if (provider.isTrustWallet) return provider
}
} else {
- window.open('https://trustwallet.com/download', '_blank')
+ window.open("https://trustwallet.com/download", "_blank")
}
}
const currenciesByChainId = {
- '1': {
- name: 'Mainnet ETH',
- currency: 'ETH',
+ "1": {
+ name: "Mainnet ETH",
+ currency: "ETH",
},
- '3': {
- name: 'Ropsten ETH',
- currency: 'ETH',
+ "3": {
+ name: "Ropsten ETH",
+ currency: "ETH",
},
- '4': {
- name: 'Rinkeby ETH',
- currency: 'ETH',
+ "4": {
+ name: "Rinkeby ETH",
+ currency: "ETH",
},
- '5': {
- name: 'Goerli ETH',
- currency: 'ETH',
+ "5": {
+ name: "Goerli ETH",
+ currency: "ETH",
},
- '42': {
- name: 'Kovan ETH',
- currency: 'ETH',
+ "42": {
+ name: "Kovan ETH",
+ currency: "ETH",
},
- '56': {
- name: 'Binance Smart Chain',
- currency: 'BNB',
+ "56": {
+ name: "Binance Smart Chain",
+ currency: "BNB",
},
- '97': {
- name: 'Binance Smart Chain Testnet',
- currency: 'BNB',
+ "97": {
+ name: "Binance Smart Chain Testnet",
+ currency: "BNB",
},
- '137': {
- name: 'Polygon',
- currency: 'MATIC',
+ "137": {
+ name: "Polygon",
+ currency: "MATIC",
},
- '31337': {
- name: 'Localhost Network',
- currency: 'ETH',
+ "31337": {
+ name: "Localhost Network",
+ currency: "ETH",
},
- '80001': {
- name: 'Polygon Testnet',
- currency: 'MATIC',
+ "80001": {
+ name: "Polygon Testnet",
+ currency: "MATIC",
},
- '4690': {
- name: 'IoTeX',
- currency: 'IOTX',
+ "4690": {
+ name: "IoTeX",
+ currency: "IOTX",
},
- '4691': {
- name: 'IoTeX Testnet',
- currency: 'IOTX',
+ "4691": {
+ name: "IoTeX Testnet",
+ currency: "IOTX",
},
}
const iotexNetwork = {
chainId: ethers.utils.hexlify(4690),
- chainName: 'IoTeX',
+ chainName: "IoTeX",
nativeCurrency: {
- name: 'IoTeX',
- symbol: 'IOTX',
- decimals: 18
+ name: "IoTeX",
+ symbol: "IOTX",
+ decimals: 18
},
- rpcUrls: ['https://api.testnet.iotex.one:80', 'http://api.testnet.iotex.one:80'],
- blockExplorerUrls: ['https://iotexscan.io']
+ rpcUrls: ["https://api.testnet.iotex.one:80", "http://api.testnet.iotex.one:80"],
+ blockExplorerUrls: ["https://iotexscan.io"]
}
const goerliNetwork = {
- chainId: '0x5',
- chainName: 'Goerli Testnet',
+ chainId: "0x5",
+ chainName: "Goerli Testnet",
nativeCurrency: {
- name: 'Goerli',
- symbol: 'GÖETH',
- decimals: 18
+ name: "Goerli",
+ symbol: "GÖETH",
+ decimals: 18
},
- rpcUrls: ['https://goerli.infura.io/v3/6b9f3a5d3d5e4c8e9b5d1f0c3e5f1e4a'],
- blockExplorerUrls: ['https://goerli.etherscan.io']
+ rpcUrls: ["https://goerli.infura.io/v3/6b9f3a5d3d5e4c8e9b5d1f0c3e5f1e4a"],
+ blockExplorerUrls: ["https://goerli.etherscan.io"]
}
\ No newline at end of file
diff --git a/apps/web/src/composables/files.ts b/apps/web/src/composables/files.ts
index d44bd21c6..93b963852 100644
--- a/apps/web/src/composables/files.ts
+++ b/apps/web/src/composables/files.ts
@@ -1,69 +1,69 @@
-import * as XLSX from 'xlsx'
+import * as XLSX from "xlsx"
export default function useFiles() {
- function exportFile(checkedItems: any, filteredData: any) {
- const jsonData = checkedItems.value.length > 0 ? checkedItems.value : filteredData.value
+ function exportFile(checkedItems: any, filteredData: any) {
+ const jsonData = checkedItems.value.length > 0 ? checkedItems.value : filteredData.value
- const isMac = navigator.userAgent.indexOf('Mac') !== -1
- const fileExtension = isMac ? 'csv' : 'xlsx'
+ const isMac = navigator.userAgent.indexOf("Mac") !== -1
+ const fileExtension = isMac ? "csv" : "xlsx"
- if (fileExtension === 'csv') {
- const csvContent = convertJsonToCsv(jsonData)
- downloadFile(csvContent, 'operator_performance.csv', 'text/csv')
- } else {
- const excelBuffer = convertJsonToExcelBuffer(jsonData)
- downloadFile(excelBuffer, 'operator_performance.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
- }
+ if (fileExtension === "csv") {
+ const csvContent = convertJsonToCsv(jsonData)
+ downloadFile(csvContent, "operator_performance.csv", "text/csv")
+ } else {
+ const excelBuffer = convertJsonToExcelBuffer(jsonData)
+ downloadFile(excelBuffer, "operator_performance.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
}
+ }
- return {
- exportFile
- }
+ return {
+ exportFile
+ }
}
function downloadFile (content: any, filename: string, mimeType: any) {
- const blob = new Blob([content], { type: mimeType })
- const url = URL.createObjectURL(blob)
- const link = document.createElement('a')
- link.href = url
- link.download = filename
- link.click()
+ const blob = new Blob([content], { type: mimeType })
+ const url = URL.createObjectURL(blob)
+ const link = document.createElement("a")
+ link.href = url
+ link.download = filename
+ link.click()
- // Cleanup
- URL.revokeObjectURL(url)
+ // Cleanup
+ URL.revokeObjectURL(url)
}
function convertJsonToExcelBuffer (jsonData: unknown[]) {
- const worksheet = XLSX.utils.json_to_sheet(jsonData)
- const workbook = XLSX.utils.book_new()
- XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
- const excelBuffer = XLSX.write(workbook, { type: 'array', bookType: 'xlsx' })
+ const worksheet = XLSX.utils.json_to_sheet(jsonData)
+ const workbook = XLSX.utils.book_new()
+ XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1")
+ const excelBuffer = XLSX.write(workbook, { type: "array", bookType: "xlsx" })
- return excelBuffer
+ return excelBuffer
}
function convertJsonToCsv (jsonData: any[]) {
- const separator = ','
- const csvRows = []
+ const separator = ","
+ const csvRows = []
- if (!Array.isArray(jsonData)) {
- return ''
- }
+ if (!Array.isArray(jsonData)) {
+ return ""
+ }
- if (jsonData.length === 0) {
- return ''
- }
+ if (jsonData.length === 0) {
+ return ""
+ }
- const keys = Object.keys(jsonData[0])
+ const keys = Object.keys(jsonData[0])
- // Add headers
- csvRows.push(keys.join(separator))
+ // Add headers
+ csvRows.push(keys.join(separator))
- // Convert JSON data to CSV rows
- jsonData.forEach(obj => {
- const values = keys.map(key => obj[key])
- csvRows.push(values.join(separator))
- })
+ // Convert JSON data to CSV rows
+ jsonData.forEach(obj => {
+ const values = keys.map(key => obj[key])
+ csvRows.push(values.join(separator))
+ })
- return csvRows.join('\n')
- }
\ No newline at end of file
+ return csvRows.join("\n")
+}
\ No newline at end of file
diff --git a/apps/web/src/composables/format.ts b/apps/web/src/composables/format.ts
index 5311f1c25..1adba37b7 100644
--- a/apps/web/src/composables/format.ts
+++ b/apps/web/src/composables/format.ts
@@ -1,52 +1,58 @@
export default function useFormat() {
- function convertString(inputString: string){
- if (inputString.length && inputString.length <= 4) {
- return inputString
- }
+ function convertString(inputString: string) {
+ if (inputString.length && inputString.length <= 4) {
+ return inputString
+ }
- const start = inputString.substring(0, 4)
- const end = inputString.substring(inputString.length - 4)
- const middle = '.'.repeat(4)
+ const start = inputString.substring(0, 4)
+ const end = inputString.substring(inputString.length - 4)
+ const middle = ".".repeat(4)
- return start + middle + end
- }
+ return start + middle + end
+ }
- function formatDecimalString(decimalString: string) {
- return parseFloat(decimalString).toFixed(2)
- }
+ function formatDecimalString(decimalString: string) {
+ return parseFloat(decimalString).toFixed(2)
+ }
- function formatNumber(number: number) {
- const SI_SYMBOL = ['', 'K', 'M', 'B', 'T', 'P', 'E']
- const tier = Math.floor(Math.log10(Math.abs(number)) / 3)
- let scale, scaled, suffix
+ function formatNumber(number: number) {
+ const SI_SYMBOL = ["",
+ "K",
+ "M",
+ "B",
+ "T",
+ "P",
+ "E"]
+ const tier = Math.floor(Math.log10(Math.abs(number)) / 3)
+ let scale, scaled, suffix
- if (number === 0) {
- return '0.00'
- } else if (Math.abs(number) < 1) {
- // Find the position of the first non-zero digit after the decimal point
- const decimalPlaces = Math.ceil(-Math.log10(Math.abs(number)))
- // Limit to 6 decimal places
- const fixedDecimals = Math.min(decimalPlaces, 6)
- return number.toFixed(fixedDecimals)
- } else if (tier === 0) {
- return number.toFixed(2)
- } else {
- suffix = SI_SYMBOL[tier]
- scale = Math.pow(10, tier * 3)
- scaled = number / scale
- return scaled.toFixed(2) + suffix
- }
+ if (number === 0) {
+ return "0.00"
+ } else if (Math.abs(number) < 1) {
+ // Find the position of the first non-zero digit after the decimal point
+ const decimalPlaces = Math.ceil(-Math.log10(Math.abs(number)))
+ // Limit to 6 decimal places
+ const fixedDecimals = Math.min(decimalPlaces, 6)
+ return number.toFixed(fixedDecimals)
+ } else if (tier === 0) {
+ return number.toFixed(2)
+ } else {
+ suffix = SI_SYMBOL[tier]
+ scale = Math.pow(10, tier * 3)
+ scaled = number / scale
+ return scaled.toFixed(2) + suffix
}
+ }
- function trimAndLowercaseAddress(address: string) {
- return address.trim().toLowerCase()
- }
+ function trimAndLowercaseAddress(address: string) {
+ return address.trim().toLowerCase()
+ }
- return {
- convertString,
- formatDecimalString,
- formatNumber,
- trimAndLowercaseAddress,
- }
+ return {
+ convertString,
+ formatDecimalString,
+ formatNumber,
+ trimAndLowercaseAddress,
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/ledger.ts b/apps/web/src/composables/ledger.ts
index 1626d8f6e..9ae596bb0 100644
--- a/apps/web/src/composables/ledger.ts
+++ b/apps/web/src/composables/ledger.ts
@@ -1,10 +1,10 @@
-import { /*BitcoinLedgerSigner, */EthersLedgerSigner } from '@casimir/wallets'
-import { ethers } from 'ethers'
-import { MessageRequest, TransactionRequest } from '@casimir/types'
-import { CryptoAddress, LoginCredentials } from '@casimir/types'
-import useEnvironment from '@/composables/environment'
-import useEthers from '@/composables/ethers'
-import useSiwe from '@/composables/siwe'
+import { /*BitcoinLedgerSigner, */EthersLedgerSigner } from "@casimir/wallets"
+import { ethers } from "ethers"
+import { MessageRequest, TransactionRequest } from "@casimir/types"
+import { CryptoAddress, LoginCredentials } from "@casimir/types"
+import useEnvironment from "@/composables/environment"
+import useEthers from "@/composables/ethers"
+import useSiwe from "@/composables/siwe"
const { createSiweMessage, signInWithEthereum } = useSiwe()
@@ -21,7 +21,7 @@ export default function useLedger() {
// }
function getEthersLedgerSigner(pathIndex?: number) {
- const path = pathIndex ? `m/44'/60'/0'/0/${pathIndex}` : 'm/44\'/60\'/0\'/0/0'
+ const path = pathIndex ? `m/44'/60'/0'/0/${pathIndex}` : "m/44'/60'/0'/0/0"
const options = {
provider: new ethers.providers.JsonRpcProvider(ethereumUrl),
type: ledgerType,
@@ -33,29 +33,29 @@ export default function useLedger() {
const getLedgerAddress = {
// 'BTC': getBitcoinLedgerAddress,
- 'ETH': getEthersLedgerAddresses,
- 'IOTX': () => {
+ "ETH": getEthersLedgerAddresses,
+ "IOTX": () => {
return new Promise((resolve, reject) => {
- console.log('IOTX is not yet supported on Ledger')
- resolve('IOTX is not yet supported on Ledger')
+ console.log("IOTX is not yet supported on Ledger")
+ resolve("IOTX is not yet supported on Ledger")
}) as Promise
},
- 'SOL': () => {
+ "SOL": () => {
return new Promise((resolve, reject) => {
- console.log('SOL is not yet supported on Ledger')
- resolve('SOL is not yet supported on Ledger')
+ console.log("SOL is not yet supported on Ledger")
+ resolve("SOL is not yet supported on Ledger")
}) as Promise
},
- '': () => {
+ "": () => {
return new Promise((resolve, reject) => {
- console.log('No currency selected')
- resolve('No currency selected')
+ console.log("No currency selected")
+ resolve("No currency selected")
}) as Promise
},
- 'USD': () => {
+ "USD": () => {
return new Promise((resolve, reject) => {
- console.log('USD is not yet supported on Ledger')
- resolve('USD is not yet supported on Ledger')
+ console.log("USD is not yet supported on Ledger")
+ resolve("USD is not yet supported on Ledger")
}) as Promise
}
}
@@ -77,7 +77,7 @@ export default function useLedger() {
// Derivation path m/44\'/60\'/0\'/0/1: 0x1a16ae0F5cf84CaE346a1D586d00366bBA69bccc
const { provider, address, currency, pathIndex } = loginCredentials
try {
- const message = await createSiweMessage(address, 'Sign in with Ethereum to the app.')
+ const message = await createSiweMessage(address, "Sign in with Ethereum to the app.")
const signer = getEthersLedgerSigner(pathIndex)
const signedMessage = await signer.signMessageWithIndex(message, pathIndex as number)
await signInWithEthereum({
@@ -88,13 +88,13 @@ export default function useLedger() {
signedMessage
})
} catch (err) {
- console.log('Error logging in: ', err)
+ console.log("Error logging in: ", err)
return err
}
}
async function sendLedgerTransaction({ from, to, value, currency }: TransactionRequest) {
- if (currency === 'ETH') {
+ if (currency === "ETH") {
const signer = getEthersLedgerSigner()
const provider = signer.provider as ethers.providers.Provider
const unsignedTransaction = {
@@ -107,8 +107,8 @@ export default function useLedger() {
const { gasPrice, gasLimit } = await getGasPriceAndLimit(ethereumUrl, unsignedTransaction as ethers.utils.Deferrable)
const balance = await provider.getBalance(from)
const required = gasPrice.mul(gasLimit).add(ethers.utils.parseEther(value))
- console.log('Balance', ethers.utils.formatEther(balance))
- console.log('Required', ethers.utils.formatEther(required))
+ console.log("Balance", ethers.utils.formatEther(balance))
+ console.log("Required", ethers.utils.formatEther(required))
return await signer.sendTransaction(unsignedTransaction as ethers.utils.Deferrable)
}/* else if (currency === 'BTC') {
@@ -117,7 +117,7 @@ export default function useLedger() {
}
async function signLedgerMessage(messageRequest: MessageRequest): Promise {
- if (messageRequest.currency === 'ETH') {
+ if (messageRequest.currency === "ETH") {
const { message } = messageRequest
const signer = getEthersLedgerSigner()
return await signer.signMessage(message)
@@ -126,7 +126,7 @@ export default function useLedger() {
const signer = getBitcoinLedgerSigner()
return await signer.signMessage(message)
} */else {
- return ''
+ return ""
}
}
diff --git a/apps/web/src/composables/operators.ts b/apps/web/src/composables/operators.ts
index 9773a3626..5aa5fa9cd 100644
--- a/apps/web/src/composables/operators.ts
+++ b/apps/web/src/composables/operators.ts
@@ -1,16 +1,16 @@
-import { readonly, ref } from 'vue'
-import { Operator, Scanner } from '@casimir/ssv'
-import { Account, PoolConfig, RegisteredOperator, RegisterOperatorWithCasimirParams } from '@casimir/types'
-import { ethers } from 'ethers'
-import useContracts from '@/composables/contracts'
-import useEnvironment from '@/composables/environment'
-import useEthers from '@/composables/ethers'
-import useLedger from '@/composables/ledger'
-import useTrezor from '@/composables/trezor'
-import useUser from '@/composables/user'
-import useWallets from '@/composables/wallets'
-import useWalletConnectV2 from '@/composables/walletConnectV2'
-import { CasimirManager, CasimirRegistry, CasimirViews } from '@casimir/ethereum/build/@types'
+import { readonly, ref } from "vue"
+import { Operator, Scanner } from "@casimir/ssv"
+import { Account, PoolConfig, RegisteredOperator, RegisterOperatorWithCasimirParams } from "@casimir/types"
+import { ethers } from "ethers"
+import useContracts from "@/composables/contracts"
+import useEnvironment from "@/composables/environment"
+import useEthers from "@/composables/ethers"
+import useLedger from "@/composables/ledger"
+import useTrezor from "@/composables/trezor"
+import useUser from "@/composables/user"
+import useWallets from "@/composables/wallets"
+import useWalletConnectV2 from "@/composables/walletConnectV2"
+import { CasimirManager, CasimirRegistry, CasimirViews } from "@casimir/ethereum/build/@types"
let baseManager: CasimirManager
let baseRegistry: CasimirRegistry
@@ -32,202 +32,201 @@ const loadingInitializeOperators = ref(false)
const loadingInitializeOperatorsError = ref(false)
export default function useOperators() {
- const loadingAddOperator = ref(false)
- const loadingAddOperatorError = ref(false)
- const loadingRegisteredOperators = ref(false)
- const loadingRegisteredOperatorsError = ref(false)
+ const loadingAddOperator = ref(false)
+ const loadingAddOperatorError = ref(false)
+ const loadingRegisteredOperators = ref(false)
+ const loadingRegisteredOperatorsError = ref(false)
- const nonregisteredBaseOperators = ref([])
- const nonregisteredEigenOperators = ref([])
- const registeredBaseOperators = ref([])
- const registeredEigenOperators = ref([])
+ const nonregisteredBaseOperators = ref([])
+ const nonregisteredEigenOperators = ref([])
+ const registeredBaseOperators = ref([])
+ const registeredEigenOperators = ref([])
- async function addOperator({ address, nodeUrl }: { address: string, nodeUrl: string }) {
- try {
- loadingAddOperator.value = true
- const requestOptions = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({ address, nodeUrl })
- }
- const response = await fetch(`${usersUrl}/user/add-operator`, requestOptions)
- const { error, message } = await response.json()
- loadingAddOperator.value = false
- return { error, message }
- } catch (error: any) {
- loadingAddOperatorError.value = true
- throw new Error(error.message || 'Error adding operator')
- }
+ async function addOperator({ address, nodeUrl }: { address: string, nodeUrl: string }) {
+ try {
+ loadingAddOperator.value = true
+ const requestOptions = {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({ address, nodeUrl })
+ }
+ const response = await fetch(`${usersUrl}/user/add-operator`, requestOptions)
+ const { error, message } = await response.json()
+ loadingAddOperator.value = false
+ return { error, message }
+ } catch (error: any) {
+ loadingAddOperatorError.value = true
+ throw new Error(error.message || "Error adding operator")
}
+ }
- async function getUserOperators(): Promise {
- const userAddresses = user.value?.accounts.map((account: Account) => account.address) as string[]
+ async function getUserOperators(): Promise {
+ const userAddresses = user.value?.accounts.map((account: Account) => account.address) as string[]
- const scanner = new Scanner({
- ethereumUrl,
- ssvNetworkAddress,
- ssvViewsAddress
- })
+ const scanner = new Scanner({
+ ethereumUrl,
+ ssvNetworkAddress,
+ ssvViewsAddress
+ })
- const ssvOperators: Operator[] = []
- for (const address of userAddresses) {
- const userOperators = await scanner.getOperators(address)
- ssvOperators.push(...userOperators)
- }
+ const ssvOperators: Operator[] = []
+ for (const address of userAddresses) {
+ const userOperators = await scanner.getOperators(address)
+ ssvOperators.push(...userOperators)
+ }
- registeredBaseOperators.value = await _getRegisteredOperators(ssvOperators, 'base') as Array
- registeredEigenOperators.value = await _getRegisteredOperators(ssvOperators, 'eigen') as Array
+ registeredBaseOperators.value = await _getRegisteredOperators(ssvOperators, "base") as Array
+ registeredEigenOperators.value = await _getRegisteredOperators(ssvOperators, "eigen") as Array
- nonregisteredBaseOperators.value = ssvOperators.filter((operator: any) => {
- const idRegistered = registeredBaseOperators.value.find((registeredOperator: any) => registeredOperator.id === operator.id)
- return !idRegistered
- }) as Array
- nonregisteredEigenOperators.value = ssvOperators.filter((operator: any) => {
- const idRegistered = registeredEigenOperators.value.find((registeredOperator: any) => registeredOperator.id === operator.id)
- return !idRegistered
- }) as Array
- }
+ nonregisteredBaseOperators.value = ssvOperators.filter((operator: any) => {
+ const idRegistered = registeredBaseOperators.value.find((registeredOperator: any) => registeredOperator.id === operator.id)
+ return !idRegistered
+ }) as Array
+ nonregisteredEigenOperators.value = ssvOperators.filter((operator: any) => {
+ const idRegistered = registeredEigenOperators.value.find((registeredOperator: any) => registeredOperator.id === operator.id)
+ return !idRegistered
+ }) as Array
+ }
- async function _getRegisteredOperators(ssvOperators: Operator[], type: 'base' | 'eigen'): Promise {
- const casimirOperators: RegisteredOperator[] = []
- const registry = type === 'base' ? baseRegistry : eigenRegistry
- if (registry.address === ethers.constants.AddressZero) return casimirOperators
- for (const operator of ssvOperators) {
- const { active, collateral, poolCount, resharing } = await (registry as CasimirRegistry).getOperator(operator.id)
- const registered = active || collateral.gt(0) || poolCount.gt(0) || resharing
- if (registered) {
- const pools = await _getPools(operator.id, type)
- // TODO: Replace these Public Nodes URLs once we have this working again
- const operatorStore = {
- '208': 'https://nodes.casimir.co/eth/goerli/dkg/1',
- '209': 'https://nodes.casimir.co/eth/goerli/dkg/2',
- '210': 'https://nodes.casimir.co/eth/goerli/dkg/3',
- '211': 'https://nodes.casimir.co/eth/goerli/dkg/4',
- '212': 'https://nodes.casimir.co/eth/goerli/dkg/5',
- '213': 'https://nodes.casimir.co/eth/goerli/dkg/6',
- '214': 'https://nodes.casimir.co/eth/goerli/dkg/7',
- '215': 'https://nodes.casimir.co/eth/goerli/dkg/8'
- }
- const url = operatorStore[operator.id.toString() as keyof typeof operatorStore]
- casimirOperators.push({
- ...operator,
- active,
- collateral: ethers.utils.formatEther(collateral),
- poolCount: poolCount.toNumber(),
- url,
- resharing,
- pools
- })
- }
+ async function _getRegisteredOperators(ssvOperators: Operator[], type: "base" | "eigen"): Promise {
+ const casimirOperators: RegisteredOperator[] = []
+ const registry = type === "base" ? baseRegistry : eigenRegistry
+ if (registry.address === ethers.constants.AddressZero) return casimirOperators
+ for (const operator of ssvOperators) {
+ const { active, collateral, poolCount, resharing } = await (registry as CasimirRegistry).getOperator(operator.id)
+ const registered = active || collateral.gt(0) || poolCount.gt(0) || resharing
+ if (registered) {
+ const pools = await _getPools(operator.id, type)
+ // TODO: Replace these Public Nodes URLs once we have this working again
+ const operatorStore = {
+ "208": "https://nodes.casimir.co/eth/goerli/dkg/1",
+ "209": "https://nodes.casimir.co/eth/goerli/dkg/2",
+ "210": "https://nodes.casimir.co/eth/goerli/dkg/3",
+ "211": "https://nodes.casimir.co/eth/goerli/dkg/4",
+ "212": "https://nodes.casimir.co/eth/goerli/dkg/5",
+ "213": "https://nodes.casimir.co/eth/goerli/dkg/6",
+ "214": "https://nodes.casimir.co/eth/goerli/dkg/7",
+ "215": "https://nodes.casimir.co/eth/goerli/dkg/8"
}
- return casimirOperators
+ const url = operatorStore[operator.id.toString() as keyof typeof operatorStore]
+ casimirOperators.push({
+ ...operator,
+ active,
+ collateral: ethers.utils.formatEther(collateral),
+ poolCount: poolCount.toNumber(),
+ url,
+ resharing,
+ pools
+ })
+ }
}
+ return casimirOperators
+ }
- async function _getPools(operatorId: number, type: 'base' | 'eigen'): Promise {
- const pools: PoolConfig[] = []
- const manager = type === 'base' ? baseManager : eigenManager
- const poolIds = [
- ...await (manager as CasimirManager).getPendingPoolIds(),
- ...await (manager as CasimirManager).getStakedPoolIds()
- ]
- const views = type === 'base' ? baseViews : eigenViews
+ async function _getPools(operatorId: number, type: "base" | "eigen"): Promise {
+ const pools: PoolConfig[] = []
+ const manager = type === "base" ? baseManager : eigenManager
+ const poolIds = [
+ ...await (manager as CasimirManager).getPendingPoolIds(), ...await (manager as CasimirManager).getStakedPoolIds()
+ ]
+ const views = type === "base" ? baseViews : eigenViews
- for (const poolId of poolIds) {
- const poolConfig = await (views as CasimirViews).getPoolConfig(poolId)
- const pool = {
- ...poolConfig,
- operatorIds: poolConfig.operatorIds.map(id => id.toNumber()),
- reshares: poolConfig.reshares.toNumber()
- }
- if (pool.operatorIds.includes(operatorId)) {
- pools.push(pool)
- }
- }
- return pools
+ for (const poolId of poolIds) {
+ const poolConfig = await (views as CasimirViews).getPoolConfig(poolId)
+ const pool = {
+ ...poolConfig,
+ operatorIds: poolConfig.operatorIds.map(id => id.toNumber()),
+ reshares: poolConfig.reshares.toNumber()
+ }
+ if (pool.operatorIds.includes(operatorId)) {
+ pools.push(pool)
+ }
}
+ return pools
+ }
- async function initializeOperatorComposable(){
- try {
- /* Get Manager, Views, and Registry */
- const { baseManager: managerContract, baseRegistry: registryContract, baseViews: viewsContract } = await getContracts()
- const { eigenManager: eigenManagerContract, eigenRegistry: eigenRegistryContract, eigenViews: eigenViewsContract } = await getContracts()
- baseManager = managerContract
- baseRegistry = registryContract
- baseViews = viewsContract
- eigenManager = eigenManagerContract
- eigenRegistry = eigenRegistryContract
- eigenViews = eigenViewsContract
+ async function initializeOperatorComposable() {
+ try {
+ /* Get Manager, Views, and Registry */
+ const { baseManager: managerContract, baseRegistry: registryContract, baseViews: viewsContract } = await getContracts()
+ const { eigenManager: eigenManagerContract, eigenRegistry: eigenRegistryContract, eigenViews: eigenViewsContract } = await getContracts()
+ baseManager = managerContract
+ baseRegistry = registryContract
+ baseViews = viewsContract
+ eigenManager = eigenManagerContract
+ eigenRegistry = eigenRegistryContract
+ eigenViews = eigenViewsContract
- loadingInitializeOperators.value = true
- listenForContractEvents()
- await getUserOperators()
- loadingInitializeOperators.value = false
- } catch (error) {
- loadingInitializeOperatorsError.value = true
- console.log('Error initializing operators :>> ', error)
- loadingInitializeOperators.value = false
- }
+ loadingInitializeOperators.value = true
+ listenForContractEvents()
+ await getUserOperators()
+ loadingInitializeOperators.value = false
+ } catch (error) {
+ loadingInitializeOperatorsError.value = true
+ console.log("Error initializing operators :>> ", error)
+ loadingInitializeOperators.value = false
}
+ }
- function listenForContractEvents() {
- try {
- (baseRegistry as CasimirRegistry).on('OperatorRegistered', () => getUserOperators());
- (eigenRegistry as CasimirRegistry).on('OperatorRegistered', () => getUserOperators())
+ function listenForContractEvents() {
+ try {
+ (baseRegistry as CasimirRegistry).on("OperatorRegistered", () => getUserOperators());
+ (eigenRegistry as CasimirRegistry).on("OperatorRegistered", () => getUserOperators())
- // (registry as CasimirRegistry).on('OperatorDeregistered', getUserOperators)
- // (registry as CasimirRegistry).on('DeregistrationRequested', getUserOperators)
- } catch (err) {
- console.log(`There was an error in listenForContractEvents: ${err}`)
- }
+ // (registry as CasimirRegistry).on('OperatorDeregistered', getUserOperators)
+ // (registry as CasimirRegistry).on('DeregistrationRequested', getUserOperators)
+ } catch (err) {
+ console.log(`There was an error in listenForContractEvents: ${err}`)
}
+ }
- // TODO: Move this to operators.ts to combine with AddOperator method
- async function registerOperatorWithCasimir({ walletProvider, address, operatorId, collateral, nodeUrl }: RegisterOperatorWithCasimirParams) {
- const activeNetwork = await detectActiveNetwork(walletProvider)
- if (activeNetwork !== 5) {
- await switchEthersNetwork(walletProvider, '0x5')
- return window.location.reload()
- }
- loadingRegisteredOperators.value = true
- try {
- let signer
- if (browserProvidersList.includes(walletProvider)) {
- signer = getEthersBrowserSigner(walletProvider)
- } else if (walletProvider === 'WalletConnect') {
- await getWalletConnectSignerV2()
- } else if (walletProvider === 'Ledger') {
- getEthersLedgerSigner()
- } else if (walletProvider === 'Trezor') {
- getEthersTrezorSigner()
- } else {
- throw new Error(`Invalid wallet provider: ${walletProvider}`)
- }
- const result = await (baseRegistry as CasimirRegistry).connect(signer as ethers.Signer).registerOperator(operatorId, { from: address, value: ethers.utils.parseEther(collateral)})
- // TODO: @shanejearley - How many confirmations do we want to wait?
- await result?.wait(1)
- await addOperator({address, nodeUrl})
- loadingRegisteredOperators.value = false
- } catch (err) {
- loadingRegisteredOperatorsError.value = true
- console.error(`There was an error in registerOperatorWithCasimir function: ${JSON.stringify(err)}`)
- loadingRegisteredOperators.value = false
- }
+ // TODO: Move this to operators.ts to combine with AddOperator method
+ async function registerOperatorWithCasimir({ walletProvider, address, operatorId, collateral, nodeUrl }: RegisterOperatorWithCasimirParams) {
+ const activeNetwork = await detectActiveNetwork(walletProvider)
+ if (activeNetwork !== 5) {
+ await switchEthersNetwork(walletProvider, "0x5")
+ return window.location.reload()
}
-
- return {
- nonregisteredBaseOperators: readonly(nonregisteredBaseOperators),
- nonregisteredEigenOperators: readonly(nonregisteredEigenOperators),
- registeredBaseOperators: readonly(registeredBaseOperators),
- registeredEigenOperators: readonly(registeredEigenOperators),
- loadingAddOperator: readonly(loadingAddOperator),
- loadingAddOperatorError: readonly(loadingAddOperatorError),
- loadingInitializeOperators: readonly(loadingInitializeOperators),
- loadingInitializeOperatorsError: readonly(loadingInitializeOperatorsError),
- initializeOperatorComposable,
- registerOperatorWithCasimir,
+ loadingRegisteredOperators.value = true
+ try {
+ let signer
+ if (browserProvidersList.includes(walletProvider)) {
+ signer = getEthersBrowserSigner(walletProvider)
+ } else if (walletProvider === "WalletConnect") {
+ await getWalletConnectSignerV2()
+ } else if (walletProvider === "Ledger") {
+ getEthersLedgerSigner()
+ } else if (walletProvider === "Trezor") {
+ getEthersTrezorSigner()
+ } else {
+ throw new Error(`Invalid wallet provider: ${walletProvider}`)
+ }
+ const result = await (baseRegistry as CasimirRegistry).connect(signer as ethers.Signer).registerOperator(operatorId, { from: address, value: ethers.utils.parseEther(collateral) })
+ // TODO: @shanejearley - How many confirmations do we want to wait?
+ await result?.wait(1)
+ await addOperator({ address, nodeUrl })
+ loadingRegisteredOperators.value = false
+ } catch (err) {
+ loadingRegisteredOperatorsError.value = true
+ console.error(`There was an error in registerOperatorWithCasimir function: ${JSON.stringify(err)}`)
+ loadingRegisteredOperators.value = false
}
+ }
+
+ return {
+ nonregisteredBaseOperators: readonly(nonregisteredBaseOperators),
+ nonregisteredEigenOperators: readonly(nonregisteredEigenOperators),
+ registeredBaseOperators: readonly(registeredBaseOperators),
+ registeredEigenOperators: readonly(registeredEigenOperators),
+ loadingAddOperator: readonly(loadingAddOperator),
+ loadingAddOperatorError: readonly(loadingAddOperatorError),
+ loadingInitializeOperators: readonly(loadingInitializeOperators),
+ loadingInitializeOperatorsError: readonly(loadingInitializeOperatorsError),
+ initializeOperatorComposable,
+ registerOperatorWithCasimir,
+ }
}
// async function _getSSVOperators(): Promise {
diff --git a/apps/web/src/composables/price.ts b/apps/web/src/composables/price.ts
index 1f538437b..18aa0ae66 100644
--- a/apps/web/src/composables/price.ts
+++ b/apps/web/src/composables/price.ts
@@ -1,5 +1,5 @@
-import { Currency } from '@casimir/types'
-import useEnvironment from './environment'
+import { Currency } from "@casimir/types"
+import useEnvironment from "./environment"
type PriceEntry = {
time: number;
@@ -15,85 +15,85 @@ type PriceEntry = {
export default function usePrice() {
- const { cryptoCompareApiKey } = useEnvironment()
+ const { cryptoCompareApiKey } = useEnvironment()
- function convertToWholeUnits (currency: Currency | string, amount: number) {
- switch (currency) {
- case 'BTC':
- return amount / 100000000
- break
+ function convertToWholeUnits (currency: Currency | string, amount: number) {
+ switch (currency) {
+ case "BTC":
+ return amount / 100000000
+ break
- case 'ETH':
- return amount / 1000000000000000000
- break
+ case "ETH":
+ return amount / 1000000000000000000
+ break
- default:
- break
- }
+ default:
+ break
}
+ }
- async function getExchangeRate(amount: string) {
+ async function getExchangeRate(amount: string) {
- if (amount === '0.0') {
- return 0
- }
+ if (amount === "0.0") {
+ return 0
+ }
- const price = await getCurrentPrice({ coin: 'ETH', currency: 'USD' })
- const rate = price * parseFloat(amount)
+ const price = await getCurrentPrice({ coin: "ETH", currency: "USD" })
+ const rate = price * parseFloat(amount)
- return rate
- }
+ return rate
+ }
- async function getConversionRateByDate (from: Currency, to: Currency, date: string) {
- const timestamp = Math.floor(new Date(date).getTime() / 1000)
- const options = {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- 'authorization': `Apikey ${cryptoCompareApiKey}`
- }
- }
- const response = await fetch (`https://min-api.cryptocompare.com/data/pricehistorical?fsym=${from}&tsyms=${to}&ts=${timestamp}`, options)
- const { [from]: data } = await response.json()
- return data[to]
+ async function getConversionRateByDate (from: Currency, to: Currency, date: string) {
+ const timestamp = Math.floor(new Date(date).getTime() / 1000)
+ const options = {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ "authorization": `Apikey ${cryptoCompareApiKey}`
+ }
}
+ const response = await fetch (`https://min-api.cryptocompare.com/data/pricehistorical?fsym=${from}&tsyms=${to}&ts=${timestamp}`, options)
+ const { [from]: data } = await response.json()
+ return data[to]
+ }
- async function getCurrentPrice({ coin, currency }: { coin: 'ETH' | 'BTC'; currency: 'USD' }) {
- const opt = {
- method: 'GET'
- }
+ async function getCurrentPrice({ coin, currency }: { coin: "ETH" | "BTC"; currency: "USD" }) {
+ const opt = {
+ method: "GET"
+ }
- const now = Math.floor(Date.now() / 1000)
+ const now = Math.floor(Date.now() / 1000)
- const url = `https://min-api.cryptocompare.com/data/v2/histominute?fsym=${coin}&tsym=${currency}&toTs=${now}&limit=1`
+ const url = `https://min-api.cryptocompare.com/data/v2/histominute?fsym=${coin}&tsym=${currency}&toTs=${now}&limit=1`
- try {
- const response = await fetch(url, opt)
+ try {
+ const response = await fetch(url, opt)
- const data = await response.json()
+ const data = await response.json()
- if (data.Response.toLowerCase() !== 'success') {
- throw new Error(data.Message)
- }
+ if (data.Response.toLowerCase() !== "success") {
+ throw new Error(data.Message)
+ }
- if (data.Data.Data.length === 0) {
- throw new Error('Empty response from API')
- }
+ if (data.Data.Data.length === 0) {
+ throw new Error("Empty response from API")
+ }
- const first = data.Data.Data[0] as PriceEntry
- const mid = (first.high + first.low) / 2
+ const first = data.Data.Data[0] as PriceEntry
+ const mid = (first.high + first.low) / 2
- return mid
- } catch (e) {
- console.log(e)
- return 0
- }
+ return mid
+ } catch (e) {
+ console.log(e)
+ return 0
}
+ }
- return {
- convertToWholeUnits,
- getCurrentPrice,
- getExchangeRate,
- getConversionRateByDate,
- }
+ return {
+ convertToWholeUnits,
+ getCurrentPrice,
+ getExchangeRate,
+ getConversionRateByDate,
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/router.ts b/apps/web/src/composables/router.ts
index 5d8d70d39..442ed5066 100644
--- a/apps/web/src/composables/router.ts
+++ b/apps/web/src/composables/router.ts
@@ -1,33 +1,32 @@
-import { createWebHistory, createRouter } from 'vue-router'
-import Overview from '@/pages/overview/Overview.vue'
-import Operator from '@/pages/operators/Operator.vue'
+import { createWebHistory, createRouter } from "vue-router"
+import Overview from "@/pages/overview/Overview.vue"
+import Operator from "@/pages/operators/Operator.vue"
const routes = [
- {
- path: '/',
- name: Overview,
- component: Overview,
- },
- {
- path: '/operator',
- name: Operator,
- component: Operator,
- }
+ {
+ path: "/",
+ name: Overview,
+ component: Overview,
+ }, {
+ path: "/operator",
+ name: Operator,
+ component: Operator,
+ }
]
if (import.meta.env.DEV) {
- // routes.push({
- // path: '/test',
- // name: Test,
- // component: Test,
- // })
+ // routes.push({
+ // path: '/test',
+ // name: Test,
+ // component: Test,
+ // })
}
const router = createRouter({
- history: createWebHistory(),
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- routes
+ history: createWebHistory(),
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ routes
})
export default router
\ No newline at end of file
diff --git a/apps/web/src/composables/screenDimensions.ts b/apps/web/src/composables/screenDimensions.ts
index cef49cf9e..40c904cf4 100644
--- a/apps/web/src/composables/screenDimensions.ts
+++ b/apps/web/src/composables/screenDimensions.ts
@@ -1,4 +1,4 @@
-import { onMounted, onUnmounted, readonly, ref } from 'vue'
+import { onMounted, onUnmounted, readonly, ref } from "vue"
const initializeComposable = ref(false)
@@ -8,32 +8,32 @@ const screenHeight = ref(0)
export default function useScreenDimensions() {
- const findScreenDimensions = () => {
- try {
- screenWidth.value = window.innerWidth
- screenHeight.value = window.innerHeight
- } catch (error) {
- console.log('Listening to screen dimensions error', error)
- }
-
+ const findScreenDimensions = () => {
+ try {
+ screenWidth.value = window.innerWidth
+ screenHeight.value = window.innerHeight
+ } catch (error) {
+ console.log("Listening to screen dimensions error", error)
}
+
+ }
- onMounted(() => {
- if(!initializeComposable.value){
- findScreenDimensions()
- window.addEventListener('resize', findScreenDimensions)
- initializeComposable.value = true
- }
+ onMounted(() => {
+ if (!initializeComposable.value) {
+ findScreenDimensions()
+ window.addEventListener("resize", findScreenDimensions)
+ initializeComposable.value = true
+ }
- })
+ })
- onUnmounted(() =>{
- window.removeEventListener('resize', findScreenDimensions)
- initializeComposable.value = false
- })
+ onUnmounted(() =>{
+ window.removeEventListener("resize", findScreenDimensions)
+ initializeComposable.value = false
+ })
- return {
- screenWidth: readonly(screenWidth),
- screenHeight: readonly(screenHeight)
- }
+ return {
+ screenWidth: readonly(screenWidth),
+ screenHeight: readonly(screenHeight)
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/siwe.ts b/apps/web/src/composables/siwe.ts
index aa58e281e..63c4a2df3 100644
--- a/apps/web/src/composables/siwe.ts
+++ b/apps/web/src/composables/siwe.ts
@@ -1,88 +1,88 @@
-import useEnvironment from '@/composables/environment'
-import { SignInWithEthereumCredentials } from '@casimir/types'
+import useEnvironment from "@/composables/environment"
+import { SignInWithEthereumCredentials } from "@casimir/types"
const { domain, usersUrl } = useEnvironment()
export default function useSiwe() {
- /**
+ /**
* Creates the message from the server to sign, which includes getting the nonce from auth server
*
* @param {ProviderString} address - The address the user is using to sign in
* @param {string} statement - The statement the user is signing
* @returns {Promise} - The response from the message request
*/
- async function createSiweMessage(address: string, statement: string) {
- try {
- const requestOptions = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- address
- })
- }
- const res = await fetch(`${usersUrl}/auth/nonce`, requestOptions)
- const { error, message: resMessage, data: nonce } = (await res.json())
- if (error) throw new Error(resMessage)
- const message = {
- domain,
- address,
- statement,
- uri: origin,
- version: '1',
- chainId: 5,
- nonce
- }
- return prepareMessage(message)
- } catch (error: any) {
- throw new Error(error.message || 'Error creating SIWE message')
- }
+ async function createSiweMessage(address: string, statement: string) {
+ try {
+ const requestOptions = {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ address
+ })
+ }
+ const res = await fetch(`${usersUrl}/auth/nonce`, requestOptions)
+ const { error, message: resMessage, data: nonce } = (await res.json())
+ if (error) throw new Error(resMessage)
+ const message = {
+ domain,
+ address,
+ statement,
+ uri: origin,
+ version: "1",
+ chainId: 5,
+ nonce
+ }
+ return prepareMessage(message)
+ } catch (error: any) {
+ throw new Error(error.message || "Error creating SIWE message")
}
+ }
- /**
+ /**
* Signs user up if they don't exist, otherwise
* logs the user in with an address, message, and signed message
*
* @param {SignInWithEthereumCredentials} signInWithEthereumCredentials - The user's address, provider, currency, message, and signed message
* @returns {Promise} - The response from the login request
*/
- async function signInWithEthereum(signInWithEthereumCredentials: SignInWithEthereumCredentials): Promise {
- try {
- const requestOptions = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(signInWithEthereumCredentials)
- }
- const response = await fetch(`${usersUrl}/auth/login`, requestOptions)
- const { error, message } = await response.json()
- if (error) throw new Error(message)
- } catch (error: any) {
- throw new Error(error.message || 'Error signing in with Ethereum')
- }
+ async function signInWithEthereum(signInWithEthereumCredentials: SignInWithEthereumCredentials): Promise {
+ try {
+ const requestOptions = {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify(signInWithEthereumCredentials)
+ }
+ const response = await fetch(`${usersUrl}/auth/login`, requestOptions)
+ const { error, message } = await response.json()
+ if (error) throw new Error(message)
+ } catch (error: any) {
+ throw new Error(error.message || "Error signing in with Ethereum")
}
+ }
- return {
- createSiweMessage,
- signInWithEthereum
- }
+ return {
+ createSiweMessage,
+ signInWithEthereum
+ }
}
function prepareMessage(obj: any) {
- const {
- domain,
- address,
- statement,
- uri,
- version,
- chainId,
- nonce,
- } = obj
+ const {
+ domain,
+ address,
+ statement,
+ uri,
+ version,
+ chainId,
+ nonce,
+ } = obj
- const issuedAt = new Date().toISOString()
- const message = `${domain} wants you to sign in with your Ethereum account:\n${address}\n\n${statement}\n\nURI: ${uri}\nVersion: ${version}\nChain ID: ${chainId}\nNonce: ${nonce}\nIssued At: ${issuedAt}`
+ const issuedAt = new Date().toISOString()
+ const message = `${domain} wants you to sign in with your Ethereum account:\n${address}\n\n${statement}\n\nURI: ${uri}\nVersion: ${version}\nChain ID: ${chainId}\nNonce: ${nonce}\nIssued At: ${issuedAt}`
- return message
+ return message
}
\ No newline at end of file
diff --git a/apps/web/src/composables/staking.ts b/apps/web/src/composables/staking.ts
index f486f4f59..7461ca813 100644
--- a/apps/web/src/composables/staking.ts
+++ b/apps/web/src/composables/staking.ts
@@ -1,14 +1,14 @@
-import { ref } from 'vue'
-import { ethers } from 'ethers'
-import { ProviderString } from '@casimir/types'
-import useContracts from '@/composables/contracts'
-import useEnvironment from '@/composables/environment'
-import useEthers from '@/composables/ethers'
-import useLedger from '@/composables/ledger'
-import useTrezor from '@/composables/trezor'
-import useWallets from '@/composables/wallets'
-import useWalletConnectV2 from './walletConnectV2'
-import { CasimirManager } from '@casimir/ethereum/build/@types'
+import { ref } from "vue"
+import { ethers } from "ethers"
+import { ProviderString } from "@casimir/types"
+import useContracts from "@/composables/contracts"
+import useEnvironment from "@/composables/environment"
+import useEthers from "@/composables/ethers"
+import useLedger from "@/composables/ledger"
+import useTrezor from "@/composables/trezor"
+import useWallets from "@/composables/wallets"
+import useWalletConnectV2 from "./walletConnectV2"
+import { CasimirManager } from "@casimir/ethereum/build/@types"
const { getContracts } = useContracts()
const { provider } = useEnvironment()
@@ -25,131 +25,131 @@ let eigenManager: CasimirManager
export default function useStaking() {
- async function initializeStakingComposable(){
- if (stakingComposableInitialized.value) return
- try {
- /* Get Managers */
- const { baseManager: baseManagerFromContracts, eigenManager: eigenManagerFromContracts } = await getContracts()
- baseManager = baseManagerFromContracts
- eigenManager = eigenManagerFromContracts
- stakingComposableInitialized.value = true
- } catch (error) {
- console.log('Error initializing staking component :>> ', error)
- }
+ async function initializeStakingComposable() {
+ if (stakingComposableInitialized.value) return
+ try {
+ /* Get Managers */
+ const { baseManager: baseManagerFromContracts, eigenManager: eigenManagerFromContracts } = await getContracts()
+ baseManager = baseManagerFromContracts
+ eigenManager = eigenManagerFromContracts
+ stakingComposableInitialized.value = true
+ } catch (error) {
+ console.log("Error initializing staking component :>> ", error)
}
+ }
- async function deposit({ amount, walletProvider, type }: { amount: string, walletProvider: ProviderString, type: 'default' | 'eigen' }) {
- try {
- const activeNetwork = await detectActiveNetwork(walletProvider)
- if (activeNetwork !== 5) {
- await switchEthersNetwork(walletProvider, '0x5')
- return window.location.reload()
- }
+ async function deposit({ amount, walletProvider, type }: { amount: string, walletProvider: ProviderString, type: "default" | "eigen" }) {
+ try {
+ const activeNetwork = await detectActiveNetwork(walletProvider)
+ if (activeNetwork !== 5) {
+ await switchEthersNetwork(walletProvider, "0x5")
+ return window.location.reload()
+ }
- let signer
- if (browserProvidersList.includes(walletProvider)) {
- signer = getEthersBrowserSigner(walletProvider)
- } else if (walletProvider === 'WalletConnect') {
- await getWalletConnectSignerV2()
- } else if (walletProvider === 'Ledger') {
- getEthersLedgerSigner()
- } else if (walletProvider === 'Trezor') {
- getEthersTrezorSigner()
- } else {
- throw new Error(`Invalid wallet provider: ${walletProvider}`)
- }
- const manager = type === 'default' ? baseManager : eigenManager
- const managerSigner = (manager as CasimirManager).connect(signer as ethers.Signer)
- const fees = await getDepositFees()
- const depositAmount = parseFloat(amount) * ((100 + fees) / 100)
- const value = ethers.utils.parseEther(depositAmount.toString())
- return await managerSigner.depositStake({ value, type: 2 })
- } catch (err) {
- console.error(`There was an error in deposit function: ${JSON.stringify(err)}`)
- return false
- }
+ let signer
+ if (browserProvidersList.includes(walletProvider)) {
+ signer = getEthersBrowserSigner(walletProvider)
+ } else if (walletProvider === "WalletConnect") {
+ await getWalletConnectSignerV2()
+ } else if (walletProvider === "Ledger") {
+ getEthersLedgerSigner()
+ } else if (walletProvider === "Trezor") {
+ getEthersTrezorSigner()
+ } else {
+ throw new Error(`Invalid wallet provider: ${walletProvider}`)
+ }
+ const manager = type === "default" ? baseManager : eigenManager
+ const managerSigner = (manager as CasimirManager).connect(signer as ethers.Signer)
+ const fees = await getDepositFees()
+ const depositAmount = parseFloat(amount) * ((100 + fees) / 100)
+ const value = ethers.utils.parseEther(depositAmount.toString())
+ return await managerSigner.depositStake({ value, type: 2 })
+ } catch (err) {
+ console.error(`There was an error in deposit function: ${JSON.stringify(err)}`)
+ return false
}
+ }
- async function getDepositFees(): Promise {
- try {
- // TODO: Fix this bug
- // const fees = await (manager as CasimirManager).FEE_PERCENT()
- const fees = 5
- const feesRounded = Math.round(fees * 100) / 100
- return feesRounded
- } catch (err: any) {
- console.error(`There was an error in getDepositFees function: ${JSON.stringify(err)}`)
- throw new Error(err)
- }
- }
-
- async function getUserStake(address: string): Promise {
- if (!stakingComposableInitialized.value) return 0
- try {
- const baseManagerBigNumber = await (baseManager as CasimirManager).getUserStake(address)
- const number = parseFloat(ethers.utils.formatEther(baseManagerBigNumber))
- const eigenManagerBigNumber = await (eigenManager as CasimirManager).getUserStake(address)
- const number2 = parseFloat(ethers.utils.formatEther(eigenManagerBigNumber))
- const total = number + number2
- return total
- } catch (err) {
- console.error(`There was an error in getUserStake function: ${JSON.stringify(err)}`)
- return 0
- }
+ async function getDepositFees(): Promise {
+ try {
+ // TODO: Fix this bug
+ // const fees = await (manager as CasimirManager).FEE_PERCENT()
+ const fees = 5
+ const feesRounded = Math.round(fees * 100) / 100
+ return feesRounded
+ } catch (err: any) {
+ console.error(`There was an error in getDepositFees function: ${JSON.stringify(err)}`)
+ throw new Error(err)
}
+ }
- async function getWithdrawableBalance({walletProvider, type}: {walletProvider: ProviderString, type: 'default' | 'eigen'}) {
- let signer
- if (browserProvidersList.includes(walletProvider)) {
- signer = getEthersBrowserSigner(walletProvider)
- } else if (walletProvider === 'WalletConnect') {
- await getWalletConnectSignerV2()
- } else if (walletProvider === 'Ledger') {
- getEthersLedgerSigner()
- } else if (walletProvider === 'Trezor') {
- getEthersTrezorSigner()
- } else {
- throw new Error(`Invalid wallet provider: ${walletProvider}`)
- }
- const manager = type === 'default' ? baseManager : eigenManager
- const managerSigner = (manager as CasimirManager).connect(signer as ethers.Signer)
- const withdrawableBalance = await managerSigner.getWithdrawableBalance()
- const withdrawableBalanceEther = ethers.utils.formatEther(withdrawableBalance)
- return withdrawableBalanceEther
+ async function getUserStake(address: string): Promise {
+ if (!stakingComposableInitialized.value) return 0
+ try {
+ const baseManagerBigNumber = await (baseManager as CasimirManager).getUserStake(address)
+ const number = parseFloat(ethers.utils.formatEther(baseManagerBigNumber))
+ const eigenManagerBigNumber = await (eigenManager as CasimirManager).getUserStake(address)
+ const number2 = parseFloat(ethers.utils.formatEther(eigenManagerBigNumber))
+ const total = number + number2
+ return total
+ } catch (err) {
+ console.error(`There was an error in getUserStake function: ${JSON.stringify(err)}`)
+ return 0
}
+ }
- async function withdraw({ amount, walletProvider, type }: { amount: string, walletProvider: ProviderString, type: 'default' | 'eigen' }) {
- const activeNetwork = await detectActiveNetwork(walletProvider)
- if (activeNetwork !== 5) {
- await switchEthersNetwork(walletProvider, '0x5')
- return window.location.reload()
- }
+ async function getWithdrawableBalance({ walletProvider, type }: {walletProvider: ProviderString, type: "default" | "eigen"}) {
+ let signer
+ if (browserProvidersList.includes(walletProvider)) {
+ signer = getEthersBrowserSigner(walletProvider)
+ } else if (walletProvider === "WalletConnect") {
+ await getWalletConnectSignerV2()
+ } else if (walletProvider === "Ledger") {
+ getEthersLedgerSigner()
+ } else if (walletProvider === "Trezor") {
+ getEthersTrezorSigner()
+ } else {
+ throw new Error(`Invalid wallet provider: ${walletProvider}`)
+ }
+ const manager = type === "default" ? baseManager : eigenManager
+ const managerSigner = (manager as CasimirManager).connect(signer as ethers.Signer)
+ const withdrawableBalance = await managerSigner.getWithdrawableBalance()
+ const withdrawableBalanceEther = ethers.utils.formatEther(withdrawableBalance)
+ return withdrawableBalanceEther
+ }
- let signer
- if (browserProvidersList.includes(walletProvider)) {
- signer = getEthersBrowserSigner(walletProvider)
- } else if (walletProvider === 'WalletConnect') {
- await getWalletConnectSignerV2()
- } else if (walletProvider === 'Ledger') {
- getEthersLedgerSigner()
- } else if (walletProvider === 'Trezor') {
- getEthersTrezorSigner()
- } else {
- throw new Error(`Invalid wallet provider: ${walletProvider}`)
- }
- const manager = type === 'default' ? baseManager : eigenManager
- const managerSigner = (manager as CasimirManager).connect(signer as ethers.Signer)
- const value = ethers.utils.parseEther(amount)
- return await managerSigner.requestWithdrawal(value)
+ async function withdraw({ amount, walletProvider, type }: { amount: string, walletProvider: ProviderString, type: "default" | "eigen" }) {
+ const activeNetwork = await detectActiveNetwork(walletProvider)
+ if (activeNetwork !== 5) {
+ await switchEthersNetwork(walletProvider, "0x5")
+ return window.location.reload()
}
- return {
- stakingComposableInitialized,
- initializeStakingComposable,
- deposit,
- getDepositFees,
- getUserStake,
- getWithdrawableBalance,
- withdraw
+ let signer
+ if (browserProvidersList.includes(walletProvider)) {
+ signer = getEthersBrowserSigner(walletProvider)
+ } else if (walletProvider === "WalletConnect") {
+ await getWalletConnectSignerV2()
+ } else if (walletProvider === "Ledger") {
+ getEthersLedgerSigner()
+ } else if (walletProvider === "Trezor") {
+ getEthersTrezorSigner()
+ } else {
+ throw new Error(`Invalid wallet provider: ${walletProvider}`)
}
+ const manager = type === "default" ? baseManager : eigenManager
+ const managerSigner = (manager as CasimirManager).connect(signer as ethers.Signer)
+ const value = ethers.utils.parseEther(amount)
+ return await managerSigner.requestWithdrawal(value)
+ }
+
+ return {
+ stakingComposableInitialized,
+ initializeStakingComposable,
+ deposit,
+ getDepositFees,
+ getUserStake,
+ getWithdrawableBalance,
+ withdraw
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/trezor.ts b/apps/web/src/composables/trezor.ts
index f5b5de085..d7314d457 100644
--- a/apps/web/src/composables/trezor.ts
+++ b/apps/web/src/composables/trezor.ts
@@ -1,129 +1,129 @@
-import { EthersTrezorSigner } from '@casimir/wallets'
-import useSiwe from '@/composables/siwe'
-import useEthers from '@/composables/ethers'
-import useEnvironment from '@/composables/environment'
-import { ethers } from 'ethers'
-import { LoginCredentials, MessageRequest, TransactionRequest } from '@casimir/types'
+import { EthersTrezorSigner } from "@casimir/wallets"
+import useSiwe from "@/composables/siwe"
+import useEthers from "@/composables/ethers"
+import useEnvironment from "@/composables/environment"
+import { ethers } from "ethers"
+import { LoginCredentials, MessageRequest, TransactionRequest } from "@casimir/types"
const { createSiweMessage, signInWithEthereum } = useSiwe()
-const trezorPath = 'm/44\'/60\'/0\'/0/0'
+const trezorPath = "m/44'/60'/0'/0/0"
export default function useTrezor() {
- const { ethereumUrl } = useEnvironment()
- const { getGasPriceAndLimit } = useEthers()
+ const { ethereumUrl } = useEnvironment()
+ const { getGasPriceAndLimit } = useEthers()
- // TODO: Implement this:
- function getBitcoinTrezorSigner() {
- return alert('Not implemented yet')
- // const options = {
- // path: trezorPath
- // }
- // return new BitcoinTrezorSigner(options)
- }
+ // TODO: Implement this:
+ function getBitcoinTrezorSigner() {
+ return alert("Not implemented yet")
+ // const options = {
+ // path: trezorPath
+ // }
+ // return new BitcoinTrezorSigner(options)
+ }
- function getEthersTrezorSigner(): EthersTrezorSigner {
- const options = {
- provider: new ethers.providers.JsonRpcProvider(ethereumUrl),
- path: trezorPath
- }
- return new EthersTrezorSigner(options)
+ function getEthersTrezorSigner(): EthersTrezorSigner {
+ const options = {
+ provider: new ethers.providers.JsonRpcProvider(ethereumUrl),
+ path: trezorPath
}
+ return new EthersTrezorSigner(options)
+ }
- const getTrezorAddress = {
- 'BTC': () => {
- return new Promise((resolve, reject) => {
- console.log('BTC is not yet supported on Trezor')
- resolve('BTC is not yet supported on Trezor')
- }) as Promise
- },
- 'ETH': getEthersTrezorAddresses,
- 'IOTX': () => {
- return new Promise((resolve, reject) => {
- console.log('IOTX is not yet supported on Trezor')
- resolve('IOTX is not yet supported on Trezor')
- }) as Promise
- },
- 'SOL': () => {
- return new Promise((resolve, reject) => {
- console.log('SOL is not yet supported on Trezor')
- resolve('SOL is not yet supported on Trezor')
- }) as Promise
- },
- '': () => {
- return new Promise((resolve, reject) => {
- console.log('No currency selected')
- resolve('No currency selected')
- }) as Promise
- },
- 'USD': () => {
- return new Promise((resolve, reject) => {
- console.log('USD is not yet supported on Trezor')
- resolve('USD is not yet supported on Trezor')
- }) as Promise
- }
+ const getTrezorAddress = {
+ "BTC": () => {
+ return new Promise((resolve, reject) => {
+ console.log("BTC is not yet supported on Trezor")
+ resolve("BTC is not yet supported on Trezor")
+ }) as Promise
+ },
+ "ETH": getEthersTrezorAddresses,
+ "IOTX": () => {
+ return new Promise((resolve, reject) => {
+ console.log("IOTX is not yet supported on Trezor")
+ resolve("IOTX is not yet supported on Trezor")
+ }) as Promise
+ },
+ "SOL": () => {
+ return new Promise((resolve, reject) => {
+ console.log("SOL is not yet supported on Trezor")
+ resolve("SOL is not yet supported on Trezor")
+ }) as Promise
+ },
+ "": () => {
+ return new Promise((resolve, reject) => {
+ console.log("No currency selected")
+ resolve("No currency selected")
+ }) as Promise
+ },
+ "USD": () => {
+ return new Promise((resolve, reject) => {
+ console.log("USD is not yet supported on Trezor")
+ resolve("USD is not yet supported on Trezor")
+ }) as Promise
}
+ }
- async function getEthersTrezorAddresses() {
- const signer = getEthersTrezorSigner()
- return await signer.getAddresses()
- }
+ async function getEthersTrezorAddresses() {
+ const signer = getEthersTrezorSigner()
+ return await signer.getAddresses()
+ }
- async function loginWithTrezor(loginCredentials: LoginCredentials) {
- const { provider, address, currency, pathIndex } = loginCredentials
- try {
- const message = await createSiweMessage(address, 'Sign in with Ethereum to the app.')
- const signer = getEthersTrezorSigner()
- const signedMessage = await signer.signMessageWithIndex(message, pathIndex as number)
- await signInWithEthereum({
- address,
- currency,
- message,
- provider,
- signedMessage
- })
- } catch (error: any) {
- console.log(error)
- throw new Error(error)
- }
+ async function loginWithTrezor(loginCredentials: LoginCredentials) {
+ const { provider, address, currency, pathIndex } = loginCredentials
+ try {
+ const message = await createSiweMessage(address, "Sign in with Ethereum to the app.")
+ const signer = getEthersTrezorSigner()
+ const signedMessage = await signer.signMessageWithIndex(message, pathIndex as number)
+ await signInWithEthereum({
+ address,
+ currency,
+ message,
+ provider,
+ signedMessage
+ })
+ } catch (error: any) {
+ console.log(error)
+ throw new Error(error)
}
+ }
- async function sendTrezorTransaction({ from, to, value }: TransactionRequest) {
- const signer = getEthersTrezorSigner()
- const provider = signer.provider as ethers.providers.Provider
- const { chainId } = await provider.getNetwork()
- const nonce = await provider.getTransactionCount(from)
- const unsignedTransaction = {
- to,
- data: '0x00',
- nonce,
- chainId,
- value: ethers.utils.parseUnits(value),
- type: 0
- } as ethers.UnsignedTransaction
- const { gasPrice, gasLimit } = await getGasPriceAndLimit(ethereumUrl, unsignedTransaction as ethers.utils.Deferrable)
- unsignedTransaction.gasPrice = gasPrice
- unsignedTransaction.gasLimit = gasLimit
+ async function sendTrezorTransaction({ from, to, value }: TransactionRequest) {
+ const signer = getEthersTrezorSigner()
+ const provider = signer.provider as ethers.providers.Provider
+ const { chainId } = await provider.getNetwork()
+ const nonce = await provider.getTransactionCount(from)
+ const unsignedTransaction = {
+ to,
+ data: "0x00",
+ nonce,
+ chainId,
+ value: ethers.utils.parseUnits(value),
+ type: 0
+ } as ethers.UnsignedTransaction
+ const { gasPrice, gasLimit } = await getGasPriceAndLimit(ethereumUrl, unsignedTransaction as ethers.utils.Deferrable)
+ unsignedTransaction.gasPrice = gasPrice
+ unsignedTransaction.gasLimit = gasLimit
- // Todo check before click (user can +/- gas limit accordingly)
- const balance = await provider.getBalance(from)
- const required = gasPrice.mul(gasLimit).add(ethers.utils.parseEther(value))
- console.log('Balance', ethers.utils.formatEther(balance))
- console.log('Required', ethers.utils.formatEther(required))
- return await signer.sendTransaction(unsignedTransaction as ethers.utils.Deferrable)
- }
+ // Todo check before click (user can +/- gas limit accordingly)
+ const balance = await provider.getBalance(from)
+ const required = gasPrice.mul(gasLimit).add(ethers.utils.parseEther(value))
+ console.log("Balance", ethers.utils.formatEther(balance))
+ console.log("Required", ethers.utils.formatEther(required))
+ return await signer.sendTransaction(unsignedTransaction as ethers.utils.Deferrable)
+ }
- async function signTrezorMessage(messageRequest: MessageRequest): Promise {
- const { message } = messageRequest
- const signer = getEthersTrezorSigner()
- return await signer.signMessage(message)
- }
+ async function signTrezorMessage(messageRequest: MessageRequest): Promise {
+ const { message } = messageRequest
+ const signer = getEthersTrezorSigner()
+ return await signer.signMessage(message)
+ }
- return {
- getEthersTrezorSigner,
- getTrezorAddress,
- loginWithTrezor,
- sendTrezorTransaction,
- signTrezorMessage
- }
+ return {
+ getEthersTrezorSigner,
+ getTrezorAddress,
+ loginWithTrezor,
+ sendTrezorTransaction,
+ signTrezorMessage
+ }
}
\ No newline at end of file
diff --git a/apps/web/src/composables/user.ts b/apps/web/src/composables/user.ts
index 1700493da..502bb8655 100644
--- a/apps/web/src/composables/user.ts
+++ b/apps/web/src/composables/user.ts
@@ -1,7 +1,7 @@
-import { onMounted, onUnmounted, readonly, ref, watch } from 'vue'
-import { Account, UserWithAccountsAndOperators } from '@casimir/types'
-import useEnvironment from '@/composables/environment'
-import { ethers } from 'ethers'
+import { onMounted, onUnmounted, readonly, ref, watch } from "vue"
+import { Account, UserWithAccountsAndOperators } from "@casimir/types"
+import useEnvironment from "@/composables/environment"
+import { ethers } from "ethers"
// Test address: 0xd557a5745d4560B24D36A68b52351ffF9c86A212
const { provider, usersUrl } = useEnvironment()
@@ -49,15 +49,15 @@ export default function useUser() {
user.value.accounts = accountsWithBalances
}
} catch (error) {
- throw new Error('Error setting user account balances')
+ throw new Error("Error setting user account balances")
}
}
async function updateUserAgreement(agreed: boolean) {
const requestOptions = {
- method: 'PUT',
+ method: "PUT",
headers: {
- 'Content-Type': 'application/json',
+ "Content-Type": "application/json",
},
body: JSON.stringify({ agreed }),
}
diff --git a/apps/web/src/composables/walletConnectV2.ts b/apps/web/src/composables/walletConnectV2.ts
index 59c9f3148..81393b464 100644
--- a/apps/web/src/composables/walletConnectV2.ts
+++ b/apps/web/src/composables/walletConnectV2.ts
@@ -1,12 +1,12 @@
-import { ref, shallowRef } from 'vue'
-import { providers } from 'ethers'
-import { EthereumProvider } from '@walletconnect/ethereum-provider'
-import { WalletConnectModal } from '@walletconnect/modal'
-import { PairingTypes, SessionTypes } from '@walletconnect/types'
-import useSiwe from '@/composables/siwe'
-import useEthers from '@/composables/ethers'
-import useEnvironment from '@/composables/environment'
-import { CryptoAddress, LoginCredentials } from '@casimir/types'
+import { ref, shallowRef } from "vue"
+import { providers } from "ethers"
+import { EthereumProvider } from "@walletconnect/ethereum-provider"
+import { WalletConnectModal } from "@walletconnect/modal"
+import { PairingTypes, SessionTypes } from "@walletconnect/types"
+import useSiwe from "@/composables/siwe"
+import useEthers from "@/composables/ethers"
+import useEnvironment from "@/composables/environment"
+import { CryptoAddress, LoginCredentials } from "@casimir/types"
const { createSiweMessage, signInWithEthereum } = useSiwe()
const { walletConnectProjectId } = useEnvironment()
@@ -27,31 +27,31 @@ const componentIsMounted = ref(false)
const isInitializing = ref(false)
export default function useWalletConnectV2() {
- async function connectWalletConnectV2(chainId: '1' | '5' | '1337', pairing?: PairingTypes.Struct): Promise {
+ async function connectWalletConnectV2(chainId: "1" | "5" | "1337", pairing?: PairingTypes.Struct): Promise {
try {
- if (!ethereumProvider.value) throw new ReferenceError('WalletConnect Client is not initialized.')
+ if (!ethereumProvider.value) throw new ReferenceError("WalletConnect Client is not initialized.")
- const customRpcs = {
- '1': `https://rpc.walletconnect.com?chainId=eip155:1&projectId=${walletConnectProjectId}`,
- '5': `https://rpc.walletconnect.com?chainId=eip155:5&projectId=${walletConnectProjectId}`,
- '1337': `https://rpc.walletconnect.com?chainId=eip155:1337&projectId=${walletConnectProjectId}`
- }
- const rpcUrl = customRpcs[chainId]
- if (!rpcUrl) throw new Error(`RPC URL not found for chainId: ${chainId}`)
-
- await ethereumProvider.value.connect()
- createEthersProvider()
- const _accounts = await ethereumProvider.value.enable()
- accounts.value = _accounts
- session.value = session
- web3Modal.value?.closeModal()
- const connectedAddress = _accounts[0].toLowerCase().trim() as string
- const connectedAddressBalance = (await getEthersBalance(connectedAddress)).toString()
-
- return [{ address: connectedAddress as string, balance: connectedAddressBalance }]
+ const customRpcs = {
+ "1": `https://rpc.walletconnect.com?chainId=eip155:1&projectId=${walletConnectProjectId}`,
+ "5": `https://rpc.walletconnect.com?chainId=eip155:5&projectId=${walletConnectProjectId}`,
+ "1337": `https://rpc.walletconnect.com?chainId=eip155:1337&projectId=${walletConnectProjectId}`
+ }
+ const rpcUrl = customRpcs[chainId]
+ if (!rpcUrl) throw new Error(`RPC URL not found for chainId: ${chainId}`)
+
+ await ethereumProvider.value.connect()
+ createEthersProvider()
+ const _accounts = await ethereumProvider.value.enable()
+ accounts.value = _accounts
+ session.value = session
+ web3Modal.value?.closeModal()
+ const connectedAddress = _accounts[0].toLowerCase().trim() as string
+ const connectedAddressBalance = (await getEthersBalance(connectedAddress)).toString()
+
+ return [{ address: connectedAddress as string, balance: connectedAddressBalance }]
} catch (error) {
- console.error('Failed to connect:', error)
- throw error
+ console.error("Failed to connect:", error)
+ throw error
}
}
@@ -64,7 +64,11 @@ export default function useWalletConnectV2() {
projectId: walletConnectProjectId,
chains: [5],
showQrModal: true,
- methods: ['eth_sendTransaction', 'eth_signTransaction', 'eth_sign', 'personal_sign', 'eth_signTypedData']
+ methods: ["eth_sendTransaction",
+ "eth_signTransaction",
+ "eth_sign",
+ "personal_sign",
+ "eth_signTypedData"]
})
web3Modal.value = new WalletConnectModal({
@@ -87,7 +91,7 @@ export default function useWalletConnectV2() {
async function disconnect() {
if (!ethereumProvider.value) {
- throw new Error('ethereumProvider is not initialized')
+ throw new Error("ethereumProvider is not initialized")
}
await ethereumProvider.value.disconnect()
_resetApp()
@@ -95,14 +99,14 @@ export default function useWalletConnectV2() {
function getWalletConnectSignerV2() {
if (!web3Provider.value) {
- throw new Error('Web3Provider is not initialized')
+ throw new Error("Web3Provider is not initialized")
}
return web3Provider.value.getSigner()
}
async function initializeWalletConnect() {
if (componentIsMounted.value) return
- if (import.meta.env.MODE === 'development') console.log('initializing wallet connect')
+ if (import.meta.env.MODE === "development") console.log("initializing wallet connect")
componentIsMounted.value = true
// Check for persisted sessions & Subscribe to provider events
@@ -119,30 +123,30 @@ export default function useWalletConnectV2() {
async function loginWithWalletConnectV2(loginCredentials: LoginCredentials) {
const { provider, address, currency } = loginCredentials
try {
- const message = await createSiweMessage(address, 'Sign in with Ethereum to the Casimir.')
+ const message = await createSiweMessage(address, "Sign in with Ethereum to the Casimir.")
const signedMessage = await signWalletConnectMessage(message)
await signInWithEthereum({
address,
- currency: currency || 'ETH',
+ currency: currency || "ETH",
provider,
message,
signedMessage
})
} catch (err) {
- console.log('error in loginWithWalletConnect :>> ', err)
+ console.log("error in loginWithWalletConnect :>> ", err)
}
}
- async function signWalletConnectMessage(message: string) : Promise{
+ async function signWalletConnectMessage(message: string) : Promise {
try {
- console.log('got to signWalletConnectMessage')
- console.log('message :>> ', message)
+ console.log("got to signWalletConnectMessage")
+ console.log("message :>> ", message)
const signer = await web3Provider.value?.getSigner()
return await signer?.signMessage(message) as string
- } catch(err) {
- console.error('error in signWalletConnectMessage :>> ', err)
+ } catch (err) {
+ console.error("error in signWalletConnectMessage :>> ", err)
throw err
- return ''
+ return ""
}
}
@@ -154,28 +158,28 @@ export default function useWalletConnectV2() {
async function _checkForPersistedSession() {
if (ethereumProvider.value?.session) {
- const _session = ethereumProvider.value?.session
- console.log('RESTORED SESSION:', _session)
- await _onSessionConnected(_session)
- return _session
+ const _session = ethereumProvider.value?.session
+ console.log("RESTORED SESSION:", _session)
+ await _onSessionConnected(_session)
+ return _session
}
}
async function _onSessionConnected(_session: SessionTypes.Struct) {
if (!ethereumProvider.value) {
- throw new ReferenceError('EthereumProvider is not initialized.')
+ throw new ReferenceError("EthereumProvider is not initialized.")
}
const allNamespaceAccounts = Object.values(_session.namespaces).map(namespace => namespace.accounts).flat()
const allNamespaceChains = Object.keys(_session.namespaces)
session.value = _session
- accounts.value = allNamespaceAccounts.map(account => account.split(':')[2])
- console.log('RESTORED', allNamespaceChains, allNamespaceAccounts)
+ accounts.value = allNamespaceAccounts.map(account => account.split(":")[2])
+ console.log("RESTORED", allNamespaceChains, allNamespaceAccounts)
createEthersProvider()
}
function _resetApp() {
- console.log('resetting app')
+ console.log("resetting app")
pairings.value = []
session.value = undefined
accounts.value = []
@@ -183,53 +187,53 @@ export default function useWalletConnectV2() {
function _subscribeToProviderEvents() {
if (!ethereumProvider.value) {
- throw new Error('WalletConnect is not initialized')
+ throw new Error("WalletConnect is not initialized")
}
// Event handler for display_uri
const handleDisplayUri = (uri: string) => {
- console.log('DISPLAY URI EVENT', 'QR Code Modal open')
+ console.log("DISPLAY URI EVENT", "QR Code Modal open")
web3Modal.value?.openModal({ uri })
}
// Event handler for session_ping
const handleSessionPing = ({ id, topic }: { id: number; topic: string }) => {
- console.log('SESSION PING EVENT', 'session_ping')
+ console.log("SESSION PING EVENT", "session_ping")
console.log(id, topic)
}
// Event handler for session_event
const handleSessionEvent = ({ event, chainId }: { event: any; chainId: string }) => {
- console.log('SESSION EVENT', 'session_event')
+ console.log("SESSION EVENT", "session_event")
console.log(event, chainId)
}
// Event handler for session_update
const handleSessionUpdate = ({ topic, _session }: { topic: string; _session: SessionTypes.Struct }) => {
- console.log('SESSION UPDATE EVENT', 'session_updated')
+ console.log("SESSION UPDATE EVENT", "session_updated")
session.value = _session
}
// Event handler for session_delete
const handleSessionDelete = ({ id, topic }: { id: number; topic: string }) => {
- console.log('DELETE SESSION EVENT', 'session_deleted')
+ console.log("DELETE SESSION EVENT", "session_deleted")
console.log(id, topic)
_resetApp()
}
// Attaching the event listeners
- ethereumProvider.value.on('display_uri', handleDisplayUri)
- ethereumProvider.value.on('session_ping', handleSessionPing)
- ethereumProvider.value.on('session_event', handleSessionEvent)
- ethereumProvider.value.on('session_update', handleSessionUpdate)
- ethereumProvider.value.on('session_delete', handleSessionDelete)
+ ethereumProvider.value.on("display_uri", handleDisplayUri)
+ ethereumProvider.value.on("session_ping", handleSessionPing)
+ ethereumProvider.value.on("session_event", handleSessionEvent)
+ ethereumProvider.value.on("session_update", handleSessionUpdate)
+ ethereumProvider.value.on("session_delete", handleSessionDelete)
// Storing cleanup functions
- cleanupFunctions.push(() => ethereumProvider.value.off('display_uri', handleDisplayUri))
- cleanupFunctions.push(() => ethereumProvider.value.off('session_ping', handleSessionPing))
- cleanupFunctions.push(() => ethereumProvider.value.off('session_event', handleSessionEvent))
- cleanupFunctions.push(() => ethereumProvider.value.off('session_update', handleSessionUpdate))
- cleanupFunctions.push(() => ethereumProvider.value.off('session_delete', handleSessionDelete))
+ cleanupFunctions.push(() => ethereumProvider.value.off("display_uri", handleDisplayUri))
+ cleanupFunctions.push(() => ethereumProvider.value.off("session_ping", handleSessionPing))
+ cleanupFunctions.push(() => ethereumProvider.value.off("session_event", handleSessionEvent))
+ cleanupFunctions.push(() => ethereumProvider.value.off("session_update", handleSessionUpdate))
+ cleanupFunctions.push(() => ethereumProvider.value.off("session_delete", handleSessionDelete))
}
return {
diff --git a/apps/web/src/composables/wallets.ts b/apps/web/src/composables/wallets.ts
index 4f166b21c..9bca725e7 100644
--- a/apps/web/src/composables/wallets.ts
+++ b/apps/web/src/composables/wallets.ts
@@ -1,93 +1,93 @@
-import { ref, readonly } from 'vue'
-import { ProviderString } from '@casimir/types'
-import useEthers from '@/composables/ethers'
+import { ref, readonly } from "vue"
+import { ProviderString } from "@casimir/types"
+import useEthers from "@/composables/ethers"
const installedWallets = ref([] as ProviderString[])
const { browserProvidersList, getBrowserProvider } = useEthers()
export default function useWallets() {
- async function detectActiveNetwork(providerString: ProviderString) {
- try {
- if (browserProvidersList.includes(providerString)) {
- const provider = getBrowserProvider(providerString)
- const chainId = parseInt(await provider.request({ method: 'eth_chainId' }), 16)
- return chainId
- } else if (providerString === 'WalletConnect') {
- const provider = getBrowserProvider(providerString)
- const chainId = parseInt(await provider.request({ method: 'eth_chainId' }), 16)
- return chainId
- } else if (providerString === 'Ledger') {
- // TODO: Implement Ledger
- alert('detectActiveNetwork not yet implemented')
- return '0'
- } else if (providerString === 'Trezor') {
- // TODO: Implement Trezor
- alert('detectActiveNetwork not yet implemented')
- return '0'
- }
- } catch (err) {
- console.log('Error in detectActiveNetwork: ', err)
- }
+ async function detectActiveNetwork(providerString: ProviderString) {
+ try {
+ if (browserProvidersList.includes(providerString)) {
+ const provider = getBrowserProvider(providerString)
+ const chainId = parseInt(await provider.request({ method: "eth_chainId" }), 16)
+ return chainId
+ } else if (providerString === "WalletConnect") {
+ const provider = getBrowserProvider(providerString)
+ const chainId = parseInt(await provider.request({ method: "eth_chainId" }), 16)
+ return chainId
+ } else if (providerString === "Ledger") {
+ // TODO: Implement Ledger
+ alert("detectActiveNetwork not yet implemented")
+ return "0"
+ } else if (providerString === "Trezor") {
+ // TODO: Implement Trezor
+ alert("detectActiveNetwork not yet implemented")
+ return "0"
}
+ } catch (err) {
+ console.log("Error in detectActiveNetwork: ", err)
+ }
+ }
- async function detectInstalledWalletProviders() {
- const ethereum = (window as any).ethereum
- if (ethereum) {
- // MetaMask, CoinbaseWallet, TrustWallet
- if (ethereum.providers) {
- // Iterate over ethereum.providers and check if MetaMask, CoinbaseWallet, TrustWallet
- for (const provider of ethereum.providers) {
- // Check if MetaMask
- if (provider.isMetaMask) installedWallets.value.push('MetaMask')
- // Check if CoinbaseWallet
- if (provider.isCoinbaseWallet) installedWallets.value.push('CoinbaseWallet')
- // Check if TrustWallet
- if (provider.isTrust) installedWallets.value.push('TrustWallet')
- }
- } else if(ethereum.providerMap) { // This will not show Trust Wallet even if it is installed
- // MetaMask & CoinbaseWallet
- // Check if MetaMask
- const isMetaMask = ethereum.providerMap.has('MetaMask')
- if (isMetaMask) installedWallets.value.push('MetaMask')
- // Check if CoinbaseWallet
- const isCoinbaseWallet = ethereum.providerMap.has('CoinbaseWallet')
- if (isCoinbaseWallet) installedWallets.value.push('CoinbaseWallet')
- } else if (ethereum.isMetaMask) installedWallets.value.push('MetaMask') // Just MetaMask
- else if (ethereum.isCoinbaseWallet) installedWallets.value.push('CoinbaseWallet') // Just CoinbaseWallet
- else if (ethereum.isTrust) installedWallets.value.push('TrustWallet') // Just TrustWallet
- // console.log('installedWallets.value :>> ', installedWallets.value)
- } else {
- console.log('No ethereum browser provider found')
+ async function detectInstalledWalletProviders() {
+ const ethereum = (window as any).ethereum
+ if (ethereum) {
+ // MetaMask, CoinbaseWallet, TrustWallet
+ if (ethereum.providers) {
+ // Iterate over ethereum.providers and check if MetaMask, CoinbaseWallet, TrustWallet
+ for (const provider of ethereum.providers) {
+ // Check if MetaMask
+ if (provider.isMetaMask) installedWallets.value.push("MetaMask")
+ // Check if CoinbaseWallet
+ if (provider.isCoinbaseWallet) installedWallets.value.push("CoinbaseWallet")
+ // Check if TrustWallet
+ if (provider.isTrust) installedWallets.value.push("TrustWallet")
}
+ } else if (ethereum.providerMap) { // This will not show Trust Wallet even if it is installed
+ // MetaMask & CoinbaseWallet
+ // Check if MetaMask
+ const isMetaMask = ethereum.providerMap.has("MetaMask")
+ if (isMetaMask) installedWallets.value.push("MetaMask")
+ // Check if CoinbaseWallet
+ const isCoinbaseWallet = ethereum.providerMap.has("CoinbaseWallet")
+ if (isCoinbaseWallet) installedWallets.value.push("CoinbaseWallet")
+ } else if (ethereum.isMetaMask) installedWallets.value.push("MetaMask") // Just MetaMask
+ else if (ethereum.isCoinbaseWallet) installedWallets.value.push("CoinbaseWallet") // Just CoinbaseWallet
+ else if (ethereum.isTrust) installedWallets.value.push("TrustWallet") // Just TrustWallet
+ // console.log('installedWallets.value :>> ', installedWallets.value)
+ } else {
+ console.log("No ethereum browser provider found")
}
+ }
- async function switchEthersNetwork (providerString: ProviderString, chainId: string) {
- const provider = getBrowserProvider(providerString)
- try {
- await provider.request({
- method:'wallet_switchEthereumChain',
- params: [{ chainId }]
- })
- } catch (err: any) {
- console.log(`Error occurred while switching chain to chainId ${chainId}, err: ${err.message} code: ${err.code}`)
- // if (err.code === 4902){
- // if (chainId === '5') {
- // addEthersNetwork(providerString, goerliNetwork)
- // } else if (chainId === '0x1252') {
- // addEthersNetwork(providerString, iotexNetwork)
- // }
- // }
- }
+ async function switchEthersNetwork (providerString: ProviderString, chainId: string) {
+ const provider = getBrowserProvider(providerString)
+ try {
+ await provider.request({
+ method:"wallet_switchEthereumChain",
+ params: [{ chainId }]
+ })
+ } catch (err: any) {
+ console.log(`Error occurred while switching chain to chainId ${chainId}, err: ${err.message} code: ${err.code}`)
+ // if (err.code === 4902){
+ // if (chainId === '5') {
+ // addEthersNetwork(providerString, goerliNetwork)
+ // } else if (chainId === '0x1252') {
+ // addEthersNetwork(providerString, iotexNetwork)
+ // }
+ // }
}
+ }
- return {
- installedWallets: readonly(installedWallets),
- detectActiveNetwork,
- detectInstalledWalletProviders,
- switchEthersNetwork
- }
+ return {
+ installedWallets: readonly(installedWallets),
+ detectActiveNetwork,
+ detectInstalledWalletProviders,
+ switchEthersNetwork
+ }
}
// async function addEthersNetwork (providerString: ProviderString, network: any) {
diff --git a/apps/web/src/env.d.ts b/apps/web/src/env.d.ts
index 30672d3d9..0555309d4 100644
--- a/apps/web/src/env.d.ts
+++ b/apps/web/src/env.d.ts
@@ -1,8 +1,8 @@
///
///
-declare module '*.vue' {
- import type { DefineComponent } from 'vue'
+declare module "*.vue" {
+ import type { DefineComponent } from "vue"
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
diff --git a/apps/web/src/layouts/default-layout.vue b/apps/web/src/layouts/default-layout.vue
index 758fe2444..958b2ad6f 100644
--- a/apps/web/src/layouts/default-layout.vue
+++ b/apps/web/src/layouts/default-layout.vue
@@ -1,13 +1,13 @@
diff --git a/apps/web/src/pages/overview/components/BreakdownChart.vue b/apps/web/src/pages/overview/components/BreakdownChart.vue
index b7aa34bde..d50fdd537 100644
--- a/apps/web/src/pages/overview/components/BreakdownChart.vue
+++ b/apps/web/src/pages/overview/components/BreakdownChart.vue
@@ -1,40 +1,40 @@
diff --git a/apps/web/src/pages/overview/components/StakingAvg.vue b/apps/web/src/pages/overview/components/StakingAvg.vue
index 6fc48d900..8223ad22f 100644
--- a/apps/web/src/pages/overview/components/StakingAvg.vue
+++ b/apps/web/src/pages/overview/components/StakingAvg.vue
@@ -1,26 +1,26 @@
diff --git a/apps/web/src/sessions.config.ts b/apps/web/src/sessions.config.ts
index b1736d25c..497a2660e 100644
--- a/apps/web/src/sessions.config.ts
+++ b/apps/web/src/sessions.config.ts
@@ -1,13 +1,13 @@
-import Session from 'supertokens-web-js/recipe/session'
-import useEnvironment from '@/composables/environment'
+import Session from "supertokens-web-js/recipe/session"
+import useEnvironment from "@/composables/environment"
const { usersUrl } = useEnvironment()
export const SuperTokensWebJSConfig = {
appInfo: {
- apiDomain: usersUrl,
- appName: 'Casimir',
- // apiBasePath: '/',
+ apiDomain: usersUrl,
+ appName: "Casimir",
+ // apiBasePath: '/',
},
recipeList: [Session.init()],
}
\ No newline at end of file
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts
index ae7da0285..f4a6be976 100644
--- a/apps/web/vite.config.ts
+++ b/apps/web/vite.config.ts
@@ -1,9 +1,9 @@
-import vue from '@vitejs/plugin-vue'
-import { defineConfig } from 'vite'
-import { fileURLToPath } from 'url'
-import * as path from 'path'
-import nodePolyfills from 'rollup-plugin-polyfill-node'
-import nodeResolve from '@rollup/plugin-node-resolve'
+import vue from "@vitejs/plugin-vue"
+import { defineConfig } from "vite"
+import { fileURLToPath } from "url"
+import * as path from "path"
+import nodePolyfills from "rollup-plugin-polyfill-node"
+import nodeResolve from "@rollup/plugin-node-resolve"
export default defineConfig({
server: { port: 3001 },
@@ -13,22 +13,22 @@ export default defineConfig({
nodeResolve()
],
define: {
- 'global': 'globalThis'
+ "global": "globalThis"
},
resolve: {
alias: {
- '@': path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'src'),
- './runtimeConfig': './runtimeConfig.browser'
+ "@": path.resolve(path.dirname(fileURLToPath(import.meta.url)), "src"),
+ "./runtimeConfig": "./runtimeConfig.browser"
},
extensions: [
- '.js',
- '.json',
- '.jsx',
- '.mjs',
- '.ts',
- '.tsx',
- '.vue',
+ ".js",
+ ".json",
+ ".jsx",
+ ".mjs",
+ ".ts",
+ ".tsx",
+ ".vue",
]
},
- envPrefix: 'PUBLIC_'
+ envPrefix: "PUBLIC_"
})
\ No newline at end of file
diff --git a/common/aws/src/index.ts b/common/aws/src/index.ts
index 3d3e6188e..0e9f1721a 100644
--- a/common/aws/src/index.ts
+++ b/common/aws/src/index.ts
@@ -1,5 +1,5 @@
-import { fromIni } from '@aws-sdk/credential-providers'
-import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager'
+import { fromIni } from "@aws-sdk/credential-providers"
+import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager"
/**
* Gets a secret from AWS Secrets Manager.
@@ -7,18 +7,18 @@ import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-sec
* @returns secret string
*/
export async function getSecret(id: string) {
- const aws = new SecretsManagerClient({})
- const { SecretString } = await aws.send(
- new GetSecretValueCommand(
- {
- SecretId: id
- }
- )
+ const aws = new SecretsManagerClient({})
+ const { SecretString } = await aws.send(
+ new GetSecretValueCommand(
+ {
+ SecretId: id
+ }
)
- if (!SecretString) {
- throw new Error(`No secret found for ${id}`)
- }
- return SecretString
+ )
+ if (!SecretString) {
+ throw new Error(`No secret found for ${id}`)
+ }
+ return SecretString
}
/**
@@ -28,13 +28,13 @@ export async function getSecret(id: string) {
* @returns AWS credentials
*/
export async function loadCredentials() {
- const defaultProfile = 'consensus-networks-dev'
- if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY) {
- process.env.AWS_PROFILE = process.env.AWS_PROFILE || defaultProfile
- return await fromIni()()
- }
- return {
- accessKeyId: process.env.AWS_ACCESS_KEY_ID,
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
- }
+ const defaultProfile = "consensus-networks-dev"
+ if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY) {
+ process.env.AWS_PROFILE = process.env.AWS_PROFILE || defaultProfile
+ return await fromIni()()
+ }
+ return {
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
+ }
}
\ No newline at end of file
diff --git a/common/data/src/index.ts b/common/data/src/index.ts
index 46da978d9..e897722bb 100644
--- a/common/data/src/index.ts
+++ b/common/data/src/index.ts
@@ -1,24 +1,24 @@
-import accountSchema from './schemas/account.schema.json'
-import actionSchema from './schemas/action.schema.json'
-import eventSchema from './schemas/event.schema.json'
-import nonceSchema from './schemas/nonce.schema.json'
-import operatorSchema from './schemas/operator.schema.json'
-import userAccountSchema from './schemas/user_account.schema.json'
-import userSchema from './schemas/user.schema.json'
-import { Postgres } from '../../../services/users/src/providers/postgres'
-import { JsonType, GlueType, PostgresType, Schema } from './providers/schema'
-import { JsonSchema } from './interfaces/JsonSchema'
+import accountSchema from "./schemas/account.schema.json"
+import actionSchema from "./schemas/action.schema.json"
+import eventSchema from "./schemas/event.schema.json"
+import nonceSchema from "./schemas/nonce.schema.json"
+import operatorSchema from "./schemas/operator.schema.json"
+import userAccountSchema from "./schemas/user_account.schema.json"
+import userSchema from "./schemas/user.schema.json"
+import { Postgres } from "../../../services/users/src/providers/postgres"
+import { JsonType, GlueType, PostgresType, Schema } from "./providers/schema"
+import { JsonSchema } from "./interfaces/JsonSchema"
export {
- accountSchema,
- actionSchema,
- eventSchema,
- nonceSchema,
- operatorSchema,
- userAccountSchema,
- userSchema,
- Postgres,
- Schema
+ accountSchema,
+ actionSchema,
+ eventSchema,
+ nonceSchema,
+ operatorSchema,
+ userAccountSchema,
+ userSchema,
+ Postgres,
+ Schema
}
export type { JsonSchema, JsonType, GlueType, PostgresType }
\ No newline at end of file
diff --git a/common/data/src/providers/schema.ts b/common/data/src/providers/schema.ts
index e2667143c..e5a7d3cbd 100644
--- a/common/data/src/providers/schema.ts
+++ b/common/data/src/providers/schema.ts
@@ -1,16 +1,16 @@
-import * as glue from '@aws-cdk/aws-glue-alpha'
-import { JsonSchema } from '../interfaces/JsonSchema'
-import { snakeCase } from '@casimir/format'
+import * as glue from "@aws-cdk/aws-glue-alpha"
+import { JsonSchema } from "../interfaces/JsonSchema"
+import { snakeCase } from "@casimir/format"
-export type JsonType = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null'
+export type JsonType = "string" | "number" | "integer" | "boolean" | "object" | "array" | "null"
export type GlueType = glue.Type
-export type PostgresType = 'STRING' | 'INTEGER' | 'BOOLEAN' | 'DOUBLE' | 'DECIMAL' | 'BIGINT' | 'TIMESTAMP' | 'JSON' | 'DATE'
+export type PostgresType = "STRING" | "INTEGER" | "BOOLEAN" | "DOUBLE" | "DECIMAL" | "BIGINT" | "TIMESTAMP" | "JSON" | "DATE"
export class Schema {
- /** Input JSON schema object */
- private jsonSchema: JsonSchema
+ /** Input JSON schema object */
+ private jsonSchema: JsonSchema
- /**
+ /**
* @param jsonSchema {JsonSchema} - Input JSON schema object
* @example
* ```typescript
@@ -18,11 +18,11 @@ export class Schema {
* const schema = new Schema(eventSchema)
* ```
*/
- constructor(jsonSchema: JsonSchema) {
- this.jsonSchema = jsonSchema
- }
+ constructor(jsonSchema: JsonSchema) {
+ this.jsonSchema = jsonSchema
+ }
- /**
+ /**
* Get an array of Glue columns from the JSON schema object.
* @returns {glue.Column[]} Array of Glue columns
*
@@ -32,26 +32,26 @@ export class Schema {
* const columns = schema.getGlueColumns()
* ```
*/
- getGlueColumns(): glue.Column[] {
- return Object.keys(this.jsonSchema.properties).map((name: string) => {
- const property = this.jsonSchema.properties[name]
+ getGlueColumns(): glue.Column[] {
+ return Object.keys(this.jsonSchema.properties).map((name: string) => {
+ const property = this.jsonSchema.properties[name]
- // 'STRING' | 'INTEGER' | 'BOOLEAN' | 'DOUBLE' | 'DECIMAL' | 'BIG_INT' | 'TIMESTAMP' | 'JSON' | 'DATE'
- const typeKey = property.type.toUpperCase() as keyof glue.Schema
+ // 'STRING' | 'INTEGER' | 'BOOLEAN' | 'DOUBLE' | 'DECIMAL' | 'BIG_INT' | 'TIMESTAMP' | 'JSON' | 'DATE'
+ const typeKey = property.type.toUpperCase() as keyof glue.Schema
- let type: GlueType = glue.Schema[typeKey]
+ let type: GlueType = glue.Schema[typeKey]
- if (name.endsWith('_at')) type = glue.Schema.TIMESTAMP
- if (name.endsWith('_balance')) type = glue.Schema.BIG_INT
- if (name == 'amount') type = glue.Schema.BIG_INT
- if (name === 'price') type = glue.Schema.FLOAT
+ if (name.endsWith("_at")) type = glue.Schema.TIMESTAMP
+ if (name.endsWith("_balance")) type = glue.Schema.BIG_INT
+ if (name == "amount") type = glue.Schema.BIG_INT
+ if (name === "price") type = glue.Schema.FLOAT
- const comment = property.description
- return { name, type, comment }
- })
- }
+ const comment = property.description
+ return { name, type, comment }
+ })
+ }
- /**
+ /**
* Get a Postgres table from the JSON schema object.
* @returns {string} Postgres table
*
@@ -61,50 +61,50 @@ export class Schema {
* const table = schema.getPostgresTable()
* ```
*/
- getPostgresTable(): string {
- const compositeKey = this.jsonSchema.composite_key
- const uniqueFields = this.jsonSchema.uniqueFields || []
- const columns = Object.keys(this.jsonSchema.properties).map((name: string) => {
- const property = this.jsonSchema.properties[name]
- let type = {
- string: 'VARCHAR',
- number: 'DOUBLE',
- integer: 'INTEGER',
- boolean: 'BOOLEAN',
- object: 'JSON',
- array: 'JSON',
- null: 'VARCHAR',
- serial: 'SERIAL'
- }[property.type as JsonType] as PostgresType
-
- if (name.endsWith('_at')) type = 'TIMESTAMP'
- if (name.includes('balance')) type = 'BIGINT'
-
- let column = `${name} ${type}`
-
- const comment = property.description
- if (comment.includes('PK')) column += ' PRIMARY KEY'
+ getPostgresTable(): string {
+ const compositeKey = this.jsonSchema.composite_key
+ const uniqueFields = this.jsonSchema.uniqueFields || []
+ const columns = Object.keys(this.jsonSchema.properties).map((name: string) => {
+ const property = this.jsonSchema.properties[name]
+ let type = {
+ string: "VARCHAR",
+ number: "DOUBLE",
+ integer: "INTEGER",
+ boolean: "BOOLEAN",
+ object: "JSON",
+ array: "JSON",
+ null: "VARCHAR",
+ serial: "SERIAL"
+ }[property.type as JsonType] as PostgresType
+
+ if (name.endsWith("_at")) type = "TIMESTAMP"
+ if (name.includes("balance")) type = "BIGINT"
+
+ let column = `${name} ${type}`
+
+ const comment = property.description
+ if (comment.includes("PK")) column += " PRIMARY KEY"
- const defaultValue = property.default
- if (defaultValue !== undefined) column += ` DEFAULT ${defaultValue}`
+ const defaultValue = property.default
+ if (defaultValue !== undefined) column += ` DEFAULT ${defaultValue}`
- return column
- })
+ return column
+ })
- /** Check for composite key property and add the primary key if so */
- if (compositeKey) columns.push(`PRIMARY KEY (${compositeKey})`)
+ /** Check for composite key property and add the primary key if so */
+ if (compositeKey) columns.push(`PRIMARY KEY (${compositeKey})`)
- /** Make table name plural of schema objects (todo: check edge-cases) */
- const tableName = this.getTitle()
+ /** Make table name plural of schema objects (todo: check edge-cases) */
+ const tableName = this.getTitle()
- const queryString = uniqueFields.length > 0 ? `CREATE TABLE ${tableName} (\n\t${columns.join(',\n\t')}, \n\tUNIQUE (${uniqueFields.join(', ')}));` : `CREATE TABLE ${tableName} (\n\t${columns.join(',\n\t')}\n);`
- return queryString
- }
+ const queryString = uniqueFields.length > 0 ? `CREATE TABLE ${tableName} (\n\t${columns.join(",\n\t")}, \n\tUNIQUE (${uniqueFields.join(", ")}));` : `CREATE TABLE ${tableName} (\n\t${columns.join(",\n\t")}\n);`
+ return queryString
+ }
- /**
+ /**
* Get the title of the JSON schema object.
*/
- getTitle(): string {
- return snakeCase(this.jsonSchema.title) + 's'
- }
+ getTitle(): string {
+ return snakeCase(this.jsonSchema.title) + "s"
+ }
}
\ No newline at end of file
diff --git a/common/env/src/index.ts b/common/env/src/index.ts
index 26efc4904..c281577ea 100644
--- a/common/env/src/index.ts
+++ b/common/env/src/index.ts
@@ -1,6 +1,6 @@
-import MOCK_OPERATORS from './mock/operators.json'
-import MOCK_RESHARES from './mock/reshares.json'
-import MOCK_VALIDATORS from './mock/validators.json'
+import MOCK_OPERATORS from "./mock/operators.json"
+import MOCK_RESHARES from "./mock/reshares.json"
+import MOCK_VALIDATORS from "./mock/validators.json"
// Default CasimirManager contract deployed to 0xA279b2cD2fe7f71f3dD77deF9dedC114bBC0a68c
// Default CasimirRegistry contract deployed to 0x2c6E6453c0AA873E81a9CFcFa2206E1b9E6C21e0
@@ -8,62 +8,62 @@ import MOCK_VALIDATORS from './mock/validators.json'
// Default CasimirViews contract deployed to 0x394042CBB8bF5444766496897982A5CDd01d5099
const ETHEREUM_CONTRACTS = {
- TESTNET: {
- BEACON_LIBRARY_ADDRESS: '0x0295bfe577d6833882Ee0E1Bccc4a5825d1Df653',
- MANAGER_BEACON_ADDRESS: '0x69D830C11bbD81c0A9AC031d17A2599D3a0F632E',
- POOL_BEACON_ADDRESS: '0x9Ef6fb4fe7F7EB9DDeB019028E978439b9aD72BF',
- REGISTRY_BEACON_ADDRESS: '0xC0799f7643978828cEBCe4F327dcA233dE1871C8',
- UPKEEP_BEACON_ADDRESS: '0x0CCA5B647598e86fc0518A462f2e61C58Dc6F5ac',
- VIEWS_BEACON_ADDRESS: '0x7B07be561eA274a78D9dC30FCFAcEeb2C6Ac3962',
- FACTORY_ADDRESS: '0xA6fd22c5633bCD82Ee25045de91351a8dfA2c76F',
+ TESTNET: {
+ BEACON_LIBRARY_ADDRESS: "0x0295bfe577d6833882Ee0E1Bccc4a5825d1Df653",
+ MANAGER_BEACON_ADDRESS: "0x69D830C11bbD81c0A9AC031d17A2599D3a0F632E",
+ POOL_BEACON_ADDRESS: "0x9Ef6fb4fe7F7EB9DDeB019028E978439b9aD72BF",
+ REGISTRY_BEACON_ADDRESS: "0xC0799f7643978828cEBCe4F327dcA233dE1871C8",
+ UPKEEP_BEACON_ADDRESS: "0x0CCA5B647598e86fc0518A462f2e61C58Dc6F5ac",
+ VIEWS_BEACON_ADDRESS: "0x7B07be561eA274a78D9dC30FCFAcEeb2C6Ac3962",
+ FACTORY_ADDRESS: "0xA6fd22c5633bCD82Ee25045de91351a8dfA2c76F",
- FUNCTIONS_BILLING_REGISTRY_ADDRESS: '0x566087488869A18767cBA3Adb19dfc713FE56Ac6',
- FUNCTIONS_ORACLE_ADDRESS: '0x914F29Ddb0b8A8201a58e6eeaf71d6df36429214',
- FUNCTIONS_ORACLE_FACTORY_ADDRESS: '0x1304Dc23DD83f5c374193839E880cCa5D040f5A7',
+ FUNCTIONS_BILLING_REGISTRY_ADDRESS: "0x566087488869A18767cBA3Adb19dfc713FE56Ac6",
+ FUNCTIONS_ORACLE_ADDRESS: "0x914F29Ddb0b8A8201a58e6eeaf71d6df36429214",
+ FUNCTIONS_ORACLE_FACTORY_ADDRESS: "0x1304Dc23DD83f5c374193839E880cCa5D040f5A7",
- DEPOSIT_CONTRACT_ADDRESS: '0xff50ed3d0ec03aC01D4C79aAd74928BFF48a7b2b',
- KEEPER_REGISTRAR_ADDRESS: '0x57A4a13b35d25EE78e084168aBaC5ad360252467',
- KEEPER_REGISTRY_ADDRESS: '0xE16Df59B887e3Caa439E0b29B42bA2e7976FD8b2',
- LINK_ETH_FEED_ADDRESS: '0xb4c4a493AB6356497713A78FFA6c60FB53517c63',
- LINK_TOKEN_ADDRESS: '0x326C977E6efc84E512bB9C30f76E30c160eD06FB',
- SSV_NETWORK_ADDRESS: '0xC3CD9A0aE89Fff83b71b58b6512D43F8a41f363D',
- SSV_TOKEN_ADDRESS: '0x3a9f01091C446bdE031E39ea8354647AFef091E7',
- SSV_VIEWS_ADDRESS: '0xAE2C84c48272F5a1746150ef333D5E5B51F68763',
- SWAP_FACTORY_ADDRESS: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
- SWAP_ROUTER_ADDRESS: '0xE592427A0AEce92De3Edee1F18E0157C05861564',
- WETH_TOKEN_ADDRESS: '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6'
- }
+ DEPOSIT_CONTRACT_ADDRESS: "0xff50ed3d0ec03aC01D4C79aAd74928BFF48a7b2b",
+ KEEPER_REGISTRAR_ADDRESS: "0x57A4a13b35d25EE78e084168aBaC5ad360252467",
+ KEEPER_REGISTRY_ADDRESS: "0xE16Df59B887e3Caa439E0b29B42bA2e7976FD8b2",
+ LINK_ETH_FEED_ADDRESS: "0xb4c4a493AB6356497713A78FFA6c60FB53517c63",
+ LINK_TOKEN_ADDRESS: "0x326C977E6efc84E512bB9C30f76E30c160eD06FB",
+ SSV_NETWORK_ADDRESS: "0xC3CD9A0aE89Fff83b71b58b6512D43F8a41f363D",
+ SSV_TOKEN_ADDRESS: "0x3a9f01091C446bdE031E39ea8354647AFef091E7",
+ SSV_VIEWS_ADDRESS: "0xAE2C84c48272F5a1746150ef333D5E5B51F68763",
+ SWAP_FACTORY_ADDRESS: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
+ SWAP_ROUTER_ADDRESS: "0xE592427A0AEce92De3Edee1F18E0157C05861564",
+ WETH_TOKEN_ADDRESS: "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
+ }
}
enum ETHEREUM_NETWORK_NAME {
- TESTNET = 'goerli'
+ TESTNET = "goerli"
}
enum ETHEREUM_RPC_URL {
- TESTNET = 'https://goerli.infura.io/v3/46a379ac6895489f812f33beb726b03b' // 'https://nodes.casimir.co/eth/goerli/limited'
+ TESTNET = "https://goerli.infura.io/v3/46a379ac6895489f812f33beb726b03b" // 'https://nodes.casimir.co/eth/goerli/limited'
}
const ETHEREUM_SIGNERS = {
- TESTNET: {
- DAO_ORACLE_ADDRESS: '0x728474D29c2F81eb17a669a7582A2C17f1042b57',
- DON_TRANSMITTER_ADDRESS: '0x84725c8f954f18709aDcA150a0635D2fBE94fDfF',
- OWNER_ADDRESS: '0xd557a5745d4560B24D36A68b52351ffF9c86A212'
- }
+ TESTNET: {
+ DAO_ORACLE_ADDRESS: "0x728474D29c2F81eb17a669a7582A2C17f1042b57",
+ DON_TRANSMITTER_ADDRESS: "0x84725c8f954f18709aDcA150a0635D2fBE94fDfF",
+ OWNER_ADDRESS: "0xd557a5745d4560B24D36A68b52351ffF9c86A212"
+ }
}
enum HARDHAT_NETWORK_KEY {
- GOERLI = 'TESTNET',
- HARDHAT = 'TESTNET',
- LOCALHOST = 'TESTNET'
+ GOERLI = "TESTNET",
+ HARDHAT = "TESTNET",
+ LOCALHOST = "TESTNET"
}
export {
- ETHEREUM_CONTRACTS,
- ETHEREUM_NETWORK_NAME,
- ETHEREUM_RPC_URL,
- ETHEREUM_SIGNERS,
- HARDHAT_NETWORK_KEY,
- MOCK_OPERATORS,
- MOCK_RESHARES,
- MOCK_VALIDATORS
+ ETHEREUM_CONTRACTS,
+ ETHEREUM_NETWORK_NAME,
+ ETHEREUM_RPC_URL,
+ ETHEREUM_SIGNERS,
+ HARDHAT_NETWORK_KEY,
+ MOCK_OPERATORS,
+ MOCK_RESHARES,
+ MOCK_VALIDATORS
}
diff --git a/common/events/src/index.ts b/common/events/src/index.ts
index d44673003..50d5fe6a6 100644
--- a/common/events/src/index.ts
+++ b/common/events/src/index.ts
@@ -1,4 +1,4 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export function getEventsIterable(input: {
contractFilters: {
@@ -10,52 +10,52 @@ export function getEventsIterable(input: {
provider?: ethers.providers.JsonRpcProvider;
startBlock?: number;
}) {
- const provider = input.provider || new ethers.providers.JsonRpcProvider(input.ethereumUrl)
- return (async function* () {
- const queue: ethers.Event[] = []
- const enqueueEvent = (...args: ethers.Event[]) => {
+ const provider = input.provider || new ethers.providers.JsonRpcProvider(input.ethereumUrl)
+ return (async function* () {
+ const queue: ethers.Event[] = []
+ const enqueueEvent = (...args: ethers.Event[]) => {
+ const e = args[args.length - 1] as ethers.Event
+ queue.push(e)
+ }
+ const latestBlock = await provider.getBlockNumber()
+ for (const filter of input.contractFilters) {
+ for (const address of filter.addresses) {
+ for (const event of filter.events) {
+ const contract = new ethers.Contract(address, filter.abi, provider) as ethers.Contract
+ const tempQueue: ethers.Event[] = []
+ const tempListener = (...args: ethers.Event[]) => {
const e = args[args.length - 1] as ethers.Event
- queue.push(e)
- }
- const latestBlock = await provider.getBlockNumber()
- for (const filter of input.contractFilters) {
- for (const address of filter.addresses) {
- for (const event of filter.events) {
- const contract = new ethers.Contract(address, filter.abi, provider) as ethers.Contract
- const tempQueue: ethers.Event[] = []
- const tempListener = (...args: ethers.Event[]) => {
- const e = args[args.length - 1] as ethers.Event
- if (e.blockNumber > latestBlock) {
- tempQueue.push(e)
- }
- }
- contract.on(event, tempListener)
- if (input.startBlock) {
- const historicalEvents = await contract.queryFilter(event, input.startBlock, latestBlock)
- for (const historicalEvent of historicalEvents) {
- enqueueEvent(historicalEvent)
- }
- }
- contract.off(event, tempListener)
- while (tempQueue.length) {
- const nextTempEvent = tempQueue.shift()
- if (nextTempEvent) {
- enqueueEvent(nextTempEvent)
- }
- }
- contract.on(event, enqueueEvent)
- }
+ if (e.blockNumber > latestBlock) {
+ tempQueue.push(e)
}
- }
- while (true) {
- if (queue.length > 0) {
- const nextEvent = queue.shift()
- if (nextEvent) {
- yield nextEvent
- }
- } else {
- await new Promise((resolve) => setTimeout(resolve, 1000))
+ }
+ contract.on(event, tempListener)
+ if (input.startBlock) {
+ const historicalEvents = await contract.queryFilter(event, input.startBlock, latestBlock)
+ for (const historicalEvent of historicalEvents) {
+ enqueueEvent(historicalEvent)
}
+ }
+ contract.off(event, tempListener)
+ while (tempQueue.length) {
+ const nextTempEvent = tempQueue.shift()
+ if (nextTempEvent) {
+ enqueueEvent(nextTempEvent)
+ }
+ }
+ contract.on(event, enqueueEvent)
+ }
+ }
+ }
+ while (true) {
+ if (queue.length > 0) {
+ const nextEvent = queue.shift()
+ if (nextEvent) {
+ yield nextEvent
}
- })()
+ } else {
+ await new Promise((resolve) => setTimeout(resolve, 1000))
+ }
+ }
+ })()
}
diff --git a/common/fetch/src/index.ts b/common/fetch/src/index.ts
index 2b3acd879..778ff55ec 100644
--- a/common/fetch/src/index.ts
+++ b/common/fetch/src/index.ts
@@ -8,21 +8,21 @@
* const response = await fetchRetry('https://example.com')
*/
export async function fetchRetry(info: RequestInfo, init?: RequestInit, retriesLeft: number | undefined = 25): Promise {
- if (retriesLeft === 0) {
- throw new Error('API request failed after maximum retries')
- }
+ if (retriesLeft === 0) {
+ throw new Error("API request failed after maximum retries")
+ }
- try {
- const response = await fetch(info, init)
- if (response.status !== 200) {
- await new Promise(resolve => setTimeout(resolve, 5000))
- console.log('Retrying fetch request to', info, init)
- return await fetchRetry(info, init || {}, retriesLeft - 1)
- }
- return response
- } catch (error) {
- await new Promise(resolve => setTimeout(resolve, 5000))
- console.log('Retrying fetch request to', info, init)
- return await fetchRetry(info, init || {}, retriesLeft - 1)
+ try {
+ const response = await fetch(info, init)
+ if (response.status !== 200) {
+ await new Promise(resolve => setTimeout(resolve, 5000))
+ console.log("Retrying fetch request to", info, init)
+ return await fetchRetry(info, init || {}, retriesLeft - 1)
}
+ return response
+ } catch (error) {
+ await new Promise(resolve => setTimeout(resolve, 5000))
+ console.log("Retrying fetch request to", info, init)
+ return await fetchRetry(info, init || {}, retriesLeft - 1)
+ }
}
\ No newline at end of file
diff --git a/common/format/src/index.ts b/common/format/src/index.ts
index a4eed78b6..39df86fbd 100644
--- a/common/format/src/index.ts
+++ b/common/format/src/index.ts
@@ -4,13 +4,13 @@
* @returns A camelCase string from the input string
*/
export function camelCase(string: string): string {
- const words = string.split(/[\s_-]+/).map(word => {
- return word.replace(/\w+/g, (word) => {
- return word[0].toUpperCase() + word.slice(1).toLowerCase()
- })
+ const words = string.split(/[\s_-]+/).map(word => {
+ return word.replace(/\w+/g, (word) => {
+ return word[0].toUpperCase() + word.slice(1).toLowerCase()
})
- const result = words.join('')
- return result[0].toLowerCase() + result.slice(1)
+ })
+ const result = words.join("")
+ return result[0].toLowerCase() + result.slice(1)
}
/**
@@ -21,13 +21,13 @@ export function camelCase(string: string): string {
*
*/
export function pascalCase(string: string): string {
- const words = string.split(/[\s_-]+/).map(word => {
- return word.replace(/\w+/g, (word) => {
- return word[0].toUpperCase() + word.slice(1).toLowerCase()
- })
+ const words = string.split(/[\s_-]+/).map(word => {
+ return word.replace(/\w+/g, (word) => {
+ return word[0].toUpperCase() + word.slice(1).toLowerCase()
})
- const result = words.join('')
- return result
+ })
+ const result = words.join("")
+ return result
}
/**
@@ -36,10 +36,10 @@ export function pascalCase(string: string): string {
* @returns A snake_case string from the input string
*/
export function snakeCase(string: string): string {
- return string.replace(/\W+/g, ' ')
- .split(/ |\B(?=[A-Z])/)
- .map(word => word.toLowerCase())
- .join('_')
+ return string.replace(/\W+/g, " ")
+ .split(/ |\B(?=[A-Z])/)
+ .map(word => word.toLowerCase())
+ .join("_")
}
/**
@@ -48,8 +48,8 @@ export function snakeCase(string: string): string {
* @returns A kebab-case string from the input string
*/
export function kebabCase(string: string): string {
- return string.replace(/\W+/g, ' ')
- .split(/ |\B(?=[A-Z])/)
- .map(word => word.toLowerCase())
- .join('-')
+ return string.replace(/\W+/g, " ")
+ .split(/ |\B(?=[A-Z])/)
+ .map(word => word.toLowerCase())
+ .join("-")
}
\ No newline at end of file
diff --git a/common/logs/src/index.ts b/common/logs/src/index.ts
index 7a82c2068..763325d6c 100644
--- a/common/logs/src/index.ts
+++ b/common/logs/src/index.ts
@@ -1,19 +1,19 @@
-import fs from 'fs'
+import fs from "fs"
export function getStartBlock(blockLogPath: string) {
- if (fs.existsSync(blockLogPath)) {
- return parseInt(fs.readFileSync(blockLogPath, 'utf8'))
- }
+ if (fs.existsSync(blockLogPath)) {
+ return parseInt(fs.readFileSync(blockLogPath, "utf8"))
+ }
}
export function updateStartBlock(blockLogPath: string, blockNumber: number) {
- fs.writeFileSync(blockLogPath, blockNumber.toString())
+ fs.writeFileSync(blockLogPath, blockNumber.toString())
}
export function updateExecutionLog(executionLogPath: string, log: string) {
- fs.appendFileSync(executionLogPath, `${log}\n`)
+ fs.appendFileSync(executionLogPath, `${log}\n`)
}
export function updateErrorLog(errorLogPath: string, log: string) {
- fs.appendFileSync(errorLogPath, `${log}\n`)
+ fs.appendFileSync(errorLogPath, `${log}\n`)
}
\ No newline at end of file
diff --git a/common/shell/src/index.ts b/common/shell/src/index.ts
index 96818d2be..ae1849aca 100644
--- a/common/shell/src/index.ts
+++ b/common/shell/src/index.ts
@@ -1,4 +1,4 @@
-import { exec, execSync } from 'child_process'
+import { exec, execSync } from "child_process"
/**
* Run any shell command in a child process and return a promise
@@ -6,21 +6,21 @@ import { exec, execSync } from 'child_process'
* @returns A promise that resolves when the command exits
*/
export async function run(command: string) {
- const child = exec(command)
- let data = ''
- return new Promise((resolve, reject) => {
- child.on('error', reject)
- child.stdout?.on('data', chunk => {
- process.stdout.write(chunk.toString())
- data += chunk.toString()
- })
- child.stderr?.on('data', chunk => {
- process.stdout.write(chunk.toString())
- })
- child.on('exit', () => {
- resolve(data)
- })
+ const child = exec(command)
+ let data = ""
+ return new Promise((resolve, reject) => {
+ child.on("error", reject)
+ child.stdout?.on("data", chunk => {
+ process.stdout.write(chunk.toString())
+ data += chunk.toString()
})
+ child.stderr?.on("data", chunk => {
+ process.stdout.write(chunk.toString())
+ })
+ child.on("exit", () => {
+ resolve(data)
+ })
+ })
}
/**
@@ -30,16 +30,16 @@ export async function run(command: string) {
* @returns A promise that resolves when the command exits
*/
export async function runRetry(command: string, retriesLeft: number | undefined = 25): Promise {
- if (retriesLeft === 0) {
- throw new Error('Command failed after maximum retries')
- }
- try {
- return await run(command)
- } catch (error) {
- await new Promise(resolve => setTimeout(resolve, 5000))
- console.log('Retrying command', command)
- return await runRetry(command, retriesLeft - 1)
- }
+ if (retriesLeft === 0) {
+ throw new Error("Command failed after maximum retries")
+ }
+ try {
+ return await run(command)
+ } catch (error) {
+ await new Promise(resolve => setTimeout(resolve, 5000))
+ console.log("Retrying command", command)
+ return await runRetry(command, retriesLeft - 1)
+ }
}
/**
@@ -48,5 +48,5 @@ export async function runRetry(command: string, retriesLeft: number | undefined
* @returns The output of the command
*/
export function runSync(command: string) {
- return execSync(command).toString()
+ return execSync(command).toString()
}
\ No newline at end of file
diff --git a/common/ssv/src/index.ts b/common/ssv/src/index.ts
index ff3e8ba6c..0c990cb77 100644
--- a/common/ssv/src/index.ts
+++ b/common/ssv/src/index.ts
@@ -1,5 +1,5 @@
-import { Scanner } from './providers/scanner'
-import { Operator } from './interfaces/Operator'
+import { Scanner } from "./providers/scanner"
+import { Operator } from "./interfaces/Operator"
export { Scanner }
export type { Operator }
diff --git a/common/ssv/src/interfaces/Cluster.ts b/common/ssv/src/interfaces/Cluster.ts
index 011c669e6..1f8c45cf2 100644
--- a/common/ssv/src/interfaces/Cluster.ts
+++ b/common/ssv/src/interfaces/Cluster.ts
@@ -1,4 +1,4 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export interface Cluster {
validatorCount: number | ethers.BigNumber
diff --git a/common/ssv/src/interfaces/Operator.ts b/common/ssv/src/interfaces/Operator.ts
index 141d43b47..cf7f25a9a 100644
--- a/common/ssv/src/interfaces/Operator.ts
+++ b/common/ssv/src/interfaces/Operator.ts
@@ -1,4 +1,4 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export interface Operator {
id: number
diff --git a/common/ssv/src/interfaces/ScannerOptions.ts b/common/ssv/src/interfaces/ScannerOptions.ts
index 9e23c356d..dfa87eb1f 100644
--- a/common/ssv/src/interfaces/ScannerOptions.ts
+++ b/common/ssv/src/interfaces/ScannerOptions.ts
@@ -1,4 +1,4 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export interface ScannerOptions {
ethereumUrl?: string
diff --git a/common/ssv/src/providers/scanner.ts b/common/ssv/src/providers/scanner.ts
index 542dba7ed..b723d2e97 100644
--- a/common/ssv/src/providers/scanner.ts
+++ b/common/ssv/src/providers/scanner.ts
@@ -1,153 +1,153 @@
-import { ethers } from 'ethers'
-import { ISSVClusters, ISSVOperators, ISSVViews } from '@casimir/ethereum/build/@types'
-import ISSVClustersAbi from '@casimir/ethereum/build/abi/ISSVClusters.json'
-import ISSVOperatorsAbi from '@casimir/ethereum/build/abi/ISSVOperators.json'
-import ISSVViewsAbi from '@casimir/ethereum/build/abi/ISSVViews.json'
-import { GetClusterInput } from '../interfaces/GetClusterInput'
-import { Cluster } from '../interfaces/Cluster'
-import { Operator } from '../interfaces/Operator'
-import { ScannerOptions } from '../interfaces/ScannerOptions'
+import { ethers } from "ethers"
+import { ISSVClusters, ISSVOperators, ISSVViews } from "@casimir/ethereum/build/@types"
+import ISSVClustersAbi from "@casimir/ethereum/build/abi/ISSVClusters.json"
+import ISSVOperatorsAbi from "@casimir/ethereum/build/abi/ISSVOperators.json"
+import ISSVViewsAbi from "@casimir/ethereum/build/abi/ISSVViews.json"
+import { GetClusterInput } from "../interfaces/GetClusterInput"
+import { Cluster } from "../interfaces/Cluster"
+import { Operator } from "../interfaces/Operator"
+import { ScannerOptions } from "../interfaces/ScannerOptions"
export class Scanner {
- DAY = 5400
- WEEK = this.DAY * 7
- MONTH = this.DAY * 30
- provider: ethers.providers.JsonRpcProvider
- ssvClusters: ISSVClusters & ethers.Contract
- ssvOperators: ISSVOperators & ethers.Contract
- ssvViews: ISSVViews & ethers.Contract
+ DAY = 5400
+ WEEK = this.DAY * 7
+ MONTH = this.DAY * 30
+ provider: ethers.providers.JsonRpcProvider
+ ssvClusters: ISSVClusters & ethers.Contract
+ ssvOperators: ISSVOperators & ethers.Contract
+ ssvViews: ISSVViews & ethers.Contract
- constructor(options: ScannerOptions) {
- if (options.provider) {
- this.provider = options.provider
- } else {
- this.provider = new ethers.providers.JsonRpcProvider(options.ethereumUrl)
- }
- this.ssvClusters = new ethers.Contract(options.ssvNetworkAddress, ISSVClustersAbi, this.provider) as ISSVClusters & ethers.Contract
- this.ssvOperators = new ethers.Contract(options.ssvNetworkAddress, ISSVOperatorsAbi, this.provider) as ISSVOperators & ethers.Contract
- this.ssvViews = new ethers.Contract(options.ssvViewsAddress, ISSVViewsAbi, this.provider) as ISSVViews & ethers.Contract
+ constructor(options: ScannerOptions) {
+ if (options.provider) {
+ this.provider = options.provider
+ } else {
+ this.provider = new ethers.providers.JsonRpcProvider(options.ethereumUrl)
}
+ this.ssvClusters = new ethers.Contract(options.ssvNetworkAddress, ISSVClustersAbi, this.provider) as ISSVClusters & ethers.Contract
+ this.ssvOperators = new ethers.Contract(options.ssvNetworkAddress, ISSVOperatorsAbi, this.provider) as ISSVOperators & ethers.Contract
+ this.ssvViews = new ethers.Contract(options.ssvViewsAddress, ISSVViewsAbi, this.provider) as ISSVViews & ethers.Contract
+ }
- /**
+ /**
* Get cluster details
* @param {ClusterInput} input - Operator IDs and withdrawal address
* @returns {Promise} Cluster snapshot and required balance per validator
*/
- async getCluster(input: GetClusterInput): Promise {
- const { ownerAddress, operatorIds } = input
- const contractFilters = [
- this.ssvClusters.filters.ClusterDeposited(ownerAddress),
- this.ssvClusters.filters.ClusterWithdrawn(ownerAddress),
- this.ssvClusters.filters.ValidatorAdded(ownerAddress),
- this.ssvClusters.filters.ValidatorRemoved(ownerAddress),
- this.ssvClusters.filters.ClusterLiquidated(ownerAddress),
- this.ssvClusters.filters.ClusterReactivated(ownerAddress)
- ]
- let step = this.MONTH
- const latestBlockNumber = await this.provider.getBlockNumber()
- let fromBlock = latestBlockNumber - step
- let toBlock = latestBlockNumber
- let biggestBlockNumber = 0
- let cluster: Cluster | undefined
- while (!cluster && fromBlock > 0) {
- try {
- const items = []
- for (const filter of contractFilters) {
- const filteredItems = await this.ssvClusters.queryFilter(filter, fromBlock, toBlock)
- items.push(...filteredItems)
- }
- for (const item of items) {
- const { args, blockNumber } = item
- const clusterMatch = args?.cluster !== undefined
- const operatorsMatch = JSON.stringify(args?.operatorIds.map(id => id.toNumber())) === JSON.stringify(operatorIds)
- if (!clusterMatch || !operatorsMatch) continue
- if (blockNumber > biggestBlockNumber) {
- biggestBlockNumber = blockNumber
- const [
- validatorCount,
- networkFeeIndex,
- index,
- active,
- balance
- ] = args.cluster
- cluster = {
- validatorCount,
- networkFeeIndex,
- index,
- active,
- balance
- }
- }
- }
- toBlock = fromBlock
- } catch (error) {
- if (step === this.MONTH) {
- step = this.WEEK
- } else if (step === this.WEEK) {
- step = this.DAY
- }
+ async getCluster(input: GetClusterInput): Promise {
+ const { ownerAddress, operatorIds } = input
+ const contractFilters = [
+ this.ssvClusters.filters.ClusterDeposited(ownerAddress),
+ this.ssvClusters.filters.ClusterWithdrawn(ownerAddress),
+ this.ssvClusters.filters.ValidatorAdded(ownerAddress),
+ this.ssvClusters.filters.ValidatorRemoved(ownerAddress),
+ this.ssvClusters.filters.ClusterLiquidated(ownerAddress),
+ this.ssvClusters.filters.ClusterReactivated(ownerAddress)
+ ]
+ let step = this.MONTH
+ const latestBlockNumber = await this.provider.getBlockNumber()
+ let fromBlock = latestBlockNumber - step
+ let toBlock = latestBlockNumber
+ let biggestBlockNumber = 0
+ let cluster: Cluster | undefined
+ while (!cluster && fromBlock > 0) {
+ try {
+ const items = []
+ for (const filter of contractFilters) {
+ const filteredItems = await this.ssvClusters.queryFilter(filter, fromBlock, toBlock)
+ items.push(...filteredItems)
+ }
+ for (const item of items) {
+ const { args, blockNumber } = item
+ const clusterMatch = args?.cluster !== undefined
+ const operatorsMatch = JSON.stringify(args?.operatorIds.map(id => id.toNumber())) === JSON.stringify(operatorIds)
+ if (!clusterMatch || !operatorsMatch) continue
+ if (blockNumber > biggestBlockNumber) {
+ biggestBlockNumber = blockNumber
+ const [
+ validatorCount,
+ networkFeeIndex,
+ index,
+ active,
+ balance
+ ] = args.cluster
+ cluster = {
+ validatorCount,
+ networkFeeIndex,
+ index,
+ active,
+ balance
}
- fromBlock = toBlock - step
+ }
}
- cluster = cluster || {
- validatorCount: 0,
- networkFeeIndex: 0,
- index: 0,
- active: true,
- balance: 0
+ toBlock = fromBlock
+ } catch (error) {
+ if (step === this.MONTH) {
+ step = this.WEEK
+ } else if (step === this.WEEK) {
+ step = this.DAY
}
- return cluster
+ }
+ fromBlock = toBlock - step
+ }
+ cluster = cluster || {
+ validatorCount: 0,
+ networkFeeIndex: 0,
+ index: 0,
+ active: true,
+ balance: 0
}
+ return cluster
+ }
- /**
+ /**
* Get validator owner nonce
* @param {string} ownerAddress - Owner address
* @returns {Promise} Owner validator nonce
*/
- async getNonce(ownerAddress: string): Promise {
- const eventFilter = this.ssvClusters.filters.ValidatorAdded(ownerAddress)
- const fromBlock = 0
- const toBlock = 'latest'
- const items = await this.ssvClusters.queryFilter(eventFilter, fromBlock, toBlock)
- return items.length
- }
+ async getNonce(ownerAddress: string): Promise {
+ const eventFilter = this.ssvClusters.filters.ValidatorAdded(ownerAddress)
+ const fromBlock = 0
+ const toBlock = "latest"
+ const items = await this.ssvClusters.queryFilter(eventFilter, fromBlock, toBlock)
+ return items.length
+ }
- /**
+ /**
* Get minimum required validator fee
* @param {number[]} operatorIds - Operator IDs
* @returns {Promise} Validator fee
*/
- async getRequiredFee(operatorIds: number[]): Promise {
- let feeSum = await this.ssvViews.getNetworkFee()
- for (const operatorId of operatorIds) {
- const operatorFee = await this.ssvViews.getOperatorFee(operatorId)
- feeSum = feeSum.add(operatorFee)
- }
- const liquidationThresholdPeriod = await this.ssvViews.getLiquidationThresholdPeriod()
- return feeSum.mul(liquidationThresholdPeriod).mul(6)
+ async getRequiredFee(operatorIds: number[]): Promise {
+ let feeSum = await this.ssvViews.getNetworkFee()
+ for (const operatorId of operatorIds) {
+ const operatorFee = await this.ssvViews.getOperatorFee(operatorId)
+ feeSum = feeSum.add(operatorFee)
}
+ const liquidationThresholdPeriod = await this.ssvViews.getLiquidationThresholdPeriod()
+ return feeSum.mul(liquidationThresholdPeriod).mul(6)
+ }
- /**
+ /**
* Get operators by owner address
* @param {string} ownerAddress - Owner address
* @returns {Promise} The owner's operators
*/
- async getOperators(ownerAddress: string): Promise {
- const eventFilter = this.ssvOperators.filters.OperatorAdded(null, ownerAddress)
- const operators: Operator[] = []
- const items = await this.ssvOperators.queryFilter(eventFilter, 0, 'latest')
- for (const item of items) {
- const { args } = item
- const { operatorId } = args
- const { fee, validatorCount, isPrivate } = await this.ssvViews.getOperatorById(operatorId)
- operators.push({
- id: operatorId.toNumber(),
- fee,
- ownerAddress,
- validatorCount,
- isPrivate
- })
- }
- return operators
+ async getOperators(ownerAddress: string): Promise {
+ const eventFilter = this.ssvOperators.filters.OperatorAdded(null, ownerAddress)
+ const operators: Operator[] = []
+ const items = await this.ssvOperators.queryFilter(eventFilter, 0, "latest")
+ for (const item of items) {
+ const { args } = item
+ const { operatorId } = args
+ const { fee, validatorCount, isPrivate } = await this.ssvViews.getOperatorById(operatorId)
+ operators.push({
+ id: operatorId.toNumber(),
+ fee,
+ ownerAddress,
+ validatorCount,
+ isPrivate
+ })
}
+ return operators
+ }
}
\ No newline at end of file
diff --git a/common/types/src/index.ts b/common/types/src/index.ts
index b770e8899..5858d4d2f 100644
--- a/common/types/src/index.ts
+++ b/common/types/src/index.ts
@@ -1,90 +1,90 @@
-import { Account } from './interfaces/Account'
-import { AccountWithStakingAndOperatorInfo } from './interfaces/AccountWithStakingAndOperatorInfo'
-import { AddAccountOptions } from './interfaces/AddAccountOptions'
-import { AnalyticsData } from './interfaces/AnalyticsData'
-import { ApiResponse } from './interfaces/ApiResponse'
-import { Article } from './interfaces/Article'
-import { BalanceSnapshot } from './interfaces/BalanceSnapshot'
-import { BreakdownAmount } from './interfaces/BreakdownAmount'
-import { BreakdownString } from './interfaces/BreakdownString'
-import { BrowserProviders } from './interfaces/BrowserProviders'
-import { ContractArgs } from './interfaces/ContractArgs'
-import { ContractConfig } from './interfaces/ContractConfig'
-import { ContractEventsByAddress } from './interfaces/ContractEventsByAddress'
-import { CryptoAddress } from './interfaces/CryptoAddress'
-import { Currency } from './interfaces/Currency'
-import { DeploymentConfig } from './interfaces/DeploymentConfig'
-import { EthersProvider } from './interfaces/EthersProvider'
-import { Event } from './interfaces/Event'
-import { ExistingUserCheck } from './interfaces/ExistingUserCheck'
-import { FormattedWalletOption } from './interfaces/FormattedWalletOption'
-import { GasEstimate } from './interfaces/GasEstimate'
-import { HackmdArticle } from './interfaces/HackmdArticle'
-import { LoginCredentials } from './interfaces/LoginCredentials'
-import { ManagerConfig } from './interfaces/ManagerConfig'
-import { MessageRequest } from './interfaces/MessageRequest'
-import { Operator } from './interfaces/Operator'
-import { OperatorAddedSuccess } from './interfaces/OperatorAddedSuccess'
-import { PoolConfig } from './interfaces/PoolConfig'
-import { PoolStatus } from './interfaces/PoolStatus'
-import { ProviderString } from './interfaces/ProviderString'
-import { SignInWithEthereumCredentials } from './interfaces/SignInWithEthereumCredentials'
-import { TransactionRequest } from './interfaces/TransactionRequest'
-import { RegisteredOperator } from './interfaces/RegisteredOperator'
-import { RegisterOperatorWithCasimirParams } from './interfaces/RegisterOperatorWithCasimirParams'
-import { RemoveAccountOptions } from './interfaces/RemoveAccountOptions'
-import { Reshare } from './interfaces/Reshare'
-import { User } from './interfaces/User'
-import { UserAddedSuccess } from './interfaces/UserAddedSuccess'
-import { UserAnalyticsData } from './interfaces/UserAnalyticsData'
-import { UserAuthState } from './interfaces/UserAuthState'
-import { UserWithAccountsAndOperators } from './interfaces/UserWithAccountsAndOperators'
-import { Validator } from './interfaces/Validator'
+import { Account } from "./interfaces/Account"
+import { AccountWithStakingAndOperatorInfo } from "./interfaces/AccountWithStakingAndOperatorInfo"
+import { AddAccountOptions } from "./interfaces/AddAccountOptions"
+import { AnalyticsData } from "./interfaces/AnalyticsData"
+import { ApiResponse } from "./interfaces/ApiResponse"
+import { Article } from "./interfaces/Article"
+import { BalanceSnapshot } from "./interfaces/BalanceSnapshot"
+import { BreakdownAmount } from "./interfaces/BreakdownAmount"
+import { BreakdownString } from "./interfaces/BreakdownString"
+import { BrowserProviders } from "./interfaces/BrowserProviders"
+import { ContractArgs } from "./interfaces/ContractArgs"
+import { ContractConfig } from "./interfaces/ContractConfig"
+import { ContractEventsByAddress } from "./interfaces/ContractEventsByAddress"
+import { CryptoAddress } from "./interfaces/CryptoAddress"
+import { Currency } from "./interfaces/Currency"
+import { DeploymentConfig } from "./interfaces/DeploymentConfig"
+import { EthersProvider } from "./interfaces/EthersProvider"
+import { Event } from "./interfaces/Event"
+import { ExistingUserCheck } from "./interfaces/ExistingUserCheck"
+import { FormattedWalletOption } from "./interfaces/FormattedWalletOption"
+import { GasEstimate } from "./interfaces/GasEstimate"
+import { HackmdArticle } from "./interfaces/HackmdArticle"
+import { LoginCredentials } from "./interfaces/LoginCredentials"
+import { ManagerConfig } from "./interfaces/ManagerConfig"
+import { MessageRequest } from "./interfaces/MessageRequest"
+import { Operator } from "./interfaces/Operator"
+import { OperatorAddedSuccess } from "./interfaces/OperatorAddedSuccess"
+import { PoolConfig } from "./interfaces/PoolConfig"
+import { PoolStatus } from "./interfaces/PoolStatus"
+import { ProviderString } from "./interfaces/ProviderString"
+import { SignInWithEthereumCredentials } from "./interfaces/SignInWithEthereumCredentials"
+import { TransactionRequest } from "./interfaces/TransactionRequest"
+import { RegisteredOperator } from "./interfaces/RegisteredOperator"
+import { RegisterOperatorWithCasimirParams } from "./interfaces/RegisterOperatorWithCasimirParams"
+import { RemoveAccountOptions } from "./interfaces/RemoveAccountOptions"
+import { Reshare } from "./interfaces/Reshare"
+import { User } from "./interfaces/User"
+import { UserAddedSuccess } from "./interfaces/UserAddedSuccess"
+import { UserAnalyticsData } from "./interfaces/UserAnalyticsData"
+import { UserAuthState } from "./interfaces/UserAuthState"
+import { UserWithAccountsAndOperators } from "./interfaces/UserWithAccountsAndOperators"
+import { Validator } from "./interfaces/Validator"
export type {
- Account,
- AccountWithStakingAndOperatorInfo,
- ApiResponse,
- AddAccountOptions,
- AnalyticsData,
- Article,
- BalanceSnapshot,
- BreakdownAmount,
- BreakdownString,
- BrowserProviders,
- ContractArgs,
- ContractConfig,
- ContractEventsByAddress,
- CryptoAddress,
- Currency,
- DeploymentConfig,
- EthersProvider,
- Event,
- ExistingUserCheck,
- FormattedWalletOption,
- GasEstimate,
- HackmdArticle,
- LoginCredentials,
- ManagerConfig,
- MessageRequest,
- Operator,
- OperatorAddedSuccess,
- PoolConfig,
- ProviderString,
- SignInWithEthereumCredentials,
- TransactionRequest,
- RegisteredOperator,
- RegisterOperatorWithCasimirParams,
- RemoveAccountOptions,
- Reshare,
- User,
- UserAddedSuccess,
- UserAnalyticsData,
- UserAuthState,
- UserWithAccountsAndOperators,
- Validator
+ Account,
+ AccountWithStakingAndOperatorInfo,
+ ApiResponse,
+ AddAccountOptions,
+ AnalyticsData,
+ Article,
+ BalanceSnapshot,
+ BreakdownAmount,
+ BreakdownString,
+ BrowserProviders,
+ ContractArgs,
+ ContractConfig,
+ ContractEventsByAddress,
+ CryptoAddress,
+ Currency,
+ DeploymentConfig,
+ EthersProvider,
+ Event,
+ ExistingUserCheck,
+ FormattedWalletOption,
+ GasEstimate,
+ HackmdArticle,
+ LoginCredentials,
+ ManagerConfig,
+ MessageRequest,
+ Operator,
+ OperatorAddedSuccess,
+ PoolConfig,
+ ProviderString,
+ SignInWithEthereumCredentials,
+ TransactionRequest,
+ RegisteredOperator,
+ RegisterOperatorWithCasimirParams,
+ RemoveAccountOptions,
+ Reshare,
+ User,
+ UserAddedSuccess,
+ UserAnalyticsData,
+ UserAuthState,
+ UserWithAccountsAndOperators,
+ Validator
}
export {
- PoolStatus
+ PoolStatus
}
diff --git a/common/types/src/interfaces/Account.ts b/common/types/src/interfaces/Account.ts
index dfeefbf35..650dce46d 100644
--- a/common/types/src/interfaces/Account.ts
+++ b/common/types/src/interfaces/Account.ts
@@ -1,6 +1,6 @@
-import { BalanceSnapshot } from './BalanceSnapshot'
-import { ProviderString } from './ProviderString'
-import { Currency } from './Currency'
+import { BalanceSnapshot } from "./BalanceSnapshot"
+import { ProviderString } from "./ProviderString"
+import { Currency } from "./Currency"
export interface Account {
/** The address of the current account */
diff --git a/common/types/src/interfaces/AccountWithStakingAndOperatorInfo.ts b/common/types/src/interfaces/AccountWithStakingAndOperatorInfo.ts
index 84893d7cf..c87a6d6be 100644
--- a/common/types/src/interfaces/AccountWithStakingAndOperatorInfo.ts
+++ b/common/types/src/interfaces/AccountWithStakingAndOperatorInfo.ts
@@ -1,4 +1,4 @@
-import { Account, Operator, PoolConfig } from '@casimir/types'
+import { Account, Operator, PoolConfig } from "@casimir/types"
export interface AccountWithStakingAndOperatorInfo extends Account {
/** The user's current staking pools and details (this interface/logic is in the web app wallet composable, but it will be moved to the processor, see https://github.com/consensusnetworks/casimir/blob/master/apps/web/src/composables/wallet.ts#L146) */
diff --git a/common/types/src/interfaces/ApiResponse.ts b/common/types/src/interfaces/ApiResponse.ts
index ce907466e..a62c8f8df 100644
--- a/common/types/src/interfaces/ApiResponse.ts
+++ b/common/types/src/interfaces/ApiResponse.ts
@@ -1,4 +1,4 @@
-import { ExistingUserCheck } from './ExistingUserCheck'
+import { ExistingUserCheck } from "./ExistingUserCheck"
export interface ApiResponse {
error: boolean;
diff --git a/common/types/src/interfaces/BreakdownString.ts b/common/types/src/interfaces/BreakdownString.ts
index 61f0962e4..12d62bd16 100644
--- a/common/types/src/interfaces/BreakdownString.ts
+++ b/common/types/src/interfaces/BreakdownString.ts
@@ -1 +1 @@
-export type BreakdownString = 'currentStaked' | 'totalWalletBalance' | 'stakingRewardsEarned'
\ No newline at end of file
+export type BreakdownString = "currentStaked" | "totalWalletBalance" | "stakingRewardsEarned"
\ No newline at end of file
diff --git a/common/types/src/interfaces/BrowserProviders.ts b/common/types/src/interfaces/BrowserProviders.ts
index 613397498..468abcca8 100644
--- a/common/types/src/interfaces/BrowserProviders.ts
+++ b/common/types/src/interfaces/BrowserProviders.ts
@@ -1,4 +1,4 @@
-import { EthersProvider } from './EthersProvider'
+import { EthersProvider } from "./EthersProvider"
// TODO: Add other browser providers here and set their types accordingly?? (BraveWallet, TrustWallet)
export interface BrowserProviders {
diff --git a/common/types/src/interfaces/ContractConfig.ts b/common/types/src/interfaces/ContractConfig.ts
index 4e645d2c1..5034cea06 100644
--- a/common/types/src/interfaces/ContractConfig.ts
+++ b/common/types/src/interfaces/ContractConfig.ts
@@ -1,4 +1,4 @@
-import { ContractArgs } from './ContractArgs'
+import { ContractArgs } from "./ContractArgs"
export interface ContractConfig {
address: string | undefined
diff --git a/common/types/src/interfaces/Currency.ts b/common/types/src/interfaces/Currency.ts
index b0b9101d2..2940bb850 100644
--- a/common/types/src/interfaces/Currency.ts
+++ b/common/types/src/interfaces/Currency.ts
@@ -1 +1 @@
-export type Currency = 'ETH' | /*'BTC' |*/ 'IOTX' | 'SOL' | 'USD' | ''
\ No newline at end of file
+export type Currency = "ETH" | /*'BTC' |*/ "IOTX" | "SOL" | "USD" | ""
\ No newline at end of file
diff --git a/common/types/src/interfaces/DeploymentConfig.ts b/common/types/src/interfaces/DeploymentConfig.ts
index 7ace31a4b..8c0daff26 100644
--- a/common/types/src/interfaces/DeploymentConfig.ts
+++ b/common/types/src/interfaces/DeploymentConfig.ts
@@ -1,4 +1,4 @@
-import { ContractConfig } from './ContractConfig'
+import { ContractConfig } from "./ContractConfig"
export interface DeploymentConfig {
CasimirManager: ContractConfig
diff --git a/common/types/src/interfaces/EthersProvider.ts b/common/types/src/interfaces/EthersProvider.ts
index d3fd004f9..3a3469ff7 100644
--- a/common/types/src/interfaces/EthersProvider.ts
+++ b/common/types/src/interfaces/EthersProvider.ts
@@ -1,4 +1,4 @@
-import { ExternalProvider } from '@ethersproject/providers'
+import { ExternalProvider } from "@ethersproject/providers"
export interface EthersProvider extends ExternalProvider {
isCoinbaseWallet?: boolean
diff --git a/common/types/src/interfaces/Event.ts b/common/types/src/interfaces/Event.ts
index a4270b12c..8eaff3d7c 100644
--- a/common/types/src/interfaces/Event.ts
+++ b/common/types/src/interfaces/Event.ts
@@ -1,12 +1,12 @@
export interface Event {
// The chain which the event belongs to (e.g. iotex, ethereum)
- chain: 'etheruem' | 'iotex';
+ chain: "etheruem" | "iotex";
// The network which the event was received on (e.g. mainnet, testnet)
- network: 'mainnet' | 'testnet' | 'goerli';
+ network: "mainnet" | "testnet" | "goerli";
// The provider used to source the event (e.g. infura, consensus)
- provider: 'alchemy' | 'consensus';
+ provider: "alchemy" | "consensus";
// The type of event (e.g. block, transaction)
- type: 'block' | 'transaction';
+ type: "block" | "transaction";
// The height of the block the event belongs to
height: number;
// The block hash
diff --git a/common/types/src/interfaces/FormattedWalletOption.ts b/common/types/src/interfaces/FormattedWalletOption.ts
index 1c95f25f8..ff7d2f3a0 100644
--- a/common/types/src/interfaces/FormattedWalletOption.ts
+++ b/common/types/src/interfaces/FormattedWalletOption.ts
@@ -1,4 +1,4 @@
-import { ProviderString } from './ProviderString'
+import { ProviderString } from "./ProviderString"
export interface FormattedWalletOption {
provider: ProviderString,
diff --git a/common/types/src/interfaces/LoginCredentials.ts b/common/types/src/interfaces/LoginCredentials.ts
index e32fdd893..10c343eab 100644
--- a/common/types/src/interfaces/LoginCredentials.ts
+++ b/common/types/src/interfaces/LoginCredentials.ts
@@ -1,5 +1,5 @@
-import { Currency } from './Currency'
-import { ProviderString } from './ProviderString'
+import { Currency } from "./Currency"
+import { ProviderString } from "./ProviderString"
export interface LoginCredentials {
address: string
diff --git a/common/types/src/interfaces/ManagerConfig.ts b/common/types/src/interfaces/ManagerConfig.ts
index 96170ac67..9eba3ecf5 100644
--- a/common/types/src/interfaces/ManagerConfig.ts
+++ b/common/types/src/interfaces/ManagerConfig.ts
@@ -1,4 +1,4 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export type ManagerConfig = {
managerAddress: string
diff --git a/common/types/src/interfaces/MessageInit.ts b/common/types/src/interfaces/MessageInit.ts
index f4f41efaa..77dfc03c5 100644
--- a/common/types/src/interfaces/MessageInit.ts
+++ b/common/types/src/interfaces/MessageInit.ts
@@ -1,5 +1,5 @@
-import { ProviderString } from './ProviderString'
-import { Currency } from './Currency'
+import { ProviderString } from "./ProviderString"
+import { Currency } from "./Currency"
export interface MessageRequest {
message: string;
diff --git a/common/types/src/interfaces/MessageRequest.ts b/common/types/src/interfaces/MessageRequest.ts
index f4f41efaa..77dfc03c5 100644
--- a/common/types/src/interfaces/MessageRequest.ts
+++ b/common/types/src/interfaces/MessageRequest.ts
@@ -1,5 +1,5 @@
-import { ProviderString } from './ProviderString'
-import { Currency } from './Currency'
+import { ProviderString } from "./ProviderString"
+import { Currency } from "./Currency"
export interface MessageRequest {
message: string;
diff --git a/common/types/src/interfaces/OperatorDetails.ts b/common/types/src/interfaces/OperatorDetails.ts
index 27635aa3e..de3cd7bfc 100644
--- a/common/types/src/interfaces/OperatorDetails.ts
+++ b/common/types/src/interfaces/OperatorDetails.ts
@@ -18,8 +18,8 @@ export interface OperatorDetails {
logo: string
type: string
performance: {
- '24h': number
- '30d': number
+ "24h": number
+ "30d": number
},
is_active: number
is_valid: boolean
diff --git a/common/types/src/interfaces/PoolConfig.ts b/common/types/src/interfaces/PoolConfig.ts
index e7b9a29c8..4967bbcf0 100644
--- a/common/types/src/interfaces/PoolConfig.ts
+++ b/common/types/src/interfaces/PoolConfig.ts
@@ -1,4 +1,4 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export interface PoolConfig {
poolAddress: string;
diff --git a/common/types/src/interfaces/ProviderString.ts b/common/types/src/interfaces/ProviderString.ts
index 8081c8c8f..31859c3f4 100644
--- a/common/types/src/interfaces/ProviderString.ts
+++ b/common/types/src/interfaces/ProviderString.ts
@@ -1,9 +1,9 @@
-import { BrowserProviders } from './BrowserProviders'
+import { BrowserProviders } from "./BrowserProviders"
export type ProviderString =
| keyof BrowserProviders
- | 'IoPay'
- | 'Ledger'
- | 'Trezor'
- | 'WalletConnect'
- | 'Phantom'
- | ''
\ No newline at end of file
+ | "IoPay"
+ | "Ledger"
+ | "Trezor"
+ | "WalletConnect"
+ | "Phantom"
+ | ""
\ No newline at end of file
diff --git a/common/types/src/interfaces/RegisterOperatorWithCasimirParams.ts b/common/types/src/interfaces/RegisterOperatorWithCasimirParams.ts
index df5d8f4d8..c81e6ecd9 100644
--- a/common/types/src/interfaces/RegisterOperatorWithCasimirParams.ts
+++ b/common/types/src/interfaces/RegisterOperatorWithCasimirParams.ts
@@ -1,5 +1,5 @@
-import { ProviderString } from '@casimir/types'
-import { BigNumberish } from 'ethers'
+import { ProviderString } from "@casimir/types"
+import { BigNumberish } from "ethers"
export interface RegisterOperatorWithCasimirParams {
walletProvider: ProviderString
diff --git a/common/types/src/interfaces/RegisteredOperator.ts b/common/types/src/interfaces/RegisteredOperator.ts
index 54a6ea877..9bb9f2311 100644
--- a/common/types/src/interfaces/RegisteredOperator.ts
+++ b/common/types/src/interfaces/RegisteredOperator.ts
@@ -1,5 +1,5 @@
-import { PoolConfig } from './PoolConfig'
-import { Operator } from '@casimir/ssv'
+import { PoolConfig } from "./PoolConfig"
+import { Operator } from "@casimir/ssv"
export interface RegisteredOperator extends Operator {
active: boolean
diff --git a/common/types/src/interfaces/SignInWithEthereumCredentials.ts b/common/types/src/interfaces/SignInWithEthereumCredentials.ts
index f667c04ef..fc21ee972 100644
--- a/common/types/src/interfaces/SignInWithEthereumCredentials.ts
+++ b/common/types/src/interfaces/SignInWithEthereumCredentials.ts
@@ -1,4 +1,4 @@
-import { LoginCredentials } from './LoginCredentials'
+import { LoginCredentials } from "./LoginCredentials"
export interface SignInWithEthereumCredentials extends LoginCredentials {
message: string
diff --git a/common/types/src/interfaces/TransactionRequest.ts b/common/types/src/interfaces/TransactionRequest.ts
index 38ad759ce..37d178503 100644
--- a/common/types/src/interfaces/TransactionRequest.ts
+++ b/common/types/src/interfaces/TransactionRequest.ts
@@ -1,6 +1,6 @@
-import ethers from 'ethers'
-import { ProviderString } from './ProviderString'
-import { Currency } from './Currency'
+import ethers from "ethers"
+import { ProviderString } from "./ProviderString"
+import { Currency } from "./Currency"
export interface TransactionRequest extends ethers.providers.TransactionRequest {
/** The transaction sender's address */
diff --git a/common/types/src/interfaces/User.ts b/common/types/src/interfaces/User.ts
index d9292df99..a15b6ce48 100644
--- a/common/types/src/interfaces/User.ts
+++ b/common/types/src/interfaces/User.ts
@@ -1,4 +1,4 @@
-import { ProviderString } from '@casimir/types'
+import { ProviderString } from "@casimir/types"
export interface User {
/* Unique ID (and essential for auth verification) */
diff --git a/common/types/src/interfaces/UserAnalyticsData.ts b/common/types/src/interfaces/UserAnalyticsData.ts
index 91a65f4b7..a05da5689 100644
--- a/common/types/src/interfaces/UserAnalyticsData.ts
+++ b/common/types/src/interfaces/UserAnalyticsData.ts
@@ -1,4 +1,4 @@
-import { AnalyticsData } from '@casimir/types'
+import { AnalyticsData } from "@casimir/types"
export interface UserAnalyticsData {
oneMonth: {
diff --git a/common/types/src/interfaces/UserAuthState.ts b/common/types/src/interfaces/UserAuthState.ts
index d8d24d320..2ac31e962 100644
--- a/common/types/src/interfaces/UserAuthState.ts
+++ b/common/types/src/interfaces/UserAuthState.ts
@@ -1,9 +1,9 @@
-export type UserAuthState = 'default'
- |'loading'
- | 'Address already exists on this account'
- | 'Address already exists as a primary address on another account'
- | 'Address already exists as a secondary address on another account'
- | 'Successfully added account to user'
- | 'Successfully logged in'
- | 'Selected address is not active address in wallet'
- | 'Error in userAuthState'
\ No newline at end of file
+export type UserAuthState = "default"
+ |"loading"
+ | "Address already exists on this account"
+ | "Address already exists as a primary address on another account"
+ | "Address already exists as a secondary address on another account"
+ | "Successfully added account to user"
+ | "Successfully logged in"
+ | "Selected address is not active address in wallet"
+ | "Error in userAuthState"
\ No newline at end of file
diff --git a/common/types/src/interfaces/UserWithAccountsAndOperators.ts b/common/types/src/interfaces/UserWithAccountsAndOperators.ts
index 21facf67a..0386d28a7 100644
--- a/common/types/src/interfaces/UserWithAccountsAndOperators.ts
+++ b/common/types/src/interfaces/UserWithAccountsAndOperators.ts
@@ -1,4 +1,4 @@
-import { AccountWithStakingAndOperatorInfo, Operator, User } from '@casimir/types'
+import { AccountWithStakingAndOperatorInfo, Operator, User } from "@casimir/types"
export interface UserWithAccountsAndOperators extends User {
/** An array of the user's accounts */
diff --git a/common/uniswap/src/index.ts b/common/uniswap/src/index.ts
index 15d680124..4e97c005f 100644
--- a/common/uniswap/src/index.ts
+++ b/common/uniswap/src/index.ts
@@ -1,3 +1,3 @@
-import { Factory } from './providers/factory'
+import { Factory } from "./providers/factory"
export { Factory }
\ No newline at end of file
diff --git a/common/uniswap/src/interfaces/FactoryOptions.ts b/common/uniswap/src/interfaces/FactoryOptions.ts
index 285780d80..074f14ed0 100644
--- a/common/uniswap/src/interfaces/FactoryOptions.ts
+++ b/common/uniswap/src/interfaces/FactoryOptions.ts
@@ -1,4 +1,4 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export interface FactoryOptions {
ethereumUrl?: string
diff --git a/common/uniswap/src/providers/factory.ts b/common/uniswap/src/providers/factory.ts
index 669e12b67..37adb639e 100644
--- a/common/uniswap/src/providers/factory.ts
+++ b/common/uniswap/src/providers/factory.ts
@@ -1,34 +1,34 @@
-import { ethers } from 'ethers'
-import { FactoryOptions } from '../interfaces/FactoryOptions'
-import { PriceInput } from '../interfaces/PriceInput'
-import IUniswapV3FactoryAbi from '@casimir/ethereum/build/abi/IUniswapV3Factory.json'
-import IUniswapV3PoolStateAbi from '@casimir/ethereum/build/abi/IUniswapV3PoolState.json'
-import { IUniswapV3Factory, IUniswapV3PoolState } from '@casimir/ethereum/build/@types'
+import { ethers } from "ethers"
+import { FactoryOptions } from "../interfaces/FactoryOptions"
+import { PriceInput } from "../interfaces/PriceInput"
+import IUniswapV3FactoryAbi from "@casimir/ethereum/build/abi/IUniswapV3Factory.json"
+import IUniswapV3PoolStateAbi from "@casimir/ethereum/build/abi/IUniswapV3PoolState.json"
+import { IUniswapV3Factory, IUniswapV3PoolState } from "@casimir/ethereum/build/@types"
export class Factory {
- provider: ethers.providers.JsonRpcProvider
- uniswapV3Factory: IUniswapV3Factory & ethers.Contract
+ provider: ethers.providers.JsonRpcProvider
+ uniswapV3Factory: IUniswapV3Factory & ethers.Contract
- constructor(options: FactoryOptions) {
- if (options.provider) {
- this.provider = options.provider
- } else {
- this.provider = new ethers.providers.JsonRpcProvider(options.ethereumUrl)
- }
- this.uniswapV3Factory = new ethers.Contract(options.uniswapV3FactoryAddress, IUniswapV3FactoryAbi, this.provider) as IUniswapV3Factory & ethers.Contract
+ constructor(options: FactoryOptions) {
+ if (options.provider) {
+ this.provider = options.provider
+ } else {
+ this.provider = new ethers.providers.JsonRpcProvider(options.ethereumUrl)
}
+ this.uniswapV3Factory = new ethers.Contract(options.uniswapV3FactoryAddress, IUniswapV3FactoryAbi, this.provider) as IUniswapV3Factory & ethers.Contract
+ }
- /**
+ /**
* Get the swap price for a given token pair
* @param {PriceInput} input - Token in, token out, and uniswap fee tier
* @returns {Promise} Swap price
*/
- getSwapPrice = async (input: PriceInput): Promise => {
- const { tokenIn, tokenOut, uniswapFeeTier } = input
- const poolAddress = await this.uniswapV3Factory.getPool(tokenIn, tokenOut, uniswapFeeTier)
- const poolContract = new ethers.Contract(poolAddress, IUniswapV3PoolStateAbi, this.provider) as IUniswapV3PoolState & ethers.Contract
- const slot0 = await poolContract.slot0()
- const tick = slot0.tick
- return 1.0001 ** tick
- }
+ getSwapPrice = async (input: PriceInput): Promise => {
+ const { tokenIn, tokenOut, uniswapFeeTier } = input
+ const poolAddress = await this.uniswapV3Factory.getPool(tokenIn, tokenOut, uniswapFeeTier)
+ const poolContract = new ethers.Contract(poolAddress, IUniswapV3PoolStateAbi, this.provider) as IUniswapV3PoolState & ethers.Contract
+ const slot0 = await poolContract.slot0()
+ const tick = slot0.tick
+ return 1.0001 ** tick
+ }
}
\ No newline at end of file
diff --git a/common/wallets/src/index.ts b/common/wallets/src/index.ts
index 668e70a47..31c0320e2 100644
--- a/common/wallets/src/index.ts
+++ b/common/wallets/src/index.ts
@@ -1,8 +1,8 @@
-import { /*BitcoinLedgerSigner, */EthersLedgerSigner } from './providers/ledger'
-import { EthersTrezorSigner } from './providers/trezor'
+import { /*BitcoinLedgerSigner, */EthersLedgerSigner } from "./providers/ledger"
+import { EthersTrezorSigner } from "./providers/trezor"
export {
- /*BitcoinLedgerSigner,*/
- EthersLedgerSigner,
- EthersTrezorSigner
+ /*BitcoinLedgerSigner,*/
+ EthersLedgerSigner,
+ EthersTrezorSigner
}
\ No newline at end of file
diff --git a/common/wallets/src/providers/ledger.ts b/common/wallets/src/providers/ledger.ts
index 43f4bb5a2..5cdb525e7 100644
--- a/common/wallets/src/providers/ledger.ts
+++ b/common/wallets/src/providers/ledger.ts
@@ -1,14 +1,14 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
// import Btc from '@ledgerhq/hw-app-btc'
-import Eth, { ledgerService } from '@ledgerhq/hw-app-eth'
-import Transport from '@ledgerhq/hw-transport'
-import TransportWebUSB from '@ledgerhq/hw-transport-webusb'
-import { CryptoAddress } from '@casimir/types'
+import Eth, { ledgerService } from "@ledgerhq/hw-app-eth"
+import Transport from "@ledgerhq/hw-transport"
+import TransportWebUSB from "@ledgerhq/hw-transport-webusb"
+import { CryptoAddress } from "@casimir/types"
const transports = {
- 'usb': async function createUSBTransport(): Promise {
- return await TransportWebUSB.create()
- }
+ "usb": async function createUSBTransport(): Promise {
+ return await TransportWebUSB.create()
+ }
}
export interface LedgerSignerOptions {
@@ -120,146 +120,146 @@ export interface LedgerSignerOptions {
// }
export class EthersLedgerSigner extends ethers.Signer {
- readonly type: string = 'usb'
- readonly path: string = 'm/44\'/60\'/0\'/0/0'
- readonly eth?: Promise
-
- constructor(options: LedgerSignerOptions) {
- super()
+ readonly type: string = "usb"
+ readonly path: string = "m/44'/60'/0'/0/0"
+ readonly eth?: Promise
- if (options.type) this.type = options.type
- if (options.path) this.path = options.path
+ constructor(options: LedgerSignerOptions) {
+ super()
- // Override readonly provider for ethers.Signer
- if (options.provider) {
- ethers.utils.defineReadOnly(this, 'provider', options.provider)
- }
+ if (options.type) this.type = options.type
+ if (options.path) this.path = options.path
- // Set readonly eth to Promise
- const transportCreatorType = this.type as keyof typeof transports
- const transportCreator = transports[transportCreatorType]
- if (!transportCreator) console.log('Unknown or unsupported type', this.type)
- ethers.utils.defineReadOnly(this, 'eth', transportCreator().then(transport => {
- return new Eth(transport)
- }))
+ // Override readonly provider for ethers.Signer
+ if (options.provider) {
+ ethers.utils.defineReadOnly(this, "provider", options.provider)
}
- retry(callback: (eth: Eth) => Promise, timeout?: number): Promise {
- // The async-promise-executor is ok since retry handles necessary errors
- // eslint-disable-next-line no-async-promise-executor
- return new Promise(async (resolve, reject) => {
- const ledgerConnectionError = 'Please make sure Ledger is ready and retry'
- if (timeout && timeout > 0) {
- setTimeout(() => reject(new Error(ledgerConnectionError)), timeout)
- }
-
- const eth = await this.eth as Eth
-
- // Wait up to 5 seconds
- for (let i = 0; i < 50; i++) {
- try {
- const result = await callback(eth)
- return resolve(result)
- } catch (error) {
- if ((error as { id: string }).id !== 'TransportLocked') {
- return reject(error)
- }
- }
- await new Promise((resolve) => {
- setTimeout(resolve, 100)
- })
- }
-
- return reject(new Error(ledgerConnectionError))
+ // Set readonly eth to Promise
+ const transportCreatorType = this.type as keyof typeof transports
+ const transportCreator = transports[transportCreatorType]
+ if (!transportCreator) console.log("Unknown or unsupported type", this.type)
+ ethers.utils.defineReadOnly(this, "eth", transportCreator().then(transport => {
+ return new Eth(transport)
+ }))
+ }
+
+ retry(callback: (eth: Eth) => Promise, timeout?: number): Promise {
+ // The async-promise-executor is ok since retry handles necessary errors
+ // eslint-disable-next-line no-async-promise-executor
+ return new Promise(async (resolve, reject) => {
+ const ledgerConnectionError = "Please make sure Ledger is ready and retry"
+ if (timeout && timeout > 0) {
+ setTimeout(() => reject(new Error(ledgerConnectionError)), timeout)
+ }
+
+ const eth = await this.eth as Eth
+
+ // Wait up to 5 seconds
+ for (let i = 0; i < 50; i++) {
+ try {
+ const result = await callback(eth)
+ return resolve(result)
+ } catch (error) {
+ if ((error as { id: string }).id !== "TransportLocked") {
+ return reject(error)
+ }
+ }
+ await new Promise((resolve) => {
+ setTimeout(resolve, 100)
})
- }
+ }
- async getAddresses(): Promise | null> {
- const ledgerAddresses = []
+ return reject(new Error(ledgerConnectionError))
+ })
+ }
+
+ async getAddresses(): Promise | null> {
+ const ledgerAddresses = []
- for (let i = 0; i < 5; i++) {
- // m/coin_type'/account_index'/external_chain_index'/address_index/change_index
- const path = `m/44'/60'/${i}'/0/0`
- const { address } = await this.retry((eth) => eth.getAddress(path))
- // TODO: Replace with our own provider depending on environment
- const provider = new ethers.providers.JsonRpcProvider('https://goerli.infura.io/v3/4e8acb4e58bb4cb9978ac4a22f3326a7')
- const balance = await provider.getBalance(address)
- const ethBalance = ethers.utils.formatEther(balance)
- if (parseFloat(ethBalance) > 0) ledgerAddresses.push({ address, balance: ethBalance, pathIndex: i.toString() })
- }
- return ledgerAddresses.length ? ledgerAddresses : null
+ for (let i = 0; i < 5; i++) {
+ // m/coin_type'/account_index'/external_chain_index'/address_index/change_index
+ const path = `m/44'/60'/${i}'/0/0`
+ const { address } = await this.retry((eth) => eth.getAddress(path))
+ // TODO: Replace with our own provider depending on environment
+ const provider = new ethers.providers.JsonRpcProvider("https://goerli.infura.io/v3/4e8acb4e58bb4cb9978ac4a22f3326a7")
+ const balance = await provider.getBalance(address)
+ const ethBalance = ethers.utils.formatEther(balance)
+ if (parseFloat(ethBalance) > 0) ledgerAddresses.push({ address, balance: ethBalance, pathIndex: i.toString() })
}
+ return ledgerAddresses.length ? ledgerAddresses : null
+ }
- async getAddress(): Promise {
- const { address } = await this.retry((eth) => eth.getAddress(this.path))
- return address
- }
+ async getAddress(): Promise {
+ const { address } = await this.retry((eth) => eth.getAddress(this.path))
+ return address
+ }
- async signMessage(message: ethers.utils.Bytes | string): Promise {
- if (typeof (message) === 'string') {
- message = ethers.utils.toUtf8Bytes(message)
- }
- const messageHex = ethers.utils.hexlify(message).substring(2)
- const testPath = 'm/44\'/60\'/1\'/0/0'
- const signature = await this.retry((eth) => eth.signPersonalMessage(testPath, messageHex))
- signature.r = '0x' + signature.r
- signature.s = '0x' + signature.s
- return ethers.utils.joinSignature(signature)
+ async signMessage(message: ethers.utils.Bytes | string): Promise {
+ if (typeof (message) === "string") {
+ message = ethers.utils.toUtf8Bytes(message)
}
+ const messageHex = ethers.utils.hexlify(message).substring(2)
+ const testPath = "m/44'/60'/1'/0/0"
+ const signature = await this.retry((eth) => eth.signPersonalMessage(testPath, messageHex))
+ signature.r = "0x" + signature.r
+ signature.s = "0x" + signature.s
+ return ethers.utils.joinSignature(signature)
+ }
- async signMessageWithIndex(message: ethers.utils.Bytes | string, pathIndex: number): Promise {
- if (typeof (message) === 'string') {
- console.log('message :>> ', message)
- message = ethers.utils.toUtf8Bytes(message)
- }
- const messageHex = ethers.utils.hexlify(message).substring(2)
- const path = `m/44'/60'/${pathIndex}'/0/0`
- const signature = await this.retry((eth) => eth.signPersonalMessage(path, messageHex))
- console.log('signature :>> ', signature)
- signature.r = '0x' + signature.r
- signature.s = '0x' + signature.s
- console.log('signature :>> ', signature)
- return ethers.utils.joinSignature(signature)
+ async signMessageWithIndex(message: ethers.utils.Bytes | string, pathIndex: number): Promise {
+ if (typeof (message) === "string") {
+ console.log("message :>> ", message)
+ message = ethers.utils.toUtf8Bytes(message)
}
-
- async signTransaction(transaction: ethers.providers.TransactionRequest): Promise {
- const tx = await ethers.utils.resolveProperties(transaction)
- const baseTx: ethers.utils.UnsignedTransaction = {
- chainId: (tx.chainId || undefined),
- data: (tx.data || undefined),
- gasLimit: (tx.gasLimit || undefined),
- gasPrice: (tx.gasPrice || undefined),
- nonce: (tx.nonce ? ethers.BigNumber.from(tx.nonce).toNumber() : undefined),
- to: (tx.to || undefined),
- value: (tx.value || undefined),
- type: (tx.type || undefined)
- }
-
- const unsignedTx = ethers.utils.serializeTransaction(baseTx).substring(2)
- const resolution = await ledgerService.resolveTransaction(unsignedTx, {}, {})
- const signature = await this.retry((eth) => eth.signTransaction(this.path, unsignedTx, resolution))
-
- return ethers.utils.serializeTransaction(baseTx, {
- v: ethers.BigNumber.from('0x' + signature.v).toNumber(),
- r: ('0x' + signature.r),
- s: ('0x' + signature.s),
- })
- }
-
- // Populates all fields in a transaction, signs it and sends it to the network
- async sendTransaction(transaction: ethers.utils.Deferrable): Promise {
- this._checkProvider('sendTransaction')
- const tx = await this.populateTransaction(transaction)
- const signedTx = await this.signTransaction(tx)
- return await (this.provider as ethers.providers.JsonRpcProvider).sendTransaction(signedTx)
+ const messageHex = ethers.utils.hexlify(message).substring(2)
+ const path = `m/44'/60'/${pathIndex}'/0/0`
+ const signature = await this.retry((eth) => eth.signPersonalMessage(path, messageHex))
+ console.log("signature :>> ", signature)
+ signature.r = "0x" + signature.r
+ signature.s = "0x" + signature.s
+ console.log("signature :>> ", signature)
+ return ethers.utils.joinSignature(signature)
+ }
+
+ async signTransaction(transaction: ethers.providers.TransactionRequest): Promise {
+ const tx = await ethers.utils.resolveProperties(transaction)
+ const baseTx: ethers.utils.UnsignedTransaction = {
+ chainId: (tx.chainId || undefined),
+ data: (tx.data || undefined),
+ gasLimit: (tx.gasLimit || undefined),
+ gasPrice: (tx.gasPrice || undefined),
+ nonce: (tx.nonce ? ethers.BigNumber.from(tx.nonce).toNumber() : undefined),
+ to: (tx.to || undefined),
+ value: (tx.value || undefined),
+ type: (tx.type || undefined)
}
- connect(provider: ethers.providers.Provider): ethers.Signer {
- const options = {
- provider,
- type: this.type,
- path: this.path
- }
- return new EthersLedgerSigner(options)
+ const unsignedTx = ethers.utils.serializeTransaction(baseTx).substring(2)
+ const resolution = await ledgerService.resolveTransaction(unsignedTx, {}, {})
+ const signature = await this.retry((eth) => eth.signTransaction(this.path, unsignedTx, resolution))
+
+ return ethers.utils.serializeTransaction(baseTx, {
+ v: ethers.BigNumber.from("0x" + signature.v).toNumber(),
+ r: ("0x" + signature.r),
+ s: ("0x" + signature.s),
+ })
+ }
+
+ // Populates all fields in a transaction, signs it and sends it to the network
+ async sendTransaction(transaction: ethers.utils.Deferrable): Promise {
+ this._checkProvider("sendTransaction")
+ const tx = await this.populateTransaction(transaction)
+ const signedTx = await this.signTransaction(tx)
+ return await (this.provider as ethers.providers.JsonRpcProvider).sendTransaction(signedTx)
+ }
+
+ connect(provider: ethers.providers.Provider): ethers.Signer {
+ const options = {
+ provider,
+ type: this.type,
+ path: this.path
}
+ return new EthersLedgerSigner(options)
+ }
}
\ No newline at end of file
diff --git a/common/wallets/src/providers/trezor.ts b/common/wallets/src/providers/trezor.ts
index 689847b2b..6053ae474 100644
--- a/common/wallets/src/providers/trezor.ts
+++ b/common/wallets/src/providers/trezor.ts
@@ -1,6 +1,6 @@
-import { ethers } from 'ethers'
-import TrezorConnect, { Address, EthereumTransaction, EthereumSignedTx } from '@trezor/connect-web'
-import { CryptoAddress } from '@casimir/types'
+import { ethers } from "ethers"
+import TrezorConnect, { Address, EthereumTransaction, EthereumSignedTx } from "@trezor/connect-web"
+import { CryptoAddress } from "@casimir/types"
export interface TrezorMessageSignature {
address: string
@@ -12,136 +12,136 @@ export interface TrezorSignerOptions {
path?: string
}
-TrezorConnect.manifest({ email: 'support@consensusnetworks.com', appUrl: 'casimir.co' })
+TrezorConnect.manifest({ email: "support@consensusnetworks.com", appUrl: "casimir.co" })
export class EthersTrezorSigner extends ethers.Signer {
- readonly path: string = 'm/44\'/60\'/0\'/0/0'
- readonly eth = TrezorConnect
+ readonly path: string = "m/44'/60'/0'/0/0"
+ readonly eth = TrezorConnect
- constructor(options: TrezorSignerOptions) {
- super()
+ constructor(options: TrezorSignerOptions) {
+ super()
- /** Override readonly wallet path */
- if (options.path) this.path = options.path
+ /** Override readonly wallet path */
+ if (options.path) this.path = options.path
- // Override readonly provider for ethers.Signer
- if (options.provider) {
- ethers.utils.defineReadOnly(this, 'provider', options.provider)
- }
-
+ // Override readonly provider for ethers.Signer
+ if (options.provider) {
+ ethers.utils.defineReadOnly(this, "provider", options.provider)
}
- async getAddress(): Promise {
- const { payload } = await this.eth.ethereumGetAddress({ path: this.path })
- const { address } = payload as Address
- return ethers.utils.getAddress(address)
+ }
+
+ async getAddress(): Promise {
+ const { payload } = await this.eth.ethereumGetAddress({ path: this.path })
+ const { address } = payload as Address
+ return ethers.utils.getAddress(address)
+ }
+
+ async getAddresses(): Promise> {
+ const trezorAddresses = []
+ const bundle = []
+ for (let i = 0; i < 5; i++) {
+ // TODO: Figure out how to access Goerli derivation paths
+ // m/coin_type'/account_index'/external_chain_index'/address_index/change_index
+ // const path = `m/44'/60'/${i}'/0/0` // Mainnet
+ // const path = `m/44'/1'/${i}'/0/0` // Ropsten
+ const path = `m/44'/60'/${i}'/0/0` // Goerli?
+ bundle.push({ path, showOnTrezor: false })
}
-
- async getAddresses(): Promise> {
- const trezorAddresses = []
- const bundle = []
- for (let i = 0; i < 5; i++) {
- // TODO: Figure out how to access Goerli derivation paths
- // m/coin_type'/account_index'/external_chain_index'/address_index/change_index
- // const path = `m/44'/60'/${i}'/0/0` // Mainnet
- // const path = `m/44'/1'/${i}'/0/0` // Ropsten
- const path = `m/44'/60'/${i}'/0/0` // Goerli?
- bundle.push({ path, showOnTrezor: false })
- }
- const { payload } = await this.eth.ethereumGetAddress({ bundle }) as any
+ const { payload } = await this.eth.ethereumGetAddress({ bundle }) as any
- for (let i = 0; i < payload.length; i++) {
- const { address } = payload[i]
- // TODO: Replace with our own provider depending on environment
- const provider = new ethers.providers.JsonRpcProvider('https://goerli.infura.io/v3/4e8acb4e58bb4cb9978ac4a22f3326a7')
- const modifiedAddress = address.toLowerCase().trim()
- const balance = await provider.getBalance(modifiedAddress)
- const ethBalance = ethers.utils.formatEther(balance)
- // if (parseFloat(ethBalance) > 0) trezorAddresses.push({ address, balance: ethBalance, index: i.toString() }) // TODO: Uncomment this line; it is currently commented out for testing
- trezorAddresses.push({ address, balance: ethBalance, pathIndex: i.toString() }) // TODO: Remove this line; it is currently for testing
- }
- return trezorAddresses.length ? trezorAddresses : []
+ for (let i = 0; i < payload.length; i++) {
+ const { address } = payload[i]
+ // TODO: Replace with our own provider depending on environment
+ const provider = new ethers.providers.JsonRpcProvider("https://goerli.infura.io/v3/4e8acb4e58bb4cb9978ac4a22f3326a7")
+ const modifiedAddress = address.toLowerCase().trim()
+ const balance = await provider.getBalance(modifiedAddress)
+ const ethBalance = ethers.utils.formatEther(balance)
+ // if (parseFloat(ethBalance) > 0) trezorAddresses.push({ address, balance: ethBalance, index: i.toString() }) // TODO: Uncomment this line; it is currently commented out for testing
+ trezorAddresses.push({ address, balance: ethBalance, pathIndex: i.toString() }) // TODO: Remove this line; it is currently for testing
}
-
- async signMessage(message: ethers.utils.Bytes | string): Promise {
- if (typeof(message) === 'string') message = ethers.utils.toUtf8Bytes(message)
- const messageHex = ethers.utils.hexlify(message).substring(2)
- const { payload } = await this.eth.ethereumSignMessage({ path: this.path, message: messageHex, hex: true})
- const { signature } = payload as TrezorMessageSignature
- return signature
- }
-
- async signMessageWithIndex(message: ethers.utils.Bytes | string, pathIndex: number): Promise {
- if (typeof (message) === 'string') message = ethers.utils.toUtf8Bytes(message)
- const messageHex = ethers.utils.hexlify(message).substring(2)
- const path = `m/44'/60'/${pathIndex}'/0/0`
- const { payload } = await this.eth.ethereumSignMessage({ path, message: messageHex, hex: true})
- const { signature } = payload as TrezorMessageSignature
- const convertedSignature = convertSignature(signature)
- return convertedSignature
+ return trezorAddresses.length ? trezorAddresses : []
+ }
+
+ async signMessage(message: ethers.utils.Bytes | string): Promise {
+ if (typeof(message) === "string") message = ethers.utils.toUtf8Bytes(message)
+ const messageHex = ethers.utils.hexlify(message).substring(2)
+ const { payload } = await this.eth.ethereumSignMessage({ path: this.path, message: messageHex, hex: true })
+ const { signature } = payload as TrezorMessageSignature
+ return signature
+ }
+
+ async signMessageWithIndex(message: ethers.utils.Bytes | string, pathIndex: number): Promise {
+ if (typeof (message) === "string") message = ethers.utils.toUtf8Bytes(message)
+ const messageHex = ethers.utils.hexlify(message).substring(2)
+ const path = `m/44'/60'/${pathIndex}'/0/0`
+ const { payload } = await this.eth.ethereumSignMessage({ path, message: messageHex, hex: true })
+ const { signature } = payload as TrezorMessageSignature
+ const convertedSignature = convertSignature(signature)
+ return convertedSignature
+ }
+
+ async signTransaction(transaction: ethers.providers.TransactionRequest): Promise {
+ transaction.value = ethers.BigNumber.from(transaction.value).toHexString()
+ transaction.gasLimit = ethers.BigNumber.from(transaction.gasLimit).toHexString()
+ transaction.gasPrice = ethers.BigNumber.from(transaction.gasPrice).toHexString()
+ transaction.nonce = ethers.BigNumber.from(transaction.nonce).toHexString()
+
+ const unsignedTx: EthereumTransaction = {
+ to: transaction.to as string,
+ value: transaction.value as string,
+ data: transaction.data as string | undefined,
+ chainId: transaction.chainId as number,
+ nonce: transaction.nonce as string,
+ gasLimit: transaction.gasLimit as string,
+ gasPrice: transaction.gasPrice as string,
+ // Todo fix type
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ type: transaction.type as number
}
- async signTransaction(transaction: ethers.providers.TransactionRequest): Promise {
- transaction.value = ethers.BigNumber.from(transaction.value).toHexString()
- transaction.gasLimit = ethers.BigNumber.from(transaction.gasLimit).toHexString()
- transaction.gasPrice = ethers.BigNumber.from(transaction.gasPrice).toHexString()
- transaction.nonce = ethers.BigNumber.from(transaction.nonce).toHexString()
-
- const unsignedTx: EthereumTransaction = {
- to: transaction.to as string,
- value: transaction.value as string,
- data: transaction.data as string | undefined,
- chainId: transaction.chainId as number,
- nonce: transaction.nonce as string,
- gasLimit: transaction.gasLimit as string,
- gasPrice: transaction.gasPrice as string,
- // Todo fix type
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- type: transaction.type as number
- }
-
- const ethereumSignedTransaction = await this.eth.ethereumSignTransaction({ path: this.path, transaction: unsignedTx })
- const { payload } = ethereumSignedTransaction
+ const ethereumSignedTransaction = await this.eth.ethereumSignTransaction({ path: this.path, transaction: unsignedTx })
+ const { payload } = ethereumSignedTransaction
- const signature = payload as EthereumSignedTx
- const baseTx: ethers.utils.UnsignedTransaction = {
- ...unsignedTx,
- nonce: ethers.BigNumber.from(transaction.nonce).toNumber(),
- }
-
- const signedTransaction = ethers.utils.serializeTransaction(baseTx, {
- v: ethers.BigNumber.from(signature.v).toNumber(),
- r: signature.r,
- s: signature.s,
- })
- return signedTransaction
+ const signature = payload as EthereumSignedTx
+ const baseTx: ethers.utils.UnsignedTransaction = {
+ ...unsignedTx,
+ nonce: ethers.BigNumber.from(transaction.nonce).toNumber(),
}
- async sendTransaction(transaction: ethers.utils.Deferrable): Promise {
- this._checkProvider('sendTransaction')
-
- transaction.gasLimit = await this?.provider?.estimateGas(transaction)
- transaction.gasPrice = await this?.provider?.getGasPrice()
- transaction.nonce = await this?.provider?.getTransactionCount(await this.getAddress())
- transaction.chainId = 1337
-
- const signedTx = await this.signTransaction(transaction as ethers.providers.TransactionRequest)
- return await (this.provider as ethers.providers.JsonRpcProvider).sendTransaction(signedTx)
- }
+ const signedTransaction = ethers.utils.serializeTransaction(baseTx, {
+ v: ethers.BigNumber.from(signature.v).toNumber(),
+ r: signature.r,
+ s: signature.s,
+ })
+ return signedTransaction
+ }
- connect(provider: ethers.providers.Provider): ethers.Signer {
- const options = {
- provider,
- path: this.path
- }
- return new EthersTrezorSigner(options)
+ async sendTransaction(transaction: ethers.utils.Deferrable): Promise {
+ this._checkProvider("sendTransaction")
+
+ transaction.gasLimit = await this?.provider?.estimateGas(transaction)
+ transaction.gasPrice = await this?.provider?.getGasPrice()
+ transaction.nonce = await this?.provider?.getTransactionCount(await this.getAddress())
+ transaction.chainId = 1337
+
+ const signedTx = await this.signTransaction(transaction as ethers.providers.TransactionRequest)
+ return await (this.provider as ethers.providers.JsonRpcProvider).sendTransaction(signedTx)
+ }
+
+ connect(provider: ethers.providers.Provider): ethers.Signer {
+ const options = {
+ provider,
+ path: this.path
}
+ return new EthersTrezorSigner(options)
+ }
}
function convertSignature(signature: string): string {
- const r = '0x' + signature.slice(0, 64)
- const s = '0x' + signature.slice(64, 128)
- const v = parseInt('0x' + signature.slice(128, 130), 16)
- return ethers.utils.joinSignature({ r, s, v })
+ const r = "0x" + signature.slice(0, 64)
+ const s = "0x" + signature.slice(64, 128)
+ const v = parseInt("0x" + signature.slice(128, 130), 16)
+ return ethers.utils.joinSignature({ r, s, v })
}
\ No newline at end of file
diff --git a/common/wallets/src/providers/walletConnect.ts b/common/wallets/src/providers/walletConnect.ts
index 23d28ee2e..83bcc347a 100644
--- a/common/wallets/src/providers/walletConnect.ts
+++ b/common/wallets/src/providers/walletConnect.ts
@@ -1,64 +1,64 @@
// import { EthereumProvider } from '@walletconnect/ethereum-provider'
-import { Web3Modal } from '@web3modal/standalone'
-import UniversalProvider from '@walletconnect/universal-provider'
-import Client from '@walletconnect/sign-client'
+import { Web3Modal } from "@web3modal/standalone"
+import UniversalProvider from "@walletconnect/universal-provider"
+import Client from "@walletconnect/sign-client"
-import { ethers, providers, utils } from 'ethers'
-const DEFAULT_PROJECT_ID = '8e6877b49198d7a9f9561b8712805726'
-const DEFAULT_RELAY_URL = 'wss://relay.walletconnect.com'
-const DEFAULT_LOGGER = 'warn'
+import { ethers, providers, utils } from "ethers"
+const DEFAULT_PROJECT_ID = "8e6877b49198d7a9f9561b8712805726"
+const DEFAULT_RELAY_URL = "wss://relay.walletconnect.com"
+const DEFAULT_LOGGER = "warn"
interface WalletAddressSignerOptions {
provider?: ethers.providers.Provider
}
export class EthersWalletConnectSigner extends ethers.Signer {
- private _ethereumProvider: UniversalProvider
- private _web3Provider: providers.Web3Provider
+ private _ethereumProvider: UniversalProvider
+ private _web3Provider: providers.Web3Provider
- private constructor(options: WalletAddressSignerOptions, ethereumProvider: UniversalProvider, web3Provider: providers.Web3Provider) {
- super()
+ private constructor(options: WalletAddressSignerOptions, ethereumProvider: UniversalProvider, web3Provider: providers.Web3Provider) {
+ super()
- this._ethereumProvider = ethereumProvider
- this._web3Provider = web3Provider
+ this._ethereumProvider = ethereumProvider
+ this._web3Provider = web3Provider
- if (options.provider) {
- console.log('got to options.provider')
- ethers.utils.defineReadOnly(this, 'provider', options.provider)
- } else {
- console.log('web3Provider in !options.provider :>> ', web3Provider)
- console.log('ethereumProvider :>> ', ethereumProvider)
- ethers.utils.defineReadOnly(this, 'provider', web3Provider)
- }
+ if (options.provider) {
+ console.log("got to options.provider")
+ ethers.utils.defineReadOnly(this, "provider", options.provider)
+ } else {
+ console.log("web3Provider in !options.provider :>> ", web3Provider)
+ console.log("ethereumProvider :>> ", ethereumProvider)
+ ethers.utils.defineReadOnly(this, "provider", web3Provider)
}
+ }
- static async create(options: WalletAddressSignerOptions): Promise {
- const ethereumProvider = await UniversalProvider.init({
- projectId: DEFAULT_PROJECT_ID,
- logger: DEFAULT_LOGGER,
- relayUrl: DEFAULT_RELAY_URL,
- })
+ static async create(options: WalletAddressSignerOptions): Promise {
+ const ethereumProvider = await UniversalProvider.init({
+ projectId: DEFAULT_PROJECT_ID,
+ logger: DEFAULT_LOGGER,
+ relayUrl: DEFAULT_RELAY_URL,
+ })
- const web3Provider = new providers.Web3Provider(ethereumProvider)
+ const web3Provider = new providers.Web3Provider(ethereumProvider)
- return new EthersWalletConnectSigner(options, ethereumProvider, web3Provider)
- }
+ return new EthersWalletConnectSigner(options, ethereumProvider, web3Provider)
+ }
- async getAddress(): Promise {
- return '0x'
- }
+ async getAddress(): Promise {
+ return "0x"
+ }
- async signMessage(message: string | ethers.Bytes): Promise {
- return '0x'
- }
+ async signMessage(message: string | ethers.Bytes): Promise {
+ return "0x"
+ }
- async signTransaction(tx: ethers.providers.TransactionRequest): Promise {
- return '0x'
- }
+ async signTransaction(tx: ethers.providers.TransactionRequest): Promise {
+ return "0x"
+ }
- connect(provider: ethers.providers.Provider): ethers.Signer {
- return new EthersWalletConnectSigner()
- }
+ connect(provider: ethers.providers.Provider): ethers.Signer {
+ return new EthersWalletConnectSigner()
+ }
}
diff --git a/contracts/ethereum/hardhat.config.ts b/contracts/ethereum/hardhat.config.ts
index 88c3b25c2..33cfcd184 100644
--- a/contracts/ethereum/hardhat.config.ts
+++ b/contracts/ethereum/hardhat.config.ts
@@ -1,15 +1,15 @@
-import os from 'os'
-import localtunnel from 'localtunnel'
-import { HardhatUserConfig } from 'hardhat/types'
-import '@typechain/hardhat'
-import '@nomiclabs/hardhat-ethers'
-import '@nomicfoundation/hardhat-toolbox'
-import '@openzeppelin/hardhat-upgrades'
-import 'hardhat-abi-exporter'
-import 'hardhat-contract-sizer'
-import 'solidity-docgen'
+import os from "os"
+import localtunnel from "localtunnel"
+import { HardhatUserConfig } from "hardhat/types"
+import "@typechain/hardhat"
+import "@nomiclabs/hardhat-ethers"
+import "@nomicfoundation/hardhat-toolbox"
+import "@openzeppelin/hardhat-upgrades"
+import "hardhat-abi-exporter"
+import "hardhat-contract-sizer"
+import "solidity-docgen"
// import '@tenderly/hardhat-tenderly'
-import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL, HARDHAT_NETWORK_KEY } from '@casimir/env'
+import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL, HARDHAT_NETWORK_KEY } from "@casimir/env"
// Seed is provided
const mnemonic = process.env.BIP39_SEED as string
@@ -23,12 +23,12 @@ const hardhatNetwork = process.env.HARDHAT_NETWORK as string
// Local network fork rpc url overrides live network
const forkUrl = process.env.ETHEREUM_FORK_RPC_URL as string
-const forkNetwork = forkUrl?.includes('mainnet') ? 'mainnet' : 'goerli'
+const forkNetwork = forkUrl?.includes("mainnet") ? "mainnet" : "goerli"
const forkChainId = { mainnet: 1, goerli: 5 }[forkNetwork]
-const forkConfig = { url: forkUrl, blockNumber: parseInt(process.env.ETHEREUM_FORK_BLOCK || '0') || undefined }
+const forkConfig = { url: forkUrl, blockNumber: parseInt(process.env.ETHEREUM_FORK_BLOCK || "0") || undefined }
const hardhatKey = hardhatNetwork?.toUpperCase() as keyof typeof HARDHAT_NETWORK_KEY
-const networkKey = HARDHAT_NETWORK_KEY[hardhatKey] || 'TESTNET'
+const networkKey = HARDHAT_NETWORK_KEY[hardhatKey] || "TESTNET"
process.env.ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL || ETHEREUM_RPC_URL[networkKey]
process.env.FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey].FACTORY_ADDRESS
@@ -53,101 +53,105 @@ process.env.SWAP_ROUTER_ADDRESS = ETHEREUM_CONTRACTS[networkKey].SWAP_ROUTER_ADD
process.env.WETH_TOKEN_ADDRESS = ETHEREUM_CONTRACTS[networkKey].WETH_TOKEN_ADDRESS
const compilerSettings = {
- viaIR: true,
- optimizer: {
- enabled: true
- }
+ viaIR: true,
+ optimizer: {
+ enabled: true
+ }
}
-const compilerVersions = ['0.8.18']
-const externalCompilerVersions = ['0.4.22', '0.4.24', '0.6.6', '0.6.11', '0.8.4']
+const compilerVersions = ["0.8.18"]
+const externalCompilerVersions = ["0.4.22",
+ "0.4.24",
+ "0.6.6",
+ "0.6.11",
+ "0.8.4"]
const compilers = [...compilerVersions, ...externalCompilerVersions].map(version => ({ version, settings: compilerSettings }))
// Go to https://hardhat.org/config/ to learn more
const config: HardhatUserConfig = {
- etherscan: {
- apiKey: 'XZCVTJSMVTZ78RYAHDAUXDPRSFW8NKIGW9'
- },
- mocha: {
- timeout: 60000
- },
- solidity: {
- compilers,
- },
- paths: {
- tests: './test',
- sources: './src/v1',
- artifacts: './build/artifacts',
- cache: './build/cache'
+ etherscan: {
+ apiKey: "XZCVTJSMVTZ78RYAHDAUXDPRSFW8NKIGW9"
+ },
+ mocha: {
+ timeout: 60000
+ },
+ solidity: {
+ compilers,
+ },
+ paths: {
+ tests: "./test",
+ sources: "./src/v1",
+ artifacts: "./build/artifacts",
+ cache: "./build/cache"
+ },
+ abiExporter: {
+ path: "./build/abi",
+ runOnCompile: true,
+ clear: true,
+ flat: true,
+ spacing: 4,
+ format: "fullName"
+ },
+ typechain: {
+ outDir: "./build/@types"
+ },
+ docgen: {
+ exclude: [
+ "dev",
+ "libraries",
+ "mock",
+ "vendor"
+ ],
+ outputDir: process.env.DOCS_OUTPUT_DIR || "./build/docs",
+ templates: process.env.DOCS_TEMPLATE_DIR,
+ pages: () => "solidity-api.md"
+ },
+ networks: {
+ hardhat: {
+ accounts: mnemonic ? hid : undefined,
+ chainId: forkChainId || 1337,
+ forking: forkUrl ? forkConfig : undefined,
+ mining: miningInterval ? mining : { auto: true },
+ allowUnlimitedContractSize: true,
+ gas: "auto",
+ gasPrice: "auto"
},
- abiExporter: {
- path: './build/abi',
- runOnCompile: true,
- clear: true,
- flat: true,
- spacing: 4,
- format: 'fullName'
+ mainnet: {
+ accounts: mnemonic ? hid : undefined,
+ url: process.env.ETHEREUM_RPC_URL || "",
+ allowUnlimitedContractSize: true,
+ gas: "auto",
+ gasPrice: "auto"
},
- typechain: {
- outDir: './build/@types'
- },
- docgen: {
- exclude: [
- 'dev',
- 'libraries',
- 'mock',
- 'vendor'
- ],
- outputDir: process.env.DOCS_OUTPUT_DIR || './build/docs',
- templates: process.env.DOCS_TEMPLATE_DIR,
- pages: () => 'solidity-api.md'
- },
- networks: {
- hardhat: {
- accounts: mnemonic ? hid : undefined,
- chainId: forkChainId || 1337,
- forking: forkUrl ? forkConfig : undefined,
- mining: miningInterval ? mining : { auto: true },
- allowUnlimitedContractSize: true,
- gas: 'auto',
- gasPrice: 'auto'
- },
- mainnet: {
- accounts: mnemonic ? hid : undefined,
- url: process.env.ETHEREUM_RPC_URL || '',
- allowUnlimitedContractSize: true,
- gas: 'auto',
- gasPrice: 'auto'
- },
- goerli: {
- accounts: mnemonic ? hid : undefined,
- url: process.env.ETHEREUM_RPC_URL || '',
- allowUnlimitedContractSize: true,
- gas: 'auto',
- gasPrice: 'auto'
- }
+ goerli: {
+ accounts: mnemonic ? hid : undefined,
+ url: process.env.ETHEREUM_RPC_URL || "",
+ allowUnlimitedContractSize: true,
+ gas: "auto",
+ gasPrice: "auto"
}
+ }
}
// Start a local tunnel for using RPC over https (e.g. for Metamask on mobile)
-if (process.env.TUNNEL === 'true') {
- runLocalTunnel()
+if (process.env.TUNNEL === "true") {
+ runLocalTunnel()
}
function runLocalTunnel() {
- const localSubdomain = `local-hardhat-${os.userInfo().username.toLowerCase()}`
- const localUrl = `https://${localSubdomain}.loca.lt`
- localtunnel({ port: 8545, subdomain: localSubdomain }).then(
- (tunnel: localtunnel.Tunnel) => {
- if (localUrl === tunnel.url) {
- console.log('Your default local tunnel url is', localUrl)
- } else {
- console.log('Your default local tunnel url is not available, use', tunnel.url, 'instead')
- }
- process.on('SIGINT', () => {
- tunnel.close()
- })
- }
- )
+ const localSubdomain = `local-hardhat-${os.userInfo().username.toLowerCase()}`
+ const localUrl = `https://${localSubdomain}.loca.lt`
+ localtunnel({ port: 8545, subdomain: localSubdomain }).then(
+ (tunnel: localtunnel.Tunnel) => {
+ if (localUrl === tunnel.url) {
+ console.log("Your default local tunnel url is", localUrl)
+ } else {
+ console.log("Your default local tunnel url is not available, use", tunnel.url, "instead")
+ }
+ process.on("SIGINT", () => {
+ tunnel.close()
+ })
+ }
+ )
}
export default config
\ No newline at end of file
diff --git a/contracts/ethereum/helpers/math.ts b/contracts/ethereum/helpers/math.ts
index e72ac9769..9126e8310 100644
--- a/contracts/ethereum/helpers/math.ts
+++ b/contracts/ethereum/helpers/math.ts
@@ -1,4 +1,4 @@
export function round(num: number, decimals: number | undefined = 1) {
- const multiplier = Math.pow(10, decimals)
- return Math.round(num * multiplier) / multiplier
+ const multiplier = Math.pow(10, decimals)
+ return Math.round(num * multiplier) / multiplier
}
\ No newline at end of file
diff --git a/contracts/ethereum/helpers/network.ts b/contracts/ethereum/helpers/network.ts
index a618ff4bf..9900f8801 100644
--- a/contracts/ethereum/helpers/network.ts
+++ b/contracts/ethereum/helpers/network.ts
@@ -1,14 +1,14 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export async function waitForNetwork(provider: ethers.providers.JsonRpcProvider) {
- let networkReady = false
- while (!networkReady) {
- try {
- await provider.getBlockNumber()
- networkReady = true
- } catch (error) {
- console.log('Waiting for network to start...')
- await new Promise(resolve => setTimeout(resolve, 1000))
- }
+ let networkReady = false
+ while (!networkReady) {
+ try {
+ await provider.getBlockNumber()
+ networkReady = true
+ } catch (error) {
+ console.log("Waiting for network to start...")
+ await new Promise(resolve => setTimeout(resolve, 1000))
}
+ }
}
\ No newline at end of file
diff --git a/contracts/ethereum/helpers/oracle.ts b/contracts/ethereum/helpers/oracle.ts
index 4fe5e822d..5b94f420c 100644
--- a/contracts/ethereum/helpers/oracle.ts
+++ b/contracts/ethereum/helpers/oracle.ts
@@ -1,297 +1,302 @@
-import { ethers } from 'hardhat'
-import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
-import { CasimirManager, CasimirViews } from '../build/@types'
-import { PoolStatus, Reshare, Validator } from '@casimir/types'
-import { Scanner } from '@casimir/ssv'
-import { Factory } from '@casimir/uniswap'
-import { MOCK_VALIDATORS, MOCK_RESHARES } from '@casimir/env'
+import { ethers } from "hardhat"
+import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"
+import { CasimirManager, CasimirViews } from "../build/@types"
+import { PoolStatus, Reshare, Validator } from "@casimir/types"
+import { Scanner } from "@casimir/ssv"
+import { Factory } from "@casimir/uniswap"
+import { MOCK_VALIDATORS, MOCK_RESHARES } from "@casimir/env"
const linkTokenAddress = process.env.LINK_TOKEN_ADDRESS as string
-if (!linkTokenAddress) throw new Error('No link token address provided')
+if (!linkTokenAddress) throw new Error("No link token address provided")
const ssvNetworkAddress = process.env.SSV_NETWORK_ADDRESS as string
-if (!ssvNetworkAddress) throw new Error('No ssv network address provided')
+if (!ssvNetworkAddress) throw new Error("No ssv network address provided")
const ssvViewsAddress = process.env.SSV_VIEWS_ADDRESS as string
-if (!ssvViewsAddress) throw new Error('No ssv views address provided')
+if (!ssvViewsAddress) throw new Error("No ssv views address provided")
const ssvTokenAddress = process.env.SSV_TOKEN_ADDRESS as string
-if (!ssvTokenAddress) throw new Error('No ssv token address provided')
+if (!ssvTokenAddress) throw new Error("No ssv token address provided")
const uniswapV3FactoryAddress = process.env.SWAP_FACTORY_ADDRESS as string
-if (!uniswapV3FactoryAddress) throw new Error('No uniswap v3 factory address provided')
+if (!uniswapV3FactoryAddress) throw new Error("No uniswap v3 factory address provided")
const wethTokenAddress = process.env.WETH_TOKEN_ADDRESS as string
-if (!wethTokenAddress) throw new Error('No weth token address provided')
+if (!wethTokenAddress) throw new Error("No weth token address provided")
export async function initiatePoolHandler({ manager, signer }: { manager: CasimirManager, signer: SignerWithAddress }) {
- const mockValidators: Validator[] = MOCK_VALIDATORS[signer.address as keyof typeof MOCK_VALIDATORS]
- const nonce = await ethers.provider.getTransactionCount(manager.address)
- const poolAddress = ethers.utils.getContractAddress({
- from: manager.address,
- nonce
- })
- const poolWithdrawalCredentials = '0x' + '01' + '0'.repeat(22) + poolAddress.split('0x')[1]
- const validator = mockValidators.find((validator) => {
- return validator.withdrawalCredentials.toLowerCase() === poolWithdrawalCredentials.toLowerCase()
- })
- if (!validator) throw new Error(`No validator found for withdrawal credentials ${poolWithdrawalCredentials}`)
+ const mockValidators: Validator[] = MOCK_VALIDATORS[signer.address as keyof typeof MOCK_VALIDATORS]
+ const nonce = await ethers.provider.getTransactionCount(manager.address)
+ const poolAddress = ethers.utils.getContractAddress({
+ from: manager.address,
+ nonce
+ })
+ const poolWithdrawalCredentials = "0x" + "01" + "0".repeat(22) + poolAddress.split("0x")[1]
+ const validator = mockValidators.find((validator) => {
+ return validator.withdrawalCredentials.toLowerCase() === poolWithdrawalCredentials.toLowerCase()
+ })
+ if (!validator) throw new Error(`No validator found for withdrawal credentials ${poolWithdrawalCredentials}`)
- const {
- depositDataRoot,
- publicKey,
- signature,
- withdrawalCredentials,
- operatorIds,
- shares,
- } = validator
-
- const initiatePool = await manager.connect(signer).initiatePool(
- depositDataRoot,
- publicKey,
- signature,
- withdrawalCredentials,
- operatorIds,
- shares
- )
- await initiatePool.wait()
+ const {
+ depositDataRoot,
+ publicKey,
+ signature,
+ withdrawalCredentials,
+ operatorIds,
+ shares,
+ } = validator
+
+ const initiatePool = await manager.connect(signer).initiatePool(
+ depositDataRoot,
+ publicKey,
+ signature,
+ withdrawalCredentials,
+ operatorIds,
+ shares
+ )
+ await initiatePool.wait()
}
export async function activatePoolsHandler({ manager, views, signer, args }: { manager: CasimirManager, views: CasimirViews, signer: SignerWithAddress, args: Record }) {
- const count = args.count as number
- if (!count) throw new Error('No count provided')
+ const count = args.count as number
+ if (!count) throw new Error("No count provided")
- for (let i = 0; i < count; i++) {
- const pendingPoolIds = await manager.getPendingPoolIds()
- if (!pendingPoolIds.length) throw new Error('No pending pools')
+ for (let i = 0; i < count; i++) {
+ const pendingPoolIds = await manager.getPendingPoolIds()
+ if (!pendingPoolIds.length) throw new Error("No pending pools")
- /**
+ /**
* In production, we check the pending pool status on Beacon before activating
* Here, we're just grabbing the next pending pool
*/
- const pendingPoolIndex = 0
- const poolId = pendingPoolIds[pendingPoolIndex]
- const poolConfig = await views.getPoolConfig(poolId)
- const operatorIds = poolConfig.operatorIds.map((operatorId) => operatorId.toNumber())
-
- const scanner = new Scanner({
- provider: ethers.provider,
- ssvNetworkAddress,
- ssvViewsAddress
- })
+ const pendingPoolIndex = 0
+ const poolId = pendingPoolIds[pendingPoolIndex]
+ const poolConfig = await views.getPoolConfig(poolId)
+ const operatorIds = poolConfig.operatorIds.map((operatorId) => operatorId.toNumber())
+
+ const scanner = new Scanner({
+ provider: ethers.provider,
+ ssvNetworkAddress,
+ ssvViewsAddress
+ })
- const cluster = await scanner.getCluster({
- ownerAddress: manager.address,
- operatorIds
- })
+ const cluster = await scanner.getCluster({
+ ownerAddress: manager.address,
+ operatorIds
+ })
- const requiredFee = await scanner.getRequiredFee(operatorIds)
+ const requiredFee = await scanner.getRequiredFee(operatorIds)
- const uniswapFactory = new Factory({
- provider: ethers.provider,
- uniswapV3FactoryAddress
- })
+ const uniswapFactory = new Factory({
+ provider: ethers.provider,
+ uniswapV3FactoryAddress
+ })
- const price = await uniswapFactory.getSwapPrice({
- tokenIn: wethTokenAddress,
- tokenOut: ssvTokenAddress,
- uniswapFeeTier: 3000
- })
+ const price = await uniswapFactory.getSwapPrice({
+ tokenIn: wethTokenAddress,
+ tokenOut: ssvTokenAddress,
+ uniswapFeeTier: 3000
+ })
- const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee)) * price).toPrecision(9))
- const minTokenAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee)) * 0.99).toPrecision(9))
+ const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee)) * price).toPrecision(9))
+ const minTokenAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee)) * 0.99).toPrecision(9))
- const activatePool = await manager.connect(signer).activatePool(
- pendingPoolIndex,
- cluster,
- feeAmount,
- minTokenAmount,
- false
- )
- await activatePool.wait()
- }
+ const activatePool = await manager.connect(signer).activatePool(
+ pendingPoolIndex,
+ cluster,
+ feeAmount,
+ minTokenAmount,
+ false
+ )
+ await activatePool.wait()
+ }
}
export async function resharePoolHandler({ manager, views, signer, args }: { manager: CasimirManager, views: CasimirViews, signer: SignerWithAddress, args: Record }) {
- const operatorId = args.operatorId as number
- if (!operatorId) throw new Error('No operator id provided')
+ const operatorId = args.operatorId as number
+ if (!operatorId) throw new Error("No operator id provided")
- const poolIds = [
- ...await manager.getPendingPoolIds(),
- ...await manager.getStakedPoolIds()
- ]
-
- for (const poolId of poolIds) {
- const poolConfig = await views.getPoolConfig(poolId)
- const oldOperatorIds = poolConfig.operatorIds.map(id => id.toNumber())
- if (oldOperatorIds.includes(operatorId)) {
- const mockReshares: Reshare[] = MOCK_RESHARES[poolId as keyof typeof MOCK_RESHARES]
- const poolReshareCount = poolConfig.reshares.toNumber()
- if (mockReshares.length && poolReshareCount < 2) {
- const reshare = mockReshares.find((reshare) => {
- return JSON.stringify(reshare.oldOperatorIds) === JSON.stringify(oldOperatorIds)
- })
- if (!reshare) throw new Error(`No reshare found for pool ${poolId} with old operator ids ${oldOperatorIds}`)
-
- const newOperatorId = reshare.operatorIds.find((id) => !oldOperatorIds.includes(id)) as number
-
- const scanner = new Scanner({
- provider: ethers.provider,
- ssvNetworkAddress,
- ssvViewsAddress
- })
+ const poolIds = [
+ ...await manager.getPendingPoolIds(), ...await manager.getStakedPoolIds()
+ ]
+
+ for (const poolId of poolIds) {
+ const poolConfig = await views.getPoolConfig(poolId)
+ const oldOperatorIds = poolConfig.operatorIds.map(id => id.toNumber())
+ if (oldOperatorIds.includes(operatorId)) {
+ const mockReshares: Reshare[] = MOCK_RESHARES[poolId as keyof typeof MOCK_RESHARES]
+ const poolReshareCount = poolConfig.reshares.toNumber()
+ if (mockReshares.length && poolReshareCount < 2) {
+ const reshare = mockReshares.find((reshare) => {
+ return JSON.stringify(reshare.oldOperatorIds) === JSON.stringify(oldOperatorIds)
+ })
+ if (!reshare) throw new Error(`No reshare found for pool ${poolId} with old operator ids ${oldOperatorIds}`)
+
+ const newOperatorId = reshare.operatorIds.find((id) => !oldOperatorIds.includes(id)) as number
+
+ const scanner = new Scanner({
+ provider: ethers.provider,
+ ssvNetworkAddress,
+ ssvViewsAddress
+ })
- const oldCluster = await scanner.getCluster({
- operatorIds: oldOperatorIds,
- ownerAddress: manager.address
- })
+ const oldCluster = await scanner.getCluster({
+ operatorIds: oldOperatorIds,
+ ownerAddress: manager.address
+ })
- const cluster = await scanner.getCluster({
- operatorIds: reshare.operatorIds,
- ownerAddress: manager.address
- })
+ const cluster = await scanner.getCluster({
+ operatorIds: reshare.operatorIds,
+ ownerAddress: manager.address
+ })
- const requiredFee = await scanner.getRequiredFee(reshare.operatorIds)
+ const requiredFee = await scanner.getRequiredFee(reshare.operatorIds)
- const uniswapFactory = new Factory({
- provider: ethers.provider,
- uniswapV3FactoryAddress
- })
+ const uniswapFactory = new Factory({
+ provider: ethers.provider,
+ uniswapV3FactoryAddress
+ })
- const price = await uniswapFactory.getSwapPrice({
- tokenIn: wethTokenAddress,
- tokenOut: ssvTokenAddress,
- uniswapFeeTier: 3000
- })
+ const price = await uniswapFactory.getSwapPrice({
+ tokenIn: wethTokenAddress,
+ tokenOut: ssvTokenAddress,
+ uniswapFeeTier: 3000
+ })
- const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * Number(price)).toPrecision(9))
- const minTokenAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * 0.99).toPrecision(9))
-
- const reportReshare = await manager.connect(signer).resharePool(
- poolId,
- reshare.operatorIds,
- newOperatorId,
- operatorId,
- reshare.shares,
- cluster,
- oldCluster,
- feeAmount,
- minTokenAmount,
- false
- )
- await reportReshare.wait()
- } else {
- // Exit pool
- }
- }
+ const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * Number(price)).toPrecision(9))
+ const minTokenAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * 0.99).toPrecision(9))
+
+ const reportReshare = await manager.connect(signer).resharePool(
+ poolId,
+ reshare.operatorIds,
+ newOperatorId,
+ operatorId,
+ reshare.shares,
+ cluster,
+ oldCluster,
+ feeAmount,
+ minTokenAmount,
+ false
+ )
+ await reportReshare.wait()
+ } else {
+ // Exit pool
+ }
}
+ }
}
export async function depositFunctionsBalanceHandler({ manager, signer }: { manager: CasimirManager, signer: SignerWithAddress }) {
- /**
+ /**
* In production, we check the functions balance before reporting
* We can set processed to true if the manager has enough LINK tokens
* Here, we're just depositing double the Chainlink registration minimum
*/
- const requiredBalance = 5
-
- const uniswapFactory = new Factory({
- provider: ethers.provider,
- uniswapV3FactoryAddress
- })
-
- const price = await uniswapFactory.getSwapPrice({
- tokenIn: wethTokenAddress,
- tokenOut: linkTokenAddress,
- uniswapFeeTier: 3000
- })
-
- const feeAmount = ethers.utils.parseEther((requiredBalance * price).toPrecision(9))
- const minTokenAmount = ethers.utils.parseEther((requiredBalance * 0.99).toPrecision(9))
-
- const depositFunctionsBalance = await manager.connect(signer).depositFunctionsBalance(
- feeAmount,
- minTokenAmount,
- false
- )
- await depositFunctionsBalance.wait()
+ const requiredBalance = 5
+
+ const uniswapFactory = new Factory({
+ provider: ethers.provider,
+ uniswapV3FactoryAddress
+ })
+
+ const price = await uniswapFactory.getSwapPrice({
+ tokenIn: wethTokenAddress,
+ tokenOut: linkTokenAddress,
+ uniswapFeeTier: 3000
+ })
+
+ const feeAmount = ethers.utils.parseEther((requiredBalance * price).toPrecision(9))
+ const minTokenAmount = ethers.utils.parseEther((requiredBalance * 0.99).toPrecision(9))
+
+ const depositFunctionsBalance = await manager.connect(signer).depositFunctionsBalance(
+ feeAmount,
+ minTokenAmount,
+ false
+ )
+ await depositFunctionsBalance.wait()
}
export async function depositUpkeepBalanceHandler({ manager, signer }: { manager: CasimirManager, signer: SignerWithAddress }) {
- /**
+ /**
* In production, we check the upkeep balance before reporting
* We can set processed to true if the manager has enough LINK tokens
* Here, we're just depositing double the Chainlink registration minimum
*/
- const requiredBalance = 5
-
- const uniswapFactory = new Factory({
- provider: ethers.provider,
- uniswapV3FactoryAddress
- })
-
- const price = await uniswapFactory.getSwapPrice({
- tokenIn: wethTokenAddress,
- tokenOut: linkTokenAddress,
- uniswapFeeTier: 3000
- })
+ const requiredBalance = 5
+
+ const uniswapFactory = new Factory({
+ provider: ethers.provider,
+ uniswapV3FactoryAddress
+ })
+
+ const price = await uniswapFactory.getSwapPrice({
+ tokenIn: wethTokenAddress,
+ tokenOut: linkTokenAddress,
+ uniswapFeeTier: 3000
+ })
- const feeAmount = ethers.utils.parseEther((requiredBalance * price).toPrecision(9))
- const minTokenAmount = ethers.utils.parseEther((requiredBalance * 0.99).toPrecision(9))
-
- const depositUpkeepBalance = await manager.connect(signer).depositUpkeepBalance(
- feeAmount,
- minTokenAmount,
- false
- )
- await depositUpkeepBalance.wait()
+ const feeAmount = ethers.utils.parseEther((requiredBalance * price).toPrecision(9))
+ const minTokenAmount = ethers.utils.parseEther((requiredBalance * 0.99).toPrecision(9))
+
+ const depositUpkeepBalance = await manager.connect(signer).depositUpkeepBalance(
+ feeAmount,
+ minTokenAmount,
+ false
+ )
+ await depositUpkeepBalance.wait()
}
export async function reportCompletedExitsHandler({ manager, views, signer, args }: { manager: CasimirManager, views: CasimirViews, signer: SignerWithAddress, args: Record }) {
- const { count } = args
+ const { count } = args
- /**
+ /**
* In production, we get the completed exit order from Beacon (sorting by withdrawn epoch)
* We check all validators using:
* const stakedPublicKeys = await views.getStakedPublicKeys(startIndex, endIndex)
* Here, we're just grabbing the next exiting pool for each completed exit
*/
- const stakedPoolIds = await manager.getStakedPoolIds()
- let remaining = count
- let poolIndex = 0
- while (remaining > 0) {
- const poolId = stakedPoolIds[poolIndex]
- const poolConfig = await views.getPoolConfig(poolId)
- if (poolConfig.status === PoolStatus.EXITING_FORCED || poolConfig.status === PoolStatus.EXITING_REQUESTED) {
- remaining--
+ const stakedPoolIds = await manager.getStakedPoolIds()
+ let remaining = count
+ let poolIndex = 0
+ while (remaining > 0) {
+ const poolId = stakedPoolIds[poolIndex]
+ const poolConfig = await views.getPoolConfig(poolId)
+ if (poolConfig.status === PoolStatus.EXITING_FORCED || poolConfig.status === PoolStatus.EXITING_REQUESTED) {
+ remaining--
- /**
+ /**
* In production, we use the SSV performance data to determine blame
* We check all validators using:
* const stakedPublicKeys = await views.getStakedPublicKeys(startIndex, endIndex)
* Here, we're just hardcoding blame to the first operator if less than 32 ETH
*/
- const operatorIds = poolConfig.operatorIds.map((operatorId) => operatorId.toNumber())
-
- let blamePercents = [0, 0, 0, 0]
- if (poolConfig.balance.lt(ethers.utils.parseEther('32'))) {
- blamePercents = [100, 0, 0, 0]
- }
-
- const scanner = new Scanner({
- provider: ethers.provider,
- ssvNetworkAddress,
- ssvViewsAddress
- })
-
- const cluster = await scanner.getCluster({
- ownerAddress: manager.address,
- operatorIds
- })
-
- const reportCompletedExit = await manager.connect(signer).reportCompletedExit(
- poolIndex,
- blamePercents,
- cluster
- )
- await reportCompletedExit.wait()
- }
- poolIndex++
+ const operatorIds = poolConfig.operatorIds.map((operatorId) => operatorId.toNumber())
+
+ let blamePercents = [0,
+ 0,
+ 0,
+ 0]
+ if (poolConfig.balance.lt(ethers.utils.parseEther("32"))) {
+ blamePercents = [100,
+ 0,
+ 0,
+ 0]
+ }
+
+ const scanner = new Scanner({
+ provider: ethers.provider,
+ ssvNetworkAddress,
+ ssvViewsAddress
+ })
+
+ const cluster = await scanner.getCluster({
+ ownerAddress: manager.address,
+ operatorIds
+ })
+
+ const reportCompletedExit = await manager.connect(signer).reportCompletedExit(
+ poolIndex,
+ blamePercents,
+ cluster
+ )
+ await reportCompletedExit.wait()
}
+ poolIndex++
+ }
}
diff --git a/contracts/ethereum/helpers/upkeep.ts b/contracts/ethereum/helpers/upkeep.ts
index 61e2d89d7..6d086b164 100644
--- a/contracts/ethereum/helpers/upkeep.ts
+++ b/contracts/ethereum/helpers/upkeep.ts
@@ -1,24 +1,24 @@
-import { ethers } from 'hardhat'
-import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
-import { CasimirUpkeep, FunctionsBillingRegistry } from '../build/@types'
+import { ethers } from "hardhat"
+import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"
+import { CasimirUpkeep, FunctionsBillingRegistry } from "../build/@types"
export async function runUpkeep({
- donTransmitter, upkeep,
+ donTransmitter, upkeep,
}: {
donTransmitter: SignerWithAddress,
upkeep: CasimirUpkeep,
}) {
- let ranUpkeep = false
- const checkData = ethers.utils.toUtf8Bytes('0x')
- const { ...check } = await upkeep.connect(donTransmitter).checkUpkeep(checkData)
- const { upkeepNeeded } = check
- if (upkeepNeeded) {
- const performData = ethers.utils.toUtf8Bytes('0x')
- const performUpkeep = await upkeep.connect(donTransmitter).performUpkeep(performData)
- await performUpkeep.wait()
- ranUpkeep = true
- }
- return ranUpkeep
+ let ranUpkeep = false
+ const checkData = ethers.utils.toUtf8Bytes("0x")
+ const { ...check } = await upkeep.connect(donTransmitter).checkUpkeep(checkData)
+ const { upkeepNeeded } = check
+ if (upkeepNeeded) {
+ const performData = ethers.utils.toUtf8Bytes("0x")
+ const performUpkeep = await upkeep.connect(donTransmitter).performUpkeep(performData)
+ await performUpkeep.wait()
+ ranUpkeep = true
+ }
+ return ranUpkeep
}
export interface ReportValues {
@@ -31,76 +31,82 @@ export interface ReportValues {
}
export async function fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values
}: {
donTransmitter: SignerWithAddress,
upkeep: CasimirUpkeep,
functionsBillingRegistry: FunctionsBillingRegistry,
values: ReportValues
}) {
- const { beaconBalance, sweptBalance, activatedDeposits, forcedExits, completedExits, compoundablePoolIds } = values
+ const { beaconBalance, sweptBalance, activatedDeposits, forcedExits, completedExits, compoundablePoolIds } = values
- const requestIds = (await upkeep.queryFilter(upkeep.filters.ReportRequestSent(), -2)).map((event) => event.args.requestId)
+ const requestIds = (await upkeep.queryFilter(upkeep.filters.ReportRequestSent(), -2)).map((event) => event.args.requestId)
- const balancesRequestId = requestIds[0]
+ const balancesRequestId = requestIds[0]
- const balancesResponse = ethers.utils.defaultAbiCoder.encode(
- ['uint128', 'uint128'],
- [ethers.utils.parseEther(beaconBalance.toString()), ethers.utils.parseEther(sweptBalance.toString())]
- )
+ const balancesResponse = ethers.utils.defaultAbiCoder.encode(
+ ["uint128", "uint128"],
+ [ethers.utils.parseEther(beaconBalance.toString()), ethers.utils.parseEther(sweptBalance.toString())]
+ )
- await fulfillFunctionsRequest({
- donTransmitter,
- functionsBillingRegistry,
- requestId: balancesRequestId,
- response: balancesResponse
- })
+ await fulfillFunctionsRequest({
+ donTransmitter,
+ functionsBillingRegistry,
+ requestId: balancesRequestId,
+ response: balancesResponse
+ })
- const detailsRequestId = requestIds[1]
- const detailsResponse = ethers.utils.defaultAbiCoder.encode(
- ['uint32', 'uint32', 'uint32', 'uint32[5]'],
- [activatedDeposits, forcedExits, completedExits, compoundablePoolIds]
- )
+ const detailsRequestId = requestIds[1]
+ const detailsResponse = ethers.utils.defaultAbiCoder.encode(
+ ["uint32",
+ "uint32",
+ "uint32",
+ "uint32[5]"],
+ [activatedDeposits,
+ forcedExits,
+ completedExits,
+ compoundablePoolIds]
+ )
- await fulfillFunctionsRequest({
- donTransmitter,
- functionsBillingRegistry,
- requestId: detailsRequestId,
- response: detailsResponse
- })
+ await fulfillFunctionsRequest({
+ donTransmitter,
+ functionsBillingRegistry,
+ requestId: detailsRequestId,
+ response: detailsResponse
+ })
}
export async function fulfillFunctionsRequest({
- donTransmitter,
- functionsBillingRegistry,
- requestId,
- response
+ donTransmitter,
+ functionsBillingRegistry,
+ requestId,
+ response
}: {
donTransmitter: SignerWithAddress,
functionsBillingRegistry: FunctionsBillingRegistry,
requestId: string,
response: string
}) {
- const dummyTransmitter = donTransmitter.address
- const dummySigners = Array(31).fill(dummyTransmitter)
+ const dummyTransmitter = donTransmitter.address
+ const dummySigners = Array(31).fill(dummyTransmitter)
- // const { success, result, resultLog } = await simulateRequest(requestConfig)
+ // const { success, result, resultLog } = await simulateRequest(requestConfig)
- const fulfillAndBill = await functionsBillingRegistry.connect(donTransmitter).fulfillAndBill(
- requestId,
- response,
- '0x',
- dummyTransmitter,
- dummySigners,
- 4,
- 100_000,
- 500_000,
- {
- gasLimit: 500_000,
- }
- )
- await fulfillAndBill.wait()
+ const fulfillAndBill = await functionsBillingRegistry.connect(donTransmitter).fulfillAndBill(
+ requestId,
+ response,
+ "0x",
+ dummyTransmitter,
+ dummySigners,
+ 4,
+ 100_000,
+ 500_000,
+ {
+ gasLimit: 500_000,
+ }
+ )
+ await fulfillAndBill.wait()
}
diff --git a/contracts/ethereum/scripts/clean.ts b/contracts/ethereum/scripts/clean.ts
index 39a451a6c..7536ea7ba 100644
--- a/contracts/ethereum/scripts/clean.ts
+++ b/contracts/ethereum/scripts/clean.ts
@@ -1,5 +1,5 @@
-import fs from 'fs'
+import fs from "fs"
void function() {
- fs.rmSync('build', { recursive: true })
+ fs.rmSync("build", { recursive: true })
}()
\ No newline at end of file
diff --git a/contracts/ethereum/scripts/deploy.ts b/contracts/ethereum/scripts/deploy.ts
index 8604fa545..76eb85d92 100644
--- a/contracts/ethereum/scripts/deploy.ts
+++ b/contracts/ethereum/scripts/deploy.ts
@@ -1,6 +1,6 @@
-import { ethers, upgrades } from 'hardhat'
-import requestConfig from '@casimir/functions/Functions-request-config'
-import { CasimirFactory, CasimirUpkeep } from '../build/@types'
+import { ethers, upgrades } from "hardhat"
+import requestConfig from "@casimir/functions/Functions-request-config"
+import { CasimirFactory, CasimirUpkeep } from "../build/@types"
upgrades.silenceWarnings()
@@ -8,74 +8,75 @@ upgrades.silenceWarnings()
* Deploy ethereum contracts
*/
void async function () {
- if (!process.env.DEPOSIT_CONTRACT_ADDRESS) throw new Error('No deposit contract address provided')
- if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error('No keeper registrar address provided')
- if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error('No keeper registry address provided')
- if (!process.env.LINK_TOKEN_ADDRESS) throw new Error('No link token address provided')
- if (!process.env.LINK_ETH_FEED_ADDRESS) throw new Error('No link eth feed address provided')
- if (!process.env.SSV_NETWORK_ADDRESS) throw new Error('No ssv network address provided')
- if (!process.env.SSV_TOKEN_ADDRESS) throw new Error('No ssv token address provided')
- if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error('No swap factory address provided')
- if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error('No swap router address provided')
- if (!process.env.WETH_TOKEN_ADDRESS) throw new Error('No weth token address provided')
-
- const [, daoOracle, donTransmitter] = await ethers.getSigners()
-
- const functionsOracleFactoryFactory = await ethers.getContractFactory('FunctionsOracleFactory')
- const functionsOracleFactory = await functionsOracleFactoryFactory.deploy()
- await functionsOracleFactory.deployed()
- console.log(`FunctionsOracleFactory contract deployed to ${functionsOracleFactory.address}`)
-
- const deployNewOracle = await functionsOracleFactory.deployNewOracle()
- const deployNewOracleReceipt = await deployNewOracle.wait()
- if (!deployNewOracleReceipt.events) throw new Error('Functions oracle deployment failed')
- const functionsOracleAddress = deployNewOracleReceipt.events[1].args?.don as string
- const functionsOracle = await ethers.getContractAt('FunctionsOraclePatched', functionsOracleAddress)
- const acceptOwnership = await functionsOracle.acceptOwnership()
- await acceptOwnership.wait()
- console.log(`FunctionsOracle contract deployed to ${functionsOracle.address}`)
-
- const functionsBillingRegistryArgs = {
- linkTokenAddress: process.env.LINK_TOKEN_ADDRESS,
- linkEthFeedAddress: process.env.LINK_ETH_FEED_ADDRESS,
- functionsOracleAddress: functionsOracle.address
- }
- const functionsBillingRegistryFactory = await ethers.getContractFactory('FunctionsBillingRegistry')
- const functionsBillingRegistry = await functionsBillingRegistryFactory.deploy(...Object.values(functionsBillingRegistryArgs))
- await functionsBillingRegistry.deployed()
- console.log(`FunctionsBillingRegistry contract deployed to ${functionsBillingRegistry.address}`)
-
- const functionsBillingRegistryConfig = {
- maxGasLimit: 400_000,
- stalenessSeconds: 86_400,
- gasAfterPaymentCalculation:
+ if (!process.env.DEPOSIT_CONTRACT_ADDRESS) throw new Error("No deposit contract address provided")
+ if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error("No keeper registrar address provided")
+ if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error("No keeper registry address provided")
+ if (!process.env.LINK_TOKEN_ADDRESS) throw new Error("No link token address provided")
+ if (!process.env.LINK_ETH_FEED_ADDRESS) throw new Error("No link eth feed address provided")
+ if (!process.env.SSV_NETWORK_ADDRESS) throw new Error("No ssv network address provided")
+ if (!process.env.SSV_TOKEN_ADDRESS) throw new Error("No ssv token address provided")
+ if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error("No swap factory address provided")
+ if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error("No swap router address provided")
+ if (!process.env.WETH_TOKEN_ADDRESS) throw new Error("No weth token address provided")
+
+ const [, daoOracle,
+ donTransmitter] = await ethers.getSigners()
+
+ const functionsOracleFactoryFactory = await ethers.getContractFactory("FunctionsOracleFactory")
+ const functionsOracleFactory = await functionsOracleFactoryFactory.deploy()
+ await functionsOracleFactory.deployed()
+ console.log(`FunctionsOracleFactory contract deployed to ${functionsOracleFactory.address}`)
+
+ const deployNewOracle = await functionsOracleFactory.deployNewOracle()
+ const deployNewOracleReceipt = await deployNewOracle.wait()
+ if (!deployNewOracleReceipt.events) throw new Error("Functions oracle deployment failed")
+ const functionsOracleAddress = deployNewOracleReceipt.events[1].args?.don as string
+ const functionsOracle = await ethers.getContractAt("FunctionsOraclePatched", functionsOracleAddress)
+ const acceptOwnership = await functionsOracle.acceptOwnership()
+ await acceptOwnership.wait()
+ console.log(`FunctionsOracle contract deployed to ${functionsOracle.address}`)
+
+ const functionsBillingRegistryArgs = {
+ linkTokenAddress: process.env.LINK_TOKEN_ADDRESS,
+ linkEthFeedAddress: process.env.LINK_ETH_FEED_ADDRESS,
+ functionsOracleAddress: functionsOracle.address
+ }
+ const functionsBillingRegistryFactory = await ethers.getContractFactory("FunctionsBillingRegistry")
+ const functionsBillingRegistry = await functionsBillingRegistryFactory.deploy(...Object.values(functionsBillingRegistryArgs))
+ await functionsBillingRegistry.deployed()
+ console.log(`FunctionsBillingRegistry contract deployed to ${functionsBillingRegistry.address}`)
+
+ const functionsBillingRegistryConfig = {
+ maxGasLimit: 400_000,
+ stalenessSeconds: 86_400,
+ gasAfterPaymentCalculation:
21_000 + 5_000 + 2_100 + 20_000 + 2 * 2_100 - 15_000 + 7_315,
- weiPerUnitLink: ethers.BigNumber.from('5000000000000000'),
- gasOverhead: 100_000,
- requestTimeoutSeconds: 300,
+ weiPerUnitLink: ethers.BigNumber.from("5000000000000000"),
+ gasOverhead: 100_000,
+ requestTimeoutSeconds: 300,
+ }
+
+ await functionsBillingRegistry.setConfig(
+ functionsBillingRegistryConfig.maxGasLimit,
+ functionsBillingRegistryConfig.stalenessSeconds,
+ functionsBillingRegistryConfig.gasAfterPaymentCalculation,
+ functionsBillingRegistryConfig.weiPerUnitLink,
+ functionsBillingRegistryConfig.gasOverhead,
+ functionsBillingRegistryConfig.requestTimeoutSeconds
+ )
+
+ const beaconLibraryFactory = await ethers.getContractFactory("CasimirBeacon")
+ const beaconLibrary = await beaconLibraryFactory.deploy()
+ console.log(`CasimirBeacon library deployed at ${beaconLibrary.address}`)
+
+ const managerBeaconFactory = await ethers.getContractFactory("CasimirManager", {
+ libraries: {
+ CasimirBeacon: beaconLibrary.address
}
-
- await functionsBillingRegistry.setConfig(
- functionsBillingRegistryConfig.maxGasLimit,
- functionsBillingRegistryConfig.stalenessSeconds,
- functionsBillingRegistryConfig.gasAfterPaymentCalculation,
- functionsBillingRegistryConfig.weiPerUnitLink,
- functionsBillingRegistryConfig.gasOverhead,
- functionsBillingRegistryConfig.requestTimeoutSeconds
- )
-
- const beaconLibraryFactory = await ethers.getContractFactory('CasimirBeacon')
- const beaconLibrary = await beaconLibraryFactory.deploy()
- console.log(`CasimirBeacon library deployed at ${beaconLibrary.address}`)
-
- const managerBeaconFactory = await ethers.getContractFactory('CasimirManager', {
- libraries: {
- CasimirBeacon: beaconLibrary.address
- }
- })
- const managerBeacon = await upgrades.deployBeacon(managerBeaconFactory, {
- constructorArgs: [
- functionsBillingRegistry.address,
+ })
+ const managerBeacon = await upgrades.deployBeacon(managerBeaconFactory, {
+ constructorArgs: [
+ functionsBillingRegistry.address,
process.env.KEEPER_REGISTRAR_ADDRESS as string,
process.env.KEEPER_REGISTRY_ADDRESS as string,
process.env.LINK_TOKEN_ADDRESS as string,
@@ -84,88 +85,90 @@ void async function () {
process.env.SWAP_FACTORY_ADDRESS as string,
process.env.SWAP_ROUTER_ADDRESS as string,
process.env.WETH_TOKEN_ADDRESS as string
- ],
- unsafeAllow: ['external-library-linking']
- })
- await managerBeacon.deployed()
- console.log(`CasimirManager beacon deployed at ${managerBeacon.address}`)
-
- const poolBeaconFactory = await ethers.getContractFactory('CasimirPool')
- const poolBeacon = await upgrades.deployBeacon(poolBeaconFactory, {
- constructorArgs: [
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await managerBeacon.deployed()
+ console.log(`CasimirManager beacon deployed at ${managerBeacon.address}`)
+
+ const poolBeaconFactory = await ethers.getContractFactory("CasimirPool")
+ const poolBeacon = await upgrades.deployBeacon(poolBeaconFactory, {
+ constructorArgs: [
process.env.DEPOSIT_CONTRACT_ADDRESS as string
- ]
- })
- await poolBeacon.deployed()
- console.log(`CasimirPool beacon deployed at ${poolBeacon.address}`)
-
- const registryBeaconFactory = await ethers.getContractFactory('CasimirRegistry')
- const registryBeacon = await upgrades.deployBeacon(registryBeaconFactory, {
- constructorArgs: [
+ ]
+ })
+ await poolBeacon.deployed()
+ console.log(`CasimirPool beacon deployed at ${poolBeacon.address}`)
+
+ const registryBeaconFactory = await ethers.getContractFactory("CasimirRegistry")
+ const registryBeacon = await upgrades.deployBeacon(registryBeaconFactory, {
+ constructorArgs: [
process.env.SSV_VIEWS_ADDRESS as string
- ]
- })
- await registryBeacon.deployed()
- console.log(`CasimirRegistry beacon deployed at ${registryBeacon.address}`)
-
- const upkeepBeaconFactory = await ethers.getContractFactory('CasimirUpkeep')
- const upkeepBeacon = await upgrades.deployBeacon(upkeepBeaconFactory)
- await upkeepBeacon.deployed()
- console.log(`CasimirUpkeep beacon deployed at ${upkeepBeacon.address}`)
-
- const viewsBeaconFactory = await ethers.getContractFactory('CasimirViews')
- const viewsBeacon = await upgrades.deployBeacon(viewsBeaconFactory)
- await viewsBeacon.deployed()
- console.log(`CasimirViews beacon deployed at ${viewsBeacon.address}`)
-
- const factoryFactory = await ethers.getContractFactory('CasimirFactory', {
- libraries: {
- CasimirBeacon: beaconLibrary.address
- }
- })
- const factory = await upgrades.deployProxy(factoryFactory, undefined, {
- constructorArgs: [
- managerBeacon.address,
- poolBeacon.address,
- registryBeacon.address,
- upkeepBeacon.address,
- viewsBeacon.address
- ],
- unsafeAllow: ['external-library-linking']
- }) as CasimirFactory
- await factory.deployed()
- console.log(`CasimirFactory contract deployed at ${factory.address}`)
-
- const simpleStrategy = {
- minCollateral: ethers.utils.parseEther('1.0'),
- lockPeriod: 0,
- userFee: 5,
- compoundStake: true,
- eigenStake: false,
- liquidStake: false,
- privateOperators: false,
- verifiedOperators: false
+ ]
+ })
+ await registryBeacon.deployed()
+ console.log(`CasimirRegistry beacon deployed at ${registryBeacon.address}`)
+
+ const upkeepBeaconFactory = await ethers.getContractFactory("CasimirUpkeep")
+ const upkeepBeacon = await upgrades.deployBeacon(upkeepBeaconFactory)
+ await upkeepBeacon.deployed()
+ console.log(`CasimirUpkeep beacon deployed at ${upkeepBeacon.address}`)
+
+ const viewsBeaconFactory = await ethers.getContractFactory("CasimirViews")
+ const viewsBeacon = await upgrades.deployBeacon(viewsBeaconFactory)
+ await viewsBeacon.deployed()
+ console.log(`CasimirViews beacon deployed at ${viewsBeacon.address}`)
+
+ const factoryFactory = await ethers.getContractFactory("CasimirFactory", {
+ libraries: {
+ CasimirBeacon: beaconLibrary.address
}
- const deploySimpleManager = await factory.deployManager(
- daoOracle.address,
- functionsOracle.address,
- simpleStrategy
- )
- await deploySimpleManager.wait()
- const [managerId] = await factory.getManagerIds()
- const managerConfig = await factory.getManagerConfig(managerId)
- console.log(`Simple CasimirManager contract deployed to ${managerConfig.managerAddress}`)
- console.log(`Simple CasimirRegistry contract deployed to ${managerConfig.registryAddress}`)
- console.log(`Simple CasimirUpkeep contract deployed to ${managerConfig.upkeepAddress}`)
- console.log(`Simple CasimirViews contract deployed to ${managerConfig.viewsAddress}`)
- const upkeep = await ethers.getContractAt('CasimirUpkeep', managerConfig.upkeepAddress) as CasimirUpkeep
+ })
+ const factory = await upgrades.deployProxy(factoryFactory, undefined, {
+ constructorArgs: [
+ managerBeacon.address,
+ poolBeacon.address,
+ registryBeacon.address,
+ upkeepBeacon.address,
+ viewsBeacon.address
+ ],
+ unsafeAllow: ["external-library-linking"]
+ }) as CasimirFactory
+ await factory.deployed()
+ console.log(`CasimirFactory contract deployed at ${factory.address}`)
+
+ const simpleStrategy = {
+ minCollateral: ethers.utils.parseEther("1.0"),
+ lockPeriod: 0,
+ userFee: 5,
+ compoundStake: true,
+ eigenStake: false,
+ liquidStake: false,
+ privateOperators: false,
+ verifiedOperators: false
+ }
+ const deploySimpleManager = await factory.deployManager(
+ daoOracle.address,
+ functionsOracle.address,
+ simpleStrategy
+ )
+ await deploySimpleManager.wait()
+ const [managerId] = await factory.getManagerIds()
+ const managerConfig = await factory.getManagerConfig(managerId)
+ console.log(`Simple CasimirManager contract deployed to ${managerConfig.managerAddress}`)
+ console.log(`Simple CasimirRegistry contract deployed to ${managerConfig.registryAddress}`)
+ console.log(`Simple CasimirUpkeep contract deployed to ${managerConfig.upkeepAddress}`)
+ console.log(`Simple CasimirViews contract deployed to ${managerConfig.viewsAddress}`)
+ const upkeep = await ethers.getContractAt("CasimirUpkeep", managerConfig.upkeepAddress) as CasimirUpkeep
- requestConfig.args[1] = managerConfig.viewsAddress
- const fulfillGasLimit = 300000
- const setRequest = await upkeep.setFunctionsRequest(requestConfig.source, requestConfig.args, fulfillGasLimit)
- await setRequest.wait()
- await upkeep.setFunctionsOracle(functionsOracle.address)
- await functionsBillingRegistry.setAuthorizedSenders([functionsOracle.address, donTransmitter.address])
- await functionsOracle.setAuthorizedSenders([donTransmitter.address, managerConfig.managerAddress, managerConfig.upkeepAddress])
- await functionsOracle.setRegistry(functionsBillingRegistry.address)
+ requestConfig.args[1] = managerConfig.viewsAddress
+ const fulfillGasLimit = 300000
+ const setRequest = await upkeep.setFunctionsRequest(requestConfig.source, requestConfig.args, fulfillGasLimit)
+ await setRequest.wait()
+ await upkeep.setFunctionsOracle(functionsOracle.address)
+ await functionsBillingRegistry.setAuthorizedSenders([functionsOracle.address, donTransmitter.address])
+ await functionsOracle.setAuthorizedSenders([donTransmitter.address,
+ managerConfig.managerAddress,
+ managerConfig.upkeepAddress])
+ await functionsOracle.setRegistry(functionsBillingRegistry.address)
}()
\ No newline at end of file
diff --git a/contracts/ethereum/scripts/dev.ts b/contracts/ethereum/scripts/dev.ts
index 7a0a95c21..7f8a05fa9 100644
--- a/contracts/ethereum/scripts/dev.ts
+++ b/contracts/ethereum/scripts/dev.ts
@@ -1,13 +1,13 @@
-import { CasimirFactoryDev, CasimirManagerDev, CasimirRegistryDev, CasimirUpkeepDev, CasimirViewsDev, FunctionsOracle, FunctionsBillingRegistry } from '../build/@types'
-import { ethers, upgrades } from 'hardhat'
-import { time, setBalance } from '@nomicfoundation/hardhat-network-helpers'
-import { PoolStatus } from '@casimir/types'
-import requestConfig from '@casimir/functions/Functions-request-config'
-import { run } from '@casimir/shell'
-import { round } from '../helpers/math'
-import { waitForNetwork } from '../helpers/network'
-import { activatePoolsHandler } from '../helpers/oracle'
-import { fulfillReport, runUpkeep } from '../helpers/upkeep'
+import { CasimirFactoryDev, CasimirManagerDev, CasimirRegistryDev, CasimirUpkeepDev, CasimirViewsDev, FunctionsOracle, FunctionsBillingRegistry } from "../build/@types"
+import { ethers, upgrades } from "hardhat"
+import { time, setBalance } from "@nomicfoundation/hardhat-network-helpers"
+import { PoolStatus } from "@casimir/types"
+import requestConfig from "@casimir/functions/Functions-request-config"
+import { run } from "@casimir/shell"
+import { round } from "../helpers/math"
+import { waitForNetwork } from "../helpers/network"
+import { activatePoolsHandler } from "../helpers/oracle"
+import { fulfillReport, runUpkeep } from "../helpers/upkeep"
/**
* Fork contracts to local network and run local events and oracle handling
@@ -17,239 +17,243 @@ import { fulfillReport, runUpkeep } from '../helpers/upkeep'
* - SIMULATE_REWARDS: true | false
*/
async function dev() {
- if (!process.env.FACTORY_ADDRESS) throw new Error('No factory address provided')
- if (!process.env.MANAGER_BEACON_ADDRESS) throw new Error('No manager beacon address provided')
- if (!process.env.POOL_BEACON_ADDRESS) throw new Error('No pool beacon address provided')
- if (!process.env.REGISTRY_BEACON_ADDRESS) throw new Error('No registry beacon address provided')
- if (!process.env.UPKEEP_BEACON_ADDRESS) throw new Error('No upkeep beacon address provided')
- if (!process.env.VIEWS_BEACON_ADDRESS) throw new Error('No views beacon address provided')
- if (!process.env.BEACON_LIBRARY_ADDRESS) throw new Error('No beacon library address provided')
- if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error('No functions billing registry address provided')
- if (!process.env.FUNCTIONS_ORACLE_ADDRESS) throw new Error('No functions oracle address provided')
- if (!process.env.DEPOSIT_CONTRACT_ADDRESS) throw new Error('No deposit contract address provided')
- if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error('No keeper registrar address provided')
- if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error('No keeper registry address provided')
- if (!process.env.LINK_TOKEN_ADDRESS) throw new Error('No link token address provided')
- if (!process.env.LINK_ETH_FEED_ADDRESS) throw new Error('No link eth feed address provided')
- if (!process.env.SSV_NETWORK_ADDRESS) throw new Error('No ssv network address provided')
- if (!process.env.SSV_TOKEN_ADDRESS) throw new Error('No ssv token address provided')
- if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error('No swap factory address provided')
- if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error('No swap router address provided')
- if (!process.env.WETH_TOKEN_ADDRESS) throw new Error('No weth token address provided')
-
- await waitForNetwork(ethers.provider)
-
- const [owner, daoOracle, donTransmitter] = await ethers.getSigners()
-
- const functionsOracle = await ethers.getContractAt('FunctionsOracle', process.env.FUNCTIONS_ORACLE_ADDRESS) as FunctionsOracle
- const functionsBillingRegistry = await ethers.getContractAt('FunctionsBillingRegistry', process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) as FunctionsBillingRegistry
-
- /**
+ if (!process.env.FACTORY_ADDRESS) throw new Error("No factory address provided")
+ if (!process.env.MANAGER_BEACON_ADDRESS) throw new Error("No manager beacon address provided")
+ if (!process.env.POOL_BEACON_ADDRESS) throw new Error("No pool beacon address provided")
+ if (!process.env.REGISTRY_BEACON_ADDRESS) throw new Error("No registry beacon address provided")
+ if (!process.env.UPKEEP_BEACON_ADDRESS) throw new Error("No upkeep beacon address provided")
+ if (!process.env.VIEWS_BEACON_ADDRESS) throw new Error("No views beacon address provided")
+ if (!process.env.BEACON_LIBRARY_ADDRESS) throw new Error("No beacon library address provided")
+ if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error("No functions billing registry address provided")
+ if (!process.env.FUNCTIONS_ORACLE_ADDRESS) throw new Error("No functions oracle address provided")
+ if (!process.env.DEPOSIT_CONTRACT_ADDRESS) throw new Error("No deposit contract address provided")
+ if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error("No keeper registrar address provided")
+ if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error("No keeper registry address provided")
+ if (!process.env.LINK_TOKEN_ADDRESS) throw new Error("No link token address provided")
+ if (!process.env.LINK_ETH_FEED_ADDRESS) throw new Error("No link eth feed address provided")
+ if (!process.env.SSV_NETWORK_ADDRESS) throw new Error("No ssv network address provided")
+ if (!process.env.SSV_TOKEN_ADDRESS) throw new Error("No ssv token address provided")
+ if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error("No swap factory address provided")
+ if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error("No swap router address provided")
+ if (!process.env.WETH_TOKEN_ADDRESS) throw new Error("No weth token address provided")
+
+ await waitForNetwork(ethers.provider)
+
+ const [owner,
+ daoOracle,
+ donTransmitter] = await ethers.getSigners()
+
+ const functionsOracle = await ethers.getContractAt("FunctionsOracle", process.env.FUNCTIONS_ORACLE_ADDRESS) as FunctionsOracle
+ const functionsBillingRegistry = await ethers.getContractAt("FunctionsBillingRegistry", process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) as FunctionsBillingRegistry
+
+ /**
* Deploy in-development contract upgrades
* Helpful also for adding hardhat/console to debug existing methods
*/
- if (process.env.SIMULATE_UPGRADES === 'true') {
- upgrades.silenceWarnings()
+ if (process.env.SIMULATE_UPGRADES === "true") {
+ upgrades.silenceWarnings()
- const factoryProxyFactory = await ethers.getContractFactory('CasimirFactoryDev', {
- libraries: {
- CasimirBeacon: process.env.BEACON_LIBRARY_ADDRESS
- }
- })
- const factoryProxy = await upgrades.upgradeProxy(process.env.FACTORY_ADDRESS, factoryProxyFactory, {
- constructorArgs: [
- process.env.MANAGER_BEACON_ADDRESS,
- process.env.POOL_BEACON_ADDRESS,
- process.env.REGISTRY_BEACON_ADDRESS,
- process.env.UPKEEP_BEACON_ADDRESS,
- process.env.VIEWS_BEACON_ADDRESS
- ],
- unsafeAllow: ['external-library-linking']
- })
- await factoryProxy.deployed()
-
- const managerBeaconFactory = await ethers.getContractFactory('CasimirManagerDev', {
- libraries: {
- CasimirBeacon: process.env.BEACON_LIBRARY_ADDRESS
- }
- })
- const managerBeacon = await upgrades.upgradeBeacon(process.env.MANAGER_BEACON_ADDRESS, managerBeaconFactory, {
- constructorArgs: [
- process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS,
- process.env.KEEPER_REGISTRAR_ADDRESS,
- process.env.KEEPER_REGISTRY_ADDRESS,
- process.env.LINK_TOKEN_ADDRESS,
- process.env.SSV_NETWORK_ADDRESS,
- process.env.SSV_TOKEN_ADDRESS,
- process.env.SWAP_FACTORY_ADDRESS,
- process.env.SWAP_ROUTER_ADDRESS,
- process.env.WETH_TOKEN_ADDRESS
- ],
- unsafeAllow: ['external-library-linking']
- })
- await managerBeacon.deployed()
-
- const registryBeaconFactory = await ethers.getContractFactory('CasimirRegistryDev')
- const registryBeacon = await upgrades.upgradeBeacon(process.env.REGISTRY_BEACON_ADDRESS, registryBeaconFactory, {
- constructorArgs: [
- process.env.SSV_VIEWS_ADDRESS
- ]
- })
- await registryBeacon.deployed()
-
- const upkeepBeaconFactory = await ethers.getContractFactory('CasimirUpkeepDev')
- const upkeepBeacon = await upgrades.upgradeBeacon(process.env.UPKEEP_BEACON_ADDRESS, upkeepBeaconFactory)
- await upkeepBeacon.deployed()
-
- const viewsBeaconFactory = await ethers.getContractFactory('CasimirViewsDev')
- const viewsBeacon = await upgrades.upgradeBeacon(process.env.VIEWS_BEACON_ADDRESS, viewsBeaconFactory)
- await viewsBeacon.deployed()
- }
- const factory = await ethers.getContractAt('CasimirFactoryDev', process.env.FACTORY_ADDRESS) as CasimirFactoryDev
- console.log(`Casimir factory ${factory.address}`)
-
- const [managerId] = await factory.getManagerIds()
- const managerConfig = await factory.getManagerConfig(managerId)
-
- const manager = await ethers.getContractAt('CasimirManagerDev', managerConfig.managerAddress) as CasimirManagerDev
- console.log(`Casimir simple manager ${manager.address}`)
-
- const registry = await ethers.getContractAt('CasimirRegistryDev', managerConfig.registryAddress) as CasimirRegistryDev
- console.log(`Casimir simple registry ${registry.address}`)
-
- const upkeep = await ethers.getContractAt('CasimirUpkeepDev', managerConfig.upkeepAddress) as CasimirUpkeepDev
- console.log(`Casimir simple upkeep ${upkeep.address}`)
-
- const views = await ethers.getContractAt('CasimirViewsDev', managerConfig.viewsAddress) as CasimirViewsDev
- console.log(`Casimir simple views ${views.address}`)
+ const factoryProxyFactory = await ethers.getContractFactory("CasimirFactoryDev", {
+ libraries: {
+ CasimirBeacon: process.env.BEACON_LIBRARY_ADDRESS
+ }
+ })
+ const factoryProxy = await upgrades.upgradeProxy(process.env.FACTORY_ADDRESS, factoryProxyFactory, {
+ constructorArgs: [
+ process.env.MANAGER_BEACON_ADDRESS,
+ process.env.POOL_BEACON_ADDRESS,
+ process.env.REGISTRY_BEACON_ADDRESS,
+ process.env.UPKEEP_BEACON_ADDRESS,
+ process.env.VIEWS_BEACON_ADDRESS
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await factoryProxy.deployed()
+
+ const managerBeaconFactory = await ethers.getContractFactory("CasimirManagerDev", {
+ libraries: {
+ CasimirBeacon: process.env.BEACON_LIBRARY_ADDRESS
+ }
+ })
+ const managerBeacon = await upgrades.upgradeBeacon(process.env.MANAGER_BEACON_ADDRESS, managerBeaconFactory, {
+ constructorArgs: [
+ process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS,
+ process.env.KEEPER_REGISTRAR_ADDRESS,
+ process.env.KEEPER_REGISTRY_ADDRESS,
+ process.env.LINK_TOKEN_ADDRESS,
+ process.env.SSV_NETWORK_ADDRESS,
+ process.env.SSV_TOKEN_ADDRESS,
+ process.env.SWAP_FACTORY_ADDRESS,
+ process.env.SWAP_ROUTER_ADDRESS,
+ process.env.WETH_TOKEN_ADDRESS
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await managerBeacon.deployed()
+
+ const registryBeaconFactory = await ethers.getContractFactory("CasimirRegistryDev")
+ const registryBeacon = await upgrades.upgradeBeacon(process.env.REGISTRY_BEACON_ADDRESS, registryBeaconFactory, {
+ constructorArgs: [
+ process.env.SSV_VIEWS_ADDRESS
+ ]
+ })
+ await registryBeacon.deployed()
+
+ const upkeepBeaconFactory = await ethers.getContractFactory("CasimirUpkeepDev")
+ const upkeepBeacon = await upgrades.upgradeBeacon(process.env.UPKEEP_BEACON_ADDRESS, upkeepBeaconFactory)
+ await upkeepBeacon.deployed()
+
+ const viewsBeaconFactory = await ethers.getContractFactory("CasimirViewsDev")
+ const viewsBeacon = await upgrades.upgradeBeacon(process.env.VIEWS_BEACON_ADDRESS, viewsBeaconFactory)
+ await viewsBeacon.deployed()
+ }
+ const factory = await ethers.getContractAt("CasimirFactoryDev", process.env.FACTORY_ADDRESS) as CasimirFactoryDev
+ console.log(`Casimir factory ${factory.address}`)
+
+ const [managerId] = await factory.getManagerIds()
+ const managerConfig = await factory.getManagerConfig(managerId)
+
+ const manager = await ethers.getContractAt("CasimirManagerDev", managerConfig.managerAddress) as CasimirManagerDev
+ console.log(`Casimir simple manager ${manager.address}`)
+
+ const registry = await ethers.getContractAt("CasimirRegistryDev", managerConfig.registryAddress) as CasimirRegistryDev
+ console.log(`Casimir simple registry ${registry.address}`)
+
+ const upkeep = await ethers.getContractAt("CasimirUpkeepDev", managerConfig.upkeepAddress) as CasimirUpkeepDev
+ console.log(`Casimir simple upkeep ${upkeep.address}`)
+
+ const views = await ethers.getContractAt("CasimirViewsDev", managerConfig.viewsAddress) as CasimirViewsDev
+ console.log(`Casimir simple views ${views.address}`)
- /**
+ /**
* Deploy a second operator groups with Casimir Eigen stake enabled
* Note, this operator group is not functional it only deployed for testing purposes
*/
- if (process.env.SIMULATE_EIGEN === 'true') {
- const deployEigenManager = await factory.connect(owner).deployManager(
- daoOracle.address,
- functionsOracle.address,
- {
- minCollateral: ethers.utils.parseEther('1.0'),
- lockPeriod: ethers.BigNumber.from('0'),
- userFee: ethers.BigNumber.from('5'),
- compoundStake: true,
- eigenStake: true,
- liquidStake: false,
- privateOperators: false,
- verifiedOperators: false
- }
- )
- await deployEigenManager.wait()
- const [, eigenManagerId] = await factory.getManagerIds()
- const eigenManagerConfig = await factory.getManagerConfig(eigenManagerId)
-
- const eigenManager = await ethers.getContractAt('CasimirManagerDev', eigenManagerConfig.managerAddress) as CasimirManagerDev
- console.log(`Casimir Eigen manager ${eigenManager.address}`)
- const eigenRegistry = await ethers.getContractAt('CasimirRegistryDev', eigenManagerConfig.registryAddress) as CasimirRegistryDev
- console.log(`Casimir Eigen registry ${eigenRegistry.address}`)
- const eigenUpkeep = await ethers.getContractAt('CasimirUpkeepDev', eigenManagerConfig.upkeepAddress) as CasimirUpkeepDev
- console.log(`Casimir Eigen upkeep ${eigenUpkeep.address}`)
- const eigenViews = await ethers.getContractAt('CasimirViewsDev', eigenManagerConfig.viewsAddress) as CasimirViewsDev
- console.log(`Casimir Eigen views ${eigenViews.address}`)
-
- requestConfig.args[1] = eigenViews.address
- await (await eigenUpkeep.connect(owner).setFunctionsRequest(
- requestConfig.source, requestConfig.args, 300000
- )).wait()
-
- const functionsOracleSenders = await functionsOracle.getAuthorizedSenders()
- const newFunctionsOracleSenders = [...functionsOracleSenders, eigenManager.address, eigenUpkeep.address]
- await functionsOracle.connect(owner).setAuthorizedSenders(newFunctionsOracleSenders)
- }
-
- /**
+ if (process.env.SIMULATE_EIGEN === "true") {
+ const deployEigenManager = await factory.connect(owner).deployManager(
+ daoOracle.address,
+ functionsOracle.address,
+ {
+ minCollateral: ethers.utils.parseEther("1.0"),
+ lockPeriod: ethers.BigNumber.from("0"),
+ userFee: ethers.BigNumber.from("5"),
+ compoundStake: true,
+ eigenStake: true,
+ liquidStake: false,
+ privateOperators: false,
+ verifiedOperators: false
+ }
+ )
+ await deployEigenManager.wait()
+ const [, eigenManagerId] = await factory.getManagerIds()
+ const eigenManagerConfig = await factory.getManagerConfig(eigenManagerId)
+
+ const eigenManager = await ethers.getContractAt("CasimirManagerDev", eigenManagerConfig.managerAddress) as CasimirManagerDev
+ console.log(`Casimir Eigen manager ${eigenManager.address}`)
+ const eigenRegistry = await ethers.getContractAt("CasimirRegistryDev", eigenManagerConfig.registryAddress) as CasimirRegistryDev
+ console.log(`Casimir Eigen registry ${eigenRegistry.address}`)
+ const eigenUpkeep = await ethers.getContractAt("CasimirUpkeepDev", eigenManagerConfig.upkeepAddress) as CasimirUpkeepDev
+ console.log(`Casimir Eigen upkeep ${eigenUpkeep.address}`)
+ const eigenViews = await ethers.getContractAt("CasimirViewsDev", eigenManagerConfig.viewsAddress) as CasimirViewsDev
+ console.log(`Casimir Eigen views ${eigenViews.address}`)
+
+ requestConfig.args[1] = eigenViews.address
+ await (await eigenUpkeep.connect(owner).setFunctionsRequest(
+ requestConfig.source, requestConfig.args, 300000
+ )).wait()
+
+ const functionsOracleSenders = await functionsOracle.getAuthorizedSenders()
+ const newFunctionsOracleSenders = [...functionsOracleSenders,
+ eigenManager.address,
+ eigenUpkeep.address]
+ await functionsOracle.connect(owner).setAuthorizedSenders(newFunctionsOracleSenders)
+ }
+
+ /**
* Simulate oracle reporting on a higher than average rate
* Exit balances are swept as needed
*/
- if (process.env.SIMULATE_REWARDS === 'true') {
- const blocksPerReport = 10
- const rewardPerValidator = 0.105
- let lastReportBlock = await ethers.provider.getBlockNumber()
- let lastStakedPoolIds: number[] = []
- ethers.provider.on('block', async (block) => {
- if (block - blocksPerReport >= lastReportBlock) {
- await time.increase(time.duration.days(1))
- console.log('⌛️ Report period complete')
- lastReportBlock = await ethers.provider.getBlockNumber()
- await runUpkeep({ donTransmitter, upkeep })
- const pendingPoolIds = await manager.getPendingPoolIds()
- const stakedPoolIds = await manager.getStakedPoolIds()
- if (pendingPoolIds.length + stakedPoolIds.length) {
- console.log('🧾 Submitting report')
- const activatedPoolCount = pendingPoolIds.length
- const activatedBalance = activatedPoolCount * 32
- const sweptRewardBalance = rewardPerValidator * lastStakedPoolIds.length
- const exitingPoolCount = await manager.requestedExits()
- const sweptExitedBalance = exitingPoolCount.toNumber() * 32
- const rewardBalance = rewardPerValidator * stakedPoolIds.length
- const latestBeaconBalance = await manager.latestBeaconBalance()
- const nextBeaconBalance = round(parseFloat(ethers.utils.formatEther(latestBeaconBalance)) + activatedBalance + rewardBalance - sweptRewardBalance - sweptExitedBalance, 10)
- const nextActivatedDeposits = (await manager.getPendingPoolIds()).length
- for (const poolId of lastStakedPoolIds) {
- const poolAddress = await manager.getPoolAddress(poolId)
- const currentBalance = await ethers.provider.getBalance(poolAddress)
- const nextBalance = currentBalance.add(ethers.utils.parseEther(rewardPerValidator.toString()))
- await setBalance(poolAddress, nextBalance)
- }
- const startIndex = ethers.BigNumber.from(0)
- const endIndex = ethers.BigNumber.from(stakedPoolIds.length)
- const compoundablePoolIds = await views.getCompoundablePoolIds(startIndex, endIndex)
- const reportValues = {
- beaconBalance: nextBeaconBalance,
- sweptBalance: sweptRewardBalance + sweptExitedBalance,
- activatedDeposits: nextActivatedDeposits,
- forcedExits: 0,
- completedExits: exitingPoolCount.toNumber(),
- compoundablePoolIds
- }
- console.log('🧾 Report values', reportValues)
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
- if (activatedPoolCount) {
- await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: activatedPoolCount } })
- }
- let remaining = exitingPoolCount.toNumber()
- if (remaining) {
- for (const poolId of stakedPoolIds) {
- if (remaining === 0) break
- const poolConfig = await views.getPoolConfig(poolId)
- if (poolConfig.status === PoolStatus.EXITING_FORCED || poolConfig.status === PoolStatus.EXITING_REQUESTED) {
- remaining--
- const poolAddress = await manager.getPoolAddress(poolId)
- const currentBalance = await ethers.provider.getBalance(poolAddress)
- const poolSweptExitedBalance = sweptExitedBalance / exitingPoolCount.toNumber()
- const nextBalance = currentBalance.add(ethers.utils.parseEther(poolSweptExitedBalance.toString()))
- await setBalance(poolAddress, nextBalance)
- }
- }
- let finalizableCompletedExits = await manager.finalizableCompletedExits()
- while (finalizableCompletedExits.toNumber() !== exitingPoolCount.toNumber()) {
- finalizableCompletedExits = await manager.finalizableCompletedExits()
- }
- }
- await runUpkeep({ donTransmitter, upkeep })
- }
- lastStakedPoolIds = stakedPoolIds
+ if (process.env.SIMULATE_REWARDS === "true") {
+ const blocksPerReport = 10
+ const rewardPerValidator = 0.105
+ let lastReportBlock = await ethers.provider.getBlockNumber()
+ let lastStakedPoolIds: number[] = []
+ ethers.provider.on("block", async (block) => {
+ if (block - blocksPerReport >= lastReportBlock) {
+ await time.increase(time.duration.days(1))
+ console.log("⌛️ Report period complete")
+ lastReportBlock = await ethers.provider.getBlockNumber()
+ await runUpkeep({ donTransmitter, upkeep })
+ const pendingPoolIds = await manager.getPendingPoolIds()
+ const stakedPoolIds = await manager.getStakedPoolIds()
+ if (pendingPoolIds.length + stakedPoolIds.length) {
+ console.log("🧾 Submitting report")
+ const activatedPoolCount = pendingPoolIds.length
+ const activatedBalance = activatedPoolCount * 32
+ const sweptRewardBalance = rewardPerValidator * lastStakedPoolIds.length
+ const exitingPoolCount = await manager.requestedExits()
+ const sweptExitedBalance = exitingPoolCount.toNumber() * 32
+ const rewardBalance = rewardPerValidator * stakedPoolIds.length
+ const latestBeaconBalance = await manager.latestBeaconBalance()
+ const nextBeaconBalance = round(parseFloat(ethers.utils.formatEther(latestBeaconBalance)) + activatedBalance + rewardBalance - sweptRewardBalance - sweptExitedBalance, 10)
+ const nextActivatedDeposits = (await manager.getPendingPoolIds()).length
+ for (const poolId of lastStakedPoolIds) {
+ const poolAddress = await manager.getPoolAddress(poolId)
+ const currentBalance = await ethers.provider.getBalance(poolAddress)
+ const nextBalance = currentBalance.add(ethers.utils.parseEther(rewardPerValidator.toString()))
+ await setBalance(poolAddress, nextBalance)
+ }
+ const startIndex = ethers.BigNumber.from(0)
+ const endIndex = ethers.BigNumber.from(stakedPoolIds.length)
+ const compoundablePoolIds = await views.getCompoundablePoolIds(startIndex, endIndex)
+ const reportValues = {
+ beaconBalance: nextBeaconBalance,
+ sweptBalance: sweptRewardBalance + sweptExitedBalance,
+ activatedDeposits: nextActivatedDeposits,
+ forcedExits: 0,
+ completedExits: exitingPoolCount.toNumber(),
+ compoundablePoolIds
+ }
+ console.log("🧾 Report values", reportValues)
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+ if (activatedPoolCount) {
+ await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: activatedPoolCount } })
+ }
+ let remaining = exitingPoolCount.toNumber()
+ if (remaining) {
+ for (const poolId of stakedPoolIds) {
+ if (remaining === 0) break
+ const poolConfig = await views.getPoolConfig(poolId)
+ if (poolConfig.status === PoolStatus.EXITING_FORCED || poolConfig.status === PoolStatus.EXITING_REQUESTED) {
+ remaining--
+ const poolAddress = await manager.getPoolAddress(poolId)
+ const currentBalance = await ethers.provider.getBalance(poolAddress)
+ const poolSweptExitedBalance = sweptExitedBalance / exitingPoolCount.toNumber()
+ const nextBalance = currentBalance.add(ethers.utils.parseEther(poolSweptExitedBalance.toString()))
+ await setBalance(poolAddress, nextBalance)
+ }
+ }
+ let finalizableCompletedExits = await manager.finalizableCompletedExits()
+ while (finalizableCompletedExits.toNumber() !== exitingPoolCount.toNumber()) {
+ finalizableCompletedExits = await manager.finalizableCompletedExits()
}
- })
- }
+ }
+ await runUpkeep({ donTransmitter, upkeep })
+ }
+ lastStakedPoolIds = stakedPoolIds
+ }
+ })
+ }
- run('npm run dev --workspace @casimir/oracle')
+ run("npm run dev --workspace @casimir/oracle")
}
dev().catch(error => {
- console.error(error)
- process.exit(1)
+ console.error(error)
+ process.exit(1)
})
diff --git a/contracts/ethereum/scripts/rebalance-bug-1.ts b/contracts/ethereum/scripts/rebalance-bug-1.ts
index b52668c69..b97cdd95d 100644
--- a/contracts/ethereum/scripts/rebalance-bug-1.ts
+++ b/contracts/ethereum/scripts/rebalance-bug-1.ts
@@ -1,8 +1,8 @@
-import { ethers } from 'hardhat'
-import { CasimirFactory, CasimirManager } from '../build/@types'
-import ICasimirFactoryAbi from '../build/abi/ICasimirFactory.json'
-import ICasimirManagerAbi from '../build/abi/ICasimirManager.json'
-import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from '@casimir/env'
+import { ethers } from "hardhat"
+import { CasimirFactory, CasimirManager } from "../build/@types"
+import ICasimirFactoryAbi from "../build/abi/ICasimirFactory.json"
+import ICasimirManagerAbi from "../build/abi/ICasimirManager.json"
+import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from "@casimir/env"
// V1 testnet rebalance bug 1
// Undo stake ratio sum change 1 -409.082737011318350061 from block 9968492
@@ -13,39 +13,39 @@ import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from '@casimir/env'
void async function() {
- const doNotRun = true
- if (doNotRun) {
- throw new Error('Do not run this script. It is archived for internal documentation only.')
- }
-
- process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL['TESTNET']
- process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].FUNCTIONS_BILLING_REGISTRY_ADDRESS
- process.env.FUNCTIONS_ORACLE_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].FUNCTIONS_ORACLE_ADDRESS
- const [owner] = await ethers.getSigners()
- const provider = new ethers.providers.JsonRpcProvider(ETHEREUM_RPC_URL['TESTNET'])
- const factory = new ethers.Contract(ETHEREUM_CONTRACTS['TESTNET'].FACTORY_ADDRESS, ICasimirFactoryAbi, provider) as CasimirFactory
- const [managerId] = await factory.getManagerIds()
- const managerConfig = await factory.getManagerConfig(managerId)
- const manager = new ethers.Contract(managerConfig.managerAddress, ICasimirManagerAbi, provider) as CasimirManager
-
- const wrongStakeRatioSumChange1 = ethers.utils.parseEther('-409.082737011318350061')
- const undoStakeRatioSumChange1 = await manager.connect(owner).unbalanceStake(wrongStakeRatioSumChange1)
- await undoStakeRatioSumChange1.wait()
-
- const correctStakeRatioSumChange1 = ethers.utils.parseEther('0.035209244538409142')
- const redoStakeRatioSumChange1 = await manager.connect(owner).unbalanceStake(correctStakeRatioSumChange1)
- await redoStakeRatioSumChange1.wait()
-
- const wrongStakeRatioSumChange2 = ethers.utils.parseEther('617.841429400917953927')
- const undoStakeRatioSumChange2 = await manager.connect(owner).unbalanceStake(wrongStakeRatioSumChange2)
- await undoStakeRatioSumChange2.wait()
-
- const correctStakeRatioSumChange2 = ethers.utils.parseEther('-0.000323535550800035')
- const redoStakeRatioSumChange2 = await manager.connect(owner).unbalanceStake(correctStakeRatioSumChange2)
- await redoStakeRatioSumChange2.wait()
-
- const latestBeaconBalanceAfterFees = ethers.utils.parseEther('63.998872616')
- const setLatestBeaconBalanceAfterFees = await manager.connect(owner).setLatestBeaconBalanceAfterFees(latestBeaconBalanceAfterFees)
- await setLatestBeaconBalanceAfterFees.wait()
+ const doNotRun = true
+ if (doNotRun) {
+ throw new Error("Do not run this script. It is archived for internal documentation only.")
+ }
+
+ process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL["TESTNET"]
+ process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS = ETHEREUM_CONTRACTS["TESTNET"].FUNCTIONS_BILLING_REGISTRY_ADDRESS
+ process.env.FUNCTIONS_ORACLE_ADDRESS = ETHEREUM_CONTRACTS["TESTNET"].FUNCTIONS_ORACLE_ADDRESS
+ const [owner] = await ethers.getSigners()
+ const provider = new ethers.providers.JsonRpcProvider(ETHEREUM_RPC_URL["TESTNET"])
+ const factory = new ethers.Contract(ETHEREUM_CONTRACTS["TESTNET"].FACTORY_ADDRESS, ICasimirFactoryAbi, provider) as CasimirFactory
+ const [managerId] = await factory.getManagerIds()
+ const managerConfig = await factory.getManagerConfig(managerId)
+ const manager = new ethers.Contract(managerConfig.managerAddress, ICasimirManagerAbi, provider) as CasimirManager
+
+ const wrongStakeRatioSumChange1 = ethers.utils.parseEther("-409.082737011318350061")
+ const undoStakeRatioSumChange1 = await manager.connect(owner).unbalanceStake(wrongStakeRatioSumChange1)
+ await undoStakeRatioSumChange1.wait()
+
+ const correctStakeRatioSumChange1 = ethers.utils.parseEther("0.035209244538409142")
+ const redoStakeRatioSumChange1 = await manager.connect(owner).unbalanceStake(correctStakeRatioSumChange1)
+ await redoStakeRatioSumChange1.wait()
+
+ const wrongStakeRatioSumChange2 = ethers.utils.parseEther("617.841429400917953927")
+ const undoStakeRatioSumChange2 = await manager.connect(owner).unbalanceStake(wrongStakeRatioSumChange2)
+ await undoStakeRatioSumChange2.wait()
+
+ const correctStakeRatioSumChange2 = ethers.utils.parseEther("-0.000323535550800035")
+ const redoStakeRatioSumChange2 = await manager.connect(owner).unbalanceStake(correctStakeRatioSumChange2)
+ await redoStakeRatioSumChange2.wait()
+
+ const latestBeaconBalanceAfterFees = ethers.utils.parseEther("63.998872616")
+ const setLatestBeaconBalanceAfterFees = await manager.connect(owner).setLatestBeaconBalanceAfterFees(latestBeaconBalanceAfterFees)
+ await setLatestBeaconBalanceAfterFees.wait()
}()
\ No newline at end of file
diff --git a/contracts/ethereum/scripts/report.ts b/contracts/ethereum/scripts/report.ts
index b09d1cfd9..1880287f0 100644
--- a/contracts/ethereum/scripts/report.ts
+++ b/contracts/ethereum/scripts/report.ts
@@ -1,45 +1,45 @@
-import { ethers } from 'hardhat'
-import { CasimirFactory, CasimirManager, CasimirPool, CasimirRegistry, CasimirUpkeep, CasimirViews } from '../build/@types'
-import { waitForNetwork } from '../helpers/network'
-import { runUpkeep } from '../helpers/upkeep'
-import e from 'cors'
+import { ethers } from "hardhat"
+import { CasimirFactory, CasimirManager, CasimirPool, CasimirRegistry, CasimirUpkeep, CasimirViews } from "../build/@types"
+import { waitForNetwork } from "../helpers/network"
+import { runUpkeep } from "../helpers/upkeep"
+import e from "cors"
void async function() {
- if (!process.env.FACTORY_ADDRESS) throw new Error('No factory address provided')
+ if (!process.env.FACTORY_ADDRESS) throw new Error("No factory address provided")
- await waitForNetwork(ethers.provider)
+ await waitForNetwork(ethers.provider)
- const [owner, , donTransmitter] = await ethers.getSigners()
- const factory = await ethers.getContractAt('CasimirFactory', process.env.FACTORY_ADDRESS) as CasimirFactory
- const [managerId] = await factory.getManagerIds()
- const managerConfig = await factory.getManagerConfig(managerId)
- const manager = await ethers.getContractAt('CasimirManager', managerConfig.managerAddress) as CasimirManager
- const registry = await ethers.getContractAt('CasimirRegistry', managerConfig.registryAddress) as CasimirRegistry
- const upkeep = await ethers.getContractAt('CasimirUpkeep', managerConfig.upkeepAddress) as CasimirUpkeep
- const views = await ethers.getContractAt('CasimirViews', managerConfig.viewsAddress) as CasimirViews
+ const [owner, , donTransmitter] = await ethers.getSigners()
+ const factory = await ethers.getContractAt("CasimirFactory", process.env.FACTORY_ADDRESS) as CasimirFactory
+ const [managerId] = await factory.getManagerIds()
+ const managerConfig = await factory.getManagerConfig(managerId)
+ const manager = await ethers.getContractAt("CasimirManager", managerConfig.managerAddress) as CasimirManager
+ const registry = await ethers.getContractAt("CasimirRegistry", managerConfig.registryAddress) as CasimirRegistry
+ const upkeep = await ethers.getContractAt("CasimirUpkeep", managerConfig.upkeepAddress) as CasimirUpkeep
+ const views = await ethers.getContractAt("CasimirViews", managerConfig.viewsAddress) as CasimirViews
- // const pause = await manager.connect(owner).setPaused(false)
- // await pause.wait()
- const requestReport = await upkeep.connect(owner).requestReport()
- await requestReport.wait()
+ // const pause = await manager.connect(owner).setPaused(false)
+ // await pause.wait()
+ const requestReport = await upkeep.connect(owner).requestReport()
+ await requestReport.wait()
- if (process.env.SIMULATE_UPKEEP === 'true') {
- await runUpkeep({ donTransmitter, upkeep })
- let finalizedReport = false
- while (!finalizedReport) {
- finalizedReport = await runUpkeep({ donTransmitter, upkeep })
- await new Promise(resolve => setTimeout(resolve, 2500))
- }
- const poolIds = await manager.getStakedPoolIds()
- const sweptBalance = await views.getSweptBalance(0, poolIds.length)
- console.log('Swept balance', ethers.utils.formatEther(sweptBalance))
- let totalBalance = ethers.BigNumber.from(0)
- for (const poolId of poolIds) {
- const poolAddress = await manager.getPoolAddress(poolId)
- const poolBalance = await ethers.provider.getBalance(poolAddress)
- totalBalance = totalBalance.add(poolBalance)
- console.log('Pool', poolId, ethers.utils.formatEther(poolBalance))
- }
- console.log('Total balance', ethers.utils.formatEther(totalBalance))
+ if (process.env.SIMULATE_UPKEEP === "true") {
+ await runUpkeep({ donTransmitter, upkeep })
+ let finalizedReport = false
+ while (!finalizedReport) {
+ finalizedReport = await runUpkeep({ donTransmitter, upkeep })
+ await new Promise(resolve => setTimeout(resolve, 2500))
}
+ const poolIds = await manager.getStakedPoolIds()
+ const sweptBalance = await views.getSweptBalance(0, poolIds.length)
+ console.log("Swept balance", ethers.utils.formatEther(sweptBalance))
+ let totalBalance = ethers.BigNumber.from(0)
+ for (const poolId of poolIds) {
+ const poolAddress = await manager.getPoolAddress(poolId)
+ const poolBalance = await ethers.provider.getBalance(poolAddress)
+ totalBalance = totalBalance.add(poolBalance)
+ console.log("Pool", poolId, ethers.utils.formatEther(poolBalance))
+ }
+ console.log("Total balance", ethers.utils.formatEther(totalBalance))
+ }
}()
\ No newline at end of file
diff --git a/contracts/ethereum/scripts/test.ts b/contracts/ethereum/scripts/test.ts
index 25355e492..d0a817e22 100644
--- a/contracts/ethereum/scripts/test.ts
+++ b/contracts/ethereum/scripts/test.ts
@@ -1,49 +1,49 @@
-import { ethers } from 'ethers'
-import { loadCredentials, getSecret } from '@casimir/aws'
-import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run } from '@casimir/shell'
+import { ethers } from "ethers"
+import { loadCredentials, getSecret } from "@casimir/aws"
+import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run } from "@casimir/shell"
/**
* Test ethereum contracts and services
*/
async function test() {
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- }
- console.log(`Your mnemonic is ${process.env.BIP39_SEED}`)
-
- process.env.FORK = process.env.FORK || 'testnet'
-
- const networkKey = process.env.FORK.toUpperCase() as keyof typeof ETHEREUM_RPC_URL
- process.env.ETHEREUM_FORK_RPC_URL = ETHEREUM_RPC_URL[networkKey]
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") as string
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ }
+ console.log(`Your mnemonic is ${process.env.BIP39_SEED}`)
+
+ process.env.FORK = process.env.FORK || "testnet"
+
+ const networkKey = process.env.FORK.toUpperCase() as keyof typeof ETHEREUM_RPC_URL
+ process.env.ETHEREUM_FORK_RPC_URL = ETHEREUM_RPC_URL[networkKey]
- const networkName = ETHEREUM_NETWORK_NAME[networkKey]
- console.log(`Using ${networkName} fork from ${process.env.ETHEREUM_FORK_RPC_URL}`)
+ const networkName = ETHEREUM_NETWORK_NAME[networkKey]
+ console.log(`Using ${networkName} fork from ${process.env.ETHEREUM_FORK_RPC_URL}`)
- const provider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_FORK_RPC_URL)
- const wallet = ethers.Wallet.fromMnemonic(process.env.BIP39_SEED)
+ const provider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_FORK_RPC_URL)
+ const wallet = ethers.Wallet.fromMnemonic(process.env.BIP39_SEED)
- // Account for the mock, beacon, and library deployments
- const walletNonce = await provider.getTransactionCount(wallet.address) + 14
+ // Account for the mock, beacon, and library deployments
+ const walletNonce = await provider.getTransactionCount(wallet.address) + 14
- process.env.FACTORY_ADDRESS = ethers.utils.getContractAddress({
- from: wallet.address,
- nonce: walletNonce
- })
- console.log(`Expecting factory at ${process.env.FACTORY_ADDRESS}`)
+ process.env.FACTORY_ADDRESS = ethers.utils.getContractAddress({
+ from: wallet.address,
+ nonce: walletNonce
+ })
+ console.log(`Expecting factory at ${process.env.FACTORY_ADDRESS}`)
- process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS
- process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS
- process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SWAP_FACTORY_ADDRESS
+ process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS
+ process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS
+ process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SWAP_FACTORY_ADDRESS
- await run('npm run generate --workspace @casimir/oracle')
- run('npm hardhat test')
+ await run("npm run generate --workspace @casimir/oracle")
+ run("npm hardhat test")
}
test().catch(error => {
- console.error(error)
- process.exit(1)
+ console.error(error)
+ process.exit(1)
})
\ No newline at end of file
diff --git a/contracts/ethereum/scripts/upgrade-all.ts b/contracts/ethereum/scripts/upgrade-all.ts
index f77cadd13..80a5fdeac 100644
--- a/contracts/ethereum/scripts/upgrade-all.ts
+++ b/contracts/ethereum/scripts/upgrade-all.ts
@@ -1,84 +1,84 @@
-import { ethers, upgrades } from 'hardhat'
+import { ethers, upgrades } from "hardhat"
/**
* Upgrade ethereum contracts
*/
void async function () {
- // Redeploying functions billing registry for updates
- // if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error('No functions billing registry address provided')
- if (!process.env.MANAGER_BEACON_ADDRESS) throw new Error('No manager beacon address provided')
- if (!process.env.POOL_BEACON_ADDRESS) throw new Error('No pool beacon address provided')
- if (!process.env.REGISTRY_BEACON_ADDRESS) throw new Error('No registry beacon address provided')
- if (!process.env.UPKEEP_BEACON_ADDRESS) throw new Error('No upkeep beacon address provided')
- if (!process.env.VIEWS_BEACON_ADDRESS) throw new Error('No views address provided')
- if (!process.env.FACTORY_ADDRESS) throw new Error('No factory address provided')
- if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error('No keeper registrar address provided')
- if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error('No keeper registry address provided')
- if (!process.env.LINK_TOKEN_ADDRESS) throw new Error('No link token address provided')
- if (!process.env.SSV_NETWORK_ADDRESS) throw new Error('No ssv network address provided')
- if (!process.env.SSV_TOKEN_ADDRESS) throw new Error('No ssv token address provided')
- if (!process.env.SSV_VIEWS_ADDRESS) throw new Error('No ssv views address provided')
- if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error('No swap factory address provided')
- if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error('No swap router address provided')
- if (!process.env.WETH_TOKEN_ADDRESS) throw new Error('No weth token address provided')
+ // Redeploying functions billing registry for updates
+ // if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error('No functions billing registry address provided')
+ if (!process.env.MANAGER_BEACON_ADDRESS) throw new Error("No manager beacon address provided")
+ if (!process.env.POOL_BEACON_ADDRESS) throw new Error("No pool beacon address provided")
+ if (!process.env.REGISTRY_BEACON_ADDRESS) throw new Error("No registry beacon address provided")
+ if (!process.env.UPKEEP_BEACON_ADDRESS) throw new Error("No upkeep beacon address provided")
+ if (!process.env.VIEWS_BEACON_ADDRESS) throw new Error("No views address provided")
+ if (!process.env.FACTORY_ADDRESS) throw new Error("No factory address provided")
+ if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error("No keeper registrar address provided")
+ if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error("No keeper registry address provided")
+ if (!process.env.LINK_TOKEN_ADDRESS) throw new Error("No link token address provided")
+ if (!process.env.SSV_NETWORK_ADDRESS) throw new Error("No ssv network address provided")
+ if (!process.env.SSV_TOKEN_ADDRESS) throw new Error("No ssv token address provided")
+ if (!process.env.SSV_VIEWS_ADDRESS) throw new Error("No ssv views address provided")
+ if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error("No swap factory address provided")
+ if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error("No swap router address provided")
+ if (!process.env.WETH_TOKEN_ADDRESS) throw new Error("No weth token address provided")
- const [, , donTransmitter] = await ethers.getSigners()
+ const [, , donTransmitter] = await ethers.getSigners()
- const functionsOracleFactoryFactory = await ethers.getContractFactory('FunctionsOracleFactory')
- const functionsOracleFactory = await functionsOracleFactoryFactory.deploy()
- await functionsOracleFactory.deployed()
- console.log(`FunctionsOracleFactory contract deployed to ${functionsOracleFactory.address}`)
+ const functionsOracleFactoryFactory = await ethers.getContractFactory("FunctionsOracleFactory")
+ const functionsOracleFactory = await functionsOracleFactoryFactory.deploy()
+ await functionsOracleFactory.deployed()
+ console.log(`FunctionsOracleFactory contract deployed to ${functionsOracleFactory.address}`)
- const deployNewOracle = await functionsOracleFactory.deployNewOracle()
- const deployNewOracleReceipt = await deployNewOracle.wait()
- if (!deployNewOracleReceipt.events) throw new Error('Functions oracle deployment failed')
- const functionsOracleAddress = deployNewOracleReceipt.events[1].args?.don as string
- const functionsOracle = await ethers.getContractAt('FunctionsOracle', functionsOracleAddress)
- const acceptOwnership = await functionsOracle.acceptOwnership()
- await acceptOwnership.wait()
- console.log(`FunctionsOracle contract deployed to ${functionsOracle.address}`)
+ const deployNewOracle = await functionsOracleFactory.deployNewOracle()
+ const deployNewOracleReceipt = await deployNewOracle.wait()
+ if (!deployNewOracleReceipt.events) throw new Error("Functions oracle deployment failed")
+ const functionsOracleAddress = deployNewOracleReceipt.events[1].args?.don as string
+ const functionsOracle = await ethers.getContractAt("FunctionsOracle", functionsOracleAddress)
+ const acceptOwnership = await functionsOracle.acceptOwnership()
+ await acceptOwnership.wait()
+ console.log(`FunctionsOracle contract deployed to ${functionsOracle.address}`)
- const functionsBillingRegistryArgs = {
- linkTokenAddress: process.env.LINK_TOKEN_ADDRESS,
- linkEthFeedAddress: process.env.LINK_ETH_FEED_ADDRESS,
- functionsOracleAddress: functionsOracle.address
- }
- const functionsBillingRegistryFactory = await ethers.getContractFactory('FunctionsBillingRegistry')
- const functionsBillingRegistry = await functionsBillingRegistryFactory.deploy(...Object.values(functionsBillingRegistryArgs))
- await functionsBillingRegistry.deployed()
- console.log(`FunctionsBillingRegistry contract deployed to ${functionsBillingRegistry.address}`)
+ const functionsBillingRegistryArgs = {
+ linkTokenAddress: process.env.LINK_TOKEN_ADDRESS,
+ linkEthFeedAddress: process.env.LINK_ETH_FEED_ADDRESS,
+ functionsOracleAddress: functionsOracle.address
+ }
+ const functionsBillingRegistryFactory = await ethers.getContractFactory("FunctionsBillingRegistry")
+ const functionsBillingRegistry = await functionsBillingRegistryFactory.deploy(...Object.values(functionsBillingRegistryArgs))
+ await functionsBillingRegistry.deployed()
+ console.log(`FunctionsBillingRegistry contract deployed to ${functionsBillingRegistry.address}`)
- const functionsBillingRegistryConfig = {
- maxGasLimit: 400_000,
- stalenessSeconds: 86_400,
- gasAfterPaymentCalculation:
+ const functionsBillingRegistryConfig = {
+ maxGasLimit: 400_000,
+ stalenessSeconds: 86_400,
+ gasAfterPaymentCalculation:
21_000 + 5_000 + 2_100 + 20_000 + 2 * 2_100 - 15_000 + 7_315,
- weiPerUnitLink: ethers.BigNumber.from('5000000000000000'),
- gasOverhead: 100_000,
- requestTimeoutSeconds: 300,
- }
+ weiPerUnitLink: ethers.BigNumber.from("5000000000000000"),
+ gasOverhead: 100_000,
+ requestTimeoutSeconds: 300,
+ }
- await functionsBillingRegistry.setConfig(
- functionsBillingRegistryConfig.maxGasLimit,
- functionsBillingRegistryConfig.stalenessSeconds,
- functionsBillingRegistryConfig.gasAfterPaymentCalculation,
- functionsBillingRegistryConfig.weiPerUnitLink,
- functionsBillingRegistryConfig.gasOverhead,
- functionsBillingRegistryConfig.requestTimeoutSeconds
- )
+ await functionsBillingRegistry.setConfig(
+ functionsBillingRegistryConfig.maxGasLimit,
+ functionsBillingRegistryConfig.stalenessSeconds,
+ functionsBillingRegistryConfig.gasAfterPaymentCalculation,
+ functionsBillingRegistryConfig.weiPerUnitLink,
+ functionsBillingRegistryConfig.gasOverhead,
+ functionsBillingRegistryConfig.requestTimeoutSeconds
+ )
- const beaconLibraryFactory = await ethers.getContractFactory('CasimirBeacon')
- const beaconLibrary = await beaconLibraryFactory.deploy()
- console.log(`CasimirBeacon library deployed at ${beaconLibrary.address}`)
+ const beaconLibraryFactory = await ethers.getContractFactory("CasimirBeacon")
+ const beaconLibrary = await beaconLibraryFactory.deploy()
+ console.log(`CasimirBeacon library deployed at ${beaconLibrary.address}`)
- const managerBeaconFactory = await ethers.getContractFactory('CasimirManager', {
- libraries: {
- CasimirBeacon: beaconLibrary.address
- }
- })
- const managerBeacon = await upgrades.upgradeBeacon(process.env.MANAGER_BEACON_ADDRESS, managerBeaconFactory, {
- constructorArgs: [
- functionsBillingRegistry.address,
+ const managerBeaconFactory = await ethers.getContractFactory("CasimirManager", {
+ libraries: {
+ CasimirBeacon: beaconLibrary.address
+ }
+ })
+ const managerBeacon = await upgrades.upgradeBeacon(process.env.MANAGER_BEACON_ADDRESS, managerBeaconFactory, {
+ constructorArgs: [
+ functionsBillingRegistry.address,
process.env.KEEPER_REGISTRAR_ADDRESS as string,
process.env.KEEPER_REGISTRY_ADDRESS as string,
process.env.LINK_TOKEN_ADDRESS as string,
@@ -87,64 +87,66 @@ void async function () {
process.env.SWAP_FACTORY_ADDRESS as string,
process.env.SWAP_ROUTER_ADDRESS as string,
process.env.WETH_TOKEN_ADDRESS as string
- ],
- unsafeAllow: ['external-library-linking']
- })
- await managerBeacon.deployed()
- console.log(`CasimirManager beacon upgraded at ${managerBeacon.address}`)
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await managerBeacon.deployed()
+ console.log(`CasimirManager beacon upgraded at ${managerBeacon.address}`)
- const poolBeaconFactory = await ethers.getContractFactory('CasimirPool')
- const poolBeacon = await upgrades.upgradeBeacon(process.env.POOL_BEACON_ADDRESS, poolBeaconFactory, {
- constructorArgs: [
+ const poolBeaconFactory = await ethers.getContractFactory("CasimirPool")
+ const poolBeacon = await upgrades.upgradeBeacon(process.env.POOL_BEACON_ADDRESS, poolBeaconFactory, {
+ constructorArgs: [
process.env.DEPOSIT_CONTRACT_ADDRESS as string
- ]
- })
- await poolBeacon.deployed()
- console.log(`CasimirPool beacon upgraded at ${poolBeacon.address}`)
+ ]
+ })
+ await poolBeacon.deployed()
+ console.log(`CasimirPool beacon upgraded at ${poolBeacon.address}`)
- const registryBeaconFactory = await ethers.getContractFactory('CasimirRegistry')
- const registryBeacon = await upgrades.upgradeBeacon(process.env.REGISTRY_BEACON_ADDRESS, registryBeaconFactory, {
- constructorArgs: [
+ const registryBeaconFactory = await ethers.getContractFactory("CasimirRegistry")
+ const registryBeacon = await upgrades.upgradeBeacon(process.env.REGISTRY_BEACON_ADDRESS, registryBeaconFactory, {
+ constructorArgs: [
process.env.SSV_VIEWS_ADDRESS as string
- ]
- })
- await registryBeacon.deployed()
- console.log(`CasimirRegistry beacon upgraded at ${registryBeacon.address}`)
+ ]
+ })
+ await registryBeacon.deployed()
+ console.log(`CasimirRegistry beacon upgraded at ${registryBeacon.address}`)
- const upkeepBeaconFactory = await ethers.getContractFactory('CasimirUpkeep')
- const upkeepBeacon = await upgrades.upgradeBeacon(process.env.UPKEEP_BEACON_ADDRESS, upkeepBeaconFactory)
- await upkeepBeacon.deployed()
- console.log(`CasimirUpkeep beacon upgraded at ${upkeepBeacon.address}`)
+ const upkeepBeaconFactory = await ethers.getContractFactory("CasimirUpkeep")
+ const upkeepBeacon = await upgrades.upgradeBeacon(process.env.UPKEEP_BEACON_ADDRESS, upkeepBeaconFactory)
+ await upkeepBeacon.deployed()
+ console.log(`CasimirUpkeep beacon upgraded at ${upkeepBeacon.address}`)
- const viewsBeaconFactory = await ethers.getContractFactory('CasimirViews')
- const viewsBeacon = await upgrades.upgradeBeacon(process.env.VIEWS_BEACON_ADDRESS, viewsBeaconFactory)
- await viewsBeacon.deployed()
- console.log(`CasimirViews beacon upgraded at ${viewsBeacon.address}`)
+ const viewsBeaconFactory = await ethers.getContractFactory("CasimirViews")
+ const viewsBeacon = await upgrades.upgradeBeacon(process.env.VIEWS_BEACON_ADDRESS, viewsBeaconFactory)
+ await viewsBeacon.deployed()
+ console.log(`CasimirViews beacon upgraded at ${viewsBeacon.address}`)
- const factoryFactory = await ethers.getContractFactory('CasimirFactory', {
- libraries: {
- CasimirBeacon: beaconLibrary.address
- }
- })
- const factory = await upgrades.upgradeProxy(process.env.FACTORY_ADDRESS, factoryFactory, {
- constructorArgs: [
- managerBeacon.address,
- poolBeacon.address,
- registryBeacon.address,
- upkeepBeacon.address,
- viewsBeacon.address
- ],
- unsafeAllow: ['external-library-linking']
- })
- await factory.deployed()
- console.log(`CasimirFactory contract upgraded at ${factory.address}`)
+ const factoryFactory = await ethers.getContractFactory("CasimirFactory", {
+ libraries: {
+ CasimirBeacon: beaconLibrary.address
+ }
+ })
+ const factory = await upgrades.upgradeProxy(process.env.FACTORY_ADDRESS, factoryFactory, {
+ constructorArgs: [
+ managerBeacon.address,
+ poolBeacon.address,
+ registryBeacon.address,
+ upkeepBeacon.address,
+ viewsBeacon.address
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await factory.deployed()
+ console.log(`CasimirFactory contract upgraded at ${factory.address}`)
- const [managerId] = await factory.getManagerIds()
- const managerConfig = await factory.getManagerConfig(managerId)
- const upkeep = await ethers.getContractAt('CasimirUpkeep', managerConfig.upkeepAddress)
- await upkeep.setFunctionsOracle(functionsOracle.address)
- await functionsBillingRegistry.setAuthorizedSenders([functionsOracle.address, donTransmitter.address])
- await functionsOracle.setAuthorizedSenders([donTransmitter.address, managerConfig.managerAddress, managerConfig.upkeepAddress])
- await functionsOracle.setRegistry(functionsBillingRegistry.address)
+ const [managerId] = await factory.getManagerIds()
+ const managerConfig = await factory.getManagerConfig(managerId)
+ const upkeep = await ethers.getContractAt("CasimirUpkeep", managerConfig.upkeepAddress)
+ await upkeep.setFunctionsOracle(functionsOracle.address)
+ await functionsBillingRegistry.setAuthorizedSenders([functionsOracle.address, donTransmitter.address])
+ await functionsOracle.setAuthorizedSenders([donTransmitter.address,
+ managerConfig.managerAddress,
+ managerConfig.upkeepAddress])
+ await functionsOracle.setRegistry(functionsBillingRegistry.address)
}()
\ No newline at end of file
diff --git a/contracts/ethereum/scripts/upgrade-proxies.ts b/contracts/ethereum/scripts/upgrade-proxies.ts
index e6043737a..803045402 100644
--- a/contracts/ethereum/scripts/upgrade-proxies.ts
+++ b/contracts/ethereum/scripts/upgrade-proxies.ts
@@ -1,92 +1,92 @@
-import { ethers, upgrades } from 'hardhat'
+import { ethers, upgrades } from "hardhat"
/**
* Upgrade ethereum contracts
*/
void async function () {
- if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error('No functions billing registry address provided')
- if (!process.env.BEACON_LIBRARY_ADDRESS) throw new Error('No beacon library address provided')
- if (!process.env.MANAGER_BEACON_ADDRESS) throw new Error('No manager beacon address provided')
- if (!process.env.POOL_BEACON_ADDRESS) throw new Error('No pool beacon address provided')
- if (!process.env.REGISTRY_BEACON_ADDRESS) throw new Error('No registry beacon address provided')
- if (!process.env.UPKEEP_BEACON_ADDRESS) throw new Error('No upkeep beacon address provided')
- if (!process.env.VIEWS_BEACON_ADDRESS) throw new Error('No views address provided')
- if (!process.env.FACTORY_ADDRESS) throw new Error('No factory address provided')
- if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error('No keeper registrar address provided')
- if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error('No keeper registry address provided')
- if (!process.env.LINK_TOKEN_ADDRESS) throw new Error('No link token address provided')
- if (!process.env.SSV_NETWORK_ADDRESS) throw new Error('No ssv network address provided')
- if (!process.env.SSV_TOKEN_ADDRESS) throw new Error('No ssv token address provided')
- if (!process.env.SSV_VIEWS_ADDRESS) throw new Error('No ssv views address provided')
- if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error('No swap factory address provided')
- if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error('No swap router address provided')
- if (!process.env.WETH_TOKEN_ADDRESS) throw new Error('No weth token address provided')
+ if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error("No functions billing registry address provided")
+ if (!process.env.BEACON_LIBRARY_ADDRESS) throw new Error("No beacon library address provided")
+ if (!process.env.MANAGER_BEACON_ADDRESS) throw new Error("No manager beacon address provided")
+ if (!process.env.POOL_BEACON_ADDRESS) throw new Error("No pool beacon address provided")
+ if (!process.env.REGISTRY_BEACON_ADDRESS) throw new Error("No registry beacon address provided")
+ if (!process.env.UPKEEP_BEACON_ADDRESS) throw new Error("No upkeep beacon address provided")
+ if (!process.env.VIEWS_BEACON_ADDRESS) throw new Error("No views address provided")
+ if (!process.env.FACTORY_ADDRESS) throw new Error("No factory address provided")
+ if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error("No keeper registrar address provided")
+ if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error("No keeper registry address provided")
+ if (!process.env.LINK_TOKEN_ADDRESS) throw new Error("No link token address provided")
+ if (!process.env.SSV_NETWORK_ADDRESS) throw new Error("No ssv network address provided")
+ if (!process.env.SSV_TOKEN_ADDRESS) throw new Error("No ssv token address provided")
+ if (!process.env.SSV_VIEWS_ADDRESS) throw new Error("No ssv views address provided")
+ if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error("No swap factory address provided")
+ if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error("No swap router address provided")
+ if (!process.env.WETH_TOKEN_ADDRESS) throw new Error("No weth token address provided")
- const managerBeaconFactory = await ethers.getContractFactory('CasimirManager', {
- libraries: {
- CasimirBeacon: process.env.BEACON_LIBRARY_ADDRESS
- }
- })
- const managerBeacon = await upgrades.upgradeBeacon(process.env.MANAGER_BEACON_ADDRESS, managerBeaconFactory, {
- constructorArgs: [
- process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS,
- process.env.KEEPER_REGISTRAR_ADDRESS,
- process.env.KEEPER_REGISTRY_ADDRESS,
- process.env.LINK_TOKEN_ADDRESS,
- process.env.SSV_NETWORK_ADDRESS,
- process.env.SSV_TOKEN_ADDRESS,
- process.env.SWAP_FACTORY_ADDRESS,
- process.env.SWAP_ROUTER_ADDRESS,
- process.env.WETH_TOKEN_ADDRESS
- ],
- unsafeAllow: ['external-library-linking']
- })
- await managerBeacon.deployed()
- console.log(`CasimirManager beacon upgraded at ${managerBeacon.address}`)
+ const managerBeaconFactory = await ethers.getContractFactory("CasimirManager", {
+ libraries: {
+ CasimirBeacon: process.env.BEACON_LIBRARY_ADDRESS
+ }
+ })
+ const managerBeacon = await upgrades.upgradeBeacon(process.env.MANAGER_BEACON_ADDRESS, managerBeaconFactory, {
+ constructorArgs: [
+ process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS,
+ process.env.KEEPER_REGISTRAR_ADDRESS,
+ process.env.KEEPER_REGISTRY_ADDRESS,
+ process.env.LINK_TOKEN_ADDRESS,
+ process.env.SSV_NETWORK_ADDRESS,
+ process.env.SSV_TOKEN_ADDRESS,
+ process.env.SWAP_FACTORY_ADDRESS,
+ process.env.SWAP_ROUTER_ADDRESS,
+ process.env.WETH_TOKEN_ADDRESS
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await managerBeacon.deployed()
+ console.log(`CasimirManager beacon upgraded at ${managerBeacon.address}`)
- const poolBeaconFactory = await ethers.getContractFactory('CasimirPool')
- const poolBeacon = await upgrades.upgradeBeacon(process.env.POOL_BEACON_ADDRESS, poolBeaconFactory, {
- constructorArgs: [
- process.env.DEPOSIT_CONTRACT_ADDRESS
- ]
- })
- await poolBeacon.deployed()
- console.log(`CasimirPool beacon upgraded at ${poolBeacon.address}`)
+ const poolBeaconFactory = await ethers.getContractFactory("CasimirPool")
+ const poolBeacon = await upgrades.upgradeBeacon(process.env.POOL_BEACON_ADDRESS, poolBeaconFactory, {
+ constructorArgs: [
+ process.env.DEPOSIT_CONTRACT_ADDRESS
+ ]
+ })
+ await poolBeacon.deployed()
+ console.log(`CasimirPool beacon upgraded at ${poolBeacon.address}`)
- const registryBeaconFactory = await ethers.getContractFactory('CasimirRegistry')
- const registryBeacon = await upgrades.upgradeBeacon(process.env.REGISTRY_BEACON_ADDRESS, registryBeaconFactory, {
- constructorArgs: [
- process.env.SSV_VIEWS_ADDRESS
- ]
- })
- await registryBeacon.deployed()
- console.log(`CasimirRegistry beacon upgraded at ${registryBeacon.address}`)
+ const registryBeaconFactory = await ethers.getContractFactory("CasimirRegistry")
+ const registryBeacon = await upgrades.upgradeBeacon(process.env.REGISTRY_BEACON_ADDRESS, registryBeaconFactory, {
+ constructorArgs: [
+ process.env.SSV_VIEWS_ADDRESS
+ ]
+ })
+ await registryBeacon.deployed()
+ console.log(`CasimirRegistry beacon upgraded at ${registryBeacon.address}`)
- const upkeepBeaconFactory = await ethers.getContractFactory('CasimirUpkeep')
- const upkeepBeacon = await upgrades.upgradeBeacon(process.env.UPKEEP_BEACON_ADDRESS, upkeepBeaconFactory)
- await upkeepBeacon.deployed()
- console.log(`CasimirUpkeep beacon upgraded at ${upkeepBeacon.address}`)
+ const upkeepBeaconFactory = await ethers.getContractFactory("CasimirUpkeep")
+ const upkeepBeacon = await upgrades.upgradeBeacon(process.env.UPKEEP_BEACON_ADDRESS, upkeepBeaconFactory)
+ await upkeepBeacon.deployed()
+ console.log(`CasimirUpkeep beacon upgraded at ${upkeepBeacon.address}`)
- const viewsBeaconFactory = await ethers.getContractFactory('CasimirViews')
- const viewsBeacon = await upgrades.upgradeBeacon(process.env.VIEWS_BEACON_ADDRESS, viewsBeaconFactory)
- await viewsBeacon.deployed()
- console.log(`CasimirViews beacon upgraded at ${viewsBeacon.address}`)
+ const viewsBeaconFactory = await ethers.getContractFactory("CasimirViews")
+ const viewsBeacon = await upgrades.upgradeBeacon(process.env.VIEWS_BEACON_ADDRESS, viewsBeaconFactory)
+ await viewsBeacon.deployed()
+ console.log(`CasimirViews beacon upgraded at ${viewsBeacon.address}`)
- const factoryFactory = await ethers.getContractFactory('CasimirFactory', {
- libraries: {
- CasimirBeacon: process.env.BEACON_LIBRARY_ADDRESS
- }
- })
- const factory = await upgrades.upgradeProxy(process.env.FACTORY_ADDRESS, factoryFactory, {
- constructorArgs: [
- managerBeacon.address,
- poolBeacon.address,
- registryBeacon.address,
- upkeepBeacon.address,
- viewsBeacon.address
- ],
- unsafeAllow: ['external-library-linking']
- })
- await factory.deployed()
- console.log(`CasimirFactory contract upgraded at ${factory.address}`)
+ const factoryFactory = await ethers.getContractFactory("CasimirFactory", {
+ libraries: {
+ CasimirBeacon: process.env.BEACON_LIBRARY_ADDRESS
+ }
+ })
+ const factory = await upgrades.upgradeProxy(process.env.FACTORY_ADDRESS, factoryFactory, {
+ constructorArgs: [
+ managerBeacon.address,
+ poolBeacon.address,
+ registryBeacon.address,
+ upkeepBeacon.address,
+ viewsBeacon.address
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await factory.deployed()
+ console.log(`CasimirFactory contract upgraded at ${factory.address}`)
}()
\ No newline at end of file
diff --git a/contracts/ethereum/test/debug.ts b/contracts/ethereum/test/debug.ts
index 03a86c24f..647ea1b63 100644
--- a/contracts/ethereum/test/debug.ts
+++ b/contracts/ethereum/test/debug.ts
@@ -1,103 +1,103 @@
// import { expect } from 'chai'
-import fs from 'fs'
-import { ethers, upgrades } from 'hardhat'
-import { ETHEREUM_CONTRACTS } from '@casimir/env'
-import CasimirFactoryAbi from '../build/abi/CasimirFactory.json'
-import ICasimirManagerDevAbi from '../build/abi/ICasimirManagerDev.json'
-import ICasimirRegistryAbi from '../build/abi/ICasimirRegistry.json'
-import ICasimirUpkeepDevAbi from '../build/abi/ICasimirUpkeepDev.json'
-import ICasimirViewsAbi from '../build/abi/ICasimirViews.json'
-import { CasimirManagerDev, CasimirRegistry, CasimirUpkeepDev, CasimirViews } from '../build/@types'
+import fs from "fs"
+import { ethers, upgrades } from "hardhat"
+import { ETHEREUM_CONTRACTS } from "@casimir/env"
+import CasimirFactoryAbi from "../build/abi/CasimirFactory.json"
+import ICasimirManagerDevAbi from "../build/abi/ICasimirManagerDev.json"
+import ICasimirRegistryAbi from "../build/abi/ICasimirRegistry.json"
+import ICasimirUpkeepDevAbi from "../build/abi/ICasimirUpkeepDev.json"
+import ICasimirViewsAbi from "../build/abi/ICasimirViews.json"
+import { CasimirManagerDev, CasimirRegistry, CasimirUpkeepDev, CasimirViews } from "../build/@types"
-describe('Upgrades', async function () {
- it('Check values with dev', async function () {
- if (process.env.DEBUG) {
- const debugBlockNumber = process.env.ETHEREUM_FORK_BLOCK ? parseInt(process.env.ETHEREUM_FORK_BLOCK) : await ethers.provider.getBlockNumber()
- const networkKey = (process.env.NETWORK?.toUpperCase() || 'TESTNET') as keyof typeof ETHEREUM_CONTRACTS
- const factory = new ethers.Contract(ETHEREUM_CONTRACTS[networkKey].FACTORY_ADDRESS, CasimirFactoryAbi, ethers.provider)
- const [managerId] = await factory.getManagerIds()
- const managerConfig = await factory.getManagerConfig(managerId)
+describe("Upgrades", async function () {
+ it("Check values with dev", async function () {
+ if (process.env.DEBUG) {
+ const debugBlockNumber = process.env.ETHEREUM_FORK_BLOCK ? parseInt(process.env.ETHEREUM_FORK_BLOCK) : await ethers.provider.getBlockNumber()
+ const networkKey = (process.env.NETWORK?.toUpperCase() || "TESTNET") as keyof typeof ETHEREUM_CONTRACTS
+ const factory = new ethers.Contract(ETHEREUM_CONTRACTS[networkKey].FACTORY_ADDRESS, CasimirFactoryAbi, ethers.provider)
+ const [managerId] = await factory.getManagerIds()
+ const managerConfig = await factory.getManagerConfig(managerId)
- const managerDevFactory = await ethers.getContractFactory('CasimirManagerDev', {
- libraries: {
- CasimirBeacon: ETHEREUM_CONTRACTS[networkKey].BEACON_LIBRARY_ADDRESS
- }
- })
- const managerBeacon = await upgrades.upgradeBeacon(ETHEREUM_CONTRACTS[networkKey].MANAGER_BEACON_ADDRESS, managerDevFactory, {
- constructorArgs: [
- ETHEREUM_CONTRACTS[networkKey].FUNCTIONS_BILLING_REGISTRY_ADDRESS,
- ETHEREUM_CONTRACTS[networkKey].KEEPER_REGISTRAR_ADDRESS,
- ETHEREUM_CONTRACTS[networkKey].KEEPER_REGISTRY_ADDRESS,
- ETHEREUM_CONTRACTS[networkKey].LINK_TOKEN_ADDRESS,
- ETHEREUM_CONTRACTS[networkKey].SSV_NETWORK_ADDRESS,
- ETHEREUM_CONTRACTS[networkKey].SSV_TOKEN_ADDRESS,
- ETHEREUM_CONTRACTS[networkKey].SWAP_FACTORY_ADDRESS,
- ETHEREUM_CONTRACTS[networkKey].SWAP_ROUTER_ADDRESS,
- ETHEREUM_CONTRACTS[networkKey].WETH_TOKEN_ADDRESS
- ],
- unsafeAllow: ['external-library-linking']
- })
- await managerBeacon.deployed()
- const manager = new ethers.Contract(managerConfig.managerAddress, ICasimirManagerDevAbi, ethers.provider) as CasimirManagerDev
- console.log(`CasimirManager beacon upgraded at ${manager.address}`)
+ const managerDevFactory = await ethers.getContractFactory("CasimirManagerDev", {
+ libraries: {
+ CasimirBeacon: ETHEREUM_CONTRACTS[networkKey].BEACON_LIBRARY_ADDRESS
+ }
+ })
+ const managerBeacon = await upgrades.upgradeBeacon(ETHEREUM_CONTRACTS[networkKey].MANAGER_BEACON_ADDRESS, managerDevFactory, {
+ constructorArgs: [
+ ETHEREUM_CONTRACTS[networkKey].FUNCTIONS_BILLING_REGISTRY_ADDRESS,
+ ETHEREUM_CONTRACTS[networkKey].KEEPER_REGISTRAR_ADDRESS,
+ ETHEREUM_CONTRACTS[networkKey].KEEPER_REGISTRY_ADDRESS,
+ ETHEREUM_CONTRACTS[networkKey].LINK_TOKEN_ADDRESS,
+ ETHEREUM_CONTRACTS[networkKey].SSV_NETWORK_ADDRESS,
+ ETHEREUM_CONTRACTS[networkKey].SSV_TOKEN_ADDRESS,
+ ETHEREUM_CONTRACTS[networkKey].SWAP_FACTORY_ADDRESS,
+ ETHEREUM_CONTRACTS[networkKey].SWAP_ROUTER_ADDRESS,
+ ETHEREUM_CONTRACTS[networkKey].WETH_TOKEN_ADDRESS
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await managerBeacon.deployed()
+ const manager = new ethers.Contract(managerConfig.managerAddress, ICasimirManagerDevAbi, ethers.provider) as CasimirManagerDev
+ console.log(`CasimirManager beacon upgraded at ${manager.address}`)
- const registry = new ethers.Contract(managerConfig.registryAddress, ICasimirRegistryAbi, ethers.provider) as CasimirRegistry
+ const registry = new ethers.Contract(managerConfig.registryAddress, ICasimirRegistryAbi, ethers.provider) as CasimirRegistry
- const upkeepDevFactory = await ethers.getContractFactory('CasimirUpkeepDev')
- const upkeepBeacon = await upgrades.upgradeBeacon(ETHEREUM_CONTRACTS['TESTNET'].UPKEEP_BEACON_ADDRESS, upkeepDevFactory)
- await upkeepBeacon.deployed()
- const upkeep = new ethers.Contract(managerConfig.upkeepAddress, ICasimirUpkeepDevAbi, ethers.provider) as CasimirUpkeepDev
- console.log(`CasimirUpkeep beacon upgraded at ${upkeep.address}`)
+ const upkeepDevFactory = await ethers.getContractFactory("CasimirUpkeepDev")
+ const upkeepBeacon = await upgrades.upgradeBeacon(ETHEREUM_CONTRACTS["TESTNET"].UPKEEP_BEACON_ADDRESS, upkeepDevFactory)
+ await upkeepBeacon.deployed()
+ const upkeep = new ethers.Contract(managerConfig.upkeepAddress, ICasimirUpkeepDevAbi, ethers.provider) as CasimirUpkeepDev
+ console.log(`CasimirUpkeep beacon upgraded at ${upkeep.address}`)
- const views = new ethers.Contract(managerConfig.viewsAddress, ICasimirViewsAbi, ethers.provider) as CasimirViews
+ const views = new ethers.Contract(managerConfig.viewsAddress, ICasimirViewsAbi, ethers.provider) as CasimirViews
- const latestActiveRewardBalance = await manager.getLatestActiveRewardBalance()
- const latestBeaconBalance = await manager.latestBeaconBalance()
- const stakeRatioSum = await manager.getStakeRatioSum()
- const totalStake = await manager.getTotalStake()
- const deposits = await manager.queryFilter(manager.filters.StakeDeposited(), 0, debugBlockNumber)
- const userAddresses = deposits.map(deposit => deposit.args?.sender).filter((value, index, self) => self.indexOf(value) === index)
- const userStakes: Record = {}
- for (const userAddress of userAddresses) {
- const userStake = await manager.getUserStake(userAddress)
- userStakes[userAddress] = ethers.utils.formatEther(userStake)
- }
+ const latestActiveRewardBalance = await manager.getLatestActiveRewardBalance()
+ const latestBeaconBalance = await manager.latestBeaconBalance()
+ const stakeRatioSum = await manager.getStakeRatioSum()
+ const totalStake = await manager.getTotalStake()
+ const deposits = await manager.queryFilter(manager.filters.StakeDeposited(), 0, debugBlockNumber)
+ const userAddresses = deposits.map(deposit => deposit.args?.sender).filter((value, index, self) => self.indexOf(value) === index)
+ const userStakes: Record = {}
+ for (const userAddress of userAddresses) {
+ const userStake = await manager.getUserStake(userAddress)
+ userStakes[userAddress] = ethers.utils.formatEther(userStake)
+ }
- // const depositedPoolCount = await views.getDepositedPoolCount()
- // const compoundablePoolIds = await views.getCompoundablePoolIds(0, depositedPoolCount)
- // const sweptBalance = await views.getSweptBalance(0, depositedPoolCount)
+ // const depositedPoolCount = await views.getDepositedPoolCount()
+ // const compoundablePoolIds = await views.getCompoundablePoolIds(0, depositedPoolCount)
+ // const sweptBalance = await views.getSweptBalance(0, depositedPoolCount)
- const dust = totalStake.sub(Object.values(userStakes).reduce((acc, curr) => {
- return acc.add(ethers.utils.parseEther(curr))
- }, ethers.utils.parseEther('0')))
- const values = {
- // compoundablePoolIds,
- dust: ethers.utils.formatEther(dust),
- latestActiveRewardBalance: ethers.utils.formatEther(latestActiveRewardBalance),
- latestBeaconBalance: ethers.utils.formatEther(latestBeaconBalance),
- stakeRatioSum: ethers.utils.formatEther(stakeRatioSum),
- // sweptBalance: ethers.utils.formatEther(sweptBalance),
- totalStake: ethers.utils.formatEther(totalStake),
- userStakes
- }
- const debugBlock = {
- block: debugBlockNumber,
- values
- }
- const debugBlocksDir = 'debug'
- const debugBlocksFile = 'blocks.json'
- const debugBlocksPath = `${debugBlocksDir}/${debugBlocksFile}`
- if (!fs.existsSync(debugBlocksDir)) {
- fs.mkdirSync(debugBlocksDir, { recursive: true })
- }
- let existingDebugBlocks: typeof debugBlock[]
- try {
- existingDebugBlocks = JSON.parse(fs.readFileSync(debugBlocksPath).toString())
- } catch (e) {
- existingDebugBlocks = []
- }
- existingDebugBlocks.push(debugBlock)
- fs.writeFileSync(debugBlocksPath, JSON.stringify(existingDebugBlocks, null, 4))
- }
- })
+ const dust = totalStake.sub(Object.values(userStakes).reduce((acc, curr) => {
+ return acc.add(ethers.utils.parseEther(curr))
+ }, ethers.utils.parseEther("0")))
+ const values = {
+ // compoundablePoolIds,
+ dust: ethers.utils.formatEther(dust),
+ latestActiveRewardBalance: ethers.utils.formatEther(latestActiveRewardBalance),
+ latestBeaconBalance: ethers.utils.formatEther(latestBeaconBalance),
+ stakeRatioSum: ethers.utils.formatEther(stakeRatioSum),
+ // sweptBalance: ethers.utils.formatEther(sweptBalance),
+ totalStake: ethers.utils.formatEther(totalStake),
+ userStakes
+ }
+ const debugBlock = {
+ block: debugBlockNumber,
+ values
+ }
+ const debugBlocksDir = "debug"
+ const debugBlocksFile = "blocks.json"
+ const debugBlocksPath = `${debugBlocksDir}/${debugBlocksFile}`
+ if (!fs.existsSync(debugBlocksDir)) {
+ fs.mkdirSync(debugBlocksDir, { recursive: true })
+ }
+ let existingDebugBlocks: typeof debugBlock[]
+ try {
+ existingDebugBlocks = JSON.parse(fs.readFileSync(debugBlocksPath).toString())
+ } catch (e) {
+ existingDebugBlocks = []
+ }
+ existingDebugBlocks.push(debugBlock)
+ fs.writeFileSync(debugBlocksPath, JSON.stringify(existingDebugBlocks, null, 4))
+ }
+ })
})
\ No newline at end of file
diff --git a/contracts/ethereum/test/fixtures/shared.ts b/contracts/ethereum/test/fixtures/shared.ts
index 8193fcad9..0d3eda3cd 100644
--- a/contracts/ethereum/test/fixtures/shared.ts
+++ b/contracts/ethereum/test/fixtures/shared.ts
@@ -1,80 +1,81 @@
-import { ethers, network, upgrades } from 'hardhat'
-import { loadFixture, time, setBalance } from '@nomicfoundation/hardhat-network-helpers'
-import { AuthorizedReceiver, CasimirFactory, CasimirManager, CasimirRegistry, CasimirUpkeep, CasimirViews, FunctionsBillingRegistry, FunctionsOracle, FunctionsOracleFactory, ISSVViews } from '../../build/@types'
-import { fulfillReport, runUpkeep } from '../../helpers/upkeep'
-import { activatePoolsHandler, depositFunctionsBalanceHandler, depositUpkeepBalanceHandler, initiatePoolHandler, reportCompletedExitsHandler } from '../../helpers/oracle'
-import { round } from '../../helpers/math'
-import ISSVViewsAbi from '../../build/abi/ISSVViews.json'
-import requestConfig from '@casimir/functions/Functions-request-config'
+import { ethers, network, upgrades } from "hardhat"
+import { loadFixture, time, setBalance } from "@nomicfoundation/hardhat-network-helpers"
+import { AuthorizedReceiver, CasimirFactory, CasimirManager, CasimirRegistry, CasimirUpkeep, CasimirViews, FunctionsBillingRegistry, FunctionsOracle, FunctionsOracleFactory, ISSVViews } from "../../build/@types"
+import { fulfillReport, runUpkeep } from "../../helpers/upkeep"
+import { activatePoolsHandler, depositFunctionsBalanceHandler, depositUpkeepBalanceHandler, initiatePoolHandler, reportCompletedExitsHandler } from "../../helpers/oracle"
+import { round } from "../../helpers/math"
+import ISSVViewsAbi from "../../build/abi/ISSVViews.json"
+import requestConfig from "@casimir/functions/Functions-request-config"
upgrades.silenceWarnings()
/** Fixture to deploy SSV manager contract */
export async function deploymentFixture() {
- if (!process.env.DEPOSIT_CONTRACT_ADDRESS) throw new Error('No deposit contract address provided')
- if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error('No keeper registrar address provided')
- if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error('No keeper registry address provided')
- if (!process.env.LINK_TOKEN_ADDRESS) throw new Error('No link token address provided')
- if (!process.env.LINK_ETH_FEED_ADDRESS) throw new Error('No link eth feed address provided')
- if (!process.env.SSV_NETWORK_ADDRESS) throw new Error('No ssv network address provided')
- if (!process.env.SSV_TOKEN_ADDRESS) throw new Error('No ssv token address provided')
- if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error('No swap factory address provided')
- if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error('No swap router address provided')
- if (!process.env.WETH_TOKEN_ADDRESS) throw new Error('No weth token address provided')
-
- const [, daoOracle, donTransmitter] = await ethers.getSigners()
-
- const functionsOracleFactoryFactory = await ethers.getContractFactory('FunctionsOracleFactory')
- const functionsOracleFactory = await functionsOracleFactoryFactory.deploy() as FunctionsOracleFactory
- await functionsOracleFactory.deployed()
-
- const deployNewOracle = await functionsOracleFactory.deployNewOracle()
- const deployNewOracleReceipt = await deployNewOracle.wait()
- if (!deployNewOracleReceipt.events) throw new Error('Functions oracle deployment failed')
- const functionsOracleAddress = deployNewOracleReceipt.events[1].args?.don as string
- const functionsOracle = await ethers.getContractAt('FunctionsOracle', functionsOracleAddress) as FunctionsOracle & AuthorizedReceiver
- const acceptOwnership = await functionsOracle.acceptOwnership()
- await acceptOwnership.wait()
-
- const functionsBillingRegistryArgs = {
- linkTokenAddress: process.env.LINK_TOKEN_ADDRESS,
- linkEthFeedAddress: process.env.LINK_ETH_FEED_ADDRESS,
- functionsOracleAddress: functionsOracle.address
- }
- const functionsBillingRegistryFactory = await ethers.getContractFactory('FunctionsBillingRegistry')
- const functionsBillingRegistry = await functionsBillingRegistryFactory.deploy(...Object.values(functionsBillingRegistryArgs)) as FunctionsBillingRegistry
- await functionsBillingRegistry.deployed()
-
- const functionsBillingRegistryConfig = {
- maxGasLimit: 400_000,
- stalenessSeconds: 86_400,
- gasAfterPaymentCalculation:
+ if (!process.env.DEPOSIT_CONTRACT_ADDRESS) throw new Error("No deposit contract address provided")
+ if (!process.env.KEEPER_REGISTRAR_ADDRESS) throw new Error("No keeper registrar address provided")
+ if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error("No keeper registry address provided")
+ if (!process.env.LINK_TOKEN_ADDRESS) throw new Error("No link token address provided")
+ if (!process.env.LINK_ETH_FEED_ADDRESS) throw new Error("No link eth feed address provided")
+ if (!process.env.SSV_NETWORK_ADDRESS) throw new Error("No ssv network address provided")
+ if (!process.env.SSV_TOKEN_ADDRESS) throw new Error("No ssv token address provided")
+ if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error("No swap factory address provided")
+ if (!process.env.SWAP_ROUTER_ADDRESS) throw new Error("No swap router address provided")
+ if (!process.env.WETH_TOKEN_ADDRESS) throw new Error("No weth token address provided")
+
+ const [, daoOracle,
+ donTransmitter] = await ethers.getSigners()
+
+ const functionsOracleFactoryFactory = await ethers.getContractFactory("FunctionsOracleFactory")
+ const functionsOracleFactory = await functionsOracleFactoryFactory.deploy() as FunctionsOracleFactory
+ await functionsOracleFactory.deployed()
+
+ const deployNewOracle = await functionsOracleFactory.deployNewOracle()
+ const deployNewOracleReceipt = await deployNewOracle.wait()
+ if (!deployNewOracleReceipt.events) throw new Error("Functions oracle deployment failed")
+ const functionsOracleAddress = deployNewOracleReceipt.events[1].args?.don as string
+ const functionsOracle = await ethers.getContractAt("FunctionsOracle", functionsOracleAddress) as FunctionsOracle & AuthorizedReceiver
+ const acceptOwnership = await functionsOracle.acceptOwnership()
+ await acceptOwnership.wait()
+
+ const functionsBillingRegistryArgs = {
+ linkTokenAddress: process.env.LINK_TOKEN_ADDRESS,
+ linkEthFeedAddress: process.env.LINK_ETH_FEED_ADDRESS,
+ functionsOracleAddress: functionsOracle.address
+ }
+ const functionsBillingRegistryFactory = await ethers.getContractFactory("FunctionsBillingRegistry")
+ const functionsBillingRegistry = await functionsBillingRegistryFactory.deploy(...Object.values(functionsBillingRegistryArgs)) as FunctionsBillingRegistry
+ await functionsBillingRegistry.deployed()
+
+ const functionsBillingRegistryConfig = {
+ maxGasLimit: 400_000,
+ stalenessSeconds: 86_400,
+ gasAfterPaymentCalculation:
21_000 + 5_000 + 2_100 + 20_000 + 2 * 2_100 - 15_000 + 7_315,
- weiPerUnitLink: ethers.BigNumber.from('5000000000000000'),
- gasOverhead: 100_000,
- requestTimeoutSeconds: 300,
+ weiPerUnitLink: ethers.BigNumber.from("5000000000000000"),
+ gasOverhead: 100_000,
+ requestTimeoutSeconds: 300,
+ }
+
+ await functionsBillingRegistry.setConfig(
+ functionsBillingRegistryConfig.maxGasLimit,
+ functionsBillingRegistryConfig.stalenessSeconds,
+ functionsBillingRegistryConfig.gasAfterPaymentCalculation,
+ functionsBillingRegistryConfig.weiPerUnitLink,
+ functionsBillingRegistryConfig.gasOverhead,
+ functionsBillingRegistryConfig.requestTimeoutSeconds
+ )
+
+ const beaconLibraryFactory = await ethers.getContractFactory("CasimirBeacon")
+ const beaconLibrary = await beaconLibraryFactory.deploy()
+
+ const managerBeaconFactory = await ethers.getContractFactory("CasimirManager", {
+ libraries: {
+ CasimirBeacon: beaconLibrary.address
}
-
- await functionsBillingRegistry.setConfig(
- functionsBillingRegistryConfig.maxGasLimit,
- functionsBillingRegistryConfig.stalenessSeconds,
- functionsBillingRegistryConfig.gasAfterPaymentCalculation,
- functionsBillingRegistryConfig.weiPerUnitLink,
- functionsBillingRegistryConfig.gasOverhead,
- functionsBillingRegistryConfig.requestTimeoutSeconds
- )
-
- const beaconLibraryFactory = await ethers.getContractFactory('CasimirBeacon')
- const beaconLibrary = await beaconLibraryFactory.deploy()
-
- const managerBeaconFactory = await ethers.getContractFactory('CasimirManager', {
- libraries: {
- CasimirBeacon: beaconLibrary.address
- }
- })
- const managerBeacon = await upgrades.deployBeacon(managerBeaconFactory, {
- constructorArgs: [
- functionsBillingRegistry.address,
+ })
+ const managerBeacon = await upgrades.deployBeacon(managerBeaconFactory, {
+ constructorArgs: [
+ functionsBillingRegistry.address,
process.env.KEEPER_REGISTRAR_ADDRESS as string,
process.env.KEEPER_REGISTRY_ADDRESS as string,
process.env.LINK_TOKEN_ADDRESS as string,
@@ -83,618 +84,678 @@ export async function deploymentFixture() {
process.env.SWAP_FACTORY_ADDRESS as string,
process.env.SWAP_ROUTER_ADDRESS as string,
process.env.WETH_TOKEN_ADDRESS as string
- ],
- unsafeAllow: ['external-library-linking']
- })
- await managerBeacon.deployed()
-
- const poolBeaconFactory = await ethers.getContractFactory('CasimirPool')
- const poolBeacon = await upgrades.deployBeacon(poolBeaconFactory, {
- constructorArgs: [
+ ],
+ unsafeAllow: ["external-library-linking"]
+ })
+ await managerBeacon.deployed()
+
+ const poolBeaconFactory = await ethers.getContractFactory("CasimirPool")
+ const poolBeacon = await upgrades.deployBeacon(poolBeaconFactory, {
+ constructorArgs: [
process.env.DEPOSIT_CONTRACT_ADDRESS as string
- ]
- })
- await poolBeacon.deployed()
+ ]
+ })
+ await poolBeacon.deployed()
- const registryBeaconFactory = await ethers.getContractFactory('CasimirRegistry')
- const registryBeacon = await upgrades.deployBeacon(registryBeaconFactory, {
- constructorArgs: [
+ const registryBeaconFactory = await ethers.getContractFactory("CasimirRegistry")
+ const registryBeacon = await upgrades.deployBeacon(registryBeaconFactory, {
+ constructorArgs: [
process.env.SSV_VIEWS_ADDRESS as string
- ]
- })
- await registryBeacon.deployed()
+ ]
+ })
+ await registryBeacon.deployed()
- const upkeepBeaconFactory = await ethers.getContractFactory('CasimirUpkeep')
- const upkeepBeacon = await upgrades.deployBeacon(upkeepBeaconFactory)
- await upkeepBeacon.deployed()
+ const upkeepBeaconFactory = await ethers.getContractFactory("CasimirUpkeep")
+ const upkeepBeacon = await upgrades.deployBeacon(upkeepBeaconFactory)
+ await upkeepBeacon.deployed()
- const viewsBeaconFactory = await ethers.getContractFactory('CasimirViews')
- const viewsBeacon = await upgrades.deployBeacon(viewsBeaconFactory)
- await viewsBeacon.deployed()
+ const viewsBeaconFactory = await ethers.getContractFactory("CasimirViews")
+ const viewsBeacon = await upgrades.deployBeacon(viewsBeaconFactory)
+ await viewsBeacon.deployed()
- const factoryFactory = await ethers.getContractFactory('CasimirFactory', {
- libraries: {
- CasimirBeacon: beaconLibrary.address
- }
- })
- const factory = await upgrades.deployProxy(factoryFactory, undefined, {
- constructorArgs: [
- managerBeacon.address,
- poolBeacon.address,
- registryBeacon.address,
- upkeepBeacon.address,
- viewsBeacon.address
- ],
- unsafeAllow: ['external-library-linking']
- }) as CasimirFactory
- await factory.deployed()
-
- const simpleStrategy = {
- minCollateral: ethers.utils.parseEther('1.0'),
- lockPeriod: 0,
- userFee: 5,
- compoundStake: true,
- eigenStake: false,
- liquidStake: false,
- privateOperators: false,
- verifiedOperators: false
- }
- const deploySimpleManager = await factory.deployManager(
- daoOracle.address,
- functionsOracle.address,
- simpleStrategy
- )
- await deploySimpleManager.wait()
- const [managerId] = await factory.getManagerIds()
- const [managerAddress, registryAddress, upkeepAddress, viewsAddress] = await factory.getManagerConfig(managerId)
- const manager = await ethers.getContractAt('CasimirManager', managerAddress) as CasimirManager
- const registry = await ethers.getContractAt('CasimirRegistry', registryAddress) as CasimirRegistry
- const upkeep = await ethers.getContractAt('CasimirUpkeep', upkeepAddress) as CasimirUpkeep
- const views = await ethers.getContractAt('CasimirViews', viewsAddress) as CasimirViews
-
- requestConfig.args[1] = viewsAddress
- const fulfillGasLimit = 300000
- const setRequest = await upkeep.setFunctionsRequest(requestConfig.source, requestConfig.args, fulfillGasLimit)
- await setRequest.wait()
-
- await functionsBillingRegistry.setAuthorizedSenders([donTransmitter.address, functionsOracle.address])
- await functionsOracle.setRegistry(functionsBillingRegistry.address)
- await functionsOracle.setAuthorizedSenders([donTransmitter.address, manager.address, upkeep.address])
-
- const ssvViews = await ethers.getContractAt(ISSVViewsAbi, process.env.SSV_VIEWS_ADDRESS as string) as ISSVViews
-
- return {
- managerBeacon,
- poolBeacon,
- registryBeacon,
- upkeepBeacon,
- viewsBeacon,
- factory,
- manager,
- registry,
- upkeep,
- views,
- functionsBillingRegistry,
- functionsOracle,
- ssvViews,
- daoOracle,
- donTransmitter
+ const factoryFactory = await ethers.getContractFactory("CasimirFactory", {
+ libraries: {
+ CasimirBeacon: beaconLibrary.address
}
+ })
+ const factory = await upgrades.deployProxy(factoryFactory, undefined, {
+ constructorArgs: [
+ managerBeacon.address,
+ poolBeacon.address,
+ registryBeacon.address,
+ upkeepBeacon.address,
+ viewsBeacon.address
+ ],
+ unsafeAllow: ["external-library-linking"]
+ }) as CasimirFactory
+ await factory.deployed()
+
+ const simpleStrategy = {
+ minCollateral: ethers.utils.parseEther("1.0"),
+ lockPeriod: 0,
+ userFee: 5,
+ compoundStake: true,
+ eigenStake: false,
+ liquidStake: false,
+ privateOperators: false,
+ verifiedOperators: false
+ }
+ const deploySimpleManager = await factory.deployManager(
+ daoOracle.address,
+ functionsOracle.address,
+ simpleStrategy
+ )
+ await deploySimpleManager.wait()
+ const [managerId] = await factory.getManagerIds()
+ const [managerAddress,
+ registryAddress,
+ upkeepAddress,
+ viewsAddress] = await factory.getManagerConfig(managerId)
+ const manager = await ethers.getContractAt("CasimirManager", managerAddress) as CasimirManager
+ const registry = await ethers.getContractAt("CasimirRegistry", registryAddress) as CasimirRegistry
+ const upkeep = await ethers.getContractAt("CasimirUpkeep", upkeepAddress) as CasimirUpkeep
+ const views = await ethers.getContractAt("CasimirViews", viewsAddress) as CasimirViews
+
+ requestConfig.args[1] = viewsAddress
+ const fulfillGasLimit = 300000
+ const setRequest = await upkeep.setFunctionsRequest(requestConfig.source, requestConfig.args, fulfillGasLimit)
+ await setRequest.wait()
+
+ await functionsBillingRegistry.setAuthorizedSenders([donTransmitter.address, functionsOracle.address])
+ await functionsOracle.setRegistry(functionsBillingRegistry.address)
+ await functionsOracle.setAuthorizedSenders([donTransmitter.address,
+ manager.address,
+ upkeep.address])
+
+ const ssvViews = await ethers.getContractAt(ISSVViewsAbi, process.env.SSV_VIEWS_ADDRESS as string) as ISSVViews
+
+ return {
+ managerBeacon,
+ poolBeacon,
+ registryBeacon,
+ upkeepBeacon,
+ viewsBeacon,
+ factory,
+ manager,
+ registry,
+ upkeep,
+ views,
+ functionsBillingRegistry,
+ functionsOracle,
+ ssvViews,
+ daoOracle,
+ donTransmitter
+ }
}
/** Fixture to preregister operators */
export async function preregistrationFixture() {
- const {
- managerBeacon,
- poolBeacon,
- registryBeacon,
- upkeepBeacon,
- viewsBeacon,
- factory,
- manager,
- registry,
- upkeep,
- views,
- functionsBillingRegistry,
- functionsOracle,
- ssvViews,
- daoOracle,
- donTransmitter
- } = await loadFixture(deploymentFixture)
-
- const preregisteredOperatorIds = process.env.PREREGISTERED_OPERATOR_IDS?.split(',').map(id => parseInt(id)) || [208, 209, 210, 211/*, 212, 213, 214, 215*/]
- if (preregisteredOperatorIds.length < 4) throw new Error('Not enough operator ids provided')
- const preregisteredBalance = ethers.utils.parseEther('10')
- for (const operatorId of preregisteredOperatorIds) {
- const [operatorOwnerAddress] = await ssvViews.getOperatorById(operatorId)
- const operatorOwnerSigner = ethers.provider.getSigner(operatorOwnerAddress)
- const currentBalance = await ethers.provider.getBalance(operatorOwnerAddress)
- const nextBalance = currentBalance.add(preregisteredBalance)
- await setBalance(operatorOwnerAddress, nextBalance)
- await network.provider.request({
- method: 'hardhat_impersonateAccount',
- params: [operatorOwnerAddress]
- })
- const result = await registry.connect(operatorOwnerSigner).registerOperator(operatorId, { value: preregisteredBalance })
- await result.wait()
- }
-
- return {
- managerBeacon,
- poolBeacon,
- registryBeacon,
- upkeepBeacon,
- viewsBeacon,
- factory,
- manager,
- registry,
- upkeep,
- views,
- functionsBillingRegistry,
- functionsOracle,
- ssvViews,
- daoOracle,
- donTransmitter
- }
+ const {
+ managerBeacon,
+ poolBeacon,
+ registryBeacon,
+ upkeepBeacon,
+ viewsBeacon,
+ factory,
+ manager,
+ registry,
+ upkeep,
+ views,
+ functionsBillingRegistry,
+ functionsOracle,
+ ssvViews,
+ daoOracle,
+ donTransmitter
+ } = await loadFixture(deploymentFixture)
+
+ const preregisteredOperatorIds = process.env.PREREGISTERED_OPERATOR_IDS?.split(",").map(id => parseInt(id)) || [208,
+ 209,
+ 210,
+ 211/*, 212, 213, 214, 215*/]
+ if (preregisteredOperatorIds.length < 4) throw new Error("Not enough operator ids provided")
+ const preregisteredBalance = ethers.utils.parseEther("10")
+ for (const operatorId of preregisteredOperatorIds) {
+ const [operatorOwnerAddress] = await ssvViews.getOperatorById(operatorId)
+ const operatorOwnerSigner = ethers.provider.getSigner(operatorOwnerAddress)
+ const currentBalance = await ethers.provider.getBalance(operatorOwnerAddress)
+ const nextBalance = currentBalance.add(preregisteredBalance)
+ await setBalance(operatorOwnerAddress, nextBalance)
+ await network.provider.request({
+ method: "hardhat_impersonateAccount",
+ params: [operatorOwnerAddress]
+ })
+ const result = await registry.connect(operatorOwnerSigner).registerOperator(operatorId, { value: preregisteredBalance })
+ await result.wait()
+ }
+
+ return {
+ managerBeacon,
+ poolBeacon,
+ registryBeacon,
+ upkeepBeacon,
+ viewsBeacon,
+ factory,
+ manager,
+ registry,
+ upkeep,
+ views,
+ functionsBillingRegistry,
+ functionsOracle,
+ ssvViews,
+ daoOracle,
+ donTransmitter
+ }
}
/** Fixture to stake 16 for the first user */
export async function firstUserDepositFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter } = await loadFixture(preregistrationFixture)
- const [, , , firstUser] = await ethers.getSigners()
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter } = await loadFixture(preregistrationFixture)
+ const [, , , firstUser] = await ethers.getSigners()
- const depositAmount = round(16 * ((100 + await manager.userFee()) / 100), 10)
- const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
- await deposit.wait()
+ const depositAmount = round(16 * ((100 + await manager.userFee()) / 100), 10)
+ const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
+ await deposit.wait()
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser }
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser }
}
/** Fixture to stake 24 for the second user */
export async function secondUserDepositFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser } = await loadFixture(firstUserDepositFixture)
- const [, , , , secondUser] = await ethers.getSigners()
-
- const depositAmount = round(24 * ((100 + await manager.userFee()) / 100), 10)
- const deposit = await manager.connect(secondUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
- await deposit.wait()
-
- await depositFunctionsBalanceHandler({ manager, signer: daoOracle })
- await depositUpkeepBalanceHandler({ manager, signer: daoOracle })
-
- await initiatePoolHandler({ manager, signer: daoOracle })
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: 32,
- sweptBalance: 0,
- activatedDeposits: 1,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
-
- await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
-
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser }
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser } = await loadFixture(firstUserDepositFixture)
+ const [, , , , secondUser] = await ethers.getSigners()
+
+ const depositAmount = round(24 * ((100 + await manager.userFee()) / 100), 10)
+ const deposit = await manager.connect(secondUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
+ await deposit.wait()
+
+ await depositFunctionsBalanceHandler({ manager, signer: daoOracle })
+ await depositUpkeepBalanceHandler({ manager, signer: daoOracle })
+
+ await initiatePoolHandler({ manager, signer: daoOracle })
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const reportValues = {
+ beaconBalance: 32,
+ sweptBalance: 0,
+ activatedDeposits: 1,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+
+ await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser }
}
/** Fixture to report increase of 0.105 in total rewards before fees */
export async function rewardsPostSecondUserDepositFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser } = await loadFixture(secondUserDepositFixture)
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: 32.105,
- sweptBalance: 0,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues,
- })
-
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser }
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser } = await loadFixture(secondUserDepositFixture)
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const reportValues = {
+ beaconBalance: 32.105,
+ sweptBalance: 0,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues,
+ })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser }
}
/** Fixture to sweep 0.105 to the manager */
export async function sweepPostSecondUserDepositFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser } = await loadFixture(secondUserDepositFixture)
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const sweptRewards = 0.105
- const stakedPoolIds = await manager.getStakedPoolIds()
- for (const poolId of stakedPoolIds) {
- const poolAddress = await manager.getPoolAddress(poolId)
- const poolSweptRewards = sweptRewards / stakedPoolIds.length
- const currentBalance = await ethers.provider.getBalance(poolAddress)
- const nextBalance = currentBalance.add(ethers.utils.parseEther(poolSweptRewards.toString()))
- await setBalance(poolAddress, nextBalance)
- }
- const compoundablePoolIds = [1, 0, 0, 0, 0]
- const reportValues = {
- beaconBalance: 32,
- sweptBalance: sweptRewards,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues,
- })
-
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser }
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser } = await loadFixture(secondUserDepositFixture)
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const sweptRewards = 0.105
+ const stakedPoolIds = await manager.getStakedPoolIds()
+ for (const poolId of stakedPoolIds) {
+ const poolAddress = await manager.getPoolAddress(poolId)
+ const poolSweptRewards = sweptRewards / stakedPoolIds.length
+ const currentBalance = await ethers.provider.getBalance(poolAddress)
+ const nextBalance = currentBalance.add(ethers.utils.parseEther(poolSweptRewards.toString()))
+ await setBalance(poolAddress, nextBalance)
+ }
+ const compoundablePoolIds = [1,
+ 0,
+ 0,
+ 0,
+ 0]
+ const reportValues = {
+ beaconBalance: 32,
+ sweptBalance: sweptRewards,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues,
+ })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser }
}
/** Fixture to stake 24 for the third user */
export async function thirdUserDepositFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser } = await loadFixture(sweepPostSecondUserDepositFixture)
- const [, , , , , thirdUser] = await ethers.getSigners()
-
- const depositAmount = round(24 * ((100 + await manager.userFee()) / 100), 10)
- const deposit = await manager.connect(thirdUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
- await deposit.wait()
-
- await initiatePoolHandler({ manager, signer: daoOracle })
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: 64,
- sweptBalance: 0,
- activatedDeposits: 1,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
-
- await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
-
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser }
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser } = await loadFixture(sweepPostSecondUserDepositFixture)
+ const [, , , , , thirdUser] = await ethers.getSigners()
+
+ const depositAmount = round(24 * ((100 + await manager.userFee()) / 100), 10)
+ const deposit = await manager.connect(thirdUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
+ await deposit.wait()
+
+ await initiatePoolHandler({ manager, signer: daoOracle })
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const reportValues = {
+ beaconBalance: 64,
+ sweptBalance: 0,
+ activatedDeposits: 1,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+
+ await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser }
}
/** Fixture to report increase of 0.21 in total rewards before fees */
export async function rewardsPostThirdUserDepositFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser } = await loadFixture(thirdUserDepositFixture)
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: 64.21,
- sweptBalance: 0,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues,
- })
-
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser }
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser } = await loadFixture(thirdUserDepositFixture)
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const reportValues = {
+ beaconBalance: 64.21,
+ sweptBalance: 0,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues,
+ })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser }
}
/** Fixture to sweep 0.21 to the manager */
export async function sweepPostThirdUserDepositFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser } = await loadFixture(rewardsPostThirdUserDepositFixture)
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const sweptRewards = 0.21
- const stakedPoolIds = await manager.getStakedPoolIds()
- for (const poolId of stakedPoolIds) {
- const poolAddress = await manager.getPoolAddress(poolId)
- const poolSweptRewards = sweptRewards / stakedPoolIds.length
- const currentBalance = await ethers.provider.getBalance(poolAddress)
- const nextBalance = currentBalance.add(ethers.utils.parseEther(poolSweptRewards.toString()))
- await setBalance(poolAddress, nextBalance)
- }
- const compoundablePoolIds = [1, 2, 0, 0, 0]
- const reportValues = {
- beaconBalance: 64,
- sweptBalance: sweptRewards,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
-
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser }
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser } = await loadFixture(rewardsPostThirdUserDepositFixture)
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const sweptRewards = 0.21
+ const stakedPoolIds = await manager.getStakedPoolIds()
+ for (const poolId of stakedPoolIds) {
+ const poolAddress = await manager.getPoolAddress(poolId)
+ const poolSweptRewards = sweptRewards / stakedPoolIds.length
+ const currentBalance = await ethers.provider.getBalance(poolAddress)
+ const nextBalance = currentBalance.add(ethers.utils.parseEther(poolSweptRewards.toString()))
+ await setBalance(poolAddress, nextBalance)
+ }
+ const compoundablePoolIds = [1,
+ 2,
+ 0,
+ 0,
+ 0]
+ const reportValues = {
+ beaconBalance: 64,
+ sweptBalance: sweptRewards,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser }
}
/** Fixture to partial withdraw 0.3 to the first user */
export async function firstUserPartialWithdrawalFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser } = await loadFixture(sweepPostThirdUserDepositFixture)
- const withdrawableBalance = await manager.getWithdrawableBalance()
- const withdraw = await manager.connect(firstUser).requestWithdrawal(withdrawableBalance)
- await withdraw.wait()
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: 64,
- sweptBalance: 0,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
-
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser }
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser } = await loadFixture(sweepPostThirdUserDepositFixture)
+ const withdrawableBalance = await manager.getWithdrawableBalance()
+ const withdraw = await manager.connect(firstUser).requestWithdrawal(withdrawableBalance)
+ await withdraw.wait()
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const reportValues = {
+ beaconBalance: 64,
+ sweptBalance: 0,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser }
}
/** Fixture to stake 72 for the fourth user */
export async function fourthUserDepositFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser } = await loadFixture(firstUserPartialWithdrawalFixture)
- const [, , , , , , fourthUser] = await ethers.getSigners()
-
- const depositAmount = round(72 * ((100 + await manager.userFee()) / 100), 10)
- const deposit = await manager.connect(fourthUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
- await deposit.wait()
-
- for (let i = 0; i < 2; i++) {
- await initiatePoolHandler({ manager, signer: daoOracle })
- }
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: 128,
- sweptBalance: 0,
- activatedDeposits: 2,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser } = await loadFixture(firstUserPartialWithdrawalFixture)
+ const [, , , , , , fourthUser] = await ethers.getSigners()
- await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: 2 } })
+ const depositAmount = round(72 * ((100 + await manager.userFee()) / 100), 10)
+ const deposit = await manager.connect(fourthUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
+ await deposit.wait()
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
+ for (let i = 0; i < 2; i++) {
+ await initiatePoolHandler({ manager, signer: daoOracle })
+ }
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const reportValues = {
+ beaconBalance: 128,
+ sweptBalance: 0,
+ activatedDeposits: 2,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+
+ await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: 2 } })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
}
/** Fixture to simulate a validator stake penalty that decreases the beacon chain balance */
export async function beaconBalanceLossFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(fourthUserDepositFixture)
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: 126,
- sweptBalance: 0,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
-
- await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(fourthUserDepositFixture)
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const reportValues = {
+ beaconBalance: 126,
+ sweptBalance: 0,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
}
/** Fixture to simulate a validator reward that brings the beacon chain balance back to expected */
export async function beaconBalanceRecoveryFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(beaconBalanceLossFixture)
-
- let nextBeaconBalance = 127
- for (let i = 0; i < 2; i++) {
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: nextBeaconBalance,
- sweptBalance: 0,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
-
- await runUpkeep({ donTransmitter, upkeep })
- nextBeaconBalance += 1
- }
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
-}
-
-/** Fixture to full withdraw ~24.07 */
-export async function thirdUserFullWithdrawalFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(beaconBalanceRecoveryFixture)
-
- const thirdStake = await manager.getUserStake(thirdUser.address)
- const withdraw = await manager.connect(thirdUser).requestWithdrawal(thirdStake)
- await withdraw.wait()
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(beaconBalanceLossFixture)
+ let nextBeaconBalance = 127
+ for (let i = 0; i < 2; i++) {
await time.increase(time.duration.days(1))
await runUpkeep({ donTransmitter, upkeep })
- const sweptExitedBalance = 32
const reportValues = {
- beaconBalance: 96,
- sweptBalance: sweptExitedBalance,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 1,
- compoundablePoolIds: [0, 0, 0, 0, 0]
+ beaconBalance: nextBeaconBalance,
+ sweptBalance: 0,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
}
await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
})
- const exitedPoolId = (await manager.getStakedPoolIds())[0]
- const exitedPoolAddress = await manager.getPoolAddress(exitedPoolId)
- const currentBalance = await ethers.provider.getBalance(exitedPoolAddress)
- const nextBalance = currentBalance.add(ethers.utils.parseEther(sweptExitedBalance.toString()))
- await setBalance(exitedPoolAddress, nextBalance)
-
- await reportCompletedExitsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
-
await runUpkeep({ donTransmitter, upkeep })
+ nextBeaconBalance += 1
+ }
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
+}
+
+/** Fixture to full withdraw ~24.07 */
+export async function thirdUserFullWithdrawalFixture() {
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(beaconBalanceRecoveryFixture)
+
+ const thirdStake = await manager.getUserStake(thirdUser.address)
+ const withdraw = await manager.connect(thirdUser).requestWithdrawal(thirdStake)
+ await withdraw.wait()
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const sweptExitedBalance = 32
+ const reportValues = {
+ beaconBalance: 96,
+ sweptBalance: sweptExitedBalance,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 1,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+
+ const exitedPoolId = (await manager.getStakedPoolIds())[0]
+ const exitedPoolAddress = await manager.getPoolAddress(exitedPoolId)
+ const currentBalance = await ethers.provider.getBalance(exitedPoolAddress)
+ const nextBalance = currentBalance.add(ethers.utils.parseEther(sweptExitedBalance.toString()))
+ await setBalance(exitedPoolAddress, nextBalance)
+
+ await reportCompletedExitsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
}
/** Fixture to simulate rewards */
export async function simulationFixture() {
- const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(thirdUserFullWithdrawalFixture)
-
- const rewardsPerValidator = 0.105
- let nextBeaconBalance = 96
- let totalRewards = 0
- for (let i = 0; i < 5; i++) {
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const stakedPoolIds = await manager.getStakedPoolIds()
- const rewardsAmount = rewardsPerValidator * stakedPoolIds.length
- totalRewards += round(rewardsAmount, 10)
- nextBeaconBalance = round(nextBeaconBalance + rewardsAmount, 10)
- const reportValues = {
- beaconBalance: nextBeaconBalance,
- sweptBalance: 0,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
-
- await runUpkeep({ donTransmitter, upkeep })
- }
-
- const sweptRewards = totalRewards
- const stakedPoolIds = await manager.getStakedPoolIds()
+ const { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(thirdUserFullWithdrawalFixture)
+ const rewardsPerValidator = 0.105
+ let nextBeaconBalance = 96
+ let totalRewards = 0
+ for (let i = 0; i < 5; i++) {
await time.increase(time.duration.days(1))
await runUpkeep({ donTransmitter, upkeep })
- for (const poolId of stakedPoolIds) {
- const poolAddress = await manager.getPoolAddress(poolId)
- const poolSweptRewards = sweptRewards / stakedPoolIds.length
- const currentBalance = await ethers.provider.getBalance(poolAddress)
- const nextBalance = currentBalance.add(ethers.utils.parseEther(poolSweptRewards.toString()))
- await setBalance(poolAddress, nextBalance)
- }
- const compoundablePoolIds = [2, 3, 4, 0, 0]
+ const stakedPoolIds = await manager.getStakedPoolIds()
+ const rewardsAmount = rewardsPerValidator * stakedPoolIds.length
+ totalRewards += round(rewardsAmount, 10)
+ nextBeaconBalance = round(nextBeaconBalance + rewardsAmount, 10)
const reportValues = {
- beaconBalance: 96,
- sweptBalance: sweptRewards,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds
+ beaconBalance: nextBeaconBalance,
+ sweptBalance: 0,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
}
await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
})
await runUpkeep({ donTransmitter, upkeep })
-
- return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
+ }
+
+ const sweptRewards = totalRewards
+ const stakedPoolIds = await manager.getStakedPoolIds()
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ for (const poolId of stakedPoolIds) {
+ const poolAddress = await manager.getPoolAddress(poolId)
+ const poolSweptRewards = sweptRewards / stakedPoolIds.length
+ const currentBalance = await ethers.provider.getBalance(poolAddress)
+ const nextBalance = currentBalance.add(ethers.utils.parseEther(poolSweptRewards.toString()))
+ await setBalance(poolAddress, nextBalance)
+ }
+ const compoundablePoolIds = [2,
+ 3,
+ 4,
+ 0,
+ 0]
+ const reportValues = {
+ beaconBalance: 96,
+ sweptBalance: sweptRewards,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
+ })
+
+ await runUpkeep({ donTransmitter, upkeep })
+
+ return { manager, registry, upkeep, views, functionsBillingRegistry, ssvViews, daoOracle, donTransmitter, firstUser, secondUser, thirdUser, fourthUser }
}
\ No newline at end of file
diff --git a/contracts/ethereum/test/integration.ts b/contracts/ethereum/test/integration.ts
index 9be2f1291..7505cbb38 100644
--- a/contracts/ethereum/test/integration.ts
+++ b/contracts/ethereum/test/integration.ts
@@ -1,186 +1,186 @@
-import { ethers } from 'hardhat'
-import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'
-import { expect } from 'chai'
-import { firstUserDepositFixture, rewardsPostSecondUserDepositFixture, secondUserDepositFixture, thirdUserDepositFixture, rewardsPostThirdUserDepositFixture, simulationFixture, firstUserPartialWithdrawalFixture, fourthUserDepositFixture, sweepPostSecondUserDepositFixture, sweepPostThirdUserDepositFixture, beaconBalanceLossFixture, beaconBalanceRecoveryFixture, thirdUserFullWithdrawalFixture } from './fixtures/shared'
-
-describe('Integration', async function () {
-
- it('First user\'s 16.0 stake increases the total stake to 16.0', async function () {
- const { manager } = await loadFixture(firstUserDepositFixture)
- const stake = await manager.getTotalStake()
- expect(ethers.utils.formatEther(stake)).equal('16.0')
- })
-
- it('First user\'s 16.0 stake increases their stake to 16.0', async function () {
- const { manager, firstUser } = await loadFixture(firstUserDepositFixture)
- const stake = await manager.getUserStake(firstUser.address)
- expect(ethers.utils.formatEther(stake)).equal('16.0')
- })
-
- it('Second user\'s 24.0 stake completes the first pool with 32.0', async function () {
- const { manager, views } = await loadFixture(secondUserDepositFixture)
- const stakedPoolIds = await manager.getStakedPoolIds()
- expect(stakedPoolIds.length).equal(1)
-
- const firstPoolId = stakedPoolIds[0]
- const poolConfig = await views.getPoolConfig(firstPoolId)
- expect(poolConfig.publicKey).not.equal('0x')
- expect(poolConfig.operatorIds.length).equal(4)
- })
-
- it('Second user\'s 24.0 stake increases the total stake to 40.0', async function () {
- const { manager } = await loadFixture(secondUserDepositFixture)
- const stake = await manager.getTotalStake()
- expect(ethers.utils.formatEther(stake)).equal('40.0')
- })
-
- it('Second user\'s 24.0 stake increases their stake to 24.0', async function () {
- const { manager, secondUser } = await loadFixture(secondUserDepositFixture)
- const stake = await manager.getUserStake(secondUser.address)
- expect(ethers.utils.formatEther(stake)).equal('24.0')
- })
-
- it('Functions oracle reports an increase of 0.1 in total after fees', async function () {
- const { manager } = await loadFixture(rewardsPostSecondUserDepositFixture)
- const stake = await manager.getTotalStake()
- expect(ethers.utils.formatEther(stake)).equal('40.1')
- })
-
- it('First and second user\'s stake earns them 0.04 and 0.06', async function () {
- const { manager, firstUser, secondUser } = await loadFixture(rewardsPostSecondUserDepositFixture)
- const firstStake = await manager.getUserStake(firstUser.address)
- const secondStake = await manager.getUserStake(secondUser.address)
- expect(ethers.utils.formatEther(firstStake)).equal('16.04')
- expect(ethers.utils.formatEther(secondStake)).equal('24.06')
- })
-
- it('First pool\'s 0.1 is swept and compounded', async function () {
- const { manager } = await loadFixture(sweepPostSecondUserDepositFixture)
- const withdrawableBalance = await manager.getWithdrawableBalance()
- expect(ethers.utils.formatEther(withdrawableBalance)).equal('8.1')
- })
-
- it('Third user\'s 24.0 stake completes the second pool with 32.0', async function () {
- const { manager, views } = await loadFixture(thirdUserDepositFixture)
- const stakedPools = await manager.getStakedPoolIds()
- expect(stakedPools.length).equal(2)
-
- const secondPoolId = stakedPools[1]
- const poolConfig = await views.getPoolConfig(secondPoolId)
- expect(poolConfig.publicKey).not.equal('0x')
- expect(poolConfig.operatorIds.length).equal(4)
- })
-
- it('Third user\'s 24.0 stake increases the total stake to 64.1', async function () {
- const { manager } = await loadFixture(thirdUserDepositFixture)
- const stake = await manager.getTotalStake()
- expect(ethers.utils.formatEther(stake)).equal('64.1')
- })
-
- it('Third user\'s 24.0 stake increases their stake to 24.0', async function () {
- const { manager, thirdUser } = await loadFixture(thirdUserDepositFixture)
- const stake = await manager.getUserStake(thirdUser.address)
- expect(ethers.utils.formatEther(stake)).equal('24.0')
- })
-
- it('Functions oracle reports an increase of 0.2 in total after fees', async function () {
- const { manager } = await loadFixture(rewardsPostThirdUserDepositFixture)
- const stake = await manager.getTotalStake()
- expect(ethers.utils.formatEther(stake)).equal('64.3')
- })
-
- it('First, second, and third user\'s stake earns them ~0.09, ~0.135 and ~0.075', async function () {
- const { manager, firstUser, secondUser, thirdUser } = await loadFixture(rewardsPostThirdUserDepositFixture)
- const firstStake = await manager.getUserStake(firstUser.address)
- const secondStake = await manager.getUserStake(secondUser.address)
- const thirdStake = await manager.getUserStake(thirdUser.address)
-
- expect(ethers.utils.formatEther(firstStake)).equal('16.090046801872074882')
- expect(ethers.utils.formatEther(secondStake)).equal('24.135070202808112324')
- expect(ethers.utils.formatEther(thirdStake)).equal('24.074882995319812792')
- })
-
- it('First and second pool\'s 0.2 is swept and compounded', async function () {
- const { manager } = await loadFixture(sweepPostThirdUserDepositFixture)
- const withdrawableBalance = await manager.getWithdrawableBalance()
- expect(ethers.utils.formatEther(withdrawableBalance)).equal('0.3')
- })
-
- it('First user\'s 0.3 withdrawal decreases their stake to ~15.79', async function () {
- const { manager, firstUser, secondUser, thirdUser } = await loadFixture(firstUserPartialWithdrawalFixture)
- const firstStake = await manager.getUserStake(firstUser.address)
- const secondStake = await manager.getUserStake(secondUser.address)
- const thirdStake = await manager.getUserStake(thirdUser.address)
-
- expect(ethers.utils.formatEther(firstStake)).equal('15.790046801872074882')
- expect(ethers.utils.formatEther(secondStake)).equal('24.135070202808112324')
- expect(ethers.utils.formatEther(thirdStake)).equal('24.074882995319812792')
- })
-
- it('Fourth user\'s 72 stake completes the third and fourth pool with 72', async function () {
- const { manager, views } = await loadFixture(fourthUserDepositFixture)
- const stakedPools = await manager.getStakedPoolIds()
- expect(stakedPools.length).equal(4)
-
- const thirdPoolId = stakedPools[2]
- const thirdPoolConfig = await views.getPoolConfig(thirdPoolId)
- expect(thirdPoolConfig.publicKey).not.equal('0x')
- expect(thirdPoolConfig.operatorIds.length).equal(4)
-
- const fourthPoolId = stakedPools[3]
- const fourthPoolConfig = await views.getPoolConfig(fourthPoolId)
- expect(fourthPoolConfig.publicKey).not.equal('0x')
- expect(fourthPoolConfig.operatorIds.length).equal(4)
- })
-
- it('A loss is reported and brings the active stake below expected', async function () {
- const { manager } = await loadFixture(beaconBalanceLossFixture)
- const beaconBalance = await manager.latestBeaconBalance()
- expect(ethers.utils.formatEther(beaconBalance)).equal('126.0')
- })
-
- it('Gains are reported and bring the active stake back to expected', async function () {
- const { manager } = await loadFixture(beaconBalanceRecoveryFixture)
- const beaconBalance = await manager.latestBeaconBalance()
- expect(ethers.utils.formatEther(beaconBalance)).equal('128.0')
- })
-
- it('Third user full withdrawal is completed on exit report', async function () {
- const { manager, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(thirdUserFullWithdrawalFixture)
- const stake = await manager.getTotalStake()
- const firstStake = await manager.getUserStake(firstUser.address)
- const secondStake = await manager.getUserStake(secondUser.address)
- const thirdStake = await manager.getUserStake(thirdUser.address)
- const fourthStake = await manager.getUserStake(fourthUser.address)
-
- expect(ethers.utils.formatEther(stake)).equal('111.925117004680187208')
- expect(ethers.utils.formatEther(firstStake)).equal('15.790046801872074882')
- expect(ethers.utils.formatEther(secondStake)).equal('24.135070202808112324')
- expect(ethers.utils.formatEther(thirdStake)).equal('0.0')
- expect(ethers.utils.formatEther(fourthStake)).equal('72.0')
- })
-
- it('Check more rewards and dust', async function () {
- const { manager, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(simulationFixture)
- const stake = await manager.getTotalStake()
- const firstStake = await manager.getUserStake(firstUser.address)
- const secondStake = await manager.getUserStake(secondUser.address)
- const thirdStake = await manager.getUserStake(thirdUser.address)
- const fourthStake = await manager.getUserStake(fourthUser.address)
-
- const line = '----------------------------------------'
- console.log(`${line}\n💿 Simulation results\n${line}`)
- console.log('🏦 Manager stake', ethers.utils.formatEther(stake))
- console.log('👤 First user stake', ethers.utils.formatEther(firstStake))
- console.log('👤 Second user stake', ethers.utils.formatEther(secondStake))
- console.log('👤 Third user stake', ethers.utils.formatEther(thirdStake))
- console.log('👤 Fourth user stake', ethers.utils.formatEther(fourthStake))
- const withdrawableBalance = await manager.getWithdrawableBalance()
- console.log('📦 Withdrawable balance', ethers.utils.formatEther(withdrawableBalance))
- const dust = stake.sub(firstStake.add(secondStake).add(thirdStake).add(fourthStake))
- if (dust !== ethers.utils.parseEther('0.0')) {
- console.log('🧹 Dust', ethers.utils.formatEther(dust))
- }
- console.log(line)
- })
+import { ethers } from "hardhat"
+import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"
+import { expect } from "chai"
+import { firstUserDepositFixture, rewardsPostSecondUserDepositFixture, secondUserDepositFixture, thirdUserDepositFixture, rewardsPostThirdUserDepositFixture, simulationFixture, firstUserPartialWithdrawalFixture, fourthUserDepositFixture, sweepPostSecondUserDepositFixture, sweepPostThirdUserDepositFixture, beaconBalanceLossFixture, beaconBalanceRecoveryFixture, thirdUserFullWithdrawalFixture } from "./fixtures/shared"
+
+describe("Integration", async function () {
+
+ it("First user's 16.0 stake increases the total stake to 16.0", async function () {
+ const { manager } = await loadFixture(firstUserDepositFixture)
+ const stake = await manager.getTotalStake()
+ expect(ethers.utils.formatEther(stake)).equal("16.0")
+ })
+
+ it("First user's 16.0 stake increases their stake to 16.0", async function () {
+ const { manager, firstUser } = await loadFixture(firstUserDepositFixture)
+ const stake = await manager.getUserStake(firstUser.address)
+ expect(ethers.utils.formatEther(stake)).equal("16.0")
+ })
+
+ it("Second user's 24.0 stake completes the first pool with 32.0", async function () {
+ const { manager, views } = await loadFixture(secondUserDepositFixture)
+ const stakedPoolIds = await manager.getStakedPoolIds()
+ expect(stakedPoolIds.length).equal(1)
+
+ const firstPoolId = stakedPoolIds[0]
+ const poolConfig = await views.getPoolConfig(firstPoolId)
+ expect(poolConfig.publicKey).not.equal("0x")
+ expect(poolConfig.operatorIds.length).equal(4)
+ })
+
+ it("Second user's 24.0 stake increases the total stake to 40.0", async function () {
+ const { manager } = await loadFixture(secondUserDepositFixture)
+ const stake = await manager.getTotalStake()
+ expect(ethers.utils.formatEther(stake)).equal("40.0")
+ })
+
+ it("Second user's 24.0 stake increases their stake to 24.0", async function () {
+ const { manager, secondUser } = await loadFixture(secondUserDepositFixture)
+ const stake = await manager.getUserStake(secondUser.address)
+ expect(ethers.utils.formatEther(stake)).equal("24.0")
+ })
+
+ it("Functions oracle reports an increase of 0.1 in total after fees", async function () {
+ const { manager } = await loadFixture(rewardsPostSecondUserDepositFixture)
+ const stake = await manager.getTotalStake()
+ expect(ethers.utils.formatEther(stake)).equal("40.1")
+ })
+
+ it("First and second user's stake earns them 0.04 and 0.06", async function () {
+ const { manager, firstUser, secondUser } = await loadFixture(rewardsPostSecondUserDepositFixture)
+ const firstStake = await manager.getUserStake(firstUser.address)
+ const secondStake = await manager.getUserStake(secondUser.address)
+ expect(ethers.utils.formatEther(firstStake)).equal("16.04")
+ expect(ethers.utils.formatEther(secondStake)).equal("24.06")
+ })
+
+ it("First pool's 0.1 is swept and compounded", async function () {
+ const { manager } = await loadFixture(sweepPostSecondUserDepositFixture)
+ const withdrawableBalance = await manager.getWithdrawableBalance()
+ expect(ethers.utils.formatEther(withdrawableBalance)).equal("8.1")
+ })
+
+ it("Third user's 24.0 stake completes the second pool with 32.0", async function () {
+ const { manager, views } = await loadFixture(thirdUserDepositFixture)
+ const stakedPools = await manager.getStakedPoolIds()
+ expect(stakedPools.length).equal(2)
+
+ const secondPoolId = stakedPools[1]
+ const poolConfig = await views.getPoolConfig(secondPoolId)
+ expect(poolConfig.publicKey).not.equal("0x")
+ expect(poolConfig.operatorIds.length).equal(4)
+ })
+
+ it("Third user's 24.0 stake increases the total stake to 64.1", async function () {
+ const { manager } = await loadFixture(thirdUserDepositFixture)
+ const stake = await manager.getTotalStake()
+ expect(ethers.utils.formatEther(stake)).equal("64.1")
+ })
+
+ it("Third user's 24.0 stake increases their stake to 24.0", async function () {
+ const { manager, thirdUser } = await loadFixture(thirdUserDepositFixture)
+ const stake = await manager.getUserStake(thirdUser.address)
+ expect(ethers.utils.formatEther(stake)).equal("24.0")
+ })
+
+ it("Functions oracle reports an increase of 0.2 in total after fees", async function () {
+ const { manager } = await loadFixture(rewardsPostThirdUserDepositFixture)
+ const stake = await manager.getTotalStake()
+ expect(ethers.utils.formatEther(stake)).equal("64.3")
+ })
+
+ it("First, second, and third user's stake earns them ~0.09, ~0.135 and ~0.075", async function () {
+ const { manager, firstUser, secondUser, thirdUser } = await loadFixture(rewardsPostThirdUserDepositFixture)
+ const firstStake = await manager.getUserStake(firstUser.address)
+ const secondStake = await manager.getUserStake(secondUser.address)
+ const thirdStake = await manager.getUserStake(thirdUser.address)
+
+ expect(ethers.utils.formatEther(firstStake)).equal("16.090046801872074882")
+ expect(ethers.utils.formatEther(secondStake)).equal("24.135070202808112324")
+ expect(ethers.utils.formatEther(thirdStake)).equal("24.074882995319812792")
+ })
+
+ it("First and second pool's 0.2 is swept and compounded", async function () {
+ const { manager } = await loadFixture(sweepPostThirdUserDepositFixture)
+ const withdrawableBalance = await manager.getWithdrawableBalance()
+ expect(ethers.utils.formatEther(withdrawableBalance)).equal("0.3")
+ })
+
+ it("First user's 0.3 withdrawal decreases their stake to ~15.79", async function () {
+ const { manager, firstUser, secondUser, thirdUser } = await loadFixture(firstUserPartialWithdrawalFixture)
+ const firstStake = await manager.getUserStake(firstUser.address)
+ const secondStake = await manager.getUserStake(secondUser.address)
+ const thirdStake = await manager.getUserStake(thirdUser.address)
+
+ expect(ethers.utils.formatEther(firstStake)).equal("15.790046801872074882")
+ expect(ethers.utils.formatEther(secondStake)).equal("24.135070202808112324")
+ expect(ethers.utils.formatEther(thirdStake)).equal("24.074882995319812792")
+ })
+
+ it("Fourth user's 72 stake completes the third and fourth pool with 72", async function () {
+ const { manager, views } = await loadFixture(fourthUserDepositFixture)
+ const stakedPools = await manager.getStakedPoolIds()
+ expect(stakedPools.length).equal(4)
+
+ const thirdPoolId = stakedPools[2]
+ const thirdPoolConfig = await views.getPoolConfig(thirdPoolId)
+ expect(thirdPoolConfig.publicKey).not.equal("0x")
+ expect(thirdPoolConfig.operatorIds.length).equal(4)
+
+ const fourthPoolId = stakedPools[3]
+ const fourthPoolConfig = await views.getPoolConfig(fourthPoolId)
+ expect(fourthPoolConfig.publicKey).not.equal("0x")
+ expect(fourthPoolConfig.operatorIds.length).equal(4)
+ })
+
+ it("A loss is reported and brings the active stake below expected", async function () {
+ const { manager } = await loadFixture(beaconBalanceLossFixture)
+ const beaconBalance = await manager.latestBeaconBalance()
+ expect(ethers.utils.formatEther(beaconBalance)).equal("126.0")
+ })
+
+ it("Gains are reported and bring the active stake back to expected", async function () {
+ const { manager } = await loadFixture(beaconBalanceRecoveryFixture)
+ const beaconBalance = await manager.latestBeaconBalance()
+ expect(ethers.utils.formatEther(beaconBalance)).equal("128.0")
+ })
+
+ it("Third user full withdrawal is completed on exit report", async function () {
+ const { manager, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(thirdUserFullWithdrawalFixture)
+ const stake = await manager.getTotalStake()
+ const firstStake = await manager.getUserStake(firstUser.address)
+ const secondStake = await manager.getUserStake(secondUser.address)
+ const thirdStake = await manager.getUserStake(thirdUser.address)
+ const fourthStake = await manager.getUserStake(fourthUser.address)
+
+ expect(ethers.utils.formatEther(stake)).equal("111.925117004680187208")
+ expect(ethers.utils.formatEther(firstStake)).equal("15.790046801872074882")
+ expect(ethers.utils.formatEther(secondStake)).equal("24.135070202808112324")
+ expect(ethers.utils.formatEther(thirdStake)).equal("0.0")
+ expect(ethers.utils.formatEther(fourthStake)).equal("72.0")
+ })
+
+ it("Check more rewards and dust", async function () {
+ const { manager, firstUser, secondUser, thirdUser, fourthUser } = await loadFixture(simulationFixture)
+ const stake = await manager.getTotalStake()
+ const firstStake = await manager.getUserStake(firstUser.address)
+ const secondStake = await manager.getUserStake(secondUser.address)
+ const thirdStake = await manager.getUserStake(thirdUser.address)
+ const fourthStake = await manager.getUserStake(fourthUser.address)
+
+ const line = "----------------------------------------"
+ console.log(`${line}\n💿 Simulation results\n${line}`)
+ console.log("🏦 Manager stake", ethers.utils.formatEther(stake))
+ console.log("👤 First user stake", ethers.utils.formatEther(firstStake))
+ console.log("👤 Second user stake", ethers.utils.formatEther(secondStake))
+ console.log("👤 Third user stake", ethers.utils.formatEther(thirdStake))
+ console.log("👤 Fourth user stake", ethers.utils.formatEther(fourthStake))
+ const withdrawableBalance = await manager.getWithdrawableBalance()
+ console.log("📦 Withdrawable balance", ethers.utils.formatEther(withdrawableBalance))
+ const dust = stake.sub(firstStake.add(secondStake).add(thirdStake).add(fourthStake))
+ if (dust !== ethers.utils.parseEther("0.0")) {
+ console.log("🧹 Dust", ethers.utils.formatEther(dust))
+ }
+ console.log(line)
+ })
})
\ No newline at end of file
diff --git a/contracts/ethereum/test/operators.ts b/contracts/ethereum/test/operators.ts
index 7cafcfa8f..76777c1d4 100644
--- a/contracts/ethereum/test/operators.ts
+++ b/contracts/ethereum/test/operators.ts
@@ -1,138 +1,142 @@
-import { ethers, network } from 'hardhat'
-import { loadFixture, setBalance, time } from '@nomicfoundation/hardhat-network-helpers'
-import { expect } from 'chai'
-import { preregistrationFixture, secondUserDepositFixture } from './fixtures/shared'
-import { round } from '../helpers/math'
-import { initiatePoolHandler, reportCompletedExitsHandler } from '../helpers/oracle'
-import { fulfillReport, runUpkeep } from '../helpers/upkeep'
-
-describe('Operators', async function () {
- it('Preregistration of operators 1 through 4 creates 4 eligible operators', async function () {
- const { registry, views } = await loadFixture(preregistrationFixture)
- const operatorIds = await registry.getOperatorIds()
- const startIndex = 0
- const endIndex = operatorIds.length
- const operators = await views.getOperators(startIndex, endIndex)
- expect(operators.length).equal(4)
+import { ethers, network } from "hardhat"
+import { loadFixture, setBalance, time } from "@nomicfoundation/hardhat-network-helpers"
+import { expect } from "chai"
+import { preregistrationFixture, secondUserDepositFixture } from "./fixtures/shared"
+import { round } from "../helpers/math"
+import { initiatePoolHandler, reportCompletedExitsHandler } from "../helpers/oracle"
+import { fulfillReport, runUpkeep } from "../helpers/upkeep"
+
+describe("Operators", async function () {
+ it("Preregistration of operators 1 through 4 creates 4 eligible operators", async function () {
+ const { registry, views } = await loadFixture(preregistrationFixture)
+ const operatorIds = await registry.getOperatorIds()
+ const startIndex = 0
+ const endIndex = operatorIds.length
+ const operators = await views.getOperators(startIndex, endIndex)
+ expect(operators.length).equal(4)
+ })
+
+ it("First initiated deposit uses 4 eligible operators", async function () {
+ const { manager, registry, views, daoOracle } = await loadFixture(preregistrationFixture)
+ const [firstUser] = await ethers.getSigners()
+
+ const depositAmount = round(32 * ((100 + await manager.userFee()) / 100), 10)
+ const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
+ await deposit.wait()
+
+ await initiatePoolHandler({ manager, signer: daoOracle })
+
+ const operatorIds = await registry.getOperatorIds()
+ const startIndex = 0
+ const endIndex = operatorIds.length
+ const operators = await views.getOperators(startIndex, endIndex)
+
+ const operatorsWithPools = operators.filter(operator => Number(operator.poolCount.toString()) === 1)
+ expect(operatorsWithPools.length).equal(4)
+ })
+
+ it("Operator deregistration with 1 pool emits 1 reshare request", async function () {
+ const { manager, registry, ssvViews, daoOracle } = await loadFixture(preregistrationFixture)
+ const [firstUser] = await ethers.getSigners()
+
+ const depositAmount = round(32 * ((100 + await manager.userFee()) / 100), 10)
+ const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
+ await deposit.wait()
+
+ await initiatePoolHandler({ manager, signer: daoOracle })
+
+ const operatorIds = await registry.getOperatorIds()
+ const deregisteringOperatorId = operatorIds[0]
+ const operatorOwnerAddress = (await ssvViews.getOperatorById(deregisteringOperatorId)).owner
+ const operatorOwnerSigner = ethers.provider.getSigner(operatorOwnerAddress)
+ await network.provider.request({
+ method: "hardhat_impersonateAccount",
+ params: [operatorOwnerAddress]
})
-
- it('First initiated deposit uses 4 eligible operators', async function () {
- const { manager, registry, views, daoOracle } = await loadFixture(preregistrationFixture)
- const [firstUser] = await ethers.getSigners()
-
- const depositAmount = round(32 * ((100 + await manager.userFee()) / 100), 10)
- const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
- await deposit.wait()
-
- await initiatePoolHandler({ manager, signer: daoOracle })
-
- const operatorIds = await registry.getOperatorIds()
- const startIndex = 0
- const endIndex = operatorIds.length
- const operators = await views.getOperators(startIndex, endIndex)
-
- const operatorsWithPools = operators.filter(operator => Number(operator.poolCount.toString()) === 1)
- expect(operatorsWithPools.length).equal(4)
+ const requestDeactivation = await registry.connect(operatorOwnerSigner).requestDeactivation(deregisteringOperatorId)
+ await requestDeactivation.wait()
+ const deregisteringOperator = await registry.getOperator(deregisteringOperatorId)
+
+ expect(deregisteringOperator.resharing).equal(true)
+ })
+
+ it("Operator deregistration with 0 pools allows immediate collateral withdrawal", async function () {
+ const { registry, ssvViews } = await loadFixture(preregistrationFixture)
+
+ const operatorIds = await registry.getOperatorIds()
+ const deregisteringOperatorId = operatorIds[0]
+ const [operatorOwnerAddress] = await ssvViews.getOperatorById(deregisteringOperatorId)
+ const operatorOwnerSigner = ethers.provider.getSigner(operatorOwnerAddress)
+ await network.provider.request({
+ method: "hardhat_impersonateAccount",
+ params: [operatorOwnerAddress]
})
-
- it('Operator deregistration with 1 pool emits 1 reshare request', async function () {
- const { manager, registry, ssvViews, daoOracle } = await loadFixture(preregistrationFixture)
- const [firstUser] = await ethers.getSigners()
-
- const depositAmount = round(32 * ((100 + await manager.userFee()) / 100), 10)
- const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
- await deposit.wait()
-
- await initiatePoolHandler({ manager, signer: daoOracle })
-
- const operatorIds = await registry.getOperatorIds()
- const deregisteringOperatorId = operatorIds[0]
- const operatorOwnerAddress = (await ssvViews.getOperatorById(deregisteringOperatorId)).owner
- const operatorOwnerSigner = ethers.provider.getSigner(operatorOwnerAddress)
- await network.provider.request({
- method: 'hardhat_impersonateAccount',
- params: [operatorOwnerAddress]
- })
- const requestDeactivation = await registry.connect(operatorOwnerSigner).requestDeactivation(deregisteringOperatorId)
- await requestDeactivation.wait()
- const deregisteringOperator = await registry.getOperator(deregisteringOperatorId)
-
- expect(deregisteringOperator.resharing).equal(true)
+ const requestDeactivation = await registry.connect(operatorOwnerSigner).requestDeactivation(deregisteringOperatorId)
+ await requestDeactivation.wait()
+ const deregisteringOperator = await registry.getOperator(deregisteringOperatorId)
+ const deactivationRequestedEvents = await registry.queryFilter(registry.filters.DeactivationRequested(), -1)
+
+ expect(deregisteringOperator.active).equal(false)
+ expect(deregisteringOperator.resharing).equal(false)
+ expect(deactivationRequestedEvents.length).equal(0)
+
+ const operatorOwnerBalanceBefore = await ethers.provider.getBalance(operatorOwnerAddress)
+ const requestWithdrawal = await registry.connect(operatorOwnerSigner).requestWithdrawal(deregisteringOperatorId, ethers.utils.parseEther("10"))
+ await requestWithdrawal.wait()
+ const operatorOwnerBalanceAfter = await ethers.provider.getBalance(operatorOwnerAddress)
+ const deregisteredOperator = await registry.getOperator(deregisteringOperatorId)
+
+ expect(deregisteredOperator.collateral.toString()).equal("0")
+ expect(ethers.utils.formatEther(operatorOwnerBalanceAfter.sub(operatorOwnerBalanceBefore).toString())).contains("9.9")
+ })
+
+ it("Pool exits with 31.0 and recovers from the blamed operator", async function () {
+ const { manager, registry, upkeep, views, secondUser, donTransmitter, daoOracle, functionsBillingRegistry } = await loadFixture(secondUserDepositFixture)
+
+ const secondStake = await manager.getUserStake(secondUser.address)
+ const withdraw = await manager.connect(secondUser).requestWithdrawal(secondStake)
+ await withdraw.wait()
+
+ const sweptExitedBalance = 31
+ const withdrawnPoolId = (await manager.getStakedPoolIds())[0]
+ const withdrawnPoolAddress = await manager.getPoolAddress(withdrawnPoolId)
+ const currentBalance = await ethers.provider.getBalance(withdrawnPoolAddress)
+ const nextBalance = currentBalance.add(ethers.utils.parseEther(sweptExitedBalance.toString()))
+ await setBalance(withdrawnPoolAddress, nextBalance)
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const reportValues = {
+ beaconBalance: 0,
+ sweptBalance: sweptExitedBalance,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 1,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: reportValues
})
- it('Operator deregistration with 0 pools allows immediate collateral withdrawal', async function () {
- const { registry, ssvViews } = await loadFixture(preregistrationFixture)
-
- const operatorIds = await registry.getOperatorIds()
- const deregisteringOperatorId = operatorIds[0]
- const [operatorOwnerAddress] = await ssvViews.getOperatorById(deregisteringOperatorId)
- const operatorOwnerSigner = ethers.provider.getSigner(operatorOwnerAddress)
- await network.provider.request({
- method: 'hardhat_impersonateAccount',
- params: [operatorOwnerAddress]
- })
- const requestDeactivation = await registry.connect(operatorOwnerSigner).requestDeactivation(deregisteringOperatorId)
- await requestDeactivation.wait()
- const deregisteringOperator = await registry.getOperator(deregisteringOperatorId)
- const deactivationRequestedEvents = await registry.queryFilter(registry.filters.DeactivationRequested(), -1)
-
- expect(deregisteringOperator.active).equal(false)
- expect(deregisteringOperator.resharing).equal(false)
- expect(deactivationRequestedEvents.length).equal(0)
-
- const operatorOwnerBalanceBefore = await ethers.provider.getBalance(operatorOwnerAddress)
- const requestWithdrawal = await registry.connect(operatorOwnerSigner).requestWithdrawal(deregisteringOperatorId, ethers.utils.parseEther('10'))
- await requestWithdrawal.wait()
- const operatorOwnerBalanceAfter = await ethers.provider.getBalance(operatorOwnerAddress)
- const deregisteredOperator = await registry.getOperator(deregisteringOperatorId)
-
- expect(deregisteredOperator.collateral.toString()).equal('0')
- expect(ethers.utils.formatEther(operatorOwnerBalanceAfter.sub(operatorOwnerBalanceBefore).toString())).contains('9.9')
- })
+ await reportCompletedExitsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
+ await runUpkeep({ donTransmitter, upkeep })
- it('Pool exits with 31.0 and recovers from the blamed operator', async function () {
- const { manager, registry, upkeep, views, secondUser, donTransmitter, daoOracle, functionsBillingRegistry } = await loadFixture(secondUserDepositFixture)
-
- const secondStake = await manager.getUserStake(secondUser.address)
- const withdraw = await manager.connect(secondUser).requestWithdrawal(secondStake)
- await withdraw.wait()
-
- const sweptExitedBalance = 31
- const withdrawnPoolId = (await manager.getStakedPoolIds())[0]
- const withdrawnPoolAddress = await manager.getPoolAddress(withdrawnPoolId)
- const currentBalance = await ethers.provider.getBalance(withdrawnPoolAddress)
- const nextBalance = currentBalance.add(ethers.utils.parseEther(sweptExitedBalance.toString()))
- await setBalance(withdrawnPoolAddress, nextBalance)
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const reportValues = {
- beaconBalance: 0,
- sweptBalance: sweptExitedBalance,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 1,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: reportValues
- })
-
- await reportCompletedExitsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
- await runUpkeep({ donTransmitter, upkeep })
-
- const stake = await manager.getTotalStake()
- const userStake = await manager.getUserStake(secondUser.address)
- const blamedOperatorId = 208 // Hardcoded the first operator
- const blamedOperator = await registry.getOperator(blamedOperatorId)
-
- expect(ethers.utils.formatEther(stake)).equal('16.0')
- expect(ethers.utils.formatEther(userStake)).equal('0.0')
- expect(blamedOperator.collateral.toString()).equal(ethers.utils.parseEther('9.0').toString())
- })
+ const stake = await manager.getTotalStake()
+ const userStake = await manager.getUserStake(secondUser.address)
+ const blamedOperatorId = 208 // Hardcoded the first operator
+ const blamedOperator = await registry.getOperator(blamedOperatorId)
+
+ expect(ethers.utils.formatEther(stake)).equal("16.0")
+ expect(ethers.utils.formatEther(userStake)).equal("0.0")
+ expect(blamedOperator.collateral.toString()).equal(ethers.utils.parseEther("9.0").toString())
+ })
})
\ No newline at end of file
diff --git a/contracts/ethereum/test/users.ts b/contracts/ethereum/test/users.ts
index 209026a45..770913072 100644
--- a/contracts/ethereum/test/users.ts
+++ b/contracts/ethereum/test/users.ts
@@ -1,137 +1,145 @@
-import { ethers } from 'hardhat'
-import { loadFixture, setBalance, time } from '@nomicfoundation/hardhat-network-helpers'
-import { expect } from 'chai'
-import { preregistrationFixture } from './fixtures/shared'
-import { round } from '../helpers/math'
-import { activatePoolsHandler, depositFunctionsBalanceHandler, depositUpkeepBalanceHandler, initiatePoolHandler, reportCompletedExitsHandler } from '../helpers/oracle'
-import { fulfillReport, runUpkeep } from '../helpers/upkeep'
-
-describe('Users', async function () {
- it('User\'s 16.0 stake and half withdrawal updates total and user stake, and user balance', async function () {
- const { manager } = await loadFixture(preregistrationFixture)
- const [firstUser] = await ethers.getSigners()
-
- const depositAmount = round(16 * ((100 + await manager.userFee()) / 100), 10)
- const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
- await deposit.wait()
-
- let stake = await manager.getTotalStake()
- let userStake = await manager.getUserStake(firstUser.address)
-
- expect(ethers.utils.formatEther(stake)).equal('16.0')
- expect(ethers.utils.formatEther(userStake)).equal('16.0')
-
- const userBalanceBefore = await ethers.provider.getBalance(firstUser.address)
- const userWithdrawalRequest = await manager.connect(firstUser).requestWithdrawal(ethers.utils.parseEther('8.0'))
- await userWithdrawalRequest.wait()
- const userBalanceAfter = await ethers.provider.getBalance(firstUser.address)
-
- stake = await manager.getTotalStake()
- userStake = await manager.getUserStake(firstUser.address)
-
- expect(ethers.utils.formatEther(stake)).equal('8.0')
- expect(ethers.utils.formatEther(userStake)).equal('8.0')
- expect(ethers.utils.formatEther(userBalanceAfter.sub(userBalanceBefore))).contains('7.9')
+import { ethers } from "hardhat"
+import { loadFixture, setBalance, time } from "@nomicfoundation/hardhat-network-helpers"
+import { expect } from "chai"
+import { preregistrationFixture } from "./fixtures/shared"
+import { round } from "../helpers/math"
+import { activatePoolsHandler, depositFunctionsBalanceHandler, depositUpkeepBalanceHandler, initiatePoolHandler, reportCompletedExitsHandler } from "../helpers/oracle"
+import { fulfillReport, runUpkeep } from "../helpers/upkeep"
+
+describe("Users", async function () {
+ it("User's 16.0 stake and half withdrawal updates total and user stake, and user balance", async function () {
+ const { manager } = await loadFixture(preregistrationFixture)
+ const [firstUser] = await ethers.getSigners()
+
+ const depositAmount = round(16 * ((100 + await manager.userFee()) / 100), 10)
+ const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
+ await deposit.wait()
+
+ let stake = await manager.getTotalStake()
+ let userStake = await manager.getUserStake(firstUser.address)
+
+ expect(ethers.utils.formatEther(stake)).equal("16.0")
+ expect(ethers.utils.formatEther(userStake)).equal("16.0")
+
+ const userBalanceBefore = await ethers.provider.getBalance(firstUser.address)
+ const userWithdrawalRequest = await manager.connect(firstUser).requestWithdrawal(ethers.utils.parseEther("8.0"))
+ await userWithdrawalRequest.wait()
+ const userBalanceAfter = await ethers.provider.getBalance(firstUser.address)
+
+ stake = await manager.getTotalStake()
+ userStake = await manager.getUserStake(firstUser.address)
+
+ expect(ethers.utils.formatEther(stake)).equal("8.0")
+ expect(ethers.utils.formatEther(userStake)).equal("8.0")
+ expect(ethers.utils.formatEther(userBalanceAfter.sub(userBalanceBefore))).contains("7.9")
+ })
+
+ it("User's 64.0 stake and half withdrawal updates total and user stake, and user balance", async function () {
+ const { manager, upkeep, views, functionsBillingRegistry, daoOracle, donTransmitter } = await loadFixture(preregistrationFixture)
+ const [firstUser] = await ethers.getSigners()
+
+ const depositAmount = round(64 * ((100 + await manager.userFee()) / 100), 10)
+ const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
+ await deposit.wait()
+
+ await depositFunctionsBalanceHandler({ manager, signer: daoOracle })
+ await depositUpkeepBalanceHandler({ manager, signer: daoOracle })
+
+ await initiatePoolHandler({ manager, signer: daoOracle })
+ await initiatePoolHandler({ manager, signer: daoOracle })
+
+ const pendingPoolIds = await manager.getPendingPoolIds()
+
+ expect(pendingPoolIds.length).equal(2)
+
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
+
+ const firstReportValues = {
+ beaconBalance: 64,
+ sweptBalance: 0,
+ activatedDeposits: 2,
+ forcedExits: 0,
+ completedExits: 0,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
+
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: firstReportValues
})
- it('User\'s 64.0 stake and half withdrawal updates total and user stake, and user balance', async function () {
- const { manager, upkeep, views, functionsBillingRegistry, daoOracle, donTransmitter } = await loadFixture(preregistrationFixture)
- const [firstUser] = await ethers.getSigners()
+ await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: 2 } })
- const depositAmount = round(64 * ((100 + await manager.userFee()) / 100), 10)
- const deposit = await manager.connect(firstUser).depositStake({ value: ethers.utils.parseEther(depositAmount.toString()) })
- await deposit.wait()
+ await runUpkeep({ donTransmitter, upkeep })
- await depositFunctionsBalanceHandler({ manager, signer: daoOracle })
- await depositUpkeepBalanceHandler({ manager, signer: daoOracle })
+ const stakedPoolIds = await manager.getStakedPoolIds()
- await initiatePoolHandler({ manager, signer: daoOracle })
- await initiatePoolHandler({ manager, signer: daoOracle })
+ expect(stakedPoolIds.length).equal(2)
- const pendingPoolIds = await manager.getPendingPoolIds()
+ let stake = await manager.getTotalStake()
+ let userStake = await manager.getUserStake(firstUser.address)
- expect(pendingPoolIds.length).equal(2)
+ expect(ethers.utils.formatEther(stake)).equal("64.0")
+ expect(ethers.utils.formatEther(userStake)).equal("64.0")
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
+ const userBalanceBefore = await ethers.provider.getBalance(firstUser.address)
+ const userWithdrawalRequest = await manager.connect(firstUser).requestWithdrawal(ethers.utils.parseEther("32.0"))
+ await userWithdrawalRequest.wait()
- const firstReportValues = {
- beaconBalance: 64,
- sweptBalance: 0,
- activatedDeposits: 2,
- forcedExits: 0,
- completedExits: 0,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
+ stake = await manager.getTotalStake()
+ userStake = await manager.getUserStake(firstUser.address)
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: firstReportValues
- })
+ expect(ethers.utils.formatEther(stake)).equal("32.0")
+ expect(ethers.utils.formatEther(userStake)).equal("32.0")
- await activatePoolsHandler({ manager, views, signer: daoOracle, args: { count: 2 } })
+ await time.increase(time.duration.days(1))
+ await runUpkeep({ donTransmitter, upkeep })
- await runUpkeep({ donTransmitter, upkeep })
+ const sweptExitedBalance = 32
+ const secondReportValues = {
+ beaconBalance: 32,
+ sweptBalance: sweptExitedBalance,
+ activatedDeposits: 0,
+ forcedExits: 0,
+ completedExits: 1,
+ compoundablePoolIds: [0,
+ 0,
+ 0,
+ 0,
+ 0]
+ }
- const stakedPoolIds = await manager.getStakedPoolIds()
-
- expect(stakedPoolIds.length).equal(2)
-
- let stake = await manager.getTotalStake()
- let userStake = await manager.getUserStake(firstUser.address)
-
- expect(ethers.utils.formatEther(stake)).equal('64.0')
- expect(ethers.utils.formatEther(userStake)).equal('64.0')
-
- const userBalanceBefore = await ethers.provider.getBalance(firstUser.address)
- const userWithdrawalRequest = await manager.connect(firstUser).requestWithdrawal(ethers.utils.parseEther('32.0'))
- await userWithdrawalRequest.wait()
-
- stake = await manager.getTotalStake()
- userStake = await manager.getUserStake(firstUser.address)
-
- expect(ethers.utils.formatEther(stake)).equal('32.0')
- expect(ethers.utils.formatEther(userStake)).equal('32.0')
-
- await time.increase(time.duration.days(1))
- await runUpkeep({ donTransmitter, upkeep })
-
- const sweptExitedBalance = 32
- const secondReportValues = {
- beaconBalance: 32,
- sweptBalance: sweptExitedBalance,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 1,
- compoundablePoolIds: [0, 0, 0, 0, 0]
- }
-
- await fulfillReport({
- donTransmitter,
- upkeep,
- functionsBillingRegistry,
- values: secondReportValues
- })
-
- const exitedPoolId = (await manager.getStakedPoolIds())[0]
- const exitedPoolAddress = await manager.getPoolAddress(exitedPoolId)
- const currentBalance = await ethers.provider.getBalance(exitedPoolAddress)
- const nextBalance = currentBalance.add(ethers.utils.parseEther(sweptExitedBalance.toString()))
- await setBalance(exitedPoolAddress, nextBalance)
- await reportCompletedExitsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
- const finalizableCompletedExits = await manager.finalizableCompletedExits()
- expect(finalizableCompletedExits.toNumber()).equal(1)
- await runUpkeep({ donTransmitter, upkeep })
-
- stake = await manager.getTotalStake()
- userStake = await manager.getUserStake(firstUser.address)
-
- const userBalanceAfter = await ethers.provider.getBalance(firstUser.address)
-
- expect(ethers.utils.formatEther(stake)).equal('32.0')
- expect(ethers.utils.formatEther(userStake)).equal('32.0')
- expect(ethers.utils.formatEther(userBalanceAfter.sub(userBalanceBefore))).contains('31.9')
+ await fulfillReport({
+ donTransmitter,
+ upkeep,
+ functionsBillingRegistry,
+ values: secondReportValues
})
+
+ const exitedPoolId = (await manager.getStakedPoolIds())[0]
+ const exitedPoolAddress = await manager.getPoolAddress(exitedPoolId)
+ const currentBalance = await ethers.provider.getBalance(exitedPoolAddress)
+ const nextBalance = currentBalance.add(ethers.utils.parseEther(sweptExitedBalance.toString()))
+ await setBalance(exitedPoolAddress, nextBalance)
+ await reportCompletedExitsHandler({ manager, views, signer: daoOracle, args: { count: 1 } })
+ const finalizableCompletedExits = await manager.finalizableCompletedExits()
+ expect(finalizableCompletedExits.toNumber()).equal(1)
+ await runUpkeep({ donTransmitter, upkeep })
+
+ stake = await manager.getTotalStake()
+ userStake = await manager.getUserStake(firstUser.address)
+
+ const userBalanceAfter = await ethers.provider.getBalance(firstUser.address)
+
+ expect(ethers.utils.formatEther(stake)).equal("32.0")
+ expect(ethers.utils.formatEther(userStake)).equal("32.0")
+ expect(ethers.utils.formatEther(userBalanceAfter.sub(userBalanceBefore))).contains("31.9")
+ })
})
\ No newline at end of file
diff --git a/infrastructure/cdk/src/index.ts b/infrastructure/cdk/src/index.ts
index e71f8374a..b28f2b0ce 100755
--- a/infrastructure/cdk/src/index.ts
+++ b/infrastructure/cdk/src/index.ts
@@ -1,32 +1,32 @@
-import * as cdk from 'aws-cdk-lib'
-import { Config } from './providers/config'
-import { AnalyticsStack } from './providers/analytics'
-import { BlogStack } from './providers/blog'
-import { DocsStack } from './providers/docs'
-import { DnsStack } from './providers/dns'
-import { LandingStack } from './providers/landing'
-import { NetworkStack } from './providers/network'
-import { NodesStack } from './providers/nodes'
-import { UsersStack } from './providers/users'
-import { WebStack } from './providers/web'
+import * as cdk from "aws-cdk-lib"
+import { Config } from "./providers/config"
+import { AnalyticsStack } from "./providers/analytics"
+import { BlogStack } from "./providers/blog"
+import { DocsStack } from "./providers/docs"
+import { DnsStack } from "./providers/dns"
+import { LandingStack } from "./providers/landing"
+import { NetworkStack } from "./providers/network"
+import { NodesStack } from "./providers/nodes"
+import { UsersStack } from "./providers/users"
+import { WebStack } from "./providers/web"
const config = new Config()
const { env, stage } = config
const app = new cdk.App()
-const { hostedZone, certificate } = new DnsStack(app, config.getFullStackName('dns'), { env })
-const { vpc } = new NetworkStack(app, config.getFullStackName('network'), { env })
+const { hostedZone, certificate } = new DnsStack(app, config.getFullStackName("dns"), { env })
+const { vpc } = new NetworkStack(app, config.getFullStackName("network"), { env })
-if (stage !== 'prod') {
- new AnalyticsStack(app, config.getFullStackName('analytics'), { env })
- new BlogStack(app, config.getFullStackName('blog'), { env, certificate, hostedZone, vpc })
- new DocsStack(app, config.getFullStackName('docs'), { env, certificate, hostedZone })
- new LandingStack(app, config.getFullStackName('landing'), { env, certificate, hostedZone })
- new UsersStack(app, config.getFullStackName('users'), { env, certificate, hostedZone, vpc })
- new WebStack(app, config.getFullStackName('web'), { env, certificate, hostedZone })
+if (stage !== "prod") {
+ new AnalyticsStack(app, config.getFullStackName("analytics"), { env })
+ new BlogStack(app, config.getFullStackName("blog"), { env, certificate, hostedZone, vpc })
+ new DocsStack(app, config.getFullStackName("docs"), { env, certificate, hostedZone })
+ new LandingStack(app, config.getFullStackName("landing"), { env, certificate, hostedZone })
+ new UsersStack(app, config.getFullStackName("users"), { env, certificate, hostedZone, vpc })
+ new WebStack(app, config.getFullStackName("web"), { env, certificate, hostedZone })
} else {
- new BlogStack(app, config.getFullStackName('blog'), { env, certificate, hostedZone, vpc })
- new DocsStack(app, config.getFullStackName('docs'), { env, certificate, hostedZone })
- new LandingStack(app, config.getFullStackName('landing'), { env, certificate, hostedZone })
- new NodesStack(app, config.getFullStackName('nodes'), { env, hostedZone })
+ new BlogStack(app, config.getFullStackName("blog"), { env, certificate, hostedZone, vpc })
+ new DocsStack(app, config.getFullStackName("docs"), { env, certificate, hostedZone })
+ new LandingStack(app, config.getFullStackName("landing"), { env, certificate, hostedZone })
+ new NodesStack(app, config.getFullStackName("nodes"), { env, hostedZone })
}
diff --git a/infrastructure/cdk/src/interfaces/StackProps.ts b/infrastructure/cdk/src/interfaces/StackProps.ts
index 52fc80156..d7124d044 100644
--- a/infrastructure/cdk/src/interfaces/StackProps.ts
+++ b/infrastructure/cdk/src/interfaces/StackProps.ts
@@ -1,7 +1,7 @@
-import * as cdk from 'aws-cdk-lib'
-import * as certmgr from 'aws-cdk-lib/aws-certificatemanager'
-import * as ec2 from 'aws-cdk-lib/aws-ec2'
-import * as route53 from 'aws-cdk-lib/aws-route53'
+import * as cdk from "aws-cdk-lib"
+import * as certmgr from "aws-cdk-lib/aws-certificatemanager"
+import * as ec2 from "aws-cdk-lib/aws-ec2"
+import * as route53 from "aws-cdk-lib/aws-route53"
export type DnsStackProps = cdk.StackProps
export type AnalyticsStackProps = cdk.StackProps
diff --git a/infrastructure/cdk/src/providers/analytics.ts b/infrastructure/cdk/src/providers/analytics.ts
index 31f08de5a..1908f74e5 100644
--- a/infrastructure/cdk/src/providers/analytics.ts
+++ b/infrastructure/cdk/src/providers/analytics.ts
@@ -1,56 +1,56 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as s3 from 'aws-cdk-lib/aws-s3'
-import * as glue from '@aws-cdk/aws-glue-alpha'
-import { Schema, eventSchema, actionSchema } from '@casimir/data'
-import { kebabCase, pascalCase, snakeCase } from '@casimir/format'
-import { Config } from './config'
-import { AnalyticsStackProps } from '../interfaces/StackProps'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as s3 from "aws-cdk-lib/aws-s3"
+import * as glue from "@aws-cdk/aws-glue-alpha"
+import { Schema, eventSchema, actionSchema } from "@casimir/data"
+import { kebabCase, pascalCase, snakeCase } from "@casimir/format"
+import { Config } from "./config"
+import { AnalyticsStackProps } from "../interfaces/StackProps"
/**
* Data analytics stack
*/
export class AnalyticsStack extends cdk.Stack {
- public readonly name = pascalCase('analytics')
+ public readonly name = pascalCase("analytics")
- constructor(scope: Construct, id: string, props: AnalyticsStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: AnalyticsStackProps) {
+ super(scope, id, props)
- const config = new Config()
+ const config = new Config()
- const eventColumns = new Schema(eventSchema).getGlueColumns()
- const actionColumns = new Schema(actionSchema).getGlueColumns()
+ const eventColumns = new Schema(eventSchema).getGlueColumns()
+ const actionColumns = new Schema(actionSchema).getGlueColumns()
- const database = new glue.Database(this, config.getFullStackResourceName(this.name, 'database'), {
- databaseName: snakeCase(config.getFullStackResourceName(this.name, 'database'))
- })
+ const database = new glue.Database(this, config.getFullStackResourceName(this.name, "database"), {
+ databaseName: snakeCase(config.getFullStackResourceName(this.name, "database"))
+ })
- const eventBucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, 'event-bucket', config.dataVersion), {
- bucketName: kebabCase(config.getFullStackResourceName(this.name, 'event-bucket', config.dataVersion))
- })
+ const eventBucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, "event-bucket", config.dataVersion), {
+ bucketName: kebabCase(config.getFullStackResourceName(this.name, "event-bucket", config.dataVersion))
+ })
- const actionBucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, 'action-bucket', config.dataVersion), {
- bucketName: kebabCase(config.getFullStackResourceName(this.name, 'action-bucket', config.dataVersion))
- })
+ const actionBucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, "action-bucket", config.dataVersion), {
+ bucketName: kebabCase(config.getFullStackResourceName(this.name, "action-bucket", config.dataVersion))
+ })
- new s3.Bucket(this, config.getFullStackResourceName(this.name, 'output-bucket', config.dataVersion), {
- bucketName: kebabCase(config.getFullStackResourceName(this.name, 'output-bucket', config.dataVersion))
- })
-
- new glue.Table(this, config.getFullStackResourceName(this.name, 'event-table', config.dataVersion), {
- database: database,
- tableName: snakeCase(config.getFullStackResourceName(this.name, 'event-table', config.dataVersion)),
- bucket: eventBucket,
- columns: eventColumns,
- dataFormat: glue.DataFormat.JSON,
- })
+ new s3.Bucket(this, config.getFullStackResourceName(this.name, "output-bucket", config.dataVersion), {
+ bucketName: kebabCase(config.getFullStackResourceName(this.name, "output-bucket", config.dataVersion))
+ })
+
+ new glue.Table(this, config.getFullStackResourceName(this.name, "event-table", config.dataVersion), {
+ database: database,
+ tableName: snakeCase(config.getFullStackResourceName(this.name, "event-table", config.dataVersion)),
+ bucket: eventBucket,
+ columns: eventColumns,
+ dataFormat: glue.DataFormat.JSON,
+ })
- new glue.Table(this, config.getFullStackResourceName(this.name, 'action-table', config.dataVersion), {
- database: database,
- tableName: snakeCase(config.getFullStackResourceName(this.name, 'action-table', config.dataVersion)),
- bucket: actionBucket,
- columns: actionColumns,
- dataFormat: glue.DataFormat.JSON,
- })
- }
+ new glue.Table(this, config.getFullStackResourceName(this.name, "action-table", config.dataVersion), {
+ database: database,
+ tableName: snakeCase(config.getFullStackResourceName(this.name, "action-table", config.dataVersion)),
+ bucket: actionBucket,
+ columns: actionColumns,
+ dataFormat: glue.DataFormat.JSON,
+ })
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/src/providers/blog.ts b/infrastructure/cdk/src/providers/blog.ts
index 0f5966f34..71e147abb 100644
--- a/infrastructure/cdk/src/providers/blog.ts
+++ b/infrastructure/cdk/src/providers/blog.ts
@@ -1,59 +1,59 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as ecrAssets from 'aws-cdk-lib/aws-ecr-assets'
-import * as ecs from 'aws-cdk-lib/aws-ecs'
-import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns'
-import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'
-import { BlogStackProps } from '../interfaces/StackProps'
-import { Config } from './config'
-import { kebabCase, pascalCase } from '@casimir/format'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as ecrAssets from "aws-cdk-lib/aws-ecr-assets"
+import * as ecs from "aws-cdk-lib/aws-ecs"
+import * as ecsPatterns from "aws-cdk-lib/aws-ecs-patterns"
+import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager"
+import { BlogStackProps } from "../interfaces/StackProps"
+import { Config } from "./config"
+import { kebabCase, pascalCase } from "@casimir/format"
/**
* Blog service stack
*/
export class BlogStack extends cdk.Stack {
- public readonly name = 'blog'
+ public readonly name = "blog"
- constructor(scope: Construct, id: string, props: BlogStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: BlogStackProps) {
+ super(scope, id, props)
- const config = new Config()
- const { project, stage, rootDomain, subdomains } = config
- const { certificate, hostedZone, vpc } = props
+ const config = new Config()
+ const { project, stage, rootDomain, subdomains } = config
+ const { certificate, hostedZone, vpc } = props
- const imageAsset = new ecrAssets.DockerImageAsset(this, config.getFullStackResourceName(this.name, 'image'), {
- directory: '../../',
- file: 'services/blog/Dockerfile',
- platform: ecrAssets.Platform.LINUX_AMD64,
- ignoreMode: cdk.IgnoreMode.GIT
- })
+ const imageAsset = new ecrAssets.DockerImageAsset(this, config.getFullStackResourceName(this.name, "image"), {
+ directory: "../../",
+ file: "services/blog/Dockerfile",
+ platform: ecrAssets.Platform.LINUX_AMD64,
+ ignoreMode: cdk.IgnoreMode.GIT
+ })
- const hackmdTokenKey = 'casimir-blog-hackmd-token'
- const hackmdToken = ecs.Secret.fromSecretsManager(
- secretsmanager.Secret.fromSecretNameV2(this, pascalCase(hackmdTokenKey), kebabCase(hackmdTokenKey))
- )
+ const hackmdTokenKey = "casimir-blog-hackmd-token"
+ const hackmdToken = ecs.Secret.fromSecretsManager(
+ secretsmanager.Secret.fromSecretNameV2(this, pascalCase(hackmdTokenKey), kebabCase(hackmdTokenKey))
+ )
- const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, config.getFullStackResourceName(this.name, 'fargate'), {
- assignPublicIp: true,
- certificate,
- domainName: `${subdomains.blog}.${rootDomain}`, // e.g. blog.casimir.co or blog.dev.casimir.co
- domainZone: hostedZone,
- taskImageOptions: {
- containerPort: 4001,
- image: ecs.ContainerImage.fromDockerImageAsset(imageAsset),
- environment: {
- PROJECT: project,
- STAGE: stage
- },
- secrets: {
- HACKMD_TOKEN: hackmdToken
- }
- },
- vpc
- })
+ const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, config.getFullStackResourceName(this.name, "fargate"), {
+ assignPublicIp: true,
+ certificate,
+ domainName: `${subdomains.blog}.${rootDomain}`, // e.g. blog.casimir.co or blog.dev.casimir.co
+ domainZone: hostedZone,
+ taskImageOptions: {
+ containerPort: 4001,
+ image: ecs.ContainerImage.fromDockerImageAsset(imageAsset),
+ environment: {
+ PROJECT: project,
+ STAGE: stage
+ },
+ secrets: {
+ HACKMD_TOKEN: hackmdToken
+ }
+ },
+ vpc
+ })
- fargateService.targetGroup.configureHealthCheck({
- path: '/health'
- })
- }
+ fargateService.targetGroup.configureHealthCheck({
+ path: "/health"
+ })
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/src/providers/config.ts b/infrastructure/cdk/src/providers/config.ts
index a6ecce79c..c4dce91e3 100644
--- a/infrastructure/cdk/src/providers/config.ts
+++ b/infrastructure/cdk/src/providers/config.ts
@@ -1,55 +1,58 @@
-import { pascalCase } from '@casimir/format'
-import { ProjectConfig } from '../interfaces/ProjectConfig'
-import dataPackage from '@casimir/data/package.json'
+import { pascalCase } from "@casimir/format"
+import { ProjectConfig } from "../interfaces/ProjectConfig"
+import dataPackage from "@casimir/data/package.json"
/**
* CDK app config
*/
export class Config implements ProjectConfig {
- public readonly project
- public readonly stage
- public readonly env
- public readonly rootDomain
- public readonly subdomains
- public readonly dataVersion
+ public readonly project
+ public readonly stage
+ public readonly env
+ public readonly rootDomain
+ public readonly subdomains
+ public readonly dataVersion
- public readonly requiredEnvVars = ['PROJECT', 'STAGE', 'AWS_ACCOUNT', 'AWS_REGION']
+ public readonly requiredEnvVars = ["PROJECT",
+ "STAGE",
+ "AWS_ACCOUNT",
+ "AWS_REGION"]
- constructor() {
- this.checkEnvVars()
- this.project = process.env.PROJECT as string
- this.stage = process.env.STAGE as string
- this.env = {
- account: process.env.AWS_ACCOUNT as string,
- region: process.env.AWS_REGION as string
- }
- this.rootDomain = `${this.stage === 'prod' ? '' : `${this.stage}.`}casimir.co`
- this.subdomains = {
- blog: 'blog',
- docs: 'docs',
- nodes: 'nodes',
- landing: 'www',
- users: 'users',
- web: 'app',
- wildcard: '*'
- }
- this.dataVersion = Number(dataPackage.version.split('.')[0])
+ constructor() {
+ this.checkEnvVars()
+ this.project = process.env.PROJECT as string
+ this.stage = process.env.STAGE as string
+ this.env = {
+ account: process.env.AWS_ACCOUNT as string,
+ region: process.env.AWS_REGION as string
}
+ this.rootDomain = `${this.stage === "prod" ? "" : `${this.stage}.`}casimir.co`
+ this.subdomains = {
+ blog: "blog",
+ docs: "docs",
+ nodes: "nodes",
+ landing: "www",
+ users: "users",
+ web: "app",
+ wildcard: "*"
+ }
+ this.dataVersion = Number(dataPackage.version.split(".")[0])
+ }
- /**
+ /**
* Check for required environment variables and exit if any are missing
* @returns void
*/
- checkEnvVars(): void {
- this.requiredEnvVars.forEach(v => {
- if (!process.env[v]) {
- console.log('No value provided for', v)
- process.exit(1)
- }
- })
- }
+ checkEnvVars(): void {
+ this.requiredEnvVars.forEach(v => {
+ if (!process.env[v]) {
+ console.log("No value provided for", v)
+ process.exit(1)
+ }
+ })
+ }
- /**
+ /**
* Get stack name with project prefix and stage suffix
* @param stackName Stack name
* @returns Full stack name
@@ -59,11 +62,11 @@ export class Config implements ProjectConfig {
* console.log(stackName) // EtlDev
* ```
*/
- getFullStackName(stackName: string): string {
- return pascalCase(this.project) + pascalCase(stackName) + pascalCase(this.stage)
- }
+ getFullStackName(stackName: string): string {
+ return pascalCase(this.project) + pascalCase(stackName) + pascalCase(this.stage)
+ }
- /**
+ /**
* Get stack resource name with project prefix and stage suffix
* @param stackName Stack name
* @param resourceName Resource name
@@ -75,11 +78,11 @@ export class Config implements ProjectConfig {
* console.log(resourceName) // CasimirEtlEventBucketDev
* ```
*/
- getFullStackResourceName(stackName: string, resourceName: string, version?: number): string {
- const name = pascalCase(this.project) + pascalCase(stackName) + pascalCase(resourceName) + pascalCase(this.stage)
- if (version) {
- return name + version
- }
- return name
+ getFullStackResourceName(stackName: string, resourceName: string, version?: number): string {
+ const name = pascalCase(this.project) + pascalCase(stackName) + pascalCase(resourceName) + pascalCase(this.stage)
+ if (version) {
+ return name + version
}
+ return name
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/src/providers/dns.ts b/infrastructure/cdk/src/providers/dns.ts
index 2d3d7e690..a429f8494 100644
--- a/infrastructure/cdk/src/providers/dns.ts
+++ b/infrastructure/cdk/src/providers/dns.ts
@@ -1,40 +1,40 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as certmgr from 'aws-cdk-lib/aws-certificatemanager'
-import * as route53 from 'aws-cdk-lib/aws-route53'
-import { DnsStackProps } from '../interfaces/StackProps'
-import { pascalCase } from '@casimir/format'
-import { Config } from './config'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as certmgr from "aws-cdk-lib/aws-certificatemanager"
+import * as route53 from "aws-cdk-lib/aws-route53"
+import { DnsStackProps } from "../interfaces/StackProps"
+import { pascalCase } from "@casimir/format"
+import { Config } from "./config"
/**
* Route53 dns stack
*/
export class DnsStack extends cdk.Stack {
- public readonly name = pascalCase('dns')
- public readonly hostedZone: route53.HostedZone
- public readonly certificate: certmgr.Certificate
+ public readonly name = pascalCase("dns")
+ public readonly hostedZone: route53.HostedZone
+ public readonly certificate: certmgr.Certificate
- constructor(scope: Construct, id: string, props: DnsStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: DnsStackProps) {
+ super(scope, id, props)
- const config = new Config()
- const { rootDomain, subdomains } = config
+ const config = new Config()
+ const { rootDomain, subdomains } = config
- const absoluteRootDomain = (() => {
- if (rootDomain.split('.').length > 2) {
- return rootDomain.split('.').slice(1).join('.')
- }
- return rootDomain
- })()
+ const absoluteRootDomain = (() => {
+ if (rootDomain.split(".").length > 2) {
+ return rootDomain.split(".").slice(1).join(".")
+ }
+ return rootDomain
+ })()
- this.hostedZone = route53.HostedZone.fromLookup(this, config.getFullStackResourceName(this.name, 'hosted-zone'), {
- domainName: absoluteRootDomain
- }) as route53.HostedZone
+ this.hostedZone = route53.HostedZone.fromLookup(this, config.getFullStackResourceName(this.name, "hosted-zone"), {
+ domainName: absoluteRootDomain
+ }) as route53.HostedZone
- this.certificate = new certmgr.Certificate(this, config.getFullStackResourceName(this.name, 'cert'), {
- domainName: rootDomain,
- subjectAlternativeNames: [`${subdomains.wildcard}.${rootDomain}`],
- validation: certmgr.CertificateValidation.fromDns(this.hostedZone)
- })
- }
+ this.certificate = new certmgr.Certificate(this, config.getFullStackResourceName(this.name, "cert"), {
+ domainName: rootDomain,
+ subjectAlternativeNames: [`${subdomains.wildcard}.${rootDomain}`],
+ validation: certmgr.CertificateValidation.fromDns(this.hostedZone)
+ })
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/src/providers/docs.ts b/infrastructure/cdk/src/providers/docs.ts
index 006a5bef5..8094e5e8e 100644
--- a/infrastructure/cdk/src/providers/docs.ts
+++ b/infrastructure/cdk/src/providers/docs.ts
@@ -1,91 +1,90 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as certmgr from 'aws-cdk-lib/aws-certificatemanager'
-import * as route53targets from 'aws-cdk-lib/aws-route53-targets'
-import * as route53 from 'aws-cdk-lib/aws-route53'
-import * as s3 from 'aws-cdk-lib/aws-s3'
-import * as s3Deployment from 'aws-cdk-lib/aws-s3-deployment'
-import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'
-import * as cloudfrontOrigins from 'aws-cdk-lib/aws-cloudfront-origins'
-import { DocsStackProps } from '../interfaces/StackProps'
-import { pascalCase } from '@casimir/format'
-import { Config } from './config'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as certmgr from "aws-cdk-lib/aws-certificatemanager"
+import * as route53targets from "aws-cdk-lib/aws-route53-targets"
+import * as route53 from "aws-cdk-lib/aws-route53"
+import * as s3 from "aws-cdk-lib/aws-s3"
+import * as s3Deployment from "aws-cdk-lib/aws-s3-deployment"
+import * as cloudfront from "aws-cdk-lib/aws-cloudfront"
+import * as cloudfrontOrigins from "aws-cdk-lib/aws-cloudfront-origins"
+import { DocsStackProps } from "../interfaces/StackProps"
+import { pascalCase } from "@casimir/format"
+import { Config } from "./config"
/**
* Docs app stack
*/
export class DocsStack extends cdk.Stack {
- public readonly name = pascalCase('docs')
+ public readonly name = pascalCase("docs")
- constructor(scope: Construct, id: string, props: DocsStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: DocsStackProps) {
+ super(scope, id, props)
- const config = new Config()
- const { rootDomain, subdomains } = config
- const { hostedZone, certificate } = props
+ const config = new Config()
+ const { rootDomain, subdomains } = config
+ const { hostedZone, certificate } = props
- const bucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, 'bucket'), {
- accessControl: s3.BucketAccessControl.PRIVATE
- })
+ const bucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, "bucket"), {
+ accessControl: s3.BucketAccessControl.PRIVATE
+ })
- const originAccessIdentity = new cloudfront.OriginAccessIdentity(this, config.getFullStackResourceName(this.name, 'origin-access-identity'))
- bucket.grantRead(originAccessIdentity)
+ const originAccessIdentity = new cloudfront.OriginAccessIdentity(this, config.getFullStackResourceName(this.name, "origin-access-identity"))
+ bucket.grantRead(originAccessIdentity)
- const distributionCertificate = (() => {
- if (certificate?.env.region === 'us-east-1') return certificate
- /** Replace deprecated method when cross-region support is out of beta */
- return new certmgr.DnsValidatedCertificate(this, config.getFullStackResourceName(this.name, 'cert'), {
- domainName: rootDomain,
- subjectAlternativeNames: [`${subdomains.docs}.${rootDomain}`],
- hostedZone,
- region: 'us-east-1'
- })
- })()
+ const distributionCertificate = (() => {
+ if (certificate?.env.region === "us-east-1") return certificate
+ /** Replace deprecated method when cross-region support is out of beta */
+ return new certmgr.DnsValidatedCertificate(this, config.getFullStackResourceName(this.name, "cert"), {
+ domainName: rootDomain,
+ subjectAlternativeNames: [`${subdomains.docs}.${rootDomain}`],
+ hostedZone,
+ region: "us-east-1"
+ })
+ })()
- const redirectFunction = new cloudfront.Function(this, config.getFullStackResourceName(this.name, 'redirect'), {
- code: cloudfront.FunctionCode.fromFile({ filePath: '../../services/redirect/dist/index.js' })
- })
+ const redirectFunction = new cloudfront.Function(this, config.getFullStackResourceName(this.name, "redirect"), {
+ code: cloudfront.FunctionCode.fromFile({ filePath: "../../services/redirect/dist/index.js" })
+ })
- const distribution = new cloudfront.Distribution(this, config.getFullStackResourceName(this.name, 'distribution'), {
- certificate: distributionCertificate,
- defaultRootObject: 'index.html',
- defaultBehavior: {
- functionAssociations: [{
- function: redirectFunction,
- eventType: cloudfront.FunctionEventType.VIEWER_REQUEST
- }],
- viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
- origin: new cloudfrontOrigins.S3Origin(bucket, { originAccessIdentity })
- },
- errorResponses: [
- {
- httpStatus: 403,
- responseHttpStatus: 200,
- responsePagePath: '/index.html',
- ttl: cdk.Duration.minutes(30)
- },
- {
- httpStatus: 404,
- responseHttpStatus: 200,
- responsePagePath: '/index.html',
- ttl: cdk.Duration.minutes(30)
- }
- ],
- domainNames: [`${subdomains.docs}.${rootDomain}`]
- })
+ const distribution = new cloudfront.Distribution(this, config.getFullStackResourceName(this.name, "distribution"), {
+ certificate: distributionCertificate,
+ defaultRootObject: "index.html",
+ defaultBehavior: {
+ functionAssociations: [{
+ function: redirectFunction,
+ eventType: cloudfront.FunctionEventType.VIEWER_REQUEST
+ }],
+ viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
+ origin: new cloudfrontOrigins.S3Origin(bucket, { originAccessIdentity })
+ },
+ errorResponses: [
+ {
+ httpStatus: 403,
+ responseHttpStatus: 200,
+ responsePagePath: "/index.html",
+ ttl: cdk.Duration.minutes(30)
+ }, {
+ httpStatus: 404,
+ responseHttpStatus: 200,
+ responsePagePath: "/index.html",
+ ttl: cdk.Duration.minutes(30)
+ }
+ ],
+ domainNames: [`${subdomains.docs}.${rootDomain}`]
+ })
- new s3Deployment.BucketDeployment(this, config.getFullStackResourceName(this.name, 'bucket-deployment'), {
- destinationBucket: bucket,
- sources: [s3Deployment.Source.asset('../../apps/docs/dist')],
- distribution,
- distributionPaths: ['/*'],
- })
+ new s3Deployment.BucketDeployment(this, config.getFullStackResourceName(this.name, "bucket-deployment"), {
+ destinationBucket: bucket,
+ sources: [s3Deployment.Source.asset("../../apps/docs/dist")],
+ distribution,
+ distributionPaths: ["/*"],
+ })
- new route53.ARecord(this, config.getFullStackResourceName(this.name, 'a-record-docs'), {
- recordName: `${subdomains.docs}.${rootDomain}`,
- zone: hostedZone as route53.IHostedZone,
- target: route53.RecordTarget.fromAlias(new route53targets.CloudFrontTarget(distribution)),
- ttl: cdk.Duration.minutes(1),
- })
- }
+ new route53.ARecord(this, config.getFullStackResourceName(this.name, "a-record-docs"), {
+ recordName: `${subdomains.docs}.${rootDomain}`,
+ zone: hostedZone as route53.IHostedZone,
+ target: route53.RecordTarget.fromAlias(new route53targets.CloudFrontTarget(distribution)),
+ ttl: cdk.Duration.minutes(1),
+ })
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/src/providers/landing.ts b/infrastructure/cdk/src/providers/landing.ts
index 10a10dc9b..38bf41b32 100644
--- a/infrastructure/cdk/src/providers/landing.ts
+++ b/infrastructure/cdk/src/providers/landing.ts
@@ -1,90 +1,89 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as certmgr from 'aws-cdk-lib/aws-certificatemanager'
-import * as route53targets from 'aws-cdk-lib/aws-route53-targets'
-import * as route53 from 'aws-cdk-lib/aws-route53'
-import * as s3 from 'aws-cdk-lib/aws-s3'
-import * as s3Deployment from 'aws-cdk-lib/aws-s3-deployment'
-import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'
-import * as cloudfrontOrigins from 'aws-cdk-lib/aws-cloudfront-origins'
-import { LandingStackProps } from '../interfaces/StackProps'
-import { pascalCase } from '@casimir/format'
-import { Config } from './config'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as certmgr from "aws-cdk-lib/aws-certificatemanager"
+import * as route53targets from "aws-cdk-lib/aws-route53-targets"
+import * as route53 from "aws-cdk-lib/aws-route53"
+import * as s3 from "aws-cdk-lib/aws-s3"
+import * as s3Deployment from "aws-cdk-lib/aws-s3-deployment"
+import * as cloudfront from "aws-cdk-lib/aws-cloudfront"
+import * as cloudfrontOrigins from "aws-cdk-lib/aws-cloudfront-origins"
+import { LandingStackProps } from "../interfaces/StackProps"
+import { pascalCase } from "@casimir/format"
+import { Config } from "./config"
/**
* Landing page stack
*/
export class LandingStack extends cdk.Stack {
- public readonly name = pascalCase('landing')
+ public readonly name = pascalCase("landing")
- constructor(scope: Construct, id: string, props: LandingStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: LandingStackProps) {
+ super(scope, id, props)
- const config = new Config()
- const { rootDomain, subdomains } = config
- const { hostedZone, certificate } = props
+ const config = new Config()
+ const { rootDomain, subdomains } = config
+ const { hostedZone, certificate } = props
- const bucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, 'bucket'), {
- accessControl: s3.BucketAccessControl.PRIVATE
- })
+ const bucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, "bucket"), {
+ accessControl: s3.BucketAccessControl.PRIVATE
+ })
- const originAccessIdentity = new cloudfront.OriginAccessIdentity(this, config.getFullStackResourceName(this.name, 'origin-access-identity'))
- bucket.grantRead(originAccessIdentity)
+ const originAccessIdentity = new cloudfront.OriginAccessIdentity(this, config.getFullStackResourceName(this.name, "origin-access-identity"))
+ bucket.grantRead(originAccessIdentity)
- const distributionCertificate = (() => {
- if (certificate?.env.region === 'us-east-1') return certificate
- /** Replace deprecated method when cross-region support is out of beta */
- return new certmgr.DnsValidatedCertificate(this, config.getFullStackResourceName(this.name, 'cert'), {
- domainName: rootDomain,
- subjectAlternativeNames: [`${subdomains.landing}.${rootDomain}`],
- hostedZone,
- region: 'us-east-1'
- })
- })()
+ const distributionCertificate = (() => {
+ if (certificate?.env.region === "us-east-1") return certificate
+ /** Replace deprecated method when cross-region support is out of beta */
+ return new certmgr.DnsValidatedCertificate(this, config.getFullStackResourceName(this.name, "cert"), {
+ domainName: rootDomain,
+ subjectAlternativeNames: [`${subdomains.landing}.${rootDomain}`],
+ hostedZone,
+ region: "us-east-1"
+ })
+ })()
- const distribution = new cloudfront.Distribution(this, config.getFullStackResourceName(this.name, 'distribution'), {
- certificate: distributionCertificate,
- defaultRootObject: 'index.html',
- errorResponses: [
- {
- httpStatus: 403,
- responseHttpStatus: 200,
- responsePagePath: '/index.html',
- ttl: cdk.Duration.minutes(30)
- },
- {
- httpStatus: 404,
- responseHttpStatus: 200,
- responsePagePath: '/index.html',
- ttl: cdk.Duration.minutes(30)
- }
- ],
- defaultBehavior: {
- viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
- origin: new cloudfrontOrigins.S3Origin(bucket, { originAccessIdentity })
- },
- domainNames: [rootDomain, `${subdomains.landing}.${rootDomain}`]
- })
+ const distribution = new cloudfront.Distribution(this, config.getFullStackResourceName(this.name, "distribution"), {
+ certificate: distributionCertificate,
+ defaultRootObject: "index.html",
+ errorResponses: [
+ {
+ httpStatus: 403,
+ responseHttpStatus: 200,
+ responsePagePath: "/index.html",
+ ttl: cdk.Duration.minutes(30)
+ }, {
+ httpStatus: 404,
+ responseHttpStatus: 200,
+ responsePagePath: "/index.html",
+ ttl: cdk.Duration.minutes(30)
+ }
+ ],
+ defaultBehavior: {
+ viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
+ origin: new cloudfrontOrigins.S3Origin(bucket, { originAccessIdentity })
+ },
+ domainNames: [rootDomain, `${subdomains.landing}.${rootDomain}`]
+ })
- new s3Deployment.BucketDeployment(this, config.getFullStackResourceName(this.name, 'bucket-deployment'), {
- destinationBucket: bucket,
- sources: [s3Deployment.Source.asset('../../apps/landing/dist')],
- distribution,
- distributionPaths: ['/*']
- })
+ new s3Deployment.BucketDeployment(this, config.getFullStackResourceName(this.name, "bucket-deployment"), {
+ destinationBucket: bucket,
+ sources: [s3Deployment.Source.asset("../../apps/landing/dist")],
+ distribution,
+ distributionPaths: ["/*"]
+ })
- new route53.ARecord(this, config.getFullStackResourceName(this.name, 'a-record'), {
- recordName: rootDomain,
- zone: hostedZone as route53.IHostedZone,
- target: route53.RecordTarget.fromAlias(new route53targets.CloudFrontTarget(distribution)),
- ttl: cdk.Duration.minutes(1),
- })
+ new route53.ARecord(this, config.getFullStackResourceName(this.name, "a-record"), {
+ recordName: rootDomain,
+ zone: hostedZone as route53.IHostedZone,
+ target: route53.RecordTarget.fromAlias(new route53targets.CloudFrontTarget(distribution)),
+ ttl: cdk.Duration.minutes(1),
+ })
- new route53.ARecord(this, config.getFullStackResourceName(this.name, 'a-record-www'), {
- recordName: `${subdomains.landing}.${rootDomain}`,
- zone: hostedZone as route53.IHostedZone,
- target: route53.RecordTarget.fromAlias(new route53targets.CloudFrontTarget(distribution)),
- ttl: cdk.Duration.minutes(1),
- })
- }
+ new route53.ARecord(this, config.getFullStackResourceName(this.name, "a-record-www"), {
+ recordName: `${subdomains.landing}.${rootDomain}`,
+ zone: hostedZone as route53.IHostedZone,
+ target: route53.RecordTarget.fromAlias(new route53targets.CloudFrontTarget(distribution)),
+ ttl: cdk.Duration.minutes(1),
+ })
+ }
}
diff --git a/infrastructure/cdk/src/providers/network.ts b/infrastructure/cdk/src/providers/network.ts
index 29debec35..8d894420f 100644
--- a/infrastructure/cdk/src/providers/network.ts
+++ b/infrastructure/cdk/src/providers/network.ts
@@ -1,24 +1,24 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as ec2 from 'aws-cdk-lib/aws-ec2'
-import { NetworkStackProps } from '../interfaces/StackProps'
-import { pascalCase } from '@casimir/format'
-import { Config } from './config'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as ec2 from "aws-cdk-lib/aws-ec2"
+import { NetworkStackProps } from "../interfaces/StackProps"
+import { pascalCase } from "@casimir/format"
+import { Config } from "./config"
/**
* VPC network stack
*/
export class NetworkStack extends cdk.Stack {
- public readonly name = pascalCase('network')
- public readonly vpc: ec2.Vpc
+ public readonly name = pascalCase("network")
+ public readonly vpc: ec2.Vpc
- constructor(scope: Construct, id: string, props: NetworkStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: NetworkStackProps) {
+ super(scope, id, props)
- const config = new Config()
+ const config = new Config()
- this.vpc = new ec2.Vpc(this, config.getFullStackResourceName(this.name, 'vpc'), {
- natGateways: 0
- })
- }
+ this.vpc = new ec2.Vpc(this, config.getFullStackResourceName(this.name, "vpc"), {
+ natGateways: 0
+ })
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/src/providers/nodes.ts b/infrastructure/cdk/src/providers/nodes.ts
index 5a72e645a..87f7e6954 100644
--- a/infrastructure/cdk/src/providers/nodes.ts
+++ b/infrastructure/cdk/src/providers/nodes.ts
@@ -1,32 +1,32 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as route53 from 'aws-cdk-lib/aws-route53'
-import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'
-import { NodesStackProps } from '../interfaces/StackProps'
-import { kebabCase, pascalCase } from '@casimir/format'
-import { Config } from './config'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as route53 from "aws-cdk-lib/aws-route53"
+import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager"
+import { NodesStackProps } from "../interfaces/StackProps"
+import { kebabCase, pascalCase } from "@casimir/format"
+import { Config } from "./config"
/**
* Public node stack
*/
export class NodesStack extends cdk.Stack {
- public readonly name = pascalCase('nodes')
+ public readonly name = pascalCase("nodes")
- constructor(scope: Construct, id: string, props: NodesStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: NodesStackProps) {
+ super(scope, id, props)
- const config = new Config()
- const { rootDomain, subdomains } = config
- const { hostedZone } = props
+ const config = new Config()
+ const { rootDomain, subdomains } = config
+ const { hostedZone } = props
- const nodesIpKey = 'casimir-nodes-ip'
- const nodesIp = secretsmanager.Secret.fromSecretNameV2(this, pascalCase(nodesIpKey), kebabCase(nodesIpKey))
+ const nodesIpKey = "casimir-nodes-ip"
+ const nodesIp = secretsmanager.Secret.fromSecretNameV2(this, pascalCase(nodesIpKey), kebabCase(nodesIpKey))
- new route53.ARecord(this, config.getFullStackResourceName(this.name, 'a-record-api'), {
- recordName: `${subdomains.nodes}.${rootDomain}`,
- zone: hostedZone as route53.IHostedZone,
- target: route53.RecordTarget.fromIpAddresses(nodesIp.secretValue.unsafeUnwrap()),
- ttl: cdk.Duration.minutes(1)
- })
- }
+ new route53.ARecord(this, config.getFullStackResourceName(this.name, "a-record-api"), {
+ recordName: `${subdomains.nodes}.${rootDomain}`,
+ zone: hostedZone as route53.IHostedZone,
+ target: route53.RecordTarget.fromIpAddresses(nodesIp.secretValue.unsafeUnwrap()),
+ ttl: cdk.Duration.minutes(1)
+ })
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/src/providers/users.ts b/infrastructure/cdk/src/providers/users.ts
index c16e9a2d1..743fa66ad 100644
--- a/infrastructure/cdk/src/providers/users.ts
+++ b/infrastructure/cdk/src/providers/users.ts
@@ -1,125 +1,125 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as ecrAssets from 'aws-cdk-lib/aws-ecr-assets'
-import * as ec2 from 'aws-cdk-lib/aws-ec2'
-import * as ecs from 'aws-cdk-lib/aws-ecs'
-import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns'
-import * as rds from 'aws-cdk-lib/aws-rds'
-import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager'
-import { UsersStackProps } from '../interfaces/StackProps'
-import { Config } from './config'
-import { kebabCase } from '@casimir/format'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as ecrAssets from "aws-cdk-lib/aws-ecr-assets"
+import * as ec2 from "aws-cdk-lib/aws-ec2"
+import * as ecs from "aws-cdk-lib/aws-ecs"
+import * as ecsPatterns from "aws-cdk-lib/aws-ecs-patterns"
+import * as rds from "aws-cdk-lib/aws-rds"
+import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager"
+import { UsersStackProps } from "../interfaces/StackProps"
+import { Config } from "./config"
+import { kebabCase } from "@casimir/format"
/**
* Users service stack
*/
export class UsersStack extends cdk.Stack {
- public readonly name = 'users'
+ public readonly name = "users"
- constructor(scope: Construct, id: string, props: UsersStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: UsersStackProps) {
+ super(scope, id, props)
- const config = new Config()
- const { project, stage, rootDomain, subdomains } = config
- const { certificate, hostedZone, vpc } = props
+ const config = new Config()
+ const { project, stage, rootDomain, subdomains } = config
+ const { certificate, hostedZone, vpc } = props
- const dbCredentials = new secretsmanager.Secret(this, config.getFullStackResourceName(this.name, 'db-credentials'), {
- secretName: kebabCase(config.getFullStackResourceName(this.name, 'db-credentials')),
- generateSecretString: {
- secretStringTemplate: JSON.stringify({
- username: 'postgres'
- }),
- generateStringKey: 'password',
- passwordLength: 30,
- excludePunctuation: true
- }
- })
+ const dbCredentials = new secretsmanager.Secret(this, config.getFullStackResourceName(this.name, "db-credentials"), {
+ secretName: kebabCase(config.getFullStackResourceName(this.name, "db-credentials")),
+ generateSecretString: {
+ secretStringTemplate: JSON.stringify({
+ username: "postgres"
+ }),
+ generateStringKey: "password",
+ passwordLength: 30,
+ excludePunctuation: true
+ }
+ })
- const dbSecurityGroup = new ec2.SecurityGroup(this, config.getFullStackResourceName(this.name, 'db-security-group'), {
- vpc,
- allowAllOutbound: true
- })
+ const dbSecurityGroup = new ec2.SecurityGroup(this, config.getFullStackResourceName(this.name, "db-security-group"), {
+ vpc,
+ allowAllOutbound: true
+ })
- dbSecurityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(5432))
+ dbSecurityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(5432))
- const dbCluster = new rds.DatabaseCluster(this, config.getFullStackResourceName(this.name, 'db-cluster'), {
- engine: rds.DatabaseClusterEngine.auroraPostgres({
- version: rds.AuroraPostgresEngineVersion.VER_15_2
- }),
- credentials: rds.Credentials.fromSecret(dbCredentials),
- defaultDatabaseName: this.name,
- instances: 1,
- instanceProps: {
- instanceType: new ec2.InstanceType('serverless'),
- publiclyAccessible: true,
- securityGroups: [dbSecurityGroup],
- vpc,
- vpcSubnets: {
- subnetType: ec2.SubnetType.PUBLIC
- }
- },
- port: 5432
- })
+ const dbCluster = new rds.DatabaseCluster(this, config.getFullStackResourceName(this.name, "db-cluster"), {
+ engine: rds.DatabaseClusterEngine.auroraPostgres({
+ version: rds.AuroraPostgresEngineVersion.VER_15_2
+ }),
+ credentials: rds.Credentials.fromSecret(dbCredentials),
+ defaultDatabaseName: this.name,
+ instances: 1,
+ instanceProps: {
+ instanceType: new ec2.InstanceType("serverless"),
+ publiclyAccessible: true,
+ securityGroups: [dbSecurityGroup],
+ vpc,
+ vpcSubnets: {
+ subnetType: ec2.SubnetType.PUBLIC
+ }
+ },
+ port: 5432
+ })
- cdk.Aspects.of(dbCluster).add({
- visit(node) {
- if (node instanceof rds.CfnDBCluster) {
- node.serverlessV2ScalingConfiguration = {
- minCapacity: 0.5,
- maxCapacity: 1
- }
- }
- },
- })
+ cdk.Aspects.of(dbCluster).add({
+ visit(node) {
+ if (node instanceof rds.CfnDBCluster) {
+ node.serverlessV2ScalingConfiguration = {
+ minCapacity: 0.5,
+ maxCapacity: 1
+ }
+ }
+ },
+ })
- const ecsCluster = new ecs.Cluster(this, config.getFullStackResourceName(this.name, 'cluster'), {
- vpc
- })
+ const ecsCluster = new ecs.Cluster(this, config.getFullStackResourceName(this.name, "cluster"), {
+ vpc
+ })
- const imageAsset = new ecrAssets.DockerImageAsset(this, config.getFullStackResourceName(this.name, 'image'), {
- directory: '../../',
- file: 'services/users/Dockerfile',
- platform: ecrAssets.Platform.LINUX_AMD64,
- ignoreMode: cdk.IgnoreMode.GIT
- })
+ const imageAsset = new ecrAssets.DockerImageAsset(this, config.getFullStackResourceName(this.name, "image"), {
+ directory: "../../",
+ file: "services/users/Dockerfile",
+ platform: ecrAssets.Platform.LINUX_AMD64,
+ ignoreMode: cdk.IgnoreMode.GIT
+ })
- const requiredSecrets = {
- DB_HOST: ecs.Secret.fromSecretsManager(dbCredentials, 'host'),
- DB_PORT: ecs.Secret.fromSecretsManager(dbCredentials, 'port'),
- DB_NAME: ecs.Secret.fromSecretsManager(dbCredentials, 'dbname'),
- DB_USER: ecs.Secret.fromSecretsManager(dbCredentials, 'username'),
- DB_PASSWORD: ecs.Secret.fromSecretsManager(dbCredentials, 'password')
- }
+ const requiredSecrets = {
+ DB_HOST: ecs.Secret.fromSecretsManager(dbCredentials, "host"),
+ DB_PORT: ecs.Secret.fromSecretsManager(dbCredentials, "port"),
+ DB_NAME: ecs.Secret.fromSecretsManager(dbCredentials, "dbname"),
+ DB_USER: ecs.Secret.fromSecretsManager(dbCredentials, "username"),
+ DB_PASSWORD: ecs.Secret.fromSecretsManager(dbCredentials, "password")
+ }
- const optionalSecrets: { SESSIONS_HOST?: ecs.Secret, SESSIONS_KEY?: ecs.Secret } = {}
+ const optionalSecrets: { SESSIONS_HOST?: ecs.Secret, SESSIONS_KEY?: ecs.Secret } = {}
- if (config.stage === 'prod' || config.stage === 'dev') {
- const sessionsCredentials = secretsmanager.Secret.fromSecretNameV2(this, config.getFullStackResourceName(this.name, 'sessions-credentials'), kebabCase(config.getFullStackResourceName(this.name, 'sessions-credentials')))
- optionalSecrets.SESSIONS_HOST = ecs.Secret.fromSecretsManager(sessionsCredentials, 'host')
- optionalSecrets.SESSIONS_KEY = ecs.Secret.fromSecretsManager(sessionsCredentials, 'key')
- }
+ if (config.stage === "prod" || config.stage === "dev") {
+ const sessionsCredentials = secretsmanager.Secret.fromSecretNameV2(this, config.getFullStackResourceName(this.name, "sessions-credentials"), kebabCase(config.getFullStackResourceName(this.name, "sessions-credentials")))
+ optionalSecrets.SESSIONS_HOST = ecs.Secret.fromSecretsManager(sessionsCredentials, "host")
+ optionalSecrets.SESSIONS_KEY = ecs.Secret.fromSecretsManager(sessionsCredentials, "key")
+ }
- const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, config.getFullStackResourceName(this.name, 'fargate'), {
- assignPublicIp: true,
- certificate,
- cluster: ecsCluster,
- domainName: `${subdomains.users}.${rootDomain}`, // e.g. users.casimir.co or users.dev.casimir.co
- domainZone: hostedZone,
- taskImageOptions: {
- containerPort: 4000,
- image: ecs.ContainerImage.fromDockerImageAsset(imageAsset),
- environment: {
- PROJECT: project,
- STAGE: stage,
- USERS_URL: `https://${subdomains.users}.${rootDomain}`,
- WEB_URL: `https://${subdomains.web}.${rootDomain}`
- },
- secrets: { ...requiredSecrets, ...optionalSecrets }
- }
- })
+ const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, config.getFullStackResourceName(this.name, "fargate"), {
+ assignPublicIp: true,
+ certificate,
+ cluster: ecsCluster,
+ domainName: `${subdomains.users}.${rootDomain}`, // e.g. users.casimir.co or users.dev.casimir.co
+ domainZone: hostedZone,
+ taskImageOptions: {
+ containerPort: 4000,
+ image: ecs.ContainerImage.fromDockerImageAsset(imageAsset),
+ environment: {
+ PROJECT: project,
+ STAGE: stage,
+ USERS_URL: `https://${subdomains.users}.${rootDomain}`,
+ WEB_URL: `https://${subdomains.web}.${rootDomain}`
+ },
+ secrets: { ...requiredSecrets, ...optionalSecrets }
+ }
+ })
- fargateService.targetGroup.configureHealthCheck({
- path: '/health'
- })
- }
+ fargateService.targetGroup.configureHealthCheck({
+ path: "/health"
+ })
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/src/providers/web.ts b/infrastructure/cdk/src/providers/web.ts
index 53ba32192..0ca11bed7 100644
--- a/infrastructure/cdk/src/providers/web.ts
+++ b/infrastructure/cdk/src/providers/web.ts
@@ -1,83 +1,82 @@
-import { Construct } from 'constructs'
-import * as cdk from 'aws-cdk-lib'
-import * as certmgr from 'aws-cdk-lib/aws-certificatemanager'
-import * as route53targets from 'aws-cdk-lib/aws-route53-targets'
-import * as route53 from 'aws-cdk-lib/aws-route53'
-import * as s3 from 'aws-cdk-lib/aws-s3'
-import * as s3Deployment from 'aws-cdk-lib/aws-s3-deployment'
-import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'
-import * as cloudfrontOrigins from 'aws-cdk-lib/aws-cloudfront-origins'
-import { WebStackProps } from '../interfaces/StackProps'
-import { pascalCase } from '@casimir/format'
-import { Config } from './config'
+import { Construct } from "constructs"
+import * as cdk from "aws-cdk-lib"
+import * as certmgr from "aws-cdk-lib/aws-certificatemanager"
+import * as route53targets from "aws-cdk-lib/aws-route53-targets"
+import * as route53 from "aws-cdk-lib/aws-route53"
+import * as s3 from "aws-cdk-lib/aws-s3"
+import * as s3Deployment from "aws-cdk-lib/aws-s3-deployment"
+import * as cloudfront from "aws-cdk-lib/aws-cloudfront"
+import * as cloudfrontOrigins from "aws-cdk-lib/aws-cloudfront-origins"
+import { WebStackProps } from "../interfaces/StackProps"
+import { pascalCase } from "@casimir/format"
+import { Config } from "./config"
/**
* Web app stack
*/
export class WebStack extends cdk.Stack {
- public readonly name = pascalCase('web')
+ public readonly name = pascalCase("web")
- constructor(scope: Construct, id: string, props: WebStackProps) {
- super(scope, id, props)
+ constructor(scope: Construct, id: string, props: WebStackProps) {
+ super(scope, id, props)
- const config = new Config()
- const { rootDomain, subdomains } = config
- const { hostedZone, certificate } = props
+ const config = new Config()
+ const { rootDomain, subdomains } = config
+ const { hostedZone, certificate } = props
- const bucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, 'bucket'), {
- accessControl: s3.BucketAccessControl.PRIVATE
- })
+ const bucket = new s3.Bucket(this, config.getFullStackResourceName(this.name, "bucket"), {
+ accessControl: s3.BucketAccessControl.PRIVATE
+ })
- const originAccessIdentity = new cloudfront.OriginAccessIdentity(this, config.getFullStackResourceName(this.name, 'origin-access-identity'))
- bucket.grantRead(originAccessIdentity)
+ const originAccessIdentity = new cloudfront.OriginAccessIdentity(this, config.getFullStackResourceName(this.name, "origin-access-identity"))
+ bucket.grantRead(originAccessIdentity)
- const distributionCertificate = (() => {
- if (certificate?.env.region === 'us-east-1') return certificate
- /** Replace deprecated method when cross-region support is out of beta */
- return new certmgr.DnsValidatedCertificate(this, config.getFullStackResourceName(this.name, 'cert'), {
- domainName: rootDomain,
- subjectAlternativeNames: [`${subdomains.web}.${rootDomain}`],
- hostedZone,
- region: 'us-east-1'
- })
- })()
+ const distributionCertificate = (() => {
+ if (certificate?.env.region === "us-east-1") return certificate
+ /** Replace deprecated method when cross-region support is out of beta */
+ return new certmgr.DnsValidatedCertificate(this, config.getFullStackResourceName(this.name, "cert"), {
+ domainName: rootDomain,
+ subjectAlternativeNames: [`${subdomains.web}.${rootDomain}`],
+ hostedZone,
+ region: "us-east-1"
+ })
+ })()
- const distribution = new cloudfront.Distribution(this, config.getFullStackResourceName(this.name, 'distribution'), {
- certificate: distributionCertificate,
- defaultRootObject: 'index.html',
- errorResponses: [
- {
- httpStatus: 403,
- responseHttpStatus: 200,
- responsePagePath: '/index.html',
- ttl: cdk.Duration.minutes(30)
- },
- {
- httpStatus: 404,
- responseHttpStatus: 200,
- responsePagePath: '/index.html',
- ttl: cdk.Duration.minutes(30)
- }
- ],
- defaultBehavior: {
- viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
- origin: new cloudfrontOrigins.S3Origin(bucket, { originAccessIdentity })
- },
- domainNames: [`${subdomains.web}.${rootDomain}`]
- })
+ const distribution = new cloudfront.Distribution(this, config.getFullStackResourceName(this.name, "distribution"), {
+ certificate: distributionCertificate,
+ defaultRootObject: "index.html",
+ errorResponses: [
+ {
+ httpStatus: 403,
+ responseHttpStatus: 200,
+ responsePagePath: "/index.html",
+ ttl: cdk.Duration.minutes(30)
+ }, {
+ httpStatus: 404,
+ responseHttpStatus: 200,
+ responsePagePath: "/index.html",
+ ttl: cdk.Duration.minutes(30)
+ }
+ ],
+ defaultBehavior: {
+ viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
+ origin: new cloudfrontOrigins.S3Origin(bucket, { originAccessIdentity })
+ },
+ domainNames: [`${subdomains.web}.${rootDomain}`]
+ })
- new s3Deployment.BucketDeployment(this, config.getFullStackResourceName(this.name, 'bucket-deployment'), {
- destinationBucket: bucket,
- sources: [s3Deployment.Source.asset('../../apps/web/dist')],
- distribution,
- distributionPaths: ['/*']
- })
+ new s3Deployment.BucketDeployment(this, config.getFullStackResourceName(this.name, "bucket-deployment"), {
+ destinationBucket: bucket,
+ sources: [s3Deployment.Source.asset("../../apps/web/dist")],
+ distribution,
+ distributionPaths: ["/*"]
+ })
- new route53.ARecord(this, config.getFullStackResourceName(this.name, 'a-record-app'), {
- recordName: `${subdomains.web}.${rootDomain}`,
- zone: hostedZone as route53.IHostedZone,
- target: route53.RecordTarget.fromAlias(new route53targets.CloudFrontTarget(distribution)),
- ttl: cdk.Duration.minutes(1),
- })
- }
+ new route53.ARecord(this, config.getFullStackResourceName(this.name, "a-record-app"), {
+ recordName: `${subdomains.web}.${rootDomain}`,
+ zone: hostedZone as route53.IHostedZone,
+ target: route53.RecordTarget.fromAlias(new route53targets.CloudFrontTarget(distribution)),
+ ttl: cdk.Duration.minutes(1),
+ })
+ }
}
\ No newline at end of file
diff --git a/infrastructure/cdk/test/all.test.ts b/infrastructure/cdk/test/all.test.ts
index 87d9ba31d..28c7d4a49 100644
--- a/infrastructure/cdk/test/all.test.ts
+++ b/infrastructure/cdk/test/all.test.ts
@@ -1,64 +1,64 @@
-import * as cdk from 'aws-cdk-lib'
-import * as assertions from 'aws-cdk-lib/assertions'
-import { Config } from '../src/providers/config'
-import { AnalyticsStack } from '../src/providers/analytics'
-import { DnsStack } from '../src/providers/dns'
-import { DocsStack } from '../src/providers/docs'
-import { BlogStack } from '../src/providers/blog'
-import { LandingStack } from '../src/providers/landing'
-import { NetworkStack } from '../src/providers/network'
-import { NodesStack } from '../src/providers/nodes'
-import { UsersStack } from '../src/providers/users'
-import { WebStack } from '../src/providers/web'
+import * as cdk from "aws-cdk-lib"
+import * as assertions from "aws-cdk-lib/assertions"
+import { Config } from "../src/providers/config"
+import { AnalyticsStack } from "../src/providers/analytics"
+import { DnsStack } from "../src/providers/dns"
+import { DocsStack } from "../src/providers/docs"
+import { BlogStack } from "../src/providers/blog"
+import { LandingStack } from "../src/providers/landing"
+import { NetworkStack } from "../src/providers/network"
+import { NodesStack } from "../src/providers/nodes"
+import { UsersStack } from "../src/providers/users"
+import { WebStack } from "../src/providers/web"
-test('All stacks created', () => {
- const config = new Config()
- const { env } = config
- const app = new cdk.App()
+test("All stacks created", () => {
+ const config = new Config()
+ const { env } = config
+ const app = new cdk.App()
- const { hostedZone, certificate } = new DnsStack(app, config.getFullStackName('dns'), { env })
- const { vpc } = new NetworkStack(app, config.getFullStackName('network'), { env })
+ const { hostedZone, certificate } = new DnsStack(app, config.getFullStackName("dns"), { env })
+ const { vpc } = new NetworkStack(app, config.getFullStackName("network"), { env })
- const analyticsStack = new AnalyticsStack(app, config.getFullStackName('analytics'), { env })
- const blogStack = new BlogStack(app, config.getFullStackName('blog'), { env, certificate, hostedZone, vpc })
- const docsStack = new DocsStack(app, config.getFullStackName('docs'), { env, certificate, hostedZone })
- const landingStack = new LandingStack(app, config.getFullStackName('landing'), { env, certificate, hostedZone })
- const nodesStack = new NodesStack(app, config.getFullStackName('nodes'), { env, hostedZone })
- const usersStack = new UsersStack(app, config.getFullStackName('users'), { env, certificate, hostedZone, vpc })
- const webStack = new WebStack(app, config.getFullStackName('web'), { env, certificate, hostedZone })
+ const analyticsStack = new AnalyticsStack(app, config.getFullStackName("analytics"), { env })
+ const blogStack = new BlogStack(app, config.getFullStackName("blog"), { env, certificate, hostedZone, vpc })
+ const docsStack = new DocsStack(app, config.getFullStackName("docs"), { env, certificate, hostedZone })
+ const landingStack = new LandingStack(app, config.getFullStackName("landing"), { env, certificate, hostedZone })
+ const nodesStack = new NodesStack(app, config.getFullStackName("nodes"), { env, hostedZone })
+ const usersStack = new UsersStack(app, config.getFullStackName("users"), { env, certificate, hostedZone, vpc })
+ const webStack = new WebStack(app, config.getFullStackName("web"), { env, certificate, hostedZone })
- const analyticsTemplate = assertions.Template.fromStack(analyticsStack)
- Object.keys(analyticsTemplate.findOutputs('*')).forEach(output => {
- expect(output).toBeDefined()
- })
+ const analyticsTemplate = assertions.Template.fromStack(analyticsStack)
+ Object.keys(analyticsTemplate.findOutputs("*")).forEach(output => {
+ expect(output).toBeDefined()
+ })
- const blogTemplate = assertions.Template.fromStack(blogStack)
- Object.keys(blogTemplate.findOutputs('*')).forEach(output => {
- expect(output).toBeDefined()
- })
+ const blogTemplate = assertions.Template.fromStack(blogStack)
+ Object.keys(blogTemplate.findOutputs("*")).forEach(output => {
+ expect(output).toBeDefined()
+ })
- const docsTemplate = assertions.Template.fromStack(docsStack)
- Object.keys(docsTemplate.findOutputs('*')).forEach(output => {
- expect(output).toBeDefined()
- })
+ const docsTemplate = assertions.Template.fromStack(docsStack)
+ Object.keys(docsTemplate.findOutputs("*")).forEach(output => {
+ expect(output).toBeDefined()
+ })
- const landingTemplate = assertions.Template.fromStack(landingStack)
- Object.keys(landingTemplate.findOutputs('*')).forEach(output => {
- expect(output).toBeDefined()
- })
+ const landingTemplate = assertions.Template.fromStack(landingStack)
+ Object.keys(landingTemplate.findOutputs("*")).forEach(output => {
+ expect(output).toBeDefined()
+ })
- const nodesTemplate = assertions.Template.fromStack(nodesStack)
- Object.keys(nodesTemplate.findOutputs('*')).forEach(output => {
- expect(output).toBeDefined()
- })
+ const nodesTemplate = assertions.Template.fromStack(nodesStack)
+ Object.keys(nodesTemplate.findOutputs("*")).forEach(output => {
+ expect(output).toBeDefined()
+ })
- const usersTemplate = assertions.Template.fromStack(usersStack)
- Object.keys(usersTemplate.findOutputs('*')).forEach(output => {
- expect(output).toBeDefined()
- })
+ const usersTemplate = assertions.Template.fromStack(usersStack)
+ Object.keys(usersTemplate.findOutputs("*")).forEach(output => {
+ expect(output).toBeDefined()
+ })
- const webTemplate = assertions.Template.fromStack(webStack)
- Object.keys(webTemplate.findOutputs('*')).forEach(output => {
- expect(output).toBeDefined()
- })
+ const webTemplate = assertions.Template.fromStack(webStack)
+ Object.keys(webTemplate.findOutputs("*")).forEach(output => {
+ expect(output).toBeDefined()
+ })
})
diff --git a/infrastructure/cdk/test/analytics.test.ts b/infrastructure/cdk/test/analytics.test.ts
index 12d33c51f..c558d4b16 100644
--- a/infrastructure/cdk/test/analytics.test.ts
+++ b/infrastructure/cdk/test/analytics.test.ts
@@ -1,46 +1,46 @@
-import * as cdk from 'aws-cdk-lib'
-import * as assertions from 'aws-cdk-lib/assertions'
-import { Config } from '../src/providers/config'
-import { AnalyticsStack } from '../src/providers/analytics'
-import { Schema, eventSchema, actionSchema } from '@casimir/data'
-
-test('Analytics stack created', () => {
- const config = new Config()
- const { env } = config
- const app = new cdk.App()
-
- const analyticsStack = new AnalyticsStack(app, config.getFullStackName('analytics'), { env })
- const analyticsTemplate = assertions.Template.fromStack(analyticsStack)
- Object.keys(analyticsTemplate.findOutputs('*')).forEach(output => {
- expect(output).toBeDefined()
- })
-
- const resource = analyticsTemplate.findResources('AWS::Glue::Table')
-
- const eventTable = Object.keys(resource).filter(key => key.includes('EventTable'))
- const eventColumns = resource[eventTable[0]].Properties.TableInput.StorageDescriptor.Columns
- const eventGlueSchema = new Schema(eventSchema).getGlueColumns()
-
- for (const column of eventColumns) {
- const { Name: name, Type: type } = column
- const columnName = Object.keys(eventSchema.properties).filter(key => key === name)[0]
- const columnType = eventGlueSchema.filter(key => key.name === name)[0].type.inputString
-
- expect(columnType).toEqual(type)
- expect(columnName).toEqual(name)
- }
-
- const actionTable = Object.keys(resource).filter(key => key.includes('ActionTable'))[0]
- const actionColumns = resource[actionTable].Properties.TableInput.StorageDescriptor.Columns
- const actionGlueSchema = new Schema(actionSchema).getGlueColumns()
-
-
- for (const column of actionColumns) {
- const { Name: name, Type: type } = column
- const columnName = Object.keys(actionSchema.properties).filter(key => key === name)[0]
- const columnType = actionGlueSchema.filter(key => key.name === name)[0].type.inputString
-
- expect(columnType).toEqual(type)
- expect(columnName).toEqual(name)
- }
+import * as cdk from "aws-cdk-lib"
+import * as assertions from "aws-cdk-lib/assertions"
+import { Config } from "../src/providers/config"
+import { AnalyticsStack } from "../src/providers/analytics"
+import { Schema, eventSchema, actionSchema } from "@casimir/data"
+
+test("Analytics stack created", () => {
+ const config = new Config()
+ const { env } = config
+ const app = new cdk.App()
+
+ const analyticsStack = new AnalyticsStack(app, config.getFullStackName("analytics"), { env })
+ const analyticsTemplate = assertions.Template.fromStack(analyticsStack)
+ Object.keys(analyticsTemplate.findOutputs("*")).forEach(output => {
+ expect(output).toBeDefined()
+ })
+
+ const resource = analyticsTemplate.findResources("AWS::Glue::Table")
+
+ const eventTable = Object.keys(resource).filter(key => key.includes("EventTable"))
+ const eventColumns = resource[eventTable[0]].Properties.TableInput.StorageDescriptor.Columns
+ const eventGlueSchema = new Schema(eventSchema).getGlueColumns()
+
+ for (const column of eventColumns) {
+ const { Name: name, Type: type } = column
+ const columnName = Object.keys(eventSchema.properties).filter(key => key === name)[0]
+ const columnType = eventGlueSchema.filter(key => key.name === name)[0].type.inputString
+
+ expect(columnType).toEqual(type)
+ expect(columnName).toEqual(name)
+ }
+
+ const actionTable = Object.keys(resource).filter(key => key.includes("ActionTable"))[0]
+ const actionColumns = resource[actionTable].Properties.TableInput.StorageDescriptor.Columns
+ const actionGlueSchema = new Schema(actionSchema).getGlueColumns()
+
+
+ for (const column of actionColumns) {
+ const { Name: name, Type: type } = column
+ const columnName = Object.keys(actionSchema.properties).filter(key => key === name)[0]
+ const columnType = actionGlueSchema.filter(key => key.name === name)[0].type.inputString
+
+ expect(columnType).toEqual(type)
+ expect(columnName).toEqual(name)
+ }
})
\ No newline at end of file
diff --git a/scripts/actions/test.ts b/scripts/actions/test.ts
index 3bce8d6c1..3f189d2a0 100755
--- a/scripts/actions/test.ts
+++ b/scripts/actions/test.ts
@@ -1,17 +1,17 @@
-import { loadCredentials } from '@casimir/aws'
-import { run } from '@casimir/shell'
+import { loadCredentials } from "@casimir/aws"
+import { run } from "@casimir/shell"
/**
* Test a workflow from `.github/workflows`
*/
void async function () {
- const workflow = process.env.WORKFLOW || 'push'
+ const workflow = process.env.WORKFLOW || "push"
- const { accessKeyId, secretAccessKey } = await loadCredentials()
+ const { accessKeyId, secretAccessKey } = await loadCredentials()
- const slackWebhookURL = process.env.SLACK_WEBHOOK_URL
+ const slackWebhookURL = process.env.SLACK_WEBHOOK_URL
- console.log(`🚀 Running ${workflow} workflow`)
- await run(`act ${workflow} --rebuild --secret AWS_ACCESS_KEY_ID=${accessKeyId} --secret AWS_SECRET_ACCESS_KEY=${secretAccessKey} --secret SLACK_WEBHOOK_URL=${slackWebhookURL}`)
+ console.log(`🚀 Running ${workflow} workflow`)
+ await run(`act ${workflow} --rebuild --secret AWS_ACCESS_KEY_ID=${accessKeyId} --secret AWS_SECRET_ACCESS_KEY=${secretAccessKey} --secret SLACK_WEBHOOK_URL=${slackWebhookURL}`)
}()
\ No newline at end of file
diff --git a/scripts/cdk/deploy.ts b/scripts/cdk/deploy.ts
index ce0b77f73..e061e8425 100755
--- a/scripts/cdk/deploy.ts
+++ b/scripts/cdk/deploy.ts
@@ -1,58 +1,58 @@
-import { getSecret, loadCredentials } from '@casimir/aws'
-import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run } from '@casimir/shell'
+import { getSecret, loadCredentials } from "@casimir/aws"
+import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run } from "@casimir/shell"
/**
* Deploy CDK stacks
*/
void async function () {
- process.env.PROJECT = process.env.PROJECT || 'casimir'
- process.env.STAGE = process.env.STAGE || 'dev'
- process.env.AWS_REGION = process.env.AWS_REGION || 'us-east-2'
+ process.env.PROJECT = process.env.PROJECT || "casimir"
+ process.env.STAGE = process.env.STAGE || "dev"
+ process.env.AWS_REGION = process.env.AWS_REGION || "us-east-2"
- await loadCredentials()
- process.env.AWS_ACCOUNT = await getSecret('casimir-aws-account')
-
- // Hardcode app url to dev in prod to link goerli testnet
- process.env.APP_URL = process.env.STAGE === 'prod' ? /*'https://app.casimir.co'*/'https://app.dev.casimir.co' : `https://app.${process.env.STAGE}.casimir.co`
- process.env.BLOG_URL = process.env.STAGE === 'prod' ? 'https://blog.casimir.co' : `https://blog.${process.env.STAGE}.casimir.co`
- process.env.DOCS_URL = process.env.STAGE === 'prod' ? 'https://docs.casimir.co' : `https://docs.${process.env.STAGE}.casimir.co`
- process.env.USERS_URL = process.env.STAGE === 'prod' ? 'https://users.casimir.co' : `https://users.${process.env.STAGE}.casimir.co`
- process.env.WEBSITE_URL = process.env.STAGE === 'prod' ? 'https://casimir.co' : `https://${process.env.STAGE}.casimir.co`
- process.env.CRYPTO_COMPARE_API_KEY = await getSecret('casimir-crypto-compare-api-key')
-
- const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || 'TESTNET'
- process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[networkKey]
- process.env.FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FACTORY_ADDRESS
- process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS
- process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS
+ await loadCredentials()
+ process.env.AWS_ACCOUNT = await getSecret("casimir-aws-account")
+
+ // Hardcode app url to dev in prod to link goerli testnet
+ process.env.APP_URL = process.env.STAGE === "prod" ? /*'https://app.casimir.co'*/"https://app.dev.casimir.co" : `https://app.${process.env.STAGE}.casimir.co`
+ process.env.BLOG_URL = process.env.STAGE === "prod" ? "https://blog.casimir.co" : `https://blog.${process.env.STAGE}.casimir.co`
+ process.env.DOCS_URL = process.env.STAGE === "prod" ? "https://docs.casimir.co" : `https://docs.${process.env.STAGE}.casimir.co`
+ process.env.USERS_URL = process.env.STAGE === "prod" ? "https://users.casimir.co" : `https://users.${process.env.STAGE}.casimir.co`
+ process.env.WEBSITE_URL = process.env.STAGE === "prod" ? "https://casimir.co" : `https://${process.env.STAGE}.casimir.co`
+ process.env.CRYPTO_COMPARE_API_KEY = await getSecret("casimir-crypto-compare-api-key")
+
+ const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || "TESTNET"
+ process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[networkKey]
+ process.env.FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FACTORY_ADDRESS
+ process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS
+ process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS
- process.env.PUBLIC_APP_URL = process.env.APP_URL
- process.env.PUBLIC_BLOG_URL = process.env.BLOG_URL
- process.env.PUBLIC_DOCS_URL = process.env.DOCS_URL
- process.env.PUBLIC_USERS_URL = process.env.USERS_URL
- process.env.PUBLIC_WEBSITE_URL = process.env.WEBSITE_URL
- process.env.PUBLIC_CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY
- process.env.PUBLIC_ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL
- process.env.PUBLIC_FACTORY_ADDRESS = process.env.FACTORY_ADDRESS
- process.env.PUBLIC_SSV_NETWORK_ADDRESS = process.env.SSV_NETWORK_ADDRESS
- process.env.PUBLIC_SSV_VIEWS_ADDRESS = process.env.SSV_VIEWS_ADDRESS
- process.env.PUBLIC_CRYPTO_COMPARE_API_KEY = await getSecret('casimir-crypto-compare-api-key')
- process.env.PUBLIC_WALLET_CONNECT_PROJECT_ID = await getSecret('casimir-wallet-connect-project-id')
+ process.env.PUBLIC_APP_URL = process.env.APP_URL
+ process.env.PUBLIC_BLOG_URL = process.env.BLOG_URL
+ process.env.PUBLIC_DOCS_URL = process.env.DOCS_URL
+ process.env.PUBLIC_USERS_URL = process.env.USERS_URL
+ process.env.PUBLIC_WEBSITE_URL = process.env.WEBSITE_URL
+ process.env.PUBLIC_CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY
+ process.env.PUBLIC_ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL
+ process.env.PUBLIC_FACTORY_ADDRESS = process.env.FACTORY_ADDRESS
+ process.env.PUBLIC_SSV_NETWORK_ADDRESS = process.env.SSV_NETWORK_ADDRESS
+ process.env.PUBLIC_SSV_VIEWS_ADDRESS = process.env.SSV_VIEWS_ADDRESS
+ process.env.PUBLIC_CRYPTO_COMPARE_API_KEY = await getSecret("casimir-crypto-compare-api-key")
+ process.env.PUBLIC_WALLET_CONNECT_PROJECT_ID = await getSecret("casimir-wallet-connect-project-id")
- await run('npm run build --workspace @casimir/ethereum')
- await run('npm run docgen --workspace @casimir/docs')
- await run('npm run build --workspace @casimir/docs')
- await run('npm run build --workspace @casimir/redirect')
- await run('npm run build --workspace @casimir/landing')
- await run('npm run build --workspace @casimir/users')
- await run('npm run build --workspace @casimir/web')
-
- await run('npm run bootstrap --workspace @casimir/cdk')
- await run('npm run synth --workspace @casimir/cdk')
-
- console.log('🚀 Deploying CDK app')
- await run('npm run deploy --workspace @casimir/cdk')
+ await run("npm run build --workspace @casimir/ethereum")
+ await run("npm run docgen --workspace @casimir/docs")
+ await run("npm run build --workspace @casimir/docs")
+ await run("npm run build --workspace @casimir/redirect")
+ await run("npm run build --workspace @casimir/landing")
+ await run("npm run build --workspace @casimir/users")
+ await run("npm run build --workspace @casimir/web")
+
+ await run("npm run bootstrap --workspace @casimir/cdk")
+ await run("npm run synth --workspace @casimir/cdk")
+
+ console.log("🚀 Deploying CDK app")
+ await run("npm run deploy --workspace @casimir/cdk")
}()
diff --git a/scripts/cdk/test.ts b/scripts/cdk/test.ts
index ee467a98c..eef541d3a 100644
--- a/scripts/cdk/test.ts
+++ b/scripts/cdk/test.ts
@@ -1,25 +1,25 @@
-import { getSecret, loadCredentials } from '@casimir/aws'
-import { run } from '@casimir/shell'
+import { getSecret, loadCredentials } from "@casimir/aws"
+import { run } from "@casimir/shell"
/**
* Test CDK stacks
*/
void async function () {
- process.env.PROJECT = process.env.PROJECT || 'casimir'
- process.env.STAGE = process.env.STAGE || 'dev'
- process.env.AWS_REGION = process.env.AWS_REGION || 'us-east-2'
+ process.env.PROJECT = process.env.PROJECT || "casimir"
+ process.env.STAGE = process.env.STAGE || "dev"
+ process.env.AWS_REGION = process.env.AWS_REGION || "us-east-2"
- await loadCredentials()
- process.env.AWS_ACCOUNT = await getSecret('casimir-aws-account')
+ await loadCredentials()
+ process.env.AWS_ACCOUNT = await getSecret("casimir-aws-account")
- await run('npm run build --workspace @casimir/ethereum')
- await run('npm run docgen --workspace @casimir/docs')
- await run('npm run build --workspace @casimir/docs')
- await run('npm run build --workspace @casimir/redirect')
- await run('npm run build --workspace @casimir/landing')
- await run('npm run build --workspace @casimir/users')
- await run('npm run build --workspace @casimir/web')
+ await run("npm run build --workspace @casimir/ethereum")
+ await run("npm run docgen --workspace @casimir/docs")
+ await run("npm run build --workspace @casimir/docs")
+ await run("npm run build --workspace @casimir/redirect")
+ await run("npm run build --workspace @casimir/landing")
+ await run("npm run build --workspace @casimir/users")
+ await run("npm run build --workspace @casimir/web")
- console.log('🚀 Testing CDK app')
- await run('npm run test --workspace @casimir/cdk')
+ console.log("🚀 Testing CDK app")
+ await run("npm run test --workspace @casimir/cdk")
}()
\ No newline at end of file
diff --git a/scripts/ethereum/debug.ts b/scripts/ethereum/debug.ts
index ee50be3d8..b11282e95 100644
--- a/scripts/ethereum/debug.ts
+++ b/scripts/ethereum/debug.ts
@@ -1,33 +1,33 @@
-import { loadCredentials, getSecret } from '@casimir/aws'
-import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run } from '@casimir/shell'
+import { loadCredentials, getSecret } from "@casimir/aws"
+import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run } from "@casimir/shell"
/**
* Test ethereum contracts and services
*/
void async function () {
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- }
- console.log(`Your mnemonic is ${process.env.BIP39_SEED}`)
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") as string
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ }
+ console.log(`Your mnemonic is ${process.env.BIP39_SEED}`)
- process.env.FORK = process.env.FORK || 'testnet'
+ process.env.FORK = process.env.FORK || "testnet"
- process.env.ETHEREUM_FORK_RPC_URL = process.env.ETHEREUM_FORK_RPC_URL || ETHEREUM_RPC_URL[process.env.FORK.toUpperCase()]
- if (!process.env.ETHEREUM_FORK_RPC_URL) {
- throw new Error(`Ethereum ${process.env.FORK} is not supported`)
- }
+ process.env.ETHEREUM_FORK_RPC_URL = process.env.ETHEREUM_FORK_RPC_URL || ETHEREUM_RPC_URL[process.env.FORK.toUpperCase()]
+ if (!process.env.ETHEREUM_FORK_RPC_URL) {
+ throw new Error(`Ethereum ${process.env.FORK} is not supported`)
+ }
- const networkName = ETHEREUM_NETWORK_NAME[process.env.FORK.toUpperCase()]
+ const networkName = ETHEREUM_NETWORK_NAME[process.env.FORK.toUpperCase()]
- console.log(`Using ${networkName} fork from ${process.env.ETHEREUM_FORK_RPC_URL}`)
+ console.log(`Using ${networkName} fork from ${process.env.ETHEREUM_FORK_RPC_URL}`)
- process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[process.env.FORK.toUpperCase()]?.SSV_NETWORK_ADDRESS
- process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[process.env.FORK.toUpperCase()]?.SSV_VIEWS_ADDRESS
- process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS[process.env.FORK.toUpperCase()]?.SWAP_FACTORY_ADDRESS
+ process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[process.env.FORK.toUpperCase()]?.SSV_NETWORK_ADDRESS
+ process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[process.env.FORK.toUpperCase()]?.SSV_VIEWS_ADDRESS
+ process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS[process.env.FORK.toUpperCase()]?.SWAP_FACTORY_ADDRESS
- run('npm run test:debug --workspace @casimir/ethereum')
+ run("npm run test:debug --workspace @casimir/ethereum")
}()
diff --git a/scripts/ethereum/deploy.ts b/scripts/ethereum/deploy.ts
index 4c2397d67..03f7e513e 100644
--- a/scripts/ethereum/deploy.ts
+++ b/scripts/ethereum/deploy.ts
@@ -1,24 +1,24 @@
-import { loadCredentials, getSecret } from '@casimir/aws'
-import { ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run } from '@casimir/shell'
+import { loadCredentials, getSecret } from "@casimir/aws"
+import { ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run } from "@casimir/shell"
/**
* Deploy ethereum contracts
*/
void async function () {
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- }
- console.log(`Your mnemonic seed is ${process.env.BIP39_SEED}`)
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") as string
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ }
+ console.log(`Your mnemonic seed is ${process.env.BIP39_SEED}`)
- process.env.NETWORK = process.env.NETWORK || 'testnet'
- process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[process.env.NETWORK.toUpperCase()]
- const networkName = ETHEREUM_NETWORK_NAME[process.env.NETWORK.toUpperCase()]
+ process.env.NETWORK = process.env.NETWORK || "testnet"
+ process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[process.env.NETWORK.toUpperCase()]
+ const networkName = ETHEREUM_NETWORK_NAME[process.env.NETWORK.toUpperCase()]
- console.log(`Using ${networkName} network from ${process.env.ETHEREUM_RPC_URL}`)
+ console.log(`Using ${networkName} network from ${process.env.ETHEREUM_RPC_URL}`)
- run(`npm run deploy --workspace @casimir/ethereum -- --network ${networkName}`)
+ run(`npm run deploy --workspace @casimir/ethereum -- --network ${networkName}`)
}()
diff --git a/scripts/ethereum/report.ts b/scripts/ethereum/report.ts
index 81cc9f416..24d4c0cab 100644
--- a/scripts/ethereum/report.ts
+++ b/scripts/ethereum/report.ts
@@ -1,22 +1,22 @@
-import { loadCredentials, getSecret } from '@casimir/aws'
-import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME } from '@casimir/env'
-import { run } from '@casimir/shell'
+import { loadCredentials, getSecret } from "@casimir/aws"
+import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME } from "@casimir/env"
+import { run } from "@casimir/shell"
/**
* Run an ethereum development environment
*/
void async function () {
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- }
- console.log(`Your mnemonic seed is ${process.env.BIP39_SEED}`)
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") as string
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ }
+ console.log(`Your mnemonic seed is ${process.env.BIP39_SEED}`)
- process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].SSV_NETWORK_ADDRESS
- process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].SSV_VIEWS_ADDRESS
- process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS['TESTNET'].SWAP_FACTORY_ADDRESS
+ process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS["TESTNET"].SSV_NETWORK_ADDRESS
+ process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS["TESTNET"].SSV_VIEWS_ADDRESS
+ process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS["TESTNET"].SWAP_FACTORY_ADDRESS
- run(`npm run report --workspace @casimir/ethereum -- --network ${ETHEREUM_NETWORK_NAME['TESTNET']}`)
+ run(`npm run report --workspace @casimir/ethereum -- --network ${ETHEREUM_NETWORK_NAME["TESTNET"]}`)
}()
diff --git a/scripts/ethereum/upgrade.ts b/scripts/ethereum/upgrade.ts
index f3ec37f3d..4971e3474 100644
--- a/scripts/ethereum/upgrade.ts
+++ b/scripts/ethereum/upgrade.ts
@@ -1,27 +1,27 @@
-import { loadCredentials, getSecret } from '@casimir/aws'
-import { ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run } from '@casimir/shell'
+import { loadCredentials, getSecret } from "@casimir/aws"
+import { ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run } from "@casimir/shell"
/**
* Upgrade ethereum contracts
*/
void async function () {
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- }
- console.log(`Your mnemonic seed is ${process.env.BIP39_SEED}`)
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") as string
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ }
+ console.log(`Your mnemonic seed is ${process.env.BIP39_SEED}`)
- process.env.NETWORK = process.env.NETWORK || 'testnet'
- process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[process.env.NETWORK.toUpperCase()]
- const networkName = ETHEREUM_NETWORK_NAME[process.env.NETWORK.toUpperCase()]
+ process.env.NETWORK = process.env.NETWORK || "testnet"
+ process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[process.env.NETWORK.toUpperCase()]
+ const networkName = ETHEREUM_NETWORK_NAME[process.env.NETWORK.toUpperCase()]
- console.log(`Using ${networkName} network from ${process.env.ETHEREUM_RPC_URL}`)
+ console.log(`Using ${networkName} network from ${process.env.ETHEREUM_RPC_URL}`)
- run(`npm run upgrade:proxies --workspace @casimir/ethereum -- --network ${networkName}`)
+ run(`npm run upgrade:proxies --workspace @casimir/ethereum -- --network ${networkName}`)
- // Instead to upgrade all contracts including mocks and libraries
- // run(`npm run upgrade:all --workspace @casimir/ethereum -- --network ${networkName}`)
+ // Instead to upgrade all contracts including mocks and libraries
+ // run(`npm run upgrade:all --workspace @casimir/ethereum -- --network ${networkName}`)
}()
\ No newline at end of file
diff --git a/scripts/migrations/users.ts b/scripts/migrations/users.ts
index 2c71b8087..d4d29ba4c 100644
--- a/scripts/migrations/users.ts
+++ b/scripts/migrations/users.ts
@@ -1,52 +1,52 @@
-import fs from 'fs'
-import os from 'os'
-import { JsonSchema, Schema, accountSchema, nonceSchema, operatorSchema, userAccountSchema, userSchema } from '@casimir/data'
-import { run } from '@casimir/shell'
-import { getSecret } from '@casimir/aws'
+import fs from "fs"
+import os from "os"
+import { JsonSchema, Schema, accountSchema, nonceSchema, operatorSchema, userAccountSchema, userSchema } from "@casimir/data"
+import { run } from "@casimir/shell"
+import { getSecret } from "@casimir/aws"
/**
* Generate SQL schema from JSON schemas
*/
void async function () {
- const project = process.env.PROJECT || 'casimir'
- const stage = process.env.STAGE || 'dev'
- const dbName = 'users'
+ const project = process.env.PROJECT || "casimir"
+ const stage = process.env.STAGE || "dev"
+ const dbName = "users"
- const dbCredentials = await getSecret(`${project}-${dbName}-db-credentials-${stage}`)
+ const dbCredentials = await getSecret(`${project}-${dbName}-db-credentials-${stage}`)
- const { port, host, username, password } = JSON.parse(dbCredentials as string)
- const pgUrl = `postgres://${username}:${password}@${host}:${port}/${dbName}`
+ const { port, host, username, password } = JSON.parse(dbCredentials as string)
+ const pgUrl = `postgres://${username}:${password}@${host}:${port}/${dbName}`
- const resourceDir = './scripts'
+ const resourceDir = "./scripts"
- const tableSchemas = {
- account: accountSchema,
- operator: operatorSchema,
- nonce: nonceSchema,
- user: userSchema,
- userAccount: userAccountSchema
- }
+ const tableSchemas = {
+ account: accountSchema,
+ operator: operatorSchema,
+ nonce: nonceSchema,
+ user: userSchema,
+ userAccount: userAccountSchema
+ }
- let sqlSchema = ''
- for (const table of Object.keys(tableSchemas)) {
- const tableSchema = tableSchemas[table] as JsonSchema
- const schema = new Schema(tableSchema)
- const postgresTable = schema.getPostgresTable()
- console.log(`${schema.getTitle()} JSON schema parsed to SQL`)
- sqlSchema += `${postgresTable}\n\n`
- }
+ let sqlSchema = ""
+ for (const table of Object.keys(tableSchemas)) {
+ const tableSchema = tableSchemas[table] as JsonSchema
+ const schema = new Schema(tableSchema)
+ const postgresTable = schema.getPostgresTable()
+ console.log(`${schema.getTitle()} JSON schema parsed to SQL`)
+ sqlSchema += `${postgresTable}\n\n`
+ }
- const sqlDir = `${resourceDir}/.out/sql`
- if (!fs.existsSync(sqlDir)) fs.mkdirSync(sqlDir, { recursive: true })
- fs.writeFileSync(`${sqlDir}/schema.sql`, sqlSchema)
+ const sqlDir = `${resourceDir}/.out/sql`
+ if (!fs.existsSync(sqlDir)) fs.mkdirSync(sqlDir, { recursive: true })
+ fs.writeFileSync(`${sqlDir}/schema.sql`, sqlSchema)
- const atlas = await run('which atlas') as string
- if (!atlas || atlas.includes('not found')) {
- if (os.platform() === 'darwin') {
- await run('echo y | brew install atlas')
- } else {
- throw new Error('Please install atlas using `curl -sSf https://atlasgo.sh | sh`')
- }
+ const atlas = await run("which atlas") as string
+ if (!atlas || atlas.includes("not found")) {
+ if (os.platform() === "darwin") {
+ await run("echo y | brew install atlas")
+ } else {
+ throw new Error("Please install atlas using `curl -sSf https://atlasgo.sh | sh`")
}
- await run(`atlas schema apply --url "${pgUrl}?sslmode=disable" --to "file://${sqlDir}/schema.sql" --dev-url "docker://postgres/15" --auto-approve`)
+ }
+ await run(`atlas schema apply --url "${pgUrl}?sslmode=disable" --to "file://${sqlDir}/schema.sql" --dev-url "docker://postgres/15" --auto-approve`)
}()
\ No newline at end of file
diff --git a/scripts/root/check.ts b/scripts/root/check.ts
index e2370b0bf..8a35e4fb1 100644
--- a/scripts/root/check.ts
+++ b/scripts/root/check.ts
@@ -1,64 +1,64 @@
-import { run } from '@casimir/shell'
-import fs from 'fs'
+import { run } from "@casimir/shell"
+import fs from "fs"
/**
* Check environment prerequisites
*/
void async function () {
- if (process.env.CI !== 'true') {
- const docker = await run('docker --version') as string
- try {
- const dockerSplit = docker.split(' ')
- const dockerNumber = dockerSplit[2]
- const dockerNumberSplit = dockerNumber.split('.')
- const dockerMajor = parseInt(dockerNumberSplit[0])
- if (dockerMajor < 24) {
- throw new Error('🚩 Incompatible docker version')
- }
- } catch (error) {
- console.error(error.message)
- throw new Error('🚩 Please install docker 24.x (see https://github.com/consensusnetworks/casimir#prerequisites #1)')
- }
+ if (process.env.CI !== "true") {
+ const docker = await run("docker --version") as string
+ try {
+ const dockerSplit = docker.split(" ")
+ const dockerNumber = dockerSplit[2]
+ const dockerNumberSplit = dockerNumber.split(".")
+ const dockerMajor = parseInt(dockerNumberSplit[0])
+ if (dockerMajor < 24) {
+ throw new Error("🚩 Incompatible docker version")
+ }
+ } catch (error) {
+ console.error(error.message)
+ throw new Error("🚩 Please install docker 24.x (see https://github.com/consensusnetworks/casimir#prerequisites #1)")
+ }
- const submodules = fs.readFileSync('.gitmodules', 'utf8')
- const submoduleDirs = submodules.match(/path = (.*)/g)?.map((path) => path.replace('path = ', ''))
- if (submoduleDirs) {
- try {
- for (const dir of submoduleDirs) {
- const content = fs.readdirSync(dir)
- if (!content.length) {
- throw new Error('🚩 Missing ssh key for submodules')
- }
- }
- } catch (error) {
- console.error(error.message)
- throw new Error('🚩 Please add an ssh key for submodules (see https://github.com/consensusnetworks/casimir#prerequisites #2)')
- }
+ const submodules = fs.readFileSync(".gitmodules", "utf8")
+ const submoduleDirs = submodules.match(/path = (.*)/g)?.map((path) => path.replace("path = ", ""))
+ if (submoduleDirs) {
+ try {
+ for (const dir of submoduleDirs) {
+ const content = fs.readdirSync(dir)
+ if (!content.length) {
+ throw new Error("🚩 Missing ssh key for submodules")
+ }
}
+ } catch (error) {
+ console.error(error.message)
+ throw new Error("🚩 Please add an ssh key for submodules (see https://github.com/consensusnetworks/casimir#prerequisites #2)")
+ }
+ }
- const go = await run('go version') as string
- try {
- const goSplit = go.split(' ')
- const goNumber = goSplit[2]
- const goNumberSplit = goNumber.split('.')
- const goMajor = parseInt(goNumberSplit[0])
- const goMinor = parseInt(goNumberSplit[1])
- if (goMajor < 1 || goMinor < 20) {
- throw new Error('🚩 Incompatible go version')
- }
- } catch (error) {
- console.error(error.message)
- throw new Error('🚩 Please install go v1.18.x (see https://github.com/consensusnetworks/casimir#prerequisites #3)')
- }
+ const go = await run("go version") as string
+ try {
+ const goSplit = go.split(" ")
+ const goNumber = goSplit[2]
+ const goNumberSplit = goNumber.split(".")
+ const goMajor = parseInt(goNumberSplit[0])
+ const goMinor = parseInt(goNumberSplit[1])
+ if (goMajor < 1 || goMinor < 20) {
+ throw new Error("🚩 Incompatible go version")
+ }
+ } catch (error) {
+ console.error(error.message)
+ throw new Error("🚩 Please install go v1.18.x (see https://github.com/consensusnetworks/casimir#prerequisites #3)")
+ }
- try {
- const node = await run('node --version') as string
- if (!node.includes('v18')) {
- throw new Error('🚩 Incompatible node version')
- }
- } catch (error) {
- console.error(error.message)
- throw new Error('🚩 Please install node v18.x (see https://github.com/consensusnetworks/casimir#prerequisites #4)')
- }
+ try {
+ const node = await run("node --version") as string
+ if (!node.includes("v18")) {
+ throw new Error("🚩 Incompatible node version")
+ }
+ } catch (error) {
+ console.error(error.message)
+ throw new Error("🚩 Please install node v18.x (see https://github.com/consensusnetworks/casimir#prerequisites #4)")
}
+ }
}()
\ No newline at end of file
diff --git a/scripts/root/clean.ts b/scripts/root/clean.ts
index 2cfa0cb00..f9ce2d30f 100644
--- a/scripts/root/clean.ts
+++ b/scripts/root/clean.ts
@@ -1,6 +1,6 @@
-import { run } from '@casimir/shell'
-import fs from 'fs'
-import { promisify } from 'util'
+import { run } from "@casimir/shell"
+import fs from "fs"
+import { promisify } from "util"
const readFile = promisify(fs.readFile)
const readdir = promisify(fs.readdir)
@@ -12,32 +12,32 @@ const rm = promisify(fs.rm)
*/
void async function () {
- const { workspaces } = JSON.parse(await readFile('package.json', 'utf8'))
- const packageDirs: string[] = []
- for (const workspace of workspaces) {
- const baseDir = workspace.replace('/*', '')
- const packages = await readdir(baseDir)
- for (const pkg of packages) {
- const isNpm = await exists(`${baseDir}/${pkg}/package.json`)
- if (isNpm) {
- packageDirs.push(`${baseDir}/${pkg}/build`)
- packageDirs.push(`${baseDir}/${pkg}/dist`)
- packageDirs.push(`${baseDir}/${pkg}/node_modules`)
- packageDirs.push(`${baseDir}/${pkg}/scripts/.out`)
- }
- }
+ const { workspaces } = JSON.parse(await readFile("package.json", "utf8"))
+ const packageDirs: string[] = []
+ for (const workspace of workspaces) {
+ const baseDir = workspace.replace("/*", "")
+ const packages = await readdir(baseDir)
+ for (const pkg of packages) {
+ const isNpm = await exists(`${baseDir}/${pkg}/package.json`)
+ if (isNpm) {
+ packageDirs.push(`${baseDir}/${pkg}/build`)
+ packageDirs.push(`${baseDir}/${pkg}/dist`)
+ packageDirs.push(`${baseDir}/${pkg}/node_modules`)
+ packageDirs.push(`${baseDir}/${pkg}/scripts/.out`)
+ }
}
+ }
- const submodules = await readFile('.gitmodules', 'utf8')
- const submoduleDirs = submodules.match(/path = (.*)/g)?.map((path) => path.replace('path = ', '')) || []
+ const submodules = await readFile(".gitmodules", "utf8")
+ const submoduleDirs = submodules.match(/path = (.*)/g)?.map((path) => path.replace("path = ", "")) || []
- const items = ['node_modules', 'package-lock.json'].concat(packageDirs, submoduleDirs)
- for (const item of items) {
- if (await exists(item)) {
- console.log('Removing', item)
- await rm(item, { recursive: true })
- }
+ const items = ["node_modules", "package-lock.json"].concat(packageDirs, submoduleDirs)
+ for (const item of items) {
+ if (await exists(item)) {
+ console.log("Removing", item)
+ await rm(item, { recursive: true })
}
- console.log('Reinstalling dependencies')
- await run('npm i')
+ }
+ console.log("Reinstalling dependencies")
+ await run("npm i")
}()
\ No newline at end of file
diff --git a/scripts/root/dev.ts b/scripts/root/dev.ts
index 209ff4924..7269906b9 100644
--- a/scripts/root/dev.ts
+++ b/scripts/root/dev.ts
@@ -1,7 +1,7 @@
-import { ethers } from 'ethers'
-import { loadCredentials, getSecret } from '@casimir/aws'
-import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run, runSync } from '@casimir/shell'
+import { ethers } from "ethers"
+import { loadCredentials, getSecret } from "@casimir/aws"
+import { ETHEREUM_CONTRACTS, ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run, runSync } from "@casimir/shell"
/**
* Root script used to run an integrated development environment
@@ -23,128 +23,128 @@ import { run, runSync } from '@casimir/shell'
* - ETHEREUM_FORK_BLOCK: string
*/
async function root() {
- const apps = {
- landing: {
- contracts: false,
- port: 3002,
- services: {
- blog: {
- port: 4001,
- }
- }
- },
- web: {
- contracts: true,
- port: 3001,
- services: {
- users: {
- port: 4000,
- }
- }
+ const apps = {
+ landing: {
+ contracts: false,
+ port: 3002,
+ services: {
+ blog: {
+ port: 4001,
}
+ }
+ },
+ web: {
+ contracts: true,
+ port: 3001,
+ services: {
+ users: {
+ port: 4000,
+ }
+ }
}
+ }
- const app = process.env.APP || 'web'
- if (!apps[app]) {
- throw new Error(`App ${app} is not supported`)
- }
- const services = apps[app].services || {}
+ const app = process.env.APP || "web"
+ if (!apps[app]) {
+ throw new Error(`App ${app} is not supported`)
+ }
+ const services = apps[app].services || {}
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') || ''
- process.env.CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY || await getSecret('casimir-crypto-compare-api-key') || ''
- process.env.HACKMD_TOKEN = process.env.HACKMD_TOKEN || await getSecret('casimir-blog-hackmd-token') || ''
- process.env.WALLET_CONNECT_PROJECT_ID = process.env.WALLET_CONNECT_PROJECT_ID || await getSecret('casimir-wallet-connect-project-id') || ''
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- process.env.CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY || ''
- process.env.HACKMD_TOKEN = process.env.HACKMD_TOKEN || ''
- process.env.WALLET_CONNECT_PROJECT_ID = process.env.WALLET_CONNECT_PROJECT_ID || '8e6877b49198d7a9f9561b8712805726'
- }
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") || ""
+ process.env.CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY || await getSecret("casimir-crypto-compare-api-key") || ""
+ process.env.HACKMD_TOKEN = process.env.HACKMD_TOKEN || await getSecret("casimir-blog-hackmd-token") || ""
+ process.env.WALLET_CONNECT_PROJECT_ID = process.env.WALLET_CONNECT_PROJECT_ID || await getSecret("casimir-wallet-connect-project-id") || ""
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ process.env.CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY || ""
+ process.env.HACKMD_TOKEN = process.env.HACKMD_TOKEN || ""
+ process.env.WALLET_CONNECT_PROJECT_ID = process.env.WALLET_CONNECT_PROJECT_ID || "8e6877b49198d7a9f9561b8712805726"
+ }
- console.log(process.env.BIP39_SEED)
+ console.log(process.env.BIP39_SEED)
- process.env.PROJECT = process.env.PROJECT || 'casimir'
- process.env.STAGE = process.env.STAGE || 'local'
- process.env.FORK = process.env.FORK || 'testnet'
- process.env.MOCK_SERVICES = process.env.MOCK_SERVICES || 'true'
- process.env.BUILD_PREVIEW = process.env.BUILD_PREVIEW || 'false'
+ process.env.PROJECT = process.env.PROJECT || "casimir"
+ process.env.STAGE = process.env.STAGE || "local"
+ process.env.FORK = process.env.FORK || "testnet"
+ process.env.MOCK_SERVICES = process.env.MOCK_SERVICES || "true"
+ process.env.BUILD_PREVIEW = process.env.BUILD_PREVIEW || "false"
- if (process.env.BUILD_PREVIEW === 'true') {
- process.env[`${app.toUpperCase()}_URL`] = `http://localhost:${apps[app].port}`
- } else {
- process.env[`${app.toUpperCase()}_URL`] = `http://localhost:${apps[app].port}`
- }
+ if (process.env.BUILD_PREVIEW === "true") {
+ process.env[`${app.toUpperCase()}_URL`] = `http://localhost:${apps[app].port}`
+ } else {
+ process.env[`${app.toUpperCase()}_URL`] = `http://localhost:${apps[app].port}`
+ }
- if (process.env.MOCK_SERVICES === 'true') {
- for (const service of Object.keys(services)) {
- const existingProcess = await run(`lsof -i :${services[service].port} | grep LISTEN | awk '{print $2}'`)
- if (existingProcess) {
- throw new Error(`Port ${services[service].port} is already in use by process ${existingProcess}, but is required by ${service}.`)
- }
+ if (process.env.MOCK_SERVICES === "true") {
+ for (const service of Object.keys(services)) {
+ const existingProcess = await run(`lsof -i :${services[service].port} | grep LISTEN | awk '{print $2}'`)
+ if (existingProcess) {
+ throw new Error(`Port ${services[service].port} is already in use by process ${existingProcess}, but is required by ${service}.`)
+ }
- process.env[`${service.toUpperCase()}_URL`] = `http://localhost:${services[service].port}`
- run(`npm run dev --workspace @casimir/${service}`)
- }
+ process.env[`${service.toUpperCase()}_URL`] = `http://localhost:${services[service].port}`
+ run(`npm run dev --workspace @casimir/${service}`)
}
+ }
- const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || 'TESTNET'
- process.env.FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FACTORY_ADDRESS
- process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS
- process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS
- if (apps[app].contracts) {
- if (process.env.NETWORK) {
- const networkName = ETHEREUM_NETWORK_NAME[networkKey]
- process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[networkKey]
- console.log(`Connecting to ${networkName} network at ${process.env.ETHEREUM_RPC_URL}`)
- } else {
- const networkName = ETHEREUM_NETWORK_NAME[networkKey]
- process.env.ETHEREUM_FORK_RPC_URL = ETHEREUM_RPC_URL[networkKey]
- process.env.ETHEREUM_RPC_URL = 'http://127.0.0.1:8545'
- console.log(`Connecting to ${networkName} network fork at ${process.env.ETHEREUM_RPC_URL}`)
+ const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || "TESTNET"
+ process.env.FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FACTORY_ADDRESS
+ process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS
+ process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS
+ if (apps[app].contracts) {
+ if (process.env.NETWORK) {
+ const networkName = ETHEREUM_NETWORK_NAME[networkKey]
+ process.env.ETHEREUM_RPC_URL = ETHEREUM_RPC_URL[networkKey]
+ console.log(`Connecting to ${networkName} network at ${process.env.ETHEREUM_RPC_URL}`)
+ } else {
+ const networkName = ETHEREUM_NETWORK_NAME[networkKey]
+ process.env.ETHEREUM_FORK_RPC_URL = ETHEREUM_RPC_URL[networkKey]
+ process.env.ETHEREUM_RPC_URL = "http://127.0.0.1:8545"
+ console.log(`Connecting to ${networkName} network fork at ${process.env.ETHEREUM_RPC_URL}`)
- const forkProvider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_FORK_RPC_URL)
- process.env.ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK || `${await forkProvider.getBlockNumber() - 10}`
- console.log(`📍 Forking started at ${process.env.ETHEREUM_FORK_BLOCK}`)
+ const forkProvider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_FORK_RPC_URL)
+ process.env.ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK || `${await forkProvider.getBlockNumber() - 10}`
+ console.log(`📍 Forking started at ${process.env.ETHEREUM_FORK_BLOCK}`)
- process.env.TUNNEL = process.env.TUNNEL || 'false'
- process.env.MINING_INTERVAL = '12'
- process.env.SIMULATE_EIGEN = 'true'
- process.env.SIMULATE_REWARDS = 'true'
+ process.env.TUNNEL = process.env.TUNNEL || "false"
+ process.env.MINING_INTERVAL = "12"
+ process.env.SIMULATE_EIGEN = "true"
+ process.env.SIMULATE_REWARDS = "true"
- run('npm run dev --workspace @casimir/ethereum -- --network localhost')
- }
+ run("npm run dev --workspace @casimir/ethereum -- --network localhost")
}
+ }
- process.env.PUBLIC_STAGE = process.env.STAGE
- process.env.PUBLIC_BLOG_URL = process.env.BLOG_URL
- process.env.PUBLIC_USERS_URL = process.env.USERS_URL
- process.env.PUBLIC_ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL
- process.env.PUBLIC_FACTORY_ADDRESS = process.env.FACTORY_ADDRESS
- process.env.PUBLIC_SSV_NETWORK_ADDRESS = process.env.SSV_NETWORK_ADDRESS
- process.env.PUBLIC_SSV_VIEWS_ADDRESS = process.env.SSV_VIEWS_ADDRESS
- process.env.PUBLIC_CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY
- process.env.PUBLIC_ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK
- process.env.PUBLIC_WALLET_CONNECT_PROJECT_ID = process.env.WALLET_CONNECT_PROJECT_ID
+ process.env.PUBLIC_STAGE = process.env.STAGE
+ process.env.PUBLIC_BLOG_URL = process.env.BLOG_URL
+ process.env.PUBLIC_USERS_URL = process.env.USERS_URL
+ process.env.PUBLIC_ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL
+ process.env.PUBLIC_FACTORY_ADDRESS = process.env.FACTORY_ADDRESS
+ process.env.PUBLIC_SSV_NETWORK_ADDRESS = process.env.SSV_NETWORK_ADDRESS
+ process.env.PUBLIC_SSV_VIEWS_ADDRESS = process.env.SSV_VIEWS_ADDRESS
+ process.env.PUBLIC_CRYPTO_COMPARE_API_KEY = process.env.CRYPTO_COMPARE_API_KEY
+ process.env.PUBLIC_ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK
+ process.env.PUBLIC_WALLET_CONNECT_PROJECT_ID = process.env.WALLET_CONNECT_PROJECT_ID
- if (process.env.BUILD_PREVIEW === 'true') {
- await run(`npm run build --workspace @casimir/${app}`)
- run(`npm run preview --workspace @casimir/${app}`)
- } else {
- run(`npm run dev --workspace @casimir/${app}`)
- }
+ if (process.env.BUILD_PREVIEW === "true") {
+ await run(`npm run build --workspace @casimir/${app}`)
+ run(`npm run preview --workspace @casimir/${app}`)
+ } else {
+ run(`npm run dev --workspace @casimir/${app}`)
+ }
- if (process.env.MOCK_SERVICES === 'true' && app === 'web') {
- process.on('SIGINT', () => {
- console.log('🧹 Cleaning up users service')
- runSync('npm run clean --workspace @casimir/users')
- process.exit()
- })
- }
+ if (process.env.MOCK_SERVICES === "true" && app === "web") {
+ process.on("SIGINT", () => {
+ console.log("🧹 Cleaning up users service")
+ runSync("npm run clean --workspace @casimir/users")
+ process.exit()
+ })
+ }
}
root().catch(error => {
- console.error(error)
- process.exit(1)
+ console.error(error)
+ process.exit(1)
})
diff --git a/services/blog/src/index.ts b/services/blog/src/index.ts
index 221652620..a9e28f492 100644
--- a/services/blog/src/index.ts
+++ b/services/blog/src/index.ts
@@ -1,53 +1,53 @@
-import express from 'express'
-import cors from 'cors'
-import { HackmdArticle } from '@casimir/types'
+import express from "express"
+import cors from "cors"
+import { HackmdArticle } from "@casimir/types"
const app = express()
app.use(cors())
app.use(express.json())
-const hackmdUrl = 'https://api.hackmd.io/v1/teams'
+const hackmdUrl = "https://api.hackmd.io/v1/teams"
-app.get('/articles', async (_req, res) => {
- const options = {
- method: 'GET',
- headers: {
- Authorization: `Bearer ${process.env.HACKMD_TOKEN}`,
- 'Content-Type': 'application/json',
- }
- }
- const response = await fetch(`${hackmdUrl}/consensusnetworks/notes`, options)
- if (!response.ok) {
- res.status(response.status).send('Error fetching articles')
- } else {
- const data = await response.json() as HackmdArticle[]
- const hackmdArticles = data.filter((item) => item.tags.includes('blog') && item.publishedAt)
- res.json(hackmdArticles)
+app.get("/articles", async (_req, res) => {
+ const options = {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${process.env.HACKMD_TOKEN}`,
+ "Content-Type": "application/json",
}
+ }
+ const response = await fetch(`${hackmdUrl}/consensusnetworks/notes`, options)
+ if (!response.ok) {
+ res.status(response.status).send("Error fetching articles")
+ } else {
+ const data = await response.json() as HackmdArticle[]
+ const hackmdArticles = data.filter((item) => item.tags.includes("blog") && item.publishedAt)
+ res.json(hackmdArticles)
+ }
})
-app.get('/articles/:id', async (req, res) => {
- const notesId = req.params.id
- const options = {
- method: 'GET',
- headers: {
- Authorization: `Bearer ${process.env.HACKMD_TOKEN}`,
- 'Content-Type': 'application/json',
- },
- }
- const response = await fetch(`${hackmdUrl}/consensusnetworks/notes/${notesId}`, options)
- if (!response.ok) {
- res.status(response.status).send(`Error fetching article ${notesId}`)
- } else {
- const hackmdArticle = await response.json() as HackmdArticle
- res.json(hackmdArticle)
- }
+app.get("/articles/:id", async (req, res) => {
+ const notesId = req.params.id
+ const options = {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${process.env.HACKMD_TOKEN}`,
+ "Content-Type": "application/json",
+ },
+ }
+ const response = await fetch(`${hackmdUrl}/consensusnetworks/notes/${notesId}`, options)
+ if (!response.ok) {
+ res.status(response.status).send(`Error fetching article ${notesId}`)
+ } else {
+ const hackmdArticle = await response.json() as HackmdArticle
+ res.json(hackmdArticle)
+ }
})
-app.get('/health', (_req, res) => {
- res.status(200).send('OK')
+app.get("/health", (_req, res) => {
+ res.status(200).send("OK")
})
app.listen(4001, () => {
- console.log('Blog server listening on port 4001')
+ console.log("Blog server listening on port 4001")
})
diff --git a/services/functions/Functions-request-config.d.ts b/services/functions/Functions-request-config.d.ts
index bc34ce5ab..eef9f5fc9 100644
--- a/services/functions/Functions-request-config.d.ts
+++ b/services/functions/Functions-request-config.d.ts
@@ -1,4 +1,4 @@
-declare module '@casimir/functions/Functions-request-config' {
+declare module "@casimir/functions/Functions-request-config" {
const requestConfig: {
codeLocation: number
codeLanguage: number
diff --git a/services/functions/scripts/dev.ts b/services/functions/scripts/dev.ts
index fdac31d19..96c5110c0 100644
--- a/services/functions/scripts/dev.ts
+++ b/services/functions/scripts/dev.ts
@@ -1,34 +1,34 @@
-import { ethers } from 'ethers'
-import { loadCredentials, getSecret } from '@casimir/aws'
-import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run } from '@casimir/shell'
-import { waitForNetwork } from '@casimir/ethereum/helpers/network'
+import { ethers } from "ethers"
+import { loadCredentials, getSecret } from "@casimir/aws"
+import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run } from "@casimir/shell"
+import { waitForNetwork } from "@casimir/ethereum/helpers/network"
/**
* Start the Chainlink functions service
*/
async function dev() {
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- }
- const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || 'TESTNET'
- process.env.ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL || ETHEREUM_RPC_URL[networkKey]
- process.env.ETHEREUM_BEACON_RPC_URL = process.env.ETHEREUM_BEACON_RPC_URL || 'http://127.0.0.1:5052'
- process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FUNCTIONS_BILLING_REGISTRY_ADDRESS
- process.env.FUNCTIONS_ORACLE_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FUNCTIONS_ORACLE_ADDRESS
- process.env.USE_LOGS = process.env.USE_LOGS || 'false'
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") as string
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ }
+ const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || "TESTNET"
+ process.env.ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL || ETHEREUM_RPC_URL[networkKey]
+ process.env.ETHEREUM_BEACON_RPC_URL = process.env.ETHEREUM_BEACON_RPC_URL || "http://127.0.0.1:5052"
+ process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FUNCTIONS_BILLING_REGISTRY_ADDRESS
+ process.env.FUNCTIONS_ORACLE_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.FUNCTIONS_ORACLE_ADDRESS
+ process.env.USE_LOGS = process.env.USE_LOGS || "false"
- const provider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_RPC_URL)
- await waitForNetwork(provider)
+ const provider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_RPC_URL)
+ await waitForNetwork(provider)
- run('npx esno -r dotenv/config src/index.ts')
- console.log('🔗 Functions service started')
+ run("npx esno -r dotenv/config src/index.ts")
+ console.log("🔗 Functions service started")
}
dev().catch(error => {
- console.error(error)
- process.exit(1)
+ console.error(error)
+ process.exit(1)
})
\ No newline at end of file
diff --git a/services/functions/scripts/simulate.ts b/services/functions/scripts/simulate.ts
index b24c566af..ef8406f13 100644
--- a/services/functions/scripts/simulate.ts
+++ b/services/functions/scripts/simulate.ts
@@ -1,37 +1,37 @@
-import { ethers } from 'ethers'
-import { ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run } from '@casimir/shell'
-import { getSecret, loadCredentials } from '@casimir/aws'
-import { waitForNetwork } from '@casimir/ethereum/helpers/network'
+import { ethers } from "ethers"
+import { ETHEREUM_NETWORK_NAME, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run } from "@casimir/shell"
+import { getSecret, loadCredentials } from "@casimir/aws"
+import { waitForNetwork } from "@casimir/ethereum/helpers/network"
async function simulate() {
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- }
- const networkKey = process.env.FORK?.toUpperCase() || 'TESTNET'
- const networkName = ETHEREUM_NETWORK_NAME[networkKey]
- process.env.ETHEREUM_FORK_RPC_URL = ETHEREUM_RPC_URL[networkKey]
- process.env.ETHEREUM_RPC_URL = 'http://127.0.0.1:8545'
- console.log(`Connecting to ${networkName} network fork at ${process.env.ETHEREUM_RPC_URL}`)
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") as string
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ }
+ const networkKey = process.env.FORK?.toUpperCase() || "TESTNET"
+ const networkName = ETHEREUM_NETWORK_NAME[networkKey]
+ process.env.ETHEREUM_FORK_RPC_URL = ETHEREUM_RPC_URL[networkKey]
+ process.env.ETHEREUM_RPC_URL = "http://127.0.0.1:8545"
+ console.log(`Connecting to ${networkName} network fork at ${process.env.ETHEREUM_RPC_URL}`)
- const forkProvider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_FORK_RPC_URL)
- process.env.ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK || `${await forkProvider.getBlockNumber() - 10}`
- console.log(`📍 Forking started at ${process.env.ETHEREUM_FORK_BLOCK}`)
+ const forkProvider = new ethers.providers.JsonRpcProvider(process.env.ETHEREUM_FORK_RPC_URL)
+ process.env.ETHEREUM_FORK_BLOCK = process.env.ETHEREUM_FORK_BLOCK || `${await forkProvider.getBlockNumber() - 10}`
+ console.log(`📍 Forking started at ${process.env.ETHEREUM_FORK_BLOCK}`)
- process.env.TUNNEL = process.env.TUNNEL || 'false'
- process.env.MINING_INTERVAL = '12'
- process.env.SIMULATE_UPGRADES = 'true'
- process.env.SIMULATE_UPKEEP = 'true'
+ process.env.TUNNEL = process.env.TUNNEL || "false"
+ process.env.MINING_INTERVAL = "12"
+ process.env.SIMULATE_UPGRADES = "true"
+ process.env.SIMULATE_UPKEEP = "true"
- run('npm run dev --workspace @casimir/ethereum -- --network localhost')
- run('npm run report --workspace @casimir/ethereum -- --network localhost')
- run('npm run dev --workspace @casimir/functions')
+ run("npm run dev --workspace @casimir/ethereum -- --network localhost")
+ run("npm run report --workspace @casimir/ethereum -- --network localhost")
+ run("npm run dev --workspace @casimir/functions")
}
simulate().catch(error => {
- console.error(error)
- process.exit(1)
+ console.error(error)
+ process.exit(1)
})
\ No newline at end of file
diff --git a/services/functions/src/index.ts b/services/functions/src/index.ts
index 669d87b93..e5fb949ae 100644
--- a/services/functions/src/index.ts
+++ b/services/functions/src/index.ts
@@ -1,68 +1,68 @@
-import { getConfig } from './providers/config'
-import { getEventsIterable } from '@casimir/events'
-import { getStartBlock, updateErrorLog, updateStartBlock } from '@casimir/logs'
-import { fulfillRequestHandler } from './providers/handlers'
-import { ethers } from 'ethers'
-import { HandlerInput } from './interfaces/HandlerInput'
-import FunctionsOracleAbi from '@casimir/ethereum/build/abi/FunctionsOracle.json'
+import { getConfig } from "./providers/config"
+import { getEventsIterable } from "@casimir/events"
+import { getStartBlock, updateErrorLog, updateStartBlock } from "@casimir/logs"
+import { fulfillRequestHandler } from "./providers/handlers"
+import { ethers } from "ethers"
+import { HandlerInput } from "./interfaces/HandlerInput"
+import FunctionsOracleAbi from "@casimir/ethereum/build/abi/FunctionsOracle.json"
const config = getConfig()
async function run() {
- const contracts = {
- FunctionsOracle: {
- abi: FunctionsOracleAbi,
- addresses: [config.functionsOracleAddress],
- events: {
- OracleRequest: fulfillRequestHandler
- }
- }
+ const contracts = {
+ FunctionsOracle: {
+ abi: FunctionsOracleAbi,
+ addresses: [config.functionsOracleAddress],
+ events: {
+ OracleRequest: fulfillRequestHandler
+ }
}
+ }
- const contractFilters = Object.values(contracts).map((contract) => {
- return {
- abi: contract.abi,
- addresses: contract.addresses,
- events: Object.keys(contract.events)
- }
- })
-
- let startBlock
- if (process.env.USE_LOGS === 'true') {
- startBlock = getStartBlock('block.log')
+ const contractFilters = Object.values(contracts).map((contract) => {
+ return {
+ abi: contract.abi,
+ addresses: contract.addresses,
+ events: Object.keys(contract.events)
}
+ })
+
+ let startBlock
+ if (process.env.USE_LOGS === "true") {
+ startBlock = getStartBlock("block.log")
+ }
- const eventsIterable = getEventsIterable({
- contractFilters,
- ethereumUrl: config.ethereumUrl,
- startBlock
- })
+ const eventsIterable = getEventsIterable({
+ contractFilters,
+ ethereumUrl: config.ethereumUrl,
+ startBlock
+ })
- const handlers: Record Promise> = {}
- for (const contract of Object.values(contracts)) {
- for (const [event, handler] of Object.entries(contract.events)) {
- handlers[event as keyof typeof handlers] = handler
- }
+ const handlers: Record Promise> = {}
+ for (const contract of Object.values(contracts)) {
+ for (const [event, handler] of Object.entries(contract.events)) {
+ handlers[event as keyof typeof handlers] = handler
}
+ }
- for await (const event of eventsIterable) {
- console.log(`Received ${event.event} event from ${event.address}`)
- const args = event.args as ethers.utils.Result
- const handler = handlers[event.event as string]
- if (!handler) throw new Error(`No handler found for event ${event.event}`)
- await handler({ args })
- if (process.env.USE_LOGS === 'true') {
- // Todo check if this possibly misses events
- updateStartBlock('block.log', event.blockNumber + 1)
- }
+ for await (const event of eventsIterable) {
+ console.log(`Received ${event.event} event from ${event.address}`)
+ const args = event.args as ethers.utils.Result
+ const handler = handlers[event.event as string]
+ if (!handler) throw new Error(`No handler found for event ${event.event}`)
+ await handler({ args })
+ if (process.env.USE_LOGS === "true") {
+ // Todo check if this possibly misses events
+ updateStartBlock("block.log", event.blockNumber + 1)
}
+ }
}
run().catch(error => {
- if (process.env.USE_LOGS === 'true') {
- updateErrorLog('error.log', (error as Error).message)
- } else {
- console.log(error)
- }
- process.exit(1)
+ if (process.env.USE_LOGS === "true") {
+ updateErrorLog("error.log", (error as Error).message)
+ } else {
+ console.log(error)
+ }
+ process.exit(1)
})
\ No newline at end of file
diff --git a/services/functions/src/interfaces/HandlerInput.ts b/services/functions/src/interfaces/HandlerInput.ts
index 7a9fbef60..d9ef33c8d 100644
--- a/services/functions/src/interfaces/HandlerInput.ts
+++ b/services/functions/src/interfaces/HandlerInput.ts
@@ -1,4 +1,4 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export interface HandlerInput {
args?: ethers.utils.Result
diff --git a/services/functions/src/providers/config.ts b/services/functions/src/providers/config.ts
index 9c8ba13f9..a43e08383 100644
--- a/services/functions/src/providers/config.ts
+++ b/services/functions/src/providers/config.ts
@@ -1,24 +1,24 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export function getConfig() {
- const ethereumUrl = process.env.ETHEREUM_RPC_URL
- if (!ethereumUrl) throw new Error('No ethereum rpc url provided')
+ const ethereumUrl = process.env.ETHEREUM_RPC_URL
+ if (!ethereumUrl) throw new Error("No ethereum rpc url provided")
- const mnemonic = process.env.BIP39_SEED
- if (!mnemonic) throw new Error('No mnemonic provided')
- const accountPath = 'm/44\'/60\'/0\'/0/2'
- const wallet = ethers.Wallet.fromMnemonic(mnemonic, accountPath)
+ const mnemonic = process.env.BIP39_SEED
+ if (!mnemonic) throw new Error("No mnemonic provided")
+ const accountPath = "m/44'/60'/0'/0/2"
+ const wallet = ethers.Wallet.fromMnemonic(mnemonic, accountPath)
- const functionsBillingRegistryAddress = process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS
- if (!functionsBillingRegistryAddress) throw new Error('No functions billing registry address provided')
+ const functionsBillingRegistryAddress = process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS
+ if (!functionsBillingRegistryAddress) throw new Error("No functions billing registry address provided")
- const functionsOracleAddress = process.env.FUNCTIONS_ORACLE_ADDRESS
- if (!functionsOracleAddress) throw new Error('No functions oracle address provided')
+ const functionsOracleAddress = process.env.FUNCTIONS_ORACLE_ADDRESS
+ if (!functionsOracleAddress) throw new Error("No functions oracle address provided")
- return {
- ethereumUrl,
- functionsBillingRegistryAddress,
- functionsOracleAddress,
- wallet
- }
+ return {
+ ethereumUrl,
+ functionsBillingRegistryAddress,
+ functionsOracleAddress,
+ wallet
+ }
}
\ No newline at end of file
diff --git a/services/functions/src/providers/format.ts b/services/functions/src/providers/format.ts
index df8017b65..5e32b51e3 100644
--- a/services/functions/src/providers/format.ts
+++ b/services/functions/src/providers/format.ts
@@ -1,13 +1,13 @@
-import { ethers } from 'ethers'
-import cbor from 'cbor'
+import { ethers } from "ethers"
+import cbor from "cbor"
/**
* Decodes a CBOR hex string, and adds opening and closing brackets to the CBOR if they are not present.
* @param hex The hex string to decode
*/
export function decodeDietCBOR(hex: string) {
- const buf = hexToBuf(hex)
- return cbor.decodeFirstSync(addCBORMapDelimiters(buf))
+ const buf = hexToBuf(hex)
+ return cbor.decodeFirstSync(addCBORMapDelimiters(buf))
}
/**
@@ -15,7 +15,7 @@ export function decodeDietCBOR(hex: string) {
* @param hex The hex string to convert to a buffer
*/
export function hexToBuf(hex: string): Buffer {
- return Buffer.from(stripHexPrefix(hex), 'hex')
+ return Buffer.from(stripHexPrefix(hex), "hex")
}
/**
@@ -23,32 +23,34 @@ export function hexToBuf(hex: string): Buffer {
* @param hex The hex string to strip the leading hex prefix out of
*/
export function stripHexPrefix(hex: string): string {
- if (!ethers.utils.isHexString(hex)) {
- throw Error(`Expected valid hex string, got: "${hex}"`)
- }
- return hex.replace('0x', '')
+ if (!ethers.utils.isHexString(hex)) {
+ throw Error(`Expected valid hex string, got: "${hex}"`)
+ }
+ return hex.replace("0x", "")
}
/**
* Add a starting and closing map characters to a CBOR encoding if they are not already present.
*/
export function addCBORMapDelimiters(buffer: Buffer): Buffer {
- if (buffer[0] >> 5 === 5) {
- return buffer
- }
+ if (buffer[0] >> 5 === 5) {
+ return buffer
+ }
- /**
+ /**
* This is the opening character of a CBOR map.
* @see https://en.wikipedia.org/wiki/CBOR#CBOR_data_item_header
*/
- const startIndefiniteLengthMap = Buffer.from([0xbf])
- /**
+ const startIndefiniteLengthMap = Buffer.from([0xbf])
+ /**
* This is the closing character in a CBOR map.
* @see https://en.wikipedia.org/wiki/CBOR#CBOR_data_item_header
*/
- const endIndefiniteLengthMap = Buffer.from([0xff])
- return Buffer.concat(
- [startIndefiniteLengthMap, buffer, endIndefiniteLengthMap],
- buffer.length + 2,
- )
+ const endIndefiniteLengthMap = Buffer.from([0xff])
+ return Buffer.concat(
+ [startIndefiniteLengthMap,
+ buffer,
+ endIndefiniteLengthMap],
+ buffer.length + 2,
+ )
}
\ No newline at end of file
diff --git a/services/functions/src/providers/handlers.ts b/services/functions/src/providers/handlers.ts
index a5cbb9f59..e1945dab0 100644
--- a/services/functions/src/providers/handlers.ts
+++ b/services/functions/src/providers/handlers.ts
@@ -1,51 +1,51 @@
-import { ethers } from 'ethers'
-import { decodeDietCBOR } from './format'
-import requestConfig from '@casimir/functions/Functions-request-config'
-import { simulateRequest } from '../../FunctionsSandboxLibrary'
-import { getConfig } from './config'
-import { FunctionsBillingRegistry } from '@casimir/ethereum/build/@types'
-import { updateExecutionLog } from '@casimir/logs'
-import { HandlerInput } from '../interfaces/HandlerInput'
-import FunctionsBillingRegistryAbi from '@casimir/ethereum/build/abi/FunctionsBillingRegistry.json'
+import { ethers } from "ethers"
+import { decodeDietCBOR } from "./format"
+import requestConfig from "@casimir/functions/Functions-request-config"
+import { simulateRequest } from "../../FunctionsSandboxLibrary"
+import { getConfig } from "./config"
+import { FunctionsBillingRegistry } from "@casimir/ethereum/build/@types"
+import { updateExecutionLog } from "@casimir/logs"
+import { HandlerInput } from "../interfaces/HandlerInput"
+import FunctionsBillingRegistryAbi from "@casimir/ethereum/build/abi/FunctionsBillingRegistry.json"
const config = getConfig()
export async function fulfillRequestHandler(input: HandlerInput): Promise {
- const { requestId, data } = input.args as ethers.utils.Result
- if (!requestId) throw new Error('No request id provided')
- if (!data) throw new Error('No data provided')
+ const { requestId, data } = input.args as ethers.utils.Result
+ if (!requestId) throw new Error("No request id provided")
+ if (!data) throw new Error("No data provided")
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const functionsBillingRegistry = new ethers.Contract(config.functionsBillingRegistryAddress, FunctionsBillingRegistryAbi, provider) as FunctionsBillingRegistry
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const functionsBillingRegistry = new ethers.Contract(config.functionsBillingRegistryAddress, FunctionsBillingRegistryAbi, provider) as FunctionsBillingRegistry
- const { args } = decodeDietCBOR(data)
- const currentRequestConfig = {
- ...requestConfig,
- args
- }
+ const { args } = decodeDietCBOR(data)
+ const currentRequestConfig = {
+ ...requestConfig,
+ args
+ }
- const { result, resultLog, success } = await simulateRequest(currentRequestConfig)
- if (success) {
- const signer = config.wallet.connect(provider)
- const dummySigners = Array(31).fill(signer.address)
- const fulfillAndBill = await functionsBillingRegistry.connect(signer).fulfillAndBill(
- requestId,
- result,
- '0x',
- signer.address,
- dummySigners,
- 4,
- 100_000,
- 500_000,
- {
- gasLimit: 500_000,
- }
- )
- await fulfillAndBill.wait()
- if (process.env.USE_LOGS === 'true') {
- updateExecutionLog('execution.log', resultLog)
- }
- } else {
- throw new Error(resultLog)
+ const { result, resultLog, success } = await simulateRequest(currentRequestConfig)
+ if (success) {
+ const signer = config.wallet.connect(provider)
+ const dummySigners = Array(31).fill(signer.address)
+ const fulfillAndBill = await functionsBillingRegistry.connect(signer).fulfillAndBill(
+ requestId,
+ result,
+ "0x",
+ signer.address,
+ dummySigners,
+ 4,
+ 100_000,
+ 500_000,
+ {
+ gasLimit: 500_000,
+ }
+ )
+ await fulfillAndBill.wait()
+ if (process.env.USE_LOGS === "true") {
+ updateExecutionLog("execution.log", resultLog)
}
+ } else {
+ throw new Error(resultLog)
+ }
}
\ No newline at end of file
diff --git a/services/oracle/scripts/dev.ts b/services/oracle/scripts/dev.ts
index b60d046b1..6695529f2 100644
--- a/services/oracle/scripts/dev.ts
+++ b/services/oracle/scripts/dev.ts
@@ -1,48 +1,48 @@
-import { loadCredentials, getSecret } from '@casimir/aws'
-import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from '@casimir/env'
-import { run } from '@casimir/shell'
+import { loadCredentials, getSecret } from "@casimir/aws"
+import { ETHEREUM_CONTRACTS, ETHEREUM_RPC_URL } from "@casimir/env"
+import { run } from "@casimir/shell"
/**
* Start development DAO oracle service
*/
void async function () {
- process.env.CLI_PATH = process.env.CLI_PATH || './lib/dkg/bin/ssv-dkg'
- process.env.CONFIG_PATH = process.env.CONFIG_PATH || './config/example.dkg.initiator.yaml'
+ process.env.CLI_PATH = process.env.CLI_PATH || "./lib/dkg/bin/ssv-dkg"
+ process.env.CONFIG_PATH = process.env.CONFIG_PATH || "./config/example.dkg.initiator.yaml"
- if (process.env.USE_SECRETS !== 'false') {
- await loadCredentials()
- process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret('consensus-networks-bip39-seed') as string
- } else {
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
- }
+ if (process.env.USE_SECRETS !== "false") {
+ await loadCredentials()
+ process.env.BIP39_SEED = process.env.BIP39_SEED || await getSecret("consensus-networks-bip39-seed") as string
+ } else {
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
+ }
- const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || 'TESTNET'
+ const networkKey = process.env.NETWORK?.toUpperCase() || process.env.FORK?.toUpperCase() || "TESTNET"
- process.env.ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL || ETHEREUM_RPC_URL[networkKey]
- process.env.FACTORY_ADDRESS = process.env.FACTORY_ADDRESS || ETHEREUM_CONTRACTS[networkKey]?.FACTORY_ADDRESS
- process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS = process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS || ETHEREUM_CONTRACTS[networkKey]?.FUNCTIONS_BILLING_REGISTRY_ADDRESS
+ process.env.ETHEREUM_RPC_URL = process.env.ETHEREUM_RPC_URL || ETHEREUM_RPC_URL[networkKey]
+ process.env.FACTORY_ADDRESS = process.env.FACTORY_ADDRESS || ETHEREUM_CONTRACTS[networkKey]?.FACTORY_ADDRESS
+ process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS = process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS || ETHEREUM_CONTRACTS[networkKey]?.FUNCTIONS_BILLING_REGISTRY_ADDRESS
- process.env.KEEPER_REGISTRY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.KEEPER_REGISTRY_ADDRESS
- process.env.LINK_TOKEN_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.LINK_TOKEN_ADDRESS
- process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS
- process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS
- process.env.SSV_TOKEN_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_TOKEN_ADDRESS
- process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SWAP_FACTORY_ADDRESS
- process.env.WETH_TOKEN_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.WETH_TOKEN_ADDRESS
+ process.env.KEEPER_REGISTRY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.KEEPER_REGISTRY_ADDRESS
+ process.env.LINK_TOKEN_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.LINK_TOKEN_ADDRESS
+ process.env.SSV_NETWORK_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_NETWORK_ADDRESS
+ process.env.SSV_VIEWS_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_VIEWS_ADDRESS
+ process.env.SSV_TOKEN_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SSV_TOKEN_ADDRESS
+ process.env.SWAP_FACTORY_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.SWAP_FACTORY_ADDRESS
+ process.env.WETH_TOKEN_ADDRESS = ETHEREUM_CONTRACTS[networkKey]?.WETH_TOKEN_ADDRESS
- if (!process.env.ETHEREUM_RPC_URL) throw new Error(`No ethereum rpc url provided for ${networkKey}`)
- if (!process.env.FACTORY_ADDRESS) throw new Error(`No factory address provided for ${networkKey}`)
- if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error(`No functions billing registry address provided for ${networkKey}`)
- if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error(`No keeper registry address provided for ${networkKey}`)
- if (!process.env.LINK_TOKEN_ADDRESS) throw new Error(`No link token address provided for ${networkKey}`)
- if (!process.env.SSV_NETWORK_ADDRESS) throw new Error(`No ssv network address provided for ${networkKey}`)
- if (!process.env.SSV_VIEWS_ADDRESS) throw new Error(`No ssv views address provided for ${networkKey}`)
- if (!process.env.SSV_TOKEN_ADDRESS) throw new Error(`No ssv token address provided for ${networkKey}`)
- if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error(`No uniswap v3 factory address provided for ${networkKey}`)
+ if (!process.env.ETHEREUM_RPC_URL) throw new Error(`No ethereum rpc url provided for ${networkKey}`)
+ if (!process.env.FACTORY_ADDRESS) throw new Error(`No factory address provided for ${networkKey}`)
+ if (!process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS) throw new Error(`No functions billing registry address provided for ${networkKey}`)
+ if (!process.env.KEEPER_REGISTRY_ADDRESS) throw new Error(`No keeper registry address provided for ${networkKey}`)
+ if (!process.env.LINK_TOKEN_ADDRESS) throw new Error(`No link token address provided for ${networkKey}`)
+ if (!process.env.SSV_NETWORK_ADDRESS) throw new Error(`No ssv network address provided for ${networkKey}`)
+ if (!process.env.SSV_VIEWS_ADDRESS) throw new Error(`No ssv views address provided for ${networkKey}`)
+ if (!process.env.SSV_TOKEN_ADDRESS) throw new Error(`No ssv token address provided for ${networkKey}`)
+ if (!process.env.SWAP_FACTORY_ADDRESS) throw new Error(`No uniswap v3 factory address provided for ${networkKey}`)
- await run('GOWORK=off make -C lib/dkg build')
+ await run("GOWORK=off make -C lib/dkg build")
- process.env.USE_LOGS = process.env.USE_LOGS || 'false'
- run('npx esno -r dotenv/config src/index.ts')
- console.log('🔮 Oracle service started')
+ process.env.USE_LOGS = process.env.USE_LOGS || "false"
+ run("npx esno -r dotenv/config src/index.ts")
+ console.log("🔮 Oracle service started")
}()
\ No newline at end of file
diff --git a/services/oracle/scripts/generate.ts b/services/oracle/scripts/generate.ts
index e9a90e647..c8791fa98 100644
--- a/services/oracle/scripts/generate.ts
+++ b/services/oracle/scripts/generate.ts
@@ -1,94 +1,97 @@
-import fs from 'fs'
-import { ethers } from 'ethers'
-import { run } from '@casimir/shell'
-import { Dkg } from '../src/providers/dkg'
-import { MOCK_VALIDATORS/*, MOCK_RESHARES*/ } from '@casimir/env'
-import { Validator/*, Reshare*/ } from '@casimir/types'
+import fs from "fs"
+import { ethers } from "ethers"
+import { run } from "@casimir/shell"
+import { Dkg } from "../src/providers/dkg"
+import { MOCK_VALIDATORS/*, MOCK_RESHARES*/ } from "@casimir/env"
+import { Validator/*, Reshare*/ } from "@casimir/types"
/**
* Generate validator keys for ethereum testing
*/
void async function () {
- const outputPath = '../../common/env/src/mock'
+ const outputPath = "../../common/env/src/mock"
- process.env.CLI_PATH = process.env.CLI_PATH || './lib/dkg/bin/ssv-dkg'
- process.env.CONFIG_PATH = process.env.CONFIG_PATH || './config/example.dkg.initiator.yaml'
+ process.env.CLI_PATH = process.env.CLI_PATH || "./lib/dkg/bin/ssv-dkg"
+ process.env.CONFIG_PATH = process.env.CONFIG_PATH || "./config/example.dkg.initiator.yaml"
- process.env.BIP39_SEED = process.env.BIP39_SEED || 'inflict ball claim confirm cereal cost note dad mix donate traffic patient'
+ process.env.BIP39_SEED = process.env.BIP39_SEED || "inflict ball claim confirm cereal cost note dad mix donate traffic patient"
- if (!process.env.FACTORY_ADDRESS) throw new Error('No factory address provided')
-
- const preregisteredOperatorIds = process.env.PREREGISTERED_OPERATOR_IDS?.split(',').map(id => parseInt(id)) || [208, 209, 210, 211/*, 212, 213, 214, 215*/]
- if (preregisteredOperatorIds.length < 4) throw new Error('Not enough operator ids provided')
-
- const accountPath = 'm/44\'/60\'/0\'/0/1'
- const wallet = ethers.Wallet.fromMnemonic(process.env.BIP39_SEED, accountPath)
-
- const validatorCount = 4
- const mockValidators = MOCK_VALIDATORS || {}
- if (!mockValidators[wallet.address] || Object.keys(mockValidators[wallet.address]).length < validatorCount) {
- await run('GOWORK=off make -C lib/dkg build')
-
- const managerAddress = ethers.utils.getContractAddress({
- from: process.env.FACTORY_ADDRESS,
- nonce: 1
- })
- let managerNonce = 3
- let ownerNonce = 0
-
- const newValidators: Validator[] = []
- // const newReshares: Reshare[] = []
-
- for (let i = 0; i < validatorCount; i++) {
- const poolId = i + 1
- console.log('🤖 Creating deposit for', poolId)
-
- const poolAddress = ethers.utils.getContractAddress({
- from: managerAddress,
- nonce: managerNonce
- })
-
- const selectedOperatorIds = preregisteredOperatorIds.slice(0, 4)
-
- const dkg = new Dkg({
- cliPath: process.env.CLI_PATH,
- configPath: process.env.CONFIG_PATH,
- })
-
- const validator = await dkg.init({
- poolId,
- operatorIds: selectedOperatorIds,
- ownerAddress: managerAddress,
- ownerNonce,
- withdrawalAddress: poolAddress
- })
-
- newValidators.push(validator)
-
- // for (let j = 0; j < 2; j++) {
- // const oldOperatorIds = selectedOperatorIds.slice(1)
- // const reshareOperatorIds = preregisteredOperatorIds.slice(0, 3).concat(preregisteredOperatorIds[4])
-
- // const reshare = await dkg.reshare({
- // oldOperatorIds,
- // operatorIds: reshareOperatorIds,
- // ownerAddress: managerAddress,
- // ownerNonce,
- // poolId,
- // publicKey: validator.publicKey,
- // withdrawalAddress: poolAddress
- // })
- // newReshares.push(reshare)
- // }
- // reshareStore[poolId] = newReshares
-
- managerNonce++
- ownerNonce++
- }
-
- mockValidators[wallet.address] = newValidators
-
- fs.writeFileSync(`${outputPath}/validators.json`, JSON.stringify(mockValidators))
- // fs.writeFileSync(`${outputPath}/reshares.json`, JSON.stringify(MOCK_RESHARES))
+ if (!process.env.FACTORY_ADDRESS) throw new Error("No factory address provided")
+
+ const preregisteredOperatorIds = process.env.PREREGISTERED_OPERATOR_IDS?.split(",").map(id => parseInt(id)) || [208,
+ 209,
+ 210,
+ 211/*, 212, 213, 214, 215*/]
+ if (preregisteredOperatorIds.length < 4) throw new Error("Not enough operator ids provided")
+
+ const accountPath = "m/44'/60'/0'/0/1"
+ const wallet = ethers.Wallet.fromMnemonic(process.env.BIP39_SEED, accountPath)
+
+ const validatorCount = 4
+ const mockValidators = MOCK_VALIDATORS || {}
+ if (!mockValidators[wallet.address] || Object.keys(mockValidators[wallet.address]).length < validatorCount) {
+ await run("GOWORK=off make -C lib/dkg build")
+
+ const managerAddress = ethers.utils.getContractAddress({
+ from: process.env.FACTORY_ADDRESS,
+ nonce: 1
+ })
+ let managerNonce = 3
+ let ownerNonce = 0
+
+ const newValidators: Validator[] = []
+ // const newReshares: Reshare[] = []
+
+ for (let i = 0; i < validatorCount; i++) {
+ const poolId = i + 1
+ console.log("🤖 Creating deposit for", poolId)
+
+ const poolAddress = ethers.utils.getContractAddress({
+ from: managerAddress,
+ nonce: managerNonce
+ })
+
+ const selectedOperatorIds = preregisteredOperatorIds.slice(0, 4)
+
+ const dkg = new Dkg({
+ cliPath: process.env.CLI_PATH,
+ configPath: process.env.CONFIG_PATH,
+ })
+
+ const validator = await dkg.init({
+ poolId,
+ operatorIds: selectedOperatorIds,
+ ownerAddress: managerAddress,
+ ownerNonce,
+ withdrawalAddress: poolAddress
+ })
+
+ newValidators.push(validator)
+
+ // for (let j = 0; j < 2; j++) {
+ // const oldOperatorIds = selectedOperatorIds.slice(1)
+ // const reshareOperatorIds = preregisteredOperatorIds.slice(0, 3).concat(preregisteredOperatorIds[4])
+
+ // const reshare = await dkg.reshare({
+ // oldOperatorIds,
+ // operatorIds: reshareOperatorIds,
+ // ownerAddress: managerAddress,
+ // ownerNonce,
+ // poolId,
+ // publicKey: validator.publicKey,
+ // withdrawalAddress: poolAddress
+ // })
+ // newReshares.push(reshare)
+ // }
+ // reshareStore[poolId] = newReshares
+
+ managerNonce++
+ ownerNonce++
}
+
+ mockValidators[wallet.address] = newValidators
+
+ fs.writeFileSync(`${outputPath}/validators.json`, JSON.stringify(mockValidators))
+ // fs.writeFileSync(`${outputPath}/reshares.json`, JSON.stringify(MOCK_RESHARES))
+ }
}()
\ No newline at end of file
diff --git a/services/oracle/src/index.ts b/services/oracle/src/index.ts
index 6901b5c91..d9064b664 100644
--- a/services/oracle/src/index.ts
+++ b/services/oracle/src/index.ts
@@ -1,113 +1,115 @@
-import { ethers } from 'ethers'
-import { getEventsIterable } from '@casimir/events'
-import { getStartBlock, updateErrorLog, updateStartBlock } from '@casimir/logs'
-import ICasimirFactoryAbi from '@casimir/ethereum/build/abi/ICasimirFactory.json'
-import ICasimirManagerAbi from '@casimir/ethereum/build/abi/ICasimirManager.json'
-import ICasimirRegistryAbi from '@casimir/ethereum/build/abi/ICasimirRegistry.json'
-import ICasimirUpkeepAbi from '@casimir/ethereum/build/abi/ICasimirUpkeep.json'
-import { ICasimirFactory } from '@casimir/ethereum/build/@types'
-import { HandlerInput } from './interfaces/HandlerInput'
-import { getConfig } from './providers/config'
+import { ethers } from "ethers"
+import { getEventsIterable } from "@casimir/events"
+import { getStartBlock, updateErrorLog, updateStartBlock } from "@casimir/logs"
+import ICasimirFactoryAbi from "@casimir/ethereum/build/abi/ICasimirFactory.json"
+import ICasimirManagerAbi from "@casimir/ethereum/build/abi/ICasimirManager.json"
+import ICasimirRegistryAbi from "@casimir/ethereum/build/abi/ICasimirRegistry.json"
+import ICasimirUpkeepAbi from "@casimir/ethereum/build/abi/ICasimirUpkeep.json"
+import { ICasimirFactory } from "@casimir/ethereum/build/@types"
+import { HandlerInput } from "./interfaces/HandlerInput"
+import { getConfig } from "./providers/config"
import {
- depositFunctionsBalanceHandler,
- depositUpkeepBalanceHandler,
- initiatePoolHandler,
- activatePoolsHandler,
- resharePoolsHandler,
- // exitPoolHandler,
- // reportForcedExitsHandler,
- reportCompletedExitsHandler
-} from './providers/handlers'
-import { ManagerConfig } from '@casimir/types'
+ depositFunctionsBalanceHandler,
+ depositUpkeepBalanceHandler,
+ initiatePoolHandler,
+ activatePoolsHandler,
+ resharePoolsHandler,
+ // exitPoolHandler,
+ // reportForcedExitsHandler,
+ reportCompletedExitsHandler
+} from "./providers/handlers"
+import { ManagerConfig } from "@casimir/types"
const config = getConfig()
void async function () {
- try {
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const factory = new ethers.Contract(config.factoryAddress, ICasimirFactoryAbi, provider) as ICasimirFactory
- const managerConfigs = await Promise.all((await factory.getManagerIds()).map(async (id) => {
- return await factory.getManagerConfig(id)
- }))
+ try {
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const factory = new ethers.Contract(config.factoryAddress, ICasimirFactoryAbi, provider) as ICasimirFactory
+ const managerConfigs = await Promise.all((await factory.getManagerIds()).map(async (id) => {
+ return await factory.getManagerConfig(id)
+ }))
- const contracts = {
- CasimirManager: {
- abi: ICasimirManagerAbi,
- addresses: managerConfigs.map(({ managerAddress }) => managerAddress),
- events: {
- InitiationRequested: initiatePoolHandler
- // ExitRequested: exitPoolHandler
- }
- },
- CasimirRegistry: {
- abi: ICasimirRegistryAbi,
- addresses: managerConfigs.map(({ registryAddress }) => registryAddress),
- events: {
- DeactivationRequested: resharePoolsHandler
- }
- },
- CasimirUpkeep: {
- abi: ICasimirUpkeepAbi,
- addresses: managerConfigs.map(({ upkeepAddress }) => upkeepAddress),
- events: {
- ActivationsRequested: activatePoolsHandler,
- // ForcedExitReportsRequested: reportForcedExitsHandler,
- CompletedExitReportsRequested: reportCompletedExitsHandler
- }
- }
+ const contracts = {
+ CasimirManager: {
+ abi: ICasimirManagerAbi,
+ addresses: managerConfigs.map(({ managerAddress }) => managerAddress),
+ events: {
+ InitiationRequested: initiatePoolHandler
+ // ExitRequested: exitPoolHandler
}
+ },
+ CasimirRegistry: {
+ abi: ICasimirRegistryAbi,
+ addresses: managerConfigs.map(({ registryAddress }) => registryAddress),
+ events: {
+ DeactivationRequested: resharePoolsHandler
+ }
+ },
+ CasimirUpkeep: {
+ abi: ICasimirUpkeepAbi,
+ addresses: managerConfigs.map(({ upkeepAddress }) => upkeepAddress),
+ events: {
+ ActivationsRequested: activatePoolsHandler,
+ // ForcedExitReportsRequested: reportForcedExitsHandler,
+ CompletedExitReportsRequested: reportCompletedExitsHandler
+ }
+ }
+ }
- const contractFilters = Object.values(contracts).map((contract) => {
- return {
- abi: contract.abi,
- addresses: contract.addresses,
- events: Object.keys(contract.events)
- }
- })
+ const contractFilters = Object.values(contracts).map((contract) => {
+ return {
+ abi: contract.abi,
+ addresses: contract.addresses,
+ events: Object.keys(contract.events)
+ }
+ })
- let startBlock
- if (process.env.USE_LOGS === 'true') {
- startBlock = getStartBlock('block.log')
- }
+ let startBlock
+ if (process.env.USE_LOGS === "true") {
+ startBlock = getStartBlock("block.log")
+ }
- const eventsIterable = getEventsIterable({
- contractFilters,
- ethereumUrl: config.ethereumUrl,
- startBlock
- })
+ const eventsIterable = getEventsIterable({
+ contractFilters,
+ ethereumUrl: config.ethereumUrl,
+ startBlock
+ })
- const handlers: Record Promise> = {}
- for (const contract of Object.values(contracts)) {
- for (const [event, handler] of Object.entries(contract.events)) {
- handlers[event as keyof typeof handlers] = handler
- }
- }
+ const handlers: Record Promise> = {}
+ for (const contract of Object.values(contracts)) {
+ for (const [event, handler] of Object.entries(contract.events)) {
+ handlers[event as keyof typeof handlers] = handler
+ }
+ }
- for await (const event of eventsIterable) {
- console.log(`Received ${event.event} event from ${event.address}`)
- const managerConfig = managerConfigs.find(({ managerAddress, registryAddress, upkeepAddress }) => {
- return [managerAddress, registryAddress, upkeepAddress].includes(event.address)
- })
- if (!managerConfig) throw new Error(`No manager config found for address ${event.address}`)
- const args = event.args as ethers.utils.Result
- const handler = handlers[event.event as keyof typeof handlers]
- if (!handler) throw new Error(`No handler found for event ${event.event}`)
- await depositFunctionsBalanceHandler({ managerConfig })
- await depositUpkeepBalanceHandler({ managerConfig })
- await handler({ managerConfig, args })
- if (process.env.USE_LOGS === 'true') {
- // Todo check if this possibly misses events
- updateStartBlock('block.log', event.blockNumber + 1)
- }
- }
- } catch (error) {
- if (process.env.USE_LOGS === 'true') {
- updateErrorLog('error.log', (error as Error).message)
- } else {
- console.log(error)
- }
- process.exit(1)
+ for await (const event of eventsIterable) {
+ console.log(`Received ${event.event} event from ${event.address}`)
+ const managerConfig = managerConfigs.find(({ managerAddress, registryAddress, upkeepAddress }) => {
+ return [managerAddress,
+ registryAddress,
+ upkeepAddress].includes(event.address)
+ })
+ if (!managerConfig) throw new Error(`No manager config found for address ${event.address}`)
+ const args = event.args as ethers.utils.Result
+ const handler = handlers[event.event as keyof typeof handlers]
+ if (!handler) throw new Error(`No handler found for event ${event.event}`)
+ await depositFunctionsBalanceHandler({ managerConfig })
+ await depositUpkeepBalanceHandler({ managerConfig })
+ await handler({ managerConfig, args })
+ if (process.env.USE_LOGS === "true") {
+ // Todo check if this possibly misses events
+ updateStartBlock("block.log", event.blockNumber + 1)
+ }
+ }
+ } catch (error) {
+ if (process.env.USE_LOGS === "true") {
+ updateErrorLog("error.log", (error as Error).message)
+ } else {
+ console.log(error)
}
+ process.exit(1)
+ }
}()
diff --git a/services/oracle/src/interfaces/HandlerInput.ts b/services/oracle/src/interfaces/HandlerInput.ts
index c19bed072..99be7297b 100644
--- a/services/oracle/src/interfaces/HandlerInput.ts
+++ b/services/oracle/src/interfaces/HandlerInput.ts
@@ -1,5 +1,5 @@
-import { ethers } from 'ethers'
-import { ManagerConfig } from '@casimir/types'
+import { ethers } from "ethers"
+import { ManagerConfig } from "@casimir/types"
export interface HandlerInput {
managerConfig: ManagerConfig
diff --git a/services/oracle/src/providers/config.ts b/services/oracle/src/providers/config.ts
index 6bac671b7..7ed91882f 100644
--- a/services/oracle/src/providers/config.ts
+++ b/services/oracle/src/providers/config.ts
@@ -1,51 +1,51 @@
-import { ethers } from 'ethers'
+import { ethers } from "ethers"
export function getConfig() {
- const cliPath = process.env.CLI_PATH
- if (!cliPath) throw new Error('No cli path provided')
- const configPath = process.env.CONFIG_PATH
- if (!configPath) throw new Error('No config path provided')
+ const cliPath = process.env.CLI_PATH
+ if (!cliPath) throw new Error("No cli path provided")
+ const configPath = process.env.CONFIG_PATH
+ if (!configPath) throw new Error("No config path provided")
- const ethereumUrl = process.env.ETHEREUM_RPC_URL
- if (!ethereumUrl) throw new Error('No ethereum rpc url provided')
+ const ethereumUrl = process.env.ETHEREUM_RPC_URL
+ if (!ethereumUrl) throw new Error("No ethereum rpc url provided")
- const mnemonic = process.env.BIP39_SEED
- if (!mnemonic) throw new Error('No mnemonic provided')
- const accountPath = 'm/44\'/60\'/0\'/0/1'
- const wallet = ethers.Wallet.fromMnemonic(mnemonic, accountPath)
+ const mnemonic = process.env.BIP39_SEED
+ if (!mnemonic) throw new Error("No mnemonic provided")
+ const accountPath = "m/44'/60'/0'/0/1"
+ const wallet = ethers.Wallet.fromMnemonic(mnemonic, accountPath)
- const factoryAddress = process.env.FACTORY_ADDRESS
- if (!factoryAddress) throw new Error('No factory address provided')
- const functionsBillingRegistryAddress = process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS
- if (!functionsBillingRegistryAddress) throw new Error('No functions billing registry address provided')
- const keeperRegistryAddress = process.env.KEEPER_REGISTRY_ADDRESS
- if (!keeperRegistryAddress) throw new Error('No link registry address provided')
- const linkTokenAddress = process.env.LINK_TOKEN_ADDRESS
- if (!linkTokenAddress) throw new Error('No link token address provided')
- const ssvNetworkAddress = process.env.SSV_NETWORK_ADDRESS
- if (!ssvNetworkAddress) throw new Error('No ssv network address provided')
- const ssvTokenAddress = process.env.SSV_TOKEN_ADDRESS
- if (!ssvTokenAddress) throw new Error('No ssv token address provided')
- const ssvViewsAddress = process.env.SSV_VIEWS_ADDRESS
- if (!ssvViewsAddress) throw new Error('No ssv network views address provided')
- const uniswapV3FactoryAddress = process.env.SWAP_FACTORY_ADDRESS
- if (!uniswapV3FactoryAddress) throw new Error('No uniswap v3 factory address provided')
- const wethTokenAddress = process.env.WETH_TOKEN_ADDRESS
- if (!wethTokenAddress) throw new Error('No weth token address provided')
+ const factoryAddress = process.env.FACTORY_ADDRESS
+ if (!factoryAddress) throw new Error("No factory address provided")
+ const functionsBillingRegistryAddress = process.env.FUNCTIONS_BILLING_REGISTRY_ADDRESS
+ if (!functionsBillingRegistryAddress) throw new Error("No functions billing registry address provided")
+ const keeperRegistryAddress = process.env.KEEPER_REGISTRY_ADDRESS
+ if (!keeperRegistryAddress) throw new Error("No link registry address provided")
+ const linkTokenAddress = process.env.LINK_TOKEN_ADDRESS
+ if (!linkTokenAddress) throw new Error("No link token address provided")
+ const ssvNetworkAddress = process.env.SSV_NETWORK_ADDRESS
+ if (!ssvNetworkAddress) throw new Error("No ssv network address provided")
+ const ssvTokenAddress = process.env.SSV_TOKEN_ADDRESS
+ if (!ssvTokenAddress) throw new Error("No ssv token address provided")
+ const ssvViewsAddress = process.env.SSV_VIEWS_ADDRESS
+ if (!ssvViewsAddress) throw new Error("No ssv network views address provided")
+ const uniswapV3FactoryAddress = process.env.SWAP_FACTORY_ADDRESS
+ if (!uniswapV3FactoryAddress) throw new Error("No uniswap v3 factory address provided")
+ const wethTokenAddress = process.env.WETH_TOKEN_ADDRESS
+ if (!wethTokenAddress) throw new Error("No weth token address provided")
- return {
- cliPath,
- configPath,
- ethereumUrl,
- wallet,
- factoryAddress,
- functionsBillingRegistryAddress,
- keeperRegistryAddress,
- linkTokenAddress,
- ssvNetworkAddress,
- ssvTokenAddress,
- ssvViewsAddress,
- uniswapV3FactoryAddress,
- wethTokenAddress
- }
+ return {
+ cliPath,
+ configPath,
+ ethereumUrl,
+ wallet,
+ factoryAddress,
+ functionsBillingRegistryAddress,
+ keeperRegistryAddress,
+ linkTokenAddress,
+ ssvNetworkAddress,
+ ssvTokenAddress,
+ ssvViewsAddress,
+ uniswapV3FactoryAddress,
+ wethTokenAddress
+ }
}
diff --git a/services/oracle/src/providers/dkg.ts b/services/oracle/src/providers/dkg.ts
index f6a52f6fd..4c94aa291 100644
--- a/services/oracle/src/providers/dkg.ts
+++ b/services/oracle/src/providers/dkg.ts
@@ -1,111 +1,111 @@
-import fs from 'fs'
-import { MOCK_OPERATORS } from '@casimir/env'
-import { run } from '@casimir/shell'
-import { InitInput } from '../interfaces/InitInput'
-import { ReshareInput } from '../interfaces/ReshareInput'
-import { Reshare, Validator } from '@casimir/types'
-import { DkgOptions } from '../interfaces/DkgOptions'
+import fs from "fs"
+import { MOCK_OPERATORS } from "@casimir/env"
+import { run } from "@casimir/shell"
+import { InitInput } from "../interfaces/InitInput"
+import { ReshareInput } from "../interfaces/ReshareInput"
+import { Reshare, Validator } from "@casimir/types"
+import { DkgOptions } from "../interfaces/DkgOptions"
export class Dkg {
- cliPath: string
- configPath: string
+ cliPath: string
+ configPath: string
- constructor(options: DkgOptions) {
- this.cliPath = options.cliPath
- this.configPath = options.configPath
- }
+ constructor(options: DkgOptions) {
+ this.cliPath = options.cliPath
+ this.configPath = options.configPath
+ }
- /**
+ /**
* Init a new DKG and create a validator
* @param {InitInput} input - Init input
* @param {number} retries - Number of retries
* @returns {Promise} New validator
*/
- async init(input: InitInput, retries: number | undefined = 25): Promise {
- try {
- const operators = MOCK_OPERATORS.filter((operator) => input.operatorIds.includes(operator.id))
- if (!fs.existsSync('./data')) fs.mkdirSync('./data')
- fs.writeFileSync('./data/operators.json', JSON.stringify(operators))
+ async init(input: InitInput, retries: number | undefined = 25): Promise {
+ try {
+ const operators = MOCK_OPERATORS.filter((operator) => input.operatorIds.includes(operator.id))
+ if (!fs.existsSync("./data")) fs.mkdirSync("./data")
+ fs.writeFileSync("./data/operators.json", JSON.stringify(operators))
- const flags = [
- `--configPath ${this.configPath}`,
- `--operatorIDs ${input.operatorIds.join(',')}`,
- `--owner ${input.ownerAddress}`,
- `--nonce ${input.ownerNonce}`,
- `--withdrawAddress ${input.withdrawalAddress.split('0x')[1]}`
- ]
+ const flags = [
+ `--configPath ${this.configPath}`,
+ `--operatorIDs ${input.operatorIds.join(",")}`,
+ `--owner ${input.ownerAddress}`,
+ `--nonce ${input.ownerNonce}`,
+ `--withdrawAddress ${input.withdrawalAddress.split("0x")[1]}`
+ ]
- const command = `${this.cliPath} init ${flags.join(' ')}`
- const response = await run(`${command}`) as string
+ const command = `${this.cliPath} init ${flags.join(" ")}`
+ const response = await run(`${command}`) as string
- const depositFileLine = response.split('Writing deposit data json to file')[1]
- const depositFilePath = depositFileLine.split('{"path": "')[1].split('"}')[0]
- const [deposit] = JSON.parse(fs.readFileSync(depositFilePath, 'utf8'))
- const { deposit_data_root, pubkey, signature, withdrawal_credentials } = deposit
+ const depositFileLine = response.split("Writing deposit data json to file")[1]
+ const depositFilePath = depositFileLine.split("{\"path\": \"")[1].split("\"}")[0]
+ const [deposit] = JSON.parse(fs.readFileSync(depositFilePath, "utf8"))
+ const { deposit_data_root, pubkey, signature, withdrawal_credentials } = deposit
- const keysharesFileLine = response.split('Writing keyshares payload to file')[1]
- const keysharesFilePath = keysharesFileLine.split('{"path": "')[1].split('"}')[0]
- const { payload } = JSON.parse(fs.readFileSync(`${keysharesFilePath}`, 'utf8'))
- const shares = payload.sharesData
+ const keysharesFileLine = response.split("Writing keyshares payload to file")[1]
+ const keysharesFilePath = keysharesFileLine.split("{\"path\": \"")[1].split("\"}")[0]
+ const { payload } = JSON.parse(fs.readFileSync(`${keysharesFilePath}`, "utf8"))
+ const shares = payload.sharesData
- return {
- depositDataRoot: `0x${deposit_data_root}`,
- publicKey: `0x${pubkey}`,
- operatorIds: input.operatorIds,
- shares: shares,
- signature: `0x${signature}`,
- withdrawalCredentials: `0x${withdrawal_credentials}`
- }
- } catch (error) {
- if (retries === 0) {
- throw error
- }
- await new Promise(resolve => setTimeout(resolve, 2500))
- console.log(`Retrying init ${retries} more times`)
- return await this.init(input, retries - 1)
- }
+ return {
+ depositDataRoot: `0x${deposit_data_root}`,
+ publicKey: `0x${pubkey}`,
+ operatorIds: input.operatorIds,
+ shares: shares,
+ signature: `0x${signature}`,
+ withdrawalCredentials: `0x${withdrawal_credentials}`
+ }
+ } catch (error) {
+ if (retries === 0) {
+ throw error
+ }
+ await new Promise(resolve => setTimeout(resolve, 2500))
+ console.log(`Retrying init ${retries} more times`)
+ return await this.init(input, retries - 1)
}
+ }
- /**
+ /**
* Reshare an existing validator
* @param {ReshareInput} input - Reshare input
* @param {number} retries - Number of retries
* @returns {Promise} Reshared validator
*/
- async reshare(input: ReshareInput, retries: number | undefined = 25): Promise {
- try {
- const operators = MOCK_OPERATORS.filter((operator) => input.operatorIds.includes(operator.id))
- if (!fs.existsSync('./data')) fs.mkdirSync('./data')
- fs.writeFileSync('./data/operators.json', JSON.stringify(operators))
+ async reshare(input: ReshareInput, retries: number | undefined = 25): Promise {
+ try {
+ const operators = MOCK_OPERATORS.filter((operator) => input.operatorIds.includes(operator.id))
+ if (!fs.existsSync("./data")) fs.mkdirSync("./data")
+ fs.writeFileSync("./data/operators.json", JSON.stringify(operators))
- const flags = [
- `--configPath ${this.configPath}`,
- `--oldOperatorIDs ${input.oldOperatorIds.join(',')}`,
- `--operatorIDs ${input.operatorIds.join(',')}`
- ]
+ const flags = [
+ `--configPath ${this.configPath}`,
+ `--oldOperatorIDs ${input.oldOperatorIds.join(",")}`,
+ `--operatorIDs ${input.operatorIds.join(",")}`
+ ]
- const command = `${this.cliPath} reshare ${flags.join(' ')}`
- const response = await run(`${command}`) as string
+ const command = `${this.cliPath} reshare ${flags.join(" ")}`
+ const response = await run(`${command}`) as string
- const keysharesFileLine = response.split('Writing keyshares payload to file')[1]
- const keysharesFilePath = keysharesFileLine.split('{"path": "')[1].split('"}')[0]
- const { payload } = JSON.parse(fs.readFileSync(`${keysharesFilePath}`, 'utf8'))
- const shares = payload.sharesData
+ const keysharesFileLine = response.split("Writing keyshares payload to file")[1]
+ const keysharesFilePath = keysharesFileLine.split("{\"path\": \"")[1].split("\"}")[0]
+ const { payload } = JSON.parse(fs.readFileSync(`${keysharesFilePath}`, "utf8"))
+ const shares = payload.sharesData
- return {
- oldOperatorIds: input.oldOperatorIds,
- operatorIds: input.operatorIds,
- poolId: input.poolId,
- publicKey: input.publicKey,
- shares
- }
- } catch (error) {
- if (retries === 0) {
- throw error
- }
- await new Promise(resolve => setTimeout(resolve, 2500))
- console.log(`Retrying reshare ${retries} more times`)
- return await this.reshare(input, retries - 1)
- }
+ return {
+ oldOperatorIds: input.oldOperatorIds,
+ operatorIds: input.operatorIds,
+ poolId: input.poolId,
+ publicKey: input.publicKey,
+ shares
+ }
+ } catch (error) {
+ if (retries === 0) {
+ throw error
+ }
+ await new Promise(resolve => setTimeout(resolve, 2500))
+ console.log(`Retrying reshare ${retries} more times`)
+ return await this.reshare(input, retries - 1)
}
+ }
}
diff --git a/services/oracle/src/providers/handlers.ts b/services/oracle/src/providers/handlers.ts
index 9450b0dde..19042943f 100644
--- a/services/oracle/src/providers/handlers.ts
+++ b/services/oracle/src/providers/handlers.ts
@@ -1,459 +1,464 @@
-import { ethers } from 'ethers'
-import { CasimirManager, CasimirRegistry, CasimirViews, IFunctionsBillingRegistry, IAutomationRegistry } from '@casimir/ethereum/build/@types'
-import ICasimirManagerAbi from '@casimir/ethereum/build/abi/CasimirManager.json'
-import CasimirViewsAbi from '@casimir/ethereum/build/abi/CasimirViews.json'
-import CasimirRegistryAbi from '@casimir/ethereum/build/abi/CasimirRegistry.json'
-import IFunctionsBillingRegistryAbi from '@casimir/ethereum/build/abi/IFunctionsBillingRegistry.json'
-import IAutomationRegistryAbi from '@casimir/ethereum/build/abi/IAutomationRegistry.json'
-import { Scanner } from '@casimir/ssv'
-import { PoolStatus } from '@casimir/types'
-import { Factory } from '@casimir/uniswap'
-import { getConfig } from './config'
-import { Dkg } from './dkg'
-import { HandlerInput } from '../interfaces/HandlerInput'
+import { ethers } from "ethers"
+import { CasimirManager, CasimirRegistry, CasimirViews, IFunctionsBillingRegistry, IAutomationRegistry } from "@casimir/ethereum/build/@types"
+import ICasimirManagerAbi from "@casimir/ethereum/build/abi/CasimirManager.json"
+import CasimirViewsAbi from "@casimir/ethereum/build/abi/CasimirViews.json"
+import CasimirRegistryAbi from "@casimir/ethereum/build/abi/CasimirRegistry.json"
+import IFunctionsBillingRegistryAbi from "@casimir/ethereum/build/abi/IFunctionsBillingRegistry.json"
+import IAutomationRegistryAbi from "@casimir/ethereum/build/abi/IAutomationRegistry.json"
+import { Scanner } from "@casimir/ssv"
+import { PoolStatus } from "@casimir/types"
+import { Factory } from "@casimir/uniswap"
+import { getConfig } from "./config"
+import { Dkg } from "./dkg"
+import { HandlerInput } from "../interfaces/HandlerInput"
const config = getConfig()
const dkg = new Dkg({
- cliPath: config.cliPath,
- configPath: config.configPath
+ cliPath: config.cliPath,
+ configPath: config.configPath
})
export async function depositFunctionsBalanceHandler(input: HandlerInput) {
- const { managerConfig } = input
- const { managerAddress } = managerConfig
-
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const signer = config.wallet.connect(provider)
- const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
- const functionsBillingRegistry = new ethers.Contract(config.functionsBillingRegistryAddress, IFunctionsBillingRegistryAbi, provider) as ethers.Contract & IFunctionsBillingRegistry
-
- const minimumBalance = 0.2
- const refundBalance = 5
- const functionsId = await manager.functionsId()
- let balance = 0
- if (functionsId.gt(0)) {
- const subscription = await functionsBillingRegistry.getSubscription(functionsId)
- balance = Number(ethers.utils.formatEther(subscription.balance).split('.').map((part, index) => {
- if (index === 0) return part
- return part.slice(0, 1)
- }).join('.'))
- }
-
- if (balance < minimumBalance) {
- const uniswapFactory = new Factory({
- provider,
- uniswapV3FactoryAddress: config.uniswapV3FactoryAddress
- })
+ const { managerConfig } = input
+ const { managerAddress } = managerConfig
+
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const signer = config.wallet.connect(provider)
+ const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
+ const functionsBillingRegistry = new ethers.Contract(config.functionsBillingRegistryAddress, IFunctionsBillingRegistryAbi, provider) as ethers.Contract & IFunctionsBillingRegistry
+
+ const minimumBalance = 0.2
+ const refundBalance = 5
+ const functionsId = await manager.functionsId()
+ let balance = 0
+ if (functionsId.gt(0)) {
+ const subscription = await functionsBillingRegistry.getSubscription(functionsId)
+ balance = Number(ethers.utils.formatEther(subscription.balance).split(".").map((part, index) => {
+ if (index === 0) return part
+ return part.slice(0, 1)
+ }).join("."))
+ }
+
+ if (balance < minimumBalance) {
+ const uniswapFactory = new Factory({
+ provider,
+ uniswapV3FactoryAddress: config.uniswapV3FactoryAddress
+ })
- const price = await uniswapFactory.getSwapPrice({
- tokenIn: config.wethTokenAddress,
- tokenOut: config.linkTokenAddress,
- uniswapFeeTier: 3000
- })
+ const price = await uniswapFactory.getSwapPrice({
+ tokenIn: config.wethTokenAddress,
+ tokenOut: config.linkTokenAddress,
+ uniswapFeeTier: 3000
+ })
- const feeAmount = ethers.utils.parseEther((refundBalance * price).toPrecision(9))
- const minTokenAmount = ethers.utils.parseEther((refundBalance * 0.9).toPrecision(9))
+ const feeAmount = ethers.utils.parseEther((refundBalance * price).toPrecision(9))
+ const minTokenAmount = ethers.utils.parseEther((refundBalance * 0.9).toPrecision(9))
- const depositFunctionsBalance = await manager.connect(signer).depositFunctionsBalance(
- feeAmount,
- minTokenAmount,
- false
- )
- await depositFunctionsBalance.wait()
- }
+ const depositFunctionsBalance = await manager.connect(signer).depositFunctionsBalance(
+ feeAmount,
+ minTokenAmount,
+ false
+ )
+ await depositFunctionsBalance.wait()
+ }
}
export async function depositUpkeepBalanceHandler(input: HandlerInput) {
- const { managerConfig } = input
- const { managerAddress } = managerConfig
-
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const signer = config.wallet.connect(provider)
- const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
- const keeperRegistry = new ethers.Contract(config.keeperRegistryAddress, IAutomationRegistryAbi, provider) as ethers.Contract & IAutomationRegistry
-
- const minimumBalance = 6.5
- const refundBalance = 13
- const upkeepId = await manager.upkeepId()
- let balance = 0
- if (upkeepId.gt(0)) {
- const subscription = await keeperRegistry.getUpkeep(upkeepId)
- balance = Number(ethers.utils.formatEther(subscription.balance).split('.').map((part, index) => {
- if (index === 0) return part
- return part.slice(0, 1)
- }).join('.'))
- }
-
- if (balance < minimumBalance) {
- const uniswapFactory = new Factory({
- provider,
- uniswapV3FactoryAddress: config.uniswapV3FactoryAddress
- })
-
- const price = await uniswapFactory.getSwapPrice({
- tokenIn: config.wethTokenAddress,
- tokenOut: config.linkTokenAddress,
- uniswapFeeTier: 3000
- })
-
- const feeAmount = ethers.utils.parseEther((refundBalance * price).toPrecision(9))
- const minTokenAmount = ethers.utils.parseEther((refundBalance * 0.9).toPrecision(9))
-
- const depositUpkeepBalance = await manager.connect(signer).depositUpkeepBalance(
- feeAmount,
- minTokenAmount,
- false
- )
- await depositUpkeepBalance.wait()
- }
-}
-
-export async function initiatePoolHandler(input: HandlerInput) {
- const { managerConfig, args } = input
- const { managerAddress, registryAddress, viewsAddress } = managerConfig
- const poolId = args?.poolId
- if (!poolId) throw new Error('No pool id provided')
-
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const signer = config.wallet.connect(provider)
- const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
- const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
- const registry = new ethers.Contract(registryAddress, CasimirRegistryAbi, provider) as ethers.Contract & CasimirRegistry
-
- const managerNonce = await provider.getTransactionCount(manager.address)
- const poolAddress = ethers.utils.getContractAddress({
- from: manager.address,
- nonce: managerNonce
+ const { managerConfig } = input
+ const { managerAddress } = managerConfig
+
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const signer = config.wallet.connect(provider)
+ const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
+ const keeperRegistry = new ethers.Contract(config.keeperRegistryAddress, IAutomationRegistryAbi, provider) as ethers.Contract & IAutomationRegistry
+
+ const minimumBalance = 6.5
+ const refundBalance = 13
+ const upkeepId = await manager.upkeepId()
+ let balance = 0
+ if (upkeepId.gt(0)) {
+ const subscription = await keeperRegistry.getUpkeep(upkeepId)
+ balance = Number(ethers.utils.formatEther(subscription.balance).split(".").map((part, index) => {
+ if (index === 0) return part
+ return part.slice(0, 1)
+ }).join("."))
+ }
+
+ if (balance < minimumBalance) {
+ const uniswapFactory = new Factory({
+ provider,
+ uniswapV3FactoryAddress: config.uniswapV3FactoryAddress
})
- const operatorCount = (await registry.getOperatorIds()).length
- const operators = await views.getOperators(0, operatorCount)
-
- const eligibleOperators = operators.filter((operator) => {
- const availableCollateral = parseInt(ethers.utils.formatEther(operator.collateral)) - parseInt(operator.poolCount.toString())
- return operator.active && !operator.resharing && availableCollateral > 0
+ const price = await uniswapFactory.getSwapPrice({
+ tokenIn: config.wethTokenAddress,
+ tokenOut: config.linkTokenAddress,
+ uniswapFeeTier: 3000
})
- const smallestOperators = eligibleOperators.sort((a, b) => {
- const aPoolCount = parseInt(a.poolCount.toString())
- const bPoolCount = parseInt(b.poolCount.toString())
- if (aPoolCount < bPoolCount) return -1
- if (aPoolCount > bPoolCount) return 1
- return 0
- })
+ const feeAmount = ethers.utils.parseEther((refundBalance * price).toPrecision(9))
+ const minTokenAmount = ethers.utils.parseEther((refundBalance * 0.9).toPrecision(9))
- const selectedOperatorIds = smallestOperators.slice(0, 4).map((operator) => operator.id.toNumber())
- console.log('🤖 Selected operators', selectedOperatorIds)
+ const depositUpkeepBalance = await manager.connect(signer).depositUpkeepBalance(
+ feeAmount,
+ minTokenAmount,
+ false
+ )
+ await depositUpkeepBalance.wait()
+ }
+}
- const scanner = new Scanner({
- ethereumUrl: config.ethereumUrl,
- ssvNetworkAddress: config.ssvNetworkAddress,
- ssvViewsAddress: config.ssvViewsAddress
- })
+export async function initiatePoolHandler(input: HandlerInput) {
+ const { managerConfig, args } = input
+ const { managerAddress, registryAddress, viewsAddress } = managerConfig
+ const poolId = args?.poolId
+ if (!poolId) throw new Error("No pool id provided")
+
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const signer = config.wallet.connect(provider)
+ const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
+ const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
+ const registry = new ethers.Contract(registryAddress, CasimirRegistryAbi, provider) as ethers.Contract & CasimirRegistry
+
+ const managerNonce = await provider.getTransactionCount(manager.address)
+ const poolAddress = ethers.utils.getContractAddress({
+ from: manager.address,
+ nonce: managerNonce
+ })
+
+ const operatorCount = (await registry.getOperatorIds()).length
+ const operators = await views.getOperators(0, operatorCount)
+
+ const eligibleOperators = operators.filter((operator) => {
+ const availableCollateral = parseInt(ethers.utils.formatEther(operator.collateral)) - parseInt(operator.poolCount.toString())
+ return operator.active && !operator.resharing && availableCollateral > 0
+ })
+
+ const smallestOperators = eligibleOperators.sort((a, b) => {
+ const aPoolCount = parseInt(a.poolCount.toString())
+ const bPoolCount = parseInt(b.poolCount.toString())
+ if (aPoolCount < bPoolCount) return -1
+ if (aPoolCount > bPoolCount) return 1
+ return 0
+ })
+
+ const selectedOperatorIds = smallestOperators.slice(0, 4).map((operator) => operator.id.toNumber())
+ console.log("🤖 Selected operators", selectedOperatorIds)
+
+ const scanner = new Scanner({
+ ethereumUrl: config.ethereumUrl,
+ ssvNetworkAddress: config.ssvNetworkAddress,
+ ssvViewsAddress: config.ssvViewsAddress
+ })
+
+ const ownerNonce = await scanner.getNonce(manager.address)
+
+ const validator = await dkg.init({
+ operatorIds: selectedOperatorIds,
+ ownerAddress: manager.address,
+ ownerNonce,
+ poolId,
+ withdrawalAddress: poolAddress
+ })
+
+ const {
+ depositDataRoot,
+ publicKey,
+ signature,
+ withdrawalCredentials,
+ operatorIds,
+ shares
+ } = validator
+
+ const initiatePool = await manager.initiatePool(
+ depositDataRoot,
+ publicKey,
+ signature,
+ withdrawalCredentials,
+ operatorIds,
+ shares
+ )
+ await initiatePool.wait()
+}
- const ownerNonce = await scanner.getNonce(manager.address)
+export async function activatePoolsHandler(input: HandlerInput) {
+ const { managerConfig, args } = input
+ const { managerAddress, viewsAddress } = managerConfig
+ const count = args?.count
+ if (!count) throw new Error("No count provided")
+ console.log("🤖 Activate pools", count)
- const validator = await dkg.init({
- operatorIds: selectedOperatorIds,
- ownerAddress: manager.address,
- ownerNonce,
- poolId,
- withdrawalAddress: poolAddress
- })
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const signer = config.wallet.connect(provider)
+ const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
+ const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
- const {
- depositDataRoot,
- publicKey,
- signature,
- withdrawalCredentials,
- operatorIds,
- shares
- } = validator
-
- const initiatePool = await manager.initiatePool(
- depositDataRoot,
- publicKey,
- signature,
- withdrawalCredentials,
- operatorIds,
- shares
- )
- await initiatePool.wait()
-}
+ for (let i = 0; i < count; i++) {
+ const pendingPoolIds = await manager.getPendingPoolIds()
+ if (!pendingPoolIds.length) throw new Error("No pending pools")
-export async function activatePoolsHandler(input: HandlerInput) {
- const { managerConfig, args } = input
- const { managerAddress, viewsAddress } = managerConfig
- const count = args?.count
- if (!count) throw new Error('No count provided')
- console.log('🤖 Activate pools', count)
-
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const signer = config.wallet.connect(provider)
- const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
- const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
-
- for (let i = 0; i < count; i++) {
- const pendingPoolIds = await manager.getPendingPoolIds()
- if (!pendingPoolIds.length) throw new Error('No pending pools')
-
- /**
+ /**
* In production, we check the pending pool status on Beacon before activating
* Here, we're just grabbing the next pending pool
*/
- const pendingPoolIndex = 0
- const poolId = pendingPoolIds[pendingPoolIndex]
- const poolConfig = await views.getPoolConfig(poolId)
- const operatorIds = poolConfig.operatorIds.map((operatorId) => operatorId.toNumber())
+ const pendingPoolIndex = 0
+ const poolId = pendingPoolIds[pendingPoolIndex]
+ const poolConfig = await views.getPoolConfig(poolId)
+ const operatorIds = poolConfig.operatorIds.map((operatorId) => operatorId.toNumber())
- const scanner = new Scanner({
- ethereumUrl: config.ethereumUrl,
- ssvNetworkAddress: config.ssvNetworkAddress,
- ssvViewsAddress: config.ssvViewsAddress
- })
+ const scanner = new Scanner({
+ ethereumUrl: config.ethereumUrl,
+ ssvNetworkAddress: config.ssvNetworkAddress,
+ ssvViewsAddress: config.ssvViewsAddress
+ })
- const cluster = await scanner.getCluster({
- ownerAddress: manager.address,
- operatorIds
- })
+ const cluster = await scanner.getCluster({
+ ownerAddress: manager.address,
+ operatorIds
+ })
- const requiredFee = await scanner.getRequiredFee(operatorIds)
+ const requiredFee = await scanner.getRequiredFee(operatorIds)
- const uniswapFactory = new Factory({
- ethereumUrl: config.ethereumUrl,
- uniswapV3FactoryAddress: config.uniswapV3FactoryAddress
- })
+ const uniswapFactory = new Factory({
+ ethereumUrl: config.ethereumUrl,
+ uniswapV3FactoryAddress: config.uniswapV3FactoryAddress
+ })
- const price = await uniswapFactory.getSwapPrice({
- tokenIn: config.wethTokenAddress,
- tokenOut: config.ssvTokenAddress,
- uniswapFeeTier: 3000
- })
+ const price = await uniswapFactory.getSwapPrice({
+ tokenIn: config.wethTokenAddress,
+ tokenOut: config.ssvTokenAddress,
+ uniswapFeeTier: 3000
+ })
- const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee)) * price).toPrecision(9))
- const minTokenAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee)) * 0.99).toPrecision(9))
+ const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee)) * price).toPrecision(9))
+ const minTokenAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee)) * 0.99).toPrecision(9))
- const activatePool = await manager.connect(signer).activatePool(
- pendingPoolIndex,
- cluster,
- feeAmount,
- minTokenAmount,
- false
- )
- await activatePool.wait()
- }
+ const activatePool = await manager.connect(signer).activatePool(
+ pendingPoolIndex,
+ cluster,
+ feeAmount,
+ minTokenAmount,
+ false
+ )
+ await activatePool.wait()
+ }
}
export async function resharePoolsHandler(input: HandlerInput) {
- const { args, managerConfig } = input
- const { managerAddress, registryAddress, viewsAddress } = managerConfig
- const operatorId = args?.operatorId
- if (!operatorId) throw new Error('No operator id provided')
-
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const signer = config.wallet.connect(provider)
- const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
- const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
- const registry = new ethers.Contract(registryAddress, CasimirRegistryAbi, provider) as ethers.Contract & CasimirRegistry
-
- const poolIds = [
- ...await manager.getPendingPoolIds(),
- ...await manager.getStakedPoolIds()
- ]
-
- for (const poolId of poolIds) {
- const poolConfig = await views.getPoolConfig(poolId)
- const oldOperatorIds = poolConfig.operatorIds.map(id => id.toNumber())
- if (oldOperatorIds.includes(operatorId)) {
- const poolAddress = await manager.getPoolAddress(poolId)
-
- const operatorCount = (await registry.getOperatorIds()).length
- const operators = await views.getOperators(0, operatorCount)
+ const { args, managerConfig } = input
+ const { managerAddress, registryAddress, viewsAddress } = managerConfig
+ const operatorId = args?.operatorId
+ if (!operatorId) throw new Error("No operator id provided")
+
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const signer = config.wallet.connect(provider)
+ const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
+ const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
+ const registry = new ethers.Contract(registryAddress, CasimirRegistryAbi, provider) as ethers.Contract & CasimirRegistry
+
+ const poolIds = [
+ ...await manager.getPendingPoolIds(), ...await manager.getStakedPoolIds()
+ ]
+
+ for (const poolId of poolIds) {
+ const poolConfig = await views.getPoolConfig(poolId)
+ const oldOperatorIds = poolConfig.operatorIds.map(id => id.toNumber())
+ if (oldOperatorIds.includes(operatorId)) {
+ const poolAddress = await manager.getPoolAddress(poolId)
+
+ const operatorCount = (await registry.getOperatorIds()).length
+ const operators = await views.getOperators(0, operatorCount)
- const eligibleOperators = operators.filter((operator) => {
- const availableCollateral = parseInt(ethers.utils.formatEther(operator.collateral)) - parseInt(operator.poolCount.toString())
- return operator.active && !operator.resharing && availableCollateral > 0
- })
+ const eligibleOperators = operators.filter((operator) => {
+ const availableCollateral = parseInt(ethers.utils.formatEther(operator.collateral)) - parseInt(operator.poolCount.toString())
+ return operator.active && !operator.resharing && availableCollateral > 0
+ })
- const smallestOperators = eligibleOperators.sort((a, b) => {
- const aPoolCount = parseInt(a.poolCount.toString())
- const bPoolCount = parseInt(b.poolCount.toString())
- if (aPoolCount < bPoolCount) return -1
- if (aPoolCount > bPoolCount) return 1
- return 0
- })
+ const smallestOperators = eligibleOperators.sort((a, b) => {
+ const aPoolCount = parseInt(a.poolCount.toString())
+ const bPoolCount = parseInt(b.poolCount.toString())
+ if (aPoolCount < bPoolCount) return -1
+ if (aPoolCount > bPoolCount) return 1
+ return 0
+ })
- const newOperatorId = smallestOperators.find((operator) => !oldOperatorIds.includes(operator.id.toNumber()))?.id.toNumber()
- console.log('🤖 New selected operator', newOperatorId)
-
- if (newOperatorId && poolConfig.reshares.toNumber() < 2) {
- const operatorIds = oldOperatorIds.map((id) => {
- if (id === operatorId) return newOperatorId
- return id
- })
+ const newOperatorId = smallestOperators.find((operator) => !oldOperatorIds.includes(operator.id.toNumber()))?.id.toNumber()
+ console.log("🤖 New selected operator", newOperatorId)
+
+ if (newOperatorId && poolConfig.reshares.toNumber() < 2) {
+ const operatorIds = oldOperatorIds.map((id) => {
+ if (id === operatorId) return newOperatorId
+ return id
+ })
- const scanner = new Scanner({
- ethereumUrl: config.ethereumUrl,
- ssvNetworkAddress: config.ssvNetworkAddress,
- ssvViewsAddress: config.ssvViewsAddress
- })
+ const scanner = new Scanner({
+ ethereumUrl: config.ethereumUrl,
+ ssvNetworkAddress: config.ssvNetworkAddress,
+ ssvViewsAddress: config.ssvViewsAddress
+ })
- const oldCluster = await scanner.getCluster({
- operatorIds: oldOperatorIds,
- ownerAddress: manager.address
- })
+ const oldCluster = await scanner.getCluster({
+ operatorIds: oldOperatorIds,
+ ownerAddress: manager.address
+ })
- const cluster = await scanner.getCluster({
- operatorIds,
- ownerAddress: manager.address
- })
+ const cluster = await scanner.getCluster({
+ operatorIds,
+ ownerAddress: manager.address
+ })
- const ownerNonce = await scanner.getNonce(manager.address)
+ const ownerNonce = await scanner.getNonce(manager.address)
- const requiredFee = await scanner.getRequiredFee(operatorIds)
+ const requiredFee = await scanner.getRequiredFee(operatorIds)
- const reshare = await dkg.reshare({
- oldOperatorIds,
- operatorIds,
- poolId,
- publicKey: poolConfig.publicKey
- })
+ const reshare = await dkg.reshare({
+ oldOperatorIds,
+ operatorIds,
+ poolId,
+ publicKey: poolConfig.publicKey
+ })
- const uniswapFactory = new Factory({
- ethereumUrl: config.ethereumUrl,
- uniswapV3FactoryAddress: config.uniswapV3FactoryAddress
- })
+ const uniswapFactory = new Factory({
+ ethereumUrl: config.ethereumUrl,
+ uniswapV3FactoryAddress: config.uniswapV3FactoryAddress
+ })
- const price = await uniswapFactory.getSwapPrice({
- tokenIn: config.wethTokenAddress,
- tokenOut: config.ssvTokenAddress,
- uniswapFeeTier: 3000
- })
+ const price = await uniswapFactory.getSwapPrice({
+ tokenIn: config.wethTokenAddress,
+ tokenOut: config.ssvTokenAddress,
+ uniswapFeeTier: 3000
+ })
- const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * Number(price)).toPrecision(9))
- const minTokenAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * 0.99).toPrecision(9))
-
- const reportReshare = await manager.reportReshare(
- poolId,
- operatorIds,
- newOperatorId,
- operatorId,
- reshare.shares,
- cluster,
- oldCluster,
- feeAmount,
- minTokenAmount,
- false
- )
- await reportReshare.wait()
- } else {
- // Exit pool
- }
- }
+ const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * Number(price)).toPrecision(9))
+ const minTokenAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * 0.99).toPrecision(9))
+
+ const reportReshare = await manager.reportReshare(
+ poolId,
+ operatorIds,
+ newOperatorId,
+ operatorId,
+ reshare.shares,
+ cluster,
+ oldCluster,
+ feeAmount,
+ minTokenAmount,
+ false
+ )
+ await reportReshare.wait()
+ } else {
+ // Exit pool
+ }
}
+ }
}
export async function initiateExitsHandler(input: HandlerInput) {
- const { managerConfig, args } = input
- const { managerAddress, viewsAddress } = managerConfig
- const poolId = args?.poolId
- if (!poolId) throw new Error('No pool id provided')
+ const { managerConfig, args } = input
+ const { managerAddress, viewsAddress } = managerConfig
+ const poolId = args?.poolId
+ if (!poolId) throw new Error("No pool id provided")
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, provider) as ethers.Contract & CasimirManager
- const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, provider) as ethers.Contract & CasimirManager
+ const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
- // Get pool to exit
- const poolConfig = await views.getPoolConfig(poolId)
+ // Get pool to exit
+ const poolConfig = await views.getPoolConfig(poolId)
- // Get operators to sign exit
+ // Get operators to sign exit
}
export async function reportForcedExitsHandler(input: HandlerInput) {
- const { managerConfig, args } = input
- const { managerAddress, viewsAddress } = managerConfig
- const count = args?.count
- if (!count) throw new Error('No count provided')
-
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const signer = config.wallet.connect(provider)
- const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
- const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
-
- const stakedPoolIds = await manager.getStakedPoolIds()
- let poolIndex = 0
- let remaining = count
- while (remaining > 0) {
- const poolId = stakedPoolIds[poolIndex]
- const poolConfig = await views.getPoolConfig(poolId)
- if (poolConfig.status === PoolStatus.ACTIVE) {
- remaining--
- const reportForcedExit = await manager.reportForcedExit(
- poolIndex
- )
- await reportForcedExit.wait()
- }
- poolIndex++
+ const { managerConfig, args } = input
+ const { managerAddress, viewsAddress } = managerConfig
+ const count = args?.count
+ if (!count) throw new Error("No count provided")
+
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const signer = config.wallet.connect(provider)
+ const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
+ const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
+
+ const stakedPoolIds = await manager.getStakedPoolIds()
+ let poolIndex = 0
+ let remaining = count
+ while (remaining > 0) {
+ const poolId = stakedPoolIds[poolIndex]
+ const poolConfig = await views.getPoolConfig(poolId)
+ if (poolConfig.status === PoolStatus.ACTIVE) {
+ remaining--
+ const reportForcedExit = await manager.reportForcedExit(
+ poolIndex
+ )
+ await reportForcedExit.wait()
}
+ poolIndex++
+ }
}
export async function reportCompletedExitsHandler(input: HandlerInput) {
- const { managerConfig, args } = input
- const { managerAddress, viewsAddress } = managerConfig
- const count = args?.count
- if (!count) throw new Error('No count provided')
+ const { managerConfig, args } = input
+ const { managerAddress, viewsAddress } = managerConfig
+ const count = args?.count
+ if (!count) throw new Error("No count provided")
- const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
- const signer = config.wallet.connect(provider)
- const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
- const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
+ const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
+ const signer = config.wallet.connect(provider)
+ const manager = new ethers.Contract(managerAddress, ICasimirManagerAbi, signer) as ethers.Contract & CasimirManager
+ const views = new ethers.Contract(viewsAddress, CasimirViewsAbi, provider) as ethers.Contract & CasimirViews
- /**
+ /**
* In production, we get the completed exit order from the Beacon API (sorting by withdrawn epoch)
* We check all validators using:
* const stakedPublicKeys = await views.getStakedPublicKeys(startIndex, endIndex)
* Here, we're just grabbing the next exiting pool for each completed exit
*/
- const stakedPoolIds = await manager.getStakedPoolIds()
- let remaining = count
- let poolIndex = 0
- while (remaining > 0) {
- const poolId = stakedPoolIds[poolIndex]
- const poolConfig = await views.getPoolConfig(poolId)
- if (poolConfig.status === PoolStatus.EXITING_FORCED || poolConfig.status === PoolStatus.EXITING_REQUESTED) {
- remaining--
+ const stakedPoolIds = await manager.getStakedPoolIds()
+ let remaining = count
+ let poolIndex = 0
+ while (remaining > 0) {
+ const poolId = stakedPoolIds[poolIndex]
+ const poolConfig = await views.getPoolConfig(poolId)
+ if (poolConfig.status === PoolStatus.EXITING_FORCED || poolConfig.status === PoolStatus.EXITING_REQUESTED) {
+ remaining--
- /**
+ /**
* In production, we use the SSV performance data to determine blame
* We check all validators using:
* const stakedPublicKeys = await views.getStakedPublicKeys(startIndex, endIndex)
* Here, we're just hardcoding blame to the first operator if less than 32 ETH
*/
- const operatorIds = poolConfig.operatorIds.map((operatorId) => operatorId.toNumber())
- let blamePercents = [0, 0, 0, 0]
- if (poolConfig.balance.lt(ethers.utils.parseEther('32'))) {
- blamePercents = [100, 0, 0, 0]
- }
-
- const scanner = new Scanner({
- ethereumUrl: config.ethereumUrl,
- ssvNetworkAddress: config.ssvNetworkAddress,
- ssvViewsAddress: config.ssvViewsAddress
- })
-
- const cluster = await scanner.getCluster({
- ownerAddress: manager.address,
- operatorIds
- })
-
- const reportCompletedExit = await manager.reportCompletedExit(
- poolIndex,
- blamePercents,
- cluster
- )
- await reportCompletedExit.wait()
- }
- poolIndex++
+ const operatorIds = poolConfig.operatorIds.map((operatorId) => operatorId.toNumber())
+ let blamePercents = [0,
+ 0,
+ 0,
+ 0]
+ if (poolConfig.balance.lt(ethers.utils.parseEther("32"))) {
+ blamePercents = [100,
+ 0,
+ 0,
+ 0]
+ }
+
+ const scanner = new Scanner({
+ ethereumUrl: config.ethereumUrl,
+ ssvNetworkAddress: config.ssvNetworkAddress,
+ ssvViewsAddress: config.ssvViewsAddress
+ })
+
+ const cluster = await scanner.getCluster({
+ ownerAddress: manager.address,
+ operatorIds
+ })
+
+ const reportCompletedExit = await manager.reportCompletedExit(
+ poolIndex,
+ blamePercents,
+ cluster
+ )
+ await reportCompletedExit.wait()
}
+ poolIndex++
+ }
}
\ No newline at end of file
diff --git a/services/redirect/src/index.ts b/services/redirect/src/index.ts
index f73c83c58..6da7b73a3 100644
--- a/services/redirect/src/index.ts
+++ b/services/redirect/src/index.ts
@@ -1,7 +1,7 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function handler(event: AWSCloudFrontFunction.Event) {
- if (!event.request.uri.includes('.')) {
- event.request.uri += '.html'
- }
- return event.request
+ if (!event.request.uri.includes(".")) {
+ event.request.uri += ".html"
+ }
+ return event.request
}
\ No newline at end of file
diff --git a/services/users/scripts/clean.ts b/services/users/scripts/clean.ts
index ce20544b1..685986d3b 100644
--- a/services/users/scripts/clean.ts
+++ b/services/users/scripts/clean.ts
@@ -1,11 +1,11 @@
-import { run } from '@casimir/shell'
+import { run } from "@casimir/shell"
/**
* Clean up users resources
*/
void async function () {
- const resourceDir = './scripts'
- const stackName = 'casimir-users-db'
- await run(`rm -rf ${resourceDir}/.out`)
- await run(`docker compose -p ${stackName} -f ${resourceDir}/docker-compose.yaml down`)
+ const resourceDir = "./scripts"
+ const stackName = "casimir-users-db"
+ await run(`rm -rf ${resourceDir}/.out`)
+ await run(`docker compose -p ${stackName} -f ${resourceDir}/docker-compose.yaml down`)
}()
\ No newline at end of file
diff --git a/services/users/scripts/db.ts b/services/users/scripts/db.ts
index 30d500a04..9039c2f2d 100644
--- a/services/users/scripts/db.ts
+++ b/services/users/scripts/db.ts
@@ -1,68 +1,68 @@
-import fs from 'fs'
-import os from 'os'
-import { run } from '@casimir/shell'
-import { getSecret, loadCredentials } from '@casimir/aws'
-import { JsonSchema, Schema, accountSchema, nonceSchema, operatorSchema, userSchema, userAccountSchema } from '@casimir/data'
+import fs from "fs"
+import os from "os"
+import { run } from "@casimir/shell"
+import { getSecret, loadCredentials } from "@casimir/aws"
+import { JsonSchema, Schema, accountSchema, nonceSchema, operatorSchema, userSchema, userAccountSchema } from "@casimir/data"
/**
* Run a local users database and service
*/
void async function () {
- if (process.env.STAGE !== 'local') {
- await loadCredentials()
- const dbCredentials = await getSecret(`${process.env.PROJECT}-users-db-credentials-${process.env.STAGE}`)
- const { port: dbPort, host: dbHost, dbname: dbName, username: dbUser, password: dbPassword } = JSON.parse(dbCredentials as string)
- process.env.DB_HOST = dbHost
- process.env.DB_PORT = dbPort
- process.env.DB_NAME = dbName
- process.env.DB_USER = dbUser
- process.env.DB_PASSWORD = dbPassword
- const sessionsCredentials = await getSecret(`${process.env.PROJECT}-sessions-credentials-${process.env.STAGE}`)
- const { host: sessionsHost, key: sessionsKey } = JSON.parse(sessionsCredentials as string)
- process.env.SESSIONS_HOST = sessionsHost
- process.env.SESSIONS_KEY = sessionsKey
- }
+ if (process.env.STAGE !== "local") {
+ await loadCredentials()
+ const dbCredentials = await getSecret(`${process.env.PROJECT}-users-db-credentials-${process.env.STAGE}`)
+ const { port: dbPort, host: dbHost, dbname: dbName, username: dbUser, password: dbPassword } = JSON.parse(dbCredentials as string)
+ process.env.DB_HOST = dbHost
+ process.env.DB_PORT = dbPort
+ process.env.DB_NAME = dbName
+ process.env.DB_USER = dbUser
+ process.env.DB_PASSWORD = dbPassword
+ const sessionsCredentials = await getSecret(`${process.env.PROJECT}-sessions-credentials-${process.env.STAGE}`)
+ const { host: sessionsHost, key: sessionsKey } = JSON.parse(sessionsCredentials as string)
+ process.env.SESSIONS_HOST = sessionsHost
+ process.env.SESSIONS_KEY = sessionsKey
+ }
- const resourceDir = './scripts'
+ const resourceDir = "./scripts"
- const tableSchemas = {
- account: accountSchema,
- operator: operatorSchema,
- nonce: nonceSchema,
- user: userSchema,
- userAccount: userAccountSchema
- }
+ const tableSchemas = {
+ account: accountSchema,
+ operator: operatorSchema,
+ nonce: nonceSchema,
+ user: userSchema,
+ userAccount: userAccountSchema
+ }
- let sqlSchema = ''
- for (const table of Object.keys(tableSchemas)) {
- const tableSchema = tableSchemas[table] as JsonSchema
- const schema = new Schema(tableSchema)
- const postgresTable = schema.getPostgresTable()
- console.log(`${schema.getTitle()} JSON schema parsed to SQL`)
- sqlSchema += `${postgresTable}\n\n`
- }
+ let sqlSchema = ""
+ for (const table of Object.keys(tableSchemas)) {
+ const tableSchema = tableSchemas[table] as JsonSchema
+ const schema = new Schema(tableSchema)
+ const postgresTable = schema.getPostgresTable()
+ console.log(`${schema.getTitle()} JSON schema parsed to SQL`)
+ sqlSchema += `${postgresTable}\n\n`
+ }
- const sqlDir = `${resourceDir}/.out/sql`
- if (!fs.existsSync(sqlDir)) fs.mkdirSync(sqlDir, { recursive: true })
- fs.writeFileSync(`${sqlDir}/schema.sql`, sqlSchema)
+ const sqlDir = `${resourceDir}/.out/sql`
+ if (!fs.existsSync(sqlDir)) fs.mkdirSync(sqlDir, { recursive: true })
+ fs.writeFileSync(`${sqlDir}/schema.sql`, sqlSchema)
- const stackName = 'casimir-users-db'
- await run(`docker compose -p ${stackName} -f ${resourceDir}/docker-compose.yaml up -d`)
- let dbReady = false
- while (!dbReady) {
- const health = await run('docker inspect --format=\'{{lower .State.Health.Status}}\' postgres') as string
- dbReady = health.trim() === 'healthy'
- await new Promise(resolve => setTimeout(resolve, 2500))
- }
- const atlas = await run('which atlas') as string
- if (!atlas || atlas.includes('not found')) {
- if (os.platform() === 'darwin') {
- await run('echo y | brew install atlas')
- } else {
- throw new Error('Please install atlas using `curl -sSf https://atlasgo.sh | sh`')
- }
+ const stackName = "casimir-users-db"
+ await run(`docker compose -p ${stackName} -f ${resourceDir}/docker-compose.yaml up -d`)
+ let dbReady = false
+ while (!dbReady) {
+ const health = await run("docker inspect --format='{{lower .State.Health.Status}}' postgres") as string
+ dbReady = health.trim() === "healthy"
+ await new Promise(resolve => setTimeout(resolve, 2500))
+ }
+ const atlas = await run("which atlas") as string
+ if (!atlas || atlas.includes("not found")) {
+ if (os.platform() === "darwin") {
+ await run("echo y | brew install atlas")
+ } else {
+ throw new Error("Please install atlas using `curl -sSf https://atlasgo.sh | sh`")
}
+ }
- await run(`atlas schema apply --url "postgres://postgres:password@localhost:5432/users?sslmode=disable" --to "file://${sqlDir}/schema.sql" --dev-url "docker://postgres/15" --auto-approve`)
+ await run(`atlas schema apply --url "postgres://postgres:password@localhost:5432/users?sslmode=disable" --to "file://${sqlDir}/schema.sql" --dev-url "docker://postgres/15" --auto-approve`)
}()
\ No newline at end of file
diff --git a/services/users/src/index.ts b/services/users/src/index.ts
index 09ebd34e4..4da31c145 100644
--- a/services/users/src/index.ts
+++ b/services/users/src/index.ts
@@ -1,12 +1,12 @@
-import express from 'express'
-import cors from 'cors'
-import supertokens from 'supertokens-node'
-import { middleware, errorHandler } from 'supertokens-node/framework/express'
-import { SuperTokensBackendConfig } from './sessions.config'
-import analytics from './routes/analytics'
-import auth from './routes/auth'
-import user from './routes/user'
-import health from './routes/health'
+import express from "express"
+import cors from "cors"
+import supertokens from "supertokens-node"
+import { middleware, errorHandler } from "supertokens-node/framework/express"
+import { SuperTokensBackendConfig } from "./sessions.config"
+import analytics from "./routes/analytics"
+import auth from "./routes/auth"
+import user from "./routes/user"
+import health from "./routes/health"
supertokens.init(SuperTokensBackendConfig)
const app = express()
@@ -14,42 +14,45 @@ app.use(express.json())
/** CORS needs explicit origin (no *) with credentials:true */
app.use(
- cors({
- origin: process.env.WEB_URL || 'http://localhost:3001',
- allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()],
- methods: ['GET', 'PUT', 'POST', 'DELETE'],
- credentials: true
- })
+ cors({
+ origin: process.env.WEB_URL || "http://localhost:3001",
+ allowedHeaders: ["content-type", ...supertokens.getAllCORSHeaders()],
+ methods: ["GET",
+ "PUT",
+ "POST",
+ "DELETE"],
+ credentials: true
+ })
)
/** Expose all the APIs from SuperTokens to the client */
app.use(middleware())
-app.use('/auth', auth)
-app.use('/user', user)
-app.use('/health', health)
-app.use('/analytics', analytics)
+app.use("/auth", auth)
+app.use("/user", user)
+app.use("/health", health)
+app.use("/analytics", analytics)
/** Returns 401 to the client in the case of session related errors */
app.use(errorHandler())
/* Handle 500 errors */
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
- // Log the error stack trace
- console.error(`Error stack trace in middleware: ${err.stack}`)
- console.error(`Error message in middleware: ${err.message}`)
+ // Log the error stack trace
+ console.error(`Error stack trace in middleware: ${err.stack}`)
+ console.error(`Error message in middleware: ${err.message}`)
- // Check if headers have already been sent to the client
- if (res.headersSent) {
- return next(err)
- }
-
- res.status(500).json({
- error: true,
- message: 'Server error.'
- })
+ // Check if headers have already been sent to the client
+ if (res.headersSent) {
+ return next(err)
+ }
+
+ res.status(500).json({
+ error: true,
+ message: "Server error."
+ })
})
app.listen(4000, () => {
- console.log('Users server listening on port 4000')
+ console.log("Users server listening on port 4000")
})
\ No newline at end of file
diff --git a/services/users/src/providers/db.ts b/services/users/src/providers/db.ts
index a8a747bae..d6020acd5 100644
--- a/services/users/src/providers/db.ts
+++ b/services/users/src/providers/db.ts
@@ -1,16 +1,16 @@
-import { Postgres } from './postgres'
-import { camelCase } from '@casimir/format'
-import { Account, OperatorAddedSuccess, RemoveAccountOptions, User, UserAddedSuccess, UserWithAccountsAndOperators } from '@casimir/types'
-import useEthers from './ethers'
+import { Postgres } from "./postgres"
+import { camelCase } from "@casimir/format"
+import { Account, OperatorAddedSuccess, RemoveAccountOptions, User, UserAddedSuccess, UserWithAccountsAndOperators } from "@casimir/types"
+import useEthers from "./ethers"
const { generateNonce } = useEthers()
const postgres = new Postgres({
- host: process.env.DB_HOST || 'localhost',
- port: parseInt(process.env.DB_PORT as string) || 5432,
- database: process.env.DB_NAME || 'users',
- user: process.env.DB_USER || 'postgres',
- password: process.env.DB_PASSWORD || 'password'
+ host: process.env.DB_HOST || "localhost",
+ port: parseInt(process.env.DB_PORT as string) || 5432,
+ database: process.env.DB_NAME || "users",
+ user: process.env.DB_USER || "postgres",
+ password: process.env.DB_PASSWORD || "password"
})
interface AddOperatorOptions {
@@ -21,136 +21,149 @@ interface AddOperatorOptions {
export default function useDB() {
- /**
+ /**
* Add an account.
* @param account - The account to add
* @param createdAt - The account's creation date (optional)
* @returns The new account
*/
- async function addAccount(account: Account, createdAt?: string) : Promise {
- try {
- if (!createdAt) createdAt = new Date().toISOString()
- const { address, currency, userId, walletProvider } = account
+ async function addAccount(account: Account, createdAt?: string) : Promise {
+ try {
+ if (!createdAt) createdAt = new Date().toISOString()
+ const { address, currency, userId, walletProvider } = account
- // Check if the account already exists for the user
- const checkText = 'SELECT * FROM accounts WHERE user_id = $1 AND address = $2;'
- const checkParams = [userId, address]
- const checkResultRows = await postgres.query(checkText, checkParams)
+ // Check if the account already exists for the user
+ const checkText = "SELECT * FROM accounts WHERE user_id = $1 AND address = $2;"
+ const checkParams = [userId, address]
+ const checkResultRows = await postgres.query(checkText, checkParams)
- if (checkResultRows[0]) {
- // Account with this address already exists for the user
- throw new Error('Account with this address already exists for the user')
- }
+ if (checkResultRows[0]) {
+ // Account with this address already exists for the user
+ throw new Error("Account with this address already exists for the user")
+ }
- // Proceed to add the account
- const text = 'INSERT INTO accounts (address, currency, user_id, wallet_provider, created_at) VALUES ($1, $2, $3, $4, $5) RETURNING *;'
- const params = [address, currency, userId, walletProvider, createdAt]
- const rows = await postgres.query(text, params)
- const accountAdded = rows[0]
- const accountId = accountAdded.id
- await addUserAccount(parseInt(userId), accountId)
- return accountAdded as Account
- } catch (error: any) {
- throw new Error('There was an error adding the account to the database: ' + error.message)
- }
- }
+ // Proceed to add the account
+ const text = "INSERT INTO accounts (address, currency, user_id, wallet_provider, created_at) VALUES ($1, $2, $3, $4, $5) RETURNING *;"
+ const params = [address,
+ currency,
+ userId,
+ walletProvider,
+ createdAt]
+ const rows = await postgres.query(text, params)
+ const accountAdded = rows[0]
+ const accountId = accountAdded.id
+ await addUserAccount(parseInt(userId), accountId)
+ return accountAdded as Account
+ } catch (error: any) {
+ throw new Error("There was an error adding the account to the database: " + error.message)
+ }
+ }
- /**
+ /**
* Adds operator to operator table
* @param userId
* @param accountId
* @returns Promise
*/
- // TODO: Need some check to make sure operator is properly registered
- async function addOperator({ userId, accountId, nodeUrl }: AddOperatorOptions) : Promise {
- try {
- const created_at = new Date().toISOString()
- const text = 'INSERT INTO operators (user_id, account_id, node_url, created_at, updated_at) VALUES ($1, $2, $3, $4, $5) RETURNING *;'
- const params = [userId, accountId, nodeUrl, created_at, created_at]
- const rows = await postgres.query(text, params)
- const addedOperator = rows[0]
- return formatResult(addedOperator)
- } catch (error) {
- console.error(`There was an error in addOperator in useDB.ts: ${error}`)
- throw new Error('There was an error adding the operator to the database')
- }
+ // TODO: Need some check to make sure operator is properly registered
+ async function addOperator({ userId, accountId, nodeUrl }: AddOperatorOptions) : Promise {
+ try {
+ const created_at = new Date().toISOString()
+ const text = "INSERT INTO operators (user_id, account_id, node_url, created_at, updated_at) VALUES ($1, $2, $3, $4, $5) RETURNING *;"
+ const params = [userId,
+ accountId,
+ nodeUrl,
+ created_at,
+ created_at]
+ const rows = await postgres.query(text, params)
+ const addedOperator = rows[0]
+ return formatResult(addedOperator)
+ } catch (error) {
+ console.error(`There was an error in addOperator in useDB.ts: ${error}`)
+ throw new Error("There was an error adding the operator to the database")
}
+ }
- /**
+ /**
* Add a user.
* @param user - The user to add
* @param account - The user's accounts
* @returns The new user
*/
- async function addUser(user: User, account: Account) : Promise {
- const { address, createdAt, updatedAt, walletProvider } = user
- const text = 'INSERT INTO users (address, created_at, updated_at, wallet_provider) VALUES ($1, $2, $3, $4) RETURNING *;'
- const params = [address, createdAt, updatedAt, walletProvider]
- const rows = await postgres.query(text, params)
- const addedUser = rows[0]
- account.userId = addedUser.id
+ async function addUser(user: User, account: Account) : Promise {
+ const { address, createdAt, updatedAt, walletProvider } = user
+ const text = "INSERT INTO users (address, created_at, updated_at, wallet_provider) VALUES ($1, $2, $3, $4) RETURNING *;"
+ const params = [address,
+ createdAt,
+ updatedAt,
+ walletProvider]
+ const rows = await postgres.query(text, params)
+ const addedUser = rows[0]
+ account.userId = addedUser.id
- const accountAdded = await addAccount(account, createdAt)
- addedUser.accounts = [accountAdded]
+ const accountAdded = await addAccount(account, createdAt)
+ addedUser.accounts = [accountAdded]
- return formatResult(addedUser)
- }
+ return formatResult(addedUser)
+ }
- /**
+ /**
* Add a user account.
* @param user_id - The user's id
* @param account_id - The account's id
* @returns The new user account
*/
- async function addUserAccount(user_id: number, account_id: number) {
- const createdAt = new Date().toISOString()
- const text = 'INSERT INTO user_accounts (user_id, account_id, created_at) VALUES ($1, $2, $3) RETURNING *;'
- const params = [user_id, account_id, createdAt]
- const rows = await postgres.query(text, params)
- return rows[0]
- }
+ async function addUserAccount(user_id: number, account_id: number) {
+ const createdAt = new Date().toISOString()
+ const text = "INSERT INTO user_accounts (user_id, account_id, created_at) VALUES ($1, $2, $3) RETURNING *;"
+ const params = [user_id,
+ account_id,
+ createdAt]
+ const rows = await postgres.query(text, params)
+ return rows[0]
+ }
- /**
+ /**
* Get accounts by address.
* @param address - The account's address
* @returns The account if found, otherwise undefined
*/
- async function getAccounts(address: string): Promise {
- try {
- const text = 'SELECT * FROM accounts WHERE address = $1;'
- const params = [address.toLowerCase()]
- const rows = await postgres.query(text, params)
- return formatResult(rows) as Account[]
- } catch (error) {
- throw new Error('There was an error getting accounts from the database')
- }
+ async function getAccounts(address: string): Promise {
+ try {
+ const text = "SELECT * FROM accounts WHERE address = $1;"
+ const params = [address.toLowerCase()]
+ const rows = await postgres.query(text, params)
+ return formatResult(rows) as Account[]
+ } catch (error) {
+ throw new Error("There was an error getting accounts from the database")
}
+ }
- /**
+ /**
* Get nonce by address.
* @param address - The address user is using to sign in with ethereum
* @returns - The nonce if address is a pk on the table or undefined
*/
- async function getNonce(address:string) {
- try {
- const text = 'SELECT nonce FROM nonces WHERE address = $1;'
- const params = [address]
- const rows = await postgres.query(text, params)
- const { nonce } = rows[0]
- return formatResult(nonce)
- } catch (error) {
- throw new Error('There was an error getting nonce from the database')
- }
+ async function getNonce(address:string) {
+ try {
+ const text = "SELECT nonce FROM nonces WHERE address = $1;"
+ const params = [address]
+ const rows = await postgres.query(text, params)
+ const { nonce } = rows[0]
+ return formatResult(nonce)
+ } catch (error) {
+ throw new Error("There was an error getting nonce from the database")
}
+ }
- /**
+ /**
* Get a user by address.
* @param address - The user's address
* @returns The user if found, otherwise undefined
*/
- async function getUserByAddress(address: string): Promise {
- try {
- const text = `
+ async function getUserByAddress(address: string): Promise {
+ try {
+ const text = `
SELECT
u.*,
json_agg(
@@ -184,25 +197,25 @@ export default function useDB() {
GROUP BY
u.id
`
- const params = [address]
- const rows = await postgres.query(text, params)
- const user = rows[0]
- return formatResult(user) as UserWithAccountsAndOperators
- } catch (error) {
- console.log('ERROR in DB')
- throw new Error('There was an error getting user from the database')
- }
+ const params = [address]
+ const rows = await postgres.query(text, params)
+ const user = rows[0]
+ return formatResult(user) as UserWithAccountsAndOperators
+ } catch (error) {
+ console.log("ERROR in DB")
+ throw new Error("There was an error getting user from the database")
}
+ }
- /**
+ /**
* Get a user by id.
* @param id - The user's id
* @returns The user if found, otherwise undefined
* @throws Error if the user is not found
*/
- async function getUserById(id: string): Promise {
- try {
- const text = `
+ async function getUserById(id: string): Promise {
+ try {
+ const text = `
SELECT
u.*,
json_agg(
@@ -236,17 +249,17 @@ export default function useDB() {
GROUP BY
u.id
`
- const params = [id]
- const rows = await postgres.query(text, params)
- const user = rows[0]
- return formatResult(user) as UserWithAccountsAndOperators
- } catch (err) {
- throw new Error('There was an error getting user by id from the database')
- }
+ const params = [id]
+ const rows = await postgres.query(text, params)
+ const user = rows[0]
+ return formatResult(user) as UserWithAccountsAndOperators
+ } catch (err) {
+ throw new Error("There was an error getting user by id from the database")
}
+ }
- // TODO: Does this also delete any operator associated with the address associated with this account?
- /**
+ // TODO: Does this also delete any operator associated with the address associated with this account?
+ /**
* Remove an account.
* @param address - The account's address (pk)
* @param ownerAddress - The account's owner address
@@ -254,14 +267,17 @@ export default function useDB() {
* @param currency - The account's currency
* @returns The removed account if found, otherwise undefined
*/
- async function removeAccount({ address, currency, ownerAddress, walletProvider } : RemoveAccountOptions) {
- const text = 'DELETE FROM accounts WHERE address = $1 AND owner_address = $2 AND wallet_provider = $3 AND currency = $4 RETURNING *;'
- const params = [address, ownerAddress, walletProvider, currency]
- const rows = await postgres.query(text, params)
- return rows[0] as Account
- }
+ async function removeAccount({ address, currency, ownerAddress, walletProvider } : RemoveAccountOptions) {
+ const text = "DELETE FROM accounts WHERE address = $1 AND owner_address = $2 AND wallet_provider = $3 AND currency = $4 RETURNING *;"
+ const params = [address,
+ ownerAddress,
+ walletProvider,
+ currency]
+ const rows = await postgres.query(text, params)
+ return rows[0] as Account
+ }
- /**
+ /**
* Update user's address based on userId.
* @param userId - The user's id
* @param address - The user's new address
@@ -269,23 +285,25 @@ export default function useDB() {
* @throws Error if the user is not found
* @throws Error if the user's address is not updated
*/
- async function updateUserAddress(userId: number, address: string): Promise {
- try {
- const updated_at = new Date().toISOString()
- const text = 'UPDATE users SET address = $1, updated_at = $2 WHERE id = $3 RETURNING *;'
- const params = [address, updated_at, userId]
- const rows = await postgres.query(text, params)
- const user = rows[0]
- if (!user) throw new Error('User not found.')
- if (user.address !== address) throw new Error('User address not updated.')
- return user
- } catch (error) {
- console.error('There was an error updating the user address in updateUserAddress.', error)
- throw error
- }
+ async function updateUserAddress(userId: number, address: string): Promise {
+ try {
+ const updated_at = new Date().toISOString()
+ const text = "UPDATE users SET address = $1, updated_at = $2 WHERE id = $3 RETURNING *;"
+ const params = [address,
+ updated_at,
+ userId]
+ const rows = await postgres.query(text, params)
+ const user = rows[0]
+ if (!user) throw new Error("User not found.")
+ if (user.address !== address) throw new Error("User address not updated.")
+ return user
+ } catch (error) {
+ console.error("There was an error updating the user address in updateUserAddress.", error)
+ throw error
}
+ }
- /**
+ /**
* Update user's agreedToTermsOfService based on userId.
* @param userId - The user's id
* @param agreedToTermsOfService - The user's new agreedToTermsOfService
@@ -293,89 +311,91 @@ export default function useDB() {
* @throws Error if the user is not found
*
*/
- async function updateUserAgreedToTermsOfService(userId: number, agreedToTermsOfService: boolean): Promise {
- try {
- const updated_at = new Date().toISOString()
- const text = 'UPDATE users SET agreed_to_terms_of_service = $1, updated_at = $2 WHERE id = $3 RETURNING *;'
- const params = [agreedToTermsOfService, updated_at, userId]
- const rows = await postgres.query(text, params)
- const user = rows[0]
- if (!user) throw new Error('User not found.')
- return user
- } catch (error) {
- console.error('There was an error updating the user agreedToTermsOfService in updateUserAgreedToTermsOfService.', error)
- throw error
- }
+ async function updateUserAgreedToTermsOfService(userId: number, agreedToTermsOfService: boolean): Promise {
+ try {
+ const updated_at = new Date().toISOString()
+ const text = "UPDATE users SET agreed_to_terms_of_service = $1, updated_at = $2 WHERE id = $3 RETURNING *;"
+ const params = [agreedToTermsOfService,
+ updated_at,
+ userId]
+ const rows = await postgres.query(text, params)
+ const user = rows[0]
+ if (!user) throw new Error("User not found.")
+ return user
+ } catch (error) {
+ console.error("There was an error updating the user agreedToTermsOfService in updateUserAgreedToTermsOfService.", error)
+ throw error
}
+ }
- /**
+ /**
* Add or update nonce for an address.
* @param address - The address
* @returns A promise that resolves when the nonce is added or updated
*/
- async function upsertNonce(address: string): Promise {
- try {
- const nonce = generateNonce()
- const text = 'INSERT INTO nonces (address, nonce) VALUES ($1, $2) ON CONFLICT (address) DO UPDATE SET nonce = $2;'
- const params = [address, nonce]
- await postgres.query(text, params)
- return nonce
- } catch (error) {
- throw new Error('There was an error upserting nonce in the database')
- }
+ async function upsertNonce(address: string): Promise {
+ try {
+ const nonce = generateNonce()
+ const text = "INSERT INTO nonces (address, nonce) VALUES ($1, $2) ON CONFLICT (address) DO UPDATE SET nonce = $2;"
+ const params = [address, nonce]
+ await postgres.query(text, params)
+ return nonce
+ } catch (error) {
+ throw new Error("There was an error upserting nonce in the database")
}
+ }
- /**
+ /**
* Format data from a database result object (convert to camelCase).
* @param rows - The result date
* @returns The formatted data
*/
- function formatResult(obj: any) : any {
- if (typeof obj !== 'object' || obj === null) {
- // Return non-object values as is
- return obj
- }
+ function formatResult(obj: any) : any {
+ if (typeof obj !== "object" || obj === null) {
+ // Return non-object values as is
+ return obj
+ }
- if (Array.isArray(obj)) {
- // If obj is an array, map over each item and recursively call the function
- return obj.map(item => formatResult(item))
- }
+ if (Array.isArray(obj)) {
+ // If obj is an array, map over each item and recursively call the function
+ return obj.map(item => formatResult(item))
+ }
- const convertedObj: any = {}
+ const convertedObj: any = {}
- for (const key in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
- const camelCaseKey = camelCase(key)
- const value = obj[key]
+ for (const key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
+ const camelCaseKey = camelCase(key)
+ const value = obj[key]
- if (typeof value === 'object' && value !== null) {
- // Recursively convert nested objects
- convertedObj[camelCaseKey] = formatResult(value)
- } else {
- // Convert key to camel case and assign the value
- convertedObj[camelCaseKey] = value
- }
- }
+ if (typeof value === "object" && value !== null) {
+ // Recursively convert nested objects
+ convertedObj[camelCaseKey] = formatResult(value)
+ } else {
+ // Convert key to camel case and assign the value
+ convertedObj[camelCaseKey] = value
}
-
- return convertedObj
}
+ }
+
+ return convertedObj
+ }
- return {
- addAccount,
- addOperator,
- addUser,
- formatResult,
- getAccounts,
- getNonce,
- getUserByAddress,
- getUserById,
- removeAccount,
- updateUserAddress,
- updateUserAgreedToTermsOfService,
- upsertNonce
- }
+ return {
+ addAccount,
+ addOperator,
+ addUser,
+ formatResult,
+ getAccounts,
+ getNonce,
+ getUserByAddress,
+ getUserById,
+ removeAccount,
+ updateUserAddress,
+ updateUserAgreedToTermsOfService,
+ upsertNonce
+ }
}
\ No newline at end of file
diff --git a/services/users/src/providers/ethers.ts b/services/users/src/providers/ethers.ts
index 6c7ba3a82..ce4908bf0 100644
--- a/services/users/src/providers/ethers.ts
+++ b/services/users/src/providers/ethers.ts
@@ -1,43 +1,43 @@
-import { ethers } from 'ethers'
-import { LoginCredentials } from '@casimir/types'
+import { ethers } from "ethers"
+import { LoginCredentials } from "@casimir/types"
export default function useEthers() {
- /**
+ /**
* Generate nonce using EIP-4361 (Sign in with Ethereum)
*
* @returns {string} - The nonce
* @see https://eips.ethereum.org/EIPS/eip-4361
*/
- function generateNonce(length = 16): string {
- let result = ''
- const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
- for (let i = 0; i < length; i++) {
- result += characters.charAt(Math.floor(Math.random() * characters.length))
- }
- return result
+ function generateNonce(length = 16): string {
+ let result = ""
+ const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ for (let i = 0; i < length; i++) {
+ result += characters.charAt(Math.floor(Math.random() * characters.length))
}
+ return result
+ }
- /**
+ /**
* Verifies a user's login attempt with an address, message and signed message
*
* @param {LoginCredentials} loginCredentials - The user's address, message and signed message
* @returns {boolean} - The response from the login request
*/
- function verifyMessageSignature(loginCredentials: LoginCredentials): boolean {
- const { address, message, signedMessage } = loginCredentials
- try {
- if (!address.length || !message.length || !signedMessage.length) {
- return false
- } else {
- const recoveredAddress = ethers.utils.verifyMessage(message, signedMessage)
- return address.toLowerCase() === recoveredAddress.toLowerCase()
- }
- } catch (error) {
- console.log('error :>> ', error)
- return false
- }
+ function verifyMessageSignature(loginCredentials: LoginCredentials): boolean {
+ const { address, message, signedMessage } = loginCredentials
+ try {
+ if (!address.length || !message.length || !signedMessage.length) {
+ return false
+ } else {
+ const recoveredAddress = ethers.utils.verifyMessage(message, signedMessage)
+ return address.toLowerCase() === recoveredAddress.toLowerCase()
+ }
+ } catch (error) {
+ console.log("error :>> ", error)
+ return false
}
+ }
- return { generateNonce, verifyMessageSignature }
+ return { generateNonce, verifyMessageSignature }
}
diff --git a/services/users/src/providers/postgres.ts b/services/users/src/providers/postgres.ts
index 2ea5294e3..eea730f23 100644
--- a/services/users/src/providers/postgres.ts
+++ b/services/users/src/providers/postgres.ts
@@ -1,20 +1,20 @@
-import { Pool, PoolConfig } from 'pg'
+import { Pool, PoolConfig } from "pg"
/**
* Postgres database provider with pool client auto-connect-and-release
*/
export class Postgres {
- /** Postgres connection pool */
- private pool: Pool
+ /** Postgres connection pool */
+ private pool: Pool
- /**
+ /**
* Create a new Postgres database provider
*/
- constructor(poolConfig: PoolConfig) {
- this.pool = new Pool(poolConfig)
- }
+ constructor(poolConfig: PoolConfig) {
+ this.pool = new Pool(poolConfig)
+ }
- /**
+ /**
* Query the database
* @param text SQL query
* @param params Query parameters
@@ -26,11 +26,11 @@ export class Postgres {
* if (rows.length) console.log(rows[0].text) // Hello world!
* ```
*/
- async query(text: string, params: any[] = []) {
- const client = await this.pool.connect()
- const res = await client.query(text, params)
- client.release()
- const { rows } = res
- return rows
- }
+ async query(text: string, params: any[] = []) {
+ const client = await this.pool.connect()
+ const res = await client.query(text, params)
+ client.release()
+ const { rows } = res
+ return rows
+ }
}
\ No newline at end of file
diff --git a/services/users/src/routes/analytics.ts b/services/users/src/routes/analytics.ts
index 90a1442f7..fedf4c32c 100644
--- a/services/users/src/routes/analytics.ts
+++ b/services/users/src/routes/analytics.ts
@@ -1,43 +1,43 @@
-import express from 'express'
-import { verifySession } from 'supertokens-node/recipe/session/framework/express'
-import { SessionRequest } from 'supertokens-node/framework/express'
-import useDB from '../providers/db'
-import { query } from 'athena-query'
-import { UserWithAccountsAndOperators } from '@casimir/types'
+import express from "express"
+import { verifySession } from "supertokens-node/recipe/session/framework/express"
+import { SessionRequest } from "supertokens-node/framework/express"
+import useDB from "../providers/db"
+import { query } from "athena-query"
+import { UserWithAccountsAndOperators } from "@casimir/types"
const router = express.Router()
const { formatResult, getUserById } = useDB()
-router.get('/', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- console.log('got to athena route')
- // Two tables
- // Events
- // any events on the blockchain (including the block itself)
- // so all txs + 1 for block
- // Athena currently has all of this Goerli tx data
- // Actions <-- this is the one we want for Overview Chart
- // contract data (StakeDeposited, Withdrawal, etc.)
- // includes tx data (outgoing, incoming, etc.)
- const id = req.session?.getUserId() as string
- const userId = id.toString()
- const user = await getUserById(userId)
- const { accounts } = user as UserWithAccountsAndOperators
- const addresses = accounts.map((account) => account.address)
- const database = 'casimir_analytics_database_dev'
- const athenaTable = 'casimir_analytics_action_table_dev1'
- const opt = {
- profile: process.env.AWS_PROFILE as string,
- database,
- // output: 's3://casimir-analytics-wallet-bucket-dev1/',
- output: 's3://casimir-analytics-action-bucket-dev1/',
- workgroup: 'primary',
- catalog: 'AwsDataCatalog',
- backoff: 1000,
- region: 'us-east-2',
- }
- /**
+router.get("/", verifySession(), async (req: SessionRequest, res: express.Response) => {
+ try {
+ console.log("got to athena route")
+ // Two tables
+ // Events
+ // any events on the blockchain (including the block itself)
+ // so all txs + 1 for block
+ // Athena currently has all of this Goerli tx data
+ // Actions <-- this is the one we want for Overview Chart
+ // contract data (StakeDeposited, Withdrawal, etc.)
+ // includes tx data (outgoing, incoming, etc.)
+ const id = req.session?.getUserId() as string
+ const userId = id.toString()
+ const user = await getUserById(userId)
+ const { accounts } = user as UserWithAccountsAndOperators
+ const addresses = accounts.map((account) => account.address)
+ const database = "casimir_analytics_database_dev"
+ const athenaTable = "casimir_analytics_action_table_dev1"
+ const opt = {
+ profile: process.env.AWS_PROFILE as string,
+ database,
+ // output: 's3://casimir-analytics-wallet-bucket-dev1/',
+ output: "s3://casimir-analytics-action-bucket-dev1/",
+ workgroup: "primary",
+ catalog: "AwsDataCatalog",
+ backoff: 1000,
+ region: "us-east-2",
+ }
+ /**
* Can query the following properties:
* wallet_address
* wallet_balance
@@ -48,44 +48,44 @@ router.get('/', verifySession(), async (req: SessionRequest, res: express.Respon
* price
* gas_fee
*/
- // TODO: Include type in WHERE to decrease query time
- // const testStmt = 'SELECT * FROM "casimir_analytics_action_table_dev1" limit 10;'
- // const stmt = `
- // SELECT * FROM ${database}.${athenaTable}
- // WHERE address IN (${addresses.map((address: string) => `'${address}'`).join(',')})
- // ORDER BY received_at DESC
- // LIMIT 100;
- // `
- // const { rows } = await query(testStmt, opt)
- // console.log('rows :>> ', rows)
- console.log('addresses :>> ', addresses)
- const stmt = `SELECT * FROM "casimir_analytics_database_dev"."casimir_analytics_action_table_dev1"
- WHERE "address" IN (${addresses.map((address: string) => `'${address}'`).join(',')})
+ // TODO: Include type in WHERE to decrease query time
+ // const testStmt = 'SELECT * FROM "casimir_analytics_action_table_dev1" limit 10;'
+ // const stmt = `
+ // SELECT * FROM ${database}.${athenaTable}
+ // WHERE address IN (${addresses.map((address: string) => `'${address}'`).join(',')})
+ // ORDER BY received_at DESC
+ // LIMIT 100;
+ // `
+ // const { rows } = await query(testStmt, opt)
+ // console.log('rows :>> ', rows)
+ console.log("addresses :>> ", addresses)
+ const stmt = `SELECT * FROM "casimir_analytics_database_dev"."casimir_analytics_action_table_dev1"
+ WHERE "address" IN (${addresses.map((address: string) => `'${address}'`).join(",")})
ORDER BY received_at DESC
LIMIT 100;`
- const [columns, rows ] = await query(stmt, {
- database: 'casimir_analytics_database_dev',
- workgroup: 'primary',
- profile: 'consensus-networks-dev',
- output: 's3://cms-lds-agg/cms_hcf_aggregates/',
- catalog: 'AwsDataCatalog',
- backoff: 1000,
- region: 'us-east-2',
- })
- const data = formatResult(rows)
- console.log('data :>> ', data)
- res.status(200).json({
- error: false,
- message: 'Analytics data successfully fetched.',
- data
- })
- } catch (err) {
- console.error('err :>> ', err)
- res.status(500).json({
- error: true,
- message: 'Server error.'
- })
- }
+ const [columns, rows ] = await query(stmt, {
+ database: "casimir_analytics_database_dev",
+ workgroup: "primary",
+ profile: "consensus-networks-dev",
+ output: "s3://cms-lds-agg/cms_hcf_aggregates/",
+ catalog: "AwsDataCatalog",
+ backoff: 1000,
+ region: "us-east-2",
+ })
+ const data = formatResult(rows)
+ console.log("data :>> ", data)
+ res.status(200).json({
+ error: false,
+ message: "Analytics data successfully fetched.",
+ data
+ })
+ } catch (err) {
+ console.error("err :>> ", err)
+ res.status(500).json({
+ error: true,
+ message: "Server error."
+ })
+ }
})
export default router
\ No newline at end of file
diff --git a/services/users/src/routes/auth.ts b/services/users/src/routes/auth.ts
index bc4043ec1..b1e01af38 100644
--- a/services/users/src/routes/auth.ts
+++ b/services/users/src/routes/auth.ts
@@ -1,142 +1,142 @@
-import express from 'express'
-import useDB from '../providers/db'
-import Session from 'supertokens-node/recipe/session'
-import { verifySession } from 'supertokens-node/recipe/session/framework/express'
-import { SessionRequest } from 'supertokens-node/framework/express'
-import useEthers from '../providers/ethers'
-import { Account, User } from '@casimir/types'
+import express from "express"
+import useDB from "../providers/db"
+import Session from "supertokens-node/recipe/session"
+import { verifySession } from "supertokens-node/recipe/session/framework/express"
+import { SessionRequest } from "supertokens-node/framework/express"
+import useEthers from "../providers/ethers"
+import { Account, User } from "@casimir/types"
const { verifyMessageSignature } = useEthers()
const { addUser, getNonce, getUserByAddress, upsertNonce } = useDB()
const router = express.Router()
-router.post('/nonce', async (req: express.Request, res: express.Response) => {
- try {
- const { address } = req.body
- const nonce = await upsertNonce(address)
- if (nonce) {
- res.setHeader('Content-Type', 'text/plain')
- res.status(200)
- res.json({
- error: false,
- message: 'Nonce retrieved',
- data: nonce
- })
- }
- } catch (error: any) {
- res.status(500)
- res.json({
- error: true,
- message: error.message || 'Error getting nonce'
- })
+router.post("/nonce", async (req: express.Request, res: express.Response) => {
+ try {
+ const { address } = req.body
+ const nonce = await upsertNonce(address)
+ if (nonce) {
+ res.setHeader("Content-Type", "text/plain")
+ res.status(200)
+ res.json({
+ error: false,
+ message: "Nonce retrieved",
+ data: nonce
+ })
}
+ } catch (error: any) {
+ res.status(500)
+ res.json({
+ error: true,
+ message: error.message || "Error getting nonce"
+ })
+ }
})
-router.post('/login', async (req: express.Request, res: express.Response) => {
- try {
- const { body } = req
- const loginCredentials = body
- const { provider, address, currency, message, signedMessage } = loginCredentials
- const { parsedDomain, parsedNonce } = parseMessage(message)
- const verifyDomain = parsedDomain ? verifyMessageDomain(parsedDomain) : false
- const verifyNonce = parsedNonce ? await verifyMessageNonce(address, parsedNonce) : false
- const verifySignature = verifyMessageSignature(loginCredentials)
- const verificationError = !verifyDomain ? 'domain' : !verifyNonce ? 'nonce' : !verifySignature ? 'signature' : false
- if (verificationError) {
- return res.status(422).json({
- error: true,
- message: `Invalid ${verificationError}.`,
- })
- } else {
- const user = await getUserByAddress(address)
- if (!user) { // signup
- console.log('SIGNING UP!')
- const now = new Date().toISOString()
- const newUser = {
- address,
- createdAt: now,
- updatedAt: now,
- walletProvider: provider,
- } as User
- const account = {
- address,
- currency,
- walletProvider: provider,
- } as Account
+router.post("/login", async (req: express.Request, res: express.Response) => {
+ try {
+ const { body } = req
+ const loginCredentials = body
+ const { provider, address, currency, message, signedMessage } = loginCredentials
+ const { parsedDomain, parsedNonce } = parseMessage(message)
+ const verifyDomain = parsedDomain ? verifyMessageDomain(parsedDomain) : false
+ const verifyNonce = parsedNonce ? await verifyMessageNonce(address, parsedNonce) : false
+ const verifySignature = verifyMessageSignature(loginCredentials)
+ const verificationError = !verifyDomain ? "domain" : !verifyNonce ? "nonce" : !verifySignature ? "signature" : false
+ if (verificationError) {
+ return res.status(422).json({
+ error: true,
+ message: `Invalid ${verificationError}.`,
+ })
+ } else {
+ const user = await getUserByAddress(address)
+ if (!user) { // signup
+ console.log("SIGNING UP!")
+ const now = new Date().toISOString()
+ const newUser = {
+ address,
+ createdAt: now,
+ updatedAt: now,
+ walletProvider: provider,
+ } as User
+ const account = {
+ address,
+ currency,
+ walletProvider: provider,
+ } as Account
- const addUserResult = await addUser(newUser, account)
- if (addUserResult?.address !== address) {
- res.setHeader('Content-Type', 'application/json')
- res.status(500)
- res.json({
- error: true,
- message: 'Problem creating new user',
- })
- } else {
- const id = addUserResult?.id.toString() as string
- await Session.createNewSession(req, res, id)
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- error: false,
- message: 'Sign Up Successful'
- })
- }
- } else { // login
- console.log('LOGGING IN!')
- const response = verifyMessageSignature({ address, currency, message, signedMessage, provider })
- upsertNonce(address)
- const user = await getUserByAddress(address)
- const userId = user?.id.toString() as string
- response ? await Session.createNewSession(req, res, userId) : null
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- error: false,
- message: response ? 'Login successful' : 'Login failed',
- })
- }
+ const addUserResult = await addUser(newUser, account)
+ if (addUserResult?.address !== address) {
+ res.setHeader("Content-Type", "application/json")
+ res.status(500)
+ res.json({
+ error: true,
+ message: "Problem creating new user",
+ })
+ } else {
+ const id = addUserResult?.id.toString() as string
+ await Session.createNewSession(req, res, id)
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ error: false,
+ message: "Sign Up Successful"
+ })
}
- } catch (error: any) {
- console.log('error in /login :>> ', error)
- res.status(500)
+ } else { // login
+ console.log("LOGGING IN!")
+ const response = verifyMessageSignature({ address, currency, message, signedMessage, provider })
+ upsertNonce(address)
+ const user = await getUserByAddress(address)
+ const userId = user?.id.toString() as string
+ response ? await Session.createNewSession(req, res, userId) : null
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
res.json({
- error: true,
- message: error.message || 'Error logging in'
+ error: false,
+ message: response ? "Login successful" : "Login failed",
})
+ }
}
+ } catch (error: any) {
+ console.log("error in /login :>> ", error)
+ res.status(500)
+ res.json({
+ error: true,
+ message: error.message || "Error logging in"
+ })
+ }
})
function parseDomain(msg: string) {
- const uri = msg.split('URI:')[1].split('Version:')[0].trim()
- const parsedUri = uri.split('://')[1].split('/')[0]
- const domain = msg.split('wants you to sign in with your Ethereum account:')[0].trim()
- return domain === parsedUri ? domain : null
+ const uri = msg.split("URI:")[1].split("Version:")[0].trim()
+ const parsedUri = uri.split("://")[1].split("/")[0]
+ const domain = msg.split("wants you to sign in with your Ethereum account:")[0].trim()
+ return domain === parsedUri ? domain : null
}
function parseMessage(msg: string) {
- const parsedDomain = parseDomain(msg)
- const parsedNonce = parseNonce(msg)
- return { parsedDomain, parsedNonce }
+ const parsedDomain = parseDomain(msg)
+ const parsedNonce = parseNonce(msg)
+ return { parsedDomain, parsedNonce }
}
function parseNonce(msg: string) {
- return msg.split('Nonce:')[1].split('Issued At:')[0].trim()
+ return msg.split("Nonce:")[1].split("Issued At:")[0].trim()
}
function verifyMessageDomain(domain: string): boolean {
- const url = domain.includes('localhost') ? `http://${domain}` : `https://${domain}`
- if (process.env.WEB_URL) return url === process.env.WEB_URL
- return url === 'http://localhost:3001'
+ const url = domain.includes("localhost") ? `http://${domain}` : `https://${domain}`
+ if (process.env.WEB_URL) return url === process.env.WEB_URL
+ return url === "http://localhost:3001"
}
async function verifyMessageNonce(address: string, msgNonce: string) : Promise {
- try {
- const dbNonce = await getNonce(address)
- return msgNonce === dbNonce
- } catch (error) {
- throw new Error('Problem verifying message nonce')
- }
+ try {
+ const dbNonce = await getNonce(address)
+ return msgNonce === dbNonce
+ } catch (error) {
+ throw new Error("Problem verifying message nonce")
+ }
}
export default router
\ No newline at end of file
diff --git a/services/users/src/routes/health.ts b/services/users/src/routes/health.ts
index 96de84e2d..3bb2ee358 100644
--- a/services/users/src/routes/health.ts
+++ b/services/users/src/routes/health.ts
@@ -1,9 +1,9 @@
-import express from 'express'
+import express from "express"
const router = express.Router()
-router.get('/', (_req, res) => {
- res.status(200).send('OK')
+router.get("/", (_req, res) => {
+ res.status(200).send("OK")
})
export default router
\ No newline at end of file
diff --git a/services/users/src/routes/user.ts b/services/users/src/routes/user.ts
index b3787fbd0..39041ba72 100644
--- a/services/users/src/routes/user.ts
+++ b/services/users/src/routes/user.ts
@@ -1,259 +1,259 @@
-import express from 'express'
-import { verifySession } from 'supertokens-node/recipe/session/framework/express'
-import { SessionRequest } from 'supertokens-node/framework/express'
-import useDB from '../providers/db'
-import { UserWithAccountsAndOperators } from '@casimir/types'
+import express from "express"
+import { verifySession } from "supertokens-node/recipe/session/framework/express"
+import { SessionRequest } from "supertokens-node/framework/express"
+import useDB from "../providers/db"
+import { UserWithAccountsAndOperators } from "@casimir/types"
const router = express.Router()
const { addAccount, addOperator, getAccounts, getUserByAddress, getUserById, updateUserAddress, updateUserAgreedToTermsOfService, removeAccount } = useDB()
-router.get('/', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- const id = req.session?.getUserId() as string
- const user = await getUserById(id)
- const message = user ? 'User found' : 'User not found'
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message,
- error: false,
- user
- })
- } catch (err) {
- res.status(500)
- res.json({
- message: 'Error getting user',
- error: true,
- user: null
- })
- }
+router.get("/", verifySession(), async (req: SessionRequest, res: express.Response) => {
+ try {
+ const id = req.session?.getUserId() as string
+ const user = await getUserById(id)
+ const message = user ? "User found" : "User not found"
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message,
+ error: false,
+ user
+ })
+ } catch (err) {
+ res.status(500)
+ res.json({
+ message: "Error getting user",
+ error: true,
+ user: null
+ })
+ }
})
-router.post('/add-sub-account', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- console.log('ADDING ACCOUNT!')
- const { account, id } = req.body
- const { ownerAddress } = account
- const userId = id.toString()
- const userSessionId = req.session?.getUserId()
- const validatedUserId = validateUserId(userSessionId, userId)
- console.log('validatedUserId :>> ', validatedUserId)
- if (!validatedUserId) {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Address does not match session',
- error: true,
- data: null
- })
- }
- await addAccount(account)
- const user = await getUserByAddress(ownerAddress)
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Account added',
- error: false,
- data: user
- })
- } catch (err) {
- res.status(500)
- res.json({
- message: 'Error adding account',
- error: true,
- data: null
- })
+router.post("/add-sub-account", verifySession(), async (req: SessionRequest, res: express.Response) => {
+ try {
+ console.log("ADDING ACCOUNT!")
+ const { account, id } = req.body
+ const { ownerAddress } = account
+ const userId = id.toString()
+ const userSessionId = req.session?.getUserId()
+ const validatedUserId = validateUserId(userSessionId, userId)
+ console.log("validatedUserId :>> ", validatedUserId)
+ if (!validatedUserId) {
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "Address does not match session",
+ error: true,
+ data: null
+ })
}
+ await addAccount(account)
+ const user = await getUserByAddress(ownerAddress)
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "Account added",
+ error: false,
+ data: user
+ })
+ } catch (err) {
+ res.status(500)
+ res.json({
+ message: "Error adding account",
+ error: true,
+ data: null
+ })
+ }
})
-router.post('/add-operator', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- console.log('ADDING OPERATOR!')
- const { address, nodeUrl } = req.body
- const userId = parseInt(req.session?.getUserId() as string)
- const accounts = await getAccounts(address)
- const userAccount = accounts.find(account => parseInt(account.userId) === userId)
- const accountId = userAccount?.id as number
- await addOperator({ accountId, nodeUrl, userId })
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Operator added',
- error: false
- })
- } catch (err) {
- res.status(500)
- res.json({
- message: 'Error adding operator',
- error: true
- })
- }
+router.post("/add-operator", verifySession(), async (req: SessionRequest, res: express.Response) => {
+ try {
+ console.log("ADDING OPERATOR!")
+ const { address, nodeUrl } = req.body
+ const userId = parseInt(req.session?.getUserId() as string)
+ const accounts = await getAccounts(address)
+ const userAccount = accounts.find(account => parseInt(account.userId) === userId)
+ const accountId = userAccount?.id as number
+ await addOperator({ accountId, nodeUrl, userId })
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "Operator added",
+ error: false
+ })
+ } catch (err) {
+ res.status(500)
+ res.json({
+ message: "Error adding operator",
+ error: true
+ })
+ }
})
-router.get('/check-if-primary-address-exists/:address', async (req: express.Request, res: express.Response) => {
- try {
- const { params } = req
- const { address } = params
- const user = await getUserByAddress(address)
- console.log('user in check-if-primary-.....:>> ', user)
- const userAddress = user?.address
- const userProvider = user?.walletProvider
- const sameAddress = userAddress === address
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- error: false,
- message: 'Successfully checked if primary address exists',
- data: {
- sameAddress,
- walletProvider: userProvider
- }
- })
- } catch (error: any) {
- const { message } = error
- res.setHeader('Content-Type', 'application/json')
- res.status(500)
- res.json({
- error: true,
- message: message || 'Problem checking if primary address exists'
- })
- }
+router.get("/check-if-primary-address-exists/:address", async (req: express.Request, res: express.Response) => {
+ try {
+ const { params } = req
+ const { address } = params
+ const user = await getUserByAddress(address)
+ console.log("user in check-if-primary-.....:>> ", user)
+ const userAddress = user?.address
+ const userProvider = user?.walletProvider
+ const sameAddress = userAddress === address
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ error: false,
+ message: "Successfully checked if primary address exists",
+ data: {
+ sameAddress,
+ walletProvider: userProvider
+ }
+ })
+ } catch (error: any) {
+ const { message } = error
+ res.setHeader("Content-Type", "application/json")
+ res.status(500)
+ res.json({
+ error: true,
+ message: message || "Problem checking if primary address exists"
+ })
+ }
})
-router.get('/check-secondary-address/:address', async (req: express.Request, res: express.Response) => {
- try {
- const { params } = req
- const { address } = params
- const accounts = await getAccounts(address)
- const users = await Promise.all(accounts.map(async account => {
- const { userId } = account
- const user = await getUserById(userId)
- const { address, walletProvider } = user as UserWithAccountsAndOperators
- return {
- address: maskAddress(address),
- walletProvider,
- }
- }))
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- error: false,
- message: 'Successfully checked secondary address',
- data: users
- })
- } catch (error: any) {
- console.log('error in /check-secondary-address :>> ', error)
- res.setHeader('Content-Type', 'application/json')
- res.status(500)
- res.json({
- error: true,
- message: error.message || 'Problem checking secondary address'
- })
- }
+router.get("/check-secondary-address/:address", async (req: express.Request, res: express.Response) => {
+ try {
+ const { params } = req
+ const { address } = params
+ const accounts = await getAccounts(address)
+ const users = await Promise.all(accounts.map(async account => {
+ const { userId } = account
+ const user = await getUserById(userId)
+ const { address, walletProvider } = user as UserWithAccountsAndOperators
+ return {
+ address: maskAddress(address),
+ walletProvider,
+ }
+ }))
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ error: false,
+ message: "Successfully checked secondary address",
+ data: users
+ })
+ } catch (error: any) {
+ console.log("error in /check-secondary-address :>> ", error)
+ res.setHeader("Content-Type", "application/json")
+ res.status(500)
+ res.json({
+ error: true,
+ message: error.message || "Problem checking secondary address"
+ })
+ }
})
-router.post('/remove-sub-account', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- console.log('REMOVING ACCOUNT!')
- const { address, currency, id, ownerAddress, walletProvider } = req.body
- const userId = id.toString()
- const userSessionId = req.session?.getUserId()
- const validatedAddress = validateUserId(userSessionId, userId)
- if (!validatedAddress) {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Address does not match session',
- error: true,
- data: null
- })
- return
- }
- const accountRemoved = await removeAccount({ address, currency, ownerAddress, walletProvider })
- const user = await getUserByAddress(ownerAddress)
+router.post("/remove-sub-account", verifySession(), async (req: SessionRequest, res: express.Response) => {
+ try {
+ console.log("REMOVING ACCOUNT!")
+ const { address, currency, id, ownerAddress, walletProvider } = req.body
+ const userId = id.toString()
+ const userSessionId = req.session?.getUserId()
+ const validatedAddress = validateUserId(userSessionId, userId)
+ if (!validatedAddress) {
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "Address does not match session",
+ error: true,
+ data: null
+ })
+ return
+ }
+ const accountRemoved = await removeAccount({ address, currency, ownerAddress, walletProvider })
+ const user = await getUserByAddress(ownerAddress)
- if (accountRemoved) {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Account removed',
- error: false,
- data: user
- })
- } else {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Account not found',
- error: true,
- data: user
- })
- }
- } catch (err) {
- console.log('err :>> ', err)
- res.status(500)
- res.json({
- message: 'Error adding account',
- error: true
- })
+ if (accountRemoved) {
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "Account removed",
+ error: false,
+ data: user
+ })
+ } else {
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "Account not found",
+ error: true,
+ data: user
+ })
}
+ } catch (err) {
+ console.log("err :>> ", err)
+ res.status(500)
+ res.json({
+ message: "Error adding account",
+ error: true
+ })
+ }
})
// TODO: Think through handling changing primary address with SuperTokens Sessions.
-router.put('/update-primary-account', verifySession(), async (req: SessionRequest, res: express.Response) => {
- const { userId } = req.body
- let { updatedAddress } = req.body
- updatedAddress = updatedAddress.toLowerCase()
+router.put("/update-primary-account", verifySession(), async (req: SessionRequest, res: express.Response) => {
+ const { userId } = req.body
+ let { updatedAddress } = req.body
+ updatedAddress = updatedAddress.toLowerCase()
- const user = await updateUserAddress(userId, updatedAddress)
- if (!user) {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'User not found',
- error: true,
- data: null
- })
- } else {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Primary account updated',
- error: false,
- data: user
- })
- }
+ const user = await updateUserAddress(userId, updatedAddress)
+ if (!user) {
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "User not found",
+ error: true,
+ data: null
+ })
+ } else {
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "Primary account updated",
+ error: false,
+ data: user
+ })
+ }
})
-router.put('/update-user-agreement/:userId', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- const { agreed } = req.body
- const { userId } = req.params
- const userID = parseInt(userId)
- const user = await updateUserAgreedToTermsOfService(userID, agreed)
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'User agreement updated',
- error: false,
- data: user
- })
- } catch (err) {
- res.status(500)
- res.json({
- message: 'Error updating user agreement',
- error: true,
- data: null
- })
- }
+router.put("/update-user-agreement/:userId", verifySession(), async (req: SessionRequest, res: express.Response) => {
+ try {
+ const { agreed } = req.body
+ const { userId } = req.params
+ const userID = parseInt(userId)
+ const user = await updateUserAgreedToTermsOfService(userID, agreed)
+ res.setHeader("Content-Type", "application/json")
+ res.status(200)
+ res.json({
+ message: "User agreement updated",
+ error: false,
+ data: user
+ })
+ } catch (err) {
+ res.status(500)
+ res.json({
+ message: "Error updating user agreement",
+ error: true,
+ data: null
+ })
+ }
})
function maskAddress(address: string) {
- return address.slice(0, 6) + '...' + address.slice(-4)
+ return address.slice(0, 6) + "..." + address.slice(-4)
}
function validateUserId(userSessionId:string | undefined, userId:string) {
- return userSessionId === userId
+ return userSessionId === userId
}
export default router
\ No newline at end of file
diff --git a/services/users/src/sessions.config.ts b/services/users/src/sessions.config.ts
index 1b7f6016b..0289e6690 100644
--- a/services/users/src/sessions.config.ts
+++ b/services/users/src/sessions.config.ts
@@ -1,19 +1,19 @@
-import Session from 'supertokens-node/recipe/session'
-import { TypeInput } from 'supertokens-node/types'
+import Session from "supertokens-node/recipe/session"
+import { TypeInput } from "supertokens-node/types"
export const SuperTokensBackendConfig: TypeInput = {
- framework: 'express',
- supertokens: {
- // SuperTokens core (temporary) host
- connectionURI: process.env.SESSIONS_HOST || 'https://try.supertokens.com',
- apiKey: process.env.SESSIONS_KEY || ''
- },
- appInfo: {
- appName: process.env.PROJECT || 'casimir',
- apiDomain: process.env.USERS_URL || 'http://localhost:4000',
- websiteDomain: process.env.WEB_URL || 'http://localhost:3001'
- },
- recipeList: [
- Session.init(),
- ]
+ framework: "express",
+ supertokens: {
+ // SuperTokens core (temporary) host
+ connectionURI: process.env.SESSIONS_HOST || "https://try.supertokens.com",
+ apiKey: process.env.SESSIONS_KEY || ""
+ },
+ appInfo: {
+ appName: process.env.PROJECT || "casimir",
+ apiDomain: process.env.USERS_URL || "http://localhost:4000",
+ websiteDomain: process.env.WEB_URL || "http://localhost:3001"
+ },
+ recipeList: [
+ Session.init(),
+ ]
}