Cubiq Logo

Developer Guide

Developer Guide

Build the next generation of mobile-native dApps on Cubiq Network. This comprehensive guide covers everything from setup to deployment.

SDK Ready

Full-featured SDK with TypeScript support and mobile-first APIs

Mobile Native

Built-in support for Android and iOS with native bindings

Quick Start

Get up and running with Cubiq Network in minutes. Follow these steps to create your first mobile-native dApp.

Prerequisites

  • Node.js 18+ installed
  • Basic knowledge of TypeScript/JavaScript
  • Understanding of blockchain concepts
  • Mobile development experience (optional)

Installation

Install the Cubiq CLI and SDK to get started:

npm install -g @cubiq/cli
npm install @cubiq/sdk

Initialize a new Cubiq project:

cubiq init my-mobile-dapp
cd my-mobile-dapp
npm install

Your First App

Let's create a simple mobile voting app that demonstrates Cubiq's key features:

import { Cubiq } from "@cubiq/sdk";

const client = new Cubiq({
  network: "testnet",
  zkUrlEndpoint: "zk://testnet.cubiq.org"
});

// Initialize mobile Qube connection
async function initializeApp() {
  await client.connect();
  
  // Check if running on mobile device
  if (client.isMobile()) {
    console.log("Running on mobile Qube!");
  }
}

// Verify a zkProof for a proposal
async function verifyProposal(proposalId: string) {
  const proof = await client.zk.getProof(`zk://proposal/${proposalId}`);
  
  if (await client.zk.verifyProof(proof)) {
    console.log("Proposal verified successfully!");
    return true;
  }
  
  return false;
}

// Cast a vote (mobile-optimized)
async function castVote(proposalId: string, vote: boolean) {
  if (await verifyProposal(proposalId)) {
    const tx = await client.qube.vote(proposalId, vote);
    console.log("Vote cast:", tx.hash);
  }
}

Cubiq SDK

The Cubiq SDK provides a comprehensive toolkit for building mobile-native dApps:

Core Features

  • zkURL Client - Fetch and verify zero-knowledge proofs
  • Qube Integration - Connect to mobile validator nodes
  • Smart Contract Tools - Deploy and interact with zkEVM contracts
  • Mobile Bindings - Native Android/iOS support

SDK Architecture

Core SDK

Client library for chain interaction

Mobile Runtime

WASM-based proof verification

zkURL Toolkit

Proof fetching and validation

CLI Tools

The Cubiq CLI provides essential development tools:

# Initialize new project
cubiq init myApp

# Deploy smart contracts
cubiq deploy --network testnet

# Verify zkProofs
cubiq verify --proof zkproof.json --block 123456

# Setup mobile Qube
cubiq qube onboard

# Run local development server
cubiq dev

zkURL Protocol Overview

The zkURL protocol is Cubiq's revolutionary approach to decentralized proof distribution:

zkURL is to Cubiq what HTTP is to the Web - a standardized way to fetch and verify zero-knowledge proofs across devices.

zkURL Format

zk://[proverID]@[domain_or_hash]/[proof_id]#[metadata]

Example:

zk://prover01@prover.cubiq.org/block/8472934#v1

Components

  • proverID - Registered identity of prover (mapped to pubkey)
  • domain_or_hash - Host or content-addressed hash (IPFS, Arweave)
  • proof_id - Unique proof identifier (block number or hash)
  • metadata - Optional metadata (version, compression format)

zkURL Implementation

Here's how to implement zkURL fetching in your application:

import { zkURL } from "@cubiq/sdk";

// Fetch and verify a proof
async function fetchProof(zkUrl: string) {
  try {
    // Parse zkURL
    const parsed = zkURL.parse(zkUrl);
    console.log("Prover ID:", parsed.proverID);
    console.log("Proof ID:", parsed.proofId);
    
    // Fetch proof with fallback
    const proof = await zkURL.fetch(zkUrl, {
      fallbacks: ["ipfs", "arweave"],
      timeout: 5000
    });
    
    // Verify proof integrity
    const isValid = await zkURL.verify(proof, {
      checkSignature: true,
      checkTimestamp: true,
      maxAge: 3600 // 1 hour
    });
    
    if (isValid) {
      console.log("Proof verified successfully!");
      return proof;
    } else {
      throw new Error("Proof verification failed");
    }
    
  } catch (error) {
    console.error("zkURL fetch failed:", error);
    throw error;
  }
}

zkEVM Compatibility

Cubiq provides full Solidity compatibility through its zkEVM implementation:

Supported Features

✅ Fully Supported

  • Solidity 0.8.x
  • Standard EVM opcodes
  • Events and logs
  • Contract interactions
  • Hardhat/Foundry tools

⚠️ Limited Support

  • Some precompiles
  • Complex assembly
  • Gas-intensive operations
  • Large contract sizes

Smart Contract Deployment

Deploy your contracts to Cubiq Network:

// hardhat.config.ts
import { HardhatUserConfig } from "hardhat/config";
import "@cubiq/hardhat-plugin";

const config: HardhatUserConfig = {
  solidity: "0.8.19",
  networks: {
    cubiq: {
      url: "https://rpc.cubiq.org",
      accounts: [process.env.PRIVATE_KEY!]
    },
    cubiqTestnet: {
      url: "https://testnet-rpc.cubiq.org",
      accounts: [process.env.PRIVATE_KEY!]
    }
  }
};

export default config;
# Deploy to testnet
npx hardhat deploy --network cubiqTestnet

# Verify contract
npx hardhat verify --network cubiqTestnet DEPLOYED_CONTRACT_ADDRESS

Example: Mobile Voting App

Complete example of a mobile-optimized voting application:

// VotingApp.tsx
import React, { useState, useEffect } from 'react';
import { Cubiq } from '@cubiq/sdk';

interface Proposal {
  id: string;
  title: string;
  description: string;
  zkProofUrl: string;
  verified: boolean;
}

export function VotingApp() {
  const [cubiq] = useState(() => new Cubiq({ network: 'testnet' }));
  const [proposals, setProposals] = useState<Proposal[]>([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    initializeApp();
  }, []);

  async function initializeApp() {
    try {
      await cubiq.connect();
      await loadProposals();
    } catch (error) {
      console.error('Failed to initialize:', error);
    }
  }

  async function loadProposals() {
    setLoading(true);
    try {
      const proposalList = await cubiq.contract.call('getActiveProposals');
      
      // Verify each proposal's zkProof
      const verifiedProposals = await Promise.all(
        proposalList.map(async (proposal: any) => {
          const proof = await cubiq.zk.getProof(proposal.zkProofUrl);
          const verified = await cubiq.zk.verifyProof(proof);
          
          return {
            ...proposal,
            verified
          };
        })
      );
      
      setProposals(verifiedProposals);
    } catch (error) {
      console.error('Failed to load proposals:', error);
    } finally {
      setLoading(false);
    }
  }

  async function castVote(proposalId: string, support: boolean) {
    try {
      setLoading(true);
      
      // Verify proposal proof before voting
      const proposal = proposals.find(p => p.id === proposalId);
      if (!proposal?.verified) {
        throw new Error('Proposal not verified');
      }
      
      // Cast vote through Qube
      const tx = await cubiq.qube.vote(proposalId, support);
      console.log('Vote cast:', tx.hash);
      
      // Refresh proposals
      await loadProposals();
      
    } catch (error) {
      console.error('Failed to cast vote:', error);
    } finally {
      setLoading(false);
    }
  }

  return (
    <div className="voting-app">
      <h1>Cubiq Mobile Voting</h1>
      
      {loading && <div>Loading...</div>}
      
      {proposals.map(proposal => (
        <div key={proposal.id} className="proposal-card">
          <h3>{proposal.title}</h3>
          <p>{proposal.description}</p>
          
          <div className="verification-status">
            {proposal.verified ? (
              <span className="verified">✅ Verified</span>
            ) : (
              <span className="unverified">❌ Unverified</span>
            )}
          </div>
          
          <div className="vote-buttons">
            <button 
              onClick={() => castVote(proposal.id, true)}
              disabled={!proposal.verified || loading}
            >
              Vote Yes
            </button>
            <button 
              onClick={() => castVote(proposal.id, false)}
              disabled={!proposal.verified || loading}
            >
              Vote No
            </button>
          </div>
        </div>
      ))}
    </div>
  );
}

Next Steps

Explore Examples

Check out our comprehensive example applications

Coming Soon
Join Community

Connect with other developers building on Cubiq

Discord & GitHub