Injective Frontend Wallet
Use this skill before shipping any Injective browser transaction flow. Injective looks Cosmos-shaped at the transaction layer, but its accounts and public keys are Ethereum-style. Generic Cosmos frontend code often reaches the quote screen and then fails at signing or CheckTx.
First Decision
Choose the signing stack deliberately:
- Prefer
@injectivelabs/sdk-ts / Injective broadcaster utilities when the app
already uses the Injective SDK and the transaction type is covered.
- Use CosmJS for CosmWasm frontends only if you explicitly handle Injective
account and pubkey compatibility.
- Do not assume a Keplr/Leap
inj1... address means generic
/cosmos.crypto.secp256k1.PubKey signing will validate on-chain.
Required Checks
Before calling the work complete, verify these on the actual signing path:
- Query account metadata from LCD:
GET /cosmos/auth/v1beta1/accounts/{injAddress}.
- If the account
@type is /injective.types.v1beta1.EthAccount, parse
baseaccount.accountnumber and base_account.sequence; do not rely on CosmJS' default accountFromAny.
- Ensure transaction
AuthInfo.signerinfos[0].publickey.type_url is
/injective.crypto.v1beta1.ethsecp256k1.PubKey.
- Ensure the public key bytes are encoded as protobuf field 1
(0a <len> <compressed-pubkey>), same field shape as the standard secp256k1 key but with the Injective type URL.
- For direct signing, sign the
SignDoc that contains that Injective pubkey in
authInfoBytes; otherwise the wallet signs bytes that differ from the broadcast transaction.
- Use the wallet address returned for chain
injective-1; do not derive or
substitute addresses from another chain account without conversion checks.
Browser Trading Flow Checks
Browser trading apps need UI-level guards in addition to correct signing bytes:
- Keep a single per-wallet in-flight lock around transaction-producing actions.
Disable open, close, cash-out, and bulk action buttons until the prior tx is confirmed or has failed.
- Do not rely on per-card loading state to prevent duplicate broadcasts; two
buttons can still race the same account sequence.
- Revalidate any local session, grantee, or autosign token against the currently
connected inj1 address after wallet connect, account swap, and page reload.
- Treat
account sequence mismatch, expected X, got Y as a likely concurrency
bug first. Audit parallel clicks, multiple tabs, stale cached sequence, and background retries before changing chain parameters.
- Keep raw CheckTx details in logs. User-facing errors should explain the
action, such as Order failed, please try again., not expose transaction hashes, RFQ IDs, account sequences, or signer internals.
Common Failures
If the error is:
Unsupported type: '/injective.types.v1beta1.EthAccount': the client is
using a generic Cosmos account parser for sequence/account number. Patch getSequence() or use Injective SDK account querying.
pubKey does not match signer address ... invalid pubkey: AuthInfo likely
contains /cosmos.crypto.secp256k1.PubKey; use /injective.crypto.v1beta1.ethsecp256k1.PubKey.
account does not exist on chain: the wallet has never transacted or is
unfunded. Fund it with INJ and retry after the account exists.
signature verification failed: inspect sign mode, signed authInfoBytes,
account number, sequence, and chain ID before changing business logic.
CosmJS Compatibility Pattern
When using SigningCosmWasmClient against Injective:
- Connect with the wallet signer.
- Patch or wrap
getSequence(address) so it reads account number and sequence
from Injective LCD for EthAccount.
- Patch direct signing so
AuthInfo uses the Injective ethsecp pubkey type
URL.
- Keep the actual business message unchanged, such as
MsgExecuteContract for
a swap contract.
- Add unit tests for the account payload and pubkey encoding helpers.
Minimal helper expectations:
const INJECTIVE_PUBKEY_TYPE = "/injective.crypto.v1beta1.ethsecp256k1.PubKey";
const INJECTIVE_ACCOUNT_TYPE = "/injective.types.v1beta1.EthAccount";
Swap Contract Frontends
For Injective swap-contract UIs:
- Query the contract for routes and quotes; do not inspect orderbooks in the
browser unless the task explicitly requires independent analytics.
- Execute the swap contract message (
swapminoutput or swapexactoutput)
with exactly one input coin in funds.
- Keep RFQ and direct exchange-module order placement out of scope unless the
user asks for those venues.
- Apply slippage to the contract quote's raw output quantity, not the formatted
decimal string.
- Test a live quote and a dry signing-path construction before asking the user
to sign real funds.
Regression Checklist
Add at least these tests or harness checks:
- Parse an Injective
EthAccount LCD fixture into
{ accountNumber, sequence }.
- Encode an Injective ethsecp pubkey and assert the type URL exactly.
- Build a tx or signing harness and assert
authInfoBytes contains the
Injective pubkey type before broadcast.
- Run
typecheck, unit tests, and a production build for browser apps.
Do Not Ship Until
- The account type and pubkey type checks above have been run.
- The transaction path has been tested with the same wallet family the user will
use, typically Keplr or Leap for inj1.
- Any fallback to generic CosmJS behavior is documented as unsafe for Injective
unless proven with the checks above.