TELA-MOD-1: Modular Smart Contract Extensions
Extend Without Bloat: TELA-MOD-1 provides predefined DVM modules that add functionality to INDEX contracts while keeping the base contract small and efficient.
What Is TELA-MOD-1?
TELA-MOD-1 provides a set of predefined DVM (opens in a new tab) modules that can be embedded into TELA-INDEX-1 smart contracts to extend their functionality. These modules help keep the base smart contract small and efficient while allowing developers to add features as needed.
Key Features
- 🎯 Modular Design - Add only the features you need
- 🔒 Validated Code - TELA ensures MOD consistency and standards
- 📦 Size Efficient - Keep base contracts small, add features selectively
- 🔄 Flexible Updates - Add/remove MODs when installing or updating
- ✅ Standard API - Consistent interface across all MODs
How MODs Work
Base TELA-INDEX-1 Contract
↓
+ TELA-MOD-1 (Variable Storage)
+ TELA-MOD-1 (DERO Transfers)
+ TELA-MOD-1 (Transfer Ownership)
↓
Enhanced INDEX with Extended FeaturesBest Practice: Use TELA-CLI to enable MODs - it automates the process and prevents errors during installation or updates.
MOD Structure
Each MOD consists of:
| Component | Description |
|---|---|
| Name | Descriptive name of the MOD |
| Tag | Short identifier (e.g., vsoo, txdwd) |
| Description | What the MOD does |
| Function Code | DVM function code for the MOD |
| Function Names | Names of functions within the code |
MOD Classes
MODs are organized into classes based on their utility. Each MODClass defines:
| Component | Description |
|---|---|
| Name | Name highlighting the utility |
| Tag | Short identifier for the class |
| MODs | All MODs that can be enabled |
| Rules | Class-specific rules to prevent conflicts |
Available MOD Classes
| Class Name | Tag | Rules | Purpose |
|---|---|---|---|
| Variable Store | vs | Single MOD | Store arbitrary data in contracts |
| Transfers | tx | Multi MOD | Handle DERO, assets, and ownership |
Class Rules
| Rule Name | Description |
|---|---|
| Single MOD | Only one MOD from this class can be used at a time |
| Multi MOD | Multiple MODs from the same class can be used simultaneously |
MOD Tags
MODs are identified by their tags, formatted as tag1,tag2,tag3. The MODClass tag defines the prefix for all member tags.
Examples:
- Variable Store MODs:
vsoo,vspubsu,vspubow - Transfer MODs:
txdwd,txdwa,txto
Tag Validation
import "github.com/civilware/tela"
// Validate MOD combination
tags, err := tela.Mods.TagsAreValid("vsoo,txdwd")
if err != nil {
// Returns conflict as an error
}Using MODs in INDEX
index := &tela.INDEX{
DURL: "myapp.tela",
Mods: "vsoo,txdwd,txto", // Variable storage + DERO + Ownership
DOCs: []string{"doc1-scid", "doc2-scid"},
Headers: tela.Headers{
NameHdr: "My Enhanced App",
},
}Variable Store MODs
The Variable Store MODClass focuses on storing arbitrary data in TELA smart contracts.
Variable Prefixes
Variables are prefixed to avoid conflicts:
| Prefix | Used For | Example |
|---|---|---|
var_ | Owner-stored variables | var_myKey |
var_deto1qy... | User-stored variables | var_deto1qyre...myKey |
ivar_ | Owner immutable variables | ivar_myKey |
ivar_deto1qy... | User immutable variables | ivar_deto1qyre...myKey |
Standard Variable Conventions
TELA defines standard variable keys for universal interpretation:
Owner Notes
| Key | Value Type | Usage | Examples |
|---|---|---|---|
var_owners_note | String | Commentary from owner | "Deprecated", "Offline", "Important update" |
Header Variables (Updatable)
Based on ART-NFA header standard (opens in a new tab):
| Key | Value Type | Usage | Examples |
|---|---|---|---|
var_header_name | String | Application name | "My TELA App" |
var_header_description | String | App description | "A decentralized tool for..." |
var_header_icon | String | Icon URL or SCID | "https://...", "scid..." |
Metadata Variables
Custom metadata with var_meta_ prefix:
| Key | Value Type | Usage | Examples |
|---|---|---|---|
var_meta_category | String | Primary category | "Productivity", "Game", "Development" |
var_meta_group | String | Group within category | "RPG", "FPS", "Adventure" |
var_meta_subgroup | String | Specific subcategory | "Open World", "Multiplayer" |
var_meta_tags | String | Searchable tags | "#TELA", "#DERO #Privacy" |
Variable Store API
All Variable Store MODs use a common API for operations.
Get Variable
Retrieve variables from the smart contract:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetSC",
"params": {
"scid": "your-index-scid",
"code": false,
"variables": false,
"keysstring": ["var_myKey", "var_header_name"]
}
}'Response:
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"valuesstring": ["myValue", "My App Name"],
"status": "OK"
}
}Set Variable
1. Get Gas Estimate:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetGasEstimate",
"params": {
"transfers": [],
"signer": "deto1qyre7td6x9r88y4cavdgpv6k7lvx6j39lfsx420hpvh3ydpcrtxrxqg8v8e3z",
"sc_rpc": [
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
},
{
"name": "entrypoint",
"datatype": "S",
"value": "SetVar"
},
{
"name": "k",
"datatype": "S",
"value": "myKey"
},
{
"name": "v",
"datatype": "S",
"value": "myValue"
}
]
}
}'2. Execute Transaction:
curl -X POST http://127.0.0.1:30001/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "0",
"method": "Transfer",
"params": {
"ringsize": 2,
"fees": 120,
"sc_rpc": [
{
"name": "entrypoint",
"datatype": "S",
"value": "SetVar"
},
{
"name": "k",
"datatype": "S",
"value": "myKey"
},
{
"name": "v",
"datatype": "S",
"value": "myValue"
},
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
}
]
}
}'Delete Variable
1. Get Gas Estimate:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetGasEstimate",
"params": {
"transfers": [],
"signer": "deto1qyre7td6x9r88y4cavdgpv6k7lvx6j39lfsx420hpvh3ydpcrtxrxqg8v8e3z",
"sc_rpc": [
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
},
{
"name": "entrypoint",
"datatype": "S",
"value": "DeleteVar"
},
{
"name": "k",
"datatype": "S",
"value": "myKey"
}
]
}
}'2. Execute Transaction:
curl -X POST http://127.0.0.1:30001/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "0",
"method": "Transfer",
"params": {
"ringsize": 2,
"fees": 100,
"sc_rpc": [
{
"name": "entrypoint",
"datatype": "S",
"value": "DeleteVar"
},
{
"name": "k",
"datatype": "S",
"value": "myKey"
},
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
}
]
}
}'Important: SetVar/DeleteVar operations do NOT create new commit versions. Use these for dynamic content. Use UpdateCode to create new versions for code changes.
Variable Store MOD Variants
Owner Only (vsoo)
Use Case: Only the contract owner can set and delete variables.
Best For:
- Application configuration
- Admin settings
- Deployment notes
- Owner-controlled metadata
Example:
index := &tela.INDEX{
DURL: "admin-panel.tela",
Mods: "vsoo", // Owner-only variable storage
// ... rest of config
}Owner Only Immutable (vsooim)
Use Case: Owner can set variables that cannot be changed or deleted.
Best For:
- Permanent records
- Immutable configuration
- Historical data
- Audit trails
Characteristics:
- Owner can SET variables
- Nobody (including owner) can DELETE or MODIFY
- Perfect for permanent records
Public Single Use (vspubsu)
Use Case: All wallets can store variables once, owner can manage all variables.
Best For:
- User registrations
- One-time submissions
- Voting systems
- Permanent user data
Permissions:
- Users: Can set variables once (cannot overwrite)
- Owner: Can set and delete all variables
Public Overwrite (vspubow)
Use Case: All wallets can store and overwrite their own variables.
Best For:
- User preferences
- Profile data
- Dynamic user content
- Editable submissions
Permissions:
- Users: Can set and overwrite their own variables
- Owner: Can set and delete all variables
Public Immutable (vspubim)
Use Case: All wallets can store variables that cannot be changed or deleted.
Best For:
- Permanent user contributions
- Immutable records
- Timestamp proofs
- Permanent attestations
Permissions:
- Users: Can set variables (once, permanently)
- Nobody: Can modify or delete
Transfer MODs
The Transfer MODClass handles DERO, assets, and ownership transfers.
Deposit/Withdraw DERO (txdwd)
Use Case: Accept DERO deposits and allow owner to withdraw.
Deposit DERO
1. Get Gas Estimate:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetGasEstimate",
"params": {
"transfers": [
{
"destination": "your-index-scid",
"burn": 10000
}
],
"signer": "deto1qyre7td6x9r88y4cavdgpv6k7lvx6j39lfsx420hpvh3ydpcrtxrxqg8v8e3z",
"sc_rpc": [
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
},
{
"name": "entrypoint",
"datatype": "S",
"value": "DepositDero"
}
]
}
}'2. Execute Transaction:
curl -X POST http://127.0.0.1:30001/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "0",
"method": "Transfer",
"params": {
"transfers": [
{
"destination": "your-index-scid",
"burn": 10000
}
],
"ringsize": 2,
"fees": 90,
"sc_rpc": [
{
"name": "entrypoint",
"datatype": "S",
"value": "DepositDero"
},
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
}
]
}
}'Withdraw DERO (Owner Only)
1. Get Gas Estimate:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetGasEstimate",
"params": {
"transfers": [],
"signer": "deto1qyre7td6x9r88y4cavdgpv6k7lvx6j39lfsx420hpvh3ydpcrtxrxqg8v8e3z",
"sc_rpc": [
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
},
{
"name": "entrypoint",
"datatype": "S",
"value": "WithdrawDero"
},
{
"name": "amt",
"datatype": "U",
"value": 100
}
]
}
}'2. Execute Transaction:
curl -X POST http://127.0.0.1:30001/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "0",
"method": "Transfer",
"params": {
"transfers": [],
"ringsize": 2,
"fees": 100,
"sc_rpc": [
{
"name": "entrypoint",
"datatype": "S",
"value": "WithdrawDero"
},
{
"name": "amt",
"datatype": "U",
"value": 100
},
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
}
]
}
}'Deposit/Withdraw Assets (txdwa)
Use Case: Accept asset deposits and allow owner to withdraw.
Deposit Asset
1. Get Gas Estimate:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetGasEstimate",
"params": {
"transfers": [
{
"scid": "asset-scid-here",
"burn": 10000
}
],
"signer": "deto1qyre7td6x9r88y4cavdgpv6k7lvx6j39lfsx420hpvh3ydpcrtxrxqg8v8e3z",
"sc_rpc": [
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
},
{
"name": "entrypoint",
"datatype": "S",
"value": "DepositAsset"
},
{
"name": "scid",
"datatype": "S",
"value": "asset-scid-here"
}
]
}
}'2. Execute Transaction:
curl -X POST http://127.0.0.1:30001/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "0",
"method": "Transfer",
"params": {
"transfers": [
{
"scid": "asset-scid-here",
"burn": 10000
}
],
"ringsize": 2,
"fees": 170,
"sc_rpc": [
{
"name": "entrypoint",
"datatype": "S",
"value": "DepositAsset"
},
{
"name": "scid",
"datatype": "S",
"value": "asset-scid-here"
},
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
}
]
}
}'Withdraw Asset (Owner Only)
1. Get Gas Estimate:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetGasEstimate",
"params": {
"signer": "deto1qyre7td6x9r88y4cavdgpv6k7lvx6j39lfsx420hpvh3ydpcrtxrxqg8v8e3z",
"sc_rpc": [
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
},
{
"name": "entrypoint",
"datatype": "S",
"value": "WithdrawAsset"
},
{
"name": "scid",
"datatype": "S",
"value": "asset-scid-here"
},
{
"name": "amt",
"datatype": "U",
"value": 100
}
]
}
}'2. Execute Transaction:
curl -X POST http://127.0.0.1:30001/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "0",
"method": "Transfer",
"params": {
"transfers": [],
"ringsize": 2,
"fees": 180,
"sc_rpc": [
{
"name": "entrypoint",
"datatype": "S",
"value": "WithdrawAsset"
},
{
"name": "scid",
"datatype": "S",
"value": "asset-scid-here"
},
{
"name": "amt",
"datatype": "U",
"value": 100
},
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
}
]
}
}'Transfer Ownership (txto)
Use Case: Transfer smart contract ownership to another wallet.
Transfer Ownership (Current Owner)
1. Get Gas Estimate:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetGasEstimate",
"params": {
"transfers": [],
"signer": "deto1qyre7td6x9r88y4cavdgpv6k7lvx6j39lfsx420hpvh3ydpcrtxrxqg8v8e3z",
"sc_rpc": [
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
},
{
"name": "entrypoint",
"datatype": "S",
"value": "TransferOwnership"
},
{
"name": "addr",
"datatype": "S",
"value": "new-owner-address"
}
]
}
}'2. Execute Transaction:
curl -X POST http://127.0.0.1:30001/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "0",
"method": "Transfer",
"params": {
"ringsize": 2,
"fees": 240,
"sc_rpc": [
{
"name": "entrypoint",
"datatype": "S",
"value": "TransferOwnership"
},
{
"name": "addr",
"datatype": "S",
"value": "new-owner-address"
},
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
}
]
}
}'Claim Ownership (New Owner)
1. Get Gas Estimate:
curl -X POST http://127.0.0.1:20000/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "DERO.GetGasEstimate",
"params": {
"transfers": [],
"signer": "new-owner-address",
"sc_rpc": [
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
},
{
"name": "entrypoint",
"datatype": "S",
"value": "ClaimOwnership"
}
]
}
}'2. Execute Transaction:
curl -X POST http://127.0.0.1:30001/json_rpc \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "0",
"method": "Transfer",
"params": {
"ringsize": 2,
"fees": 170,
"sc_rpc": [
{
"name": "entrypoint",
"datatype": "S",
"value": "ClaimOwnership"
},
{
"name": "SC_ACTION",
"datatype": "U",
"value": 0
},
{
"name": "SC_ID",
"datatype": "H",
"value": "your-index-scid"
}
]
}
}'Using MODs with TELA-CLI
TELA-CLI automates MOD management during installation and updates.
Install INDEX with MODs
# Start TELA-CLI
tela-cli
# Connect to network
endpoint simulator
# Connect wallet
wallet ./your-wallet.db
# Install INDEX with MODs
install-index
# Follow prompts:
# - Enter INDEX name
# - Enter description
# - Enter dURL
# - Add DOC SCIDs
# - Select MODs: vsoo,txdwd,txtoUpdate INDEX MODs
# Update existing INDEX
update-index your-index-scid
# Follow prompts to:
# - Add new MODs
# - Remove existing MODs
# - Update DOC referencesGo Package API
Access MODs
import "github.com/civilware/tela"
// Get all available MODs
allMods := tela.Mods.GetAllMods()
// Get specific MOD
mod := tela.Mods.GetMod("vsoo")
// Get MOD functions
code, funcNames := tela.Mods.Functions("vsoo")
// Get all MOD classes
classes := tela.Mods.GetAllClasses()
// Get class for a MOD
class := tela.Mods.GetClass("vsoo")
// Validate MOD combination
tags, err := tela.Mods.TagsAreValid("vsoo,txdwd")
// Inject MODs into template
finalTags, finalTemplate, err := tela.Mods.InjectMODs("vsoo,txdwd", tela.TELA_INDEX_1)List All MODs
import (
"fmt"
"github.com/civilware/tela"
)
func main() {
for _, mod := range tela.Mods.GetAllMods() {
fmt.Println()
fmt.Printf("Name: %s\n", mod.Name)
fmt.Printf("Tag: %s\n", mod.Tag)
fmt.Printf("Description: %s\n", mod.Description)
fmt.Println()
fmt.Println(mod.FunctionCode())
}
}Adding Custom MODs
Developers can add custom MODs to the civilware/tela package or their own implementations.
Step 1: Create DVM Function
Create a .bas file with your DVM function:
// TELA-MOD-1/nc/TELA-MOD-1-NCONE.bas
Function NewFunction1() Uint64
10 RETURN 0
End FunctionStep 2: Embed the File
In mods.go, embed the new bas file:
//go:embed nc/TELA-MOD-1-NCONE.bas
var TELA_MOD_1_NCONE stringStep 3: Add to initMods()
Create MODClass and MODs, then add to package:
func initMods() {
// Create new class
newClass := MODClass{
Name: "New Class",
Tag: "nc",
Rules: []MODClassRule{Mods.rules[0]}, // Single MOD rule
}
// Create MODs
newMODs := []MOD{
{
Name: "New Class Function 1",
Tag: newClass.NewTag("one"), // Creates "ncone"
Description: "The NewFunction1 function returns 0",
FunctionCode: func() string { return TELA_MOD_1_NCONE },
FunctionNames: []string{"NewFunction1"},
},
}
// Add to package
err := Mods.Add(newClass, newMODs)
if err != nil {
// Handle error
}
}Step 4: Access the New MOD
// Get the new MOD
mod := tela.Mods.GetMod("ncone")
// Get the class
class := tela.Mods.GetClass("nc")Best Practices
MOD Selection Guidelines
- Start Simple - Begin with minimal MODs, add more as needed
- Understand Rules - Respect Single MOD and Multi MOD class rules
- Validate Tags - Always validate MOD combinations before deployment
- Document Usage - Note which MODs your app uses for future reference
- Test Thoroughly - Test MOD functionality on simulator before mainnet
Common Patterns
Basic App (Owner-Managed):
Mods: "vsoo" // Owner-only variable storageCommunity App (Public Contributions):
Mods: "vspubow" // Public can contribute and editFinance App (DERO Handling):
Mods: "vsoo,txdwd" // Variables + DERO deposits/withdrawalsAdvanced App (Full Features):
Mods: "vsoo,txdwd,txdwa,txto" // All features enabledRelated Documentation
MOD Power Unlocked: You now understand how to extend TELA applications with modular functionality while keeping contracts efficient and maintainable!