Advanced Features
TELA-MOD-1 Extensions

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 Features

Best Practice: Use TELA-CLI to enable MODs - it automates the process and prevents errors during installation or updates.


MOD Structure

Each MOD consists of:

ComponentDescription
NameDescriptive name of the MOD
TagShort identifier (e.g., vsoo, txdwd)
DescriptionWhat the MOD does
Function CodeDVM function code for the MOD
Function NamesNames of functions within the code

MOD Classes

MODs are organized into classes based on their utility. Each MODClass defines:

ComponentDescription
NameName highlighting the utility
TagShort identifier for the class
MODsAll MODs that can be enabled
RulesClass-specific rules to prevent conflicts

Available MOD Classes

Class NameTagRulesPurpose
Variable StorevsSingle MODStore arbitrary data in contracts
TransferstxMulti MODHandle DERO, assets, and ownership

Class Rules

Rule NameDescription
Single MODOnly one MOD from this class can be used at a time
Multi MODMultiple 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:

PrefixUsed ForExample
var_Owner-stored variablesvar_myKey
var_deto1qy...User-stored variablesvar_deto1qyre...myKey
ivar_Owner immutable variablesivar_myKey
ivar_deto1qy...User immutable variablesivar_deto1qyre...myKey

Standard Variable Conventions

TELA defines standard variable keys for universal interpretation:

Owner Notes

KeyValue TypeUsageExamples
var_owners_noteStringCommentary from owner"Deprecated", "Offline", "Important update"

Header Variables (Updatable)

Based on ART-NFA header standard (opens in a new tab):

KeyValue TypeUsageExamples
var_header_nameStringApplication name"My TELA App"
var_header_descriptionStringApp description"A decentralized tool for..."
var_header_iconStringIcon URL or SCID"https://...", "scid..."

Metadata Variables

Custom metadata with var_meta_ prefix:

KeyValue TypeUsageExamples
var_meta_categoryStringPrimary category"Productivity", "Game", "Development"
var_meta_groupStringGroup within category"RPG", "FPS", "Adventure"
var_meta_subgroupStringSpecific subcategory"Open World", "Multiplayer"
var_meta_tagsStringSearchable 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,txto

Update INDEX MODs

# Update existing INDEX
update-index your-index-scid
 
# Follow prompts to:
# - Add new MODs
# - Remove existing MODs
# - Update DOC references

Go 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 Function

Step 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 string

Step 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

  1. Start Simple - Begin with minimal MODs, add more as needed
  2. Understand Rules - Respect Single MOD and Multi MOD class rules
  3. Validate Tags - Always validate MOD combinations before deployment
  4. Document Usage - Note which MODs your app uses for future reference
  5. Test Thoroughly - Test MOD functionality on simulator before mainnet

Common Patterns

Basic App (Owner-Managed):

Mods: "vsoo"  // Owner-only variable storage

Community App (Public Contributions):

Mods: "vspubow"  // Public can contribute and edit

Finance App (DERO Handling):

Mods: "vsoo,txdwd"  // Variables + DERO deposits/withdrawals

Advanced App (Full Features):

Mods: "vsoo,txdwd,txdwa,txto"  // All features enabled

Related Documentation


🎉

MOD Power Unlocked: You now understand how to extend TELA applications with modular functionality while keeping contracts efficient and maintainable!