Skip to content

Commit

Permalink
Use actual rebalancer types.
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahSaso committed Oct 20, 2023
1 parent eb794d6 commit 4cd0893
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 48 deletions.
1 change: 1 addition & 0 deletions packages/state/recoil/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ export * from './profile'
export * from './proposal'
export * from './token'
export * from './treasury'
export * from './valence'
export * from './wallet'
export * from './wynd'
21 changes: 19 additions & 2 deletions packages/state/recoil/selectors/valence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ export const valenceAccountsSelector = selectorFamily<
// TODO(rebalancer): Get config
const config: ValenceAccountConfig = {
rebalancer: {
config: {
base_denom: '',
has_min_balance: false,
last_rebalance: '',
max_limit: '',
pid: {
d: '',
i: '',
p: '',
},
target_override_strategy: 'proportional',
targets: [],
},
targets: [
{
source: {
Expand All @@ -46,7 +59,9 @@ export const valenceAccountsSelector = selectorFamily<
targets: [
{
timestamp: 0,
target: 0.75,
denom: 'untrn',
last_i: ['', false],
percentage: '0.75',
},
],
},
Expand All @@ -58,7 +73,9 @@ export const valenceAccountsSelector = selectorFamily<
targets: [
{
timestamp: 0,
target: 0.25,
denom: 'untrn',
last_i: ['', false],
percentage: '0.25',
},
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
ValenceAccount,
} from '@dao-dao/types'
import { ActionComponent } from '@dao-dao/types/actions'
import { TargetOverrideStrategy } from '@dao-dao/types/contracts/ValenceServiceRebalancer'
import {
convertMicroDenomToDenomWithDecimals,
formatPercentOf100,
Expand All @@ -49,7 +50,7 @@ export type ConfigureRebalancerData = {
kd: number
}
maxLimitBps?: number
targetOverrideStrategy: string
targetOverrideStrategy: TargetOverrideStrategy
}

export type ConfigureRebalancerOptions = {
Expand Down
143 changes: 125 additions & 18 deletions packages/stateful/actions/core/treasury/ConfigureRebalancer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import { useCallback } from 'react'
import { useFormContext } from 'react-hook-form'
import { useRecoilValueLoadable, waitForAll } from 'recoil'

import { valenceAccountsSelector } from '@dao-dao/state'
import { historicalUsdPriceSelector } from '@dao-dao/state/recoil/selectors/osmosis'
import { BalanceEmoji, ChainProvider } from '@dao-dao/stateless'
import {
BalanceEmoji,
ChainProvider,
useCachedLoadingWithError,
} from '@dao-dao/stateless'
import { ChainId, TokenType, UseDecodedCosmosMsg } from '@dao-dao/types'
import {
ActionComponent,
Expand All @@ -14,8 +19,15 @@ import {
UseDefaults,
UseTransformToCosmos,
} from '@dao-dao/types/actions'
import { ExecuteMsg as ValenceAccountExecuteMsg } from '@dao-dao/types/contracts/ValenceAccount'
import {
RebalancerData,
RebalancerUpdateData,
} from '@dao-dao/types/contracts/ValenceServiceRebalancer'
import {
decodePolytoneExecuteMsg,
encodeMessageAsBase64,
getAccountAddress,
getNativeIbcUsdc,
getNativeTokenForChainId,
loadableToLoadingData,
Expand All @@ -34,17 +46,61 @@ import {

const useDefaults: UseDefaults<ConfigureRebalancerData> = () => {
const {
address,
chain: { chain_id: chainId },
context,
} = useActionOptions()

const nativeDenom = getNativeTokenForChainId(chainId).denomOrAddress
const usdcDenom = getNativeIbcUsdc(chainId)?.denomOrAddress
// Get Neutron account.
const neutronAddress =
context.type === ActionContextType.Dao
? getAccountAddress({
accounts: context.info.accounts,
chainId: ChainId.NeutronMainnet,
})
: chainId === ChainId.NeutronMainnet
? address
: null
if (!neutronAddress) {
throw new Error('Missing Neutron account.')
}

const valenceAccountsLoading = useCachedLoadingWithError(
valenceAccountsSelector({
chainId: ChainId.NeutronMainnet,
address,
})
)
const valenceAccount =
valenceAccountsLoading.loading || valenceAccountsLoading.errored
? undefined
: valenceAccountsLoading.data[0]

const nativeDenom = getNativeTokenForChainId(
ChainId.NeutronMainnet
).denomOrAddress
const usdcDenom = getNativeIbcUsdc(ChainId.NeutronMainnet)?.denomOrAddress

const rebalancerConfig = valenceAccount?.config.rebalancer?.config

return {
chainId,
valenceAccount,
chainId: ChainId.NeutronMainnet,
trustee: rebalancerConfig?.trustee || undefined,
baseDenom:
REBALANCER_BASE_TOKEN_ALLOWLIST[chainId as ChainId]?.[0] ?? nativeDenom,
tokens: [
(rebalancerConfig?.base_denom ||
REBALANCER_BASE_TOKEN_ALLOWLIST[ChainId.NeutronMainnet]?.[0]) ??
nativeDenom,
tokens: rebalancerConfig?.targets.map(
({ denom, percentage, min_balance }) => ({
denom,
percent: Number(percentage),
minBalance:
min_balance && !isNaN(Number(min_balance))
? Number(min_balance)
: undefined,
})
) || [
{
denom: nativeDenom,
percent: 50,
Expand All @@ -58,17 +114,21 @@ const useDefaults: UseDefaults<ConfigureRebalancerData> = () => {
]
: []),
],
// TODO: pick default
// TODO: pick defaults
pid: {
kp: 0.1,
ki: 0.1,
kd: 0.1,
kp: Number(rebalancerConfig?.pid.p || 0.1),
ki: Number(rebalancerConfig?.pid.i || 0.1),
kd: Number(rebalancerConfig?.pid.d || 0.1),
},
maxLimitBps:
rebalancerConfig?.max_limit && !isNaN(Number(rebalancerConfig.max_limit))
? Number(rebalancerConfig.max_limit)
: // TODO: pick default
// 5%
500,
// TODO: pick default
// 5%
maxLimitBps: 500,
// TODO: pick default
targetOverrideStrategy: 'proportional',
targetOverrideStrategy:
rebalancerConfig?.target_override_strategy || 'proportional',
}
}

Expand Down Expand Up @@ -244,6 +304,7 @@ const useDecodedCosmosMsg: UseDecodedCosmosMsg<ConfigureRebalancerData> = (

if (
serviceName !== 'rebalancer' ||
!data ||
!objectMatchesStructure(data, {
base_denom: {},
targets: {},
Expand All @@ -263,7 +324,26 @@ const useDecodedCosmosMsg: UseDecodedCosmosMsg<ConfigureRebalancerData> = (

return {
match: true,
data: {},
data: {
chainId,
trustee: data.trustee || undefined,
baseDenom: data.base_denom,
tokens: data.targets.map(({ denom, min_balance, percentage }) => ({
denom,
percent: percentage,
minBalance:
min_balance && !isNaN(Number(min_balance))
? Number(min_balance)
: undefined,
})),
pid: {
kp: Number(data.pid.p),
ki: Number(data.pid.i),
kd: Number(data.pid.d),
},
maxLimitBps: data.max_limit || undefined,
targetOverrideStrategy: data.target_override_strategy,
},
}
}

Expand All @@ -284,7 +364,16 @@ export const makeConfigureRebalancerAction: ActionMaker<
ConfigureRebalancerData
> = () => {
return useCallback(
({ valenceAccount, chainId, tokens, pid }: ConfigureRebalancerData) => {
({
valenceAccount,
chainId,
trustee,
baseDenom,
tokens,
pid,
maxLimitBps,
targetOverrideStrategy,
}: ConfigureRebalancerData) => {
if (!valenceAccount) {
throw new Error('Missing valence account.')
}
Expand All @@ -298,8 +387,26 @@ export const makeConfigureRebalancerAction: ActionMaker<
contract_addr: valenceAccount.address,
funds: [],
msg: {
update_config: {},
},
update_service: {
data: encodeMessageAsBase64({
base_denom: baseDenom,
max_limit: maxLimitBps,
pid: {
p: pid.kp.toString(),
i: pid.ki.toString(),
d: pid.kd.toString(),
},
target_override_strategy: targetOverrideStrategy,
targets: tokens.map(({ denom, percent, minBalance }) => ({
denom,
min_balance:
minBalance && BigInt(minBalance).toString(),
percentage: percent,
})),
trustee,
} as RebalancerUpdateData),
},
} as ValenceAccountExecuteMsg,
},
},
})
Expand Down
12 changes: 8 additions & 4 deletions packages/stateful/components/dao/DaoTreasuryHistoryGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ export const DaoTreasuryHistoryGraph = ({
precision,
filter: account && {
account,
rebalancerOnly: showRebalancer,
// Filter by rebalancer tokens.
tokens:
showRebalancer && account.type === AccountType.Valence
? account.config.rebalancer?.targets.map(({ source }) => source)
: undefined,
},
startSecondsAgo,
})
Expand Down Expand Up @@ -143,17 +147,17 @@ export const DaoTreasuryHistoryGraph = ({
return null
}

const { target } = targets[targetIndex]
const { percentage } = targets[targetIndex]

// The target at this point is based on the total value.
return totalValue * target
return totalValue * Number(percentage)
}
)

// Add current target.
const currentTarget =
treasuryValueHistory.data.total.currentValue *
targets[targets.length - 1].target
Number(targets[targets.length - 1].percentage)
data.push(currentTarget)

const tokenIndex = treasuryValueHistory.data.tokens.findIndex(
Expand Down
26 changes: 9 additions & 17 deletions packages/stateful/recoil/selectors/treasury.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {
} from '@dao-dao/state'
import {
Account,
AccountType,
GenericToken,
GenericTokenSource,
LoadingTokens,
TokenCardInfo,
TokenType,
Expand Down Expand Up @@ -214,11 +214,7 @@ export const treasuryTokenCardInfosForDaoSelector = selectorFamily<
},
})

const ACCOUNT_FILTER_PROPERTIES: (keyof Account)[] = [
'type',
'chainId',
'address',
]
const ACCOUNT_FILTER_PROPERTIES = ['type', 'chainId', 'address'] as const

export const daoTreasuryValueHistorySelector = selectorFamily<
{
Expand All @@ -243,10 +239,9 @@ export const daoTreasuryValueHistorySelector = selectorFamily<
startSecondsAgo: number
filter?: {
// Filter by any of the account properties.
account?: Partial<Account>
// If `account` is a valence account and `rebalancerOnly` is true, only
// show valence account assets that are being rebalanced.
rebalancerOnly?: boolean
account?: Partial<Pick<Account, typeof ACCOUNT_FILTER_PROPERTIES[number]>>
// If defined, only show these tokens.
tokens?: GenericTokenSource[]
}
}>
>({
Expand Down Expand Up @@ -355,13 +350,10 @@ export const daoTreasuryValueHistorySelector = selectorFamily<
(token) =>
// Can only compute price if token decimals loaded correctly.
token.decimals > 0 &&
// Filter by rebalancer tokens in valence account.
(!filter ||
!filter.rebalancerOnly ||
filter.account?.type !== AccountType.Valence ||
!filter.account.config?.rebalancer ||
filter.account.config.rebalancer.targets.some(
({ source }) =>
// Filter by tokens.
(!filter?.tokens ||
filter.tokens.some(
(source) =>
serializeTokenSource(source) === serializeTokenSource(token)
))
)
Expand Down
Loading

0 comments on commit 4cd0893

Please sign in to comment.