- JavaScript 45.6%
- Shell 35.5%
- HTML 13.1%
- Solidity 5.8%
|
|
||
|---|---|---|
| contracts | ||
| dapps | ||
| docs | ||
| scripts | ||
| .gitignore | ||
| .gitmodules | ||
| dappstore-address.txt | ||
| README.md | ||
| testdapp-address.txt | ||
Litheum DappStore
This repository contains the DappStore smart contracts and deployment tools for the Litheum blockchain.
Overview
The DappStore is a decentralized registry for applications on Litheum. It provides:
- On-chain registration of dapps
- Approval system for quality control
- Integration with Litheum's media storage for dapp hosting
- Standardized interface (IDapp) for all applications
Note: This repository uses a local implementation of Ownable.sol to avoid external dependencies like OpenZeppelin.
Prerequisites
- Litheum node running locally (default: http://localhost:8001)
- lcli (Litheum CLI) configured with wallet
- Solidity compiler (solc)
- Basic shell utilities (bash, grep, awk)
Directory Structure
contracts/- Smart contracts for dappsIDapp.sol- Interface that all dapps must implementIDappStore.sol- Interface for dapp store contractsDappStore.sol- Main dapp store implementationTestDapp.sol- Example dapp implementationOwnable.sol- Local implementation of access control
dapps/- HTML/JS dapp frontendsdapp-store.html- Dapp store UIdapp-store.js- Dapp store JavaScripttest.html- Test dapp UItest.js- Test dapp JavaScript
scripts/- Deployment and utility scriptsdeploy-dappstore.sh- Deploys DappStore contract (saves to ~/.litheum/chaindata/dappstore)deploy-testdapp.sh- Deploys TestDapp with media publishing
docs/- Additional documentationmedia-publishing.md- Details on Litheum's media storage
DappStore Architecture
The DappStore follows the specification in the Litheum E2E Dapps design:
-
IDapp Interface - All dapps must implement:
getEntrypoint()- Returns media hash of the dapp's HTMLgetName()- Returns dapp name (max 30 chars)getIcon()- Returns media hash of the dapp's icongetDescription()- Returns description (max 500 chars)
-
DappStore Contract - Manages dapp registry:
- Submit dapps for approval
- Owner can approve/remove dapps
- Set ranking for featured ordering
- Pagination support for listing
-
Media Storage Integration - Dapps are stored on-chain:
- HTML/JS/CSS published as media transactions
- Retrieved via
/media/{hash}endpoint - Wallet loads dapps in sandboxed iframes
Quick Start
1. Clone and Setup
git clone [repository-url] litheum-dapps
cd litheum-dapps
# Make scripts executable
chmod +x scripts/*.sh
2. Deploy DappStore
./scripts/deploy-dappstore.sh
This will compile and deploy the DappStore contract. Note the deployed address.
3. Deploy a Test Dapp
./scripts/deploy-testdapp.sh
This script will:
- Publish test.html to media storage using lcli
- Deploy the TestDapp contract with the media hash
- Submit the dapp to DappStore for approval
4. Approve the Dapp
As the DappStore owner, approve the submitted dapp:
# Replace addresses with actual values from deployment
lcli send-transaction \
--to [DAPPSTORE_ADDRESS] \
--data "0x8a3e645a[TESTDAPP_ADDRESS_PADDED]" \
--gas-limit 200000
5. Configure Wallet
In LitheumWallet, configure the DappStore address to see your dapps.
Deployment Instructions (Manual)
1. Deploy DappStore Contract
Using the deployment script:
# Run the DappStore deployment script
./scripts/deploy-dappstore.sh
Or manually using lcli:
# First, compile the contracts
cd contracts
solc --abi --bin --optimize Ownable.sol -o ../build --overwrite
solc --abi --bin --optimize IDapp.sol -o ../build --overwrite
solc --abi --bin --optimize IDappStore.sol -o ../build --overwrite
solc --abi --bin --optimize DappStore.sol -o ../build --overwrite
# Deploy DappStore
lcli send-transaction \
--bytecode ../build/DappStore.bin \
--gas-limit 3000000 \
--constructor-args ""
Save the deployed contract address from the output - you'll need it for the wallet configuration.
2. Deploy a Test Dapp
The deployment script now handles media publishing automatically:
# Run the TestDapp deployment script
./scripts/deploy-testdapp.sh
Or manually:
# Compile TestDapp
cd contracts
solc --abi --bin --optimize TestDapp.sol -o ../build --overwrite
# First, publish the test dapp HTML to media storage
lcli send-transaction \
--media-file ../dapps/test.html \
--content-type "text/html" \
--bytehours 8760 # 1 year
# Note the media hash from the output (e.g., 0xabcd...1234)
# Deploy TestDapp contract with the media hash
lcli send-transaction \
--bytecode ../build/TestDapp.bin \
--gas-limit 1000000 \
--constructor-args "0xabcd...1234" # Use actual media hash
# Submit the TestDapp to DappStore
# Function selector for submitDapp(address): 0x7e5fb2f7
lcli send-transaction \
--to [DAPP_STORE_ADDRESS] \
--data "0x7e5fb2f7[TESTDAPP_ADDRESS_PADDED_TO_64_CHARS]" \
--gas-limit 200000
3. Approve the Dapp (as DappStore owner)
# Function selector for approveDapp(address): 0x8a3e645a
lcli send-transaction \
--to [DAPP_STORE_ADDRESS] \
--data "0x8a3e645a[DAPP_ADDRESS_PADDED_TO_64_CHARS]" \
--gas-limit 200000
4. Verify Deployment
# Check owner
lcli eth-call --to [DAPP_STORE_ADDRESS] --data 0x8da5cb5b
# Check dapp count
lcli eth-call --to [DAPP_STORE_ADDRESS] --data 0x4dfa8e41
# Check if a dapp is listed
# Function selector for isListed(address): 0x821b99ba
lcli eth-call --to [DAPP_STORE_ADDRESS] --data "0x821b99ba[DAPP_ADDRESS_PADDED]"
Media Publishing with lcli
lcli now supports publishing files to Litheum's media storage:
# Publish an HTML file
lcli send-transaction \
--media-file path/to/file.html \
--content-type "text/html" \
--bytehours 8760 \
--media-name "My Dapp" \
--max-payment 250000000 # Payment for storage
# Publish an image (larger file = higher payment needed)
lcli send-transaction \
--media-file logo.png \
--content-type "image/png" \
--bytehours 87600 \
--max-payment 5000000000 # Adjust based on file size
The command returns:
- Media hash (SHA256 of content)
- Transaction hash
- Access URL (/media/{hash})
Bytehours Calculation
Storage cost is based on file size × hours:
- 1 KB for 1 year = 1,024 × 8,760 = 8,972,640 bytehours
- 1 MB for 1 month = 1,048,576 × 720 = 755,497,472 bytehours
Important: For media transactions, the --max-payment parameter sets the payment amount (a U256 carried inside the media message — no u64 ceiling). The network calculates the required payment based on current storage costs; set this value high enough to cover the total bytehours cost. The legacy --max-gas-price payment (u64) is still accepted but capped.
Wallet Integration
The LitheumWallet automatically discovers DappStore addresses from multiple sources:
Automatic Discovery
- Chaindata: Deployment scripts save addresses to
~/.litheum/chaindata/dappstore/ - Default Stores: Known DappStore addresses are pre-configured for each network
- User Stores: Additional stores can be added through the wallet UI
DappStore Tab Features
- Store Selector: Switch between multiple DappStores
- Add New Store: Configure additional DappStore contracts
- Auto-import: Stores saved by deployment scripts appear automatically
- Persistent Storage: User preferences saved locally
The wallet displays approved dapps and loads them from media storage when selected.
Chaindata Integration
Contract addresses are automatically saved to ~/.litheum/chaindata/ during deployment:
~/.litheum/chaindata/dappstore- Contains the deployed DappStore address~/.litheum/chaindata/servicemarketplace- Contains the ServiceMarketplace address (when deployed)
These addresses are compiled into the LitheumWallet's WASM module at build time, making them available to the wallet automatically.
Creating a New Dapp
Step 1: Implement the IDapp Interface
contract MyDapp is IDapp {
bytes32 private _entrypoint;
constructor(bytes32 entrypointHash) {
_entrypoint = entrypointHash;
}
function getEntrypoint() external view returns (bytes32) {
return _entrypoint;
}
function getName() external pure returns (string memory) {
return "My Awesome Dapp";
}
function getIcon() external pure returns (bytes32) {
return bytes32(0); // Optional icon hash
}
function getDescription() external pure returns (string memory) {
return "Description of what my dapp does";
}
}
Step 2: Create Your Frontend
<!DOCTYPE html>
<html>
<head>
<title>My Dapp</title>
<script src="https://cdn.jsdelivr.net/npm/web3@1.9.0/dist/web3.min.js"></script>
</head>
<body>
<h1>My Dapp</h1>
<script src="mydapp.js"></script>
</body>
</html>
Step 3: Deploy
# 1. Publish HTML
lcli send-transaction \
--media-file mydapp.html \
--content-type "text/html" \
--bytehours 8760
# 2. Note the media hash (e.g., 0xabc...123)
# 3. Deploy contract with media hash
lcli send-transaction \
--bytecode MyDapp.bin \
--constructor-args "0xabc...123" \
--gas-limit 1000000
# 4. Submit to DappStore
lcli send-transaction \
--to [DAPPSTORE_ADDRESS] \
--data "0x7e5fb2f7[MYDAPP_ADDRESS_PADDED]" \
--gas-limit 200000
Security Considerations
- All dapps run in sandboxed iframes in the wallet
- Dapps communicate with the wallet via postMessage API
- Users must explicitly approve transactions
- DappStore owners curate listings for quality/safety
- Media storage is immutable - plan your deployments carefully
Troubleshooting
Common Issues
-
"File not found" when running scripts
- Make sure you're in the repository root directory
- Check that scripts have execute permissions:
chmod +x scripts/*.sh
-
"No wallet configured" error
- Ensure lcli has access to a wallet:
lcli address - Create a wallet if needed:
lcli create-wallet
- Ensure lcli has access to a wallet:
-
"Insufficient funds" for transactions
- Check balance:
lcli balance - Media publishing requires ions for bytehours
- Check balance:
-
DappStore shows no dapps
- Verify DappStore address is correct
- Check if dapp is approved:
lcli eth-call --to [STORE] --data "0x821b99ba[DAPP_PADDED]" - Ensure wallet is connected to correct network
Examples
TestDapp.sol- Minimal dapp implementationtest.html/test.js- Simple dapp frontendDappStore.sol- Full dapp registry implementation