Skip to content

Commit

Permalink
Merge pull request #44 from pnetwork-association/feat/withdraw-multip…
Browse files Browse the repository at this point in the history
…le-token

Preset for withdrawing multiple tokens to the same receipient
  • Loading branch information
gitmp01 authored Jul 29, 2024
2 parents 0087ef9 + 1b1b54a commit 2aef1f8
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 34 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dao-v2-ui",
"version": "0.5.0",
"name": "dao-v1-ui",
"version": "0.6.0",
"private": true,
"homepage": ".",
"dependencies": {
Expand Down
1 change: 1 addition & 0 deletions public/assets/svg/USDT.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions src/settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,36 @@ const settings = {
borrowingManagerClaimEnabled: true,
feesManagerClaimEnabled: true,
symbolPrice: 'USDC'
},
{
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
name: 'Tether USD',
decimals: 6,
symbol: 'USDT',
logo: './assets/svg/USDT.svg',
borrowingManagerClaimEnabled: true,
feesManagerClaimEnabled: true,
symbolPrice: 'USDT'
},
{
address: '0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1',
name: 'Arbitrum',
decimals: 18,
symbol: 'ARB',
logo: './assets/svg/ARBITRUM.svg',
borrowingManagerClaimEnabled: true,
feesManagerClaimEnabled: true,
symbolPrice: 'ARB'
},
{
address: '0x0000000000000000000000000000000000000000',
name: 'Eth',
decimals: 18,
symbol: 'ETH',
logo: './assets/svg/ETH.svg',
borrowingManagerClaimEnabled: true,
feesManagerClaimEnabled: true,
symbolPrice: 'ETH'
}
],
chains: [
Expand Down
155 changes: 155 additions & 0 deletions src/utils/presets/paymentsFromTreasury.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import _ from 'lodash'
import { ethers } from 'ethers'

import { checkAddressList, computeRawAmount, getInputFields, isContract, prepareTransfer } from './utils'
import settings from '../../settings'
import BigNumber from 'bignumber.js'

const inputList = (item, index, presetParams, setPresetParams) => {
const tokenIndex = item
const AmountIndex = item + 1
return [
{
id: `select-token-address ${index}`,
name: 'tokenAddress',
component: 'AssetSelection',
props: {
onSelect: (_address) =>
setPresetParams({
...presetParams,
[tokenIndex]: _address
})
}
},
{
id: `input-amount ${index}`,
name: 'amount',
component: 'Input',
props: {
type: 'number',
style: {
fontSize: 15
},
placeholder: `Amount for token ${index} ...`,
value: presetParams[AmountIndex] || '',
onChange: (_e) =>
setPresetParams({
...presetParams,
[AmountIndex]: _e.target.value
})
}
}
]
}

const defaultInput = (presetParams, setPresetParams) => {
return [
{
id: 'input-erc20-receiver-address',
name: 'receiverAddress',
component: 'Input',
props: {
style: {
fontSize: 15
},
placeholder: 'ERC20 tokens receiver address ...',
value: presetParams[0] || '',
onChange: (_e) =>
setPresetParams({
...presetParams,
0: _e.target.value
})
}
},
{
id: 'input-native-receiver-address',
name: 'receiverAddress',
component: 'Input',
props: {
style: {
fontSize: 15
},
placeholder: 'Native asset (ETH) receiver address ...',
value: presetParams[1] || '',
onChange: (_e) =>
setPresetParams({
...presetParams,
1: _e.target.value
})
}
},
{
id: 'input-number-of-tokens',
name: 'number-of-tokens',
component: 'Input',
props: {
style: {
fontSize: 15
},
placeholder: 'Number of tokens to payout...',
value: presetParams[2] || '',
onChange: (_e) =>
setPresetParams({
0: presetParams[0],
1: presetParams[1],
2: _e.target.value
})
}
}
]
}

const getTokenList = (data, numberOfTokens) => {
const indexesOfTokens = Array.from({ length: numberOfTokens }, (_, i) => 3 + i * 2)
return _.map(indexesOfTokens, (key) => _.get(data, key, settings.assets[0].address))
}

const getAmountList = (data, numberOfTokens) => {
const indexesOfAmounts = Array.from({ length: numberOfTokens }, (_, i) => 4 + i * 2)
return _.at(data, indexesOfAmounts)
}

function getDecimalsByAddress(address) {
const asset = _.find(settings.assets, { address })
if (!asset) throw new Error('asset not found for address: ' + address)
return asset.decimals
}

const paymentsFromTreasury = ({ presetParams, setPresetParams, provider }) => ({
id: 'paymentsFromTreasury',
name: 'Payment from treasury of multiple tokens',
description:
'Execute a payment from the treasury using multiple tokens. For technical reason native assets (ETH) can only be sent to a normal account (no contract)',
args: getInputFields(presetParams[2], presetParams, setPresetParams, defaultInput, 3, inputList, 2),
prepare: async () => {
let params = Object.values(presetParams)
if (params.length < 4) return null

const erc20RecipientAddress = presetParams[0]
const NativeRecipientAddress = presetParams[1]
checkAddressList([erc20RecipientAddress])
checkAddressList([NativeRecipientAddress])
if (await isContract(NativeRecipientAddress))
throw new Error(
'Native asset (ETH) receiver address is a contract. Only normal accounts (no contract) can receive native assets.'
)

const numberOfTokens = presetParams[2]
const tokensList = getTokenList(presetParams, numberOfTokens)
const amountList = getAmountList(presetParams, numberOfTokens)

const transferAmounts = _.flattenDeep(
tokensList.map((tokenAddress, index) => {
const decimals = getDecimalsByAddress(tokenAddress)
const rawAmount = computeRawAmount(amountList[index], decimals)
const address =
tokenAddress === '0x0000000000000000000000000000000000000000' ? NativeRecipientAddress : erc20RecipientAddress
return prepareTransfer(tokenAddress, address, rawAmount)
})
)

return [...transferAmounts]
}
})

export default paymentsFromTreasury
47 changes: 41 additions & 6 deletions src/utils/presets/utils.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import BigNumber from 'bignumber.js'
import { ethers } from 'ethers'
import { getProvider, readContract } from '@wagmi/core'
import { mainnet } from 'wagmi'

import VaultABI from '../abis/Vault.json'
import DandelionVotingABI from '../abis/DandelionVoting.json'
import EthPNTABI from '../abis/EthPNT.json'
import pNetworkV2VaultABI from '../abis/pNetworkV2Vault.json'
import MerklDistributionCreatorABI from '../abis/MerklDistributionCreator.json'
import BigNumber from 'bignumber.js'
import { ethers } from 'ethers'
import { readContract } from '@wagmi/core'

import settings from '../../settings'

export const vaultContract = new ethers.utils.Interface(VaultABI)
Expand All @@ -22,6 +23,20 @@ export const computeRawAmount = (amount, decimals) =>
.multipliedBy(10 ** decimals)
.toFixed()

export const checkAddressList = (addressList) =>
addressList.map((address, index) => {
if (!ethers.utils.isAddress(address))
throw new Error(`Inserted destination address for recipient ${index} is not valid`)
})

export const isContract = async (address) => {
checkAddressList([address])
const provider = getProvider({ chainId: mainnet.id })
const code = await provider.getCode(address)
if (code === '0x') return false
else return true
}

export const getEthPNTdata = () => {
const ethPNTAsset = settings.assets.find((asset) => asset.symbol == 'ethPNT')
if (!ethPNTAsset) throw new Error('ethPNT asset config not found!')
Expand Down Expand Up @@ -52,10 +67,10 @@ export const prepareWithdrawInflation = (ethPNTAddress, rawAmount) => [
}
]

export const prepareTransfer = (ethPNTAddress, receiverAddress, rawAmount) => [
export const prepareTransfer = (tokenAddress, receiverAddress, rawAmount) => [
{
to: settings.contracts.financeVault,
calldata: vaultContract.encodeFunctionData('transfer', [ethPNTAddress, receiverAddress, rawAmount])
calldata: vaultContract.encodeFunctionData('transfer', [tokenAddress, receiverAddress, rawAmount])
}
]

Expand All @@ -66,6 +81,26 @@ export const prepareInflationProposal = async (ethPNTAddress, receiverAddress, r
])
}

export const getInputFields = (
number,
presetParams,
setPresetParams,
defaultInput,
defaultInputLength,
inputList,
inputListLength
) => {
if (!number || isNaN(number) || ethers.utils.isAddress(number)) return defaultInput(presetParams, setPresetParams)
else {
const indices = Array.from({ length: number }, (_, index) => defaultInputLength + index * inputListLength)
const mergedInputFields = _.flattenDeep(
indices.map((item, index) => inputList(item, index + 1, presetParams, setPresetParams))
)

return _.flattenDeep([defaultInput(presetParams, setPresetParams), mergedInputFields])
}
}

const sha3 = (_string) => ethers.utils.keccak256(ethers.utils.toUtf8Bytes(_string))

const getCorrectEpochStartTimestamp = async () => {
Expand Down
32 changes: 10 additions & 22 deletions src/utils/presets/withdrawInflationToRecipients.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import _ from 'lodash'
import { ethers } from 'ethers'

import { prepareInflationData, prepareWithdrawInflation, prepareTransfer, getEthPNTdata } from './utils'
import {
prepareInflationData,
prepareWithdrawInflation,
prepareTransfer,
getInputFields,
checkAddressList
} from './utils'

const baseInput = (item, index, presetParams, setPresetParams) => {
const inputList = (item, index, presetParams, setPresetParams) => {
const receiverAddressIndex = item
const AmountIndex = item + 1
return [
Expand Down Expand Up @@ -45,7 +51,7 @@ const baseInput = (item, index, presetParams, setPresetParams) => {
]
}

const getNumber = (presetParams, setPresetParams) => {
const defaultInput = (presetParams, setPresetParams) => {
return [
{
id: 'input-number-of-receivers',
Expand All @@ -67,29 +73,11 @@ const getNumber = (presetParams, setPresetParams) => {
]
}

const getInputFields = (number, presetParams, setPresetParams) => {
if (!number || number === '') return getNumber(presetParams, setPresetParams)
else {
const indices = Array.from({ length: number }, (_, index) => 2 * index + 1)
const mergedInputFields = _.flattenDeep(
indices.map((item, index) => baseInput(item, index + 1, presetParams, setPresetParams))
)

return _.flattenDeep([getNumber(presetParams, setPresetParams), mergedInputFields])
}
}

const getAddressList = (presetParams) =>
_.filter(presetParams, (element, index) => {
return index % 2 === 0
})

const checkAddressList = (addressList) =>
addressList.map((address, index) => {
if (!ethers.utils.isAddress(address))
throw new Error(`Inserted destination address for recipient ${index} is not valid`)
})

const getAmountList = (presetParams) =>
_.filter(presetParams, (element, index) => {
return index % 2 !== 0
Expand All @@ -99,7 +87,7 @@ const withdrawInflationToRecipients = ({ presetParams, setPresetParams }) => ({
id: 'withdrawInflationToRecipients',
name: 'Withdraw Inflation To Multiple Recipients',
description: 'Withdraw requested inflated ethPNT amount from the treasury',
args: getInputFields(presetParams[0], presetParams, setPresetParams),
args: getInputFields(presetParams[0], presetParams, setPresetParams, defaultInput, 1, inputList, 2),
prepare: async () => {
const params = Object.values(presetParams)
if (params.length < 3) return null
Expand Down
2 changes: 2 additions & 0 deletions src/utils/vote-presets.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import changeInflationOwner from './presets/changeInflationOwner'
import createMerklIncentive from './presets/createMerklIncentive'
import paymentFromTreasury from './presets/paymentFromTreasury'
import paymentsFromTreasury from './presets/paymentsFromTreasury'
import withdrawInflationAndPegin from './presets/withdrawInflationAndPegin'
import withdrawInflationToAssociation from './presets/withdrawInflationToAssociation'
import withdrawInflationToRecipient from './presets/withdrawInflationToRecipient'
Expand All @@ -9,6 +10,7 @@ import withdrawInflationToRecipients from './presets/withdrawInflationToRecipien
const getVotePresets = ({ presetParams, setPresetParams, provider }) => {
return {
paymentFromTreasury: paymentFromTreasury({ presetParams, setPresetParams, provider }),
paymentsFromTreasury: paymentsFromTreasury({ presetParams, setPresetParams, provider }),
withdrawInflationToRecipient: withdrawInflationToRecipient({ presetParams, setPresetParams }),
withdrawInflationToRecipients: withdrawInflationToRecipients({ presetParams, setPresetParams }),
withdrawInflationToAssociation: withdrawInflationToAssociation({ presetParams, setPresetParams }),
Expand Down

0 comments on commit 2aef1f8

Please sign in to comment.