cosmos / cosmjs

The Swiss Army knife to power JavaScript based client solutions ranging from Web apps/explorers over browser extensions to server-side clients like faucets/scrapers.
https://cosmos.github.io/cosmjs/
Apache License 2.0
656 stars 344 forks source link

Keplr offlineSigner failing with SigningStargateClient #872

Open xanderjl opened 3 years ago

xanderjl commented 3 years ago

We're attempting to get delegation in Stargate to work with Keplr wallet. All articles and documentation seem to be out of date and do not offer a working solution.

The code block thus far:

const initKeplr = async () => {
  if (typeof window === 'undefined') return

  if (window.keplr == null) {
    alert('Go install Keplr >:(')
  } else {
    if (window.keplr.experimentalSuggestChain) {
      try {
        await window.keplr.experimentalSuggestChain(suggestChainConfig)
      } catch {
        alert('Failed to suggest the chain')
      }
    } else {
      alert('Please use the recent version of keplr extension')
    }

    try {
      // If this fails, user is not logged in to Keplr
      await window.keplr.enable(chainId)

      const offlineSigner =
        window.getOfflineSigner != null
          ? window.getOfflineSigner(chainId)
          : null
      if (offlineSigner == null) return 'error'

      // You can get the address/public keys by `getAccounts` method.
      // It can return the array of address/public key.
      // But, currently, Keplr extension manages only one address/public key pair.
      // XXX: This line is needed to set the sender address for SigningCosmosClient.
      const accounts = await offlineSigner.getAccounts()

      const delegateMsg = MsgDelegate.fromPartial({
        delegatorAddress: accounts[0].address,
        validatorAddress:
          'cosmosvaloper1address',
        amount: { denom: 'stake', amount: '1000000000' }
      })

      const stargateClient = await SigningStargateClient.connectWithSigner(
        rpcUrl,
        offlineSigner
      )

      const test = await stargateClient.getAccount(accounts[0].address)
      console.log({ test })

      stargateClient.signAndBroadcast(
        accounts[0].address,
        [
          {
            typeUrl: '/cosmos.staking.v1beta1.MsgDelegate',
            value: delegateMsg
          }
        ],
        {
          gas: '200000',
          amount: [{ denom: 'stake', amount: '1000000000' }]
        }
      )
    } catch (err) {
      console.log(err)
    }
  }
}

From the data tab in Keplr pre-approval:

{
  "txBody": {
    "messages": [
      {
        "delegatorAddress": "cosmos1address",
        "validatorAddress": "cosmosvaloper1address",
        "amount": {
          "denom": "stake",
          "amount": "1000000000"
        }
      }
    ],
    "memo": ""
  },
  "authInfo": {
    "signerInfos": [
      {
        "publicKey": {
          "type_url": "/cosmos.crypto.secp256k1.PubKey",
          "value": "didn't know if this was sensitive :)"
        },
        "modeInfo": {
          "single": {
            "mode": "SIGN_MODE_DIRECT"
          }
        }
      }
    ],
    "fee": {
      "amount": [
        {
          "denom": "stake",
          "amount": "5000"
        }
      ],
      "gasLimit": "200000"
    }
  },
  "chainId": "chain-id",
  "accountNumber": "0"
}

Error output:

Error: Broadcasting transaction failed with code 4 (codespace: sdk). Log: signature verification failed; please verify account number (0) and chain-id (strangetest-1): unauthorized

versions:

Keplr extension - 0.8.14 @cosmjs/stargate - 0.26.0-alpha2

Any insight would be greatly appreciated 🙏

ethanfrey commented 3 years ago

I highly suggest looking at the wallet and staking apps in https://github.com/CosmWasm/dApps.

You will need to update config.ts to point to a more recent network (or local test network) and likely want to launch @cosmjs/faucet locally to get funds in these new accounts (unless you just load pre-funded accounts).

It works with keplr, ledger, and local storage. Uses React/TypeScript and CosmJS 0.25.6.

A good example to start with.

Also happy if anyone wants to contribute to that repo - with docs or with code improvements.