From cb8f2b71bbdbc86c9c304e46e52d1a0e26e86a28 Mon Sep 17 00:00:00 2001 From: NxHuan Date: Mon, 25 Nov 2024 15:13:41 +0700 Subject: [PATCH] update: create proposal in new mainnet --- lib/components/Proposal/CreateProposal.vue | 122 ++++++-- lib/walletStation.ts | 326 ++++++++++++++------- lib/walletStationOld.ts | 174 +++++++++++ 3 files changed, 489 insertions(+), 133 deletions(-) create mode 100644 lib/walletStationOld.ts diff --git a/lib/components/Proposal/CreateProposal.vue b/lib/components/Proposal/CreateProposal.vue index 15ea2cd..90dd6c5 100644 --- a/lib/components/Proposal/CreateProposal.vue +++ b/lib/components/Proposal/CreateProposal.vue @@ -4,6 +4,12 @@ import { walletStation } from '../../walletStation'; import { VueEditor } from "vue3-editor"; import BigNumber from 'bignumber.js'; import { TYPE_PROPOSAL, VOTING_PERIOD_OPTIONS } from '../../../constants'; +import { QueryClient } from '@cosmjs/stargate'; +import { Tendermint37Client } from "@cosmjs/tendermint-rpc"; +import { + QueryModuleAccountByNameRequest, + QueryModuleAccountByNameResponse, +} from "cosmjs-types/cosmos/auth/v1beta1/query"; const props = defineProps({ sender: { type: String, required: true }, @@ -157,6 +163,52 @@ const handleOptionData = data => { } }; +const queryCosmos = async ( + client: QueryClient, + requestType: any, + reponseType: any, + requestInfo: any, + typeUrl: string +) => { + console.log({ + client, + requestType, + reponseType, + requestInfo, + typeUrl + }) + const requestData = Uint8Array.from(requestType.encode(requestInfo).finish()); + + const { value } = await client.queryAbci(typeUrl, requestData); + const res = reponseType.decode(value); + + console.log({ res }) + return res; +}; + +const queryGovAddress = async (urlRpc: string) => { + const cometClient = await Tendermint37Client.connect(urlRpc); + const queryClient = QueryClient.withExtensions(cometClient as any); + + const govRes = (await queryCosmos( + queryClient, + QueryModuleAccountByNameRequest, + QueryModuleAccountByNameResponse, + QueryModuleAccountByNameRequest.fromPartial({ + name: "gov", + }), + "/cosmos.auth.v1beta1.Query/ModuleAccountByName" + )) as QueryModuleAccountByNameResponse; + + let govAddress: any = "" + if (govRes.account) + govAddress = QueryModuleAccountByNameResponse.decode( + govRes.account?.value + ).account?.typeUrl; + + return govAddress +} + const handleCreateProposal = async (e: Event) => { e.preventDefault(); isCreating.value = true; @@ -165,40 +217,41 @@ const handleCreateProposal = async (e: Event) => { const newData = handleOptionData(data); const { title, description, subspace, key, value, amount, newAdmin, contract, recipient, receiveAmount } = newData; const { urlRpc, chainId, sender, denom } = props; + + const govAddress = "orai10d07y265gmmuvt4z0w9aw880jnsr700jf39xhq" + let response: any; try { if (key === TEXT_PROPOSAL) { - response = await walletStation.textProposal(urlRpc, denom, chainId, sender, amount, { - title: title, - description: description, - }); + response = await walletStation.textProposal(sender, govAddress, { title, description, amount, denom }, { urlRpc, chainId }); } else if (key == UPDATE_ADMIN_PROPOSAL) { - response = await walletStation.updateAdminProposal(urlRpc, denom, chainId, sender, amount, { + response = await walletStation.updateAdminProposal(sender, govAddress, { title: title, description: description.trim(), newAdmin: newAdmin, contract: contract, - }); + denom, + amount, + }, { urlRpc, chainId }); } else if (key == COMMUNITY_POOL_SPEND_PROPOSAL) { - response = await walletStation.communityPoolSpendProposal(urlRpc, denom, chainId, sender, amount, { - title, - description: description.trim(), - recipient, - amount: [{ denom: props.denom, amount: (receiveAmount * Math.pow(10, 6)).toString() }], - }); + response = await walletStation.communityPoolSpendProposal(sender, govAddress, + { + title, + description: description.trim(), + recipient, + amount: (receiveAmount * Math.pow(10, 6)).toString(), + denom, + }, { urlRpc, chainId }); } else { - response = await walletStation.parameterChangeProposal(urlRpc, denom, chainId, sender, amount, { - title: title, - description: description, - changes: [ - { - subspace, - key, - value, - }, - ], + response = await walletStation.parameterChangeProposal(sender, govAddress, { + title, + description, amount, - }); + denom, + subspace, + value, + key + }, { urlRpc, chainId }); } isEndProcess.value = true; } catch (err) { @@ -240,11 +293,11 @@ const viewProposal = () => {

Type Proposal

+ class="h-10 w-1/2 border p-2 rounded-lg border-base-300 outline-none hover:cursor-pointer text-white"> + +
- +

Title

{ - +
@@ -376,12 +430,16 @@ const viewProposal = () => { diff --git a/lib/walletStation.ts b/lib/walletStation.ts index 8dcc979..3a07793 100644 --- a/lib/walletStation.ts +++ b/lib/walletStation.ts @@ -1,22 +1,27 @@ // @ts-nocheck -import { TextProposal } from 'cosmjs-types/cosmos/gov/v1beta1/gov'; -import { Any } from 'cosmjs-types/google/protobuf/any'; -import { createWasmAminoConverters } from '@cosmjs/cosmwasm-stargate/build/modules/wasm/aminomessages'; -import { createStakingAminoConverters } from '@cosmjs/stargate/build/modules/staking/aminomessages'; -import { createDistributionAminoConverters } from '@cosmjs/stargate/build/modules/distribution/aminomessages'; -import { createBankAminoConverters } from '@cosmjs/stargate/build/modules/bank/aminomessages'; -import { createGovAminoConverters } from '@cosmjs/stargate/build/modules/gov/aminomessages'; -import { ParameterChangeProposal } from 'cosmjs-types/cosmos/params/v1beta1/params'; +import { Decimal } from '@cosmjs/math'; +import { coin } from '@cosmjs/amino'; +import { + AminoTypes, + GasPrice, + createStakingAminoConverters, + createDistributionAminoConverters, + createBankAminoConverters, + createGovAminoConverters, +} from '@cosmjs/stargate'; +import { createWasmAminoConverters } from '@cosmjs/cosmwasm-stargate'; import { - MsgDeposit, MsgSubmitProposal, - MsgVote, -} from 'cosmjs-types/cosmos/gov/v1beta1/tx'; -import { UpdateAdminProposal } from 'cosmjs-types/cosmwasm/wasm/v1/proposal'; -import { CommunityPoolSpendProposal } from "cosmjs-types/cosmos/distribution/v1beta1/distribution"; -import { GasPrice, AminoTypes } from '@cosmjs/stargate'; + MsgExecLegacyContent, +} from 'cosmjs-types/cosmos/gov/v1/tx'; +import { MsgUpdateAdmin } from 'cosmjs-types/cosmwasm/wasm/v1/tx'; +import { TextProposal } from 'cosmjs-types/cosmos/gov/v1beta1/gov'; +import { + ParameterChangeProposal, + ParamChange, +} from 'cosmjs-types/cosmos/params/v1beta1/params'; +import { MsgCommunityPoolSpend } from 'cosmjs-types/cosmos/distribution/v1beta1/tx'; import * as cosmwasm from '@cosmjs/cosmwasm-stargate'; -import { Decimal } from '@cosmjs/math'; export default class WalletStation { constructor() {} @@ -26,7 +31,7 @@ export default class WalletStation { return window.getOfflineSigner(chainId); }; - signerClient = async (urlRpc, wallet, denom) => { + signerClient = async (urlRpc: string, wallet: any, denom: string) => { const aminoTypes = new AminoTypes({ ...createStakingAminoConverters(), ...createDistributionAminoConverters(), @@ -46,20 +51,29 @@ export default class WalletStation { }; signAndBroadCast = async ( - urlRpc: string, + chainInfo: { + urlRpc: string; + chainId: string; + }, denom: string, - chainId: string, - address: any, + sender: string, messages: any ) => { try { - const wallet = await this.collectWallet(chainId); - const client = await this.signerClient(urlRpc, wallet, denom); + const wallet = await this.collectWallet(chainInfo?.chainId); + console.log({ wallet }); + const client = await this.signerClient( + chainInfo?.urlRpc, + wallet, + denom + ); + console.log({ client }); const result = await client.signAndBroadcast( - address, + sender, messages, 'auto' ); + console.log({ result }); return result; } catch (error) { console.log('signAndBroadcast msg error: ', error); @@ -68,106 +82,216 @@ export default class WalletStation { }; textProposal = async ( - urlRpc: string, - denom: string, - chainId: string, - proposer: any, - amount: any, - changeInfo: any + sender: string, + govAddress: string, + changeInfo: { + title: string; + description: string; + denom: string; + amount: any; + }, + chainInfo: { + urlRpc: string; + chainId: string; + } ) => { - const initial_deposit = [{ denom, amount: amount.toString() }]; + const textProposalInfo = TextProposal.fromPartial({ + title: changeInfo.title, + description: changeInfo.description, + }); + const message = { - typeUrl: '/cosmos.gov.v1beta1.MsgSubmitProposal', - value: { - content: Any.fromPartial({ - typeUrl: '/cosmos.gov.v1beta1.TextProposal', - value: TextProposal.encode(changeInfo).finish(), - }), - proposer: proposer, - initialDeposit: initial_deposit, - }, + typeUrl: '/cosmos.gov.v1.MsgSubmitProposal', + value: MsgSubmitProposal.fromPartial({ + messages: [ + { + typeUrl: '/cosmos.gov.v1.MsgExecLegacyContent', + value: MsgExecLegacyContent.encode({ + authority: govAddress, + content: { + typeUrl: '/cosmos.gov.v1beta1.TextProposal', + value: TextProposal.encode( + textProposalInfo + ).finish(), + }, + }).finish(), + }, + ], + initialDeposit: [coin(changeInfo.amount, changeInfo.denom)], + proposer: sender, + title: textProposalInfo.title, + summary: textProposalInfo.description, + metadata: '', + }), }; - return this.signAndBroadCast(urlRpc, denom, chainId, proposer, [ - message, - ]); + + return this.signAndBroadCast( + chainInfo, + changeInfo.denom, + sender, + [message] + ); }; updateAdminProposal = async ( - urlRpc, - denom, - chainId, - proposer, - amount, - change_info + sender: string, + govAddress: string, + changeInfo: { + contract: string; + description: string; + newAdmin: string; + title: string; + denom: string; + amount: any; + }, + chainInfo: { + urlRpc: string; + chainId: string; + } ) => { - const initial_deposit = [{ denom, amount: amount.toString() }]; const message = { - typeUrl: '/cosmos.gov.v1beta1.MsgSubmitProposal', + typeUrl: '/cosmos.gov.v1.MsgSubmitProposal', value: MsgSubmitProposal.fromPartial({ - content: Any.fromPartial({ - typeUrl: '/cosmwasm.wasm.v1.UpdateAdminProposal', - value: UpdateAdminProposal.encode(change_info).finish(), - }), - proposer: proposer, - initialDeposit: initial_deposit, - }), + messages: [ + { + typeUrl: '/cosmwasm.wasm.v1.MsgUpdateAdmin', + value: MsgUpdateAdmin.encode({ + contract: changeInfo.contract, + newAdmin: changeInfo.newAdmin, + sender: govAddress, + }).finish(), + }, + ], + initialDeposit: [coin(changeInfo.amount, changeInfo.denom)], + proposer: sender, + title: changeInfo.title, + summary: changeInfo.description, + metadata: '', + expedited: true, + } as any), }; - return this.signAndBroadCast(urlRpc, denom, chainId, proposer, [ - message, - ]); + + return this.signAndBroadCast( + chainInfo, + changeInfo.denom, + sender, + [message] + ); }; - communityPoolSpendProposal = async ( - urlRpc, - denom, - chainId, - sender, - amount, - community_pool_info - ) => { - const initial_deposit = [{ denom, amount: amount.toString() }]; + communityPoolSpendProposal = async (sender: string, govAddress: string, changeInfo: { + title: string; + description: string; + recipient: string; + denom: string; + amount: any;}, + chainInfo: { + urlRpc: string; + chainId: string; + }) => { + const communityPoolInfo = MsgCommunityPoolSpend.fromPartial({ + amount: [ + { + amount: changeInfo.amount, + denom: changeInfo.denom, + }, + ], + authority: govAddress, + recipient: changeInfo.recipient, + }); const message = { - typeUrl: '/cosmos.gov.v1beta1.MsgSubmitProposal', - value: { - content: Any.fromPartial({ - typeUrl: - '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', - value: CommunityPoolSpendProposal.encode( - community_pool_info - ).finish(), - }), + typeUrl: '/cosmos.gov.v1.MsgSubmitProposal', + value: MsgSubmitProposal.fromPartial({ + messages: [ + { + typeUrl: + '/cosmos.distribution.v1beta1.MsgCommunityPoolSpend', + value: MsgCommunityPoolSpend.encode( + communityPoolInfo + ).finish(), + }, + ], + initialDeposit: [coin(changeInfo.amount, changeInfo.denom)], proposer: sender, - initialDeposit: initial_deposit, - }, + title: changeInfo.title, + summary: changeInfo.description, + metadata: '', + }), }; - return this.signAndBroadCast(urlRpc, denom, chainId, sender, [ - message, - ]); + + return this.signAndBroadCast( + chainInfo, + changeInfo.denom, + sender, + [message] + ); }; parameterChangeProposal = async ( - urlRpc, - denom, - chainId, - proposer, - amount, - changeInfo + sender: string, + govAddress: string, + changeInfo: { + title: string; + description: string; + amount: any; + denom: string; + subspace: string, + key: string, + value: any + }, + chainInfo: { + urlRpc: string; + chainId: string; + } ) => { - const initial_deposit = [{ denom, amount: amount.toString() }]; - const message = { - typeUrl: '/cosmos.gov.v1beta1.MsgSubmitProposal', - value: { - content: Any.fromPartial({ - typeUrl: '/cosmos.params.v1beta1.ParameterChangeProposal', - value: ParameterChangeProposal.encode(changeInfo).finish(), + console.log({ sender, govAddress, changeInfo, chainInfo }); + const paramChangeInfo = ParameterChangeProposal.fromPartial({ + title: changeInfo.title, + description: changeInfo.description, + changes: [ + ParamChange.fromPartial({ + subspace: changeInfo.subspace, + key: changeInfo.key, + value: changeInfo.value, }), - proposer: proposer, - initialDeposit: initial_deposit, - }, + ], + }); + + console.log({paramChangeInfo}) + const message = { + typeUrl: '/cosmos.gov.v1.MsgSubmitProposal', + value: MsgSubmitProposal.fromPartial({ + messages: [ + { + typeUrl: '/cosmos.gov.v1.MsgExecLegacyContent', + value: MsgExecLegacyContent.encode({ + authority: govAddress, + content: { + typeUrl: + '/cosmos.params.v1beta1.ParameterChangeProposal', + value: ParameterChangeProposal.encode( + paramChangeInfo + ).finish(), + }, + }).finish(), + }, + ], + initialDeposit: [coin(changeInfo.amount, changeInfo.denom)], + proposer: sender, + title: paramChangeInfo.title, + summary: paramChangeInfo.description, + metadata: '', + }), }; - return this.signAndBroadCast(urlRpc, denom, chainId, proposer, [ - message, - ]); + + console.log({ message }); + + return this.signAndBroadCast( + chainInfo, + changeInfo.denom, + sender, + [message] + ); }; } diff --git a/lib/walletStationOld.ts b/lib/walletStationOld.ts new file mode 100644 index 0000000..8dcc979 --- /dev/null +++ b/lib/walletStationOld.ts @@ -0,0 +1,174 @@ +// @ts-nocheck +import { TextProposal } from 'cosmjs-types/cosmos/gov/v1beta1/gov'; +import { Any } from 'cosmjs-types/google/protobuf/any'; +import { createWasmAminoConverters } from '@cosmjs/cosmwasm-stargate/build/modules/wasm/aminomessages'; +import { createStakingAminoConverters } from '@cosmjs/stargate/build/modules/staking/aminomessages'; +import { createDistributionAminoConverters } from '@cosmjs/stargate/build/modules/distribution/aminomessages'; +import { createBankAminoConverters } from '@cosmjs/stargate/build/modules/bank/aminomessages'; +import { createGovAminoConverters } from '@cosmjs/stargate/build/modules/gov/aminomessages'; +import { ParameterChangeProposal } from 'cosmjs-types/cosmos/params/v1beta1/params'; +import { + MsgDeposit, + MsgSubmitProposal, + MsgVote, +} from 'cosmjs-types/cosmos/gov/v1beta1/tx'; +import { UpdateAdminProposal } from 'cosmjs-types/cosmwasm/wasm/v1/proposal'; +import { CommunityPoolSpendProposal } from "cosmjs-types/cosmos/distribution/v1beta1/distribution"; +import { GasPrice, AminoTypes } from '@cosmjs/stargate'; +import * as cosmwasm from '@cosmjs/cosmwasm-stargate'; +import { Decimal } from '@cosmjs/math'; + +export default class WalletStation { + constructor() {} + + collectWallet = async (chainId: string) => { + // @ts-ignore + return window.getOfflineSigner(chainId); + }; + + signerClient = async (urlRpc, wallet, denom) => { + const aminoTypes = new AminoTypes({ + ...createStakingAminoConverters(), + ...createDistributionAminoConverters(), + ...createBankAminoConverters(), + ...createWasmAminoConverters(), + ...createGovAminoConverters(), + }); + return await cosmwasm.SigningCosmWasmClient.connectWithSigner( + urlRpc, + wallet, + { + gasPrice: new GasPrice(Decimal.fromUserInput('0', 6), denom), + prefix: denom, + aminoTypes, + } + ); + }; + + signAndBroadCast = async ( + urlRpc: string, + denom: string, + chainId: string, + address: any, + messages: any + ) => { + try { + const wallet = await this.collectWallet(chainId); + const client = await this.signerClient(urlRpc, wallet, denom); + const result = await client.signAndBroadcast( + address, + messages, + 'auto' + ); + return result; + } catch (error) { + console.log('signAndBroadcast msg error: ', error); + throw error; + } + }; + + textProposal = async ( + urlRpc: string, + denom: string, + chainId: string, + proposer: any, + amount: any, + changeInfo: any + ) => { + const initial_deposit = [{ denom, amount: amount.toString() }]; + const message = { + typeUrl: '/cosmos.gov.v1beta1.MsgSubmitProposal', + value: { + content: Any.fromPartial({ + typeUrl: '/cosmos.gov.v1beta1.TextProposal', + value: TextProposal.encode(changeInfo).finish(), + }), + proposer: proposer, + initialDeposit: initial_deposit, + }, + }; + return this.signAndBroadCast(urlRpc, denom, chainId, proposer, [ + message, + ]); + }; + + updateAdminProposal = async ( + urlRpc, + denom, + chainId, + proposer, + amount, + change_info + ) => { + const initial_deposit = [{ denom, amount: amount.toString() }]; + const message = { + typeUrl: '/cosmos.gov.v1beta1.MsgSubmitProposal', + value: MsgSubmitProposal.fromPartial({ + content: Any.fromPartial({ + typeUrl: '/cosmwasm.wasm.v1.UpdateAdminProposal', + value: UpdateAdminProposal.encode(change_info).finish(), + }), + proposer: proposer, + initialDeposit: initial_deposit, + }), + }; + return this.signAndBroadCast(urlRpc, denom, chainId, proposer, [ + message, + ]); + }; + + communityPoolSpendProposal = async ( + urlRpc, + denom, + chainId, + sender, + amount, + community_pool_info + ) => { + const initial_deposit = [{ denom, amount: amount.toString() }]; + const message = { + typeUrl: '/cosmos.gov.v1beta1.MsgSubmitProposal', + value: { + content: Any.fromPartial({ + typeUrl: + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', + value: CommunityPoolSpendProposal.encode( + community_pool_info + ).finish(), + }), + proposer: sender, + initialDeposit: initial_deposit, + }, + }; + return this.signAndBroadCast(urlRpc, denom, chainId, sender, [ + message, + ]); + }; + + parameterChangeProposal = async ( + urlRpc, + denom, + chainId, + proposer, + amount, + changeInfo + ) => { + const initial_deposit = [{ denom, amount: amount.toString() }]; + const message = { + typeUrl: '/cosmos.gov.v1beta1.MsgSubmitProposal', + value: { + content: Any.fromPartial({ + typeUrl: '/cosmos.params.v1beta1.ParameterChangeProposal', + value: ParameterChangeProposal.encode(changeInfo).finish(), + }), + proposer: proposer, + initialDeposit: initial_deposit, + }, + }; + return this.signAndBroadCast(urlRpc, denom, chainId, proposer, [ + message, + ]); + }; +} + +export const walletStation = new WalletStation();