diff --git a/.prettierignore b/.prettierignore index 7085120..9077da9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,3 +2,6 @@ developers/developer-guides/vm-specific-tutorials/movevm/building-move-modules.m developers/developer-guides/vm-specific-tutorials/movevm/setting-up.mdx developers/developer-guides/vm-specific-tutorials/movevm/your-first-module.mdx developers/developer-guides/integrating-initia-apps/initiadex.mdx +hackathon/hackathon-landing.mdx +hackathon/examples/evm-bank.mdx +hackathon/builder-guide.mdx diff --git a/docs.json b/docs.json index df76bee..d2770fa 100644 --- a/docs.json +++ b/docs.json @@ -536,6 +536,28 @@ "pages": ["/resources/security/audits"] } ] + }, + { + "tab": "Hackathon", + "hidden": true, + "groups": [ + { + "group": "Hackathon 2026", + "pages": [ + "hackathon/hackathon-landing", + "hackathon/builder-guide", + "hackathon/submission-requirements" + ] + }, + { + "group": "Examples", + "pages": [ + "hackathon/examples/move-game", + "hackathon/examples/evm-bank", + "hackathon/examples/wasm-social" + ] + } + ] } ], "global": { diff --git a/hackathon/builder-guide.mdx b/hackathon/builder-guide.mdx new file mode 100644 index 0000000..6f1e6d5 --- /dev/null +++ b/hackathon/builder-guide.mdx @@ -0,0 +1,184 @@ +--- +title: 'Hackathon Builder Guide' +--- + +# 🚀 Transitioning to Your Own Idea + +The Builder Guide is designed for developers who have already completed the +initial environment setup. If you haven't yet launched your first appchain, +please start with the **[Step-by-Step Guide](/hackathon/hackathon-landing)**. + +### ✅ Readiness Checklist + +Before proceeding, ensure you have completed these milestones: + +- [ ] **Tools Installed**: You have `weave`, `initiad`, and your chosen VM CLI + (`minitiad`) in your PATH. + ([Step 4](/hackathon/hackathon-landing#step-4:-install-required-tools)) +- [ ] **Infrastructure Live**: Your rollup is running and your OPinit/Relayer + bots are active. + ([Step 6](/hackathon/hackathon-landing#step-6:-setup-interwoven-bots-[terminal])) +- [ ] **Keys Imported**: Your Gas Station mnemonic is imported into your local + `initiad` and `minitiad` keyrings. + ([Step 7](/hackathon/hackathon-landing#step-7:-final-key-setup-[terminal])) + +--- + +# ⚡ Quick Reference: The Essentials + +Use these common commands and AI prompts to manage your project during the +hackathon. + +| Task | Command / AI Prompt | +| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Resume Appchain** | `weave rollup start -d && weave opinit start executor -d` (Restarts both your chain and the bridge bot) | +| **Health Check** | _Using the `initia-appchain-dev` skill, please verify that my appchain, executor bot, and relayer are running and that my Gas Station account has a balance._ | + +--- + +# Part 1: Development Workflow + +Master the **Describe → Build → Test** cycle. This is how you win the hackathon. + +### 💰 Funding Your Personal Wallet + +Before you can interact with your appchain via a browser wallet (like Keplr, +Leap, or MetaMask), you need to fund your personal address from your Gas +Station. + +1. Copy your wallet address: + +- Move / Wasm Track: Copy your `init1...` address. +- EVM Track: Copy your `0x...` address. + +2. Ask your AI Assistant to fund you: + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please fund my personal wallet with 1 INIT on L1 and 100 of my appchain's native tokens on L2. +``` + +### The Core Loop + +1. **Describe the Goal**: Tell the AI _what_ you want to achieve and _why_. +2. **Build & Test (Unit)**: Let the AI write the code AND the unit tests. + + **Prompt:** + + ```terminal wrap + Using the `initia-appchain-dev` skill, please write a Move module for a marketplace and a unit test to verify the 'list_item' function. + ``` + +3. **Deploy & Interact**: Instruct the AI to deploy to your appchain. + + **Prompt:** + + ```terminal wrap + Using the `initia-appchain-dev` skill, please deploy this module to my appchain and execute the 'list_item' function. + ``` + +4. **Verify State**: Ask the AI to query the chain to prove the logic works. + + + **Submission Receipt:** To qualify for the hackathon prizes, you must provide + the Contract Address of your primary logic and a Transaction Hash of a user + interacting with it. Save these as soon as you have a working version! + + +# Part 2: Choose Your Blueprint (Satisfy Pillar 3) + +To qualify for the hackathon prizes, your project must implement at least one +Initia Native Feature (defined as Pillar 3 in the submission +requirements). These Blueprints provide the foundation for meeting that +requirement. + + + **The Custom Implementation:** To win, don't just deploy these examples as-is. + Judges look for your Custom Implementation: the unique code and functionality you + added on top of these base patterns to solve a specific problem. + + + + + **Pillar 3: Invisible UX.** A high-frequency application where the + blockchain handles logic silently in the background. Users never see a + wallet popup after the initial session start. + - **Native Feature:** [Auto-signing](/interwovenkit/features/autosign/introduction) + - **Best for:** Gaming, Social tipping, High-frequency trading. + + + + **Pillar 3: Liquidity & Connectivity.** An application that allows users + to move assets between the broader Initia L1 and your appchain without + leaving your interface. + - **Native Feature:** [Interwoven Bridging](/interwovenkit/features/transfers/deposit-withdraw) + - **Best for:** DeFi Lending, Cross-chain storefronts, Multi-chain games. + + + + **Pillar 3: Human Identity.** An application that prioritizes + human-readable identities, replacing complex hex addresses with personal + usernames. + - **Native Feature:** [Initia Usernames](/developers/developer-guides/integrating-initia-apps/usernames) + - **Best for:** Consumer Social, Peer-to-peer payments, DAO governance. + + + +--- + +# Part 3: Making It Demo-Ready + +Judges want to see **On-chain Proof**. Use this checklist before submitting. + +- [ ] **Contract Address**: Your primary logic is deployed. +- [ ] **Interaction TX**: You have a transaction hash of a user _interacting_ + with your contract. +- [ ] **Frontend**: You are using **InterwovenKit** for the wallet connection. +- [ ] **Native Feature**: You've pointed to the code implementing an + Initia-native feature. + +--- + +# Part 4: Debugging & Troubleshooting + +Speed is everything in a hackathon, and debugging is where most time is lost. +Use these professional workflows to unblock yourself, even when following the +standard examples. + +### ⚡️ High-Signal AI Debugging + +Whether you are building from scratch or running a blueprint example, errors are +inevitable. + +1. **Open the Browser Console**: Press `F12` or `Cmd+Option+J` to see the exact + error logs. +2. **Context is King**: Ensure your AI agent (Cursor, Gemini) is **opened in + your project root**. This allows it to reference your `package.json`, your + `interwovenkit` initialization, and your specific chain configuration. +3. The Perfect Debugging Prompt: Provide the console error and ask your + assistant to find the cause within your project. + + **Prompt:** + + ```terminal wrap + I'm getting this [INSERT_CONSOLE_ERROR] in the browser. Looking at my codebase, why is my transaction failing and how do I fix it? + ``` + +### 📚 Deep Dives & Source Truth + +If your AI agent is stuck or you need to see the source of truth: + +- **Official Docs**: Visit [docs.initia.xyz](https://docs.initia.xyz/) for + architectural details and API references. +- **Initia Examples**: Reference the + [initia-labs/examples](https://github.com/initia-labs/examples) repository for + working code across all VMs (EVM, Move, Wasm). +- **Core Repositories**: Explore [initia-labs](https://github.com/initia-labs) + on GitHub to see the underlying implementation of the SDKs and CLI tools. + +--- + +> **Mandatory:** Review the +> **[Submission & Technical Requirements](/hackathon/submission-requirements)** +> to ensure you are eligible for prizes. diff --git a/hackathon/examples/evm-bank.mdx b/hackathon/examples/evm-bank.mdx new file mode 100644 index 0000000..9123227 --- /dev/null +++ b/hackathon/examples/evm-bank.mdx @@ -0,0 +1,790 @@ +--- +title: 'EVM Tutorial: MiniBank (Liquidity & Connectivity)' +--- + + + **Prerequisite:** Before starting this tutorial, you should have completed the + [Your First Appchain: A Step-by-Step Guide](../hackathon-landing) and have + an EVM-compatible appchain running locally. + + +--- + +This tutorial will guide you through building a liquidity-ready digital piggy bank on +your EVM appchain. Users can deposit tokens, withdraw them, and access the +broader Initia ecosystem via native bridging. + +By the end of this tutorial, you will have: + +- Generated and verified a Solidity smart contract for the bank logic. +- Deployed the contract to your live appchain. +- Scaffolded and connected a React frontend. +- Verified the on-chain functionality. + +--- + +## 📂 Recommended Project Structure + +To keep your workspace organized, we recommend the following structure inside your `my-initia-project` directory: + +```text +my-initia-project/ +├── minibank/ # Solidity smart contract project +└── minibank-frontend/ # React frontend application +``` + +--- + +## Step 1: Create and Verify the Smart Contract + +Instruct your AI assistant to create the Solidity contract using the +`initia-appchain-dev` skill. Your assistant will generate the contract and +automatically run unit tests to ensure the logic is sound. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please create a Solidity smart contract project for our MiniBank in a new directory named `minibank`. The contract should: +- Allow users to deposit native tokens. +- Allow users to withdraw their own deposited tokens. +- Keep track of each user's total savings. +- Include a function to view the caller's current balance. +Please also create and run a unit test to verify these features. +``` + +Your assistant will generate the `minibank` project and confirm that the tests +(likely using Foundry or Hardhat) pass successfully. + + +If you prefer to create the contract manually, here is the Solidity code your assistant would generate. Save this as MiniBank.sol in your `minibank/src` directory. + +```solidity wrap +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +contract MiniBank { + mapping(address => uint256) private balances; + + event Deposited(address indexed user, uint256 amount); + event Withdrawn(address indexed user, uint256 amount); + + function deposit() public payable { + require(msg.value > 0, "Cannot deposit 0"); + balances[msg.sender] += msg.value; + emit Deposited(msg.sender, msg.value); + } + + function withdraw(uint256 amount) public { + require(amount > 0, "Withdrawal amount must be greater than zero"); + require(balances[msg.sender] >= amount, "Insufficient balance"); + + balances[msg.sender] -= amount; + (bool success, ) = payable(msg.sender).call{value: amount}(""); + require(success, "Transfer failed"); + + emit Withdrawn(msg.sender, amount); + } + + function getBalance() public view returns (uint256) { + // NOTE: This returns the balance for the CALLER (msg.sender). + // In tests or frontend calls, ensure the correct account is the caller. + return balances[msg.sender]; + } + + function getBalanceOf(address user) public view returns (uint256) { + // Helper to check the balance of any user without needing a 'from' address. + return balances[user]; + } +} +``` + +### Unit Testing with Foundry +To verify your contract's logic, create a test file named `MiniBank.t.sol` in the `test` directory. + + + **Pro Tip**: `testFail` is deprecated in newer versions of Foundry. Use `vm.expectRevert()` for failure testing. + + +```solidity wrap +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import "../src/MiniBank.sol"; + +contract MiniBankTest is Test { + MiniBank public bank; + address public user = address(0x123); + + function setUp() public { + bank = new MiniBank(); + vm.deal(user, 10 ether); + } + + function testDeposit() public { + vm.prank(user); + bank.deposit{value: 1 ether}(); + assertEq(bank.getBalanceOf(user), 1 ether); + } + + function testWithdraw() public { + vm.startPrank(user); + bank.deposit{value: 2 ether}(); + bank.withdraw(1 ether); + assertEq(bank.getBalanceOf(user), 1 ether); + vm.stopPrank(); + } + + function testWithdrawInsufficientBalance() public { + vm.prank(user); + bank.deposit{value: 1 ether}(); + + vm.prank(user); + vm.expectRevert("Insufficient balance"); + bank.withdraw(2 ether); + } +} +``` + +Run your tests: +```bash wrap +forge test +``` + + +--- + +## Step 2: Deploy to your Appchain + +Now that the logic is verified, build and publish the contract to your live +appchain using the gas station account. + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please build and publish the MiniBank Solidity contract located in the `minibank` directory to my appchain using my gas station account. +``` + + +First, compile your contract and extract the hex bytecode: +```bash wrap +# Navigate to the contract directory +cd minibank + +# Compile with Foundry +forge build + +# Extract bytecode (requires jq) +# Ensure NO '0x' prefix and NO trailing newlines +jq -r '.bytecode.object' out/MiniBank.sol/MiniBank.json | tr -d '\n' | sed 's/^0x//' > minibank.bin +``` + +Then deploy the binary. **Find your Chain ID first** if you don't know it: +```bash wrap +# Option 1: Using the skill's health check script (Recommended) +bash .agents/skills/initia-appchain-dev/scripts/verify-appchain.sh --gas-station --bots + +# Option 2: Direct CLI query +minitiad status 2>&1 | jq -r '.NodeInfo.network' +``` + +Now deploy: +```bash wrap +# Replace `your-chain-id` with the ID from the command above +minitiad tx evm create minibank.bin \ + --from gas-station \ + --keyring-backend test \ + --chain-id your-chain-id \ + --gas auto --gas-adjustment 1.4 --yes --output json > deploy.json +``` + +**Retrieve your contract address:** +The output will provide a `txhash`. Wait a few seconds for indexing, then find your contract address: +```bash wrap +# Replace with the hash from deploy.json +minitiad q tx --output json | jq -r '.events[] | select(.type=="contract_created") | .attributes[] | select(.key=="contract") | .value' +``` + + +--- + +## Step 3: Fund your Browser Wallet + +Ensure your personal wallet has tokens to pay for the gas and initial deposits on your appchain. + +**1. Get your Wallet Address:** Open your browser wallet and copy your address (it starts with `init1...`). + +**2. Send Tokens from Gas Station:** Replace `` in the prompt below with the address you just copied. + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please fund my wallet address with 100 of my appchain's native tokens on L2. +``` + +--- + +## Step 4: Create a Frontend + +Let's create a simple UI to interact with our bank. + +**1. Scaffold the Frontend:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please scaffold a new Vite + React application named `minibank-frontend` in my current directory. Create a component named Bank.jsx with Deposit and Withdraw buttons and an input field for the amount. +``` + +**2. Connect to Appchain:** + +```terminal wrap +Using the `initia-appchain-dev` skill, modify the Bank.jsx component in the `minibank-frontend` directory to connect to our MiniBank contract on my appchain. Use the @initia/interwovenkit-react for wallet connection and transaction signing. +``` + + +If you prefer to set up the frontend manually, follow these steps: + +**1. Create the Project and Install Dependencies:** +```bash wrap +npm create vite@latest minibank-frontend -- --template react +cd minibank-frontend +npm install +npm install @initia/interwovenkit-react wagmi viem @tanstack/react-query @initia/initia.js @initia/initia.proto +npm install --save-dev vite-plugin-node-polyfills +npm install buffer util +``` + +**2. Create index.html:** +Create `index.html` in the root of your `minibank-frontend` directory: +```html wrap + + + + + + MiniBank Frontend + + +
+ + + +``` + +**3. Configure Vite Polyfills:** +Update `vite.config.js` to include the Node polyfills: +```javascript wrap +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import { nodePolyfills } from 'vite-plugin-node-polyfills' + +export default defineConfig({ + plugins: [ + react(), + nodePolyfills({ + globals: { + Buffer: true, + }, + }), + ], +}) +``` + +**3. Set up Providers in `main.jsx`:** +```javascript wrap +import { Buffer } from 'buffer' +window.Buffer = Buffer +window.process = { env: { NODE_ENV: 'development' } } + +import React from 'react' +import ReactDOM from 'react-dom/client' +import "@initia/interwovenkit-react/styles.css"; +import { injectStyles, InterwovenKitProvider, TESTNET } from "@initia/interwovenkit-react"; +import InterwovenKitStyles from "@initia/interwovenkit-react/styles.js"; +import { WagmiProvider, createConfig, http } from "wagmi"; +import { mainnet } from "wagmi/chains"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import App from './App.jsx' + +injectStyles(InterwovenKitStyles); + +const queryClient = new QueryClient(); +const wagmiConfig = createConfig({ + chains: [mainnet], + transports: { [mainnet.id]: http() }, +}); + +const customChain = { + chain_id: "your-chain-id", + chain_name: "minibank", + pretty_name: "MiniBank Appchain", + network_type: "testnet", + bech32_prefix: "init", + logo_URIs: { + png: "https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/initia/images/initia.png", + svg: "https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/initia/images/initia.svg" + }, + 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: "GAS", + fixed_min_gas_price: 0, + low_gas_price: 0, + average_gas_price: 0, + high_gas_price: 0 + }], + }, + staking: { + staking_tokens: [{ denom: "GAS" }] + }, + metadata: { + minitia: { type: "minievm" }, + is_evm: true, + is_l1: false + } +}; + +ReactDOM.createRoot(document.getElementById('root')).render( + + + + + + + + + , +) +``` + +**4. Create the `App.jsx` Layout:** +```javascript wrap +import React from 'react' +import { useInterwovenKit } from "@initia/interwovenkit-react"; +import Bank from './Bank'; + +function App() { + const { address, openConnect, openWallet } = useInterwovenKit(); + + const containerStyle = { + fontFamily: 'system-ui, -apple-system, sans-serif', + minHeight: '100vh', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: '#f1f5f9', + padding: '20px' + }; + + const cardStyle = { + backgroundColor: '#ffffff', + borderRadius: '16px', + boxShadow: '0 10px 25px -5px rgba(0, 0, 0, 0.1)', + padding: '40px', + width: '100%', + maxWidth: '500px', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + textAlign: 'center' + }; + + const buttonStyle = { + backgroundColor: '#3b82f6', + color: 'white', + border: 'none', + padding: '12px 24px', + borderRadius: '8px', + fontSize: '16px', + fontWeight: '600', + cursor: 'pointer', + width: '100%' + }; + + const secondaryButtonStyle = { + backgroundColor: '#f1f5f9', + border: '1px solid #e2e8f0', + color: '#64748b', + padding: '12px 24px', + borderRadius: '10px', + fontSize: '14px', + fontWeight: '600', + cursor: 'pointer', + marginTop: '20px', + width: '100%' + }; + + return ( +
+
+

MiniBank

+ + {!address ? ( + <> +

+ Connect your wallet to manage your savings. +

+ + + ) : ( + <> + + + + )} +
+
+ ) +} + +export default App +``` + +**5. Create the `Bank.jsx` Component:** +Create `src/Bank.jsx` and add the contract interaction logic. + + + **Pro Tip:** For a cleaner UI, hide the numeric "up/down" arrows in your CSS: + ```css + input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } + input[type=number] { -moz-appearance: textfield; } + ``` + + + + **Pro Tip**: For `view` functions that depend on `msg.sender` (like `getBalance`), you MUST provide a `from` address in your `eth_call` parameters so the appchain knows whose balance to check. + + +```javascript wrap +import React, { useState, useEffect } from 'react'; +import { useInterwovenKit } from "@initia/interwovenkit-react"; +import { encodeFunctionData, parseEther, formatEther } from "viem"; +import { AccAddress } from "@initia/initia.js"; + +const MINI_BANK_ADDRESS = "YOUR_CONTRACT_ADDRESS"; +const CHAIN_ID = "your-chain-id"; // Found in Step 2 +const MINI_BANK_ABI = [ + { name: "deposit", type: "function", stateMutability: "payable", inputs: [] }, + { name: "withdraw", type: "function", inputs: [{ name: "amount", type: "uint256" }] }, + { name: "getBalance", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] }, + { name: "getBalanceOf", type: "function", stateMutability: "view", inputs: [{ name: "user", type: "address" }], outputs: [{ type: "uint256" }] }, +]; + +const Bank = () => { + const [amount, setAmount] = useState(''); + const [balance, setBalance] = useState('0'); + const [isPending, setIsPending] = useState(false); + const { address, initiaAddress, requestTxBlock } = useInterwovenKit(); + + const fetchBalance = async () => { + if (!address) return; + try { + const fromAddress = address.startsWith("0x") ? address : AccAddress.toHex(address); + const data = encodeFunctionData({ abi: MINI_BANK_ABI, functionName: "getBalance" }); + const response = await fetch("http://localhost:8545", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + method: "eth_call", + params: [{ from: fromAddress, to: MINI_BANK_ADDRESS, data }, "latest"], + id: 1, + }), + }); + const result = await response.json(); + if (result.result && result.result !== "0x") { + setBalance(formatEther(BigInt(result.result))); + } + } catch (error) { + console.error("Error fetching balance:", error); + } + }; + + useEffect(() => { + fetchBalance(); + const interval = setInterval(fetchBalance, 10000); + return () => clearInterval(interval); + }, [address]); + + const handleDeposit = async () => { + if (!amount || !initiaAddress) return; + const data = encodeFunctionData({ abi: MINI_BANK_ABI, functionName: "deposit" }); + setIsPending(true); + try { + await requestTxBlock({ + chainId: CHAIN_ID, + msgs: [{ + typeUrl: "/minievm.evm.v1.MsgCall", + value: { + sender: initiaAddress, + contractAddr: MINI_BANK_ADDRESS, + input: data, + value: parseEther(amount).toString(), + accessList: [], + authList: [], + }, + }], + onSuccess: () => { + alert("Deposit successful!"); + setAmount(''); + fetchBalance(); + }, + onError: () => alert("Transaction failed or was cancelled.") + }); + } catch (error) { + console.error("Deposit error:", error); + } finally { + setIsPending(false); + } + }; + + const handleWithdraw = async () => { + if (!amount || !initiaAddress) return; + const data = encodeFunctionData({ + abi: MINI_BANK_ABI, + functionName: "withdraw", + args: [parseEther(amount)], + }); + setIsPending(true); + try { + await requestTxBlock({ + chainId: CHAIN_ID, + msgs: [{ + typeUrl: "/minievm.evm.v1.MsgCall", + value: { + sender: initiaAddress, + contractAddr: MINI_BANK_ADDRESS, + input: data, + value: "0", + accessList: [], + authList: [], + }, + }], + onSuccess: () => { + alert("Withdrawal successful!"); + setAmount(''); + fetchBalance(); + }, + onError: () => alert("Transaction failed or was cancelled.") + }); + } catch (error) { + console.error("Withdraw error:", error); + } finally { + setIsPending(false); + } + }; + + const balanceContainerStyle = { backgroundColor: '#f1f5f9', padding: '30px', borderRadius: '16px', marginBottom: '30px', border: '1px solid #e2e8f0' }; + const balanceValueStyle = { fontSize: '42px', fontWeight: '800', color: '#2563eb', margin: '10px 0', fontFamily: 'monospace' }; + const inputStyle = { width: '100%', padding: '14px', marginBottom: '20px', borderRadius: '10px', border: '2px solid #e2e8f0', fontSize: '16px', boxSizing: 'border-box' }; + const buttonContainerStyle = { display: 'flex', gap: '15px' }; + const actionButtonStyle = { flex: 1, padding: '14px', borderRadius: '10px', border: 'none', fontWeight: '700', fontSize: '16px', cursor: 'pointer', color: 'white' }; + + return ( +
+
+
Your Savings Balance
+
{balance} GAS
+
+ setAmount(e.target.value)} + placeholder="0.00" + style={inputStyle} + /> +
+ + +
+
+ ); +}; + +export default Bank; +``` + +
+ + + **Open the Frontend:** After scaffolding, `cd` into the `minibank-frontend` directory and run `npm run dev` to start the application. Open the provided URL in your browser and connect your wallet extension. + + If the app doesn't appear as expected or you encounter issues, check the **browser console** (F12 or Right-click > Inspect > Console) for logs. You can share these logs with your AI assistant to help troubleshoot errors or further customize the UI and functionality to your liking. + + +--- + +## Step 5: On-Chain Verification + +Finally, ask your AI assistant to interact with your **live** appchain to prove +the deployed contract works as expected. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, I want to verify our live MiniBank contract. Using my gas station account on my appchain, please: +1. Deposit 1 token. +2. Check my balance. +3. Withdraw 0.5 tokens. +4. Check my balance again. +``` + + + +**1. Find your hex address:** +To use `eth_call`, you need your account's hex address. Run the following: +```bash wrap +# Replace with the path to the skill's scripts directory +minitiad keys show gas-station -a --keyring-backend test | xargs -I {} python3 /to_hex.py {} +``` + +**2. Interact (Deposit 1 token):** +We'll use `cast sig` to generate the function selector and `10^18` units for "1 token". +```bash wrap +SIG=$(cast sig "deposit()") +minitiad tx evm call $SIG \ + --from gas-station \ + --keyring-backend test \ + --chain-id your-chain-id \ + --value 1000000000000000000 \ + --gas auto --gas-adjustment 1.4 --yes +``` + +**3. Query Balance:** +Querying a function that uses `msg.sender` requires a `from` address in the query call. +```bash wrap +SIG=$(cast sig "getBalance()") +# Replace and +minitiad q evm call 0x$SIG --output json +``` + +**4. Withdraw (0.5 tokens):** +```bash wrap +DATA=$(cast calldata "withdraw(uint256)" 500000000000000000) +minitiad tx evm call $DATA \ + --from gas-station \ + --keyring-backend test \ + --chain-id your-chain-id \ + --gas auto --gas-adjustment 1.4 --yes +``` + + +--- + +# ⚡ Power-Up: Interwoven Bridge + +Adding bridge support allows users to bring liquidity from the broader Initia +ecosystem into your rollup. This is essential for onboarding users from L1, +enabling exit liquidity, and ensuring your app is mainnet-ready. + + + **Local Dev Limitation:** The Interwoven UI requires a registered chain ID to + resolve assets. While it may appear empty for your local-only appchain, adding + this button prepares your app for its public launch. + + +### Step 6: Update the Frontend + +The `useInterwovenKit()` hook provides `openDeposit` and `openWithdraw` +functions that open a specialized modal for bridging assets. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please enable Interwoven Bridge support in my MiniBank so I can move funds between chains on Initia. +``` + + +To implement this, update your `src/Bank.jsx` to include the bridge logic and +UI: + +```tsx wrap +// 1. Extract bridge functions from the hook +const { address, openBridge } = useInterwovenKit(); + +// 2. Add bridge handler +const handleBridge = () => { + openBridge({ + srcChainId: 'initiation-2', // Public testnet ID + srcDenom: 'uinit' // Native INIT + }); +}; + +// 3. Add the Bridge UI section to your render (conditionally) +const bridgeContainerStyle = { + marginTop: '2rem', + padding: '1.5rem', + backgroundColor: '#fffbeb', + borderRadius: '24px', + border: '1px solid #fef3c7', + textAlign: 'left' +}; + +const bridgeButtonStyle = { + width: '100%', + padding: '0.85rem', + backgroundColor: '#d97706', + color: 'white', + border: 'none', + borderRadius: '14px', + fontSize: '13px', + fontWeight: '800', + cursor: 'pointer', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + gap: '0.5rem' +}; + +// Inside return (showing it only when connected)... +{address && ( +
+
+ Interwoven Ecosystem +
+

+ Access the broader Initia network to move assets between chains. +

+ +
+)} +``` + + + **Pro Tip:** This allows users to tap into L1 liquidity (like INIT from the + faucet) and bring it into your appchain's economy seamlessly while keeping + the landing page focused. + +
+ +--- + +## Next Steps + +Now that you've mastered an EVM application, you're ready to build your own +idea! Ensure your project meets all the technical pillars before submitting. + +**[→ Review Submission Requirements](../submission-requirements)** diff --git a/hackathon/examples/move-game.mdx b/hackathon/examples/move-game.mdx new file mode 100644 index 0000000..fdd1da0 --- /dev/null +++ b/hackathon/examples/move-game.mdx @@ -0,0 +1,471 @@ +--- +title: 'Move Tutorial: BlockForge Game (Invisible UX)' +--- + + + **Prerequisite:** Before starting this tutorial, you should have completed the + [Your First Appchain: A Step-by-Step Guide](../hackathon-landing) and have a + Move-compatible appchain running locally. + + +--- + +This tutorial will guide you through building a high-frequency on-chain game on +your Move appchain. BlockForge is a crafting engine that demonstrates Invisible +UX: allowing players to interact with the blockchain seamlessly without constant +wallet popups. + +By the end of this tutorial, you will have instructed your AI assistant to: + +- Generate and verify a Move smart contract for the game logic. +- Deploy the contract to your live appchain. +- Scaffold and connect a React frontend for players to interact with the game. +- Verify the on-chain functionality. + +--- + +## 📂 Recommended Project Structure + +To keep your workspace organized, we recommend the following structure inside +your `my-initia-project` directory: + +```text +my-initia-project/ +├── blockforge/ # Move smart contract project +└── blockforge-frontend/ # React frontend application +``` + +--- + +## Step 1: Create and Verify the Smart Contract + +Instead of writing the code yourself, instruct your assistant to do it for you +using the `initia-appchain-dev` skill. Your assistant will generate the contract +and automatically run unit tests to ensure the logic is sound. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please create a Move module project for our BlockForge game in a new directory named `blockforge`. The module should be named items inside a blockforge project. The game has the following rules: +- Players can mint basic items called shards. +- Players can craft relics by burning 2 shards. +- Players should have an inventory to store their items. +- I need a way to view a player's inventory. +Please also create and run a unit test to verify these rules. +``` + +Your assistant will generate the `blockforge` project, including the +`items.move` module and a test script, and confirm that everything passes. + + +If you prefer to create the Move module and project manually, follow these steps in your `blockforge` directory. This is what your AI assistant would generate for you. + +First, create a new Move package named `blockforge`: + +```bash wrap +minitiad move new blockforge +``` + +To ensure fast builds and access to the latest Initia features, we recommend +setting up local dependencies by cloning the `movevm` repository into a `deps` +folder: + +```bash wrap +mkdir -p blockforge/deps && cd blockforge/deps +git clone --depth 1 https://github.com/initia-labs/movevm.git +cd ../.. +``` + +Now, update the `Move.toml` file to use these local dependencies and enable Move +2.1 features. Replace the content of `blockforge/Move.toml` with the following: + +```toml wrap +[package] +name = "blockforge" +version = "0.0.1" +edition = "2024.alpha" + +[dependencies] +InitiaStdlib = { local = "deps/movevm/precompile/modules/initia_stdlib" } +MoveStdlib = { local = "deps/movevm/precompile/modules/move_stdlib" } + +[addresses] +blockforge = "_" # Use a placeholder to be set during build +std = "0x1" +``` + +Next, delete the default `blockforge.move` file and create a new file named +`blockforge/sources/items.move` with the following content. + +```move wrap +module blockforge::items { + use std::signer; + use std::vector; + + /// Error codes + const E_INSUFFICIENT_SHARDS: u64 = 1; + + struct Shard has key, store, copy, drop {} + struct Relic has key, store, copy, drop {} + + struct Inventory has key { + shards: vector, + relics: vector, + } + + /// Mint basic items called shards. + /// Automatically initializes inventory if it doesn't exist. + public entry fun mint_shard(account: &signer) acquires Inventory { + let addr = signer::address_of(account); + if (!exists(addr)) { + move_to(account, Inventory { + shards: vector::singleton(Shard {}), + relics: vector::empty() + }); + } else { + let inventory = borrow_global_mut(addr); + vector::push_back(&mut inventory.shards, Shard {}); + }; + } + + /// Craft a relic by burning 2 shards + public entry fun craft_relic(account: &signer) acquires Inventory { + let addr = signer::address_of(account); + assert!(exists(addr), E_INSUFFICIENT_SHARDS); + + let inventory = borrow_global_mut(addr); + assert!(vector::length(&inventory.shards) >= 2, E_INSUFFICIENT_SHARDS); + + // Burn 2 shards + vector::pop_back(&mut inventory.shards); + vector::pop_back(&mut inventory.shards); + + // Add 1 relic + vector::push_back(&mut inventory.relics, Relic {}); + } + + /// Returns (shards, relics) for the given address. + public fun get_inventory(addr: address): (u64, u64) acquires Inventory { + if (!exists(addr)) { + return (0, 0) + }; + let inventory = borrow_global(addr); + (vector::length(&inventory.shards), vector::length(&inventory.relics)) + } +} +``` + +Once the files are created, you can verify everything is correct by building the +project. Replace `0xYOUR_HEX_ADDRESS` with your deployment address hex (0x...). + +```bash wrap +minitiad move build --named-addresses blockforge=0xYOUR_HEX_ADDRESS +``` + +If you see `BUILDING blockforge`, then **BlockForge was built successfully! 🛠️** + + + +--- + +## Step 2: Deploy to your Appchain + +Now that the logic is verified, build and publish the contract to your live +appchain using the gas station account. + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please build and publish the blockforge Move module located in the `blockforge` directory to my appchain using my gas station account. +``` + + +First, get your gas station's hex address: + +```bash wrap +# Use the to_hex.py script to convert bech32 to hex +python3 scripts/to_hex.py $(minitiad keys show gas-station -a --keyring-backend test) +``` + +Then, build and publish the compiled module to your appchain. Substitute +`0xYOUR_HEX_ADDRESS` with the value from the previous step: + +```bash wrap +cd blockforge + +# 1. Build the module with the correct hex named address +minitiad move build --named-addresses blockforge=0xYOUR_HEX_ADDRESS + +# 2. Publish the compiled bytecode +minitiad tx move publish build/blockforge/bytecode_modules/items.mv \ + --from gas-station \ + --keyring-backend test \ + --chain-id your-chain-id \ + --gas auto --gas-adjustment 1.4 --yes --upgrade-policy COMPATIBLE +``` + + + +--- + +## Step 3: Fund your Browser Wallet + +Before you can interact with the game through a frontend, your browser wallet +needs tokens to pay for transaction fees. + +**1. Get your Wallet Address:** Open your browser wallet and copy your address +(it starts with `init1...`). + +**2. Send Tokens from Gas Station:** Replace `` in the +prompt below with the address you just copied. + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please fund my wallet address with 1 INIT on L1 and 100 of my appchain's native tokens on L2. +``` + +--- + +## Step 4: Create a Frontend + +A game needs a user interface. Let's create one using the `initia-appchain-dev` +skill. + +**1. Scaffold the Frontend:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please scaffold a new Vite + React application named `blockforge-frontend` in my current directory. Then, create a component named Game.jsx with Mint Shard and Craft Relic buttons and add it to the main App.jsx file. +``` + +**2. Connect the Frontend to the Appchain:** + +```terminal wrap +Now, using the `initia-appchain-dev`, please modify the Game.jsx component in the `blockforge-frontend` directory to interact with our deployed blockforge smart contract on my appchain. + +The Mint Shard button should call the mint_shard function, and the Craft Relic button should call the craft_relic function. Also, please display the player's current inventory of shards and relics. +``` + + + ### 1. Project Setup + Refer to the [Interwoven Kit Documentation](../../interwovenkit/introduction) + for initial project scaffolding instructions. + +### 2. Configure Providers + +Wrap your application with `InterwovenKitProvider` to enable wallet +connectivity. Ensure the `customChain` includes `fee_tokens` and +`bech32_prefix`. + +```tsx main.jsx +import { Buffer } from 'buffer' +window.Buffer = Buffer +window.process = { env: { NODE_ENV: 'development' } } + +import React from 'react' +import ReactDOM from 'react-dom/client' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { WagmiProvider, createConfig, http } from 'wagmi' +import { mainnet } from 'wagmi/chains' +import { + InterwovenKitProvider, + TESTNET, + injectStyles, +} from '@initia/interwovenkit-react' +import '@initia/interwovenkit-react/styles.css' +import InterwovenKitStyles from '@initia/interwovenkit-react/styles.js' +import App from './App.jsx' + +injectStyles(InterwovenKitStyles) + +const queryClient = new QueryClient() +const wagmiConfig = createConfig({ + chains: [mainnet], + transports: { + [mainnet.id]: http(), + }, +}) + +const customChain = { + chain_id: 'your-appchain-id', + chain_name: 'BlockForge Appchain', + bech32_prefix: 'init', + network_type: 'testnet', + apis: { + rpc: [{ address: 'http://localhost:26657' }], + rest: [{ address: 'http://localhost:1317' }], + indexer: [{ address: 'http://localhost:8080' }], + }, + fees: { + fee_tokens: [ + { + denom: 'umin', // Replace with your appchain's native denom + fixed_min_gas_price: 0.15, + }, + ], + }, + metadata: { + is_l1: false, + minitia: { + type: 'minimove', + }, + }, +} + +ReactDOM.createRoot(document.getElementById('root')).render( + + + + + + + + + , +) +``` + + + **Pro Tip: Move View Function Encoding:** Address arguments for `rest.move.view` MUST be 32-byte hex (padded to exactly 64 characters) and then Base64 encoded. + ```javascript + const hexAddr = AccAddress.toHex(address).replace('0x', '').padStart(64, '0'); + const b64Addr = Buffer.from(hexAddr, 'hex').toString('base64'); + ``` + Also, remember to include a small delay (e.g., `setTimeout(fetch, 2000)`) after transactions before refreshing the state to allow the indexer to catch up. + + + + + **Open the Frontend:** After scaffolding, `cd` into the `blockforge-frontend` directory and run `npm run dev` to start the application. Open the provided URL in your browser and connect your wallet extension. + +If the app doesn't appear as expected or you encounter issues, check the +**browser console** (F12 or Right-click > Inspect > Console) for logs. You can +share these logs with your AI assistant to help troubleshoot errors or further +customize the UI and functionality to your liking. + + + +--- + +## Step 5: On-Chain Verification + +Finally, ask your AI assistant to interact with your **live** appchain to prove +the deployed contract works as expected. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, I want to verify our live BlockForge game. Using my gas station account on my appchain, please: +1. Mint 3 shards. +2. Check my inventory. +3. Craft a relic. +4. Check my inventory again. +``` + + +Here are the equivalent `minitiad` commands to interact with the module. + +**Mint 3 shards:** + +```bash wrap +for i in {1..3}; do + minitiad tx move execute items mint_shard \ + --from gas-station \ + --keyring-backend test \ + --chain-id your-chain-id \ + --gas auto --gas-adjustment 1.4 --yes \ + --args '[]' --type-args '[]' + sleep 2 +done +``` + +**Check your inventory:** + +```bash wrap +minitiad query move view items get_inventory \ + --args '["address:init1..."]' +``` + + + +--- + +# ⚡ Power-Up: Auto-signing (Session UX) + +To make your BlockForge game natively integrated with the Initia stack, you can +enable **Auto-signing** to create a frictionless experience where players don't +see wallet popups for every game action. + +### 1. How it Works + +When a user enables Auto-sign, InterwovenKit performs three steps: + +1. **Ghost Wallet Derivation**: The user signs a one-time message + (`personal_sign`) to derive a unique, application-specific HD wallet. +2. **Authz Grant**: The user's primary wallet grants permission to this ghost + wallet to execute specific Move functions (`MsgExecute`) on their behalf. +3. **Feegrant**: The primary wallet authorizes the ghost wallet to use its + balance to pay for transaction fees. + +### 2. Update the Frontend + +You can enable session-based signing by modifying your provider configuration +and adding a toggle in your UI. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please modify my InterwovenKit configuration in `main.jsx` to enable `enableAutoSign`. Then, update `Game.jsx` to include a button that toggles auto-signing on and off for the player using the `autoSign` methods from `useInterwovenKit`. +``` + + +First, enable the feature in your provider: + +```tsx main.jsx + + + +``` + +Then, use the `useInterwovenKit` hook in your component to manage the session: + +```tsx Game.jsx +const { autoSign } = useInterwovenKit() +const chainId = 'your-chain-id' + +// Check if auto-sign is active for this chain +const isAutoSignEnabled = autoSign.isEnabledByChain[chainId] + +return ( + +) +``` + + + **Pro Tip:** You can check the exact expiration of the current session using `autoSign.expiredAtByChain[chainId]`. + + + +--- + +## Next Steps + +Now that you've mastered a Move application, you're ready to build your own +idea! Ensure your project meets all the technical pillars before submitting. + +**[→ Review Submission Requirements](../submission-requirements)** diff --git a/hackathon/examples/wasm-social.mdx b/hackathon/examples/wasm-social.mdx new file mode 100644 index 0000000..5cf6290 --- /dev/null +++ b/hackathon/examples/wasm-social.mdx @@ -0,0 +1,733 @@ +--- +title: 'Wasm Tutorial: MemoBoard (Human Identity)' +--- + + + **Prerequisite:** Before starting this tutorial, you should have completed the + [Your First Appchain: A Step-by-Step Guide](../hackathon-landing) and have a + Wasm-compatible appchain running locally. + + +--- + +This tutorial will guide you through building a lightning-fast on-chain +guestbook called **MemoBoard**. Users can post public messages, and the +application prioritizes human-readable identity by resolving `.init` usernames. + +By the end of this tutorial, you will have: + +- Generated and verified a Rust smart contract for the guestbook. +- Deployed the contract to your live appchain. +- Scaffolded and connected a React frontend. +- Verified the on-chain functionality. + +--- + +## 📂 Recommended Project Structure + +To keep your workspace organized, we recommend the following structure inside +your `my-initia-project` directory: + +```text +my-initia-project/ +├── memoboard/ # Rust smart contract project +└── memoboard-frontend/ # React frontend application +``` + +--- + +## Step 1: Create and Verify the Smart Contract + +Instruct your AI assistant to create the Rust (Wasm) contract using the +`initia-appchain-dev` skill. Your assistant will generate the contract and +automatically run unit tests to ensure the logic is sound. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please create a Rust smart contract project for our MemoBoard in a new directory named `memoboard`. The contract should: +- Allow users to post a message (string). +- Store a list of all messages with the sender's address. +- Include a function to query all messages on the board. +Please also create and run a unit test to verify these features. +``` + +Your assistant will generate the `memoboard` project and confirm that the Rust +tests pass. + + +If you prefer to see the Rust logic, here is a simplified version of what your assistant would generate. If doing this manually, save the following code in `src/contract.rs` inside your `memoboard` directory (ensure `src/lib.rs` exports the `contract` module). + +**Important:** Ensure your `Cargo.toml` includes the following `[lib]` section +to correctly generate the Wasm binary: + +```toml +[lib] +crate-type = ["cdylib", "rlib"] +``` + +```rust wrap +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, Addr}; +use cw_storage_plus::Item; + +#[cw_serde] +pub struct Memo { + pub sender: Addr, + pub message: String, +} + +pub const MESSAGES: Item> = Item::new("messages"); + +#[cw_serde] +pub struct InstantiateMsg {} + +#[cw_serde] +pub enum ExecuteMsg { + PostMessage { message: String }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(AllMessagesResponse)] + AllMessages {}, +} + +#[cw_serde] +pub struct AllMessagesResponse { + pub messages: Vec, +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate(deps: DepsMut, _env: Env, _info: MessageInfo, _msg: InstantiateMsg) -> Result { + MESSAGES.save(deps.storage, &vec![])?; + Ok(Response::new().add_attribute("action", "instantiate")) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute(deps: DepsMut, _env: Env, info: MessageInfo, msg: ExecuteMsg) -> Result { + match msg { + ExecuteMsg::PostMessage { message } => { + let mut messages = MESSAGES.load(deps.storage)?; + let sender = info.sender.clone(); + messages.push(Memo { sender: info.sender, message }); + MESSAGES.save(deps.storage, &messages)?; + Ok(Response::new() + .add_attribute("action", "post_message") + .add_attribute("sender", sender.as_str())) + } + } +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::AllMessages {} => { + let messages = MESSAGES.load(deps.storage)?; + to_json_binary(&AllMessagesResponse { messages }) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::testing::{message_info, mock_dependencies, mock_env}; + use cosmwasm_std::from_json; + + #[test] + fn test_post_and_query() { + let mut deps = mock_dependencies(); + let env = mock_env(); + + // Instantiate + let info = message_info(&Addr::unchecked("creator"), &[]); + instantiate(deps.as_mut(), env.clone(), info, InstantiateMsg {}).unwrap(); + + // Post Message + let info = message_info(&Addr::unchecked("user1"), &[]); + let msg = ExecuteMsg::PostMessage { message: "Hello!".to_string() }; + execute(deps.as_mut(), env.clone(), info, msg).unwrap(); + + // Query + let res = query(deps.as_ref(), env, QueryMsg::AllMessages {}).unwrap(); + let val: AllMessagesResponse = from_json(&res).unwrap(); + assert_eq!(val.messages.len(), 1); + assert_eq!(val.messages[0].message, "Hello!"); + assert_eq!(val.messages[0].sender.as_str(), "user1"); + } +} +``` + + + +--- + +## Step 2: Deploy to your Appchain + +Now that the logic is verified, build and publish the contract to your appchain +using the gas station account. + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please build and publish the MemoBoard Rust contract located in the `memoboard` directory to my appchain using my gas station account. +``` + + +**1. Build and Store the Code:** + +Standard `cargo build` binaries often fail validation on-chain. For WasmVM +deployment, it is strongly recommended to use the **CosmWasm Optimizer**. + +**Note for Apple Silicon (M1/M2/M3):** You **MUST** use the +`cosmwasm/optimizer-arm64:0.16.1` image variant or the build will be extremely +slow and may fail. + +```bash wrap +# Run from the root of your project +# Use 'optimizer' for x86_64 or 'optimizer-arm64' for Apple Silicon +OPTIMIZER_IMAGE="cosmwasm/optimizer-arm64:0.16.1" + +docker run --rm -v "$(pwd)/memoboard":/code \ + --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + $OPTIMIZER_IMAGE +``` + +The optimized binary will be located in `./memoboard/artifacts/memoboard.wasm`. +Now, store the code: + +```bash wrap +# If the chain requires fees, add the --fees flag (e.g., --fees 1000000umin) +minitiad tx wasm store ./memoboard/artifacts/memoboard.wasm \ + --from gas-station \ + --keyring-backend test \ + --chain-id your-chain-id \ + --gas auto --gas-adjustment 1.4 --yes +``` + +**2. Retrieve the Code ID and Instantiate:** + +If the `code_id` is not returned directly, wait for 5 seconds for indexing and +then query the transaction hash: + +```bash wrap +# Retrieve Code ID +minitiad q tx --output json | jq -r '.events[] | select(.type=="store_code") | .attributes[] | select(.key=="code_id") | .value' +``` + +Then, instantiate the contract: + +```bash wrap +minitiad tx wasm instantiate '{}' \ + --label "memoboard" \ + --from gas-station \ + --keyring-backend test \ + --chain-id your-chain-id \ + --gas auto --gas-adjustment 1.4 \ + --no-admin --yes +``` + +**3. Retrieve the Contract Address:** + +Wait for 5 seconds for indexing and then query the transaction hash: + +```bash wrap +# Retrieve Contract Address +minitiad q tx --output json | jq -r '.events[] | select(.type=="instantiate") | .attributes[] | select(.key=="_contract_address") | .value' +``` + + + +--- + +## Step 3: Fund your Browser Wallet + +Ensure your personal wallet has tokens to pay for the transaction to post a +memo. + +**1. Get your Wallet Address:** Open your browser wallet and copy your address +(it starts with `init1...`). + +**2. Send Tokens from Gas Station:** Replace `` in the +prompt below with the address you just copied. + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please fund my wallet address with 1 INIT on L1 and 100 of my appchain's native tokens on L2. +``` + +--- + +## Step 4: Create a Frontend + +Let's create a UI to display and post messages. + +**1. Scaffold the Frontend:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please scaffold a new Vite + React application named `memoboard-frontend` in my current directory. Create a component named Board.jsx that displays a list of messages and a text input to post a new one. +``` + +**2. Connect to Appchain:** + +```terminal wrap +Using the `initia-appchain-dev` skill, modify the Board.jsx component in the `memoboard-frontend` directory to connect to our MemoBoard contract on my appchain. Use the @initia/interwovenkit-react for wallet connection and transaction signing. +``` + + +If you prefer to set up the frontend manually, follow these steps: + +**1. Create the Project and Install Dependencies:** + +```bash wrap +npm create vite@latest memoboard-frontend -- --template react +cd memoboard-frontend +npm install +npm install @initia/interwovenkit-react wagmi viem @tanstack/react-query @initia/initia.js @initia/initia.proto +npm install --save-dev vite-plugin-node-polyfills +npm install buffer util +``` + +**2. Configure Vite Polyfills:** Update `vite.config.js` to include the Node +polyfills: + +```javascript wrap +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import { nodePolyfills } from 'vite-plugin-node-polyfills' + +export default defineConfig({ + plugins: [ + react(), + nodePolyfills({ + globals: { + Buffer: true, + }, + }), + ], +}) +``` + +**3. Set up Providers in `main.jsx`:** + +```javascript wrap +import { Buffer } from 'buffer' +window.Buffer = Buffer +window.process = { env: { NODE_ENV: 'development' } } + +import React from 'react' +import ReactDOM from 'react-dom/client' +import '@initia/interwovenkit-react/styles.css' +import { + injectStyles, + InterwovenKitProvider, + TESTNET, +} from '@initia/interwovenkit-react' +import InterwovenKitStyles from '@initia/interwovenkit-react/styles.js' +import { WagmiProvider, createConfig, http } from 'wagmi' +import { mainnet } from 'wagmi/chains' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import App from './App.jsx' + +// Inject styles for the InterwovenKit drawer +injectStyles(InterwovenKitStyles) + +const queryClient = new QueryClient() +const wagmiConfig = createConfig({ + chains: [mainnet], + transports: { [mainnet.id]: http() }, +}) + +const customChain = { + chain_id: 'your-chain-id', + chain_name: 'social', + pretty_name: 'Social Rollup', + network_type: 'testnet', + bech32_prefix: 'init', + logo_URIs: { + png: 'https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/initia/images/initia.png', + svg: 'https://raw.githubusercontent.com/initia-labs/initia-registry/main/testnets/initia/images/initia.svg', + }, + apis: { + rpc: [{ address: 'http://localhost:26657' }], + rest: [{ address: 'http://localhost:1317' }], + indexer: [{ address: 'http://localhost:8080' }], // Placeholder REQUIRED for stability + }, + fees: { + fee_tokens: [ + { + denom: 'umin', + fixed_min_gas_price: 0.15, + low_gas_price: 0.15, + average_gas_price: 0.15, + high_gas_price: 0.15, + }, + ], + }, + staking: { + staking_tokens: [{ denom: 'umin' }], + }, + metadata: { + minitia: { type: 'miniwasm' }, + is_l1: false, // REQUIRED for local appchains + }, +} + +ReactDOM.createRoot(document.getElementById('root')).render( + + + + + + + + + , +) +``` + +**4. Create the `Board.jsx` Component:** Create `src/Board.jsx` and +`src/Board.css` with the following content: + +**src/Board.css:** + +```css wrap +.board-container { + max-width: 600px; + margin: 40px auto; + padding: 32px; + font-family: sans-serif; +} +.board-title { + font-size: 2.5rem; + font-weight: 800; + margin-bottom: 24px; + text-align: center; +} +.section-header { + font-size: 0.85rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.1em; + color: #888; + margin-bottom: 16px; + display: block; +} +.auth-section { + display: flex; + justify-content: center; + margin-bottom: 24px; +} +.wallet-info { + background: #f0f0f0; + padding: 12px 16px; + border-radius: 12px; + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; +} +.message-card { + background: white; + padding: 16px; + border-radius: 12px; + border: 1px solid #eee; + margin-bottom: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.02); +} +.message-sender { + font-family: monospace; + font-size: 0.75rem; + color: #999; +} +.message-content { + margin-top: 8px; + font-size: 1.1rem; +} +.input-group { + display: flex; + gap: 12px; + margin-top: 16px; +} +.memo-input { + flex: 1; + padding: 12px 16px; + border-radius: 8px; + border: 1px solid #ddd; + outline: none; +} +.btn-primary { + background: #000; + color: #fff; + border: none; + padding: 12px 24px; + border-radius: 8px; + font-weight: 600; + cursor: pointer; +} +``` + +**src/Board.jsx:** + +```javascript wrap +import React, { useState, useEffect } from 'react' +import { useInterwovenKit } from '@initia/interwovenkit-react' +import { RESTClient } from '@initia/initia.js' +import { useDisconnect } from 'wagmi' +import './Board.css' + +const MEMO_BOARD_ADDRESS = 'YOUR_CONTRACT_ADDRESS' +// RESTClient is the primary client for queries in initia.js v1.0+ +const rest = new RESTClient('http://localhost:1317', { + chainId: 'social-1', +}) + +const Board = () => { + const [messages, setMessages] = useState([]) + const [content, setContent] = useState('') + const { initiaAddress, requestTxSync, openConnect, openWallet } = + useInterwovenKit() + const { disconnect } = useDisconnect() + + const truncate = (addr) => `${addr.slice(0, 10)}...${addr.slice(-6)}` + + const fetchMessages = async () => { + try { + // Wasm queries via REST MUST be base64 encoded + const queryData = Buffer.from( + JSON.stringify({ all_messages: {} }), + ).toString('base64') + const res = await rest.wasm.smartContractState( + MEMO_BOARD_ADDRESS, + queryData, + ) + setMessages((res?.messages || []).reverse()) + } catch (e) { + console.error('Failed to fetch messages', e) + } + } + + useEffect(() => { + fetchMessages() + // Poll for new messages every 5 seconds + const interval = setInterval(fetchMessages, 5000) + return () => clearInterval(interval) + }, []) + + const handlePostMessage = async () => { + if (!content || !initiaAddress) return + + // Encode execute msg to Uint8Array (bytes) + const msg = new TextEncoder().encode( + JSON.stringify({ post_message: { message: content } }), + ) + + try { + // Use requestTxSync for local development transactions + // ALWAYS include the chainId to avoid RPC routing errors + await requestTxSync({ + chainId: 'social-1', + messages: [ + { + typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract', + value: { + sender: initiaAddress, + contract: MEMO_BOARD_ADDRESS, + msg, + funds: [], + }, + }, + ], + }) + setContent('') + // Small delay to allow block inclusion + setTimeout(fetchMessages, 2000) + } catch (e) { + console.error('Transaction failed', e) + } + } + + return ( +
+

MemoBoard

+ {!initiaAddress ? ( +
+ +
+ ) : ( +
+
+ + +
+
+ )} + {initiaAddress && ( +
+

Post a Memo

+
+ setContent(e.target.value)} + placeholder="Write a memo..." + /> + +
+
+ )} +
+

Board Feed

+ {messages.map((m, i) => ( +
+
{truncate(m.sender)}
+
{m.message}
+
+ ))} +
+
+ ) +} + +export default Board +``` + +
+ + + **Open the Frontend:** After scaffolding, `cd` into the `memoboard-frontend` directory and run `npm run dev` to start the application. Open the provided URL in your browser and connect your wallet extension. + +If the app doesn't appear as expected or you encounter issues, check the +**browser console** (F12 or Right-click > Inspect > Console) for logs. You can +share these logs with your AI assistant to help troubleshoot errors or further +customize the UI and functionality to your liking. + + + +--- + +## Step 5: On-Chain Verification + +Finally, ask your AI assistant to interact with your **live** appchain to prove +the deployed contract works as expected. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, I want to verify our live MemoBoard contract. Using my gas station account on my appchain, please: +1. Post a message: "Hello from Initia!" +2. Query the board to see all messages. +``` + + +**Post Message:** +```bash wrap +# If the chain requires fees, add the --fees flag (e.g., --fees 1000000umin) +minitiad tx wasm execute '{"post_message":{"message":"Hello!"}}' \ + --from gas-station \ + --keyring-backend test \ + --chain-id your-chain-id \ + --gas auto --gas-adjustment 1.4 --yes +``` + +**Query Messages:** + +```bash wrap +# Note: minitiad query commands typically do not support the --chain-id flag +minitiad query wasm contract-state smart '{"all_messages":{}}' +``` + + + +--- + +# ⚡ Power-Up: Initia Usernames + +To make your MemoBoard natively integrated with the Initia stack, you can +replace long, complex addresses with human-readable **Initia Usernames** (e.g., +`vitalik.init`). + +## Step 6: Register your .init Name + +Before updating your code, you should register a primary username for your +wallet on the Initia testnet. + +1. Navigate to + [app.testnet.initia.xyz/usernames](https://app.testnet.initia.xyz/usernames) + and connect your browser wallet (e.g., Leap or Keplr). +2. In the **Find a username** search box, enter your desired name. If it is + available, you will see a green **Available** checkmark. +3. **Crucial:** Ensure the **Set as primary name** checkbox is selected. +4. Click **Register** and approve the transaction. Once resolved, your new + `.init` name will appear in the top-right corner of the Initia App. + +## Step 7: Update the Frontend + +Your AI assistant knows how to integrate Initia Usernames. Simply ask it to +update your board. + +**Example Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please add Initia username support to my MemoBoard. +``` + + +The `useInterwovenKit()` hook provides the `username` for the currently connected wallet. To implement this, update your `src/Board.jsx` to extract the `username` and update the render logic: + +```tsx wrap +// 1. Extract username from the hook +const { initiaAddress, username, openConnect, openWallet, requestTxSync } = useInterwovenKit(); + +// 2. Update the Header to show the username +
+ + +
+ +// 3. Update the Feed to show the username for the current user's posts +
+ {m.sender === initiaAddress && username ? username : truncate(m.sender)} +
+``` + + + **Pro Tip:** This pattern ensures that the connected user sees their identity reflected immediately in the application (in both the header and their own posts). For other participants in the feed, we continue to show the truncated address until a global resolver is implemented. + +
+ +--- + +## Next Steps + +Now that you've mastered a Wasm application, you're ready to build your own +idea! Ensure your project meets all the technical pillars before submitting. + +**[→ Review Submission Requirements](../submission-requirements)** diff --git a/hackathon/hackathon-landing.mdx b/hackathon/hackathon-landing.mdx new file mode 100644 index 0000000..6ed8ab1 --- /dev/null +++ b/hackathon/hackathon-landing.mdx @@ -0,0 +1,598 @@ +--- +title: 'Your First Appchain: A Step-by-Step Guide' +--- + +## Build an Appchain with Your AI Co-pilot + +Welcome to the hackathon! This guide will walk you through building an appchain +from scratch. You'll go from a simple idea to a functioning appchain with a +frontend efficiently. + +--- + +## Step 1: Prepare Your Workspace + +Before installing tools or initializing your appchain, create a dedicated +directory for your project. This keeps your configuration files, VM binaries, +and smart contracts organized in one place. + +**Run the following commands in your terminal:** + +```bash wrap +mkdir my-initia-project +cd my-initia-project +``` + +--- + +## Step 2: Install Your AI Skill [Terminal] + +Your AI assistant needs the **Initia Appchain Dev** skill to help you manage +your appchain, write smart contracts, and build your frontend. + +**Run the following command in your terminal:** + +```bash wrap +npx skills add initia-labs/agent-skills +``` + +--- + +## 🖥️ Recommended Setup + +To get the most out of this guide, we recommend having two terminal tabs or a +split-screen setup: + +1. **AI Co-pilot**: For high-level tasks, contract generation, and + troubleshooting. +2. **Standard Terminal**: For interactive CLI commands (like `weave init`) and + long-running builds. + +--- + +## Step 3: Choose Your Track & VM [Planning] + +Before installing tools, decide what you want to build. This choice determines +which **Virtual Machine (VM)** you will need for your appchain. + +| Track | Recommended VM | Why? | +| :----------------------- | :--------------- | :------------------------------------------------------------------ | +| **Gaming / Consumer** | `Move` | Best for complex on-chain logic and object-oriented assets. | +| **DeFi / Institutional** | `EVM` (Solidity) | Best for leveraging existing Ethereum tooling and libraries. | +| **Agents / Tooling** | `Wasm` (Rust) | Best for performance-critical logic and Rust ecosystem integration. | + +--- + +## Step 4: Install Required Tools + + + **Docker Desktop must be running.** Ensure it is installed and active before + running the installation command. If you don't have it, **[download Docker + Desktop here](https://www.docker.com/products/docker-desktop/)**. + + +### 4.1 Install the Core CLI Tools [AI Assistant] + +The fastest way to install the core CLIs (`weave`, `initiad`, `jq`) is to ask +your AI assistant. It will handle the environment setup for you. + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please install the core tools for Initia development. +``` + +### 4.2 Install Your Appchain VM [Terminal] + +Because each Virtual Machine (`Move`, `EVM`, `Wasm`) requires building a +specific `minitiad` binary from source, this step can take **5-15 minutes**. Run +the commands for your chosen VM directly in your standard terminal: + + + + ```bash wrap + git clone --depth 1 https://github.com/initia-labs/minimove.git + cd minimove && make install && cd .. && rm -rf minimove + ``` + + + ```bash wrap + git clone --depth 1 https://github.com/initia-labs/minievm.git + cd minievm && make install && cd .. && rm -rf minievm + ``` + + + ```bash wrap + git clone --depth 1 https://github.com/initia-labs/miniwasm.git + cd miniwasm && make install && cd .. && rm -rf miniwasm + ``` + + + +### 4.3 Verify Installation & PATH [AI Assistant] + +After the build completes, your AI assistant can ensure the tools are accessible +from anywhere in your system. This is especially helpful if you aren't sure how +to configure your `PATH` for your specific shell (Zsh, Bash, etc.). + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please verify that `minitiad` is properly installed and accessible. If it isn't in my PATH, help me add the Go binary directory to my shell configuration. +``` + +--- + +## Step 5: Initial Setup with `weave init` [Terminal] + +Your AI assistant is your partner in this hackathon, but the `weave` CLI +requires an initial interactive setup to prepare your environment and launch +your first appchain. This is a one-time process. + +**Run the following command in your terminal:** + +```bash wrap +weave init +``` + +Here's a guide on how to navigate the interactive setup: + + + + ### Generate Gas Station Account + The Gas Station is an account on the Initia L1 that will fund your rollup's infrastructure. + + **Prompt:** + ```terminal wrap + ? How would you like to setup your Gas station account? + ``` + + **Action:** + Select `Generate new account (recommended)`. + + **Result:** + You will see your new Gas Station Address. 💡 **Copy this address.** + + ### Fund Your Gas Station Account + **Action:** + Go to the **[Initia Testnet Faucet](https://app.testnet.initia.xyz/faucet)**. + + **Action:** + Paste your address and click **Submit** to receive testnet INIT tokens. + + **Prompt:** + ```terminal wrap + ? Type 'continue' to proceed. + ``` + + **Action:** + Type `continue` and press Enter. + + + + + ### Choose Your Action + **Prompt:** + ```terminal wrap + ? What do you want to do? + ``` + + **Action:** + Select `Launch a new rollup`. + + + **Switching VMs?** If you are switching from one Virtual Machine to another (e.g., from Wasm to Move), you **must** reinstall the correct `minitiad` binary as described in [**Step 4.2**](#4-2-install-your-appchain-vm-[terminal]). The new installation will override your previous one. + + If you have existing rollup data, you will be prompted to delete it. Type `confirm` to proceed with the new launch. + + + ### Select L1 Network + **Prompt:** + ```terminal wrap + ? Select the Initia L1 network + ``` + + **Action:** + Select `Testnet (initiation-2)`. + + ### Select Virtual Machine (VM) + **Prompt:** + ```terminal wrap + ? Select the Virtual Machine (VM) + ``` + + **Action:** + Select your desired VM (e.g., `Move`). + + ### Specify Rollup Chain ID + **Prompt:** + ```terminal wrap + ? Specify rollup chain ID + ``` + + **Action:** + Enter a unique ID (e.g., `mygame-1`). + + + **Save your Chain ID!** You will need to provide this unique identifier in your final hackathon submission. + + + ### Specify Rollup Gas Denom + **Prompt:** + ```terminal wrap + ? Specify rollup gas denom + ``` + + **Action:** + Press `Tab` for default (`umin`) or enter your own. + + ### Specify Rollup Node Moniker + **Prompt:** + ```terminal wrap + ? Specify rollup node moniker + ``` + + **Action:** + Press `Tab` for default (`operator`). + + + + + ### Submission Interval + **Prompt:** + ```terminal wrap + ? Specify OP bridge config: Submission Interval + ``` + + **Action:** + Press `Tab` for default (`1m`). + + ### Finalization Period + **Prompt:** + ```terminal wrap + ? Specify OP bridge config: Output Finalization Period + ``` + + **Action:** + Press `Tab` for default (`168h`). + + ### Data Availability + **Prompt:** + ```terminal wrap + ? Where should the rollup blocks data be submitted? + ``` + + **Action:** + Select `Initia L1`. + + ### Enable Oracle Price Feed + **Prompt:** + ```terminal wrap + ? Would you like to enable oracle price feed from L1? + ``` + + **Action:** + Select `Enable`. + + + + + ### Setup Method for System Keys + **Prompt:** + ```terminal wrap + ? Select a setup method for the system keys + ``` + + **Action:** + Select `Generate new system keys`. + + ### System Accounts Funding Option + **Prompt:** + ```terminal wrap + ? Select system accounts funding option + ``` + + **Action:** + Select `Use the default preset`. + + ### Specify Fee Whitelist Addresses + **Prompt:** + ```terminal wrap + ? Specify fee whitelist addresses + ``` + + **Action:** + Press `Enter` to leave empty. + + ### Add Gas Station Account to Genesis + **Prompt:** + ```terminal wrap + ? Would you like to add the gas station account to genesis accounts? + ``` + + **Action:** + Select `Yes`. + + ### Specify Genesis Balance + **Prompt:** + ```terminal wrap + ? Specify the genesis balance for the gas station account + ``` + + **Action:** + Enter `1000000000000000000000000` (10^24). This ensures you have plenty of tokens for testing, especially if you are on the EVM track. + + + If you are on the **Move track**, use `10000000000000000000` (10^19) instead, as Move balances are represented as `u64` and will overflow with larger values. + + + ### Add Additional Genesis Accounts + **Prompt:** + ```terminal wrap + ? Would you like to add genesis accounts? + ``` + + **Action:** + Select `No`. + + + + + ### Verify System Keys & Continue + **Prompt:** + ```terminal wrap + ? Type 'continue' to proceed. + ``` + + **Action:** + Type `continue` and press Enter. + + ### Confirm Transactions + **Prompt:** + ```terminal wrap + ? Confirm to proceed with signing and broadcasting the following transactions? [y]: + ``` + + **Action:** + Type `y` and press Enter. + +Your appchain will now launch and start producing blocks! + + + + +--- + +## Step 6: Setup Interwoven Bots [Terminal] + +To enable the Optimistic bridge and cross-chain communication (IBC) between +Initia L1 and your appchain, you need to start the **OPinit Executor** and the +**IBC Relayer**. These bots manage the cross-chain connectivity of your chain. + + + **Prerequisite:** Your appchain must be running before configuring these bots. Because `weave init` runs your chain in the background, you can continue using the same terminal window. + + +### 6.1 Start the OPinit Executor + +The executor handles the submission of rollup data and bridge operations. + +**Run the following command:** + +```bash wrap +weave opinit init executor +``` + +Follow the interactive guide: + + + + **Prompt:** + ```terminal wrap + ? Existing keys in config.json detected. Would you like to add these to the keyring before proceeding? + ``` + + **Action:** + Select `Yes, use detected keys`. + + + + **Prompt:** + ```terminal wrap + ? Please select an option for the system key for Oracle Bridge Executor + ``` + + **Action:** + Select `Generate new system key`. + + + + **Prompt:** + ```terminal wrap + ? Existing config.json detected. Would you like to use the data in this file to pre-fill some fields? + ``` + + **Action:** + Select `Yes, prefill`. + + + + **Prompt:** + ```terminal wrap + ? Specify listen address of the bot + ``` + + **Action:** + Press `Tab` to use `localhost:3000` (ensure nothing else is running on this port). + + + + **Action:** + Press `Enter` for **L1 RPC**, **Chain ID**, and **Gas Denom**. For **Rollup RPC**, press `Tab` to use `http://localhost:26657`. + + + Once initialized, start the bot in the background: + ```bash wrap + weave opinit start executor -d + ``` + + + +### 6.2 Start the IBC Relayer + +The relayer enables asset transfers (like INIT) between the L1 and your +appchain. + +**Docker Desktop** must be running to launch the relayer. + +**Run the following command:** + +```bash wrap +weave relayer init +``` + +Follow the interactive guide: + + + + **Prompt:** + ```terminal wrap + ? Select the type of Interwoven rollup you want to relay + ``` + + **Action:** + Select `Local Rollup (your-chain-id)`. + + + + **Action:** + Press `Tab` for both **RPC** (`http://localhost:26657`) and **REST** (`http://localhost:1317`) endpoints. + + + **Prompt:** + ```terminal wrap + ? Select method to setup IBC channels for the relayer + ``` + + **Action:** + Select `Subscribe to only transfer and nft-transfer IBC Channels (minimal setup)`. + + + + **Prompt:** + ```terminal wrap + ? Select the IBC channels you would like to relay + ``` + + **Action:** + Press `Space` to select all (transfer and nft-transfer), then press `Enter`. + + + + **Prompt:** + ```terminal wrap + ? Do you want to setup relayer with the challenger key + ``` + + **Action:** + Select `Yes (recommended)`. + + + + Start the relayer process: + ```bash wrap + weave relayer start -d + ``` + + + You can view relayer logs at any time by running `weave relayer log` in your terminal. + + + + + + + **Persistence After Restart:** + If you shut down your computer, the **Relayer** will stay active (it's managed by Docker), but you will need to manually restart your **Rollup full node** and **Executor bot** using these commands: + + ```bash wrap + # Restart the rollup full node + weave rollup start -d + + # Restart the OPinit executor bot + weave opinit start executor -d + ``` + + +--- + +## Step 7: Final Key Setup [Terminal] + +💡 **Why:** The **Gas Station** account acts as your **Universal Developer +Key**. Importing it allows you to sign transactions manually via the CLI, and it +enables your AI co-pilot to deploy contracts and interact with your appchain. + +**Action:** Run these commands to import your account into both the L1 +(`initiad`) and L2 (`minitiad`) keychains: + +```bash wrap +# Extract your mnemonic from the weave config +MNEMONIC=$(jq -r '.common.gas_station.mnemonic' ~/.weave/config.json) + +# Import into initiad (L1) +initiad keys add gas-station --recover --keyring-backend test --coin-type 60 --key-type eth_secp256k1 --source <(echo -n "$MNEMONIC") + +# Import into minitiad (L2) +minitiad keys add gas-station --recover --keyring-backend test --coin-type 60 --key-type eth_secp256k1 --source <(echo -n "$MNEMONIC") +``` + +**Action:** Verify the import by listing your keys to ensure `gas-station` +appears in both: + +```bash wrap +# Verify L1 keys +initiad keys list --keyring-backend test + +# Verify L2 keys +minitiad keys list --keyring-backend test +``` + +--- + +## Step 8: Verifying Your Appchain [AI Assistant] + +After completing the infrastructure setup, verify that everything is healthy. + +**Prompt:** + +```terminal wrap +Using the `initia-appchain-dev` skill, please verify that my appchain, executor bot, and relayer are running and that my Gas Station account has a balance. +``` + +--- + +## Step 9: Next Steps: Master the Workflow + +Congratulations! You have successfully launched your first appchain. Before +diving into a specific blueprint, we recommend mastering the development +workflow. + +The **Builder Guide** will teach you the **Describe → Build → Test** loop using +your AI co-pilot, which is essential for building a winning hackathon entry. + +**[→ Go to the Builder Guide](/hackathon/builder-guide)** + +--- + +## 🚨 Security & Production Note + +The workflows described in this guide are optimized for **rapid prototyping +during a hackathon or testnet development**. + +- **Key Storage:** Storing mnemonics in `config.json` and using the + `--keyring-backend test` flag is convenient but insecure for production. +- **Mainnet Deployment:** When moving to Mainnet, you must use a secure keyring + (like your OS keychain or a hardware wallet) and never share or store your + mnemonics in plaintext. +- **Account Roles:** For production rollups, it is best practice to use separate + accounts for the Gas Station, Validator, and Developer roles. diff --git a/hackathon/submission-requirements.mdx b/hackathon/submission-requirements.mdx new file mode 100644 index 0000000..1533bcb --- /dev/null +++ b/hackathon/submission-requirements.mdx @@ -0,0 +1,123 @@ +--- +title: 'Submission & Eligibility Criteria' +--- + +Welcome to the Initia hackathon! Our goal is to empower builders to push the +boundaries of what's possible with Interwoven Rollups. To ensure your project is +eligible for judging and showcases the best of the Initia ecosystem, please +adhere to the following technical pillars. + +--- + +# 1. Eligibility Pillars + +To qualify for the prize pool, projects must demonstrate meaningful integration +with the Initia stack. + +### 🏗️ Pillar 1: Dedicated Rollup Architecture + +This hackathon is dedicated to the power of appchains. Your project should be +deployed as its own appchain. + +- **Requirement:** Provide your rollup's Chain ID and a link to a transaction or + contract deployment on your rollup. +- **Getting Started:** Use the `weave` CLI to launch and manage your + environment. + +### ⚛️ Pillar 2: Optimized Frontend Experience + +We encourage builders to use the flagship tooling designed for the Interwoven +ecosystem. This ensures your application is fully integrated with the Initia +stack and provides a seamless experience for users. + +- **Requirement:** Utilize InterwovenKit (`@initia/interwovenkit-react`) for + wallet connections and transaction handling. +- **Why:** This stack enables advanced Initia features like social logins via + Privy and cross-chain visibility. + +### ⚡ Pillar 3: Showcasing Initia Native Features + +High-value projects go beyond Hello World by leveraging Initia's native +features. Your submission should implement at least one of the following +Interwoven Power-Ups: + +1. **Auto-signing (Invisible UX):** Create a frictionless experience where + players or users can interact with the blockchain seamlessly without + constant wallet popups (Session UX). +2. **Interwoven Bridge (Liquidity & Connectivity):** Enable the native bridge + interface to allow users to move assets between your appchain and the + broader Initia ecosystem. +3. **Initia Usernames (Human Identity):** Integrate human-readable `.init` + names to replace complex addresses and improve user onboarding. + +--- + +# 2. Technical Resource Hub + +Access the official tools and documentation to build your project: + +### Official Repositories + +- **[Initia L1](https://github.com/initia-labs/initia):** Core Layer 1 source + code. +- **[Weave CLI](https://github.com/initia-labs/weave):** Essential for launching + appchains. +- **[InterwovenKit](https://github.com/initia-labs/interwovenkit):** The + standard React SDK for Initia frontends. +- **[Initia.js](https://github.com/initia-labs/initia.js):** The primary + JavaScript library for blockchain interactions. + +### APIs & Endpoints + +- **Local Rollup Indexer:** `http://localhost:8080` (Use this to query + transactions and assets **on your appchain**). +- **L1 Indexer:** [View Swagger](https://indexer.initia.xyz/swagger/index.html) + (Use this as a reference for querying global data like L1 assets and staking). +- **L1 Testnet RPC:** `https://rpc.testnet.initia.xyz` +- **L1 Testnet LCD:** `https://lcd.testnet.initia.xyz` +- **Faucets:** [faucet.testnet.initia.xyz](https://faucet.testnet.initia.xyz) + +--- + +# 3. Submission Summary (Add to your README) + +To assist our technical review process and ensure your project stands out, +please include the following block at the **top** of your project's `README.md`. + +### 📝 Copy-Paste README Template + +```markdown +## 🚀 Initia Hackathon Submission + +- **Project Name**: [Your Project Name] + +### 📖 Project Overview + +[Provide a 2-3 sentence description of your application. Why is it valuable and +what problem does it solve?] + +### 🛠 Technical Specification (Automated Verification) + +- **Rollup Chain ID**: [e.g. my-game-1] +- **GitHub Repository**: [Link to public repo] +- **Custom Implementation (Core Logic)**: [Link to the specific smart contract + or module file] +- **Power-Up (Interwoven Feature)**: [Link to the specific frontend file + implementing the feature] +- **L2 Interaction TX**: [Hash/Link to a primary functionality transaction] +- **Demo Video URL**: [2-minute walkthrough via Loom, YouTube, etc.] + +### 🧬 Implementation Detail + +- **The Custom Implementation**: Briefly describe the unique logic you added. + What did you build that wasn't in the base template? +- **The Power-Up**: Which Interwoven feature did you use, and exactly how does + it improve the user experience? +- **The Value Add**: How does this application benefit the broader Initia + ecosystem? Why is it better as an appchain than a generic L1 dApp? + +### 🏃 How to Run Locally + +[Provide 3-4 clear steps for a judge to run your frontend and connect it to a +local environment if necessary.] +``` diff --git a/home/tools/wallet.mdx b/home/tools/wallet.mdx index b3cfacd..362cc4c 100644 --- a/home/tools/wallet.mdx +++ b/home/tools/wallet.mdx @@ -3,11 +3,11 @@ title: Wallet icon: wallet --- -One barrier for users onboarding into a new ecosystem has always been the need -to download, install, and use a new wallet. With the Initia Wallet, users can -sign in to an application using their existing EVM-compatible wallet, regardless -of the VM or smart contract language the application uses.. +One major barrier for users onboarding into a new ecosystem has always been the +need to download and install a new wallet. With the Initia Wallet, users can +sign in to any application using their existing EVM-compatible wallet, +regardless of the VM or smart contract language the application uses. For those without an existing wallet, the Initia Wallet also allows users to -create a new wallet using their email address or Google or Twitter account, -protected by [Privy](https://privy.io/). +create a new account using their email address or social media accounts (Google +or X), powered by [Privy](https://privy.io/).