Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add docs on how to construct and broadcast transactions #11625

Open
Tracked by #139
luca992 opened this issue Apr 13, 2022 · 17 comments · May be fixed by #20421
Open
Tracked by #139

docs: add docs on how to construct and broadcast transactions #11625

luca992 opened this issue Apr 13, 2022 · 17 comments · May be fixed by #20421
Assignees
Labels
T:Docs Changes and features related to documentation.

Comments

@luca992
Copy link

luca992 commented Apr 13, 2022

I'm converting from the /txs end point to /cosmos/tx/v1beta1/txs

The documentation shows an example of a /txs post body as:

{
  "tx": {
    "msg": [
      "string"
    ],
    "fee": {
      "gas": "string",
      "amount": [
        {
          "denom": "stake",
          "amount": "50"
        }
      ]
    },
    "memo": "string",
    "signature": {
      "signature": "MEUCIQD02fsDPra8MtbRsyB1w7bqTM55Wu138zQbFcWx4+CFyAIge5WNPfKIuvzBZ69MyqHsqD8S1IwiEp+iUb6VSdtlpgY=",
      "pub_key": {
        "type": "tendermint/PubKeySecp256k1",
        "value": "Avz04VhtKJh8ACCVzlI8aTosGy0ikFXKIVHQ3jKMrosH"
      },
      "account_number": "0",
      "sequence": "0"
    }
  },
  "mode": "block"
}

but, /cosmos/tx/v1beta1/txs only shows it's example body as:

{
  "tx_bytes": "string",
  "mode": "BROADCAST_MODE_UNSPECIFIED"
}

where tx_bytes is a base64 encoded string.

But, where can I find an example of the tx_bytes json structure before encoding to base64?

Right now I am encoding the tx value from /txs which looks like:

{
    "msg": [
      "string"
    ],
    "fee": {
      "gas": "string",
      "amount": [
        {
          "denom": "stake",
          "amount": "50"
        }
      ]
    },
    "memo": "string",
    "signature": {
      "signature": "MEUCIQD02fsDPra8MtbRsyB1w7bqTM55Wu138zQbFcWx4+CFyAIge5WNPfKIuvzBZ69MyqHsqD8S1IwiEp+iUb6VSdtlpgY=",
      "pub_key": {
        "type": "tendermint/PubKeySecp256k1",
        "value": "Avz04VhtKJh8ACCVzlI8aTosGy0ikFXKIVHQ3jKMrosH"
      },
      "account_number": "0",
      "sequence": "0"
    }
  }

As base64 but I am getting the error: Code: 2; Raw log: expected 2 wire type, got 3: tx parse error

@luca992
Copy link
Author

luca992 commented Apr 13, 2022

Get ​/cosmos​/tx​/v1beta1​/txs​/{hash} shows the response as:

{
  "tx": {
    "body": {
      "messages": [
        {
          "type_url": "string",
          "value": "string"
        }
      ],
      "memo": "string",
      "timeout_height": "string",
      "extension_options": [
        {
          "type_url": "string",
          "value": "string"
        }
      ],
      "non_critical_extension_options": [
        {
          "type_url": "string",
          "value": "string"
        }
      ]
    },
    "auth_info": {
      "signer_infos": [
        {
          "public_key": {
            "type_url": "string",
            "value": "string"
          },
          "mode_info": {
            "single": {
              "mode": "SIGN_MODE_UNSPECIFIED"
            },
            "multi": {
              "bitarray": {
                "extra_bits_stored": 0,
                "elems": "string"
              },
              "mode_infos": [
                null
              ]
            }
          },
          "sequence": "string"
        }
      ],
      "fee": {
        "amount": [
          {
            "denom": "string",
            "amount": "string"
          }
        ],
        "gas_limit": "string",
        "payer": "string",
        "granter": "string"
      }
    },
    "signatures": [
      "string"
    ]
  },
  "tx_response": {
    "height": "string",
    "txhash": "string",
    "codespace": "string",
    "code": 0,
    "data": "string",
    "raw_log": "string",
    "logs": [
      {
        "msg_index": 0,
        "log": "string",
        "events": [
          {
            "type": "string",
            "attributes": [
              {
                "key": "string",
                "value": "string"
              }
            ]
          }
        ]
      }
    ],
    "info": "string",
    "gas_wanted": "string",
    "gas_used": "string",
    "tx": {
      "type_url": "string",
      "value": "string"
    },
    "timestamp": "string"
  }
}

Does that mean the tx_bytes should look like:

{
    "body": {
      "messages": [
        {
          "type_url": "string",
          "value": "string"
        }
      ],
      "memo": "string",
      "timeout_height": "string",
      "extension_options": [
        {
          "type_url": "string",
          "value": "string"
        }
      ],
      "non_critical_extension_options": [
        {
          "type_url": "string",
          "value": "string"
        }
      ]
    },
    "auth_info": {
      "signer_infos": [
        {
          "public_key": {
            "type_url": "string",
            "value": "string"
          },
          "mode_info": {
            "single": {
              "mode": "SIGN_MODE_UNSPECIFIED"
            },
            "multi": {
              "bitarray": {
                "extra_bits_stored": 0,
                "elems": "string"
              },
              "mode_infos": [
                null
              ]
            }
          },
          "sequence": "string"
        }
      ],
      "fee": {
        "amount": [
          {
            "denom": "string",
            "amount": "string"
          }
        ],
        "gas_limit": "string",
        "payer": "string",
        "granter": "string"
      }
    },
    "signatures": [
      "string"
    ]
  }

encoded to base64?

@luca992
Copy link
Author

luca992 commented Apr 13, 2022

I see now that tx_bytes is actually the base64 encoding of a protobuf: https://docs.cosmos.network/v0.45/run-node/txs.html#broadcasting-a-transaction-3. Is there no way to post a transaction using just json anymore?

If not, is there an example of how to correctly build the protobuf for posting as a tx_bytes equivalent to the /txs post body example above?

@devkhalil1337
Copy link

devkhalil1337 commented May 11, 2022

@marbar3778 can you please reply to this thread? I'm having the same issue

@luca992
Copy link
Author

luca992 commented May 12, 2022

@devkhalil1337 I don't really have time to write up how rn. But, I figured it out here: https://github.com/eqoty-labs/secretk/blob/7b0e3f222a82afa09db9b922c334badf9978801c/src/commonMain/kotlin/io/eqoty/client/SigningCosmWasmClient.kt#L126

if you step through my code you can see how I'm building it.

Or if js is easier. I figured it out based on the secret.js code: https://github.com/scrtlabs/secret.js/blob/164eed6f93c419ca7522a3605dc617a7f745b44f/src/secret_network_client.ts#L1049

But, I agree some documentation would be really helpful.

@devkhalil1337
Copy link

devkhalil1337 commented May 12, 2022

thanks for the reply @luca992 I tried but unable to understand I'd appreciate if you can share the exact payload here for the new endpoint

this is the payload I am using

{
	"tx": {
		"msg": [{
			"type": "cosmos-sdk/MsgSend",
			"value": {
				"from_address": "cosmos1k0k9jlj9hgduk5xn2nrgrygv7900hptk2xnr8w",
				"to_address": "cosmos1mkljjemr94rza337l3uqmntz7tqnrm3lntarf6",
				"amount": [{
					"denom": "uatom",
					"amount": "1041100"
				}]
			}
		}],
		"fee": {
			"gas": "74117",
			"amount": [{
				"denom": "uatom",
				"amount": "1000"
			}]
		},
		"memo": "",
		"signatures": [{
			"signature": "rJdMEOzd5lNI9dRbURSuxOOzs2KaJUzDuA3ZHT6rACtzvHsGZ0maTHQkfGYAzZNcv03tUBYAQjS7/Lu343DkvQ==",
			"pub_key": {
				"type": "tendermint/PubKeySecp256k1",
				"value": "AuffQiSZzkY2ulXITteOfEMVPvc4h4cZHQq0YsT5qyjS"
			},
			"account_number": "62932",
			"sequence": "2"
		}]
	},
	"mode": "sync"
}

then encoding to base64 like this
Buffer.from(JSON.stringify(payload), 'hex').toString('base64')

Final Payload:

{
"tx_bytes": "eyJtc2ciOlt7InR5cGUiOiJjb3Ntb3Mtc2RrL01zZ1NlbmQiLCJ2YWx1ZSI6eyJmcm9tX2FkZHJlc3MiOiJjb3Ntb3MxazBrOWpsajloZ2R1azV4bjJucmdyeWd2NzkwMGhwdGsyeG5yOHciLCJ0b19hZGRyZXNzIjoiY29zbW9zMW1rbGpqZW1yOTRyemEzMzdsM3VxbW50ejd0cW5ybTNsbnRhcmY2IiwiYW1vdW50IjpbeyJkZW5vbSI6InVhdG9tIiwiYW1vdW50IjoiMTA0MTEwMCJ9XX19XSwiZmVlIjp7ImdhcyI6Ijc0MTE3IiwiYW1vdW50IjpbeyJkZW5vbSI6InVhdG9tIiwiYW1vdW50IjoiMTAwMCJ9XX0sIm1lbW8iOiIiLCJzaWduYXR1cmVzIjpbeyJzaWduYXR1cmUiOiJySmRNRU96ZDVsTkk5ZFJiVVJTdXhPT3pzMkthSlV6RHVBM1pIVDZyQUN0enZIc0daMG1hVEhRa2ZHWUF6Wk5jdjAzdFVCWUFRalM3L0x1MzQzRGt2UT09IiwicHViX2tleSI6eyJ0eXBlIjoidGVuZGVybWludC9QdWJLZXlTZWNwMjU2azEiLCJ2YWx1ZSI6IkF1ZmZRaVNaemtZMnVsWElUdGVPZkVNVlB2YzRoNGNaSFFxMFlzVDVxeWpTIn0sImFjY291bnRfbnVtYmVyIjoiNjI5MzIiLCJzZXF1ZW5jZSI6IjIifV19",
"mode": "BROADCAST_MODE_SYNC"
}

response:

{ "tx_response": { "height": "0", "txhash": "7B234A905431A84562AC29A0F8418BD986783CEAE960C76E53D8D0178C7A7851", "codespace": "sdk", "code": 2, "data": "", "raw_log": "expected 2 wire type, got 3: tx parse error", "logs": [], "info": "", "gas_wanted": "0", "gas_used": "0", "tx": null, "timestamp": "", "events": [] } }

@luca992
Copy link
Author

luca992 commented May 13, 2022

first your actual payload should look like:

pseudo-code

// txBytes is the encoded bytearray of a protobuf
val txString = txBytes.toByteString().base64()
val params = {
                "tx_bytes": "$txString",
                "mode": "BROADCAST_MODE_SYNC"
             }

@luca992
Copy link
Author

luca992 commented May 13, 2022

Screen Shot 2022-05-13 at 2 10 01 PM

Screen Shot 2022-05-13 at 2 08 36 PM

to build txBytes. I am encoding a protobuffer to a byte array with the structure pictured above. And each of those also contained encoded byte arrays for other protobuffers... basically each probuf class required as parameter of a another protobuf class needs to be encoded to a byte array.

So, bodyBytes and authInfoBytes are protobuffer objects which were previously encoded to byte arrays here for example

The the TxRaw probuf is defined here:

Sorry, probably not the best explanation. But maybe will get you headed in the right direction. You are probably going to have to read up on how protobufs work if you haven't used them before. I definitely had to haha

@devkhalil1337
Copy link

devkhalil1337 commented May 13, 2022

@luca992 thanks for the explanation I get the final payload just one more thing, I am working in javascript and is this JSON object is fine before converting it to the byteArray and base64

{
	"tx": {
		"msg": [{
			"type": "cosmos-sdk/MsgSend",
			"value": {
				"from_address": "cosmos1k0k9jlj9hgduk5xn2nrgrygv7900hptk2xnr8w",
				"to_address": "cosmos1mkljjemr94rza337l3uqmntz7tqnrm3lntarf6",
				"amount": [{
					"denom": "uatom",
					"amount": "1041100"
				}]
			}
		}],
		"fee": {
			"gas": "74117",
			"amount": [{
				"denom": "uatom",
				"amount": "1000"
			}]
		},
		"memo": "",
		"signatures": [{
			"signature": "rJdMEOzd5lNI9dRbURSuxOOzs2KaJUzDuA3ZHT6rACtzvHsGZ0maTHQkfGYAzZNcv03tUBYAQjS7/Lu343DkvQ==",
			"pub_key": {
				"type": "tendermint/PubKeySecp256k1",
				"value": "AuffQiSZzkY2ulXITteOfEMVPvc4h4cZHQq0YsT5qyjS"
			},
			"account_number": "62932",
			"sequence": "2"
		}]
	},
	"mode": "sync"
}

or does it need to be update as below:

"tx": {
	"body": {
		"messages": [{
			"@type": "/cosmos.bank.v1beta1.MsgSend",
			"from_address": "cosmos1k0k9jlj9hgduk5xn2nrgrygv7900hptk2xnr8w",
			"to_address": "cosmos1favsh7vjakvfe2qddjdxtwmmxqfakc7jyqlhs3",
			"amount": [{
				"denom": "uatom",
				"amount": "20000"
			}]
		}],
		"memo": "",
		"timeout_height": "0",
		"extension_options": [],
		"non_critical_extension_options": []
	},
	"auth_info": {
		"signer_infos": [{
			"public_key": {
				"@type": "/cosmos.crypto.secp256k1.PubKey",
				"key": "AuffQiSZzkY2ulXITteOfEMVPvc4h4cZHQq0YsT5qyjS"
			},
			"mode_info": {
				"single": {
					"mode": "SIGN_MODE_LEGACY_AMINO_JSON"
				}
			},
			"sequence": "0"
		}],
		"fee": {
			"amount": [{
				"denom": "uatom",
				"amount": "1000"
			}],
			"gas_limit": "74117",
			"payer": "",
			"granter": ""
		}
	},
	"signatures": ["usdaBp6VRXe2AC/fGjqUFnbTuq884oyf8sdmRWWr5bYjK1T5Pgjy2H06qUcR02p6eOymqWkywRdK73jn5ZBvgg=="]
},

@luca992
Copy link
Author

luca992 commented May 13, 2022

The second. It'd be tx_bytes not tx

But, the structure looks approximately right to me. You are going to have to encode all of those sub-objects with @type to protobufs byte arrays

@devkhalil1337
Copy link

Thanks again for your time @luca992

broadcast Object :

{
	"body": {
		"messages": [{
			"@type": "/cosmos.bank.v1beta1.MsgSend",
			"from_address": "cosmos1k0k9jlj9hgduk5xn2nrgrygv7900hptk2xnr8w",
			"to_address": "cosmos1mkljjemr94rza337l3uqmntz7tqnrm3lntarf6",
			"amount": [{
				"denom": "uatom",
				"amount": "1041100"
			}]
		}],
		"memo": "",
		"timeout_height": "0",
		"extension_options": [],
		"non_critical_extension_options": []
	},
	"AuthInfo": {
		"signer_infos": [{
			"public_key": {
				"@type": "/cosmos.crypto.secp256k1.PubKey",
				"key": "AuffQiSZzkY2ulXITteOfEMVPvc4h4cZHQq0YsT5qyjS"
			},
			"mode_info": {
				"single": {
					"mode": "SIGN_MODE_LEGACY_AMINO_JSON"
				}
			},
			"sequence": "2"
		}],
		"fee": {
			"amount": [{
				"denom": "uatom",
				"amount": "1000"
			}],
			"gas_limit": "74117",
			"payer": "",
			"granter": ""
		}
	},
	"signatures": ["rJdMEOzd5lNI9dRbURSuxOOzs2KaJUzDuA3ZHT6rACtzvHsGZ0maTHQkfGYAzZNcv03tUBYAQjS7/Lu343DkvQ=="]
}

then converting it to base64
Buffer.from(JSON.stringify(broadcast)).toString('base64')

Final Payload:

{
    "tx_bytes": "eyJib2R5Ijp7Im1lc3NhZ2VzIjpbeyJAdHlwZSI6Ii9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQiLCJmcm9tX2FkZHJlc3MiOiJjb3Ntb3MxazBrOWpsajloZ2R1azV4bjJucmdyeWd2NzkwMGhwdGsyeG5yOHciLCJ0b19hZGRyZXNzIjoiY29zbW9zMW1rbGpqZW1yOTRyemEzMzdsM3VxbW50ejd0cW5ybTNsbnRhcmY2IiwiYW1vdW50IjpbeyJkZW5vbSI6InVhdG9tIiwiYW1vdW50IjoiMTA0MTEwMCJ9XX1dLCJtZW1vIjoiIiwidGltZW91dF9oZWlnaHQiOiIwIiwiZXh0ZW5zaW9uX29wdGlvbnMiOltdLCJub25fY3JpdGljYWxfZXh0ZW5zaW9uX29wdGlvbnMiOltdfSwiQXV0aEluZm8iOnsic2lnbmVyX2luZm9zIjpbeyJwdWJsaWNfa2V5Ijp7IkB0eXBlIjoiL2Nvc21vcy5jcnlwdG8uc2VjcDI1NmsxLlB1YktleSIsImtleSI6IkF1ZmZRaVNaemtZMnVsWElUdGVPZkVNVlB2YzRoNGNaSFFxMFlzVDVxeWpTIn0sIm1vZGVfaW5mbyI6eyJzaW5nbGUiOnsibW9kZSI6IlNJR05fTU9ERV9MRUdBQ1lfQU1JTk9fSlNPTiJ9fSwic2VxdWVuY2UiOiIyIn1dLCJmZWUiOnsiYW1vdW50IjpbeyJkZW5vbSI6InVhdG9tIiwiYW1vdW50IjoiMTAwMCJ9XSwiZ2FzX2xpbWl0IjoiNzQxMTciLCJwYXllciI6IiIsImdyYW50ZXIiOiIifX0sInNpZ25hdHVyZXMiOlsickpkTUVPemQ1bE5JOWRSYlVSU3V4T096czJLYUpVekR1QTNaSFQ2ckFDdHp2SHNHWjBtYVRIUWtmR1lBelpOY3YwM3RVQllBUWpTNy9MdTM0M0RrdlE9PSJdfQ==",
    "mode": "BROADCAST_MODE_SYNC"
}

Response:

{
    "tx_response": {
        "height": "0",
        "txhash": "AA38BAF1606F7A9CAF9E5181111F9C237942E1039DEFAB7BD9D1039A7894549E",
        "codespace": "sdk",
        "code": 2,
        "data": "",
        "raw_log": "expected 2 wire type, got 3: tx parse error",
        "logs": [],
        "info": "",
        "gas_wanted": "0",
        "gas_used": "0",
        "tx": null,
        "timestamp": "",
        "events": []
    }
}

@luca992
Copy link
Author

luca992 commented May 16, 2022

That won't work. You are encoding json to a byte array. You need to build a protobuffer object that contains that data. Then encode the protobuffer to a byte array

@elite0226
Copy link

Any solutions here?

@alexanderbez
Copy link
Contributor

Any solutions here?

Sorry @elite0226, but what are you trying to do again?

@tac0turtle
Copy link
Member

are you manually constructing the body or using a library. the client package in the sdk and cosmjs give you ways to handle this out of the box.

also with 0.47 there are endpoints that will handle the encoding needed for signing and broadcasting this would fix the need to write your own implementations

@tac0turtle tac0turtle changed the title Converting post body to /cosmos/tx/v1beta1/txs from /txs docs: add docs on how to construct and broadcast transactions Mar 24, 2023
@tac0turtle tac0turtle added T:Docs Changes and features related to documentation. and removed T:question labels Apr 3, 2023
@shang-chi-7
Copy link

Any update on this, facing same issue ?

@bd21
Copy link

bd21 commented Sep 3, 2023

+1 on the docs being complete ass. The example on calling modules programmatically with Go doesn't even resolve.

@tac0turtle you guys should hire a technical writer

@GabrielFerraroDev
Copy link

someone has updates on this? i have the same problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T:Docs Changes and features related to documentation.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

11 participants