From 9e70e735a717cbcd0aaf5daf3795df8adc2f86d7 Mon Sep 17 00:00:00 2001 From: mhagel Date: Tue, 15 Aug 2023 13:03:06 -0600 Subject: [PATCH 1/3] - upgrade cosmjs to 0.31.0, use createAltGovAminoConverters to register CommunitySpend in MsgSubmitProposal - encodeCommunitySpend to utils, devnet tests for communitySpend - DRY up tests and add amino tests for all - null check for mindeposit.denom to fix intermittent bug --- package.json | 4 +- .../src/chains/cosmos/filters/enricher.ts | 12 +- .../src/chains/cosmos/storageFetcher.ts | 13 +- .../app/webWallets/keplr_web_wallet.ts | 12 +- .../scripts/controllers/chain/cosmos/chain.ts | 4 +- .../controllers/chain/cosmos/chain.utils.ts | 16 +- .../chain/cosmos/gov/aminomessages.ts | 124 +++++++++ .../chain/cosmos/gov/v1/governance-v1.ts | 23 -- .../chain/cosmos/gov/v1/proposal-v1.ts | 4 +- .../cosmos/gov/v1beta1/governance-v1beta1.ts | 22 -- .../cosmos/gov/v1beta1/proposal-v1beta1.ts | 6 +- .../chain/cosmos/gov/v1beta1/utils-v1beta1.ts | 32 ++- .../client/scripts/helpers/canvas.ts | 13 +- .../ReactionButton/ReactionButton.tsx | 2 +- .../new_proposal/cosmos_proposal_form.tsx | 16 +- packages/commonwealth/package.json | 4 +- .../test/devnet/cosmos/helpers.ts | 46 ++-- .../test/devnet/cosmos/proposal-tx-v1.spec.ts | 159 ++++++----- .../devnet/cosmos/proposal-tx-v1beta1.spec.ts | 160 +++++------ .../src/providers/cosmos.ts | 6 +- .../src/providers/terra.ts | 6 +- yarn.lock | 248 ++++++++++-------- 22 files changed, 551 insertions(+), 381 deletions(-) create mode 100644 packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/aminomessages.ts diff --git a/package.json b/package.json index dd2bfef3842..047f50190bc 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,8 @@ "@capacitor/core": "^4.3.0", "@capacitor/ios": "^4.3.0", "@capacitor/splash-screen": "^4.1.0", - "@cosmjs/stargate": "^0.26.1", - "@cosmjs/tendermint-rpc": "^0.26.1", + "@cosmjs/stargate": "^0.31.0", + "@cosmjs/tendermint-rpc": "^0.31.0", "@solana/web3.js": "^1.30.2", "@types/moment": "^2.13.0", "axios": "^1.3.4", diff --git a/packages/chain-events/src/chains/cosmos/filters/enricher.ts b/packages/chain-events/src/chains/cosmos/filters/enricher.ts index 78fba4541bc..0e08cb7a3f0 100644 --- a/packages/chain-events/src/chains/cosmos/filters/enricher.ts +++ b/packages/chain-events/src/chains/cosmos/filters/enricher.ts @@ -30,10 +30,6 @@ export async function Enrich( ); }); - const dateToUnix = (d?: Date): number | undefined => { - if (d) return Math.floor(d.getTime() / 1000); - return undefined; - }; if (!proposal) throw new Error('Proposal not found!'); return { blockNumber, @@ -46,10 +42,10 @@ export async function Enrich( typeUrl: proposal.content.typeUrl, value: Buffer.from(proposal.content.value).toString('hex'), }, - submitTime: dateToUnix(proposal.submitTime), - depositEndTime: dateToUnix(proposal.depositEndTime), - votingStartTime: dateToUnix(proposal.votingStartTime), - votingEndTime: dateToUnix(proposal.votingEndTime), + submitTime: proposal.submitTime.seconds.toNumber(), + depositEndTime: proposal.depositEndTime.seconds.toNumber(), + votingStartTime: proposal.votingStartTime.seconds.toNumber(), + votingEndTime: proposal.votingEndTime.seconds.toNumber(), }, }; } diff --git a/packages/chain-events/src/chains/cosmos/storageFetcher.ts b/packages/chain-events/src/chains/cosmos/storageFetcher.ts index 3d89d530b6f..bd8ddd3944e 100644 --- a/packages/chain-events/src/chains/cosmos/storageFetcher.ts +++ b/packages/chain-events/src/chains/cosmos/storageFetcher.ts @@ -8,11 +8,6 @@ import { addPrefix, factory } from '../../logging'; import type { IEventData, Api, ISubmitProposal } from './types'; import { EventKind, coinToCoins } from './types'; -const dateToUnix = (d?: Date): number | undefined => { - if (d) return Math.floor(d.getTime() / 1000); - return undefined; -}; - export class StorageFetcher extends IStorageFetcher { private readonly log; @@ -63,10 +58,10 @@ export class StorageFetcher extends IStorageFetcher { typeUrl: proposal.content.typeUrl, value: Buffer.from(proposal.content.value).toString('hex'), }, - submitTime: dateToUnix(proposal.submitTime), - depositEndTime: dateToUnix(proposal.depositEndTime), - votingStartTime: dateToUnix(proposal.votingStartTime), - votingEndTime: dateToUnix(proposal.votingEndTime), + submitTime: proposal.submitTime.seconds.toNumber(), + depositEndTime: proposal.depositEndTime.seconds.toNumber(), + votingStartTime: proposal.votingStartTime.seconds.toNumber(), + votingEndTime: proposal.votingEndTime.seconds.toNumber(), // TODO: do we need to query the tally separately if it's complete? finalTallyResult: proposal.finalTallyResult, totalDeposit: diff --git a/packages/commonwealth/client/scripts/controllers/app/webWallets/keplr_web_wallet.ts b/packages/commonwealth/client/scripts/controllers/app/webWallets/keplr_web_wallet.ts index f3542a2ef17..5dc6cc161a0 100644 --- a/packages/commonwealth/client/scripts/controllers/app/webWallets/keplr_web_wallet.ts +++ b/packages/commonwealth/client/scripts/controllers/app/webWallets/keplr_web_wallet.ts @@ -1,4 +1,8 @@ -import type { AccountData, OfflineDirectSigner } from '@cosmjs/proto-signing'; +import type { + AccountData, + OfflineDirectSigner, + OfflineSigner, +} from '@cosmjs/proto-signing'; import type { ChainInfo, Window as KeplrWindow } from '@keplr-wallet/types'; import type { SessionPayload } from '@canvas-js/interfaces'; @@ -19,7 +23,7 @@ class KeplrWebWalletController implements IWebWallet { private _enabling = false; private _chainId: string; private _chain: string; - private _offlineSigner: OfflineDirectSigner; + private _offlineSigner: OfflineDirectSigner | OfflineSigner; public readonly name = WalletId.Keplr; public readonly label = 'Keplr'; @@ -159,7 +163,9 @@ class KeplrWebWalletController implements IWebWallet { } console.log(`Enabled web wallet for ${this._chainId}`); - this._offlineSigner = window.keplr.getOfflineSigner(this._chainId); + this._offlineSigner = await window.keplr.getOfflineSignerAuto( + this._chainId + ); this._accounts = await this._offlineSigner.getAccounts(); this._enabled = true; this._enabling = false; diff --git a/packages/commonwealth/client/scripts/controllers/chain/cosmos/chain.ts b/packages/commonwealth/client/scripts/controllers/chain/cosmos/chain.ts index fcce6dbe642..7292a1c41d2 100644 --- a/packages/commonwealth/client/scripts/controllers/chain/cosmos/chain.ts +++ b/packages/commonwealth/client/scripts/controllers/chain/cosmos/chain.ts @@ -208,9 +208,9 @@ class CosmosChain implements IChainModule { DEFAULT_MEMO ); console.log(result); - if (cosm.isBroadcastTxFailure(result)) { + if (cosm.isDeliverTxFailure(result)) { throw new Error('TX execution failed.'); - } else if (cosm.isBroadcastTxSuccess(result)) { + } else if (cosm.isDeliverTxSuccess(result)) { const txHash = result.transactionHash; const txResult = await this._tmClient.tx({ hash: Buffer.from(txHash, 'hex'), diff --git a/packages/commonwealth/client/scripts/controllers/chain/cosmos/chain.utils.ts b/packages/commonwealth/client/scripts/controllers/chain/cosmos/chain.utils.ts index 9ba7f559f7f..5a7c013854d 100644 --- a/packages/commonwealth/client/scripts/controllers/chain/cosmos/chain.utils.ts +++ b/packages/commonwealth/client/scripts/controllers/chain/cosmos/chain.utils.ts @@ -1,8 +1,13 @@ import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; import { OfflineSigner } from '@cosmjs/proto-signing'; -import { SigningStargateClient } from '@cosmjs/stargate'; +import { + AminoTypes, + SigningStargateClient, + createDefaultAminoConverters, +} from '@cosmjs/stargate'; import { CosmosApiType } from './chain'; import { LCD } from 'chain-events/src/chains/cosmos/types'; +import { createAltGovAminoConverters } from './gov/aminomessages'; export const getTMClient = async ( rpcUrl: string @@ -38,5 +43,12 @@ export const getSigningClient = async ( url: string, signer: OfflineSigner ): Promise => { - return await SigningStargateClient.connectWithSigner(url, signer); + const aminoTypes = new AminoTypes({ + ...createDefaultAminoConverters(), + ...createAltGovAminoConverters(), + }); + + return await SigningStargateClient.connectWithSigner(url, signer, { + aminoTypes, + }); }; diff --git a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/aminomessages.ts b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/aminomessages.ts new file mode 100644 index 00000000000..3eeb4acd950 --- /dev/null +++ b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/aminomessages.ts @@ -0,0 +1,124 @@ +import { AminoMsg } from '@cosmjs/amino'; +import { AminoConverters } from '@cosmjs/stargate/build/aminotypes'; +import { AminoMsgSubmitProposal } from '@cosmjs/stargate'; +import { + assert, + assertDefinedAndNotNull, + isNonNullObject, +} from '@cosmjs/utils'; +import { CommunityPoolSpendProposal } from 'cosmjs-types/cosmos/distribution/v1beta1/distribution'; +import { TextProposal } from 'cosmjs-types/cosmos/gov/v1beta1/gov'; +import { MsgSubmitProposal } from 'cosmjs-types/cosmos/gov/v1beta1/tx'; +import { Any } from 'cosmjs-types/google/protobuf/any'; + +export function isAminoMsgSubmitProposal( + msg: AminoMsg +): msg is AminoMsgSubmitProposal { + return msg.type === 'cosmos-sdk/MsgSubmitProposal'; +} + +export function createAltGovAminoConverters(): AminoConverters { + return { + /** Modified AminoConverter to add support for CommunityPoolSpendProposal */ + '/cosmos.gov.v1beta1.MsgSubmitProposal': { + aminoType: 'cosmos-sdk/MsgSubmitProposal', + toAmino: ({ + initialDeposit, + proposer, + content, + }: MsgSubmitProposal): AminoMsgSubmitProposal['value'] => { + assertDefinedAndNotNull(content); + let proposal: any; + switch (content.typeUrl) { + case '/cosmos.gov.v1beta1.TextProposal': { + const textProposal = TextProposal.decode(content.value); + proposal = { + type: 'cosmos-sdk/TextProposal', + value: { + description: textProposal.description, + title: textProposal.title, + }, + }; + break; + } + case '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal': { + const spendProposal = CommunityPoolSpendProposal.decode( + content.value + ); + proposal = { + type: 'cosmos-sdk/CommunityPoolSpendProposal', + value: { + description: spendProposal.description, + title: spendProposal.title, + recipient: spendProposal.recipient, + amount: spendProposal.amount, + }, + }; + break; + } + default: + throw new Error(`Unsupported proposal type: '${content.typeUrl}'`); + } + return { + initial_deposit: initialDeposit, + proposer: proposer, + content: proposal, + }; + }, + fromAmino: ({ + initial_deposit, + proposer, + content, + }: AminoMsgSubmitProposal['value']): MsgSubmitProposal => { + let any_content: Any; + switch (content.type) { + case 'cosmos-sdk/TextProposal': { + const { value } = content; + assert(isNonNullObject(value)); + const { title, description } = value as any; + assert(typeof title === 'string'); + assert(typeof description === 'string'); + any_content = Any.fromPartial({ + typeUrl: '/cosmos.gov.v1beta1.TextProposal', + value: TextProposal.encode( + TextProposal.fromPartial({ + title: title, + description: description, + }) + ).finish(), + }); + break; + } + case 'cosmos-sdk/CommunityPoolSpendProposal': { + const { value } = content; + assert(isNonNullObject(value)); + const { title, description, recipient, amount } = value as any; + assert(typeof title === 'string'); + assert(typeof description === 'string'); + assert(typeof recipient === 'string'); + any_content = Any.fromPartial({ + typeUrl: + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', + value: CommunityPoolSpendProposal.encode( + CommunityPoolSpendProposal.fromPartial({ + title: title, + description: description, + recipient: recipient, + amount: Array.from(amount), + }) + ).finish(), + }); + break; + } + default: + throw new Error(`Unsupported proposal type: '${content.type}'`); + } + return { + initialDeposit: Array.from(initial_deposit), + proposer: proposer, + content: any_content, + }; + }, + }, + }; +} diff --git a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1/governance-v1.ts b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1/governance-v1.ts index 31b48d43ec0..1ea4a45c68a 100644 --- a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1/governance-v1.ts +++ b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1/governance-v1.ts @@ -1,7 +1,6 @@ import BN from 'bn.js'; import type { ICosmosProposal } from 'controllers/chain/cosmos/types'; import { CosmosToken } from 'controllers/chain/cosmos/types'; -import { CommunityPoolSpendProposal } from 'cosmjs-types/cosmos/distribution/v1beta1/distribution'; import { Any } from 'common-common/src/cosmos-ts/src/codegen/google/protobuf/any'; import type { ITXModalData } from 'models/interfaces'; @@ -160,28 +159,6 @@ class CosmosGovernanceV1 extends ProposalModule< throw new Error('unsupported'); } - // TODO: support multiple amount types - public encodeCommunitySpend( - title: string, - description: string, - recipient: string, - amount: string - ): Any { - const denom = this._minDeposit.denom; - const coinAmount = [{ amount, denom }]; - const spend = CommunityPoolSpendProposal.fromPartial({ - title, - description, - recipient, - amount: coinAmount, - }); - const prop = CommunityPoolSpendProposal.encode(spend).finish(); - return Any.fromPartial({ - typeUrl: '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', - value: prop, - }); - } - // TODO: support multiple deposit types public async submitProposalTx( sender: CosmosAccount, diff --git a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1/proposal-v1.ts b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1/proposal-v1.ts index a70fbfef3fa..1e7fffdc926 100644 --- a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1/proposal-v1.ts +++ b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1/proposal-v1.ts @@ -1,7 +1,7 @@ import type { MsgDepositEncodeObject } from '@cosmjs/stargate'; import BN from 'bn.js'; import moment from 'moment'; -import { longify } from '@cosmjs/stargate/build/queries/utils'; +import { longify } from '@cosmjs/stargate/build/queryclient'; import { QueryDepositsResponseSDKType, QueryTallyResultResponseSDKType, @@ -290,7 +290,7 @@ export class CosmosProposalV1 extends Proposal< if (this.status !== 'DepositPeriod') { throw new Error('proposal not in deposit period'); } - const cosm = await import('@cosmjs/stargate/build/queries/utils'); + const cosm = await import('@cosmjs/stargate/build/queryclient'); const msg: MsgDepositEncodeObject = { typeUrl: '/cosmos.gov.v1beta1.MsgDeposit', value: { diff --git a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/governance-v1beta1.ts b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/governance-v1beta1.ts index d5cd081fe50..b70e3d3fd34 100644 --- a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/governance-v1beta1.ts +++ b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/governance-v1beta1.ts @@ -151,28 +151,6 @@ class CosmosGovernance extends ProposalModule< throw new Error('unsupported'); } - // TODO: support multiple amount types - public encodeCommunitySpend( - title: string, - description: string, - recipient: string, - amount: string - ): Any { - const denom = this._minDeposit.denom; - const coinAmount = [{ amount, denom }]; - const spend = CommunityPoolSpendProposal.fromPartial({ - title, - description, - recipient, - amount: coinAmount, - }); - const prop = CommunityPoolSpendProposal.encode(spend).finish(); - return Any.fromPartial({ - typeUrl: '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', - value: prop, - }); - } - // TODO: support multiple deposit types public async submitProposalTx( sender: CosmosAccount, diff --git a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/proposal-v1beta1.ts b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/proposal-v1beta1.ts index 2f33e9b1d27..8b29335ed5a 100644 --- a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/proposal-v1beta1.ts +++ b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/proposal-v1beta1.ts @@ -286,7 +286,9 @@ export class CosmosProposal extends Proposal< case 'Rejected': return ProposalStatus.Failed; case 'VotingPeriod': - return +this.support > 0.5 && this.veto <= 1 / 3 + return typeof this.support === 'number' && + +this.support > 0.5 && + this.veto <= 1 / 3 ? ProposalStatus.Passing : ProposalStatus.Failing; case 'DepositPeriod': @@ -303,7 +305,7 @@ export class CosmosProposal extends Proposal< if (this.status !== 'DepositPeriod') { throw new Error('proposal not in deposit period'); } - const cosm = await import('@cosmjs/stargate/build/queries/utils'); + const cosm = await import('@cosmjs/stargate/build/queryclient'); const msg: MsgDepositEncodeObject = { typeUrl: '/cosmos.gov.v1beta1.MsgDeposit', value: { diff --git a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/utils-v1beta1.ts b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/utils-v1beta1.ts index 3b0d1aa73ba..3f1ef380c90 100644 --- a/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/utils-v1beta1.ts +++ b/packages/commonwealth/client/scripts/controllers/chain/cosmos/gov/v1beta1/utils-v1beta1.ts @@ -15,7 +15,7 @@ import { MsgSubmitProposalEncodeObject, MsgVoteEncodeObject, } from '@cosmjs/stargate'; -import { longify } from '@cosmjs/stargate/build/queries/utils'; +import { longify } from '@cosmjs/stargate/build/queryclient'; import type { CoinObject, @@ -178,10 +178,10 @@ export const msgToIProposal = (p: Proposal): ICosmosProposal | null => { type, title, description, - submitTime: moment.unix(p.submitTime.valueOf() / 1000), - depositEndTime: moment.unix(p.depositEndTime.valueOf() / 1000), - votingEndTime: moment.unix(p.votingEndTime.valueOf() / 1000), - votingStartTime: moment.unix(p.votingStartTime.valueOf() / 1000), + submitTime: moment.unix(p.submitTime.seconds.toNumber()), + depositEndTime: moment.unix(p.depositEndTime.seconds.toNumber()), + votingEndTime: moment.unix(p.votingEndTime.seconds.toNumber()), + votingStartTime: moment.unix(p.votingStartTime.seconds.toNumber()), proposer: null, spendRecipient, spendAmount, @@ -244,3 +244,25 @@ export const encodeTextProposal = (title: string, description: string): Any => { value: Uint8Array.from(TextProposal.encode(tProp).finish()), }); }; + +// TODO: support multiple amount types +export const encodeCommunitySpend = ( + title: string, + description: string, + recipient: string, + amount: string, + denom: string +): Any => { + const coinAmount = [{ amount, denom }]; + const spend = CommunityPoolSpendProposal.fromPartial({ + title, + description, + recipient, + amount: coinAmount, + }); + const prop = CommunityPoolSpendProposal.encode(spend).finish(); + return Any.fromPartial({ + typeUrl: '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', + value: prop, + }); +}; diff --git a/packages/commonwealth/client/scripts/helpers/canvas.ts b/packages/commonwealth/client/scripts/helpers/canvas.ts index fc2fad6e640..fca13f3bab1 100644 --- a/packages/commonwealth/client/scripts/helpers/canvas.ts +++ b/packages/commonwealth/client/scripts/helpers/canvas.ts @@ -1,4 +1,3 @@ -import createHash from 'create-hash'; import type { Action, Session } from '@canvas-js/interfaces'; import { getCosmosSignatureData } from 'controllers/server/sessionSigners/cosmos'; @@ -64,7 +63,7 @@ export const verify = async ({ bech32.bech32.decode(sessionPayload.from).prefix === 'terra' ) { const canvas = await import('@canvas-js/interfaces'); - const prefix = cosmEncoding.Bech32.decode(sessionPayload.from).prefix; + const prefix = cosmEncoding.fromBech32(sessionPayload.from).prefix; const signDocDigest = new cosmCrypto.Sha256( Buffer.from(canvas.serializeSessionPayload(sessionPayload)) ).digest(); @@ -81,7 +80,7 @@ export const verify = async ({ ); if ( payload.from !== - cosmEncoding.Bech32.encode( + cosmEncoding.toBech32( prefix, cosmAmino.rawSecp256k1PubkeyToRawAddress(pubkey) ) @@ -127,7 +126,7 @@ export const verify = async ({ const signDocDigest = new cosmCrypto.Sha256( cosmAmino.serializeSignDoc(signDocPayload) ).digest(); - const prefix = 'cosmos'; // not: Bech32.decode(payload.from).prefix; + const prefix = 'cosmos'; // not: fromBech32(payload.from).prefix; const extendedSecp256k1Signature = cosmCrypto.ExtendedSecp256k1Signature.fromFixedLength( Buffer.from(signature, 'hex') @@ -140,7 +139,7 @@ export const verify = async ({ ); return ( actionSignerAddress === - cosmEncoding.Bech32.encode( + cosmEncoding.toBech32( prefix, cosmAmino.rawSecp256k1PubkeyToRawAddress(pubkey) ) @@ -154,14 +153,14 @@ export const verify = async ({ const signDocDigest = new cosmCrypto.Sha256( cosmAmino.serializeSignDoc(signDocPayload) ).digest(); - const prefix = cosmEncoding.Bech32.decode(payload.from).prefix; + const prefix = cosmEncoding.fromBech32(payload.from).prefix; // decode "{ pub_key, signature }" to an object with { pubkey, signature } const { pubkey, signature: decodedSignature } = cosmAmino.decodeSignature( JSON.parse(signature) ); if ( payload.from !== - cosmEncoding.Bech32.encode( + cosmEncoding.toBech32( prefix, cosmAmino.rawSecp256k1PubkeyToRawAddress(pubkey) ) diff --git a/packages/commonwealth/client/scripts/views/pages/discussions/ThreadCard/ThreadOptions/ReactionButton/ReactionButton.tsx b/packages/commonwealth/client/scripts/views/pages/discussions/ThreadCard/ThreadOptions/ReactionButton/ReactionButton.tsx index 6aa6840698c..030728e7708 100644 --- a/packages/commonwealth/client/scripts/views/pages/discussions/ThreadCard/ThreadOptions/ReactionButton/ReactionButton.tsx +++ b/packages/commonwealth/client/scripts/views/pages/discussions/ThreadCard/ThreadOptions/ReactionButton/ReactionButton.tsx @@ -70,7 +70,7 @@ export const ReactionButton = ({ if (hasReacted) { deleteThreadReaction({ chainId: app.activeChainId(), - address: app.user.activeAccount.address, + address: app.user.activeAccount?.address, threadId: thread.id, reactionId: reactedId as number, }).catch((e) => { diff --git a/packages/commonwealth/client/scripts/views/pages/new_proposal/cosmos_proposal_form.tsx b/packages/commonwealth/client/scripts/views/pages/new_proposal/cosmos_proposal_form.tsx index 97789cfd69f..41748622464 100644 --- a/packages/commonwealth/client/scripts/views/pages/new_proposal/cosmos_proposal_form.tsx +++ b/packages/commonwealth/client/scripts/views/pages/new_proposal/cosmos_proposal_form.tsx @@ -5,7 +5,10 @@ import { notifyError } from 'controllers/app/notifications'; import type CosmosAccount from 'controllers/chain/cosmos/account'; import type Cosmos from 'controllers/chain/cosmos/adapter'; import { CosmosToken } from 'controllers/chain/cosmos/types'; -import { encodeTextProposal } from 'controllers/chain/cosmos/gov/v1beta1/utils-v1beta1'; +import { + encodeCommunitySpend, + encodeTextProposal, +} from 'controllers/chain/cosmos/gov/v1beta1/utils-v1beta1'; import app from 'state'; import { CWButton } from '../../components/component_kit/cw_button'; @@ -63,7 +66,7 @@ export const CosmosProposalForm = () => { }} /> { @@ -82,7 +85,7 @@ export const CosmosProposalForm = () => { )} {cosmosProposalType !== 'textProposal' && ( { @@ -99,7 +102,7 @@ export const CosmosProposalForm = () => { const _deposit = deposit ? new CosmosToken( - cosmos.governance.minDeposit.denom, + cosmos.governance.minDeposit?.denom, deposit, false ) @@ -108,11 +111,12 @@ export const CosmosProposalForm = () => { if (cosmosProposalType === 'textProposal') { prop = encodeTextProposal(title, description); } else if (cosmosProposalType === 'communitySpend') { - prop = cosmos.governance.encodeCommunitySpend( + prop = encodeCommunitySpend( title, description, recipient, - payoutAmount.toString() + payoutAmount.toString(), + cosmos.governance.minDeposit?.denom ); } else { throw new Error('Unknown Cosmos proposal type.'); diff --git a/packages/commonwealth/package.json b/packages/commonwealth/package.json index 7f32205e2a4..9d6817ccaf9 100644 --- a/packages/commonwealth/package.json +++ b/packages/commonwealth/package.json @@ -84,8 +84,8 @@ "@canvas-js/chain-ethereum": "^0.0.50-pre4", "@canvas-js/interfaces": "^0.0.50-pre4", "@capacitor/browser": "^4.0.1", - "@cosmjs/amino": "^0.26.1", - "@cosmjs/proto-signing": "^0.26.1", + "@cosmjs/amino": "^0.31.0", + "@cosmjs/proto-signing": "^0.31.0", "@ethersproject/abi": "^5.7.0", "@ethersproject/address": "^5.7.0", "@ethersproject/bytes": "^5.7.0", diff --git a/packages/commonwealth/test/devnet/cosmos/helpers.ts b/packages/commonwealth/test/devnet/cosmos/helpers.ts index 924b204ad14..92111111a77 100644 --- a/packages/commonwealth/test/devnet/cosmos/helpers.ts +++ b/packages/commonwealth/test/devnet/cosmos/helpers.ts @@ -1,31 +1,12 @@ -import chai from 'chai'; import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing'; -import { StdFee } from '@cosmjs/amino'; +import { Secp256k1HdWallet, StdFee } from '@cosmjs/amino'; +import { DeliverTxResponse } from '@cosmjs/stargate'; -import { ProposalStatus as ProposalStatusV1 } from 'common-common/src/cosmos-ts/src/codegen/cosmos/gov/v1/gov'; -import { - ProposalStatus, - VoteOption, -} from 'cosmjs-types/cosmos/gov/v1beta1/gov'; -import { VoteOption as VoteOptionV1 } from 'common-common/src/cosmos-ts/src/codegen/cosmos/gov/v1/gov'; import { CosmosToken } from 'controllers/chain/cosmos/types'; import { - encodeMsgVote, - encodeMsgSubmitProposal, - encodeTextProposal, -} from 'controllers/chain/cosmos/gov/v1beta1/utils-v1beta1'; -import { - getLCDClient, - getRPCClient, getSigningClient, getTMClient, } from 'controllers/chain/cosmos/chain.utils'; -import { - getActiveProposalsV1, - getCompletedProposalsV1, -} from 'controllers/chain/cosmos/gov/v1/utils-v1'; -import { CosmosApiType } from 'controllers/chain/cosmos/chain'; -import { LCD } from 'chain-events/src/chains/cosmos/types'; const mnemonic = 'ignore medal pitch lesson catch stadium victory jewel first stairs humble excuse scrap clutch cup daughter bench length sell goose deliver critic favorite thought'; @@ -36,18 +17,29 @@ const DEFAULT_FEE: StdFee = { const DEFAULT_MEMO = ''; export const deposit = new CosmosToken('stake', 100000, false); -export const setupTestSigner = async (rpcUrl: string) => { - const signer = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { - prefix: 'cosmos', - }); +export const setupTestSigner = async (rpcUrl: string, isAmino?: boolean) => { + let signer; + if (isAmino) { + signer = await Secp256k1HdWallet.fromMnemonic(mnemonic, { + prefix: 'cosmos', + }); + } else { + signer = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { + prefix: 'cosmos', + }); + } const client = await getSigningClient(rpcUrl, signer); const accounts = await signer.getAccounts(); const signerAddress = accounts[0].address; return { client, signerAddress }; }; -export const sendTx = async (rpcUrl, tx) => { - const { client, signerAddress } = await setupTestSigner(rpcUrl); +export const sendTx = async ( + rpcUrl: string, + tx: any, + isAmino?: boolean +): Promise => { + const { client, signerAddress } = await setupTestSigner(rpcUrl, isAmino); const result = await client.signAndBroadcast( signerAddress, [tx], diff --git a/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1.spec.ts b/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1.spec.ts index a313a63932d..973e9812f09 100644 --- a/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1.spec.ts +++ b/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1.spec.ts @@ -1,11 +1,15 @@ import chai from 'chai'; -import { ProposalStatus as ProposalStatusV1 } from 'common-common/src/cosmos-ts/src/codegen/cosmos/gov/v1/gov'; +import { + ProposalStatus as ProposalStatusV1, + voteOptionToJSON, +} from 'common-common/src/cosmos-ts/src/codegen/cosmos/gov/v1/gov'; import { VoteOption as VoteOptionV1 } from 'common-common/src/cosmos-ts/src/codegen/cosmos/gov/v1/gov'; import { encodeMsgVote, encodeMsgSubmitProposal, encodeTextProposal, + encodeCommunitySpend, } from 'controllers/chain/cosmos/gov/v1beta1/utils-v1beta1'; import { getLCDClient } from 'controllers/chain/cosmos/chain.utils'; import { @@ -14,6 +18,7 @@ import { } from 'controllers/chain/cosmos/gov/v1/utils-v1'; import { LCD } from 'chain-events/src/chains/cosmos/types'; import { deposit, sendTx, setupTestSigner, waitOneBlock } from './helpers'; +import { isDeliverTxSuccess } from '@cosmjs/stargate'; const { expect, assert } = chai; @@ -21,7 +26,7 @@ const idV1 = 'csdk-v1'; // CI devnet const rpcUrl = `http://localhost:8080/cosmosAPI/${idV1}`; const lcdUrl = `http://localhost:8080/cosmosLCD/${idV1}`; -describe('Proposal Transaction Tests - gov v1 chain using v1beta1 signer (csdk-v1)', () => { +describe('Proposal Transaction Tests - gov v1 chain using cosmJs signer (csdk-v1)', () => { let lcd: LCD; let signer: string; before(async () => { @@ -39,92 +44,108 @@ describe('Proposal Transaction Tests - gov v1 chain using v1beta1 signer (csdk-v return activeProposals; }; - it('creates a proposal', async () => { - const content = encodeTextProposal(`v1 title`, `v1 description`); + const proposalTest = async ( + content: any, + expectedProposalType: string, + isAmino?: boolean + ) => { const msg = encodeMsgSubmitProposal(signer, deposit, content); - const resp = await sendTx(rpcUrl, msg); + const resp = await sendTx(rpcUrl, msg, isAmino); + expect(isDeliverTxSuccess(resp)).to.be.true; expect(resp.transactionHash).to.not.be.undefined; expect(resp.rawLog).to.not.be.undefined; await waitOneBlock(rpcUrl); const activeProposals = await getActiveVotingProposals(); - expect(activeProposals.length).to.be.greaterThan(0); - }); - it('votes NO on an active proposal', async () => { - await waitOneBlock(rpcUrl); - const activeProposals = await getActiveVotingProposals(); - - assert.isAtLeast(activeProposals.length, 1); - const proposal = activeProposals[0]; - - const msg = encodeMsgVote(signer, proposal.id, VoteOptionV1.VOTE_OPTION_NO); - const resp = await sendTx(rpcUrl, msg); - - expect(resp.transactionHash).to.not.be.undefined; - expect(resp.rawLog).to.not.be.undefined; - expect(resp.rawLog).to.include('VOTE_OPTION_NO'); - expect(resp.rawLog).to.not.include('VOTE_OPTION_YES'); - }); - it('votes NO WITH VETO on an active proposal', async () => { - await waitOneBlock(rpcUrl); - const activeProposals = await getActiveVotingProposals(); - - assert.isAtLeast(activeProposals.length, 1); - const proposal = activeProposals[0]; - - const msg = encodeMsgVote( - signer, - proposal.id, - VoteOptionV1.VOTE_OPTION_NO_WITH_VETO + const onchainProposal = activeProposals[activeProposals.length - 1]; + expect((onchainProposal.messages[0] as any)?.content?.['@type']).to.be.eql( + expectedProposalType ); - const resp = await sendTx(rpcUrl, msg); + }; - expect(resp.transactionHash).to.not.be.undefined; - expect(resp.rawLog).to.not.be.undefined; - expect(resp.rawLog).to.include('VOTE_OPTION_NO_WITH_VETO'); - expect(resp.rawLog).to.not.include('VOTE_OPTION_YES'); - }); - it('votes ABSTAIN on an active proposal', async () => { + const voteTest = async ( + voteOption: number, + isAmino?: boolean + ): Promise => { await waitOneBlock(rpcUrl); const activeProposals = await getActiveVotingProposals(); - assert.isAtLeast(activeProposals.length, 1); const proposal = activeProposals[0]; + const msg = encodeMsgVote(signer, proposal.id, voteOption); - const msg = encodeMsgVote( - signer, - proposal.id, - VoteOptionV1.VOTE_OPTION_ABSTAIN - ); - const resp = await sendTx(rpcUrl, msg); + const resp = await sendTx(rpcUrl, msg, isAmino); expect(resp.transactionHash).to.not.be.undefined; expect(resp.rawLog).to.not.be.undefined; - expect(resp.rawLog).to.include('VOTE_OPTION_ABSTAIN'); - expect(resp.rawLog).to.not.include('VOTE_OPTION_YES'); - }); - it('votes YES on an active proposal', async () => { - await waitOneBlock(rpcUrl); - const activeProposals = await getActiveVotingProposals(); - - expect(activeProposals).to.not.be.undefined; - expect(activeProposals.length).to.be.greaterThan(0); - - const proposal = activeProposals[0]; - - const msg = encodeMsgVote( - signer, - proposal.id, - VoteOptionV1.VOTE_OPTION_YES - ); - const resp = await sendTx(rpcUrl, msg); + expect(resp.rawLog).to.include(voteOptionToJSON(voteOption)); + }; - expect(resp.transactionHash).to.not.be.undefined; - expect(resp.rawLog).to.not.be.undefined; - expect(resp.rawLog).to.include('VOTE_OPTION_YES'); - expect(resp.rawLog).to.not.include('VOTE_OPTION_NO'); + describe('Direct Signer', () => { + it('creates a text proposal', async () => { + const content = encodeTextProposal(`v1 title`, `v1 description`); + await proposalTest(content, '/cosmos.gov.v1beta1.TextProposal'); + }); + it('creates a community spend proposal', async () => { + const content = encodeCommunitySpend( + `v1 spend title`, + `v1 spend description`, + 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', + '100', + 'stake' + ); + await proposalTest( + content, + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal' + ); + }); + it('votes NO on an active proposal', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_NO); + }); + it('votes NO WITH VETO on an active proposal', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_NO_WITH_VETO); + }); + it('votes ABSTAIN on an active proposal', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_ABSTAIN); + }); + it('votes YES on an active proposal', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_YES); + }); + }); + describe('Amino Signer', () => { + it('creates a text proposal with legacy amino', async () => { + const content = encodeTextProposal(`v1 title`, `v1 description`); + await proposalTest(content, '/cosmos.gov.v1beta1.TextProposal', true); + }); + // TODO: Unsupported. Un-skip this in + // https://github.com/hicommonwealth/commonwealth/issues/4821 + it.skip('creates a community spend proposal with legacy amino', async () => { + const content = encodeCommunitySpend( + `v1 spend title amino`, + `v1 spend description amino`, + 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', + '10', + 'stake' + ); + await proposalTest( + content, + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', + true + ); + }); + it('votes NO on an active proposal with legacy amino', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_NO, true); + }); + it('votes NO WITH VETO on an active proposal with legacy amino', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_NO_WITH_VETO, true); + }); + it('votes ABSTAIN on an active proposal with legacy amino', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_ABSTAIN, true); + }); + it('votes YES on an active proposal with legacy amino', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_YES, true); + }); }); }); diff --git a/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1beta1.spec.ts b/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1beta1.spec.ts index 35ff6218ef7..7db83509593 100644 --- a/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1beta1.spec.ts +++ b/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1beta1.spec.ts @@ -1,4 +1,5 @@ import chai from 'chai'; +import { isDeliverTxSuccess } from '@cosmjs/stargate'; import { ProposalStatus, VoteOption, @@ -7,8 +8,8 @@ import { encodeMsgVote, encodeMsgSubmitProposal, encodeTextProposal, - getCompletedProposalsV1Beta1, getActiveProposalsV1Beta1, + encodeCommunitySpend, } from 'controllers/chain/cosmos/gov/v1beta1/utils-v1beta1'; import { getRPCClient, @@ -49,99 +50,112 @@ describe('Proposal Transaction Tests - gov v1beta1 chain (csdk-beta-ci)', () => return vote; }; - it('creates a proposal', async () => { - const content = encodeTextProposal( - `beta test title`, - `beta test description` - ); + const proposalTest = async ( + content: any, + expectedProposalType: string, + isAmino?: boolean + ) => { const msg = encodeMsgSubmitProposal(signer, deposit, content); - const resp = await sendTx(rpcUrlBeta, msg); + const resp = await sendTx(rpcUrlBeta, msg, isAmino); + expect(isDeliverTxSuccess(resp)).to.be.true; expect(resp.transactionHash).to.not.be.undefined; expect(resp.rawLog).to.not.be.undefined; await waitOneBlock(rpcUrlBeta); const activeProposals = await getActiveVotingProposals(); - expect(activeProposals.length).to.be.greaterThan(0); - }); - it('votes NO on an active proposal', async () => { - await waitOneBlock(rpcUrlBeta); - const activeProposals = await getActiveVotingProposals(); - - assert.isAtLeast(activeProposals.length, 1); - const proposal = activeProposals[0]; - - const msg = encodeMsgVote( - signer, - proposal.proposalId, - VoteOption.VOTE_OPTION_NO - ); - const resp = await sendTx(rpcUrlBeta, msg); + const onchainProposal = activeProposals[activeProposals.length - 1]; + expect(onchainProposal?.content?.typeUrl).to.be.eql(expectedProposalType); + }; - expect(resp.transactionHash).to.not.be.undefined; - expect(resp.rawLog).to.not.be.undefined; - const voteValue = parseVoteValue(resp.rawLog); - expect(voteValue.option).to.eql(VoteOption.VOTE_OPTION_NO); - }); - it('votes NO WITH VETO on an active proposal', async () => { + const voteTest = async ( + voteOption: number, + isAmino?: boolean + ): Promise => { await waitOneBlock(rpcUrlBeta); const activeProposals = await getActiveVotingProposals(); - assert.isAtLeast(activeProposals.length, 1); const proposal = activeProposals[0]; + const msg = encodeMsgVote(signer, proposal.proposalId, voteOption); - const msg = encodeMsgVote( - signer, - proposal.proposalId, - VoteOption.VOTE_OPTION_NO_WITH_VETO - ); - const resp = await sendTx(rpcUrlBeta, msg); + const resp = await sendTx(rpcUrlBeta, msg, isAmino); expect(resp.transactionHash).to.not.be.undefined; expect(resp.rawLog).to.not.be.undefined; const voteValue = parseVoteValue(resp.rawLog); - expect(voteValue.option).to.eql(VoteOption.VOTE_OPTION_NO_WITH_VETO); - }); - it('votes ABSTAIN on an active proposal', async () => { - await waitOneBlock(rpcUrlBeta); - const activeProposals = await getActiveVotingProposals(); - - assert.isAtLeast(activeProposals.length, 1); - const proposal = activeProposals[0]; - - const msg = encodeMsgVote( - signer, - proposal.proposalId, - VoteOption.VOTE_OPTION_ABSTAIN - ); - const resp = await sendTx(rpcUrlBeta, msg); + expect(voteValue.option).to.eql(voteOption); + }; - expect(resp.transactionHash).to.not.be.undefined; - expect(resp.rawLog).to.not.be.undefined; - const voteValue = parseVoteValue(resp.rawLog); - expect(voteValue.option).to.eql(VoteOption.VOTE_OPTION_ABSTAIN); + describe('Direct signer', () => { + it('creates a text proposal', async () => { + const content = encodeTextProposal( + `beta text title`, + `beta text description` + ); + await proposalTest(content, '/cosmos.gov.v1beta1.TextProposal'); + }); + it('creates a community spend proposal', async () => { + const content = encodeCommunitySpend( + `beta spend title`, + `beta spend description`, + 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', + '100', + 'stake' + ); + await proposalTest( + content, + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal' + ); + }); + it('votes NO on an active proposal', async () => { + await voteTest(VoteOption.VOTE_OPTION_NO); + }); + it('votes NO WITH VETO on an active proposal', async () => { + await voteTest(VoteOption.VOTE_OPTION_NO_WITH_VETO); + }); + it('votes ABSTAIN on an active proposal', async () => { + await voteTest(VoteOption.VOTE_OPTION_ABSTAIN); + }); + it('votes YES on an active proposal', async () => { + await voteTest(VoteOption.VOTE_OPTION_YES); + }); }); - it('votes YES on an active proposal', async () => { - await waitOneBlock(rpcUrlBeta); - const activeProposals = await getActiveVotingProposals(); - - expect(activeProposals).to.not.be.undefined; - expect(activeProposals.length).to.be.greaterThan(0); - - const proposal = activeProposals[0]; - const msg = encodeMsgVote( - signer, - proposal.proposalId, - VoteOption.VOTE_OPTION_YES - ); - const resp = await sendTx(rpcUrlBeta, msg); - - expect(resp.transactionHash).to.not.be.undefined; - expect(resp.rawLog).to.not.be.undefined; - const voteValue = parseVoteValue(resp.rawLog); - expect(voteValue.option).to.eql(VoteOption.VOTE_OPTION_YES); + describe('Amino signing', () => { + it('creates a text proposal with legacy amino', async () => { + const content = encodeTextProposal( + `beta text title`, + `beta text description` + ); + await proposalTest(content, '/cosmos.gov.v1beta1.TextProposal', true); + }); + it('creates a community spend proposal with legacy amino', async () => { + const content = encodeCommunitySpend( + `beta spend title amino`, + `beta spend description amino`, + 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', + '100', + 'stake' + ); + await proposalTest( + content, + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', + true + ); + }); + it('votes NO on an active proposal with legacy amino', async () => { + await voteTest(VoteOption.VOTE_OPTION_NO, true); + }); + it('votes NO WITH VETO on an active proposal with legacy amino', async () => { + await voteTest(VoteOption.VOTE_OPTION_NO_WITH_VETO, true); + }); + it('votes ABSTAIN on an active proposal with legacy amino', async () => { + await voteTest(VoteOption.VOTE_OPTION_ABSTAIN, true); + }); + it('votes YES on an active proposal with legacy amino', async () => { + await voteTest(VoteOption.VOTE_OPTION_YES, true); + }); }); }); diff --git a/packages/token-balance-cache/src/providers/cosmos.ts b/packages/token-balance-cache/src/providers/cosmos.ts index 9c91ac3850d..2ff1492ef48 100644 --- a/packages/token-balance-cache/src/providers/cosmos.ts +++ b/packages/token-balance-cache/src/providers/cosmos.ts @@ -4,7 +4,7 @@ import { setupBankExtension, setupStakingExtension, } from '@cosmjs/stargate'; -import { Bech32 } from '@cosmjs/encoding'; +import { toBech32, fromBech32 } from '@cosmjs/encoding'; import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; import { BalanceType } from 'common-common/src/types'; @@ -39,8 +39,8 @@ export default class CosmosBalanceProvider extends BalanceProvider< if (!node.bech32) { throw new Error('No cosmos prefix found!'); } - const { data } = Bech32.decode(address); - const encodedAddress = Bech32.encode(node.bech32, data); + const { data } = fromBech32(address); + const encodedAddress = toBech32(node.bech32, data); const api = await this.getExternalProvider(node); diff --git a/packages/token-balance-cache/src/providers/terra.ts b/packages/token-balance-cache/src/providers/terra.ts index 5ef8d9d951e..6578fed3716 100644 --- a/packages/token-balance-cache/src/providers/terra.ts +++ b/packages/token-balance-cache/src/providers/terra.ts @@ -1,7 +1,7 @@ import BN from 'bn.js'; import axios from 'axios'; import { BalanceType } from 'common-common/src/types'; -import { Bech32 } from '@cosmjs/encoding'; +import { toBech32, fromBech32 } from '@cosmjs/encoding'; import type { IChainNode } from '../types'; import { BalanceProvider } from '../types'; @@ -80,8 +80,8 @@ export default class TerraBalanceProvider extends BalanceProvider< if (!node.bech32) { throw new Error('No cosmos prefix found!'); } - const { data } = Bech32.decode(address); - const encodedAddress = Bech32.encode(node.bech32, data); + const { data } = fromBech32(address); + const encodedAddress = toBech32(node.bech32, data); const [terraBalanceFn, stakedBalanceFn] = await this.getExternalProvider( node diff --git a/yarn.lock b/yarn.lock index c426f37907d..8393b99d8da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1997,41 +1997,23 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@confio/ics23@^0.6.3": - version "0.6.5" - resolved "https://registry.yarnpkg.com/@confio/ics23/-/ics23-0.6.5.tgz#9c21a61089d4c3c2429875a69d6d9cd8c87512aa" - integrity sha512-1GdPMsaP/l8JSF4P4HWFLBhdcxHcJT8lS0nknBYNSZ1XrJOsJKUy6EkOwd9Pa1qJkXzY2gyNv7MdHR+AIwSTAg== +"@confio/ics23@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@confio/ics23/-/ics23-0.6.8.tgz#2a6b4f1f2b7b20a35d9a0745bb5a446e72930b3d" + integrity sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w== dependencies: - js-sha512 "^0.8.0" + "@noble/hashes" "^1.0.0" protobufjs "^6.8.8" - ripemd160 "^2.0.2" - sha.js "^2.4.11" -"@cosmjs/amino@0.26.1", "@cosmjs/amino@^0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.26.1.tgz#78e177307756791d5c31da1d7d0f42a55a0a5d7a" - integrity sha512-8jcEwsLrLW2ltJdNQzdbx+g6Ii9lgG3j7hqaSatnqJE+8OyUjjLH1beigrpz9PhRF3qzQS8WFweTNkkTgNEcSA== +"@cosmjs/amino@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.31.0.tgz#49b33047295002804ad51bdf7ec0c2c97f1b553d" + integrity sha512-xJ5CCEK7H79FTpOuEmlpSzVI+ZeYESTVvO3wHDgbnceIyAne3C68SvyaKqLUR4uJB0Z4q4+DZHbqW6itUiv4lA== dependencies: - "@cosmjs/crypto" "0.26.1" - "@cosmjs/encoding" "0.26.1" - "@cosmjs/math" "0.26.1" - "@cosmjs/utils" "0.26.1" - -"@cosmjs/crypto@0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.26.1.tgz#2b72c74a66f81080f7c1ba2dbd20acf8e887b05a" - integrity sha512-KzX++HMvCYjekdYr6vRRfJmAzJvdB10nRSyudzirn4/055yKh9oKk/wgjq9QGOIrMzEZNoQJNE0RndbS3nRccA== - dependencies: - "@cosmjs/encoding" "0.26.1" - "@cosmjs/math" "0.26.1" - "@cosmjs/utils" "0.26.1" - bip39 "^3.0.2" - bn.js "^4.11.8" - elliptic "^6.5.3" - js-sha3 "^0.8.0" - libsodium-wrappers "^0.7.6" - ripemd160 "^2.0.2" - sha.js "^2.4.11" + "@cosmjs/crypto" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/utils" "^0.31.0" "@cosmjs/crypto@^0.24.1": version "0.24.1" @@ -2051,14 +2033,18 @@ sha.js "^2.4.11" unorm "^1.5.0" -"@cosmjs/encoding@0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.26.1.tgz#79bec892aaa831a974c9f854571d69caa549b225" - integrity sha512-wDFRvSQrTVIX7k4dPPSS/NmaytTU8ludDXi06TsaqVrgL/OR1hcGEkHhoKjodhZ2NS4gLvncI8XagV3SFySGhA== +"@cosmjs/crypto@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.31.0.tgz#0be3867ada0155da19c45a51f5fde08e84f9ec4b" + integrity sha512-UaqCe6Tgh0pe1QlZ66E13t6FlIF86QrnBXXq+EN7Xe1Rouza3fJ1ojGlPleJZkBoq3tAyYVIOOqdZIxtVj/sIQ== dependencies: - base64-js "^1.3.0" - bech32 "^1.1.4" - readonly-date "^1.0.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/utils" "^0.31.0" + "@noble/hashes" "^1" + bn.js "^5.2.0" + elliptic "^6.5.4" + libsodium-wrappers-sumo "^0.7.11" "@cosmjs/encoding@^0.20.0": version "0.20.1" @@ -2078,12 +2064,21 @@ bech32 "^1.1.4" readonly-date "^1.0.0" -"@cosmjs/json-rpc@0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/json-rpc/-/json-rpc-0.26.1.tgz#b79cefe1c3b92d05eac294d71181bfb849039307" - integrity sha512-DEMkc0XwdyIqePsYrPbN/iheOst8qvzh3zZX0rQXSr9NzptcKu/KrytlwXVBdqvq6hXbZXbsLAwzsS3DX1OrpA== +"@cosmjs/encoding@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.31.0.tgz#9a6fd80b59c35fc20638a6436128ad0be681eafc" + integrity sha512-NYGQDRxT7MIRSlcbAezwxK0FqnaSPKCH7O32cmfpHNWorFxhy9lwmBoCvoe59Kd0HmArI4h+NGzLEfX3OLnA4Q== + dependencies: + base64-js "^1.3.0" + bech32 "^1.1.4" + readonly-date "^1.0.0" + +"@cosmjs/json-rpc@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/json-rpc/-/json-rpc-0.31.0.tgz#38fda21188f2046db4a111fb5463ccde3c3751d7" + integrity sha512-Ix2Cil2qysiLNrX+E0w3vtwCrqxGVq8jklpLA7B2vtMrw7tru/rS65fdFSy8ep0wUNLL6Ud32VXa5K0YObDOMA== dependencies: - "@cosmjs/stream" "0.26.1" + "@cosmjs/stream" "^0.31.0" xstream "^11.14.0" "@cosmjs/launchpad@^0.24.0-alpha.25", "@cosmjs/launchpad@^0.24.1": @@ -2098,13 +2093,6 @@ axios "^0.21.1" fast-deep-equal "^3.1.3" -"@cosmjs/math@0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.26.1.tgz#8bfc1af4adc16a5857660c76c8429af70a43ac4d" - integrity sha512-FvCpguKswL2PYsONXHDzbcaq1gFQteFUz2w7DasVXvVlnzStDS8ePz8k36psNQ1efyX6oF62ZqMizxOZgCW33A== - dependencies: - bn.js "^4.11.8" - "@cosmjs/math@^0.20.0": version "0.20.1" resolved "https://registry.npmjs.org/@cosmjs/math/-/math-0.20.1.tgz" @@ -2119,17 +2107,12 @@ dependencies: bn.js "^4.11.8" -"@cosmjs/proto-signing@0.26.1", "@cosmjs/proto-signing@^0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.26.1.tgz#057231343096fd37bbfdd71973a1472e729a150d" - integrity sha512-R6vHulxH5njTru9Ezr8k5+u6fBzenNRE3EbQtbVreL++TLV/jKu0Vl2CFz89X8su7BqWZImqzE9+BAesLUKVfw== +"@cosmjs/math@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.31.0.tgz#c9fc5f8191df7c2375945d2eacce327dfbf26414" + integrity sha512-Sb/8Ry/+gKJaYiV6X8q45kxXC9FoV98XCY1WXtu0JQwOi61VCG2VXsURQnVvZ/EhR/CuT/swOlNKrqEs3da0fw== dependencies: - "@cosmjs/amino" "0.26.1" - "@cosmjs/crypto" "0.26.1" - "@cosmjs/math" "0.26.1" - cosmjs-types "^0.2.0" - long "^4.0.0" - protobufjs "~6.10.2" + bn.js "^5.2.0" "@cosmjs/proto-signing@^0.24.0-alpha.25": version "0.24.1" @@ -2140,61 +2123,70 @@ long "^4.0.0" protobufjs "~6.10.2" -"@cosmjs/socket@0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/socket/-/socket-0.26.1.tgz#db783483a253c7b51f325dfc0f0c106853f103ce" - integrity sha512-lZSWuQ2mIE60tsQ+VEjfVNkLJRvXBq7gibY9wud6oJ4Sl3l2sSnffPoFWQzRvQe6jGLvRcOIFpUD4Vy0Wyx2Bg== +"@cosmjs/proto-signing@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.31.0.tgz#7056963457cd967f53f56c2ab4491638e5ade2c0" + integrity sha512-JNlyOJRkn8EKB9mCthkjr6lVX6eyVQ09PFdmB4/DR874E62dFTvQ+YvyKMAgN7K7Dcjj26dVlAD3f6Xs7YOGDg== + dependencies: + "@cosmjs/amino" "^0.31.0" + "@cosmjs/crypto" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/utils" "^0.31.0" + cosmjs-types "^0.8.0" + long "^4.0.0" + +"@cosmjs/socket@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/socket/-/socket-0.31.0.tgz#ffcae48251a68b4a1c37a1c996d8b123cd8ad5ac" + integrity sha512-WDh9gTyiP3OCXvSAJJn33+Ef3XqMWag+bpR1TdMBxTmlTxuvU+kPy4cf6P2OF+jkkUBEA5Se2EAju0eFbJMT+w== dependencies: - "@cosmjs/stream" "0.26.1" + "@cosmjs/stream" "^0.31.0" isomorphic-ws "^4.0.1" ws "^7" xstream "^11.14.0" -"@cosmjs/stargate@^0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.26.1.tgz#24635ca89d4f7195843c7c8bd54f5ed29cf23894" - integrity sha512-vF586pSTAP0Z5x8GLbLLd/nw50YQQHO8ZwYmKFV7zv0dMBFOX8nEUAjb8dloFnNYm9xXEqT5UjVKQKbh/4Ds2w== - dependencies: - "@confio/ics23" "^0.6.3" - "@cosmjs/amino" "0.26.1" - "@cosmjs/encoding" "0.26.1" - "@cosmjs/math" "0.26.1" - "@cosmjs/proto-signing" "0.26.1" - "@cosmjs/stream" "0.26.1" - "@cosmjs/tendermint-rpc" "0.26.1" - "@cosmjs/utils" "0.26.1" - cosmjs-types "^0.2.0" +"@cosmjs/stargate@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.31.0.tgz#a7df1eaf1363513529607abaa52a5045aaaee0fd" + integrity sha512-GYhk9lzZPj/QmYHC0VV/4AMoRzVcOP+EnB1YZCoWlBdLuVmpBYKRagJqWIrIwdk1E0gF2ZoESd2TYfdh1fqIpg== + dependencies: + "@confio/ics23" "^0.6.8" + "@cosmjs/amino" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/proto-signing" "^0.31.0" + "@cosmjs/stream" "^0.31.0" + "@cosmjs/tendermint-rpc" "^0.31.0" + "@cosmjs/utils" "^0.31.0" + cosmjs-types "^0.8.0" long "^4.0.0" - protobufjs "~6.10.2" + protobufjs "~6.11.3" xstream "^11.14.0" -"@cosmjs/stream@0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/stream/-/stream-0.26.1.tgz#a1f29c6c12da887eeaa3bd3e29339f957ed0f6a8" - integrity sha512-RVFE7kEjUAyRMp35EYZ25XY6DRsifcXDEa0C6b6PYacqdkVhCTfNXZrYaJ/NCTowQ+dYRSR6QVsM4AfStsDgZA== +"@cosmjs/stream@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/stream/-/stream-0.31.0.tgz#7faf0f5ccd5ceffdd3b5d9fb81e292bb7a930b2c" + integrity sha512-Y+aSHwhHkLGIaQOdqRob+yga2zr9ifl9gZDKD+B7+R5pdWN5f2TTDhYWxA6YZcZ6xRmfr7u8a7tDh7iYLC/zKA== dependencies: xstream "^11.14.0" -"@cosmjs/tendermint-rpc@0.26.1", "@cosmjs/tendermint-rpc@^0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.26.1.tgz#56defe5047cf0e035cbed6b715af04ab5a7752c4" - integrity sha512-qeFF+0bAl5f55IFHC56B4iXppQ3gYQ994yd1kr6RveDBZEQOhesSi9Khypy7XhhN1mGU9VCxJWQpwOVyPVW1VQ== - dependencies: - "@cosmjs/crypto" "0.26.1" - "@cosmjs/encoding" "0.26.1" - "@cosmjs/json-rpc" "0.26.1" - "@cosmjs/math" "0.26.1" - "@cosmjs/socket" "0.26.1" - "@cosmjs/stream" "0.26.1" +"@cosmjs/tendermint-rpc@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.31.0.tgz#df82f634ff08fc377dfdccea43a31d92b5b0eaf1" + integrity sha512-yo9xbeuI6UoEKIhFZ9g0dvUKLqnBzwdpEc/uldQygQc51j38gQVwFko+6sjmhieJqRYYvrYumcbJMiV6GFM9aA== + dependencies: + "@cosmjs/crypto" "^0.31.0" + "@cosmjs/encoding" "^0.31.0" + "@cosmjs/json-rpc" "^0.31.0" + "@cosmjs/math" "^0.31.0" + "@cosmjs/socket" "^0.31.0" + "@cosmjs/stream" "^0.31.0" + "@cosmjs/utils" "^0.31.0" axios "^0.21.2" readonly-date "^1.0.0" xstream "^11.14.0" -"@cosmjs/utils@0.26.1": - version "0.26.1" - resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.26.1.tgz#52e38e26d92c34711ca8578973a76dd42faafaa6" - integrity sha512-E7sYhHfcq2V4oB504FNSt8nx6QInTea1KZT5FrtyqONmgQwccfTv5+E2PuRbQs91i56YzHORHuP57rhV7NPn3g== - "@cosmjs/utils@^0.20.0": version "0.20.1" resolved "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.20.1.tgz" @@ -2205,6 +2197,11 @@ resolved "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.24.1.tgz" integrity sha512-VA3WFx1lMFb7esp9BqHWkDgMvHoA3D9w+uDRvWhVRpUpDc7RYHxMbWExASjz+gNblTCg556WJGzF64tXnf9tdQ== +"@cosmjs/utils@^0.31.0": + version "0.31.0" + resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.31.0.tgz#3a7ac16856dcff63bbf1bb11e31f975f71ef4f21" + integrity sha512-nNcycZWUYLNJlrIXgpcgVRqdl6BXjF4YlXdxobQWpW9Tikk61bEGeAFhDYtC0PwHlokCNw0KxWiHGJL4nL7Q5A== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -4113,6 +4110,11 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== +"@noble/hashes@^1", "@noble/hashes@^1.0.0": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + "@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": version "1.6.3" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" @@ -9206,7 +9208,7 @@ bn.js@^5.1.3: resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz" integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== -bn.js@^5.2.1: +bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== @@ -10808,10 +10810,10 @@ cosmiconfig@^8.1.3: parse-json "^5.0.0" path-type "^4.0.0" -cosmjs-types@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.2.0.tgz#0c3041ed1d54e1b73486c5bf01c8bd1f44449020" - integrity sha512-9/jBr7kxfHg8HCNzUi9hxutU2GldrScXXSjfTZWuZHlFJmn5sJDXlvxSWhpeWIorHRxN8CtxDPmt7zdo/+BYDg== +cosmjs-types@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.8.0.tgz#2ed78f3e990f770229726f95f3ef5bf9e2b6859b" + integrity sha512-Q2Mj95Fl0PYMWEhA2LuGEIhipF7mQwd9gTQ85DdP9jjjopeoGaDxvmPa5nakNzsq7FnO1DMTatXTAx6bxMH7Lg== dependencies: long "^4.0.0" protobufjs "~6.11.2" @@ -17001,11 +17003,6 @@ js-sha3@0.5.7, js-sha3@0.8.0, js-sha3@^0.5.7, js-sha3@^0.8.0: resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-sha512@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha512/-/js-sha512-0.8.0.tgz#dd22db8d02756faccf19f218e3ed61ec8249f7d4" - integrity sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ== - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" @@ -17522,6 +17519,18 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +libsodium-sumo@^0.7.11: + version "0.7.11" + resolved "https://registry.yarnpkg.com/libsodium-sumo/-/libsodium-sumo-0.7.11.tgz#ab0389e2424fca5c1dc8c4fd394906190da88a11" + integrity sha512-bY+7ph7xpk51Ez2GbE10lXAQ5sJma6NghcIDaSPbM/G9elfrjLa0COHl/7P6Wb/JizQzl5UQontOOP1z0VwbLA== + +libsodium-wrappers-sumo@^0.7.11: + version "0.7.11" + resolved "https://registry.yarnpkg.com/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.11.tgz#d96329ee3c0e7ec7f5fcf4cdde16cc3a1ae91d82" + integrity sha512-DGypHOmJbB1nZn89KIfGOAkDgfv5N6SBGC3Qvmy/On0P0WD1JQvNRS/e3UL3aFF+xC0m+MYz5M+MnRnK2HMrKQ== + dependencies: + libsodium-sumo "^0.7.11" + libsodium-wrappers@^0.7.6: version "0.7.8" resolved "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.8.tgz" @@ -21505,6 +21514,25 @@ protobufjs@~6.10.2: "@types/node" "^13.7.0" long "^4.0.0" +protobufjs@~6.11.3: + version "6.11.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" + integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" ">=13.7.0" + long "^4.0.0" + proxy-addr@~2.0.4, proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz" From 3fa6469f799a87901a8f9eca7e10b2520d7ab730 Mon Sep 17 00:00:00 2001 From: Mark Hagelberg <9438198+mhagel@users.noreply.github.com> Date: Tue, 22 Aug 2023 17:21:25 -0600 Subject: [PATCH 2/3] Bootstrap mod (#4872) fix dasel syntax unstaked tokens visible in keplr fix platform for docker update wiki new image ref for CI tests --- .github/workflows/CI.yml | 2 +- .../cosmos-chain-testing/v1/Dockerfile | 17 +---- .../cosmos-chain-testing/v1/bootstrap.sh | 63 ++++++++++------- .../cosmos-chain-testing/v1/start.sh | 2 +- .../cosmos-chain-testing/v1/stop.sh | 2 +- .../cosmos-chain-testing/v1beta1/bootstrap.sh | 63 ++++++++++------- .../cosmos-chain-testing/v1beta1/dockerfile | 5 +- .../cosmos-chain-testing/v1beta1/heroku.yml | 2 +- .../client/scripts/helpers/wallet.ts | 6 +- .../test/devnet/cosmos/helpers.ts | 2 +- .../test/devnet/cosmos/proposal-tx-v1.spec.ts | 67 ++++++++++--------- .../devnet/cosmos/proposal-tx-v1beta1.spec.ts | 59 ++++++++-------- wiki/Devnet.md | 18 ++--- 13 files changed, 160 insertions(+), 148 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8f311c7b1b1..c563deb0b5c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -303,7 +303,7 @@ jobs: ports: - 3000:3000 cosmos_test_app: - image: irowan/heroku-csdk + image: mhagel1/csdk-v1 ports: - 5050:5050 cosmos_beta_test_app: diff --git a/packages/chain-events/cosmos-chain-testing/v1/Dockerfile b/packages/chain-events/cosmos-chain-testing/v1/Dockerfile index 5eab97ad019..5e7456400ba 100644 --- a/packages/chain-events/cosmos-chain-testing/v1/Dockerfile +++ b/packages/chain-events/cosmos-chain-testing/v1/Dockerfile @@ -1,17 +1,7 @@ # Simple usage with a mounted data directory: # > docker build -t simapp . -# -# Server: -# > docker run -it -p 26657:26657 -p 26656:26656 -v ~/.simapp:/root/.simapp simapp simd init test-chain -# TODO: need to set validator in genesis so start runs -# > docker run -it -p 26657:26657 -p 26656:26656 -v ~/.simapp:/root/.simapp simapp simd start -# -# Client: (Note the simapp binary always looks at ~/.simapp we can bind to different local storage) -# > docker run -it -p 26657:26657 -p 26656:26656 -v ~/.simappcli:/root/.simapp simapp simd keys add foo -# > docker run -it -p 26657:26657 -p 26656:26656 -v ~/.simappcli:/root/.simapp simapp simd keys list -# TODO: demo connecting rest-server (or is this in server now?) - -FROM golang:1.19-alpine AS build-env + +FROM --platform=linux/amd64 golang:1.19-alpine AS build-env # Install minimum necessary dependencies ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 py3-pip build-base dasel nginx @@ -33,9 +23,6 @@ RUN make build \ WORKDIR /root -# ADD https://simd-binary.s3.amazonaws.com/simd /usr/bin/simd -# COPY simd /usr/bin/simd - EXPOSE ${PORT} EXPOSE 5050 COPY nginx.conf /etc/nginx/nginx.conf diff --git a/packages/chain-events/cosmos-chain-testing/v1/bootstrap.sh b/packages/chain-events/cosmos-chain-testing/v1/bootstrap.sh index cee9ae0a9d2..35a7c3b75a1 100755 --- a/packages/chain-events/cosmos-chain-testing/v1/bootstrap.sh +++ b/packages/chain-events/cosmos-chain-testing/v1/bootstrap.sh @@ -8,7 +8,7 @@ CONFIG_FOLDER=$CSDK_HOME/config GENESIS=$CONFIG_FOLDER/genesis.json # You can add this mnemonic to keplr to use the UI COW_MNEMONIC="ignore medal pitch lesson catch stadium victory jewel first stairs humble excuse scrap clutch cup daughter bench length sell goose deliver critic favorite thought" -CSDK_CHAIN_ID="testnet" +CSDK_CHAIN_ID="csdkv1-1" ### start nginx sed -i "s/listen\ 80;/listen\ ${PORT:=5050};/" /etc/nginx/nginx.conf @@ -16,45 +16,62 @@ echo "starting nginx" nginx ### intialize the chain -simd init csdk-local --chain-id $CSDK_CHAIN_ID +simd init csdk-v1 --chain-id $CSDK_CHAIN_ID simd config keyring-backend test simd config chain-id $CSDK_CHAIN_ID simd config broadcast-mode block simd config output json -echo $COW_MNEMONIC | simd keys add cow --recover --keyring-backend=test --home $CSDK_HOME -# make cow a validator: -simd add-genesis-account cow 1000000000000stake -simd gentx cow 7000000000stake --chain-id testnet -simd collect-gentxs -# Update gov module +simd config node http://localhost:26657 ### Configure chain generated config files - genesis.json, app.toml, config.toml -dasel put string -r json -f $GENESIS -v '600s' '.app_state.gov.voting_params.voting_period' -dasel put string -r json -f $GENESIS -v '100000' '.app_state.gov.deposit_params.min_deposit.[0].amount' +# Update denom references +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.staking.params.bond_denom' +dasel put -t string -r json -f $GENESIS -v "240s" '.app_state.staking.params.unbonding_time' + +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.txfees.basedenom' +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.crisis.constant_fee.denom' +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.mint.params.mint_denom' + +# Update gov module +dasel put -t string -r json -f $GENESIS -v "90s" '.app_state.gov.voting_params.voting_period' +dasel put -t string -r json -f $GENESIS -v "2000000" '.app_state.gov.deposit_params.min_deposit.[0].amount' +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.gov.deposit_params.min_deposit.[0].denom' + +# decrease block-time so tests run faster +sed -i "s/timeout_commit = \"5s\"/timeout_commit = \"500ms\"/g" $CONFIG_FOLDER/config.toml +# bind on all interfaces, enabling ports to be exposed outside docker +sed -i "s/127\.0\.0\.1/0.0.0.0/g" $CONFIG_FOLDER/config.toml + # expose the LCD -dasel put bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.enable' +dasel put -t bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.enable' +dasel put -t string -r toml -f $CONFIG_FOLDER/app.toml -v "tcp://0.0.0.0:1317" '.api.address' -# Expose the rpc -dasel put string -r toml -f $CONFIG_FOLDER/config.toml -v "tcp://0.0.0.0:26657" '.rpc.laddr' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "tcp://0.0.0.0:26657" '.rpc.laddr' # Enable cors on RPC -dasel put string -r toml -f $CONFIG_FOLDER/config.toml -v "*" '.rpc.cors_allowed_origins.[]' -dasel put string -r toml -f $CONFIG_FOLDER/config.toml -v "Accept-Encoding" '.rpc.cors_allowed_headers.[]' -dasel put string -r toml -f $CONFIG_FOLDER/config.toml -v "DELETE" '.rpc.cors_allowed_methods.[]' -dasel put string -r toml -f $CONFIG_FOLDER/config.toml -v "OPTIONS" '.rpc.cors_allowed_methods.[]' -dasel put string -r toml -f $CONFIG_FOLDER/config.toml -v "PATCH" '.rpc.cors_allowed_methods.[]' -dasel put string -r toml -f $CONFIG_FOLDER/config.toml -v "PUT" '.rpc.cors_allowed_methods.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "*" '.rpc.cors_allowed_origins.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "Accept-Encoding" '.rpc.cors_allowed_headers.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "DELETE" '.rpc.cors_allowed_methods.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "OPTIONS" '.rpc.cors_allowed_methods.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "PATCH" '.rpc.cors_allowed_methods.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "PUT" '.rpc.cors_allowed_methods.[]' # Enable unsafe cors and swagger on the api -dasel put bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.swagger' -dasel put bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.enabled-unsafe-cors' +dasel put -t bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.swagger' +dasel put -t bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.enabled-unsafe-cors' + +echo $COW_MNEMONIC | simd keys add cow --recover --keyring-backend=test --home $CSDK_HOME +# make cow a validator: +simd add-genesis-account cow 50000000000ustake +simd gentx cow 40000000000ustake --chain-id $CSDK_CHAIN_ID --ip 127.0.0.1 +simd collect-gentxs ### Start chain echo "Starting up csdk v1 node..." -simd start --api.enable true & +simd start & CSDK_PID=$! # Sleep for node to full boot up sleep 3 # wait again on the node process so it can be terminated with ctrl+C -echo "CSDK V1 node started & state initialized!" +echo "CSDK v1 node started & state initialized!" wait $CSDK_PID diff --git a/packages/chain-events/cosmos-chain-testing/v1/start.sh b/packages/chain-events/cosmos-chain-testing/v1/start.sh index 6ec1754d376..416a9eb5539 100755 --- a/packages/chain-events/cosmos-chain-testing/v1/start.sh +++ b/packages/chain-events/cosmos-chain-testing/v1/start.sh @@ -6,7 +6,7 @@ SCRIPT_NAME=$(basename "$0") SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) PORT=5050 -IMAGE_NAME=heroku-csdk +IMAGE_NAME=csdk-v1 if [ "$1" = "--build" ]; then cd $SCRIPT_DIR diff --git a/packages/chain-events/cosmos-chain-testing/v1/stop.sh b/packages/chain-events/cosmos-chain-testing/v1/stop.sh index 3907405af5a..1e91556efa9 100755 --- a/packages/chain-events/cosmos-chain-testing/v1/stop.sh +++ b/packages/chain-events/cosmos-chain-testing/v1/stop.sh @@ -2,6 +2,6 @@ # This script is used to start a local cosmos chain for testing purposes. set -x -IMAGE_NAME=heroku-csdk +IMAGE_NAME=csdk-v1 # docker force stop and remove the container but leave the image docker stop ${IMAGE_NAME} && docker rm ${IMAGE_NAME} -f || true \ No newline at end of file diff --git a/packages/chain-events/cosmos-chain-testing/v1beta1/bootstrap.sh b/packages/chain-events/cosmos-chain-testing/v1beta1/bootstrap.sh index 8a4551aef32..32e4e8a4f01 100755 --- a/packages/chain-events/cosmos-chain-testing/v1beta1/bootstrap.sh +++ b/packages/chain-events/cosmos-chain-testing/v1beta1/bootstrap.sh @@ -8,7 +8,7 @@ CONFIG_FOLDER=$CSDK_HOME/config GENESIS=$CONFIG_FOLDER/genesis.json # You can add this mnemonic to keplr to use the UI COW_MNEMONIC="ignore medal pitch lesson catch stadium victory jewel first stairs humble excuse scrap clutch cup daughter bench length sell goose deliver critic favorite thought" -CSDK_CHAIN_ID="testnet" +CSDK_CHAIN_ID="csdkbeta-1" ### start nginx sed -i "s/listen\ 80;/listen\ ${PORT:=5051};/" /etc/nginx/nginx.conf @@ -21,42 +21,57 @@ simd config keyring-backend test simd config chain-id $CSDK_CHAIN_ID simd config broadcast-mode block simd config output json -echo $COW_MNEMONIC | simd keys add cow --recover --keyring-backend=test --home $CSDK_HOME -# make cow a validator: -simd add-genesis-account cow 1000000000000stake -simd gentx cow 7000000000stake --chain-id testnet -simd collect-gentxs +simd config node http://localhost:26657 + +### Configure chain generated config files - genesis.json, app.toml, config.toml +# Update denom references +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.staking.params.bond_denom' +dasel put -t string -r json -f $GENESIS -v "240s" '.app_state.staking.params.unbonding_time' + +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.txfees.basedenom' +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.crisis.constant_fee.denom' +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.mint.params.mint_denom' + # Update gov module +dasel put -t string -r json -f $GENESIS -v "90s" '.app_state.gov.voting_params.voting_period' +dasel put -t string -r json -f $GENESIS -v "2000000" '.app_state.gov.deposit_params.min_deposit.[0].amount' +dasel put -t string -r json -f $GENESIS -v "ustake" '.app_state.gov.deposit_params.min_deposit.[0].denom' -dasel put string -f $GENESIS '.app_state.gov.voting_params.voting_period' '600s' -dasel put string -f $GENESIS '.app_state.gov.deposit_params.min_deposit.[0].amount' '100000' +# decrease block-time so tests run faster +sed -i "s/timeout_commit = \"5s\"/timeout_commit = \"500ms\"/g" $CONFIG_FOLDER/config.toml +# bind on all interfaces, enabling ports to be exposed outside docker +sed -i "s/127\.0\.0\.1/0.0.0.0/g" $CONFIG_FOLDER/config.toml # expose the LCD -dasel put bool -f $CONFIG_FOLDER/app.toml -v "true" '.api.enable' +dasel put -t bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.enable' +dasel put -t string -r toml -f $CONFIG_FOLDER/app.toml -v "tcp://0.0.0.0:1317" '.api.address' -# Expose the rpc -dasel put string -f $CONFIG_FOLDER/config.toml -v "tcp://0.0.0.0:26657" '.rpc.laddr' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "tcp://0.0.0.0:26657" '.rpc.laddr' # Enable cors on RPC -dasel put string -f $CONFIG_FOLDER/config.toml -v "*" '.rpc.cors_allowed_origins.[]' -dasel put string -f $CONFIG_FOLDER/config.toml -v "Accept-Encoding" '.rpc.cors_allowed_headers.[]' -dasel put string -f $CONFIG_FOLDER/config.toml -v "DELETE" '.rpc.cors_allowed_methods.[]' -dasel put string -f $CONFIG_FOLDER/config.toml -v "OPTIONS" '.rpc.cors_allowed_methods.[]' -dasel put string -f $CONFIG_FOLDER/config.toml -v "PATCH" '.rpc.cors_allowed_methods.[]' -dasel put string -f $CONFIG_FOLDER/config.toml -v "PUT" '.rpc.cors_allowed_methods.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "*" '.rpc.cors_allowed_origins.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "Accept-Encoding" '.rpc.cors_allowed_headers.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "DELETE" '.rpc.cors_allowed_methods.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "OPTIONS" '.rpc.cors_allowed_methods.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "PATCH" '.rpc.cors_allowed_methods.[]' +dasel put -t string -r toml -f $CONFIG_FOLDER/config.toml -v "PUT" '.rpc.cors_allowed_methods.[]' # Enable unsafe cors and swagger on the api -dasel put bool -f $CONFIG_FOLDER/app.toml -v "true" '.api.swagger' -dasel put bool -f $CONFIG_FOLDER/app.toml -v "true" '.api.enabled-unsafe-cors' +dasel put -t bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.swagger' +dasel put -t bool -r toml -f $CONFIG_FOLDER/app.toml -v "true" '.api.enabled-unsafe-cors' -# Enable cors on gRPC Web -dasel put bool -f $CONFIG_FOLDER/app.toml -v "true" '.grpc-web.enable-unsafe-cors' +echo $COW_MNEMONIC | simd keys add cow --recover --keyring-backend=test --home $CSDK_HOME +# make cow a validator: +simd add-genesis-account cow 50000000000ustake +simd gentx cow 40000000000ustake --chain-id $CSDK_CHAIN_ID --ip 127.0.0.1 +simd collect-gentxs ### Start chain -echo "Starting up csdk-v1beta1 node..." -simd start & CSDK_PID=$! +echo "Starting up csdk v1beta1 node..." +simd start & +CSDK_PID=$! # Sleep for node to full boot up sleep 3 # wait again on the node process so it can be terminated with ctrl+C -echo "CSDK-beta node started & state initialized!" +echo "CSDK beta node started & state initialized!" wait $CSDK_PID diff --git a/packages/chain-events/cosmos-chain-testing/v1beta1/dockerfile b/packages/chain-events/cosmos-chain-testing/v1beta1/dockerfile index ad8ac67c621..71f6a236bc3 100644 --- a/packages/chain-events/cosmos-chain-testing/v1beta1/dockerfile +++ b/packages/chain-events/cosmos-chain-testing/v1beta1/dockerfile @@ -1,8 +1,7 @@ # Simple usage with a mounted data directory: # > docker build -t simapp . -# -FROM golang:1.19-alpine AS build-env +FROM --platform=linux/amd64 golang:1.19-alpine AS build-env # Install minimum necessary dependencies ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3 py3-pip build-base dasel nginx @@ -27,7 +26,7 @@ WORKDIR /root EXPOSE ${PORT} EXPOSE 5051 COPY nginx.conf /etc/nginx/nginx.conf -COPY bootstrap.sh bootstrap.sh +COPY bootstrap.sh bootstrap.sh RUN chmod +x bootstrap.sh && chmod +x /usr/bin/simd && mkdir -p /run/nginx # Run simd by default, omit entrypoint to ease using container with simcli diff --git a/packages/chain-events/cosmos-chain-testing/v1beta1/heroku.yml b/packages/chain-events/cosmos-chain-testing/v1beta1/heroku.yml index 16f42182e99..8eec25b9c99 100644 --- a/packages/chain-events/cosmos-chain-testing/v1beta1/heroku.yml +++ b/packages/chain-events/cosmos-chain-testing/v1beta1/heroku.yml @@ -1,3 +1,3 @@ build: docker: - web: dockerfile + web: Dockerfile diff --git a/packages/commonwealth/client/scripts/helpers/wallet.ts b/packages/commonwealth/client/scripts/helpers/wallet.ts index f31b02cfca9..84e7800479d 100644 --- a/packages/commonwealth/client/scripts/helpers/wallet.ts +++ b/packages/commonwealth/client/scripts/helpers/wallet.ts @@ -9,7 +9,7 @@ const getAddressFromWallet = (wallet: IWebWallet) => { } if (wallet.defaultNetwork === 'terra') { - return wallet.accounts[0].address; + return wallet.accounts[0]?.address; } if (wallet.chain === 'cosmos') { @@ -17,11 +17,11 @@ const getAddressFromWallet = (wallet: IWebWallet) => { return wallet.accounts[0]; } - return wallet.accounts[0].address; + return wallet.accounts[0]?.address; } if (wallet.chain === 'substrate') { - return wallet.accounts[0].address; + return wallet.accounts[0]?.address; } })(); diff --git a/packages/commonwealth/test/devnet/cosmos/helpers.ts b/packages/commonwealth/test/devnet/cosmos/helpers.ts index 92111111a77..16948b670e1 100644 --- a/packages/commonwealth/test/devnet/cosmos/helpers.ts +++ b/packages/commonwealth/test/devnet/cosmos/helpers.ts @@ -15,7 +15,7 @@ const DEFAULT_FEE: StdFee = { amount: [{ amount: '0', denom: 'ustake' }], }; const DEFAULT_MEMO = ''; -export const deposit = new CosmosToken('stake', 100000, false); +export const deposit = new CosmosToken('ustake', 2000000, false); export const setupTestSigner = async (rpcUrl: string, isAmino?: boolean) => { let signer; diff --git a/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1.spec.ts b/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1.spec.ts index 973e9812f09..242734772c7 100644 --- a/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1.spec.ts +++ b/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1.spec.ts @@ -50,19 +50,18 @@ describe('Proposal Transaction Tests - gov v1 chain using cosmJs signer (csdk-v1 isAmino?: boolean ) => { const msg = encodeMsgSubmitProposal(signer, deposit, content); - const resp = await sendTx(rpcUrl, msg, isAmino); - expect(isDeliverTxSuccess(resp)).to.be.true; expect(resp.transactionHash).to.not.be.undefined; expect(resp.rawLog).to.not.be.undefined; + expect(isDeliverTxSuccess(resp), 'TX failed').to.be.true; await waitOneBlock(rpcUrl); const activeProposals = await getActiveVotingProposals(); - const onchainProposal = activeProposals[activeProposals.length - 1]; - expect((onchainProposal.messages[0] as any)?.content?.['@type']).to.be.eql( - expectedProposalType - ); + const onchainProposal = activeProposals[activeProposals?.length - 1]; + expect( + (onchainProposal?.messages?.[0] as any)?.content?.['@type'] + ).to.be.eql(expectedProposalType); }; const voteTest = async ( @@ -87,19 +86,6 @@ describe('Proposal Transaction Tests - gov v1 chain using cosmJs signer (csdk-v1 const content = encodeTextProposal(`v1 title`, `v1 description`); await proposalTest(content, '/cosmos.gov.v1beta1.TextProposal'); }); - it('creates a community spend proposal', async () => { - const content = encodeCommunitySpend( - `v1 spend title`, - `v1 spend description`, - 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', - '100', - 'stake' - ); - await proposalTest( - content, - '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal' - ); - }); it('votes NO on an active proposal', async () => { await voteTest(VoteOptionV1.VOTE_OPTION_NO); }); @@ -112,21 +98,48 @@ describe('Proposal Transaction Tests - gov v1 chain using cosmJs signer (csdk-v1 it('votes YES on an active proposal', async () => { await voteTest(VoteOptionV1.VOTE_OPTION_YES); }); + it('creates a community spend proposal', async () => { + await waitOneBlock(rpcUrl); + const content = encodeCommunitySpend( + `v1 spend title`, + `v1 spend description`, + 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', + '5', + 'ustake' + ); + await proposalTest( + content, + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal' + ); + }); }); describe('Amino Signer', () => { it('creates a text proposal with legacy amino', async () => { const content = encodeTextProposal(`v1 title`, `v1 description`); await proposalTest(content, '/cosmos.gov.v1beta1.TextProposal', true); }); + it('votes NO on an active proposal with legacy amino', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_NO, true); + }); + it('votes NO WITH VETO on an active proposal with legacy amino', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_NO_WITH_VETO, true); + }); + it('votes ABSTAIN on an active proposal with legacy amino', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_ABSTAIN, true); + }); + it('votes YES on an active proposal with legacy amino', async () => { + await voteTest(VoteOptionV1.VOTE_OPTION_YES, true); + }); // TODO: Unsupported. Un-skip this in // https://github.com/hicommonwealth/commonwealth/issues/4821 it.skip('creates a community spend proposal with legacy amino', async () => { + await waitOneBlock(rpcUrl); const content = encodeCommunitySpend( `v1 spend title amino`, `v1 spend description amino`, 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', - '10', - 'stake' + '5', + 'ustake' ); await proposalTest( content, @@ -134,18 +147,6 @@ describe('Proposal Transaction Tests - gov v1 chain using cosmJs signer (csdk-v1 true ); }); - it('votes NO on an active proposal with legacy amino', async () => { - await voteTest(VoteOptionV1.VOTE_OPTION_NO, true); - }); - it('votes NO WITH VETO on an active proposal with legacy amino', async () => { - await voteTest(VoteOptionV1.VOTE_OPTION_NO_WITH_VETO, true); - }); - it('votes ABSTAIN on an active proposal with legacy amino', async () => { - await voteTest(VoteOptionV1.VOTE_OPTION_ABSTAIN, true); - }); - it('votes YES on an active proposal with legacy amino', async () => { - await voteTest(VoteOptionV1.VOTE_OPTION_YES, true); - }); }); }); diff --git a/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1beta1.spec.ts b/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1beta1.spec.ts index 7db83509593..2bdb966333d 100644 --- a/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1beta1.spec.ts +++ b/packages/commonwealth/test/devnet/cosmos/proposal-tx-v1beta1.spec.ts @@ -56,12 +56,11 @@ describe('Proposal Transaction Tests - gov v1beta1 chain (csdk-beta-ci)', () => isAmino?: boolean ) => { const msg = encodeMsgSubmitProposal(signer, deposit, content); - const resp = await sendTx(rpcUrlBeta, msg, isAmino); - expect(isDeliverTxSuccess(resp)).to.be.true; expect(resp.transactionHash).to.not.be.undefined; expect(resp.rawLog).to.not.be.undefined; + expect(isDeliverTxSuccess(resp), 'TX failed').to.be.true; await waitOneBlock(rpcUrlBeta); const activeProposals = await getActiveVotingProposals(); @@ -95,19 +94,6 @@ describe('Proposal Transaction Tests - gov v1beta1 chain (csdk-beta-ci)', () => ); await proposalTest(content, '/cosmos.gov.v1beta1.TextProposal'); }); - it('creates a community spend proposal', async () => { - const content = encodeCommunitySpend( - `beta spend title`, - `beta spend description`, - 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', - '100', - 'stake' - ); - await proposalTest( - content, - '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal' - ); - }); it('votes NO on an active proposal', async () => { await voteTest(VoteOption.VOTE_OPTION_NO); }); @@ -120,6 +106,20 @@ describe('Proposal Transaction Tests - gov v1beta1 chain (csdk-beta-ci)', () => it('votes YES on an active proposal', async () => { await voteTest(VoteOption.VOTE_OPTION_YES); }); + it('creates a community spend proposal', async () => { + await waitOneBlock(rpcUrlBeta); + const content = encodeCommunitySpend( + `beta spend title`, + `beta spend description`, + 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', + '5', + 'ustake' + ); + await proposalTest( + content, + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal' + ); + }); }); describe('Amino signing', () => { @@ -130,20 +130,6 @@ describe('Proposal Transaction Tests - gov v1beta1 chain (csdk-beta-ci)', () => ); await proposalTest(content, '/cosmos.gov.v1beta1.TextProposal', true); }); - it('creates a community spend proposal with legacy amino', async () => { - const content = encodeCommunitySpend( - `beta spend title amino`, - `beta spend description amino`, - 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', - '100', - 'stake' - ); - await proposalTest( - content, - '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', - true - ); - }); it('votes NO on an active proposal with legacy amino', async () => { await voteTest(VoteOption.VOTE_OPTION_NO, true); }); @@ -156,6 +142,21 @@ describe('Proposal Transaction Tests - gov v1beta1 chain (csdk-beta-ci)', () => it('votes YES on an active proposal with legacy amino', async () => { await voteTest(VoteOption.VOTE_OPTION_YES, true); }); + it('creates a community spend proposal with legacy amino', async () => { + await waitOneBlock(rpcUrlBeta); + const content = encodeCommunitySpend( + `beta spend title amino`, + `beta spend description amino`, + 'cosmos18q3tlnx8vguv2fadqslm7x59ejauvsmnlycckg', + '5', + 'ustake' + ); + await proposalTest( + content, + '/cosmos.distribution.v1beta1.CommunityPoolSpendProposal', + true + ); + }); }); }); diff --git a/wiki/Devnet.md b/wiki/Devnet.md index abe2f44d8e8..5c93a5b0bd4 100644 --- a/wiki/Devnet.md +++ b/wiki/Devnet.md @@ -19,8 +19,7 @@ Sandbox community: CI community (ephemeral spin-up for automated tests): * http://localhost:8080/csdk-v1 -* CI tests reference Docker image at https://hub.docker.com/repository/docker/irowan/heroku-csdk - * Note: the name `heroku-csdk` was leftover from creating the sandbox community. This image has no association with heroku. +* CI tests reference Docker image at https://hub.docker.com/repository/docker/mhagel1/csdk-v1 ### Version 0.45.0 (`gov` module v1beta1) @@ -39,15 +38,11 @@ CI community (ephemeral spin-up for automated tests): * http://localhost:8080/csdk-beta-ci * CI tests reference Docker image at https://hub.docker.com/repository/docker/mhagel1/csdk-beta -# How to [deploy updates](https://dashboard.heroku.com/apps/cosmos-devnet/deploy/heroku-git): +# How to [deploy updates](https://dashboard.heroku.com/apps/cosmos-devnet/deploy/heroku-container): 1. In terminal go to packages/chain-events/cosmos-chain-testing/v1 directory -2. `heroku git:remote -a cosmos-devnet` (or `heroku git:remote -a cosmos-devnet-beta` for v1beta1) - - this creates a heroku git instance for this directory, separate from the regular commonwealth git repo - - be careful not to confuse these - - the default branch is `main`. You should be on this branch. -3. Commit any changes you want to make to the dockerfile, bootstrap.sh, etc. -4. To apply your changes to the heroku app, `git push heroku main` -5. A new build and deployment will be triggered. +2. `heroku login` +2. `heroku container:push web` to apply your changes to the heroku app +3. `heroku container:release web` - A new build and deployment will be triggered. Local Dev CSDK: If you ever need to run devnets locally on your machine, there are three helper scripts @@ -78,6 +73,3 @@ a shared address for this purpose. - Give the wallet a name you can recognize, like "CW devnet" - Go to http://localhost:8080/csdk-beta or http://localhost:8080/csdk and join community. You should be able to create proposals and vote. - -- Note: Select "0 STAKE" gas fee to run a transaction. - - The account should have unstaked tokens too, but Keplr is not registering them for some reason. \ No newline at end of file From 25591c535569feb54f2e453ea94c28ff255fde3c Mon Sep 17 00:00:00 2001 From: mhagel Date: Wed, 23 Aug 2023 08:47:14 -0600 Subject: [PATCH 3/3] migration for more keplr-friendly chain names --- .../migrations/20230823143849-devnet-names.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 packages/commonwealth/server/migrations/20230823143849-devnet-names.js diff --git a/packages/commonwealth/server/migrations/20230823143849-devnet-names.js b/packages/commonwealth/server/migrations/20230823143849-devnet-names.js new file mode 100644 index 00000000000..32c36d94e39 --- /dev/null +++ b/packages/commonwealth/server/migrations/20230823143849-devnet-names.js @@ -0,0 +1,23 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.sequelize.query( + ` + UPDATE "Chains" SET name = 'CSDK v1 Sandbox' WHERE id = 'csdk'; + UPDATE "Chains" SET name = 'CSDK beta Sandbox' WHERE id = 'csdk-beta'; + `, + { raw: true } + ); + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.sequelize.query( + ` + UPDATE "Chains" SET name = 'Cosmos SDK CI - Gov v1beta1 v0.45.0' WHERE id = 'csdk'; + UPDATE "Chains" SET name = 'Cosmos SDK CI - Gov V1 v0.46.11' WHERE id = 'csdk-beta'; + `, + { raw: true } + ); + }, +};