diff --git a/apps/ui/src/components/Modal/VotingPower.vue b/apps/ui/src/components/Modal/VotingPower.vue
index 688ebc73e..a2618eca8 100644
--- a/apps/ui/src/components/Modal/VotingPower.vue
+++ b/apps/ui/src/components/Modal/VotingPower.vue
@@ -59,7 +59,7 @@ const loading = computed(
{{
_n(
- Number(strategy.value) / 10 ** votingPower.decimals,
+ Number(strategy.value) / 10 ** strategy.cumulativeDecimals,
'compact',
{
maximumFractionDigits: 2,
@@ -109,7 +109,7 @@ const loading = computed(
- {{ _n(Number(strategy.value) / 10 ** strategy.decimals) }}
+ {{ _n(Number(strategy.value) / 10 ** strategy.displayDecimals) }}
{{ strategy.symbol || 'units' }}
diff --git a/apps/ui/src/helpers/utils.ts b/apps/ui/src/helpers/utils.ts
index 0071df4bb..c5da8fcd3 100644
--- a/apps/ui/src/helpers/utils.ts
+++ b/apps/ui/src/helpers/utils.ts
@@ -610,8 +610,13 @@ export function getSocialNetworksLink(data: any) {
export function getFormattedVotingPower(votingPower?: VotingPowerItem) {
if (!votingPower) return;
- const { totalVotingPower, decimals, symbol } = votingPower;
- const value = _vp(Number(totalVotingPower) / 10 ** decimals);
+ const { votingPowers, symbol } = votingPower;
+ const value = _vp(
+ votingPowers.reduce(
+ (acc, b) => acc + Number(b.value) / 10 ** b.cumulativeDecimals,
+ 0
+ )
+ );
return symbol ? `${value} ${symbol}` : value;
}
diff --git a/apps/ui/src/networks/evm/actions.ts b/apps/ui/src/networks/evm/actions.ts
index 1445961e7..7b6a8f6e4 100644
--- a/apps/ui/src/networks/evm/actions.ts
+++ b/apps/ui/src/networks/evm/actions.ts
@@ -736,11 +736,22 @@ export function createActions(
if (snapshotInfo.at === null)
throw new Error('EVM requires block number to be defined');
+ const cumulativeDecimals = Math.max(
+ ...strategiesMetadata.map(metadata => metadata.decimals ?? 0)
+ );
+
return Promise.all(
strategiesAddresses.map(async (address, i) => {
const strategy = getEvmStrategy(address, networkConfig);
if (!strategy)
- return { address, value: 0n, decimals: 0, token: null, symbol: '' };
+ return {
+ address,
+ value: 0n,
+ displayDecimals: 0,
+ cumulativeDecimals: 0,
+ token: null,
+ symbol: ''
+ };
const strategyMetadata = await parseStrategyMetadata(
strategiesMetadata[i].payload
@@ -761,7 +772,8 @@ export function createActions(
return {
address,
value,
- decimals: strategiesMetadata[i]?.decimals ?? 0,
+ cumulativeDecimals,
+ displayDecimals: strategiesMetadata[i]?.decimals ?? 0,
symbol: strategiesMetadata[i]?.symbol ?? '',
token,
swapLink: getSwapLink(strategy.type, address, chainId)
diff --git a/apps/ui/src/networks/offchain/actions.ts b/apps/ui/src/networks/offchain/actions.ts
index b8452faf3..db2368769 100644
--- a/apps/ui/src/networks/offchain/actions.ts
+++ b/apps/ui/src/networks/offchain/actions.ts
@@ -242,7 +242,14 @@ export function createActions(
if (!strategy || !isAddress(voterAddress)) {
return [
- { address: name, value: 0n, decimals: 0, token: null, symbol: '' }
+ {
+ address: name,
+ value: 0n,
+ cumulativeDecimals: 0,
+ displayDecimals: 0,
+ token: null,
+ symbol: ''
+ }
];
}
@@ -257,7 +264,8 @@ export function createActions(
return [
{
address: strategiesNames[0],
- decimals: 0,
+ cumulativeDecimals: 0,
+ displayDecimals: 0,
symbol: '',
token: '',
chainId: snapshotInfo.chainId,
@@ -273,7 +281,8 @@ export function createActions(
return {
address: strategy.name,
value,
- decimals,
+ cumulativeDecimals: decimals,
+ displayDecimals: decimals,
symbol: strategy.params.symbol,
token: strategy.params.address,
chainId: strategy.network ? parseInt(strategy.network) : undefined,
diff --git a/apps/ui/src/networks/offchain/index.test.ts b/apps/ui/src/networks/offchain/index.test.ts
index 51398774d..08828d8b1 100644
--- a/apps/ui/src/networks/offchain/index.test.ts
+++ b/apps/ui/src/networks/offchain/index.test.ts
@@ -34,7 +34,8 @@ describe('offchain network', () => {
).resolves.toEqual([
{
address: 'ticket',
- decimals: 0,
+ cumulativeDecimals: 0,
+ displayDecimals: 0,
symbol: '',
token: null,
value: 0n
@@ -88,7 +89,8 @@ describe('offchain network', () => {
).resolves.toEqual([
{
address: 'ticket',
- decimals: 9,
+ cumulativeDecimals: 9,
+ displayDecimals: 9,
symbol: 'SYM',
token: 'TOKEN',
value: result[0],
@@ -97,7 +99,8 @@ describe('offchain network', () => {
},
{
address: 'math',
- decimals: 18,
+ cumulativeDecimals: 18,
+ displayDecimals: 18,
symbol: undefined,
token: undefined,
value: result[1],
@@ -106,7 +109,8 @@ describe('offchain network', () => {
},
{
address: 'api',
- decimals: 18,
+ cumulativeDecimals: 18,
+ displayDecimals: 18,
symbol: undefined,
token: undefined,
value: result[2],
@@ -141,7 +145,8 @@ describe('offchain network', () => {
).resolves.toEqual([
{
address: 'basic',
- decimals: 0,
+ cumulativeDecimals: 0,
+ displayDecimals: 0,
symbol: '',
token: null,
value: 0n
@@ -167,7 +172,8 @@ describe('offchain network', () => {
{
address: 'only-members',
value: 1n,
- decimals: 0,
+ cumulativeDecimals: 0,
+ displayDecimals: 0,
symbol: '',
token: '',
chainId: undefined
@@ -191,7 +197,8 @@ describe('offchain network', () => {
{
address: 'only-members',
value: 0n,
- decimals: 0,
+ cumulativeDecimals: 0,
+ displayDecimals: 0,
symbol: '',
token: '',
chainId: undefined
diff --git a/apps/ui/src/networks/starknet/actions.ts b/apps/ui/src/networks/starknet/actions.ts
index 34bea9659..6518560d9 100644
--- a/apps/ui/src/networks/starknet/actions.ts
+++ b/apps/ui/src/networks/starknet/actions.ts
@@ -731,11 +731,22 @@ export function createActions(
voterAddress: string,
snapshotInfo: SnapshotInfo
): Promise => {
+ const cumulativeDecimals = Math.max(
+ ...strategiesMetadata.map(metadata => metadata.decimals ?? 0)
+ );
+
return Promise.all(
strategiesAddresses.map(async (address, i) => {
const strategy = getStarknetStrategy(address, networkConfig);
if (!strategy)
- return { address, value: 0n, decimals: 0, token: null, symbol: '' };
+ return {
+ address,
+ value: 0n,
+ cumulativeDecimals: 0,
+ displayDecimals: 0,
+ token: null,
+ symbol: ''
+ };
const strategyMetadata = await parseStrategyMetadata(
strategiesMetadata[i].payload
@@ -756,7 +767,8 @@ export function createActions(
return {
address,
value,
- decimals: strategiesMetadata[i]?.decimals ?? 0,
+ cumulativeDecimals,
+ displayDecimals: strategiesMetadata[i]?.decimals ?? 0,
symbol: strategiesMetadata[i]?.symbol ?? '',
token: strategiesMetadata[i]?.token ?? null
};
diff --git a/apps/ui/src/networks/types.ts b/apps/ui/src/networks/types.ts
index 6fcfcaf7e..bcbadc9ba 100644
--- a/apps/ui/src/networks/types.ts
+++ b/apps/ui/src/networks/types.ts
@@ -110,7 +110,14 @@ export type SnapshotInfo = {
export type VotingPower = {
address: string;
value: bigint;
- decimals: number;
+ /**
+ * Decimals used to interpret value in context of final (total) VP.
+ */
+ cumulativeDecimals: number;
+ /**
+ * Decimals used to display this strategy value.
+ */
+ displayDecimals: number;
token: string | null;
symbol: string;
chainId?: number;
diff --git a/apps/ui/src/stores/votingPowers.ts b/apps/ui/src/stores/votingPowers.ts
index 613796c49..5eb31f388 100644
--- a/apps/ui/src/stores/votingPowers.ts
+++ b/apps/ui/src/stores/votingPowers.ts
@@ -10,10 +10,8 @@ const LATEST_BLOCK_NAME = 'latest';
type SpaceDetails = Proposal['space'];
export type VotingPowerItem = {
votingPowers: VotingPower[];
- totalVotingPower: bigint;
status: VotingPowerStatus;
symbol: string;
- decimals: number;
error: utils.errors.VotingPowerDetailsError | null;
canPropose: boolean;
canVote: boolean;
@@ -63,8 +61,6 @@ export const useVotingPowersStore = defineStore('votingPowers', () => {
let vpItem: VotingPowerItem = {
status: 'loading',
votingPowers: [],
- totalVotingPower: 0n,
- decimals: 18,
symbol: space.voting_power_symbol,
error: null,
canPropose: false,
@@ -106,19 +102,20 @@ export const useVotingPowersStore = defineStore('votingPowers', () => {
vpItem = {
...vpItem,
votingPowers: vp,
- totalVotingPower: vp.reduce((acc, b) => acc + b.value, 0n),
- status: 'success',
- decimals: Math.max(...vp.map(votingPower => votingPower.decimals), 0)
+ status: 'success'
};
if (isSpace(item) && proposeVp) {
- const totalProposeVp = proposeVp.reduce((acc, b) => acc + b.value, 0n);
+ const totalProposeVp = proposeVp.reduce(
+ (acc, b) => acc + Number(b.value) / 10 ** b.cumulativeDecimals,
+ 0
+ );
vpItem.canPropose =
totalProposeVp >= BigInt(item.proposal_threshold) ||
isSpaceMember(space as Space, account);
} else {
- vpItem.canVote = vpItem.totalVotingPower > 0n;
+ vpItem.canVote = vp.some(vp => vp.value > 0n);
}
} catch (e: unknown) {
if (e instanceof utils.errors.VotingPowerDetailsError) {
diff --git a/apps/ui/src/views/Proposal.vue b/apps/ui/src/views/Proposal.vue
index 20d3acb27..bf6871f95 100644
--- a/apps/ui/src/views/Proposal.vue
+++ b/apps/ui/src/views/Proposal.vue
@@ -310,7 +310,7 @@ watchEffect(() => {
getSocialNetworksLink(user.value));
const cb = computed(() => getCacheHash(user.value?.avatar));
const formattedVotingPower = computed(() => {
- const votingPower = votingPowers.value.reduce((acc, b) => acc + b.value, 0n);
- const decimals = Math.max(
- ...votingPowers.value.map(votingPower => votingPower.decimals),
- 0
+ const votingPower = _vp(
+ votingPowers.value.reduce(
+ (acc, b) => acc + Number(b.value) / 10 ** b.cumulativeDecimals,
+ 0
+ )
);
- const value = _vp(Number(votingPower) / 10 ** decimals);
-
if (props.space.voting_power_symbol) {
- return `${value} ${props.space.voting_power_symbol}`;
+ return `${votingPower} ${props.space.voting_power_symbol}`;
}
- return value;
+ return votingPower;
});
const navigation = computed(() => [