重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/initia-labs/agent-skills --skill initia-appchain-dev提供全栈 Initia 开发的实用指南:合约、前端集成和应用链操作。
本文档中的命令示例假设工作目录为 skill/;请相应地使用 scripts/... 路径。
在实施前收集缺失的输入:
evm, move, wasm)?testnet 还是 mainnet)?chain_id、RPC URL、已部署合约地址、denom)?广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
如果缺少关键值,请在生成最终代码/配置前提出简洁的后续问题。
如果缺少 chain_id/端点/虚拟机信息,请在假设默认值之前运行 references/runtime-discovery.md 中的发现流程。
如果安装了 weave 但出现 shell 级别错误,请使用 ~/.minitia/artifacts/config.json 和直接的 minitiad 命令继续发现,而不是因 weave 而阻塞。
然后询问一个特定于上下文的确认:
当用户要求"为 [Track] 赛道设置我的环境"(步骤 5)时,执行以下序列:
minimove 仓库 -> minitiad。需要 go。minievm 仓库 -> minitiad。需要 go, foundry。miniwasm 仓库 -> minitiad。需要 go, rust/cargo。根据所选赛道检查先决条件(始终检查 docker 以兼容工具安装器):
go, dockergo, docker, foundrygo, docker, cargo对于所选赛道中的每个必需工具:
rustup 为您安装它吗?")。运行 scripts/install-tools.sh 以安装 jq、weave 和 initiad(L1)。
sudo,请在运行前向用户解释。minitiad)克隆、构建并清理相关的虚拟机源代码。
从仓库目录本身运行构建。如果您的执行环境单独管理工作目录,请不要依赖 shell 链式 cd ... && make install 示例。
[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
~/go/bin 在用户的 PATH 中。.zshrc, .bashrc),如果缺失则建议 export 命令。source ~/.zshrc(或打开新终端)以在当前 shell 中应用更改。zsh -lc 'source ~/.zshrc && <command>';这不会在单独的助手命令之间持久化。运行:
weave versioninitiad versionminitiad version --long | rg '^(name|server_name|version|commit):'所需的虚拟机匹配:
name: minievmname: minimovename 与您构建的 Wasm 虚拟机匹配不要将成功的 minitiad version 命令本身视为足够的验证。PATH 上的二进制文件可能仍来自不同的虚拟机赛道。
| 领域 | 默认值 | 备注 |
|---|---|---|
| 虚拟机 | evm | 仅在请求时使用 move/wasm |
| Move 版本 | 2.1 | 使用 minitiad move build。除非特定编译器版本要求,否则优先省略 Move.toml 中的 edition。 |
| 网络 | testnet | 仅在明确请求时使用 mainnet |
| 前端 (EVM 虚拟机) | wagmi + viem JSON-RPC | 纯 EVM 应用的默认选择 |
| 前端 (Move/Wasm) | @initia/interwovenkit-react | 需要 InterwovenKit 功能时使用 |
| 交易用户体验 | requestTxBlock | 优先确认用户体验;本地开发鲁棒性使用 requestTxSync。 |
| 提供者顺序 | Wagmi -> Query -> InterwovenKit | Initia SDK 的稳定路径 |
| Rollup 数据可用性 | INITIA | 仅在明确需要时优先使用 Celestia |
| 密钥和钥匙环 | gas-station / test | 黑客松工具的默认密钥和 --keyring-backend test |
| Denoms | GAS (EVM) / umin (Move) | 测试/内部 Rollup 的典型默认值 |
[EVM]、[MOVE]、[WASM]、[ALL-VM]。[CLI]、[DEV]、[REST]、[RPC]、[FRONTEND]、[INTERWOVENKIT]、[BUILD]、[TEST]。[EVM][CLI])而非组合标签(例如,避免 [EVM CLI])。scripts/lint-tags.sh,并在交付前再次运行。useInterwovenKit().username 用于已连接钱包自身的显示名称。{username ? username : shortenAddress(initiaAddress)}useUsernameQuery(address?) 并传入发送者地址;这需要 @initia/interwovenkit-react 2.4.6 或更高版本。MessageRow)内解析发送者用户名,并在那里调用 useUsernameQuery(address)。不要在父组件的 .map() 回调或条件循环体内直接调用钩子。useUsernameQuery 行为:
useAddress() 回退)。store_tx.json、tx.json、.bin)。为本地应用链配置前端时,您必须在 InterwovenKitProvider 中同时使用 customChain 和 customChains: [customChain] 属性。
示例用法:
<InterwovenKitProvider
{...TESTNET}
customChain={customChain}
customChains={[customChain]}
>
<App />
</InterwovenKitProvider>
桥接支持:为确保桥接可以解析公共链(如 initiation-2),始终将 {...TESTNET} 预设(从 @initia/interwovenkit-react 导入)展开到 InterwovenKitProvider 中:<InterwovenKitProvider {...TESTNET} ... />。
地址前缀:customChain 必须包含顶层的 bech32_prefix 字符串(例如 bech32_prefix: "init")。这对所有应用链类型都是强制性的。
元数据完整性:为避免"链未找到"错误,customChain 对象必须包含 network_type: 'testnet'、staking、fees(带有 low/average/high_gas_price: 0)和 native_assets 数组。
API 要求:apis 对象必须包含 rpc、rest 和 indexer(如果需要,使用占位符)以满足套件的发现逻辑。
桥接支持 (openBridge):当使用 openBridge 时,仅指定 srcChainId 和 srcDenom(例如 initiation-2 和 uinit)。避免指定本地的 dstChainId,因为如果本地链尚未被索引,可能会导致解析错误。
示例 customChain 结构:
const customChain = {
chain_id: '<INSERT_APPCHAIN_ID_HERE>',
chain_name: '<INSERT_APP_NAME_HERE>',
network_type: 'testnet', // 强制
bech32_prefix: 'init',
apis: {
rpc: [{ address: 'http://localhost:26657' }],
rest: [{ address: 'http://localhost:1317' }],
indexer: [{ address: 'http://localhost:8080' }], // 强制
'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' } }
}
bank-1、GAS、minievm)更新 main.jsx 中的所有占位符(如 <INSERT_APPCHAIN_ID_HERE>、<INSERT_NATIVE_DENOM_HERE> 等)。.env / VITE_*)中,而不是只留下占位符或示例。对于 Move 特定的 API 和代码,在区分重要时保留术语 module address。如果为正在运行的 Vite 应用添加或更改了 .env 值,请告诉用户重启开发服务器。useInterwovenKit 导出 initiaAddress、address、username、openConnect、openWallet、openBridge、requestTxBlock、requestTxSync 和 autoSign。requestTxBlock 或 requestTxSync 之前,您必须验证 initiaAddress 已定义。MsgCall、MsgExecute、MsgExecuteContract)的 sender 字段必须是 Bech32 地址。为此字段使用 initiaAddress 以确保跨 EVM、Move 和 Wasm 应用链的兼容性。在 Cosmos 风格的消息中为 sender 字段使用十六进制的 address 将导致"空地址字符串"或"解码 bech32 失败"错误。minitiad move build --named-addresses <name>=0x<hex_addr>。Move.toml 中的 [addresses].<name> 是硬编码的(例如 0x42)并且您传递了不同的 --named-addresses <name>=0x...,编译将因命名地址重新分配错误而失败。优先在 [addresses] 中使用 "<name>" = "_",并将本地测试默认值保留在 [dev-addresses] 中。InitiaStdlib 解析失败,请使用:{ git = "https://github.com/initia-labs/movevm.git", subdir = "precompile/modules/initia_stdlib", rev = "main" }。minitiad move new <NAME> 可以将包写入当前工作目录,而不是创建同级目录。如果用户想要特定文件夹,例如 blockforge/,请先创建并进入该文件夹,然后再运行 minitiad move new。minitiad move clean 可能会提示确认,并在没有 TTY 时崩溃。在自动化工作流中,如果需要干净的重新构建,请直接删除包 build/ 目录。mint_shard 时为每个玩家创建资源)。minitiad tx evm create 并带上 --from。jq 从 Foundry 工件中提取字节码;确保 .bin 文件中没有 0x 前缀和没有尾随换行符。tx evm create 输入形状:minitiad tx evm create 的位置参数是字节码文件路径。如果您想直接传递原始字节码,请使用 --input 0x...。将原始十六进制作为位置参数传递可能会因文件名过长而失败。InterwovenKit 寻找替代工作流。Polyfills:在 vite.config.js 中使用 vite-plugin-node-polyfills,并设置 globals: { Buffer: true, process: true }。同时设置 resolve.dedupe 为 ['react', 'react-dom', 'wagmi', '@tanstack/react-query', 'viem'] 以避免 Vite 中的提供者上下文分裂。如果使用手动 polyfills,请在 main.jsx 的顶部定义 Buffer 和 process 全局 polyfills。
import { Buffer } from "buffer";
window.Buffer = Buffer;
window.process = { env: {} };
样式:
import "@initia/interwovenkit-react/styles.css"。import InterwovenKitStyles from "@initia/interwovenkit-react/styles.js"。import { injectStyles } from "@initia/interwovenkit-react"。injectStyles(InterwovenKitStyles)。InterwovenKitStyles 是样式子路径的默认导出,而 injectStyles 是主包的命名导出。提供者顺序:WagmiProvider -> QueryClientProvider -> InterwovenKitProvider。
钱包模态框:
openConnect(不是 openModal)来打开连接模态框(v2.4.0+)。initiaAddress 存在时,始终提供一个可点击的 UI 元素(例如,带有缩短地址的按钮),该元素调用 openWallet 以允许用户管理其连接或断开连接。自动签名实现(严格选择加入):
提供者:向 InterwovenKitProvider 传递 enableAutoSign={true}。
钩子:从 useInterwovenKit 中解构 autoSign 对象(不是函数)。
安全性:使用可选链(autoSign?.)并通过 autoSign?.isEnabledByChain[chainId] 检查状态。
操作:await autoSign?.enable(chainId) 和 是异步的。
REST 客户端:手动实例化 @initia/initia.js 中的 RESTClient;它不是从钩子导出的。
useInterwovenKit 解构 networks 或 rest。这些对象在钩子中不可用。始终通过您自己的配置手动定义您的 REST/RPC 端点。[WASM][INTERWOVENKIT] 交易信封:始终包含 chainId。优先使用 requestTxSync。
MsgExecuteContract 期望 msg 字段为字节(Uint8Array)。使用 new TextEncoder().encode(JSON.stringify(msg))。[ALL-VM][INTERWOVENKIT] 自动签名(无头):为确保自动签名的交易是"无头的"(无费用选择提示),始终在请求中包含明确的 feeDenom(例如 feeDenom: "umin")和 autoSign: true 标志:
await requestTxSync({
chainId,
autoSign: true, // 关键:静默签名流程所需
messages: [...]
})
[EVM] 发送者 (MsgCall):为 MsgCall 中的 sender 使用 bech32 地址,但为 contractAddr 使用 十六进制。
[EVM][INTERWOVENKIT] 负载:使用带有 typeUrl: "/minievm.evm.v1.MsgCall" 的普通对象。实际的消息字段必须包装在 value 键内。
{ typeUrl: "...", sender: "...", contractAddr: "..." }{ typeUrl: "...", value: { sender: "...", contractAddr: "...", ... } }[EVM][INTERWOVENKIT] requestTxBlock 键:始终使用 messages(复数),而不是 msgs。传递 msgs 可能会因 Cannot read properties of undefined (reading 'map') 而失败。
[EVM] 字段命名:为字段使用 camelCase(contractAddr、accessList、authList)并为列表包含空数组。
[MOVE][INTERWOVENKIT] MsgExecute 字段命名:为字段使用 camelCase;moduleAddress 必须是 bech32。
typeArgs: [] 和 args: [],即使它们是空的。在 Move 执行消息中省略这些字段将导致前端 Amino 转换过程中出现 TypeError(无法读取未定义的属性 'length')。[WASM][REST] 查询编码:当使用 RESTClient 查询 Wasm 合约状态时(例如 rest.wasm.smartContractState),查询消息必须是 Base64 编码的字符串。
查询 JSON 和执行 JSON 必须与合约的 Rust 消息模式完全匹配。不要假设名称如 all_messages 或特定字段名称如 text 或 message;例如,MemoBoard 变体通常使用 get_messages 和 post_message: { message: ... },而其他合约可能使用不同的字段名称。
示例实现:
const queryData = Buffer.from(JSON.stringify({ get_messages: {} })).toString("base64");
const res = await rest.wasm.smartContractState(CONTRACT_ADDR, queryData);
[WASM][REST] 响应形状:smartContractState 通常直接返回解码后的负载(例如 res.messages),而不是将其嵌套在 res.data 下。除非您已验证具体响应形状,否则不要假设存在 .data 包装器。
[WASM][REST] 方法名称:始终使用 smartContractState。queryContractSmart 等方法在 Initia RESTClient 中不可用。
[WASM][CLI] 回退:如果 minitiad query wasm contract-state smart <CONTRACT_ADDRESS> ... 因 Bech32 校验和错误而失败,即使地址来自实例化事件或 list-contract-by-code,也应将链发出的地址视为真实来源。使用 minitiad query wasm list-contract-by-code <CODE_ID> 进行验证,并继续使用 REST 端点路径或 RESTClient,而不是阻塞在 CLI 解析器上。
cosmwasm_std::Addr 与字符串字面量或 String 比较时,始终使用 .as_str()。Addr 不直接实现 PartialEq<&str> 或 PartialEq<String>。assert_eq!("user1", value.sender);assert_eq!("user1", value.sender.as_str());GAS)。parseUnits(amount, 18))。bank send 命令中使用 100000000000000000000GAS(100 + 18 个零)。viem 的 formatUnits(balance, 18) 来显示 EVM 余额。切勿在 UI 中显示原始基础单位。parseEther / formatEther 用法:parseEther 和 formatEther 仅当链代币恰好使用 18 位小数时才有效。如果小数位数可能变化,请使用运行时配置中的 parseUnits(amount, decimals) 和 formatUnits(balance, decimals)。getMyBalance;在连接前端 encodeFunctionData 调用之前,从生成的工件(例如 out/<Contract>.sol/<Contract>.json)确认名称/签名。eth_call 而非 RESTClient,以避免属性未定义错误。eth_call),使用配置的 JSON-RPC 端点(例如 VITE_JSON_RPC_URL),而不是依赖注入的钱包提供者(window.ethereum)。这可以避免在没有注入 EVM 扩展时出现"EVM 钱包提供者未找到"的失败。eth_call),始终使用 AccAddress.toHex(addr) 将 bech32 地址转换为十六进制,并确保十六进制地址是小写的。minitiad query evm call 期望第一个参数是 bech32 发送者(init1...)。minitiad query evm call -o json 在 .response 下返回调用结果(十六进制字符串)。minitiad query tx <hash> 可能短暂返回 tx not found;在判定失败前稍作重试。viem(例如 encodeFunctionData)生成合约 input 十六进制。cast calldata(例如 $(cast calldata "func(type)" arg))生成合约 input 十六进制。手动编码(例如 printf)是脆弱的,必须避免。BigInt 值转换为十六进制,并为 uint256 参数填充到恰好 64 个字符。[MOVE][REST] 模块地址格式:使用 RESTClient 查询 Move 合约状态时(例如 rest.move.view),模块地址必须是 bech32 格式。
[MOVE][REST] 结构体标签地址格式:使用 rest.move.resource 查询 Move 资源时,资源所有者保持 bech32,但结构体标签模块地址必须是十六进制(0x...::module::Struct)。不要使用 bech32 模块地址构建结构体标签。
[MOVE][REST] 地址参数:args 中的地址参数必须转换为十六进制,去除 0x,填充到 64 个字符(32 字节),然后进行 Base64 编码。
示例实现:
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]);
资源查询示例:
const structTag = `${AccAddress.toHex(moduleBech32)}::items::Inventory`;
const res = await rest.move.resource(walletBech32, structTag);
[MOVE][REST] 响应解析:来自 rest.move.view 的响应是一个 ViewResponse 对象;您必须解析 JSON.parse(res.data) 以访问实际值。
[MOVE][REST] 缺失资源处理:对于首次使用的状态,例如库存,资源可能尚不存在。将 rest.move.resource 的"未找到"响应视为有效的零/默认状态,而不是将其作为硬性故障呈现。
[MOVE][REST] 故障排除(400 错误请求):如果 rest.move.view 返回 400 错误,几乎总是因为:
args 中的地址参数未正确进行十六进制填充-base64 编码。[MOVE][INTERWOVENKIT] 自动签名(未配置消息类型):如果 autoSign.enable 因"未配置消息类型"而失败,请确保:
metadata.minitia.type 设置正确(例如 minimove、minievm)。InterwovenKitProvider 中的 defaultChainId 与您的 customChain.chain_id 匹配。bech32_prefix 存在于 customChain 的顶层。cargo、forge、minitiad)是否在 PATH 中。如果需要,使用绝对路径。Move.toml 或 package.json。对于非交互式脚手架,使用提供的脚本。RPC_ENDPOINT):
curl -s "${RPC_ENDPOINT}/status" | jq -r '.result.node_info.network'minitiad q bank total --node "${RPC_ENDPOINT}"from 账户拥有足够的实际原生 denom。weave rollup start -d 并使用 scripts/verify-appchain.sh 验证。borrow_global、borrow_global_mut、move_from 或调用执行此操作的函数)必须包含该资源类型的 acquires 注解。borrow_global_mut),除非它作为参数传递。如果需要,内联逻辑或将资源作为参数传递。///)放在属性(如 #[view] 或 #[test])之后。minitiad tx move publish 命令不使用 --path 标志。将已编译的 .mv 文件的路径作为位置参数传递:minitiad tx move publish <path_to_file>.mv ...。BACKWARD_INCOMPATIBLE_MODULE_UPDATE 而失败,请保留现有的公共 API(例如,将先前的公共入口/视图函数保留为兼容性包装器),或在发布前重命名模块。sync|async;不要假设 block 可用。minitiad 广播后立即,minitiad query tx <hash> 可能短暂返回 tx not found;在视为失败前轮询/重试。useInterwovenKit 中的 openBridge。对于本地演示,默认 srcChainId 为公共测试网(例如 initiation-2)。scripts/verify-appchain.sh --gas-station --bots 并在交付前确认交易成功。references/common-tasks.mdreferences/contracts.mdreferences/frontend-interwovenkit.mdDeliver 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.
Collect missing inputs before implementation:
evm, move, wasm)?testnet or mainnet)?chain_id, RPC URL, deployed contract 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:
When the user asks to "set up my environment for the [Track] track" (Step 5), execute this sequence:
minimove repo -> minitiad. Requires go.minievm repo -> minitiad. Requires go, foundry.miniwasm repo -> minitiad. Requires go, rust/cargo.Check prerequisites by selected track (always check docker for tool installer compatibility):
go, dockergo, docker, foundrygo, docker, cargoFor each required tool in the selected track:
rustup?").Run scripts/install-tools.sh to install jq, weave, and initiad (L1).
sudo, explain this to the user before running.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
~/go/bin is in the user's PATH..zshrc, .bashrc) and suggest the export command if missing.source ~/.zshrc (or open a new terminal) to apply changes in their current shell.zsh -lc 'source ~/.zshrc && <command>' in a single command; this does not persist across separate assistant commands.Run:
weave versioninitiad versionminitiad version --long | rg '^(name|server_name|version|commit):'Required VM match:
name: minievmname: minimovename matches the Wasm VM you builtDo not treat a successful minitiad version command by itself as sufficient verification. The binary on PATH may still be from a different VM track.
| 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 |
[EVM], [MOVE], [WASM], [ALL-VM].[CLI], [DEV], [REST], [RPC], [FRONTEND], [INTERWOVENKIT], [BUILD], [TEST].useInterwovenKit().username only for the connected wallet's own display name.{username ? username : shortenAddress(initiaAddress)}useUsernameQuery(address?) with the sender address; this requires @initia/interwovenkit-react 2.4.6 or newer.MessageRow) and call useUsernameQuery(address) there. Do NOT call hooks directly inside a parent component's .map() callback or conditional loop body.store_tx.json, tx.json, .bin) in the project directory after a task.When configuring a frontend for a local appchain, you MUST use BOTH the customChain AND customChains: [customChain] properties in InterwovenKitProvider.
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 the InterwovenKitProvider: .
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)..env / VITE_*) instead of leaving only placeholders or examples. For Move-specific APIs and code, keep the term module address where that distinction matters. If values are added or changed for a running Vite app, tell the user to restart the dev server.minitiad move build --named-addresses <name>=0x<hex_addr>.[addresses].<name> in Move.toml is hardcoded (for example 0x42) 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].Polyfills : Use vite-plugin-node-polyfills in vite.config.js with globals: { Buffer: true, process: true }. Also set resolve.dedupe to ['react', 'react-dom', 'wagmi', '@tanstack/react-query', 'viem'] to avoid provider context splits in Vite. If using manual polyfills, define Buffer and process global polyfills at the TOP of main.jsx.
import { Buffer } from "buffer";
window.Buffer = Buffer;
window.process = { env: {} };
[WASM][INTERWOVENKIT] Transaction Envelope : ALWAYS include chainId. Prefer requestTxSync.
MsgExecuteContract expects the msg field as bytes (Uint8Array). Use new TextEncoder().encode(JSON.stringify(msg)).[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 the flag in the request:
[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_messages or specific field names such as text or message; for example, MemoBoard variants commonly use get_messages with post_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);
.as_str() when comparing cosmwasm_std::Addr with a string literal or String. Addr does NOT implement PartialEq<&str> or PartialEq<String> directly.assert_eq!("user1", value.sender);assert_eq!("user1", value.sender.as_str());GAS).parseUnits(amount, 18)).100000000000000000000GAS (100 + 18 zeros) in the bank send command.formatUnits(balance, 18) from viem to display EVM balances. NEVER display raw base units in the UI.parseEther / Usage: and are valid shorthand ONLY when the chain token uses exactly 18 decimals. If decimals might vary, use and from runtime config.getMyBalance; confirm names/signatures from the generated artifact (for example out/<Contract>.sol/<Contract>.json) before wiring frontend encodeFunctionData calls.eth_call over RESTClient for EVM state queries to avoid property-undefined errors.eth_call), use a configured JSON-RPC endpoint (for example VITE_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.[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 args MUST be converted to hex, stripped of 0x, 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]);
cargo, forge, minitiad) are in PATH. Use absolute paths if needed.Move.toml or package.json before scaffolding. Use provided scripts for non-interactive scaffolding.RPC_ENDPOINT from runtime discovery):
curl -s "${RPC_ENDPOINT}/status" | jq -r '.result.node_info.network'references/common-tasks.mdreferences/contracts.mdreferences/frontend-interwovenkit.mdreferences/frontend-evm-rpc.mdreferences/e2e-recipes.mdreferences/runtime-discovery.mdreferences/weave-commands.mdhttps://docs.initia.xyzhttps://docs.initia.xyz/interwovenkitscripts/scaffold-contract.sh, scripts/scaffold-frontend.shscripts/verify-appchain.shscripts/convert-address.py, scripts/to_hex.py, scripts/generate-system-keys.pyscripts/install-tools.sh, scripts/fund-user.shWeekly Installs
51
Repository
First Seen
Mar 9, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
opencode51
codex51
gemini-cli48
github-copilot48
amp48
cline48
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
125,600 周安装
Context7自动研究技能:为Claude Code自动获取最新库/框架文档的API工具
309 周安装
Python 3.14+ 专家最佳实践与代码审查指南:生产级代码核心要点
309 周安装
Azure 工作负载自动升级评估工具 - 支持 Functions、App Service 计划与 SKU 迁移
309 周安装
Motion Designer动态设计指南:掌握迪士尼12条动画原则,打造专业UI/UX动画效果
312 周安装
LobeChat i18n 国际化指南:使用 react-i18next 实现多语言支持与最佳实践
319 周安装
AI文案撰写技能:专业品牌文案与转化文案撰写指南 | 营销内容创作
315 周安装
await autoSign?.disable(chainId)权限(关键):为确保会话密钥可以签署特定的消息类型,始终在 autoSign.enable 中包含明确的权限:
await autoSign.enable(chainId, { permissions: ["/initia.move.v1.MsgExecute"] })
错误处理:如果 autoSign.disable 因"未找到授权"而失败,请通过调用带有所需权限的 autoSign.enable 来重置会话。
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 |
[EVM][CLI]) over combined tags (for example, avoid [EVM CLI]).scripts/lint-tags.sh before changes and run it again before handoff.useUsernameQuery behavior:
useAddress() fallback).<InterwovenKitProvider {...TESTNET} ... />Address Prefix : customChain MUST include a top-level bech32_prefix string (e.g., bech32_prefix: "init"). This is mandatory for all appchain types.
Metadata Completeness : To avoid "Chain not found" errors, the customChain object MUST include network_type: 'testnet', staking, fees (with low/average/high_gas_price: 0), and native_assets arrays.
API Requirements : The apis object MUST include rpc, rest, AND indexer (use a placeholder if needed) to satisfy the kit's discovery logic.
Bridge Support (openBridge) : When using openBridge, ONLY specify srcChainId and srcDenom (e.g., initiation-2 and uinit). Avoid specifying a local dstChainId as it may cause resolution errors if the local chain is not yet indexed.
ExamplecustomChain Structure:
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' } }
}
.envuseInterwovenKit exports initiaAddress, address, username, openConnect, openWallet, openBridge, requestTxBlock, requestTxSync, and autoSign.requestTxBlock or requestTxSync, you MUST verify that initiaAddress is defined.sender field for all message types (MsgCall, MsgExecute, MsgExecuteContract) MUST be the Bech32 address. Use initiaAddress for this field to ensure compatibility across EVM, Move, and Wasm appchains. Using the hex address on an EVM chain for the sender field in a Cosmos-style message will cause an "empty address string" or "decoding bech32 failed" error.InitiaStdlib{ git = "https://github.com/initia-labs/movevm.git", subdir = "precompile/modules/initia_stdlib", rev = "main" }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 as blockforge/, create and enter that folder first before running minitiad move new.minitiad move clean may prompt for confirmation and panic without a TTY. In automated workflows, remove the package build/ directory directly if a clean rebuild is required.mint_shard).minitiad tx evm create with --from.jq; ensure NO 0x prefix and NO trailing newlines in .bin files.tx evm create Input Shape: The positional argument to minitiad tx evm create is a bytecode file path. If you want to pass raw bytecode directly, use --input 0x.... Passing raw hex as the positional argument can fail with file name too long.InterwovenKit.Styles :
import "@initia/interwovenkit-react/styles.css".import InterwovenKitStyles from "@initia/interwovenkit-react/styles.js".import { injectStyles } from "@initia/interwovenkit-react".injectStyles(InterwovenKitStyles).InterwovenKitStyles is a DEFAULT export from the styles subpath, while injectStyles is a NAMED export from the main package.Provider Order : WagmiProvider -> QueryClientProvider -> InterwovenKitProvider.
Wallet Modal :
openConnect (not openModal) to open the connection modal (v2.4.0+).initiaAddress is present, ALWAYS provide a clickable UI element (e.g., a button with a shortened address) that calls openWallet to allow the user to manage their connection or disconnect.Auto-Sign Implementation (STRICTLY OPT-IN) :
Provider : Pass enableAutoSign={true} to InterwovenKitProvider.
Hook : Destructure the autoSign object (not functions) from useInterwovenKit.
Safety : Use optional chaining (autoSign?.) and check status via autoSign?.isEnabledByChain[chainId].
Actions : await autoSign?.enable(chainId) and await 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.disable fails with "authorization not found", handle it by calling autoSign.enable with the required permissions to reset the session.
REST Client : Instantiate RESTClient from @initia/initia.js manually; it is NOT exported from the hook.
networks or rest from useInterwovenKit. These objects are NOT available in the hook. Always define your REST/RPC endpoints manually or via your own configuration.autoSign: trueawait requestTxSync({
chainId,
autoSign: true, // CRITICAL: Required for silent signing flow
messages: [...]
})
[EVM] Sender (MsgCall) : Use bech32 address for sender in MsgCall, but hex for contractAddr.
[EVM][INTERWOVENKIT] Payload : Use plain objects with typeUrl: "/minievm.evm.v1.MsgCall". The actual message fields MUST be wrapped inside a value key.
{ typeUrl: "...", sender: "...", contractAddr: "..." }{ typeUrl: "...", value: { sender: "...", contractAddr: "...", ... } }[EVM][INTERWOVENKIT]requestTxBlock Key: ALWAYS use messages (plural), not msgs. Passing msgs can fail with Cannot 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; moduleAddress MUST be bech32.
typeArgs: [] and args: [] even if they are empty. Omitting these fields in a Move execution message will cause a TypeError (Cannot read properties of undefined reading 'length') during the Amino conversion process in the frontend.[WASM][REST] Response Shape : smartContractState commonly returns the decoded payload directly (for example res.messages) rather than nesting it under res.data. Do not assume a .data wrapper unless you have verified the concrete response shape.
[WASM][REST] Method Name : ALWAYS use smartContractState. Methods like queryContractSmart are NOT available in the Initia RESTClient.
[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 or list-contract-by-code, treat the chain-emitted address as the source of truth. Verify it with minitiad query wasm list-contract-by-code <CODE_ID> and continue with the REST endpoint path or RESTClient instead of blocking on the CLI parser.
formatEtherparseEtherformatEtherparseUnits(amount, decimals)formatUnits(balance, decimals)eth_call), ALWAYS convert the bech32 address to hex using AccAddress.toHex(addr) and ensure the hex address is lowercased.minitiad query evm call expects a bech32 sender (init1...) as the first argument.minitiad query evm call -o json returns the call result under .response (hex string).minitiad query tx <hash> may briefly return tx not found; retry briefly before failing.viem (e.g., encodeFunctionData) for generating contract input hex.cast calldata (e.g., $(cast calldata "func(type)" arg)) for generating contract input hex. Manual encoding (e.g., printf) is brittle and MUST be avoided.BigInt values are converted to hex and padded to exactly 64 characters for uint256 arguments.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.view is a ViewResponse object; you MUST parse JSON.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.resource as a valid zero/default state instead of surfacing it as a hard failure.
[MOVE][REST] Troubleshooting (400 Bad Request) : If rest.move.view returns a 400 error, it is almost ALWAYS because:
args are not correctly hex-padded-base64 encoded.[MOVE][INTERWOVENKIT] Auto-Sign (No message types configured) : If autoSign.enable fails with "No message types configured", ensure:
metadata.minitia.type is set correctly (e.g., minimove, minievm).defaultChainId in InterwovenKitProvider matches your customChain.chain_id.bech32_prefix is present at the top level of customChain.minitiad q bank total --node "${RPC_ENDPOINT}"from account has enough of the actual native denom.weave rollup start -d and verify with scripts/verify-appchain.sh.borrow_global, borrow_global_mut, move_from, or calling a function that does) MUST include the acquires annotation for that resource type.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.///) AFTER attributes like #[view] or #[test].minitiad tx move publish command does NOT use a --path flag. Pass the path to the compiled .mv file as a positional argument: minitiad tx move publish <path_to_file>.mv ....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.sync|async; do not assume block is available.minitiad broadcast, minitiad query tx <hash> may briefly return tx not found; poll/retry before treating it as failed.openBridge from useInterwovenKit. Default srcChainId to a public testnet (e.g., initiation-2) for local demos.scripts/verify-appchain.sh --gas-station --bots and confirm transaction success before handoff.references/weave-config-schema.mdreferences/troubleshooting.md