Lumera Protocol

Injective primer

A short, integration-focused tour of Injective.

What is Injective?

Injective is a Cosmos-SDK Layer-1 with CometBFT consensus, CosmWasm 2.0 smart contracts, and a custom set of finance-native modules (orderbook, oracle, insurance, peggy). The native token is INJ (inj, 18 decimals), with sub-second finality and IBC connectivity to the broader Cosmos network.

For Cascade integration purposes, three facts about Injective matter:

  1. It runs CosmWasm 2.0, so contracts are Rust crates compiled to Wasm with cosmwasm-std ≥ 2.0.
  2. It uses eth_secp256k1 key derivation (Ethereum's curve) rather than the standard secp256k1 used by Lumera and most Cosmos chains. This changes how Keplr is configured and how signing works.
  3. The bech32 prefix is inj. Addresses look like inj1….

Networks

TestnetMainnet
Chain IDinjective-888injective-1
RPChttps://testnet.sentry.tm.injective.network:443https://sentry.tm.injective.network:443
LCD/RESThttps://testnet.sentry.lcd.injective.network:443https://sentry.lcd.injective.network:443
gRPCtestnet.sentry.chain.grpc.injective.network:443sentry.chain.grpc.injective.network:443
Explorertestnet.explorer.injective.networkexplorer.injective.network
Coin denominj (18 decimals → INJ)same
Gas price500000000inj (≈0.5 Gwei equivalent)similar
Faucettestnet.faucet.injective.networkinj.supply

CosmWasm on Injective

Injective ships CosmWasm 2.0. Anything you can write in cosmwasm-std ≥ 2.0 and compile with the cosmwasm/optimizer Docker image will run on Injective once stored. Two Injective-specific things to know:

  • cosmwasm-2.0 only. Older CW 1.x bytecode will not store. Pin cosmwasm-std = "2.x" in your Cargo.toml.
  • Bonds, bets, and fees are paid in the native inj denom, which is the base unit (inj = 1 wei-equivalent). A 1-INJ value is 1000000000000000000 (1 × 10¹⁸). The gas price is denominated in inj base units; --gas-prices 500000000inj works for testnet.

A minimal deploy from a box with injectived installed:

injectived tx wasm store ./artifacts/my_contract.wasm \
  --from uploader \
  --gas auto --gas-adjustment 1.4 --gas-prices 500000000inj \
  --chain-id injective-888 \
  --node https://testnet.sentry.tm.injective.network:443 \
  --broadcast-mode sync --yes -o json

You get back a code_id; instantiate with injectived tx wasm instantiate <code_id> <init-json>.

The native orderbook

Injective has a chain-level orderbook for spot and derivatives markets. If you're building a product where price discovery matters, such as a derivatives market with permanent settlement evidence or a perpetual with permanent funding-rate justifications, the orderbook is the natural fit. Cascade serves as permanent storage for the receipts, the oracle inputs, and the dispute justifications, with action_id pointers held in the matching contract.

Wallets and signing

The Injective wallet model is essentially Ethereum's: the curve is eth_secp256k1, derivation is BIP-44 with coinType: 60, and addresses are bech32-encoded keccak256. A typical Keplr chain registration looks like this:

lib/chain.ts
import type { ChainInfo } from '@keplr-wallet/types';
 
export const injectiveTestnet: ChainInfo = {
  chainId: 'injective-888',
  chainName: 'Injective Testnet',
  rpc: 'https://testnet.sentry.tm.injective.network:443',
  rest: 'https://testnet.sentry.lcd.injective.network:443',
  bip44: { coinType: 60 },                        // ← Ethereum, not 118
  bech32Config: {
    bech32PrefixAccAddr: 'inj',
    bech32PrefixAccPub: 'injpub',
    bech32PrefixValAddr: 'injvaloper',
    bech32PrefixValPub: 'injvaloperpub',
    bech32PrefixConsAddr: 'injvalcons',
    bech32PrefixConsPub: 'injvalconspub',
  },
  currencies: [{ coinDenom: 'INJ', coinMinimalDenom: 'inj', coinDecimals: 18 }],
  feeCurrencies: [{
    coinDenom: 'INJ',
    coinMinimalDenom: 'inj',
    coinDecimals: 18,
    gasPriceStep: { low: 500_000_000, average: 700_000_000, high: 1_000_000_000 },
  }],
  stakeCurrency: { coinDenom: 'INJ', coinMinimalDenom: 'inj', coinDecimals: 18 },
  features: ['eth-address-gen', 'eth-key-sign'],  // ← required for Injective
};

The two things that differ from a standard Cosmos chain registration are bip44.coinType: 60 and the features: ['eth-address-gen', 'eth-key-sign'] array. Without eth-key-sign, Keplr signs over the wrong digest and Injective rejects every transaction.

Injective's eth_secp256k1 keys are not direct-mode-friendly under the current cosmjs build. Use keplr.getOfflineSignerOnlyAmino(chainId) rather than getOfflineSigner. If you use SigningCosmWasmClient with the standard direct-mode signer, you'll get opaque signature-mismatch errors.

The signing client wires up as:

lib/inj.ts
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';
import { GasPrice } from '@cosmjs/stargate';
 
const GAS_PRICE = GasPrice.fromString('500000000inj');
 
export async function getSigningClient() {
  await window.keplr!.experimentalSuggestChain(injectiveTestnet);
  await window.keplr!.enable('injective-888');
  const signer = await window.keplr!.getOfflineSignerOnlyAmino('injective-888');
  return SigningCosmWasmClient.connectWithSigner(INJECTIVE_RPC, signer, { gasPrice: GAS_PRICE });
}

Once you have a SigningCosmWasmClient, contract calls look like any other Cosmos chain: client.execute(sender, contractAddr, msg, 'auto', memo, funds).

Cross-chain signing

If your dApp asks users to sign Cascade writes themselves (the user-driven pattern), a session needs two addresses: an inj1… address for Injective contract calls, and a lumera1… address for Cascade uploads. Both can come from the same Keplr extension. The user enables the Injective chain (eth_secp256k1) for Injective and the Lumera chain (standard secp256k1) for Cascade. They derive from different BIP-44 paths, so the addresses differ across the two chains.

Many integrations avoid this entirely by signing Cascade writes server-side (the cascade-api path), so the user only ever signs on Injective. See Cascade from Injective for both options.

A note on IBC and Interchain Accounts

Injective is IBC-connected, and in principle a CosmWasm contract on Injective can drive an ICS-27 Interchain Account on Lumera to write to Cascade autonomously. You almost certainly do not need this. The IBC round-trip adds 30–60s of latency and degrades when the relayer is backed up, so it is the wrong tool for any user-facing flow.

The recommended integration paths don't involve IBC: they are either server-signed via the cascade-api, or user-signed from a wallet. Treat ICA as an advanced option reserved for the narrow case where a contract itself must be the signer of a canonical write with no user in the loop. It is covered, with that framing, in Cascade from Injective.

Tools you will use

PackageWhat for
@cosmjs/cosmwasm-stargateBuild and sign Injective MsgExecuteContract
@keplr-wallet/typesType-safe Keplr chain info and signer
@injectivelabs/sdk-tsInjective-specific helpers (optional; cosmjs is enough for CW calls)
@lumera-protocol/sdk-jsSign Lumera transactions and write to Cascade directly
injectivedThe CLI for storing, instantiating, and executing contracts

Where to go next

Edit this page

On this page