For the complete documentation index, see llms.txt. This page is also available as Markdown.

Running your dApp

You have two commands for running a payload. They take the same payload — a code string, or --file, with input via --input / --input-text — so you move from one to the other without rewriting anything.

Command
Where it runs
Costs gas?
Answers

ecld-test

locally, in the enclave's own executor

no

Does my call work? — function names, arguments, result wiring

ecld-run

on the network, on the enclave you published

yes (needs a funded key)

Does it work on the network, on my published enclave?

Start with ecld-test — it is instant and free, and catches almost every mistake. Reach for ecld-run once the call is correct and you want a real end-to-end run.

Test locally — ecld-test

Runs your payload with the same executor that is baked into the securelock enclave: same backend reflection, same ___etny_result___ / ___etny_data_set___ scope, same task-status codes. No SGX, no gas, no wallet.

ecld-test 'hello("World")'
ecld-test --file payload.py
ecld-test --input data.json 'process(___etny_data_set___)'

(In the JavaScript SDK, prefix with npx: npx ecld-test 'hello("World")'.)

Exit code is 0 on SUCCESS, 1 otherwise, so it drops straight into CI.

ESR is emulated locally, on by default

If your dApp uses the Enclave State Registry, ecld-test emulates it in-process: StateRegistry get/commit, the ownership/ACL API, and task_caller() all behave exactly as they do on-chain, against an in-memory registry and store — zero orders, zero gas. State persists between runs in .ecld-esr-local.*.json, so a counter advances across invocations just like real state:

ecld-test 'esr_increment()'   # -> before {}      after {"n": 1}  version 1
ecld-test 'esr_increment()'   # -> before {"n":1} after {"n": 2}  version 2

The task caller (the data-owner address the trustedzone attests on the real network) defaults to your developer address and is set for every task. Override it to test the ACL from another identity:

ecld-test --caller 0xabc...def 'esr_increment()'   # a stranger -> denied if not granted

Drive your real integration — ecld-test serve

Starts a local API that speaks the same protocol as the network. Point your runner at LOCAL mode and every run() executes against this API instead of the blockchain — so you exercise your actual frontend/runner integration end to end, still with no gas.

Run on the network — ecld-run

Submits the payload to the network and prints the decrypted result. It drives the full path — encrypt → IPFS → on-chain request → wait for a node → download and decrypt — and costs gas, so it needs a funded key.

Network and enclaves are read from your project config, exactly as ecld-publish wired them:

  • networkBLOCKCHAIN_NETWORK (e.g. Bloxberg_Testnet)

  • securelockPROJECT_NAME

  • trustedzoneTRUSTED_ZONE_IMAGE

Override any of them with --network, --securelock, --trustedzone.

The signing key pays for the order:

  • PythonECLD_PRIVATE_KEY (a plaintext 0x key), or the encrypted ENC_PRIVATE_KEY unlocked with ECLD_KEY_PASSWORD (or an interactive prompt).

  • JavaScriptPRIVATE_KEY (or ECLD_PRIVATE_KEY), a funded 0x key.

Tune the task resources with --task-price, --cpu, --memory, --storage, --bandwidth, --duration, --validators. Other flags: --node <addr> to target a specific operator, --ipfs <url>, --timeout <seconds>, --json.

Exit code is 0 on a SUCCESS task result, and 1 on a runner error, a timeout, or a non-zero enclave task code — so a failed run is never mistaken for a pass.

ESR state is enclave-private: a client cannot decrypt it. Anything the caller should see must be returned explicitly by the payload — which is the intended pattern. ecld-run --json shows the full result envelope, including the esr attachment metadata when present.

Next: give your dApp durable state in Managing dApp State (ESR)ecld-test emulates it locally by default — and confirm what actually landed on-chain with Inspecting your dApp. New to the toolchain? Start at Environment Prerequisites.

Last updated