Skip to content

Commit c063a9e

Browse files
authored
Merge pull request #19 from hippo-protocol/feature/proposal
Add custom messages in widget
2 parents 276e66f + 07ed24f commit c063a9e

File tree

8 files changed

+671
-202
lines changed

8 files changed

+671
-202
lines changed

lib/components/TxDialog/index.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ import UpdateAdmin from './wasm/UpdateAdmin.vue';
3737
import ClearAdmin from './wasm/ClearAdmin.vue';
3838
import { TokenUnitConverter } from '../../utils/TokenUnitConverter';
3939
40+
// custom messages
41+
import CommunityPoolSpend from './messages/CommunityPoolSpend.vue';
42+
import UpdateParams from './messages/UpdateParams.vue';
43+
4044
const props = defineProps({
4145
type: String,
4246
endpoint: { type: String, required: true },
@@ -46,6 +50,7 @@ const props = defineProps({
4650
params: String,
4751
});
4852
53+
const directSignMessages = ['community_pool_spend', 'update_params']
4954
const msgType = computed(() => {
5055
switch (props.type?.toLowerCase()) {
5156
case 'send':
@@ -82,6 +87,10 @@ const msgType = computed(() => {
8287
return UpdateAdmin;
8388
case 'wasm_clear_admin':
8489
return ClearAdmin;
90+
case 'community_pool_spend':
91+
return CommunityPoolSpend;
92+
// case 'update_params':
93+
// return UpdateParams
8594
default:
8695
return Send;
8796
}
@@ -260,7 +269,7 @@ async function sendTx() {
260269
tx.fee.gas = gasInfo.value.toString();
261270
}
262271
263-
const txRaw = await client.sign(tx);
272+
const txRaw = await client.sign(tx, directSignMessages.includes(props.type ?? ''));
264273
const response = await client.broadcastTx(
265274
props.endpoint,
266275
txRaw,
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<script lang="ts" setup>
2+
3+
import { computed, onMounted, PropType, ref } from 'vue';
4+
import { Coin, CoinMetadata } from '../../../utils/type';
5+
import { TokenUnitConverter } from '../../../utils/TokenUnitConverter';
6+
7+
import { MsgSubmitProposal } from 'cosmjs-types/cosmos/gov/v1/tx';
8+
import { MsgCommunityPoolSpend } from 'cosmjs-types/cosmos/distribution/v1beta1/tx';
9+
import { getAuthority, getCommunityPool } from '../../../utils/http';
10+
11+
const props = defineProps({
12+
endpoint: { type: String, required: true },
13+
sender: { type: String, required: true },
14+
balances: Object as PropType<Coin[]>,
15+
metadata: Object as PropType<Record<string, CoinMetadata>>,
16+
params: String,
17+
});
18+
19+
const denom = ref("")
20+
const deposit = ref("")
21+
const amountDenom = ref("hp")
22+
const title = ref("")
23+
const summary = ref("")
24+
const authority = ref("")
25+
const recipient = ref("")
26+
const amount = ref("")
27+
const communityPoolAvailable = ref(
28+
{ amount: "0", denom: "ahp" }
29+
)
30+
31+
const convert = new TokenUnitConverter(
32+
// below can be simplied to props.metadata if metadata api works.
33+
{
34+
ahp: {
35+
name: 'hp',
36+
description: 'The native staking token of the Hippo Protocol.',
37+
denom_units: [
38+
{
39+
denom: 'ahp',
40+
exponent: 0,
41+
aliases: [],
42+
},
43+
{
44+
denom: 'hp',
45+
exponent: 18,
46+
aliases: [],
47+
},
48+
],
49+
base: 'ahp',
50+
display: 'hp',
51+
symbol: 'hp',
52+
},
53+
}
54+
);
55+
const available = computed(() => {
56+
const base = props.balances?.find(x => x.denom === denom.value) || { amount: "0", denom: denom.value }
57+
return {
58+
base,
59+
display: convert.baseToUnit(base, amountDenom.value)
60+
}
61+
})
62+
63+
const msgs = computed(() => {
64+
return [{
65+
typeUrl: MsgSubmitProposal.typeUrl, value: MsgSubmitProposal.fromPartial({
66+
messages: [{
67+
typeUrl: MsgCommunityPoolSpend.typeUrl,
68+
value: MsgCommunityPoolSpend.encode({
69+
authority: authority.value,
70+
recipient: recipient.value,
71+
amount: [convert.displayToBase(denom.value, {
72+
amount: String(amount.value),
73+
denom: amountDenom.value
74+
})]
75+
}).finish(),
76+
}],
77+
initialDeposit: [convert.displayToBase(denom.value, {
78+
amount: String(deposit.value),
79+
denom: amountDenom.value
80+
})],
81+
proposer: props.sender,
82+
title: title.value,
83+
summary: summary.value,
84+
})
85+
}]
86+
})
87+
88+
89+
const units = computed(() => {
90+
return [{ denom: 'hp', exponent: 18, aliases: [] }];
91+
})
92+
93+
const isValid = computed(() => {
94+
let ok = true
95+
let error = ""
96+
97+
if (!authority.value) {
98+
ok = false
99+
error = "failed to fetch Authority"
100+
}
101+
if (!recipient.value) {
102+
ok = false
103+
error = "Recipient is required"
104+
}
105+
if (!(Number(deposit.value) > 0)) {
106+
ok = false
107+
error = "Initial deposit should be great than 0"
108+
}
109+
if (!(Number(amount.value) > 0)) {
110+
ok = false
111+
error = "Spend amount should be great than 0"
112+
}
113+
return { ok, error }
114+
})
115+
116+
function initial() {
117+
denom.value = 'ahp'
118+
}
119+
120+
onMounted(() => {
121+
getAuthority(props.endpoint).then((res) => {
122+
authority.value = res.address;
123+
}).catch((err) => {
124+
console.error("Failed to fetch authority:", err);
125+
});
126+
127+
getCommunityPool(props.endpoint).then((res) => {
128+
if (!res.pool[0]) throw new Error("Failed to fetch community pool");
129+
const communityPoolBalance = res.pool[0];
130+
communityPoolAvailable.value = convert.baseToDisplay({ amount: communityPoolBalance.amount, denom: communityPoolBalance.denom });
131+
}).catch((err) => {
132+
console.error("Failed to fetch community pool:", err);
133+
});
134+
})
135+
136+
defineExpose({ msgs, isValid, initial })
137+
138+
</script>
139+
<template>
140+
<div>
141+
<div class="form-control">
142+
<label class="label">
143+
<span class="label-text">Sender</span>
144+
</label>
145+
<input :value="sender" type="text"
146+
class="text-gray-600 dark:text-white input border !border-gray-300 dark:!border-gray-600" />
147+
</div>
148+
<div class="form-control">
149+
<label class="label">
150+
<span class="label-text">Title</span>
151+
<input v-model="title" type="text"
152+
class="text-gray-600 dark:text-white input border !border-gray-300 dark:!border-gray-600" />
153+
</label>
154+
</div>
155+
<div class="form-control">
156+
<label class="label">
157+
<span class="label-text">Summary</span>
158+
<input v-model="summary" type="text"
159+
class="text-gray-600 dark:text-white input border !border-gray-300 dark:!border-gray-600" />
160+
</label>
161+
</div>
162+
<div class="form-control">
163+
<label class="label">
164+
<span class="label-text">Initial Deposit</span>
165+
<span>{{ available?.display.amount }}{{ available?.display.denom }}</span>
166+
</label>
167+
<label class="input-group">
168+
<input v-model="deposit" type="number" :placeholder="`Available: ${available?.display.amount}`"
169+
class="input border border-gray-300 dark:border-gray-600 w-full dark:text-white" />
170+
<select v-model="amountDenom" class="select select-bordered dark:text-white">
171+
<option v-for="u in units">{{ u.denom }}</option>
172+
</select>
173+
</label>
174+
</div>
175+
<div class="form-control">
176+
<label class="label">
177+
<span class="label-text">Recipient</span>
178+
</label>
179+
<input v-model="recipient" type="text"
180+
class="text-gray-600 dark:text-white input border !border-gray-300 dark:!border-gray-600" />
181+
</div>
182+
<div class="form-control">
183+
<label class="label">
184+
<span class="label-text">Amount</span>
185+
<span>{{ communityPoolAvailable.amount }}{{ communityPoolAvailable.denom }}</span>
186+
</label>
187+
<label class="input-group">
188+
<input v-model="amount" type="number" :placeholder="`Available: ${communityPoolAvailable.amount}`"
189+
class="input border border-gray-300 dark:border-gray-600 w-full dark:text-white" />
190+
<select v-model="amountDenom" class="select select-bordered dark:text-white">
191+
<option v-for="u in units">{{ u.denom }}</option>
192+
</select>
193+
</label>
194+
</div>
195+
</div>
196+
</template>

0 commit comments

Comments
 (0)