Skip to main content

Network Execution

Every real on-chain broadcast under Self-Custody — a Settlement's ExecutionLegs, a Withdrawal, or a PayoutBatch — consumes real network resources (e.g. TRON Energy/Bandwidth). This cost is tracked and charged completely separately from the Platform Fee: the Platform Fee is the platform's own commercial fee on a Settlement (see Fee and Pricing Policy); the Network Execution Fee is what it actually costs to get bytes broadcast on-chain. Never assume one number includes the other.

Two sources for the resource: CUSTOMER_RESOURCES vs ISHTARAN_RESOURCES

Every Organization has a resourcePreference per AssetNetwork, controlling whose on-chain resources actually pay for a broadcast:

ISHTARAN_RESOURCES (the default)

The platform supplies the physical network resource for you. You cover the cost economically — what you're charged (totalCharged, in quoteCurrency) can include, beyond the raw network cost: a replenishment/acquisition component and Ishtaran's own margin (the markup for sponsoring the resource). NetworkExecutionFee is not a pure pass-through in this mode — don't assume the charged amount equals the raw network cost.

CUSTOMER_RESOURCES (SELF)

You supply your own on-chain resources instead. In this mode:

  • Ishtaran's margin is always 0.
  • There is no replenishment/swap component charged by Ishtaran either.
  • If your registered resources are insufficient for a given execution, it fails closed — there is no silent fallback to ISHTARAN_RESOURCES, unless you've explicitly opted into allowFallbackToIshtaranResources when setting the preference (see below).

Switching between the two, and controlling fallback, is one call: networkCostPayerAccounts.updateResourcePreference(organizationId, assetNetworkId, resourcePreference, allowFallbackToIshtaranResources) — see each SDK's CORE_API.md § Network Execution Engine for the exact signature.

Two registrations, two different things

Getting Self-Custody execution working the first time requires two separate registrations, easy to confuse because both involve "paying for network cost":

  • ExecutionSource — the address ExecutionCustody signs FROM to pay network cost, and (in CUSTOMER_RESOURCES mode) the address whose on-chain resource capacity is checked. Registered via executionSources.register(...); its available capacity is declared/re-synced via executionSources.syncResourceStake(...) (self-reported, no on-chain verification in this version).
  • NetworkCostPayerAccount — the Ledger Account debited for the charged cost (totalCharged, in quoteCurrency) once a quote is authorized. Registered via networkCostPayerAccounts.register(organizationId, assetNetworkId, accountId).

Don't confuse either of these with ExecutionDestination — a completely different concept: the address a beneficiary receives funds at (see Self-Custody).

Also don't confuse NetworkCostPayerAccount with the platform's own NetworkResourceReserve: that's Ishtaran's internal operational reserve backing ISHTARAN_RESOURCES mode — it is not something you register, fund, or query as an integrator, and CUSTOMER_RESOURCES mode never draws on it. There is no public integrator-facing route for it; if you see /v1/admin/... routes mentioning it in the API reference, those are Platform Owner operations, not part of your integration.

First funding

Before your first real execution in CUSTOMER_RESOURCES mode (or before your NetworkCostPayerAccount has enough balance in either mode), the platform will refuse to execute rather than fail partway through a broadcast: you get an explicit error (NETWORK_EXECUTION_FEE_INSUFFICIENT_BALANCE, see Errors), not a silent retry or a partial state.

The fix is always the same regardless of mode: make a normal Deposit into the relevant Account (a plain on-chain deposit like any other), wait for it to confirm, and retry. There's no separate "top-up" flow — funding an Account used for Network Execution costs works exactly like funding any other Account on the platform.

Routes