-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Delegator voting action view (#1539)
* Support delegator voting action view * Action view support
- Loading branch information
Showing
7 changed files
with
231 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
'@penumbra-zone/perspective': minor | ||
'@penumbra-zone/getters': minor | ||
'@repo/ui': minor | ||
--- | ||
|
||
Add support for delegate vote action views |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { createGetter } from './utils/create-getter.js'; | ||
import { DelegatorVoteView } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/governance/v1/governance_pb.js'; | ||
|
||
export const getDelegatorVoteBody = createGetter( | ||
(view?: DelegatorVoteView) => view?.delegatorVote.value?.delegatorVote?.body, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
packages/perspective/src/translators/delegator-vote-view.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { asOpaqueDelegatorVoteView } from './delegator-vote-view.js'; | ||
import { describe, expect, test } from 'vitest'; | ||
import { | ||
DelegatorVote, | ||
DelegatorVoteView, | ||
DelegatorVoteView_Opaque, | ||
DelegatorVoteView_Visible, | ||
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/governance/v1/governance_pb.js'; | ||
import { NoteView } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/shielded_pool/v1/shielded_pool_pb.js'; | ||
import { ValueView } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb.js'; | ||
|
||
describe('asOpaqueDelegatorVoteView', () => { | ||
test('when passed `undefined` returns an empty, opaque delegator vote view', () => { | ||
const expected = new DelegatorVoteView({ | ||
delegatorVote: { | ||
case: 'opaque', | ||
value: new DelegatorVoteView_Opaque({ | ||
delegatorVote: undefined, | ||
}), | ||
}, | ||
}); | ||
|
||
expect(asOpaqueDelegatorVoteView(undefined)).toEqual(expected); | ||
}); | ||
|
||
test('when passed an already-opaque delegator vote view returns the delegator vote view as-is', () => { | ||
const opaqueDelegatorVoteView = new DelegatorVoteView({ | ||
delegatorVote: { | ||
case: 'opaque', | ||
value: new DelegatorVoteView_Opaque({ | ||
delegatorVote: new DelegatorVote({ body: { proposal: 123n } }), | ||
}), | ||
}, | ||
}); | ||
expect( | ||
asOpaqueDelegatorVoteView(opaqueDelegatorVoteView).equals(opaqueDelegatorVoteView), | ||
).toBeTruthy(); | ||
}); | ||
|
||
test('returns an opaque version of the delegator vote view', () => { | ||
const visibleDelegatorVoteView = new DelegatorVoteView({ | ||
delegatorVote: { | ||
case: 'visible', | ||
value: new DelegatorVoteView_Visible({ | ||
delegatorVote: new DelegatorVote({ body: { proposal: 123n } }), | ||
note: new NoteView({ value: new ValueView() }), | ||
}), | ||
}, | ||
}); | ||
|
||
const result = asOpaqueDelegatorVoteView(visibleDelegatorVoteView); | ||
|
||
expect(result.delegatorVote.case).toBe('opaque'); | ||
expect( | ||
result.delegatorVote.value?.delegatorVote?.equals( | ||
visibleDelegatorVoteView.delegatorVote.value?.delegatorVote, | ||
), | ||
).toBeTruthy(); | ||
}); | ||
}); |
20 changes: 20 additions & 0 deletions
20
packages/perspective/src/translators/delegator-vote-view.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Translator } from './types.js'; | ||
import { | ||
DelegatorVoteView, | ||
DelegatorVoteView_Opaque, | ||
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/governance/v1/governance_pb.js'; | ||
|
||
export const asOpaqueDelegatorVoteView: Translator<DelegatorVoteView> = delegatorVoteView => { | ||
if (delegatorVoteView?.delegatorVote.case === 'opaque') { | ||
return delegatorVoteView; | ||
} | ||
|
||
return new DelegatorVoteView({ | ||
delegatorVote: { | ||
case: 'opaque', | ||
value: new DelegatorVoteView_Opaque({ | ||
delegatorVote: delegatorVoteView?.delegatorVote.value?.delegatorVote, | ||
}), | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
packages/ui/components/ui/tx/actions-views/delegator-vote.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { ViewBox } from '../viewbox'; | ||
import { ValueViewComponent } from '../../value'; | ||
import { getAddress } from '@penumbra-zone/getters/note-view'; | ||
import { ActionDetails } from './action-details'; | ||
import { | ||
DelegatorVoteBody, | ||
DelegatorVoteView, | ||
Vote, | ||
Vote_Vote, | ||
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/governance/v1/governance_pb'; | ||
import { getDelegatorVoteBody } from '@penumbra-zone/getters/delegator-vote-view'; | ||
import { Amount } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/num/v1/num_pb.js'; | ||
import { | ||
Metadata, | ||
ValueView, | ||
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb.js'; | ||
import { AddressViewComponent } from '../../address-view'; | ||
import { base64ToUint8Array } from '@penumbra-zone/types/base64'; | ||
|
||
// TODO: This is sad, but at the moment, we aren't provided the metadata to have a rich display. | ||
// Given the high-priority of getting action view support, this is added. | ||
// We should properly implement ValueViews into the protos for DelegatorVote action view and delete this code. | ||
const umMetadata = new Metadata({ | ||
denomUnits: [ | ||
{ | ||
denom: 'penumbra', | ||
exponent: 6, | ||
}, | ||
{ | ||
denom: 'upenumbra', | ||
exponent: 0, | ||
}, | ||
], | ||
base: 'upenumbra', | ||
display: 'penumbra', | ||
symbol: 'UM', | ||
penumbraAssetId: { | ||
inner: base64ToUint8Array('KeqcLzNx9qSH5+lcJHBB9KNW+YPrBk5dKzvPMiypahA='), | ||
}, | ||
images: [ | ||
{ | ||
svg: 'https://raw.githubusercontent.com/prax-wallet/registry/main/images/um.svg', | ||
}, | ||
], | ||
}); | ||
|
||
const umValueView = (amount?: Amount) => { | ||
return new ValueView({ | ||
valueView: { | ||
case: 'knownAssetId', | ||
value: { | ||
amount, | ||
metadata: umMetadata, | ||
}, | ||
}, | ||
}); | ||
}; | ||
|
||
export const DelegatorVoteComponent = ({ value }: { value: DelegatorVoteView }) => { | ||
const body = getDelegatorVoteBody.optional()(value); | ||
|
||
if (value.delegatorVote.case === 'visible') { | ||
const note = value.delegatorVote.value.note; | ||
const address = getAddress.optional()(note); | ||
|
||
return ( | ||
<ViewBox | ||
label='Delegator Vote' | ||
visibleContent={ | ||
<ActionDetails> | ||
<VoteBodyDetails body={body} /> | ||
<ActionDetails.Row label='Account'> | ||
<AddressViewComponent view={address} /> | ||
</ActionDetails.Row> | ||
</ActionDetails> | ||
} | ||
/> | ||
); | ||
} | ||
|
||
if (value.delegatorVote.case === 'opaque') { | ||
return ( | ||
<ViewBox | ||
label='Delegator Vote' | ||
visibleContent={ | ||
<ActionDetails> | ||
<VoteBodyDetails body={body} /> | ||
</ActionDetails> | ||
} | ||
/> | ||
); | ||
} | ||
|
||
return <div>Invalid DelegatorVoteView</div>; | ||
}; | ||
|
||
const VoteToString = (vote: Vote): string => { | ||
switch (vote.vote) { | ||
case Vote_Vote.UNSPECIFIED: | ||
return 'UNSPECIFIED'; | ||
case Vote_Vote.ABSTAIN: | ||
return 'ABSTAIN'; | ||
case Vote_Vote.YES: | ||
return 'YES'; | ||
case Vote_Vote.NO: | ||
return 'NO'; | ||
} | ||
}; | ||
|
||
const VoteBodyDetails = ({ body }: { body?: DelegatorVoteBody }) => { | ||
return ( | ||
<> | ||
{!!body?.proposal && ( | ||
<ActionDetails.Row label='Proposal'>{Number(body.proposal)}</ActionDetails.Row> | ||
)} | ||
|
||
{!!body?.vote && ( | ||
<ActionDetails.Row label='Vote'>{VoteToString(body.vote)}</ActionDetails.Row> | ||
)} | ||
{!!body?.unbondedAmount && ( | ||
<ActionDetails.Row label='Voting power'> | ||
<ValueViewComponent view={umValueView(body.unbondedAmount)} /> | ||
</ActionDetails.Row> | ||
)} | ||
</> | ||
); | ||
}; |