initia-appchain-dev
Initia Appchain Dev
Deliver practical guidance for full-stack Initia development: contracts, frontend integration, and appchain operations.
Command examples in this file assume the working directory is skill/; use scripts/... paths accordingly.
Intake Questions (Ask First)
Collect missing inputs before implementation:
- Which VM is required (
evm,move,wasm)? - Which network is targeted (
testnetormainnet)? - Is this a fresh rollup launch or operation/debug on an existing rollup?
- For frontend work, is this an EVM JSON-RPC app or an InterwovenKit wallet/bridge app?
- What chain-specific values are known (
chain_id, RPC URL, module address, denom)?
If critical values are missing, ask concise follow-up questions before generating final code/config.
If chain_id/endpoints/VM are missing, run the discovery flow in references/runtime-discovery.md before assuming defaults.
If weave is installed but fails with shell-level errors, continue discovery
with ~/.minitia/artifacts/config.json and direct minitiad commands instead
of blocking on weave.
Then ask a context-specific confirmation:
- Frontend task: "I found a local rollup config/runtime. Should I use this rollup for frontend integration?"
- Non-frontend task: "I found local runtime values (VM, chain ID, endpoints). Should I use these for this task?"
Environment Setup Workflow (One-Prompt Setup)
When the user asks to "set up my environment for the [Track] track" (Step 5), execute this sequence:
1. Identify Track Requirements & Prerequisites
- [MOVE] Track:
minimoverepo ->minitiad. Requiresgo. - [EVM] Track:
minievmrepo ->minitiad. Requiresgo,foundry. - [WASM] Track:
miniwasmrepo ->minitiad. Requiresgo,rust/cargo.
2. Check System Prerequisites
Check prerequisites by selected track (always check docker for tool installer compatibility):
- [MOVE] Track:
go,docker - [EVM] Track:
go,docker,foundry - [WASM] Track:
go,docker,cargo
For each required tool in the selected track:
- If missing: Inform the user and propose the installation command (e.g., "I see you're missing Cargo. Would you like me to install it for you using
rustup?"). - If present: Proceed silently.
3. Install Core Initia Tools
Run scripts/install-tools.sh to install jq, weave, and initiad (L1).
- Security: If the script requires
sudo, explain this to the user before running. - If the required tools are already present, prefer verifying versions over reinstalling. Pinned installer versions may lag behind what is already installed on the machine.
4. Build VM-Specific Binary (minitiad)
Clone, build, and clean up the relevant VM from source.
Run the build from the repository directory itself. Do not rely on shell-chained cd ... && make install examples if your execution environment manages working directories separately.
- [MOVE]:
git clone --depth 1 https://github.com/initia-labs/minimove.git /tmp/minimove cd /tmp/minimove make install rm -rf /tmp/minimove - [EVM]:
git clone --depth 1 https://github.com/initia-labs/minievm.git /tmp/minievm cd /tmp/minievm make install rm -rf /tmp/minievm - [WASM]:
git clone --depth 1 https://github.com/initia-labs/miniwasm.git /tmp/miniwasm cd /tmp/miniwasm make install rm -rf /tmp/miniwasm
5. Configure PATH
- Ensure
~/go/binis in the user'sPATH. - Check shell config files (
.zshrc,.bashrc) and suggest theexportcommand if missing. - After updating shell config, tell the user to run
source ~/.zshrc(or open a new terminal) to apply changes in their current shell. - For verification, you may run
zsh -lc 'source ~/.zshrc && <command>'in a single command; this does not persist across separate assistant commands.
6. Final Verification
Run:
weave versioninitiad versionminitiad version --long | rg '^(name|server_name|version|commit):'
Required VM match:
- [EVM] track:
name: minievm - [MOVE] track:
name: minimove - [WASM] track: verify the reported
namematches the Wasm VM you built
Do not treat a successful minitiad version command by itself as sufficient verification. The binary on PATH may still be from a different VM track.
Opinionated Defaults
| Area | Default | Notes |
|---|---|---|
| VM | evm |
Use move/wasm only when requested |
| Move Version | 2.1 |
Uses minitiad move build. Prefer omitting edition from Move.toml unless a specific compiler version requires it. |
| Network | testnet |
Use mainnet only when explicitly requested |
| Frontend (EVM VM) | wagmi + viem JSON-RPC | Default for pure EVM apps |
| Frontend (Move/Wasm) | @initia/interwovenkit-react |
Use when InterwovenKit features are required |
| Tx UX | requestTxBlock |
Prefer confirmation UX; use requestTxSync for local dev robustness. |
| Provider order | Wagmi -> Query -> InterwovenKit | Stable path for Initia SDKs |
| Rollup DA | INITIA |
Prefer Celestia only when explicitly needed |
| Keys & Keyring | gas-station / test |
Default key and --keyring-backend test for hackathon tools |
| Denoms | GAS (EVM) / umin (Move) |
Typical defaults for test/internal rollups |
Strict Constraints (NEVER VIOLATE)
Tagging Standard
- Use VM-first tags for VM-specific guidance:
[EVM],[MOVE],[WASM],[ALL-VM]. - Add optional context tags after VM:
[CLI],[DEV],[REST],[RPC],[FRONTEND],[INTERWOVENKIT],[BUILD],[TEST]. - Prefer stacked tags (example:
[EVM][CLI]) over combined tags (for example, avoid[EVM CLI]). - Required workflow for any skill markdown edit: run
scripts/lint-tags.shbefore changes and run it again before handoff.
Initia Usernames (STRICTLY OPT-IN)
- You MUST NOT implement username support in any scaffold, component, or code snippet unless explicitly requested (e.g., "add username support").
- When requested, use
useInterwovenKit().usernameonly for the connected wallet's own display name. - Pattern:
{username ? username : shortenAddress(initiaAddress)} - For resolving usernames of arbitrary wallet addresses (for example, MemoBoard sender rows), use
useUsernameQuery(address?)with the sender address; this requires@initia/interwovenkit-react2.4.6or newer. - For feeds, boards, or any rendered list of messages/accounts, resolve sender usernames inside a child row component (for example
MessageRow) and calluseUsernameQuery(address)there. Do NOT call hooks directly inside a parent component's.map()callback or conditional loop body. - Do NOT resolve via REST unless hook-based resolution is insufficient.
useUsernameQuerybehavior:- No param: resolves connected wallet address (
useAddress()fallback). - With param: resolves the provided address.
- No param: resolves connected wallet address (
Workspace Hygiene (CRITICAL)
- You MUST NOT leave temporary files or metadata JSON files (e.g.,
store_tx.json,tx.json,.bin) in the project directory after a task. - Delete binary files used for deployment before finishing.
InterwovenKit Local Appchains (CRITICAL)
- When configuring a frontend for a local appchain, you MUST use BOTH the
customChainANDcustomChains: [customChain]properties inInterwovenKitProvider. - Example Usage:
<InterwovenKitProvider {...TESTNET} customChain={customChain} customChains={[customChain]} > <App /> </InterwovenKitProvider> - Bridge Support: To ensure the bridge can resolve public chains (like
initiation-2), ALWAYS spread the{...TESTNET}preset (imported from@initia/interwovenkit-react) into theInterwovenKitProvider:<InterwovenKitProvider {...TESTNET} ... />. - Address Prefix:
customChainMUST include a top-levelbech32_prefixstring (e.g.,bech32_prefix: "init"). This is mandatory for all appchain types. - Metadata Completeness: To avoid "Chain not found" errors, the
customChainobject MUST includenetwork_type: 'testnet',staking,fees(withlow/average/high_gas_price: 0), andnative_assetsarrays. - API Requirements: The
apisobject MUST includerpc,rest, ANDindexer(use a placeholder if needed) to satisfy the kit's discovery logic. - Bridge Support (openBridge): When using
openBridge, ONLY specifysrcChainIdandsrcDenom(e.g.,initiation-2anduinit). Avoid specifying a localdstChainIdas it may cause resolution errors if the local chain is not yet indexed. - Example
customChainStructure:const customChain = { chain_id: '<INSERT_APPCHAIN_ID_HERE>', chain_name: '<INSERT_APP_NAME_HERE>', network_type: 'testnet', // MANDATORY bech32_prefix: 'init', apis: { rpc: [{ address: 'http://localhost:26657' }], rest: [{ address: 'http://localhost:1317' }], indexer: [{ address: 'http://localhost:8080' }], // MANDATORY 'json-rpc': [{ address: 'http://localhost:8545' }], }, fees: { fee_tokens: [{ denom: 'umin', fixed_min_gas_price: 0, low_gas_price: 0, average_gas_price: 0, high_gas_price: 0 }] }, staking: { staking_tokens: [{ denom: 'umin' }] }, native_assets: [{ denom: 'umin', name: 'Token', symbol: 'TKN', decimals: 6 }], metadata: { is_l1: false, minitia: { type: 'minimove' } } }
Frontend Requirements (CRITICAL)
- Placeholder Sync: Immediately after scaffolding a frontend, you MUST update all placeholders in
main.jsx(like<INSERT_APPCHAIN_ID_HERE>,<INSERT_NATIVE_DENOM_HERE>, etc.) with the actual values discovered during the Research phase (e.g.,bank-1,GAS,minievm). - Runtime Config Sync: If the frontend depends on a deployed contract address, you MUST wire the resolved live address into runtime config (for example,
.env/VITE_*) instead of leaving only placeholders or examples. If.envvalues are added or changed for a running Vite app, tell the user to restart the dev server. - Hook Exports:
useInterwovenKitexportsinitiaAddress,address,username,openConnect,openWallet,openBridge,requestTxBlock,requestTxSync, andautoSign. - Transaction Guards: Before calling
requestTxBlockorrequestTxSync, you MUST verify thatinitiaAddressis defined. - [ALL-VM] Sender Address: In Initia, the
senderfield for all message types (MsgCall,MsgExecute,MsgExecuteContract) MUST be the Bech32 address. UseinitiaAddressfor this field to ensure compatibility across EVM, Move, and Wasm appchains. Using the hexaddresson an EVM chain for thesenderfield in a Cosmos-style message will cause an "empty address string" or "decoding bech32 failed" error.
Security & Key Protection (STRICTLY ENFORCED)
- You MUST NOT export raw private keys from the keyring.
- [MOVE][DEV] Development (Building for Publish): Before publishing, you MUST rebuild the module using the intended deployer's Hex address:
minitiad move build --named-addresses <name>=0x<hex_addr>. - [MOVE][DEV][BUILD] Named Address Reassignment: If
[addresses].<name>inMove.tomlis hardcoded (for example0x42) and you pass a different--named-addresses <name>=0x..., compilation fails with a named-address reassignment error. Prefer"<name>" = "_"in[addresses]and keep local test defaults in[dev-addresses]. - [MOVE][DEV] Dependency Resolution: If
InitiaStdlibfails to resolve, use:{ git = "https://github.com/initia-labs/movevm.git", subdir = "precompile/modules/initia_stdlib", rev = "main" }. - [MOVE][DEV] Package Scaffolding:
minitiad move new <NAME>can write the package into the current working directory instead of creating a sibling directory. If the user wants a specific folder such asblockforge/, create and enter that folder first before runningminitiad move new. - [MOVE][DEV] Clean (Non-Interactive Shells):
minitiad move cleanmay prompt for confirmation and panic without a TTY. In automated workflows, remove the packagebuild/directory directly if a clean rebuild is required. - [MOVE][CLI] Deploy Semantics: Move modules do not have a separate instantiate transaction. "Instantiation" is typically the first state-changing entry call (for example, creating per-player resources on first
mint_shard). - [EVM][CLI] Deployment: For EVM deployment, use
minitiad tx evm createwith--from. - [EVM][CLI] Bytecode Extraction: Extract bytecode from Foundry artifacts using
jq; ensure NO0xprefix and NO trailing newlines in.binfiles. - [EVM][DEV][CLI]
tx evm createInput Shape: The positional argument tominitiad tx evm createis a bytecode file path. If you want to pass raw bytecode directly, use--input 0x.... Passing raw hex as the positional argument can fail withfile name too long. - [ALL-VM][SECURITY] Private Key Handling: If a tool requires a private key, find an alternative workflow using Initia CLI or
InterwovenKit.
Frontend Requirements (ADDITIONAL)
- Polyfills: Use
vite-plugin-node-polyfillsinvite.config.jswithglobals: { Buffer: true, process: true }. Also setresolve.dedupeto['react', 'react-dom', 'wagmi', '@tanstack/react-query', 'viem']to avoid provider context splits in Vite. If using manual polyfills, defineBufferandprocessglobal polyfills at the TOP ofmain.jsx.import { Buffer } from "buffer"; window.Buffer = Buffer; window.process = { env: {} }; - Styles:
- Import the CSS:
import "@initia/interwovenkit-react/styles.css". - Import the style data:
import InterwovenKitStyles from "@initia/interwovenkit-react/styles.js". - Import the injector function:
import { injectStyles } from "@initia/interwovenkit-react". - Inject them:
injectStyles(InterwovenKitStyles). - Note:
InterwovenKitStylesis a DEFAULT export from the styles subpath, whileinjectStylesis a NAMED export from the main package.
- Import the CSS:
- Provider Order:
WagmiProvider->QueryClientProvider->InterwovenKitProvider. - Wallet Modal:
- Use
openConnect(notopenModal) to open the connection modal (v2.4.0+). - Connected State (CRITICAL): When
initiaAddressis present, ALWAYS provide a clickable UI element (e.g., a button with a shortened address) that callsopenWalletto allow the user to manage their connection or disconnect.
- Use
- Auto-Sign Implementation (STRICTLY OPT-IN):
- You MUST NOT implement auto-sign support in any scaffold, provider, or component unless explicitly requested (e.g., "add auto-sign support").
- When requested:
- Provider: Pass
enableAutoSign={true}toInterwovenKitProvider. - Hook: Destructure the
autoSignobject (not functions) fromuseInterwovenKit. - Safety: Use optional chaining (
autoSign?.) and check status viaautoSign?.isEnabledByChain[chainId]. - Actions:
await autoSign?.enable(chainId)andawait autoSign?.disable(chainId)are asynchronous. - Permissions (CRITICAL): To ensure the session key can sign specific message types, ALWAYS include explicit permissions in
autoSign.enable:await autoSign.enable(chainId, { permissions: ["/initia.move.v1.MsgExecute"] }) - Error Handling: If
autoSign.disablefails with "authorization not found", handle it by callingautoSign.enablewith the required permissions to reset the session.
- Provider: Pass
- REST Client: Instantiate
RESTClientfrom@initia/initia.jsmanually; it is NOT exported from the hook.- CRITICAL: Do NOT attempt to destructure
networksorrestfromuseInterwovenKit. These objects are NOT available in the hook. Always define your REST/RPC endpoints manually or via your own configuration.
- CRITICAL: Do NOT attempt to destructure
Transaction Message Flow (CRITICAL)
- [WASM][INTERWOVENKIT] Transaction Envelope: ALWAYS include
chainId. PreferrequestTxSync.- [WASM][INTERWOVENKIT] Payload Encoding:
MsgExecuteContractexpects themsgfield as bytes (Uint8Array). Usenew TextEncoder().encode(JSON.stringify(msg)).
- [WASM][INTERWOVENKIT] Payload Encoding:
- [ALL-VM][INTERWOVENKIT] Auto-Sign (Headless): To ensure auto-signed transactions are "headless" (no fee selection prompt), ALWAYS include an explicit
feeDenom(e.g.,feeDenom: "umin") AND theautoSign: trueflag in the request:await requestTxSync({ chainId, autoSign: true, // CRITICAL: Required for silent signing flow messages: [...] }) - [EVM] Sender (MsgCall): Use bech32 address for
senderinMsgCall, but hex forcontractAddr.- Normalization: ALWAYS lowercase the bech32 sender address to avoid "decoding bech32 failed" errors.
- [EVM][INTERWOVENKIT] Payload: Use plain objects with
typeUrl: "/minievm.evm.v1.MsgCall". The actual message fields MUST be wrapped inside avaluekey.- Incorrect:
{ typeUrl: "...", sender: "...", contractAddr: "..." } - Correct:
{ typeUrl: "...", value: { sender: "...", contractAddr: "...", ... } }
- Incorrect:
- [EVM][INTERWOVENKIT]
requestTxBlockKey: ALWAYS usemessages(plural), notmsgs. Passingmsgscan fail withCannot read properties of undefined (reading 'map'). - [EVM] Field Naming: Use camelCase for fields (
contractAddr,accessList,authList) and include empty arrays for lists. - [MOVE][INTERWOVENKIT] MsgExecute Field Naming: Use camelCase for fields;
moduleAddressMUST be bech32.- [MOVE][INTERWOVENKIT] Mandatory Arrays: ALWAYS include
typeArgs: []andargs: []even if they are empty. Omitting these fields in a Move execution message will cause aTypeError(Cannot read properties of undefined reading 'length') during the Amino conversion process in the frontend.
- [MOVE][INTERWOVENKIT] Mandatory Arrays: ALWAYS include
Wasm REST Queries (CRITICAL)
- [WASM][REST] Query Encoding: When querying Wasm contract state using the
RESTClient(e.g.,rest.wasm.smartContractState), the query message MUST be a Base64-encoded string. - The query JSON and execute JSON MUST match the contract's Rust message schema exactly. Do NOT assume names like
all_messagesor specific field names such astextormessage; for example, MemoBoard variants commonly useget_messageswithpost_message: { message: ... }, while other contracts may use different field names. - Example Implementation:
const queryData = Buffer.from(JSON.stringify({ get_messages: {} })).toString("base64"); const res = await rest.wasm.smartContractState(CONTRACT_ADDR, queryData); - [WASM][REST] Response Shape:
smartContractStatecommonly returns the decoded payload directly (for exampleres.messages) rather than nesting it underres.data. Do not assume a.datawrapper unless you have verified the concrete response shape. - [WASM][REST] Method Name: ALWAYS use
smartContractState. Methods likequeryContractSmartare NOT available in the InitiaRESTClient. - [WASM][CLI] Fallback: If
minitiad query wasm contract-state smart <CONTRACT_ADDRESS> ...fails with a Bech32 checksum error even though the address came from the instantiate event orlist-contract-by-code, treat the chain-emitted address as the source of truth. Verify it withminitiad query wasm list-contract-by-code <CODE_ID>and continue with the REST endpoint path orRESTClientinstead of blocking on the CLI parser.
Wasm Rust Testing (CRITICAL)
- [WASM][TEST] Address Comparison: When writing unit tests for Wasm contracts, ALWAYS use
.as_str()when comparingcosmwasm_std::Addrwith a string literal orString.Addrdoes NOT implementPartialEq<&str>orPartialEq<String>directly. - Incorrect:
assert_eq!("user1", value.sender); - Correct:
assert_eq!("user1", value.sender.as_str());
Token Precision & Funding (EVM SPECIFIC)
- [EVM] Precision: Assume standard EVM precision ($10^{18}$ base units) for all native tokens on EVM appchains (e.g.,
GAS). - [EVM] Funding Requests: When a user asks for "N tokens" on an EVM chain:
- Frontend: Multiply by $10^{18}$ (e.g.,
parseUnits(amount, 18)). - CLI: You MUST manually scale the value. For "100 tokens", use
100000000000000000000GAS(100 + 18 zeros) in thebank sendcommand.
- Frontend: Multiply by $10^{18}$ (e.g.,
- [EVM][FRONTEND] Human-Readable UI: ALWAYS use
formatUnits(balance, 18)fromviemto display EVM balances. NEVER display raw base units in the UI. - [EVM][FRONTEND][DEV]
parseEther/formatEtherUsage:parseEtherandformatEtherare valid shorthand ONLY when the chain token uses exactly 18 decimals. If decimals might vary, useparseUnits(amount, decimals)andformatUnits(balance, decimals)from runtime config.
EVM Queries & Transactions (CRITICAL)
- [EVM][FRONTEND] ABI Sync: Treat compiled ABI/function names as the source of truth. Do NOT assume names like
getMyBalance; confirm names/signatures from the generated artifact (for exampleout/<Contract>.sol/<Contract>.json) before wiring frontendencodeFunctionDatacalls. - [EVM][RPC] State Queries: Prefer standard JSON-RPC
eth_calloverRESTClientfor EVM state queries to avoid property-undefined errors. - [EVM][FRONTEND][RPC] Read Path Provider: For read-only EVM queries (
eth_call), use a configured JSON-RPC endpoint (for exampleVITE_JSON_RPC_URL) instead of relying on injected wallet providers (window.ethereum). This avoids "EVM wallet provider not found" failures when no EVM extension is injected. - [EVM][RPC] Address Conversion: When querying EVM state (e.g.,
eth_call), ALWAYS convert the bech32 address to hex usingAccAddress.toHex(addr)and ensure the hex address is lowercased. - [EVM][CLI] Sender Format:
minitiad query evm callexpects a bech32 sender (init1...) as the first argument. - [EVM][CLI] Query Output Field:
minitiad query evm call -o jsonreturns the call result under.response(hex string). - [EVM][CLI] Tx Lookup Timing: Immediately after broadcast,
minitiad query tx <hash>may briefly returntx not found; retry briefly before failing. - [EVM][CLI] Calldata Encoding:
- [EVM][FRONTEND] Preferred: Prefer
viem(e.g.,encodeFunctionData) for generating contractinputhex. - [EVM][CLI] Preferred: ALWAYS use
cast calldata(e.g.,$(cast calldata "func(type)" arg)) for generating contractinputhex. Manual encoding (e.g.,printf) is brittle and MUST be avoided. - [EVM][CLI] Manual Padding: If manual encoding is unavoidable, ensure
BigIntvalues are converted to hex and padded to exactly 64 characters foruint256arguments.
- [EVM][FRONTEND] Preferred: Prefer
Move REST Queries (CRITICAL)
- [MOVE][REST] Module Address Format: When querying Move contract state using the
RESTClient(e.g.,rest.move.view), the module address MUST be in bech32 format. - [MOVE][REST] Struct Tag Address Format: When querying Move resources using
rest.move.resource, the resource owner remains bech32, but the struct tag module address MUST be hex (0x...::module::Struct). Do NOT build a struct tag with a bech32 module address. - [MOVE][REST] Address Arguments: Address arguments in
argsMUST be converted to hex, stripped of0x, padded to 64 chars (32 bytes), and then Base64-encoded. - Example Implementation:
const b64Addr = Buffer.from( AccAddress.toHex(addr).replace('0x', '').padStart(64, '0'), 'hex' ).toString('base64'); const res = await rest.move.view(mod_bech32, mod_name, func_name, [], [b64Addr]); - Resource Query Example:
const structTag = `${AccAddress.toHex(moduleBech32)}::items::Inventory`; const res = await rest.move.resource(walletBech32, structTag); - [MOVE][REST] Response Parsing: The response from
rest.move.viewis aViewResponseobject; you MUST parseJSON.parse(res.data)to access the actual values. - [MOVE][REST] Missing Resource Handling: For first-use state such as inventories, a resource may not exist yet. Treat a "not found" response from
rest.move.resourceas a valid zero/default state instead of surfacing it as a hard failure. - [MOVE][REST] Troubleshooting (400 Bad Request): If
rest.move.viewreturns a 400 error, it is almost ALWAYS because:- The module address is not bech32.
- The address arguments in
argsare not correctly hex-padded-base64 encoded.
- [MOVE][INTERWOVENKIT] Auto-Sign (No message types configured): If
autoSign.enablefails with "No message types configured", ensure:metadata.minitia.typeis set correctly (e.g.,minimove,minievm).defaultChainIdinInterwovenKitProvidermatches yourcustomChain.chain_id.bech32_prefixis present at the top level ofcustomChain.
Operating Procedure (How To Execute Tasks)
- Classify Layer: Contract, Frontend, Appchain Ops, or Integration.
- Environment Check: Verify tools (
cargo,forge,minitiad) are in PATH. Use absolute paths if needed. - Workspace Awareness: Check for existing
Move.tomlorpackage.jsonbefore scaffolding. Use provided scripts for non-interactive scaffolding. - Pre-Deployment Checklist (CLI): Before deploying contracts or sending tokens via CLI, verify the actual environment (set
RPC_ENDPOINTfrom runtime discovery):- Chain ID:
curl -s "${RPC_ENDPOINT}/status" | jq -r '.result.node_info.network' - Native Denom:
minitiad q bank total --node "${RPC_ENDPOINT}" - Balance: Ensure the
fromaccount has enough of the actual native denom.
- Chain ID:
- Scaffolding Cleanup: Delete placeholder modules/contracts after scaffolding.
- Appchain Health: If RPC is down, attempt
weave rollup start -dand verify withscripts/verify-appchain.sh. - [MOVE][DEV] Acquires Annotation: Every function that accesses global storage (using
borrow_global,borrow_global_mut,move_from, or calling a function that does) MUST include theacquiresannotation for that resource type. - [MOVE][DEV] Reference Rules: You MUST NOT return a reference (mutable or immutable) derived from a global resource (e.g., via
borrow_global_mut) from a function unless it is passed as a parameter. Inline the logic or pass the resource as a parameter if needed. - [MOVE][DEV] Syntax: Place doc comments (
///) AFTER attributes like#[view]or#[test]. - [MOVE][CLI] Publish: The
minitiad tx move publishcommand does NOT use a--pathflag. Pass the path to the compiled.mvfile as a positional argument:minitiad tx move publish <path_to_file>.mv .... - [MOVE][DEV][CLI] Republish Compatibility: If republishing from the same account fails with
BACKWARD_INCOMPATIBLE_MODULE_UPDATE, preserve existing public APIs (for example, keep prior public entry/view functions as compatibility wrappers) or rename the module before publishing. - [ALL-VM][CLI] Broadcast Mode Compatibility: In current Initia CLIs, broadcast mode supports
sync|async; do not assumeblockis available. - [MOVE][CLI] Tx Lookup Timing: Immediately after
minitiadbroadcast,minitiad query tx <hash>may briefly returntx not found; poll/retry before treating it as failed. - [WASM][BUILD] Optimization: ALWAYS use the CosmWasm optimizer Docker image for production-ready binaries.
- Visual Polish: Prioritize sticky glassmorphism headers, centered app-card layouts, and clear visual hierarchy.
- UX Excellence: Feed ordering (newest first), input accessibility (above feed), and interactive feedback (hover/focus).
- [ALL-VM][INTERWOVENKIT] Bridge Support: Use
openBridgefromuseInterwovenKit. DefaultsrcChainIdto a public testnet (e.g.,initiation-2) for local demos. - Validation: Run
scripts/verify-appchain.sh --gas-station --botsand confirm transaction success before handoff.
Progressive Disclosure (Read When Needed)
- Common Tasks (Funding, Addresses, Precision):
references/common-tasks.md - Contracts (Move/Wasm/EVM):
references/contracts.md - Frontend (InterwovenKit):
references/frontend-interwovenkit.md - Frontend (EVM JSON-RPC):
references/frontend-evm-rpc.md - End-to-End Recipes:
references/e2e-recipes.md - Runtime Discovery:
references/runtime-discovery.md - Weave CLI Reference:
references/weave-commands.md - Rollup Config Schema:
references/weave-config-schema.md - Troubleshooting & Recovery:
references/troubleshooting.md
Documentation Fallback
- Core docs:
https://docs.initia.xyz - InterwovenKit docs:
https://docs.initia.xyz/interwovenkit
Script Usage
- Scaffolding:
scripts/scaffold-contract.sh,scripts/scaffold-frontend.sh - Health:
scripts/verify-appchain.sh - Utils:
scripts/convert-address.py,scripts/to_hex.py,scripts/generate-system-keys.py - Setup:
scripts/install-tools.sh,scripts/fund-user.sh
Expected Deliverables
- Exact files changed.
- Commands for setup/build/test.
- Verification steps and outputs.
- Risk notes (security, keys, fees).