-import { ref, onMounted, onUnmounted } from 'vue'
-import VueFeather from 'vue-feather'
+import { ref, onMounted, onUnmounted } from "vue"
+import VueFeather from "vue-feather"
-const avgAPY = ref('5.2%')
+const avgAPY = ref("5.2%")
const openTimeFrameOptions = ref(false)
-const selectedTimeframe = ref('Last Week')
+const selectedTimeframe = ref("Last Week")
const timeframeOptions = ref(
[
- 'Last Week',
- '1 Month',
- '6 Months',
- '12 Months',
- 'Historical'
+ "Last Week",
+ "1 Month",
+ "6 Months",
+ "12 Months",
+ "Historical"
]
)
// eslint-disable-next-line no-undef
const props = defineProps({
viewId: {
- type: String,
- required: true,
+ type: String,
+ required: true,
}
})
@@ -28,10 +28,10 @@ const handleOutsideClick = (event: any) => {
const staking_avg_timeframe_button = document.getElementById(`${props.viewId}_staking_avg_timeframe_button`)
const staking_avg_timeframe_options = document.getElementById(`${props.viewId}_staking_avg_timeframe_options`)
- if(staking_avg_timeframe_options && staking_avg_timeframe_button){
- if(openTimeFrameOptions.value) {
- if(!staking_avg_timeframe_options.contains(event.target)){
- if(!staking_avg_timeframe_button.contains(event.target)){
+ if (staking_avg_timeframe_options && staking_avg_timeframe_button) {
+ if (openTimeFrameOptions.value) {
+ if (!staking_avg_timeframe_options.contains(event.target)) {
+ if (!staking_avg_timeframe_button.contains(event.target)) {
openTimeFrameOptions.value = false
}
}
@@ -40,11 +40,11 @@ const handleOutsideClick = (event: any) => {
}
onMounted(() => {
- window.addEventListener('click', handleOutsideClick)
+ window.addEventListener("click", handleOutsideClick)
})
onUnmounted(() =>{
- window.removeEventListener('click', handleOutsideClick)
+ window.removeEventListener("click", handleOutsideClick)
})
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..ce25ab854 100644
--- a/common/uniswap/src/providers/factory.ts
+++ b/common/uniswap/src/providers/factory.ts
@@ -1,34 +1,36 @@
-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..389b37957 100644
--- a/contracts/ethereum/helpers/oracle.ts
+++ b/contracts/ethereum/helpers/oracle.ts
@@ -1,297 +1,309 @@
-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')
+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")
- 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')
+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 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 unformattedFeeAmount = (Number(ethers.utils.formatEther(requiredFee.sub(oldCluster.balance))) * Number(price)).toPrecision(9)
+ const feeAmount = ethers.utils.parseEther(unformattedFeeAmount)
+ 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
+export async function reportCompletedExitsHandler(
+ { manager, views, signer, args }: { manager: CasimirManager, views: CasimirViews, signer: SignerWithAddress, args: Record }
+) {
+ 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..004a091ac 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,247 @@ 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 formattedBeaconBalance = ethers.utils.formatEther(latestBeaconBalance)
+ const nextBeaconBalance = round(
+ parseFloat(formattedBeaconBalance) + 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..558b55bc4 100644
--- a/contracts/ethereum/test/fixtures/shared.ts
+++ b/contracts/ethereum/test/fixtures/shared.ts
@@ -1,80 +1,83 @@
-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 +86,835 @@ 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 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 }
+ 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()
+
+ 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
- })
-
- 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 }
+ 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
+ })
+
+ 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)
+ 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: 126,
- sweptBalance: 0,
- activatedDeposits: 0,
- forcedExits: 0,
- completedExits: 0,
- 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
})
await runUpkeep({ donTransmitter, upkeep })
+ nextBeaconBalance += 1
+ }
- 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 }
+ 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 }
+ 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..408165c98 100644
--- a/contracts/ethereum/test/operators.ts
+++ b/contracts/ethereum/test/operators.ts
@@ -1,138 +1,151 @@
-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..268c07085 100644
--- a/services/functions/src/providers/handlers.ts
+++ b/services/functions/src/providers/handlers.ts
@@ -1,51 +1,53 @@
-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..d27270e36 100644
--- a/services/oracle/scripts/dev.ts
+++ b/services/oracle/scripts/dev.ts
@@ -1,48 +1,49 @@
-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..40a781aa3 100644
--- a/services/oracle/src/providers/handlers.ts
+++ b/services/oracle/src/providers/handlers.ts
@@ -1,459 +1,478 @@
-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 operatorCollateral = parseInt(ethers.utils.formatEther(operator.collateral))
+ const operatorPoolCount = parseInt(operator.poolCount.toString())
+ const availableCollateral = operatorCollateral - operatorPoolCount
+ 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 formattedRequiredFee = Number(ethers.utils.formatEther(requiredFee)) * 0.99
+ const minTokenAmount = ethers.utils.parseEther((formattedRequiredFee).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 operatorCollateral = parseInt(ethers.utils.formatEther(operator.collateral))
+ const operatorPoolCount = parseInt(operator.poolCount.toString())
+ const availableCollateral = operatorCollateral - operatorPoolCount
+ 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 requiredFeeSubOldClusterBalance = requiredFee.sub(oldCluster.balance)
+ const feeAmount = ethers.utils.parseEther((Number(ethers.utils.formatEther(requiredFeeSubOldClusterBalance)) * 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..fa4cb6fe3 100644
--- a/services/users/scripts/db.ts
+++ b/services/users/scripts/db.ts
@@ -1,68 +1,74 @@
-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..19f347bc2 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,151 @@ 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 +199,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 +251,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 +269,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 +287,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 +313,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..95169e6f5 100644
--- a/services/users/src/routes/user.ts
+++ b/services/users/src/routes/user.ts
@@ -1,259 +1,268 @@
-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()
+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(),
+ ]
}