Emoji minting on Injective EVM - a Slack bot that lets users mint emoji tokens as ERC-1155 NFTs.
Built on the injective-evm-foundry template.
Slack ──► /brrr :fire: @alice ──► Bot (TypeScript) ──► Pryntr.sol (ERC-1155) ──► Injective EVM
- Pryntr.sol : ERC-1155 contract. Each emoji is a token type. 24h cooldown per sender.
- Bot : TypeScript Slack bot (Bolt). Derives deterministic addresses from Slack user IDs, calls the contract, returns tx links.
- Local devnet : Dockerized Injective node + Blockscout explorer for development.
forge install OpenZeppelin/openzeppelin-contractsmake build
make testmake local-init # One-time: initialize chain, create funded accounts
make local-start # Start Injective node + Blockscout explorerAfter local-init, you'll see two pre-funded dev accounts with mnemonics. Derive the EVM private key:
cast wallet private-key --mnemonic "copper push brief egg scan entry inform record adjust fossil boss egg comic alien upon aspect dry avoid interest fury window hint race symptom"Create .env with the dev1 private key:
cp .env.example .env
# Edit .env — set PRIVATE_KEY to the dev1 EVM key from step 3make local-deployNote the deployed contract address from the output.
cd bot
cp .env.example .envEdit bot/.env — set PRIVATE_KEY and PRYNTR_ADDRESS from the previous steps, then generate a salt for address derivation:
openssl rand -hex 32Paste the output as ADDRESS_SALT in bot/.env. This salt prevents outsiders from mapping user IDs to on-chain addresses. Generate it once and don't change it after minting — changing it orphans existing user addresses.
npm installCLI mode (no Slack required):
npx tsx src/cli.ts mint :fire: alice bob
npx tsx src/cli.ts portfolio bob
npx tsx src/cli.ts cooldown aliceSlack bot mode (set SLACK_BOT_TOKEN, SLACK_APP_TOKEN, SLACK_SIGNING_SECRET in .env):
npm run devOpen http://localhost:3000 to see transactions in the local Blockscout explorer.
Injective has two explorers serving different purposes:
| Explorer | URL | Shows |
|---|---|---|
| Cosmos explorer | https://testnet.explorer.injective.network | Cosmos-native txs, validators, governance, IBC |
| EVM explorer (Blockscout) | https://testnet.blockscout.injective.network | EVM txs, contract source, ABI interaction, token balances |
For EVM contract development, use the Blockscout explorer. It shows contract creation addresses, verified source code, and lets you interact with contracts directly. The Cosmos explorer shows the same transactions but from the Cosmos side — it won't display EVM-specific details like deployed contract addresses.
For local development, the Blockscout instance runs at http://localhost:3000.
pryntr-tutorial/
├── foundry.toml # Foundry config (Solidity 0.8.28, Cancun EVM)
├── Makefile # Build/test/deploy targets
├── .env.example # Configuration template
├── src/
│ └── Pryntr.sol # ERC-1155 emoji minting contract
├── test/
│ └── Pryntr.t.sol # 11 test cases
├── script/
│ └── Deploy.s.sol # Deployment script
├── vendor/
│ ├── fetch.sh # Fetch Injective precompile contracts
│ └── injective/ # Vendored precompile interfaces
├── local-dev/
│ ├── docker-compose.yml # Injective node + Blockscout
│ └── setup.sh # Chain initialization
└── bot/
├── package.json
├── tsconfig.json
├── .env.example
└── src/
├── index.ts # Slack command handlers
├── cli.ts # CLI mode (no Slack required)
├── contract.ts # Ethers.js contract interaction
└── config.ts # Environment configuration
| Target | Description |
|---|---|
make build |
Compile contracts |
make test |
Run test suite (in-memory EVM) |
make local-init |
Initialize local chain (one-time) |
make local-start |
Start node and explorer |
make local-stop |
Stop all local services |
make local-clean |
Remove chain data and explorer DB |
make local-deploy |
Deploy Pryntr to local devnet |
make bot-install |
Install bot dependencies |
make bot-dev |
Run bot in dev mode (requires Slack) |
make cli CMD='...' |
Run CLI (e.g. CMD='mint :fire: alice bob') |
make testnet-deploy |
Deploy Pryntr to testnet |
make testnet-verify |
Verify contract on Blockscout |
Update .env:
RPC_URL=https://k8s.testnet.json-rpc.injective.network/
PRIVATE_KEY=0x... # Testnet-funded wallet
make testnet-deploy
# Note the contract address, then:
# CONTRACT_ADDRESS=0x... make testnet-verifyUpdate the bot's .env to point RPC_URL to testnet and set the new PRYNTR_ADDRESS.