Skip to content

Commit

Permalink
Merge pull request #278 from consensusnetworks/bug/stake
Browse files Browse the repository at this point in the history
Bug/stake
  • Loading branch information
shanejearley authored Mar 7, 2023
2 parents 9aaf6f6 + 67e683b commit 3e76b03
Show file tree
Hide file tree
Showing 12 changed files with 2,189 additions and 4,492 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
"typescript"
],
"css.lint.unknownAtRules": "ignore",
"jupyter.notebookFileRoot": "${fileDirname}"
"jupyter.notebookFileRoot": "${fileDirname}",
"volar.inlayHints.eventArgumentInInlineHandlers": false
}
22 changes: 11 additions & 11 deletions apps/web/src/components/Wallet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
<div class="network-div w-100 mx-8">
Choose Network
<div class="choose-network flex">
<button
@click="switchNetwork('5')"
>
<button @click="switchNetwork('5')">
Switch MetaMask to Goerli Network
</button>
<button
Expand Down Expand Up @@ -50,21 +48,21 @@
</button>
<ul>
<li
v-for="(pool, index) in pools"
v-for="(pool, index) in user?.pools"
:key="index"
>
<p>Pool ID: #{{ pool.id }}</p>
<p>Your Stake: {{ pool.userStake }} ETH</p>
<p>Your Rewards: {{ pool.userRewards }} ETH</p>
<p>Total Stake: {{ pool.totalStake }} ETH</p>
<p>Total Rewards: {{ pool.totalRewards }} ETH</p>
<p>Total Stake: {{ pool.stake }} ETH</p>
<p>Total Rewards: {{ pool.rewards }} ETH</p>
</li>
</ul>
<input
v-model="amountToStake"
placeholder="Amount to Stake"
>
<button @click="deposit">
<button @click="deposit({ amount: amountToStake, walletProvider: selectedProvider })">
Steak
</button>
</div>
Expand Down Expand Up @@ -182,9 +180,12 @@
<script setup lang="ts">
import { ref, watchEffect } from 'vue'
import useWallet from '@/composables/wallet'
import useSSV from '@/composables/ssv'
import useUsers from '@/composables/users'
const message = ref('')
const signedMessage = ref('')
const { user } = useUsers()
const metamaskButtonText = ref<string>('Connect Metamask')
const metamaskAccountsResult = ref<string>('Address Not Active')
Expand All @@ -207,20 +208,19 @@ const {
toAddress,
amount,
amountToStake,
pools,
connectWallet,
logout,
setPrimaryWalletAccount,
sendTransaction,
signMessage,
deposit,
getUserPools,
getUserBalance,
getCurrentBalance,
removeConnectedAccount,
switchNetwork
} = useWallet()
const { deposit, getUserPools } = useSSV()
watchEffect(() => {
if (selectedProvider.value === 'MetaMask') {
metamaskButtonText.value = 'MetaMask Connected'
Expand Down Expand Up @@ -432,6 +432,6 @@ input {
/* center in middle of screen */
margin-left: auto;
margin-right: auto;
}
</style>
10 changes: 5 additions & 5 deletions apps/web/src/composables/ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export default function useLedger() {
return await signer.getAddress()
}

async function sendLedgerTransaction({ from, to, value, token }: TransactionInit) {
if (token === 'ETH') {
async function sendLedgerTransaction({ from, to, value, currency }: TransactionInit) {
if (currency === 'ETH') {
const signer = getEthersLedgerSigner()
const provider = signer.provider as ethers.providers.Provider
const unsignedTransaction = {
Expand All @@ -55,17 +55,17 @@ export default function useLedger() {
console.log('Required', ethers.utils.formatEther(required))

return await signer.sendTransaction(unsignedTransaction as ethers.utils.Deferrable<ethers.providers.TransactionRequest>)
} else if (token === 'BTC') {
} else if (currency === 'BTC') {
alert('Send transaction not yet implemented for BTC')
}
}

async function signLedgerMessage(messageInit: MessageInit): Promise<string> {
if (messageInit.token === 'ETH') {
if (messageInit.currency === 'ETH') {
const { message } = messageInit
const signer = getEthersLedgerSigner()
return await signer.signMessage(message)
} else if ( messageInit.token === 'BTC') {
} else if ( messageInit.currency === 'BTC') {
const { message } = messageInit
const signer = getBitcoinLedgerSigner()
return await signer.signMessage(message)
Expand Down
98 changes: 92 additions & 6 deletions apps/web/src/composables/ssv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,30 @@ import { ethers } from 'ethers'
import { SSVManager } from '@casimir/ethereum/build/artifacts/types'
import { abi } from '@casimir/ethereum/build/artifacts/src/SSVManager.sol/SSVManager.json'
import useEnvironment from './environment'
import useUsers from './users'
import useEthers from './ethers'
import useLedger from './ledger'
import useTrezor from './trezor'
import useWalletConnect from './walletConnect'
import { ProviderString } from '@casimir/types'
import { Pool } from '@casimir/types/src/interfaces/Pool'

/** SSV Manager contract */
let ssvManager: SSVManager

export default function useSSV() {
const { ethereumURL } = useEnvironment()
const { getEthersBrowserSigner } = useEthers()
const { getEthersLedgerSigner } = useLedger()
const { getEthersTrezorSigner } = useTrezor()
const { isWalletConnectSigner, getEthersWalletConnectSigner } = useWalletConnect()

if (!ssvManager) {
ssvManager = (() => {
const address = import.meta.env.PUBLIC_SSV_ADDRESS
const address = import.meta.env.PUBLIC_SSV_MANAGER
if (!address) console.log(
`
The PUBLIC_SSV_ADDRESS environment variable is empty.\n
The PUBLIC_SSV_MANAGER environment variable is empty.\n
If you are on mainnet or testnet, the contract does not exist yet.\n
If you are on the local network, check your terminal logs for a contract address or errors.
`
Expand All @@ -23,15 +34,90 @@ export default function useSSV() {
})()
}

async function getSSVFeePercent() {
async function deposit({ amount, walletProvider }: { amount: string, walletProvider: ProviderString }) {
const signerCreators = {
'Browser': getEthersBrowserSigner,
'Ledger': getEthersLedgerSigner,
'Trezor': getEthersTrezorSigner,
'WalletConnect': getEthersWalletConnectSigner
}
const signerType = ['MetaMask', 'CoinbaseWallet'].includes(walletProvider) ? 'Browser' : walletProvider
const signerCreator = signerCreators[signerType as keyof typeof signerCreators]
let signer = signerCreator(walletProvider)
if (isWalletConnectSigner(signer)) signer = await signer
const ssvManagerSigner = ssvManager.connect(signer as ethers.Signer)
const fees = await ssvManagerSigner.getFees()
const { LINK, SSV } = fees
const feesTotalPercent = LINK + SSV
const depositAmount = parseFloat(amount) * ((100 + feesTotalPercent) / 100)
const value = ethers.utils.parseEther(depositAmount.toString())
const result = await ssvManagerSigner.deposit({ value, type: 0 })
return await result.wait()
}

async function getDepositFees() {
const provider = new ethers.providers.JsonRpcProvider(ethereumURL)
ssvManager.connect(provider)
const fees = await ssvManager.getFees()
const ssvManagerProvider = ssvManager.connect(provider)
const fees = await ssvManagerProvider.getFees()
const { LINK, SSV } = fees
const feesTotalPercent = LINK + SSV
const feesRounded = Math.round(feesTotalPercent * 100) / 100
return feesRounded
}

return { ssvManager, getSSVFeePercent }
async function getUserPools(userAddress: string): Promise<Pool[]> {
const provider = new ethers.providers.JsonRpcProvider(ethereumURL)
const ssvManagerProvider = ssvManager.connect(provider)
const userPoolsIds = await ssvManagerProvider.getUserPoolIds(userAddress)
return await Promise.all(userPoolsIds.map(async (poolId: number) => {
const { balance, userBalance } = await ssvManagerProvider.getPoolUserDetails(poolId, userAddress)
let pool: Pool = {
id: poolId,
rewards: ethers.utils.formatEther(balance.rewards),
stake: ethers.utils.formatEther(balance.stake),
userRewards: ethers.utils.formatEther(userBalance.rewards),
userStake: ethers.utils.formatEther(userBalance.stake)
}

const validatorPublicKey = await ssvManagerProvider.getPoolValidatorPublicKey(poolId) // Public key bytes (i.e., 0x..)
if (validatorPublicKey) {

// Validator data from beaconcha.in hardcoded for now
// const response = await fetch(`https://prater.beaconcha.in/api/v1/validator/${validatorPublicKey}`)
// const { data } = await response.json()
// const { status } = data
const validator = {
publicKey: validatorPublicKey,
status: 'Active',
effectiveness: '0%',
apr: '0%', // See issue #205 https://github.com/consensusnetworks/casimir/issues/205#issuecomment-1338142532
url: `https://prater.beaconcha.in/validator/${validatorPublicKey}`
}
const operatorIds = await ssvManagerProvider.getPoolOperatorIds(poolId) // Operator ID uint32[] (i.e., [1, 2, 3, 4])
const operators = await Promise.all(operatorIds.map(async (operatorId: number) => {
const response = await fetch(`https://api.ssv.network/api/v3/operators/${operatorId}`)
const { performance } = await response.json()
return {
id: operatorId,
'24HourPerformance': performance['24h'],
'30DayPerformance': performance['30d'],
url: `https://explorer.ssv.network/operators/${operatorId}`
}
}))

pool = {
...pool,
validator,
operators
}
}

const { user } = useUsers()
user.value?.pools.push(pool)

return pool
}))
}

return { ssvManager, deposit, getDepositFees, getUserPools }
}
2 changes: 1 addition & 1 deletion apps/web/src/composables/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ const { usersBaseURL, ethereumURL } = useEnvironment()
import { dummy_user_account } from '@/pages/user-dash/composables/dummy_data.js'
// 0xd557a5745d4560B24D36A68b52351ffF9c86A212
const user = ref<User>()
const { ssvManager } = useSSV()

export default function useUsers () {
const { ssvManager } = useSSV()

async function getUser() {
const requestOptions = {
Expand Down
Loading

0 comments on commit 3e76b03

Please sign in to comment.