All skills
injectivelabs avatar

/injective-wallet-ops

@ba428ea

Mass create, derive, and manage Injective wallets. Generate wallets from mnemonics (BIP-44 HD derivation), create random wallets, convert between ETH/INJ addresses, and batch fund wallets with INJ or USDT. Supports bulk wallet generation and batch funding.

Use this Skill: https://skilld.dev/gh/injectivelabs/agent-skills/injective-wallet-ops

This session only. Nothing lands on disk.

SKILL.md

≈70 tokens always: the name and description. ≈1.3k when used: this file.

Injective Wallet Operations Skill

Overview

Generate, derive, fund, and manage Injective wallets in bulk. Based on proven patterns from an Injective RFQ test framework.

Reference Code

Key implementation files (from an Injective RFQ test framework):

  • Wallet library: src/rfq_test/crypto/wallet.py
  • Mass generation: scripts/generate_wallets.py, scripts/setup_wallets.py
  • Key derivation CLI: derive_key.py
  • Mass funding: scripts/fund_subaccounts.py, scripts/fund_demo_subaccounts.py
  • Balance checks: scripts/check_balances.py, scripts/check_all_balances.py

Wallet Generation

From Mnemonic (Deterministic, BIP-44)

from eth_account import Account
Account.enable_unaudited_hdwallet_features()

def generate_wallets_from_seed(seed_phrase: str, count: int, start_index: int = 0):
    wallets = []
    for i in range(start_index, start_index + count):
        path = f"m/44'/60'/0'/0/{i}"
        acct = Account.from_mnemonic(seed_phrase, account_path=path)
        eth_addr = acct.address
        inj_addr = eth_to_inj_address(eth_addr)
        wallets.append({
            "index": i,
            "private_key": acct.key.hex(),
            "eth_address": eth_addr,
            "inj_address": inj_addr,
        })
    return wallets

Random Wallets

import secrets
key = secrets.token_hex(32)
# Then use PrivateKey.from_hex(key) from pyinjective

Address Conversion (ETH <-> INJ)

Injective is EVM-compatible: every secp256k1 key has two address encodings that map 1:1. The 0x form (40 hex chars) is what MetaMask + bridging tools show; the inj1 form (bech32, 38 chars after the prefix) is what Cosmos RPCs, MsgSend, contract state, and the indexer use. Any code that accepts a user-supplied address should accept both forms and canonicalize to inj1 before chain ops — rate limits, dedup keys, and authz lookups must be keyed on the inj form, otherwise a caller can dodge them by flipping encodings.

Validation regexes (accept both, reject everything else):

inj1:  ^inj1[02-9ac-hj-np-z]{38}$      (bech32 charset; no b/i/o/1)
0x:    ^0x[0-9a-fA-F]{40}$              (mixed case OK; normalize to lowercase)

Python (standalone, no SDK):

import bech32
def eth_to_inj_address(eth_address: str) -> str:
    eth_bytes = bytes.fromhex(eth_address.removeprefix("0x"))
    five_bit = bech32.convertbits(eth_bytes, 8, 5)
    return bech32.bech32_encode("inj", five_bit)

def inj_to_eth_address(inj_address: str) -> str:
    _, five_bit = bech32.bech32_decode(inj_address)
    eight_bit = bech32.convertbits(five_bit, 5, 8, False)
    return "0x" + bytes(eight_bit).hex()

Node / TypeScript (via @injectivelabs/sdk-ts, preferred when the project already depends on it):

import { getInjectiveAddress, getEthereumAddress } from '@injectivelabs/sdk-ts';

// 0x → inj1
const inj = getInjectiveAddress('0xYourEthAddress…40hex');
// inj1 → 0x (lowercase)
const eth = getEthereumAddress('inj1yourbech32address…');

Accept-either pattern (server accepting an external address):

const INJ_BECH32 = /^inj1[02-9ac-hj-np-z]{38}$/;
const ETH_HEX    = /^0x[0-9a-fA-F]{40}$/;

function normalize(raw: string) {
  const s = raw.trim();
  if (INJ_BECH32.test(s)) return { inj: s,                       eth: getEthereumAddress(s).toLowerCase() };
  if (ETH_HEX.test(s))    return { inj: getInjectiveAddress(s),  eth: s.toLowerCase() };
  throw new Error('malformed address — expected inj1… (43 chars) or 0x… (42 chars)');
}

The PrivateKey.toBech32() / .toAddress() methods on sdk-ts's PrivateKey return these two forms from a key directly — useful when you're generating + need both at once.

Mass Funding

Send INJ to Many Wallets (batched MsgSend)

The setup_wallets.py pattern batches up to 200 MsgSend messages in a single transaction:

from pyinjective.composer import Composer
from pyinjective.transaction import Transaction

msgs = []
for wallet in wallets:
    msg = composer.msg_send(
        sender=funder_address,
        receiver=wallet["inj_address"],
        amount=amount,
        denom="inj"
    )
    msgs.append(msg)
# Submit all msgs in one tx

Deposit to Exchange Subaccount

After funding bank accounts, deposit to trading subaccounts:

from pyinjective.core.broadcaster import MsgBroadcasterWithPk

msg = composer.msg_subaccount_deposit(
    sender=address,
    subaccount_id=get_subaccount_id(address, nonce=0),
    amount=Decimal(str(amount)),
    denom=denom
)

Two-Step USDT Funding (testnet)

  1. Parent wallet sends USDT via bank MsgSend to child
  2. Child deposits USDT from bank to exchange subaccount

Balance Checks

# Bank balance
balance = await client.fetch_bank_balance(address, denom)

# Subaccount deposit
deposits = await client.fetch_subaccount_deposits(subaccount_id)

Environment Config

  • Env var prefix pattern: {ENV}_LOAD_TEST_MM_SEED_PHRASE, {ENV}_LOAD_TEST_RETAIL_SEED_PHRASE
  • Or comma-separated key lists: TESTNET_MM_KEYS=hex1,hex2,...
  • YAML configs at configs/{env}.yaml

Dependencies

  • injective-py>=1.12.0
  • eth-account>=0.11.0
  • bech32>=1.2.0
  • Python >= 3.11

Source: SKILL.md on GitHub

1 alert4mo3 checks · Risk SAFE
  • Gen Agent Trust Hub4mo

    The skill provides utilities for managing Injective wallets, including key derivation and address conversion. While it includes security best practices for handling address encoding, it instructs the agent to handle sensitive private keys in plaintext, which poses a risk of accidental exposure in logs or chat history.

  • Socket4mo

    1 alert: gptSecurity

  • Snyk4mo

    Risk: HIGH · 3 issues

Signed by skilld at ba428ea. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 5 months ago
metadata
{
  "author": "ck",
  "version": "1.0.0"
}

README badge

README badge for injectivelabs/agent-skills/injective-wallet-ops