cosmology-tech / telescope

A TypeScript Transpiler for Cosmos Protobufs ⚛️
https://cosmology.zone/products/telescope
Apache License 2.0
146 stars 43 forks source link

helpers for nested create Any objects #281

Open pyramation opened 1 year ago

pyramation commented 1 year ago

https://github.com/cosmos/groups-ui/blob/master/src/shared-state/groups-store.ts#L363

import Long from 'long';
const {
    createGroupWithPolicy
} = cosmos.group.v1.MessageComposer.withTypeUrl;

const {
    PercentageDecisionPolicy   
} = cosmos.group.v1;

const msg = createGroupWithPolicy({
    admin: 'a string',
    groupMetadata: 'string here',
    groupPolicyAsAdmin: true,
    groupPolicyMetadata: 'a string here too',
    members: [], // MemberRequest[],
    decisionPolicy: { // types here aren't exactly happy with the encode function for some reason...
        // WE CAN IMPROVE THIS....
        typeUrl: '/cosmos.group.v1.PercentageDecisionPolicy',
        value: PercentageDecisionPolicy.encode({
            percentage: 'a string',
            windows: {
                votingPeriod: {
                    nanos: 0,
                    seconds: Long.fromValue(100)
                },
                minExecutionPeriod: {
                    nanos: 0,
                    seconds: Long.fromValue(100)
                }
            }
        }).finish()
    }
})
atmoner commented 1 year ago

It work!! Good job @pyramation 👏

image

For the members part, the structure is this (the weight represents the voting power of the users in the group)

    members: [{
      address: "bcna1abcdefgh",
      weight: "10", 
      metadata: "First user"
    }], // MemberRequest[],
pyramation commented 1 year ago

@atmoner I believe I fixed the amino (for ledger support) can you test sometime?

checkout interchain46@0.4.0-rc.4

import { cosmos } from 'interchain46';
const {
    MsgCreateGroupWithPolicy
} = cosmos.group.v1
import type { MsgCreateGroupWithPolicyEncoded } from 'interchain46/types/codegen/cosmos/group/v1/tx'

const policy: MsgCreateGroupWithPolicyEncoded = {
    admin: 'address',
    groupMetadata: 'https://some.ipfs.w3s.link/group_metadata.json',
    groupPolicyAsAdmin: true,
    groupPolicyMetadata: 'https://some.ipfs.w3s.link/group_metadata.json',
    members: [
        {
            address: 'address',
            weight: '10',
            metadata: 'First user'
        }
    ],
    decisionPolicy: PercentageDecisionPolicy.toProtoMsg({
        percentage: '0.5',
        windows: {
            votingPeriod: {
                nanos: 0,
                seconds: Long.fromValue(100)
            },
            minExecutionPeriod: {
                nanos: 0,
                seconds: Long.fromValue(100)
            }
        }
    })
};

// try broadcasting the amino one here:

const msg = {
    typeUrl: '/cosmos.group.v1.MsgCreateGroupWithPolicy',
    value: policy
}

@atmoner example msg in this gist with the new above code

if that works, I think we have a solution, just need to package this all up into a neat interface/api

ryanchristo commented 1 year ago

Hey there :wave:

We're in the process of switching to telescope and are now running into this issue. Any updates? How can we help?

pyramation commented 1 year ago

hey @ryanchristo which modules are you using this for? And have you guys upgraded the cosmos sdk that uses the accepts_interface and implements_interface annotations?

If so, you'll already be able to create things much more easily, and then this issue would be great to make it even easier. I think we can have @Zetazzz prioritize this soon.

pyramation commented 1 year ago

what would be great to help, if we can build this feature and @atmoner and @ryanchristo can test the result to ensure it works for your use cases.

ryanchristo commented 1 year ago

which modules are you using this for?

I ran into this issue with the group module and the same message as the example. We're using a fork of v0.46 that adds amino support for gov and group module (added amino support being the reason for a fork - https://github.com/regen-network/cosmos-sdk/pull/49).

I'd be happy to test for our use case. Feel free to add me as a reviewer or tag me in the pull request. Thanks!

pyramation commented 1 year ago

https://gist.github.com/pyramation/13f47ab2d9e6e6a86d3fb5d45999dc7b

here is an example of a test that has the buffer in view

image

and here is an example of the repo we were testing

https://github.com/pyramation/interchain46/blob/cd8e22ea63a8197935be02839c0265541ff61c09/src/codegen/cosmos/group/v1/tx.ts#L1906

https://github.com/pyramation/interchain46/blob/cd8e22ea63a8197935be02839c0265541ff61c09/src/codegen/cosmos/group/v1/tx.ts#L4007

pyramation commented 1 year ago

hey @ryanchristo have you guys tried using the toProtoMsg helpers similar to how it's done here?

import { cosmos } from 'interchain46';
const {
    MsgCreateGroupWithPolicy
} = cosmos.group.v1
import type { MsgCreateGroupWithPolicyEncoded } from 'interchain46/types/codegen/cosmos/group/v1/tx'

const policy: MsgCreateGroupWithPolicyEncoded = {
    admin: 'address',
    groupMetadata: 'https://some.ipfs.w3s.link/group_metadata.json',
    groupPolicyAsAdmin: true,
    groupPolicyMetadata: 'https://some.ipfs.w3s.link/group_metadata.json',
    members: [
        {
            address: 'address',
            weight: '10',
            metadata: 'First user'
        }
    ],
    decisionPolicy: PercentageDecisionPolicy.toProtoMsg({
        percentage: '0.5',
        windows: {
            votingPeriod: {
                nanos: 0,
                seconds: Long.fromValue(100)
            },
            minExecutionPeriod: {
                nanos: 0,
                seconds: Long.fromValue(100)
            }
        }
    })
};

// try broadcasting the amino one here:

const msg = {
    typeUrl: '/cosmos.group.v1.MsgCreateGroupWithPolicy',
    value: policy
}

we need somebody to help us test these helpers, would be amazing to get some feedback. The toProtoMsg may need to be enabled in your codegen.js config, these options will need to be enabled for this all to work:

https://github.com/pyramation/interchain46/blob/cd8e22ea63a8197935be02839c0265541ff61c09/scripts/codegen.js#L20-L23

https://github.com/pyramation/interchain46/blob/cd8e22ea63a8197935be02839c0265541ff61c09/scripts/codegen.js#LL41C1-L42C1

a nice to have IMO, to get $typeUrl so when things are decoded, you know what their types are still: https://github.com/pyramation/interchain46/blob/cd8e22ea63a8197935be02839c0265541ff61c09/scripts/codegen.js#L26

Zetazzz commented 1 year ago

Hi, so, just in short, configs are like these:

    interfaces: {
      enabled: true,
      useUnionTypes: false
    },
...
    prototypes:{
        addTypeUrlToDecoders: true,
...
    },
....
    aminoEncoding: {
      enabled: true,
      useRecursiveV2encoding: true,
    },

Other team also encountered this, and I've tested with the listed config and they work!

Hope they also work for you! Thx!!

ryanchristo commented 1 year ago

Sorry for the delay. I started testing this yesterday and ran into some issues. I updated the configuration and made use of the toProtoMsg helper within MsgCreateGroupWithPolicy and then hit the infamous unauthorized error:

Broadcasting transaction failed with code 4 (codespace: sdk). Log: signature verification failed; please verify account number (1), sequence (4) and chain-id (regen-local): unauthorized

Receiving errors with other messages as well now so I believe this is an issue on my end but will test and followup today.

ryanchristo commented 1 year ago

The above error occurs when metadata fields are empty strings or when groupPolicyAsAdmin is false. Not sure if you have any ideas as to what might be going on here. I was able to successfully execute this message using amino when creating a group with policy as admin (i.e. groupPolicyAsAdmin set to true) and with metadata ' ' (non-empty string).

ryanchristo commented 1 year ago

Another message we are hoping to provide amino support for is MsgSubmitProposal but MsgSubmitProposalEncoded does not exist. Wondering if you have any thoughts on how we would support amino for MsgSubmitProposal as well. We are ok with having limited support for which messages if we end up in a situation where we would need to encode each message.

If you want to look at some code, here is the pull request: https://github.com/regen-network/groups-ui/pull/69

hoangdv2429 commented 1 year ago

@hoangdv2429

hoangdv2429 commented 1 year ago

@ryanchristo Can you provide the message that you use so I can help you with that ?

ryanchristo commented 1 year ago

@hoangdv2429 We're trying to add amino support to a user interface for multiple group messages. We've successfully made use of the encoded type of MsgCreateGroupWithPolicy demonstrated above by @pyramation but only if groupPolicyAsAdmin is set to true. When set to false (or when metadata fields are empty), we receive an unauthorized error.

This may be outside the scope of the original issue, but it looks like zero-values for all group messages are resulting in the same unauthorized error. For example, we receive the same error when exec in MsgVote is set to 0.

Another challenge is adding amino support for MsgSubmitProposal, which has nested any types and ideally we would support all messages but we are ok with applying the same solution for nested any types in MsgCreateGroupWithPolicy. The encoded type for MsgSubmitProposal does not currently exist though.

ryanchristo commented 1 year ago

Here's an example from https://github.com/regen-network/groups-ui/pull/69:

  const encodedMsg: MsgCreateGroupWithPolicyEncoded = {
    admin,
    groupPolicyMetadata: ' ', // TODO: unauthorized error when empty
    groupPolicyAsAdmin: policyAsAdmin === 'true', // TODO: unauthorized error when false
    decisionPolicy: encodeDecisionPolicy({
      policyType,
      percentage: clearEmptyStr(percentage),
      threshold: clearEmptyStr(threshold),
      votingWindow: votingWindow,
    }),
    groupMetadata: JSON.stringify({
      name,
      description,
      forumLink,
      updatedAt: new Date().toString(),
      other: otherMetadata,
    }),
    members: members.map((m) => ({
      address: m.address,
      weight: m.weight.toString(),
      metadata: ' ', // TODO: unauthorized error when empty
      // metadata: JSON.stringify(m.metadata),
    })),
  }

  return {
    typeUrl: '/cosmos.group.v1.MsgCreateGroupWithPolicy',
    value: encodedMsg,
  }
chalabi2 commented 1 month ago

Hey everyone, sorry to bubble up an old issue but im currently running into the proposal submit issue. What is the proposed solution for amino support on group MsgSubmitProposals.

chalabi2 commented 1 month ago

According to the chat history, this

    const msg = cosmos.group.v1.MessageComposer.withTypeUrl.submitProposal({
      groupPolicyAddress: policyAddress,
      proposers: [formData.proposers],
      metadata: CID,
      messages: [{
        typeUrl: "/cosmos.bank.v1beta1.MsgSend",
        value: MsgSend.encode(MsgSend.fromPartial({fromAddress: "manifest1afk9zr2hn2jsac63h4hm60vl9z3e5u69gndzf7c99cqge3vzwjzsfmy9qj", toAddress: "manifest1uwqjtgjhjctjc45ugy7ev5prprhehc7wclherd", amount: [{amount: "1", denom: "umfx"}]})).finish(),
      }],
      exec: 1, 
      title: formData.title,
      summary: formData.metadata.summary,
    });

Should work

fmorency commented 1 month ago

I was able to reproduce the

Log: signature verification failed; please verify account number (13), sequence (1172) and chain-id (manifest-ledger-beta): unauthorized

error using the following

  const signer = await getOfflineSignerAmino({
    mnemonic: ADDR1_MNEMONIC,
    chain: {
      bech32_prefix: 'manifest',
      slip44: 118
    },
  });

  const accounts = await signer.getAccounts();
  const client = await getSigningCosmosClient({
    rpcEndpoint: RPC_ENDPOINT,
    signer: signer,
  });

  const msg2 = cosmos.group.v1.MessageComposer.withTypeUrl.createGroupWithPolicy({
    admin: ADDR1,
    groupMetadata: '',
    groupPolicyAsAdmin: true,
    groupPolicyMetadata: '',
    members: [
      // // Uncommenting the following results in
      // // Broadcasting transaction failed with code 2 (codespace: sdk). Log: errUnknownField "*group.MemberRequest": {TagNum: 4, WireType:"bytes"}: tx parse error
      // // I suspect it's because the `addedAt` field is not part of the `MemberRequest` type
      // {
      //   address: ADDR1,
      //   weight: '10',
      //   metadata: ' ',
      //   addedAt: new Date(1725471079),
      // },
    ],
    decisionPolicy: {
      typeUrl: '/cosmos.group.v1.ThresholdDecisionPolicy',
      threshold: '1',
      windows: {
        votingPeriod: {
          seconds: 10n,
          nanos: 0,
        },
        minExecutionPeriod: {
          seconds: 1n,
          nanos: 0,
        }
      }
    },
  });

  const memo = 'group any test';
  const fees = {
    amount: [
      {
        denom: 'umfx',
        amount: '10000',
      },
    ],
    gas: '200000',
  };
  const { accountNumber, sequence } = await client.getSequence(ADDR1);
  const txRaw = await client.sign(ADDR1, [msg2], fees, memo, {
    accountNumber: accountNumber,
    sequence: sequence,
    chainId: CHAIN_ID
  });
  const txBytes = cosmos.tx.v1beta1.TxRaw.encode(txRaw).finish();
  const result = await client.broadcastTx(txBytes);
  console.log(result)

Note the error when the members field is not empty.

I am using Telescope 1.8.3 on a CosmosSDK 0.50.8 chain & CosmJS 0.32.4.

fmorency commented 1 month ago

Ref: https://github.com/cosmos/cosmos-sdk/issues/18546#user-content-fnref-1-41ce66e35468557ac2054d689d4d7ddb