OptionalassetThe asset group index within that genesis transaction.
The asset's genesis transaction id, 32 bytes, in CANONICAL order — exactly the leading 32 bytes of a serialized Asset ID, no flip.
The covenant reverses it internally because the introspection opcodes match wire order; callers never do that themselves, and a caller who pre-reverses gets a contract that is unspendable on its covenant leaves with nothing in the error naming why.
OptionalnonThe emulator covenant leaves, ALL OR NOTHING. Present, this adds the three non-interactive leaves the emulator co-signs under a covenant pinning the payout to a pre-committed destination:
nonInteractiveClaim: server + a covenant-tweaked emulator
co-signer, paying receiverPkScript — the receiver's claim can
be pushed without the receiver being online.nonInteractiveRefund: server + receiver + a covenant-tweaked
emulator co-signer, paying senderPkScript, no timelock — lets
server and receiver release the refund the moment they agree the
swap has failed, and recoverable even if the sender's own key is
lost, since no OTHER refund-side leaf survives that.nonInteractiveRefundWithoutReceiver: server + the SAME
covenant-tweaked co-signer as nonInteractiveRefund, paying
senderPkScript after refundLocktime — the only refund tier
needing no participant signature at all, so a sender who funded
a lockup and vanished is refundable through it alone.WHY ONE FLAG AND NOT A SWITCH PER LEAF. The three are one mechanism
— the same emulator key, the same enforcePayTo covenant pointed
at a per-role destination — and they protect opposite directions of
the same swap, so no real configuration wants a subset. A subset
would cost, not buy: every optional leaf multiplies the tree shapes
a counterparty must derive to verify an address (nothing on the
wire says which leaves a quote carries), so per-leaf toggling turns
one address comparison into a combinatorial guess. All-or-nothing
keeps the shape count at two: suite, or no suite.
Leaf order fixes the taproot merkle root, so the suite is appended after the six signature leaves in a fixed order (claim, refund, timelocked refund) and a script built with this option NEVER collides with one built without it — which is what makes "did this quote opt in" a question an address comparison answers.
STABLE PER RELEASE: what this option builds does not change within a published SDK version. A future covenant leaf joins the suite only behind a NEW option, so re-deriving a lockup with the SDK that quoted it reproduces its address byte-for-byte.
The emulator service's public key, 32-byte x-only or 33-byte compressed. ONE key, tweaked per covenant destination, becomes the co-signer of every leaf in the suite — the leaves share it structurally, and BIP-341 tapscript sighashes committing to the tapleaf hash are what keep a signature for one leaf from replaying against another.
Optionallegacy?: "preTimelockedRefund"LEGACY REBUILD ONLY — never for a new lockup.
"preTimelockedRefund" builds the suite WITHOUT its timelocked
refund leaf: the shape every emulator-covenant lockup funded
before that leaf shipped carries. Lockups already funded in that
shape keep it permanently — a leaf cannot be retrofitted onto an
address already committed — so re-deriving such a lockup (to
spend it, or to verify an old quote's address) needs this. A new
lockup that omits the leaf gives up the one refund tier needing
nobody, for nothing.
Where the claim covenant pays: the receiver's own P2TR pkScript, 34 bytes.
Where BOTH refund covenants pay: the sender's own P2TR pkScript, 34 bytes. One destination shared by both refund leaves, so they cannot diverge on where a refund goes.
Optional: denominate this contract in an Arkade ASSET rather than in sats alone.
Only the two NON-INTERACTIVE leaves change. Every other leaf is a signature path that asserts nothing about value, so an asset makes no difference to them — which is why this option reaches exactly the leaves whose covenant the emulator enforces.
When set, those covenants additionally require the output to carry at least the input's amount of THIS asset, and to carry exactly one asset. The sat clause is RETAINED, not replaced: an asset-carrying VTXO carries sats too, so dropping it would let a spend satisfy the asset covenant while stripping the sats — exactly as the sat-only covenant lets a spend strip the asset.
ONE ASSET IS BOUND, AND ONLY THAT ONE IS PROTECTED. If a VTXO funded to this contract carries ADDITIONAL assets alongside the bound one, those are not covered: whoever assembles a covenant spend chooses where they go, and can send them anywhere.
INSPECTOUTASSETCOUNT == 1does not close that. It constrains the covenant's OUTPUT to exactly one asset — so the extras cannot ride along with the bound asset — but arkd's conservation rule is satisfied by routing them to a different output, which the covenant says nothing about. The bound asset arrives; the rest is the spender's to direct.So fund an asset contract with the asset it names and nothing else. A multi-asset VTXO behind this covenant is a loss waiting for whoever pushes the spend.
The id is the pair the introspection opcodes take. A canonical Asset ID is
(genesis txid, group index), never a single blob.