From 99dacdfd75c1f2b86d57f9f93c2a9230ab3dc29a Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Thu, 7 May 2026 12:39:56 +0300 Subject: [PATCH 1/6] wallet abi: add first draft version --- elip-wallet-abi.mediawiki | 1195 +++++++++++++++++ .../01_request_wallet_to_script.json | 51 + .../02_response_ok_build_only.json | 35 + .../03_response_error_funding.json | 16 + .../04_request_simf_bip0341_issuance.json | 154 +++ elip-wallet-abi/field-reference.json | 254 ++++ .../wallet-abi-tx-create.schema.json | 974 ++++++++++++++ 7 files changed, 2679 insertions(+) create mode 100644 elip-wallet-abi.mediawiki create mode 100644 elip-wallet-abi/01_request_wallet_to_script.json create mode 100644 elip-wallet-abi/02_response_ok_build_only.json create mode 100644 elip-wallet-abi/03_response_error_funding.json create mode 100644 elip-wallet-abi/04_request_simf_bip0341_issuance.json create mode 100644 elip-wallet-abi/field-reference.json create mode 100644 elip-wallet-abi/wallet-abi-tx-create.schema.json diff --git a/elip-wallet-abi.mediawiki b/elip-wallet-abi.mediawiki new file mode 100644 index 0000000..ab1e9fc --- /dev/null +++ b/elip-wallet-abi.mediawiki @@ -0,0 +1,1195 @@ +
+  ELIP: ?
+  Layer: Wallet
+  Title: Wallet ABI Transaction Create Protocol
+  Author: Kyrylo Riabov
+          Artem Chystiakov
+  Comments-Summary: No comments yet.
+  Comments-URI: TBD
+  Status: Draft
+  Type: Standards Track
+  Created: 2026-05-07
+  License: BSD-3-Clause
+
+ +== Introduction == + +=== Abstract === + +wallet-abi-0.1 defines a JSON request/response protocol for transaction construction. The caller declares +intended inputs, outputs, fee hints, locktime hints, issuance metadata, and finalization rules. The wallet/runtime +validates the request against its active BIP-122/CAIP-2 chain identifier and wallet state, opens a request-scoped +wallet snapshot, resolves wallet-owned and caller-provided prevouts, materializes declared outputs, appends fee/change +outputs as needed, signs/finalizes inputs, optionally broadcasts, and returns either a finalized transaction or a structured error. + +The protocol is '''state-aware and non-idempotent'''. The same request may yield different successful transactions +when wallet state, fee policy, UTXO availability, or broadcast state changes. For a single runtime request lifecycle, +however, the runtime should use a stable wallet snapshot and deterministic output allocation so fee estimation and +final build are internally consistent. + +=== Copyright === + +This document is licensed under the 3-clause BSD license. + +=== Motivation === + +Applications need a standard way to ask a wallet to construct and sign a transaction from an application-level intent +while keeping wallet-owned UTXOs inside the wallet. This protocol provides a signing capability to the requester, +but the wallet NEVER shares its UTXO set, balances, or wallet-internal selection state with the requester to facilitate the signing. + +=== Goals and non-goals === + +==== Goals ==== + +# Provide a reviewable definition of all request and response fields. +# Make the user experience clear enough for wallet UI design. +# Make non-idempotency and runtime state dependence explicit. +# Use genesis-hash-based BIP-122/CAIP-2-style network identifiers instead of bare network names. +# Provide JSON examples and a review JSON Schema. + +==== Non-goals ==== + +# Define a final WalletConnect, JSON-RPC, or transport-level standard. This document describes the ABI payload. +# Define full SimplicityHL semantic validation. This document describes how the payload is carried and resolved. +# Guarantee exact final transaction shape from declared outputs. The runtime may add fee and change outputs. +# Treat request_id as replay protection. It is correlation only. + +== Specification == + +=== Normative language === + +The words '''MUST''', '''SHOULD''', '''MAY''', and '''MUST NOT''' are used in the [https://www.rfc-editor.org/rfc/rfc2119 RFC 2119] sense for this draft. + +=== Terminology === + +{| class="wikitable" +|- +! Term +! Definition +|- +| Caller / Producer / Dapp +| Web app or protocol app that creates a TxCreateRequest. +|- +| Consumer / runtime +| Wallet/mobile/daemon side that processes the request. +|- +| Wallet snapshot +| Request-scoped view of spendable wallet UTXOs used during fee estimation and final construction. +|- +| Declared input/output +| Input/output explicitly present in params.inputs or params.outputs; the opposite of a runtime-added input/output. +|- +| Runtime-added input/output +| Wallet input, fee output, or change output added by the runtime to satisfy funding/balancing. +|- +| Finalizer +| Rule for producing witness/finalization data or deriving a finalizer-owned input lock. +|- +| SIMF +| SimplicityHL finalization payload carrying source, compiler version, JSON arguments, JSON witness values, and internal key source. +|- +| Internal key source +| Selector that must return a Taproot/BIP340 x-only public key for control-block/script derivation. +|- +| BIP-122 chain id +| A genesis-hash-based chain identifier represented in this ABI as a CAIP-2-style bip122:32-lowercase-hex string. +|- +| Input blinding secret key +| Secret key material used to unblind a confidential prevout. It is not a wallet signing key or spend authorization key. +|- +| Inflation token +| Reissuance token minted by a new issuance. This draft uses inflation_amount_sat for the amount of these token units. +|- +| Static SIMF value +| Caller-known SIMF argument or witness value carried under static_values. Each entry is keyed by a SimplicityHL argument/witness name and encoded as { "value": string, "type": string }. +|- +| Runtime SIMF value +| SIMF argument or witness value that the runtime derives only after wallet state, issuance metadata, selected UTXOs, or the transaction sighash are known. +|- +| App/request identity +| Authenticated context that lets a wallet show which actor initiated the request. This ABI does not define the identity system; it only requires wallets not to trust self-declared JSON labels as identity. +|} + +=== User experience contract === + +==== Caller-side flow ==== + +# The web app builds a transaction intention in terms of wallet inputs, provided inputs, requested outputs, issuance outputs, and finalizers. +# The web app generates a fresh request_id for this user action. +# The web app sends a TxCreateRequest over the chosen transport. +# The web app treats the returned TxCreateResponse as the only authoritative result for this processing attempt. + +==== Wallet/consumer-side review UI ==== + +A wallet UI SHOULD present, before approval: + +{| class="wikitable" +|- +! UI item +! Why it matters +|- +| App/request identity +| Helps the user connect request to the initiating action. +|- +| network +| Prevents Liquid mainnet/testnet/localtest confusion. Show the BIP-122 chain id and, if known, a friendly network label. +|- +| request_id +| Helps support/debug correlation. It should not be described as replay protection. +|- +| broadcast +| Distinguishes "build/sign only" from "publish to network". +|- +| Requested outputs +| Shows labels, assets, amounts, lock type, and blinding mode. +|- +| Runtime-added fee/change +| The declared output set is not the final transaction set. +|- +| Wallet asset deltas +| The user should approve net wallet effect, not just declared outputs. +|- +| Explicit outputs +| Warn when amount/asset confidentiality is disabled. +|- +| Provided input blinding-secret-key use +| Warn because request payload may contain sensitive prevout-unblinding material. +|- +| Issuance/reissuance +| Show minted asset amounts, inflation_amount_sat, confidential-token requirements, and positional input references. +|- +| SIMF/finalizer locks +| Show program identity/hash/source summary, simplicity_hl_version, signer key use, and internal_key source. +|- +| Locktime/sequence +| Warn that lock_time is ineffective when all sequences are final. +|} + +App/request identity is intentionally not a new trusted JSON field in this ABI. A wallet MUST NOT identify +the caller from self-declared labels inside the request payload. The authenticated caller context must come from the +transport or platform binding, for example a browser origin/RP ID, native-app association, pairing session, signed +registry entry, or another out-of-band identity system. This draft only says that such identity is important for UI review; +exact discovery, registry, branding, and anti-phishing UI rules are out of scope for wallet-abi-0.1. + +==== Response UX ==== + +The response is not a deterministic preview of an abstract request. It is the result of a specific processing attempt +against a specific wallet state. On success, the UI should show whether the transaction was merely built or was broadcast. +On error, product logic should branch on error.code, while error.message should be treated as technical context. + +=== Non-idempotency and deterministic boundaries === + +TxCreateRequest.request_id is a correlation identifier and is not replay protection. +Requests are '''not idempotent''', especially when broadcast = true. + +The runtime SHOULD provide deterministic behavior only within this narrower boundary: + +# Open one request-scoped wallet session for one processing lifecycle. +# Use the same spendable_utxos snapshot across fee estimation and final build. +# Return the same wallet output template for the same (session, request) pair. +# Resolve declared inputs in order and update funding state sequentially. + +The same JSON request sent later MAY produce a different transaction because wallet UTXOs, already-spent state, +chain height, fee policy, selected change outputs, and broadcast outcomes can change. + +=== Wire-format rules === + +# Payloads are JSON objects unless a variant is explicitly serialized as a string. +# Enum variants use snake_case. +# TxCreateRequest and RuntimeParams reject unknown fields in the attached Rust schema. +# Numeric satoshi amounts are unsigned 64-bit values. JavaScript callers SHOULD avoid unsafe integer conversion for values above 2^53 - 1. +# Byte-array fields, such as issuance entropy, are serialized as JSON arrays of integers from 0 to 255. +# FinalizerSpec::Simf.arguments and FinalizerSpec::Simf.witness are JSON objects. +# Hex fields are lowercase by convention, but consumers SHOULD accept uppercase only if their underlying parsers do. +# network is a BIP-122/CAIP-2-style chain id string of the form bip122:32-lowercase-hex. +# Secrets, including provided input blinding secret keys and intermediate PSET material, MUST NOT be logged. + +=== Request envelope: TxCreateRequest === + +
{
+  "abi_version": "wallet-abi-0.1",
+  "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
+  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
+  "params": { "inputs": [], "outputs": [] },
+  "broadcast": false
+}
+{| class="wikitable" +|- +! Field +! style="text-align: right;"| Type +! style="text-align: center;"| Required +! Definition +|- +| abi_version +| style="text-align: right;"| string +| style="text-align: center;"| yes +| MUST equal wallet-abi-0.1. Anti-confusion/version guard. +|- +| request_id +| style="text-align: right;"| UUID string +| style="text-align: center;"| yes +| Caller-generated correlation identifier. Generate fresh per user action. Not replay protection. +|- +| network +| style="text-align: right;"| Bip122ChainId +| style="text-align: center;"| yes +| Target Elements/Liquid chain id. MUST match the runtime chain id before side effects. +|- +| params +| style="text-align: right;"| RuntimeParams +| style="text-align: center;"| yes +| Transaction-construction body. +|- +| broadcast +| style="text-align: right;"| boolean +| style="text-align: center;"| yes +| true means publish through wallet broadcaster after finalization. false means build/finalize only; runtime may still sync/fetch. +|} + +==== Bip122ChainId ==== + +network MUST use the [https://standards.chainagnostic.org/CAIPs/caip-2 CAIP-2] / [https://namespaces.chainagnostic.org/bip122/caip2 BIP122 namespace] +wire shape derived from the [https://bips.dev/122/ BIP-122] chain-id concept: + +
bip122:00000000000000000000000000000000
+where genesis-prefix is the first 16 bytes of the chain genesis block hash, encoded as 32 lowercase hex +characters. The runtime MUST derive its active chain id from the active Elements node or equivalent runtime context +and reject a request whose network does not match. + +Known Liquid/Elements examples: + +{| class="wikitable" +|- +! Network +! Full genesis hash +! ABI network value +|- +| Liquid mainnet (liquidv1) +| 1466275836220db2944ca059a3a10ef6fd2ea684b0688d2c379296888a206003 +| bip122:1466275836220db2944ca059a3a10ef6 +|- +| Liquid testnet (liquidtestnet) +| a771da8e52ee6ad581ed1e9a99825e5b3b7992225534eaa2ae23244fe26ab1c1 +| bip122:a771da8e52ee6ad581ed1e9a99825e5b +|- +| Default Elements regtest/localtest +| 00902a6b70c2ca83b5d9c815d96a0e2f4202179316970d14ea1847dae5b1ca21 +| bip122:00902a6b70c2ca83b5d9c815d96a0e2f +|} + +The ABI does not rely on bare strings such as liquid, testnet-liquid, or +localtest-liquid. Implementations MAY display friendly labels, but matching MUST be done against the chain id. + +=== Runtime parameters: RuntimeParams === + +{| class="wikitable" +|- +! Field +! style="text-align: right;"| Type +! style="text-align: center;"| Required +! Definition +|- +| inputs +| style="text-align: right;"| InputSchema[] +| style="text-align: center;"| yes +| Declared inputs, resolved sequentially in declaration order. Runtime may append wallet inputs after declared-input resolution. +|- +| outputs +| style="text-align: right;"| OutputSchema[] +| style="text-align: center;"| yes +| Declared outputs, materialized in declaration order. Runtime may append fee and change outputs. +|- +| fee_rate_sat_kvb +| style="text-align: right;"| number +| style="text-align: center;"| no +| Fee-rate override in sat/kvB. MUST be finite and non-negative. If omitted, runtime policy applies. +|- +| lock_time +| style="text-align: right;"| LockTime +| style="text-align: center;"| no +| Fallback locktime written to PSET global tx data. Effective locktime still depends on input sequences. +|} + +inputs and outputs are request requirements, not a complete transaction template. + +=== Input schema: InputSchema === + +{| class="wikitable" +|- +! Field +! style="text-align: right;"| Type +! style="text-align: center;"| Required +! Definition +|- +| id +| style="text-align: right;"| string +| style="text-align: center;"| yes +| Caller label for diagnostics/UI. +|- +| utxo_source +| style="text-align: right;"| UTXOSource +| style="text-align: center;"| yes +| Prevout source selector. +|- +| unblinding +| style="text-align: right;"| InputUnblinding +| style="text-align: center;"| yes +| How to resolve explicit or confidential prevout values. +|- +| sequence +| style="text-align: right;"| u32 +| style="text-align: center;"| yes +| Input sequence controlling finality, locktime activation, relative locktime, and RBF semantics. +|- +| issuance +| style="text-align: right;"| InputIssuance +| style="text-align: center;"| no +| Issuance/reissuance metadata for this input. Required when outputs reference issuance-derived asset IDs. +|- +| finalizer +| style="text-align: right;"| FinalizerSpec +| style="text-align: center;"| yes +| Input finalization strategy. +|} + +==== UTXOSource ==== + +
{ "wallet": { "filter": { "asset": "none", "amount": "none", "lock": "none" } } }
+
{ "provided": { "outpoint": "0000000000000000000000000000000000000000000000000000000000000000:0" } }
+{| class="wikitable" +|- +! Variant +! Fields +! Definition +|- +| wallet +| filter: WalletSourceFilter +| Runtime selects a wallet UTXO from the request-scoped snapshot. Filters are conjunctive. +|- +| provided +| outpoint +| Caller supplies an outpoint. Runtime fetches prevout and resolves unblinding according to unblinding. +|} + +==== WalletSourceFilter ==== + +{| class="wikitable" +|- +! Field +! Variants +! Definition +|- +| asset +| "none" or {"exact":{"asset_id"}} +| No asset constraint, or exact asset match. +|- +| amount +| "none", {"exact":{"amount_sat"}}, {"min":{"amount_sat"}} +| No amount constraint, exact amount, or minimum amount. +|- +| lock +| "none" or {"script":{"script"}} +| No script constraint, or exact script-pubkey bytes. +|} + +==== InputUnblinding ==== + +{| class="wikitable" +|- +! Variant +! Definition +|- +| "wallet" +| Use wallet-owned descriptor/blinding material. +|- +| {"provided":{"blinding_secret_key":"..."}} +| Use caller-supplied input blinding secret key for a confidential prevout. This is prevout-unblinding material, not a wallet signing key. Sensitive by default; '''never log'''. +|- +| "explicit" +| Require explicit non-confidential prevout values. Confidential prevouts should fail. +|} + +A dapp can provide blinding_secret_key only when it already knows the prevout unblinding material out +of band or the protocol intentionally uses shared/known blinding material. Some Simplicity contract constructions +can work with public or contract-known blinding material; the field is still named after its cryptographic role so +it is not confused with a spend key. Unless local policy explicitly classifies the material as public, the runtime MUST handle it as secret. + +==== InputIssuance ==== + +{| class="wikitable" +|- +! Field +! style="text-align: right;"| Type +! Definition +|- +| kind +| style="text-align: right;"| enum +| One of "new" or "reissue". +|- +| asset_amount_sat +| style="text-align: right;"| u64 +| Amount of issued/reissued asset units to mint. +|- +| inflation_amount_sat +| style="text-align: right;"| u64 +| Amount of reissuance/inflation-token units to mint. Replaces the older token_amount_sat naming to avoid confusing token amount with ordinary asset amount. +|- +| entropy +| style="text-align: right;"| [u8; 32] +| For new, contract-hash entropy; for reissue, already-derived asset entropy. +|} + +Issuance-derived outputs reference inputs by positional input_index. Reordering inputs changes +the derived asset IDs. If a new issuance mints inflation_amount_sat > 0, outputs that carry the derived +inflation token must satisfy the confidentiality rule in [[#AssetVariant|AssetVariant]]. + +=== Output schema: OutputSchema === + +{| class="wikitable" +|- +! Field +! style="text-align: right;"| Type +! style="text-align: center;"| Required +! Definition +|- +| id +| style="text-align: right;"| string +| style="text-align: center;"| yes +| Caller label for diagnostics/UI. +|- +| amount_sat +| style="text-align: right;"| u64 +| style="text-align: center;"| yes +| Requested output amount. +|- +| lock +| style="text-align: right;"| LockVariant +| style="text-align: center;"| yes +| Script-pubkey derivation rule. +|- +| asset +| style="text-align: right;"| AssetVariant +| style="text-align: center;"| yes +| Asset selector. +|- +| blinder +| style="text-align: right;"| BlinderVariant +| style="text-align: center;"| yes +| Output confidentiality policy. +|} + +==== LockVariant ==== + +{| class="wikitable" +|- +! Variant +! Wire shape +! Definition +|- +| wallet +| {"type":"wallet"} +| Use wallet receive output template. +|- +| script +| {"type":"script","script":"0014aabbccddeeff00112233445566778899aabbccdd"} +| Use raw script-pubkey bytes (includes OP_RETURN, burn, etc.). Empty script should be rejected by runtime. +|- +| finalizer +| {"type":"finalizer","finalizer": ...} +| Derive output lock from finalizer/program. +|} + +==== AssetVariant ==== + +{| class="wikitable" +|- +! Variant +! Definition +|- +| asset_id +| Caller-provided asset ID. +|- +| new_issuance_asset +| Asset ID derived from a new issuance input. +|- +| new_issuance_token +| Confidential reissuance/inflation-token ID derived from a new issuance input. +|- +| re_issuance_asset +| Asset ID derived from a reissue input. +|} + +new_issuance_asset and new_issuance_token require params.inputs[input_index].issuance.kind == "new". +re_issuance_asset requires kind == "reissue". + +In this ABI, new_issuance_token denotes the confidential reissuance/inflation-token variant. +Any output whose asset resolves to new_issuance_token MUST be confidential: +the runtime MUST reject blinder = "explicit" for that output. This is required for compatibility with +the current reissuance model on Liquid, where reissuance tokens must remain confidential to be usable; +see [https://github.com/BlockstreamResearch/SimplicityHL/issues/309 SimplicityHL issue #309]. +Explicit reissuance-token support, if added later, belongs in Future Work and would require an ABI/capability update. + +==== BlinderVariant ==== + +{| class="wikitable" +|- +! Variant +! Definition +|- +| "wallet" +| Use wallet output template blinding pubkey. Should be paired with lock.type = "wallet". +|- +| {"provided":{"pubkey":"..."}} +| Use caller-supplied blinding public key. +|- +| "explicit" +| Disable output asset/value confidentiality for this output. +|} + +=== Finalizer specification: FinalizerSpec === + +==== Wallet finalizer ==== + +
{ "type": "wallet" }
+Delegates input finalization to the wallet signer/miniscript stack. + +==== SIMF finalizer ==== + +
{
+  "type": "simf",
+  "source_simf": "...",
+  "simplicity_hl_version": "0.4.2",
+  "internal_key": "bip0341",
+  "arguments": {
+    "static_values": {
+      "CONTRACT_NONCE": { "value": "1", "type": "u32" }
+    },
+    "runtime_arguments": {
+      "COLLATERAL_ASSET_ID": { "new_issuance_asset": { "input_index": 0 } }
+    }
+  },
+  "witness": {
+    "static_values": {
+      "PATH": {
+        "value": "Right(Left((false, 10, 1000)))",
+        "type": "Either(...)"
+      }
+    },
+    "runtime_arguments": [
+      { "sig_hash_all": { "name": "USER_SIGHASH_ALL", "public_key": "73c5da0a4f7b8f2e91cd5f8f0c7a6d5b4c3a291817161514131211100f0e0d0c" } }
+    ]
+  }
+}
+{| class="wikitable" +|- +! Field +! style="text-align: right;"| Type +! style="text-align: center;"| Required +! Definition +|- +| source_simf +| style="text-align: right;"| string +| style="text-align: center;"| yes +| UTF-8 SimplicityHL source loaded and instantiated by runtime. +|- +| simplicity_hl_version +| style="text-align: right;"| string +| style="text-align: center;"| yes +| Exact Cargo/SimplicityHL compiler version that the runtime MUST use for compilation, address derivation, and script derivation. If the runtime cannot compile with this exact version, it MUST reject the request before deriving addresses or finalizing. +|- +| internal_key +| style="text-align: right;"| InternalKeySource +| style="text-align: center;"| yes +| Taproot internal key source. +|- +| arguments +| style="text-align: right;"| SimfArguments JSON object +| style="text-align: center;"| yes +| SIMF argument payload as JSON. Contains caller-known static_values and runtime-resolved runtime_arguments. +|- +| witness +| style="text-align: right;"| SimfWitness JSON object +| style="text-align: center;"| yes +| SIMF witness payload as JSON. Contains caller-known static_values and runtime-resolved runtime_arguments. +|} + +simplicity_hl_version is intentionally part of the wire request because different +[https://github.com/BlockstreamResearch/SimplicityHL SimplicityHL] compiler versions may produce different +compiled programs, CMRs, addresses, script pubkeys, or finalization behavior from the same source_simf. + +A runtime MUST compile source_simf with the requested simplicity_hl_version; +it MUST NOT silently substitute a different compiler version. When a SIMF finalizer is used for an input, the runtime +MUST derive the expected finalizer script pubkey from the explicitly requested SIMF source, version, internal_key, +and finalizer payload. After resolving utxo_source, the runtime MUST verify that the resolved prevout script +pubkey matches that computed script pubkey before signing or finalizing. A mismatch MUST be rejected, because otherwise +the wallet could be tricked into signing a transaction for a UTXO locked by a different program. + +=== Internal key source === + +==== Stable variant: bip0341 ==== + +The only stable InternalKeySource variant in wallet-abi-0.1 is: + +
"bip0341"
+It returns the fixed [https://bips.dev/341/ BIP-0341] NUMS/example x-only internal key: + +
50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0
+This variant is deterministic, portable, and safe as the initial interoperability baseline. + +=== SIMF argument and witness payloads === + +FinalizerSpec::Simf.arguments and FinalizerSpec::Simf.witness are JSON objects +at the ABI wire level. They are not UTF-8 byte arrays in wallet-abi-0.1. + +==== static_values ==== + +static_values carries caller-known values that are already available when the app constructs the request. +A static value is not necessarily derived or finalized by the runtime; it is simply known before the wallet selects UTXOs, +derives issuance IDs, computes a sighash, or signs. + +The shape intentionally follows the SimplicityHL witness-file convention and the underlying +WitnessValues / WitnessNames model: each top-level key is a SimplicityHL argument or +witness name, and each value has two string fields: + +
{
+  "NAME": {
+    "value": "Right(Left((false, 10, 1000)))",
+    "type": "Either(...)"
+  }
+}
+value MUST be encoded as a JSON string, even for numbers and booleans, because the SimplicityHL parser +consumes Rust-like typed literals such as "100", "false", "(true, 376)", +"Left(...)", or "Right(...)". type MUST also be encoded as a JSON string, +for example "u64", "Signature", "(bool, u64)", or "Either(...)". +The runtime MUST treat both fields as untrusted compiler input and rely on the requested simplicity_hl_version +parser/type checker before using them. + +For arguments.static_values, keys are static SimplicityHL argument/parameter names. +For witness.static_values, keys are static SimplicityHL witness names. +The exact accepted names and types are defined by source_simf and the requested compiler version. + +==== static_values examples ==== + +For readability, the inline examples below abbreviate long SimplicityHL sum types as Either(...). +The auxiliary request fixture contains concrete mock type strings. + +A single branch selector known by the app at request-construction time: + +
{
+  "PATH": {
+    "value": "Right(Right((false, 10, 1000)))",
+    "type": "Either(...)"
+  }
+}
+The same witness name selecting a different branch: + +
{
+  "PATH": {
+    "value": "Right(Left((false, 10, 1000)))",
+    "type": "Either(...)"
+  }
+}
+Multiple static witness values: + +
{
+  "PATH": {
+    "value": "Left(Right(Left((false, 10, 1000, 500))))",
+    "type": "Either(...)"
+  },
+  "COLLATERAL_AMOUNT": {
+    "value": "10",
+    "type": "u32"
+  }
+}
+==== runtime_arguments ==== + +runtime_arguments carries directives for values the app cannot know at request-construction time. +Examples include an issued asset ID that depends on the wallet-selected issuance input, a confidential reissuance +token ID, or a transaction signature that depends on the final transaction sighash. + +For FinalizerSpec::Simf.arguments, runtime_arguments is an object keyed by target SimplicityHL argument names: + +
{
+  "static_values": {
+    "CONTRACT_NONCE": { "value": "1", "type": "u32" }
+  },
+  "runtime_arguments": {
+    "COLLATERAL_ASSET_ID": { "new_issuance_asset": { "input_index": 0 } },
+    "COLLATERAL_TOKEN_ID": { "new_issuance_token": { "input_index": 0 } }
+  }
+}
+Supported runtime argument directives: + +{| class="wikitable" +|- +! Runtime argument +! Definition +|- +| new_issuance_asset +| Resolve a u256 value from the issued asset ID of a new issuance input. +|- +| new_issuance_token +| Resolve a u256 value from the confidential reissuance/inflation-token ID of a new issuance input. +|} + +For FinalizerSpec::Simf.witness, runtime_arguments is currently an array of witness directives: + +
{
+  "static_values": {
+    "PATH": {
+      "value": "Right(Left((false, 10, 1000)))",
+      "type": "Either(...)"
+    }
+  },
+  "runtime_arguments": [
+    {
+      "sig_hash_all": {
+        "name": "USER_SIGHASH_ALL",
+        "public_key": "73c5da0a4f7b8f2e91cd5f8f0c7a6d5b4c3a291817161514131211100f0e0d0c"
+      }
+    }
+  ]
+}
+sig_hash_all.public_key MUST match the runtime signer x-only public key before the runtime signs. + +==== TODO: witness signature embedding ==== + +sig_hash_all is intentionally still draft/TODO. The current shape names the target witness slot (name) and the +expected signer x-only public key (public_key), but this draft does not yet finalize how the generated BIP-340 signature +is embedded back into the SimplicityHL WitnessValues structure that could include branching (Right(Left((, ...)))). + +=== Runtime processing model === + +Provider-specific state objects and wallet output allocation internals are informative implementation details in Appendix B. + +A conforming runtime MAY process a request in this order: + +# Decode JSON and reject unknown envelope/runtime fields. +# Validate abi_version and network against runtime context. +# Open one wallet request session. +# Resolve declared inputs in order. +# For any SIMF-finalized input, compile the requested source_simf with simplicity_hl_version, +derive the expected finalizer script pubkey, and reject if the resolved UTXO script pubkey does not match. +# Resolve issuance metadata for inputs and any issuance-linked output asset IDs. +# Materialize declared outputs in order. +# Estimate fee and balance supply/demand. +# Append wallet funding inputs if needed. +# Append fee output and per-asset change outputs as needed. +# Blind the transaction where requested. +# MAY present a review/approval stage once the runtime has enough information to show the materialized transaction effects, +including runtime-added inputs/outputs, fee/change, confidentiality choices, issuance/inflation-token effects, SIMF program +identity, and broadcast intent. Exact placement is runtime-dependent and may happen before finalization, during a +hardware-device signing flow, after finalization, or immediately before broadcast. +# Finalize wallet inputs and SIMF inputs. +# If broadcast = true, MAY perform a separate broadcast approval according to runtime policy, +then broadcast and return the backend-reported txid. +# Return TxCreateResponse with status = "ok" or status = "error". + +The review/approval stage is a MAY, not a mandatory protocol step, because some runtimes are non-interactive while +others split approval across wallet UI, hardware-device prompts, finalization, and broadcast confirmation. +The returned TxCreateResponse remains the only authoritative result of the processing attempt. + +=== Response envelope: TxCreateResponse === + +==== Success ==== + +
{
+  "abi_version": "wallet-abi-0.1",
+  "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
+  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
+  "status": "ok",
+  "transaction": {
+    "tx_hex": "02000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+    "txid": "5f5a9b3d8a1a55cb2fbc4f61b2b7bc4f4b6a8f8ebd5d39fb7d3e8bfe8b6a1a00"
+  },
+  "artifacts": {}
+}
+{| class="wikitable" +|- +! Field +! style="text-align: right;"| Type +! Definition +|- +| abi_version +| style="text-align: right;"| string +| Response ABI version. +|- +| request_id +| style="text-align: right;"| UUID +| Copied from request. +|- +| network +| style="text-align: right;"| Bip122ChainId +| Copied/confirmed network context. +|- +| status +| style="text-align: right;"| "ok" +| Success marker. +|- +| transaction.tx_hex +| style="text-align: right;"| hex +| Fully signed Elements transaction. +|- +| transaction.txid +| style="text-align: right;"| txid +| Transaction ID of tx_hex; if broadcasted, should match backend-reported txid. +|- +| artifacts +| style="text-align: right;"| object +| Optional producer metadata. Open-ended; consumers must ignore unknown keys. +|} + +==== Error ==== + +
{
+  "abi_version": "wallet-abi-0.1",
+  "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
+  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
+  "status": "error",
+  "error": {
+    "code": "funding",
+    "message": "insufficient wallet balance",
+    "details": {}
+  }
+}
+{| class="wikitable" +|- +! Field +! style="text-align: right;"| Type +! Definition +|- +| status +| style="text-align: right;"| "error" +| Error marker. +|- +| error.code +| style="text-align: right;"| string +| Stable machine category. Unknown strings should be preserved/tolerated. +|- +| error.message +| style="text-align: right;"| string +| Human-readable technical diagnostic, not a stable discriminator. +|- +| error.details +| style="text-align: right;"| JSON +| Optional producer-defined diagnostics. Treat as untrusted. +|} + +=== Canonical error code set === + +{| class="wikitable" +|- +! Code +! Typical meaning +|- +| invalid_request +| Request shape, incompatible fields, bad network/version, missing referenced input. +|- +| serde +| Serialization/deserialization failure. +|- +| program_error +| SimplicityHL/program-level failure, including unsupported compiler version when surfaced through the program layer. +|- +| derivation +| Key/script/address/asset derivation failure. +|- +| try_from_int +| Integer conversion overflow/failure. +|- +| funding +| Insufficient or unavailable wallet funds. +|- +| invalid_signer_config +| Signer unavailable or configured with wrong key. +|- +| invalid_response +| Runtime/adapter response contract failure. +|- +| pset +| PSET construction/finalization failure. +|- +| pset_blind +| PSET blinding failure. +|- +| amount_proof_verification +| Confidential amount proof verification failure. +|- +| invalid_finalization_steps +| Finalization sequence or witness construction failure. +|} + +=== Versioning and extension rules === + +# abi_version changes are required for incompatible request/response shape changes. +# New enum variants SHOULD be gated by ABI version or explicit capability negotiation. +# artifacts is the preferred place for producer-defined metadata that should not break older consumers. +# Unknown request fields are rejected by the current Rust request/runtime parameter schemas; do not use unknown fields for extension. +# Runtimes that cannot satisfy simplicity_hl_version MUST reject rather than silently compiling with another version. +# A future ABI may define friendly network aliases, but wire-level matching in this ABI is by BIP-122 chain id. +# Changes to the static_values {value,type} shape or the signature-embedding rules require an ABI update or explicit capability negotiation. + +== Security Considerations == + +# Treat all request data as untrusted, including scripts, outpoints, finalizer source, and pubkeys. +# Never log InputUnblinding.provided.blinding_secret_key or intermediate PSETs containing resolved input secrets. +# InputUnblinding.provided.blinding_secret_key is not a signing key, but it can reveal confidential prevout values and should be treated as sensitive unless explicitly policy-marked as public. +# broadcast = false does not mean offline/no-network; runtime may sync wallet state and fetch prevouts. +# explicit outputs reveal amount and asset. +# Outputs carrying new_issuance_token MUST NOT be explicit in this ABI. +# provided outpoints may be spent, nonexistent, or maliciously selected; resolve/fetch before relying on them. +# lock_time can be ineffective if input sequences are final. +# SIMF sig_hash_all.public_key must equal the runtime signer x-only key. +# source_simf must be compiled with the requested simplicity_hl_version; runtimes MUST NOT silently substitute a different compiler version. +# Consumer UIs should make network and broadcast status prominent. +# Consumers should ignore unknown artifacts keys and sanitize error.message/error.details before rendering. +# Wallets MUST NOT trust self-declared app names, labels, URLs, or icons in the request payload as authenticated caller identity. Authenticated app/request identity must come from the transport/platform binding or another out-of-band trust system. +# static_values.value and static_values.type are untrusted SimplicityHL compiler inputs. Parse and type-check them with the requested simplicity_hl_version; do not evaluate them with an ad hoc parser outside the compiler boundary. +# For SIMF-finalized inputs, the resolved UTXO script pubkey must match the script pubkey derived from the requested SIMF finalizer before signing/finalization. + +== Rationale == + +The ABI uses BIP-122/CAIP-2-style chain identifiers instead of bare network names so wallets can match requests against +the genesis hash of the active Elements chain. This avoids ambiguity between Liquid mainnet, Liquid testnet, local Elements chains, and custom networks. + +request_id is a correlation identifier rather than replay protection because wallet state, UTXO availability, +fee policy, and broadcast status can change between attempts. Treating the request as non-idempotent avoids giving callers +a false guarantee that the same JSON body will always produce the same transaction. + +SIMF payloads are JSON objects at the wire level to make review, schema validation, and application construction easier. +Static SIMF values use the SimplicityHL witness-style { "value": string, "type": string } shape because the +compiler, not the ABI, is responsible for parsing and type-checking Rust-like SimplicityHL literals. + +simplicity_hl_version is part of the request so the same source_simf is compiled by the version +intended by the caller. This is required because different compiler versions may produce different compiled programs, +addresses, script pubkeys, or finalization behavior. + +Outputs carrying new_issuance_token are required to be confidential in this ABI to match the current +Liquid reissuance-token constraint. Explicit reissuance-token support can be considered later if the underlying +validation model and ABI capability negotiation make it safe. + +== Backwards Compatibility == + +This ELIP defines a new application/wallet ABI and does not change Elements consensus rules, peer-to-peer networking, +transaction validity, or the PSET format. Existing wallets and applications that do not implement this ABI are unaffected. + +Unknown request fields are rejected by the current request/runtime schemas. Incompatible wire-shape changes require +an abi_version change or explicit capability negotiation. + +== Reference Implementation == + +No final reference implementation is specified by this draft. The auxiliary JSON Schema and examples are review aids +for implementers, but semantic validation remains the responsibility of the wallet/runtime. + +The current example files are mock fixtures for reviewing the ABI wire shape. They are not final conformance vectors +and are expected to be corrected or replaced after the first proper wallet/runtime implementation validates the full transaction-construction flow. + +A future implementation may include a wallet/runtime adapter, JSON Schema validation tests, SimplicityHL compiler-version +dispatch, finalizer script-pubkey verification tests, and fixtures covering confidential issuance-token outputs. + +== Test Vectors and Auxiliary Files == + +The auxiliary files below are intended to be committed with this draft in the elip-wallet-abi/ subdirectory. +After an ELIP number is assigned, the directory and links can be renamed according to editor preference. + +The example request and response files are mock fixtures for the current draft. They exercise the proposed JSON shape +and schema constraints, but they are expected to be corrected or replaced after the first proper wallet/runtime implementation is available. + +{| class="wikitable" +|- +! File +! Purpose +|- +| [[elip-wallet-abi/01_request_wallet_to_script.json|01_request_wallet_to_script.json]] +| Simple wallet-funded build-only payment to an explicit script output using network = "bip122:a771da8e52ee6ad581ed1e9a99825e5b". +|- +| [[elip-wallet-abi/02_response_ok_build_only.json|02_response_ok_build_only.json]] +| Success response for the build-only example, using the same Bip122ChainId and open-ended artifacts. +|- +| [[elip-wallet-abi/03_response_error_funding.json|03_response_error_funding.json]] +| Error response with canonical funding code and optional diagnostic details. +|- +| [[elip-wallet-abi/04_request_simf_bip0341_issuance.json|04_request_simf_bip0341_issuance.json]] +| Issuance request using a SIMF finalizer, stable bip0341 internal key, simplicity_hl_version, JSON arguments/witness, static_values examples, inflation_amount_sat, and confidential new_issuance_token output. +|- +| [[elip-wallet-abi/wallet-abi-tx-create.schema.json|wallet-abi-tx-create.schema.json]] +| Review JSON Schema for request/response shape. It includes the BIP-122 chain-id pattern, blinding_secret_key, inflation_amount_sat, simplicity_hl_version, JSON SIMF payloads, static_values typed literals, stable bip0341, and a schema-level rejection of blinder = "explicit" when asset.type = "new_issuance_token". +|- +| [[elip-wallet-abi/field-reference.json|field-reference.json]] +| Machine-readable field reference for implementers and UI review. +|} + +== References == + +These links are intentionally listed directly so reviewers do not need to search for the underlying standards or context. + +{| class="wikitable" +|- +! Topic +! Link +! Relevance +|- +| ELIP repository +| https://github.com/ElementsProject/ELIPs +| Repository that hosts Elements Improvement Proposals and review process context. +|- +| ELIP purpose and format +| https://github.com/ElementsProject/ELIPs/blob/main/elip-0001.mediawiki +| Defines the ELIP process, MediaWiki format, header preamble, and auxiliary file rules. +|- +| RFC 2119 requirement keywords +| https://www.rfc-editor.org/rfc/rfc2119 +| Defines the normative meaning of '''MUST''', '''SHOULD''', '''MAY''', and related terms. +|- +| JSON Schema draft 2020-12 +| https://json-schema.org/draft/2020-12/json-schema-core +| Version used by wallet-abi-tx-create.schema.json. +|- +| BIP-122 +| https://bips.dev/122/ +| Defines chain identity by genesis block hash for blockchain references. +|- +| CAIP-2 +| https://standards.chainagnostic.org/CAIPs/caip-2 +| Defines the namespace:reference chain-id form. +|- +| CAIP BIP122 namespace +| https://namespaces.chainagnostic.org/bip122/caip2 +| Defines bip122:32-character-lowercase-genesis-hash-prefix. +|- +| BIP-340 +| https://bips.dev/340/ +| Defines Schnorr signatures and 32-byte x-only public keys used by Taproot. +|- +| BIP-341 +| https://bips.dev/341/ +| Defines Taproot, internal keys, script-path control blocks, and the NUMS/example internal key used by bip0341. +|- +| Elements Project +| https://github.com/ElementsProject/elements +| Reference implementation for Elements/Liquid chain behavior. +|- +| Elements chainparams.cpp +| https://raw.githubusercontent.com/ElementsProject/elements/master/src/chainparams.cpp +| Source reference for chain/network parameters such as liquidv1. Implementations should derive the active chain id from their node/runtime rather than trusting a hard-coded label. +|- +| Go Elements network parameters +| https://pkg.go.dev/github.com/dirtyhighli/go-elements/network +| Convenient source for Liquid, Liquid testnet, and Elements regtest example genesis hashes used in this draft. +|- +| SimplicityHL repository +| https://github.com/BlockstreamResearch/SimplicityHL +| Source project for source_simf and simplicity_hl_version context. +|- +| SimplicityHL witness documentation +| https://docs.simplicity-lang.org/documentation/witness/ +| Describes .wit JSON files where each top-level entry has value and type string fields and names are used as witness::NAME. +|- +| SimplicityHL issue #309 +| https://github.com/BlockstreamResearch/SimplicityHL/issues/309 +| Tracks the confidential-only reissuance-token constraint motivating the new_issuance_token confidentiality rule. +|- +| Semantic Versioning 2.0.0 +| https://semver.org/ +| Informative reference for the simplicity_hl_version string shape; the ABI requires an exact compiler version, not a numeric JSON value. +|} + +Known chain-id examples used by this ABI: + +{| class="wikitable" +|- +! Friendly label +! Full genesis hash +! ABI network value +|- +| Liquid mainnet (liquidv1) +| 1466275836220db2944ca059a3a10ef6fd2ea684b0688d2c379296888a206003 +| bip122:1466275836220db2944ca059a3a10ef6 +|- +| Liquid testnet (liquidtestnet) +| a771da8e52ee6ad581ed1e9a99825e5b3b7992225534eaa2ae23244fe26ab1c1 +| bip122:a771da8e52ee6ad581ed1e9a99825e5b +|- +| Default Elements regtest/localtest +| 00902a6b70c2ca83b5d9c815d96a0e2f4202179316970d14ea1847dae5b1ca21 +| bip122:00902a6b70c2ca83b5d9c815d96a0e2f +|} + +== Appendix A: Future Work == + +This appendix collects ideas that are intentionally not part of the wallet-abi-0.1 core. + +=== A.1 Standardized preview artifacts === + +A future ABI may standardize an artifacts.preview object containing wallet deltas, selected inputs, fee, +change, confidentiality choices, and issuance effects. For wallet-abi-0.1, artifacts remains +open-ended producer metadata. + +=== A.2 Transport and capability negotiation === + +A future profile may define a WalletConnect, JSON-RPC, or other transport binding; capability negotiation +for enum variants; and supported simplicity_hl_version discovery. + +=== A.3 Friendly network aliases and local-chain metadata === + +The wire network is a BIP-122 chain id in this draft. A future profile may define friendly labels, +policy-asset metadata, and local/custom Elements network registry entries, but those aliases must not replace genesis-hash matching in the core validation path. + +== Appendix B: Informative consumer/runtime implementation notes == + +This appendix is not a caller-visible wire schema and is not required as provider API surface. It records one useful +runtime implementation model for wallet providers. Transport bindings, provider session objects, UTXO-cache structure, +and UI-state machines remain out of scope for the core ABI payload. + +=== B.1 WalletRequestSession === + +{| class="wikitable" +|- +! Field +! Definition +|- +| session_id +| Opaque wallet-owned correlation ID. +|- +| network +| BIP-122 chain id used for request validation and script derivation. +|- +| spendable_utxos +| Deterministic spendable UTXO snapshot used for input selection within one request lifecycle. +|} + +=== B.2 WalletOutputRequest === + +{| class="wikitable" +|- +! Variant +! Definition +|- +| Receive { index } +| Deterministic zero-based receive-output index within a build pass. +|- +| Change { index, asset_id } +| Deterministic zero-based change-output index for a concrete residual asset. +|} + +=== B.3 WalletOutputTemplate === + +{| class="wikitable" +|- +! Field +! Definition +|- +| script_pubkey +| Wallet-selected script for receive/change output. +|- +| blinding_pubkey +| Optional blinding public key for confidential outputs. +|} + +A wallet output allocator should be stable for the same (session, request) pair if the provider exposes +preview/final-build behavior, but this is an implementation note rather than a separate ABI field. + +== Appendix C: JSON Schema == + +The review schema for wallet-abi-0.1 request/response payloads is provided as +[[elip-wallet-abi/wallet-abi-tx-create.schema.json|wallet-abi-tx-create.schema.json]]. diff --git a/elip-wallet-abi/01_request_wallet_to_script.json b/elip-wallet-abi/01_request_wallet_to_script.json new file mode 100644 index 0000000..20e2959 --- /dev/null +++ b/elip-wallet-abi/01_request_wallet_to_script.json @@ -0,0 +1,51 @@ +{ + "abi_version": "wallet-abi-0.1", + "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14", + "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b", + "params": { + "inputs": [ + { + "id": "wallet-lbtc-funding", + "utxo_source": { + "wallet": { + "filter": { + "asset": { + "exact": { + "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49" + } + }, + "amount": { + "min": { + "amount_sat": 150000 + } + }, + "lock": "none" + } + } + }, + "unblinding": "wallet", + "sequence": 4294967295, + "finalizer": { + "type": "wallet" + } + } + ], + "outputs": [ + { + "id": "merchant-payment", + "amount_sat": 100000, + "lock": { + "type": "script", + "script": "0014aabbccddeeff00112233445566778899aabbccdd" + }, + "asset": { + "type": "asset_id", + "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49" + }, + "blinder": "explicit" + } + ], + "fee_rate_sat_kvb": 1000.0 + }, + "broadcast": false +} diff --git a/elip-wallet-abi/02_response_ok_build_only.json b/elip-wallet-abi/02_response_ok_build_only.json new file mode 100644 index 0000000..b38a090 --- /dev/null +++ b/elip-wallet-abi/02_response_ok_build_only.json @@ -0,0 +1,35 @@ +{ + "abi_version": "wallet-abi-0.1", + "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14", + "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b", + "status": "ok", + "transaction": { + "tx_hex": "02000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "txid": "5f5a9b3d8a1a55cb2fbc4f61b2b7bc4f4b6a8f8ebd5d39fb7d3e8bfe8b6a1a00" + }, + "artifacts": { + "example_note": "artifacts is producer-defined; consumers must ignore unknown keys", + "broadcast": false, + "selected_inputs": [ + { + "input_id": "wallet-lbtc-funding", + "source": "wallet", + "outpoint": "0101010101010101010101010101010101010101010101010101010101010101:0", + "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49", + "amount_sat": 150000 + } + ], + "appended_outputs": [ + { + "kind": "fee", + "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49", + "amount_sat": 450 + }, + { + "kind": "change", + "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49", + "amount_sat": 49550 + } + ] + } +} diff --git a/elip-wallet-abi/03_response_error_funding.json b/elip-wallet-abi/03_response_error_funding.json new file mode 100644 index 0000000..9fd32eb --- /dev/null +++ b/elip-wallet-abi/03_response_error_funding.json @@ -0,0 +1,16 @@ +{ + "abi_version": "wallet-abi-0.1", + "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14", + "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b", + "status": "error", + "error": { + "code": "funding", + "message": "insufficient wallet balance for asset 144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49", + "details": { + "requested_asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49", + "requested_amount_sat": 100000, + "available_amount_sat": 12345, + "broadcast_attempted": false + } + } +} diff --git a/elip-wallet-abi/04_request_simf_bip0341_issuance.json b/elip-wallet-abi/04_request_simf_bip0341_issuance.json new file mode 100644 index 0000000..e21e024 --- /dev/null +++ b/elip-wallet-abi/04_request_simf_bip0341_issuance.json @@ -0,0 +1,154 @@ +{ + "abi_version": "wallet-abi-0.1", + "request_id": "216113a8-8eb7-4d1f-8573-8b6ed04f4ad5", + "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b", + "params": { + "inputs": [ + { + "id": "issuance-funding-input", + "utxo_source": { + "wallet": { + "filter": { + "asset": { + "exact": { + "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49" + } + }, + "amount": { + "min": { + "amount_sat": 250000 + } + }, + "lock": "none" + } + } + }, + "unblinding": "wallet", + "sequence": 4294967294, + "issuance": { + "kind": "new", + "asset_amount_sat": 1, + "inflation_amount_sat": 1, + "entropy": [ + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7, + 7 + ] + }, + "finalizer": { + "type": "wallet" + } + } + ], + "outputs": [ + { + "id": "issued-asset-to-simf-lock", + "amount_sat": 1, + "lock": { + "type": "finalizer", + "finalizer": { + "type": "simf", + "source_simf": "-- SimplicityHL source placeholder for review wire-shape only\n-- Replace with canonical source before production.", + "simplicity_hl_version": "0.4.2", + "internal_key": "bip0341", + "arguments": { + "static_values": { + "CONTRACT_NONCE": { + "value": "1", + "type": "u32" + } + }, + "runtime_arguments": { + "COLLATERAL_ASSET_ID": { + "new_issuance_asset": { + "input_index": 0 + } + }, + "COLLATERAL_TOKEN_ID": { + "new_issuance_token": { + "input_index": 0 + } + } + } + }, + "witness": { + "static_values": { + "PATH": { + "value": "Left(Right(Left((false, 10, 1000, 500))))", + "type": "Either>, Either<(bool, u64, u64), (bool, u64, u64)>>" + }, + "COLLATERAL_AMOUNT": { + "value": "10", + "type": "u32" + } + }, + "runtime_arguments": [ + { + "sig_hash_all": { + "name": "USER_SIGHASH_ALL", + "public_key": "73c5da0a4f7b8f2e91cd5f8f0c7a6d5b4c3a291817161514131211100f0e0d0c" + } + } + ] + } + } + }, + "asset": { + "type": "new_issuance_asset", + "input_index": 0 + }, + "blinder": { + "provided": { + "pubkey": "0273c5da0a4f7b8f2e91cd5f8f0c7a6d5b4c3a291817161514131211100f0e0d0c" + } + } + }, + { + "id": "issued-token-to-wallet", + "amount_sat": 1, + "lock": { + "type": "wallet" + }, + "asset": { + "type": "new_issuance_token", + "input_index": 0 + }, + "blinder": "wallet" + } + ], + "fee_rate_sat_kvb": 1000.0, + "lock_time": { + "Blocks": 900000 + } + }, + "broadcast": true +} diff --git a/elip-wallet-abi/field-reference.json b/elip-wallet-abi/field-reference.json new file mode 100644 index 0000000..683f5cd --- /dev/null +++ b/elip-wallet-abi/field-reference.json @@ -0,0 +1,254 @@ +[ + { + "path": "TxCreateRequest.abi_version", + "type": "string", + "required": true, + "definition": "ABI contract version. Must equal wallet-abi-0.1." + }, + { + "path": "TxCreateRequest.request_id", + "type": "uuid", + "required": true, + "definition": "Correlation identifier generated per user action. Not replay protection and not an idempotency key." + }, + { + "path": "TxCreateRequest.network", + "type": "Bip122ChainId", + "required": true, + "definition": "CAIP-2-style BIP-122 chain id string, bip122:<32-lowercase-hex genesis prefix>. Must match runtime chain id before side effects." + }, + { + "path": "TxCreateRequest.params", + "type": "RuntimeParams", + "required": true, + "definition": "Transaction-construction request body." + }, + { + "path": "TxCreateRequest.broadcast", + "type": "boolean", + "required": true, + "definition": "Whether runtime should publish the finalized transaction. false still permits sync/fetch/validation network calls." + }, + { + "path": "RuntimeParams.inputs", + "type": "InputSchema[]", + "required": true, + "definition": "Declared inputs resolved in order. Order can affect wallet selection and issuance-linked references." + }, + { + "path": "RuntimeParams.outputs", + "type": "OutputSchema[]", + "required": true, + "definition": "Declared outputs materialized in order. Runtime may append fee and per-asset change outputs." + }, + { + "path": "RuntimeParams.fee_rate_sat_kvb", + "type": "number", + "required": false, + "definition": "Optional finite non-negative fee rate in sat/kvB." + }, + { + "path": "RuntimeParams.lock_time", + "type": "LockTime", + "required": false, + "definition": "Optional fallback locktime. Effective only when input sequence semantics activate locktime." + }, + { + "path": "InputSchema.id", + "type": "string", + "required": true, + "definition": "Caller-facing label for diagnostics and review UI." + }, + { + "path": "InputSchema.utxo_source", + "type": "UTXOSource", + "required": true, + "definition": "Prevout source selector: wallet-selected from filters or caller-provided outpoint." + }, + { + "path": "InputSchema.unblinding", + "type": "InputUnblinding", + "required": true, + "definition": "How runtime obtains prevout values/secrets: wallet, provided blinding_secret_key, or explicit." + }, + { + "path": "InputUnblinding.provided.blinding_secret_key", + "type": "SecretKey", + "required": "provided only", + "definition": "Caller-supplied input blinding secret key for prevout unblinding. This is not a spend/signing private key; handle as sensitive unless explicitly policy-marked public." + }, + { + "path": "InputSchema.sequence", + "type": "u32", + "required": true, + "definition": "Bitcoin/Elements input sequence for finality, locktime, relative locktime, and RBF semantics." + }, + { + "path": "InputSchema.issuance", + "type": "InputIssuance?", + "required": false, + "definition": "Optional issuance/reissuance metadata used for PSET issuance fields and issuance-linked output asset IDs." + }, + { + "path": "InputIssuance.kind", + "type": "new | reissue", + "required": true, + "definition": "Issuance kind for this input." + }, + { + "path": "InputIssuance.asset_amount_sat", + "type": "u64", + "required": true, + "definition": "Amount of issued/reissued asset units to mint." + }, + { + "path": "InputIssuance.inflation_amount_sat", + "type": "u64", + "required": true, + "definition": "Amount of reissuance/inflation-token units to mint. Replaces token_amount_sat." + }, + { + "path": "InputIssuance.entropy", + "type": "[u8; 32]", + "required": true, + "definition": "For new issuance, contract-hash entropy; for reissue, already-derived asset entropy." + }, + { + "path": "InputSchema.finalizer", + "type": "FinalizerSpec", + "required": true, + "definition": "Input finalization strategy: wallet/miniscript or SimplicityHL finalizer." + }, + { + "path": "OutputSchema.id", + "type": "string", + "required": true, + "definition": "Caller-facing output label for diagnostics and UI." + }, + { + "path": "OutputSchema.amount_sat", + "type": "u64", + "required": true, + "definition": "Requested output amount in satoshi/base units." + }, + { + "path": "OutputSchema.lock", + "type": "LockVariant", + "required": true, + "definition": "How runtime determines scriptPubKey: wallet receive template, raw script, or finalizer-derived script." + }, + { + "path": "OutputSchema.asset", + "type": "AssetVariant", + "required": true, + "definition": "Explicit asset ID or issuance-derived asset/token selector." + }, + { + "path": "OutputSchema.asset.new_issuance_token", + "type": "AssetVariant", + "required": false, + "definition": "Confidential reissuance/inflation token derived from a new issuance input. Outputs using this asset MUST NOT use blinder = explicit." + }, + { + "path": "OutputSchema.blinder", + "type": "BlinderVariant", + "required": true, + "definition": "Output confidentiality policy: wallet blinding key, provided blinding pubkey, or explicit output." + }, + { + "path": "FinalizerSpec.type", + "type": "wallet | simf", + "required": true, + "definition": "Finalization variant tag." + }, + { + "path": "FinalizerSpec.source_simf", + "type": "string", + "required": "simf only", + "definition": "UTF-8 SimplicityHL source loaded/instantiated at runtime." + }, + { + "path": "FinalizerSpec.simplicity_hl_version", + "type": "string", + "required": "simf only", + "definition": "Exact Cargo/SimplicityHL compiler version the runtime must use for compilation/address derivation/finalization." + }, + { + "path": "FinalizerSpec.internal_key", + "type": "InternalKeySource", + "required": "simf only", + "definition": "Source for Taproot x-only internal key. Stable wallet-abi-0.1 supports only bip0341." + }, + { + "path": "FinalizerSpec.arguments", + "type": "SimfArguments JSON object", + "required": "simf only", + "definition": "SIMF argument payload as a JSON object at the ABI wire level; no UTF-8 byte-array wrapper." + }, + { + "path": "FinalizerSpec.witness", + "type": "SimfWitness JSON object", + "required": "simf only", + "definition": "SIMF witness payload as a JSON object at the ABI wire level; no UTF-8 byte-array wrapper." + }, + { + "path": "TxCreateResponse.status", + "type": "ok | error", + "required": true, + "definition": "High-level outcome." + }, + { + "path": "TxCreateResponse.transaction", + "type": "TransactionInfo?", + "required": "ok only", + "definition": "Finalized transaction hex and txid." + }, + { + "path": "TxCreateResponse.artifacts", + "type": "object?", + "required": false, + "definition": "Open-ended producer metadata. Consumers must ignore unknown keys." + }, + { + "path": "TxCreateResponse.error", + "type": "ErrorInfo?", + "required": "error only", + "definition": "Structured error code, technical message, and optional details." + }, + { + "path": "FinalizerSpec.simf.arguments.static_values", + "type": "SimfStaticValues", + "required": true, + "definition": "Caller-known compile-time/static SIMF argument values. Map from SimplicityHL argument name to {value,type} strings; values are parsed/type-checked by the requested SimplicityHL compiler." + }, + { + "path": "FinalizerSpec.simf.arguments.runtime_arguments", + "type": "object", + "required": true, + "definition": "Runtime-resolved SIMF argument directives, keyed by the target SimplicityHL argument name, such as deriving COLLATERAL_ASSET_ID from a selected issuance input." + }, + { + "path": "FinalizerSpec.simf.witness.static_values", + "type": "SimfStaticValues", + "required": true, + "definition": "Caller-known static witness values, keyed by SimplicityHL witness name. Examples include PATH branch selectors or COLLATERAL_AMOUNT constants encoded as typed literal strings." + }, + { + "path": "FinalizerSpec.simf.witness.runtime_arguments", + "type": "RuntimeSimfWitness[]", + "required": true, + "definition": "Runtime-resolved witness directives. sig_hash_all signature embedding is still TODO/draft and must be finalized before production compatibility is claimed." + }, + { + "path": "SimfStaticValues..value", + "type": "string", + "required": true, + "definition": "SimplicityHL literal string, for example Right(Left((false, 10, 1000))) or 100. Numeric values remain strings, following SimplicityHL witness-file conventions." + }, + { + "path": "SimfStaticValues..type", + "type": "string", + "required": true, + "definition": "SimplicityHL type annotation string, for example u64, Signature, (bool, u64), or Either<...>." + } +] diff --git a/elip-wallet-abi/wallet-abi-tx-create.schema.json b/elip-wallet-abi/wallet-abi-tx-create.schema.json new file mode 100644 index 0000000..52934a2 --- /dev/null +++ b/elip-wallet-abi/wallet-abi-tx-create.schema.json @@ -0,0 +1,974 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.invalid/wallet-abi/tx-create/wallet-abi-0.1.schema.json", + "title": "Wallet ABI tx_create wallet-abi-0.1 review schema", + "description": "Review schema for the Wallet ABI tx_create draft. Includes BIP-122 network ids, JSON SIMF payloads, static_values typed literals, runtime SIMF directives, and response shapes. Semantic validation remains the runtime's responsibility.", + "oneOf": [ + { + "$ref": "#/$defs/TxCreateRequest" + }, + { + "$ref": "#/$defs/TxCreateResponse" + } + ], + "$defs": { + "Hex": { + "type": "string", + "pattern": "^[0-9a-fA-F]*$" + }, + "Hex32": { + "type": "string", + "pattern": "^[0-9a-fA-F]{64}$" + }, + "Uuid": { + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" + }, + "Bip122ChainId": { + "type": "string", + "pattern": "^bip122:[0-9a-f]{32}$", + "description": "CAIP-2-style BIP-122 chain id: bip122:.", + "examples": [ + "bip122:1466275836220db2944ca059a3a10ef6", + "bip122:a771da8e52ee6ad581ed1e9a99825e5b", + "bip122:00902a6b70c2ca83b5d9c815d96a0e2f" + ] + }, + "U64": { + "type": "integer", + "minimum": 0, + "maximum": 18446744073709551615 + }, + "U32": { + "type": "integer", + "minimum": 0, + "maximum": 4294967295 + }, + "Byte": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "ByteArray": { + "type": "array", + "items": { + "$ref": "#/$defs/Byte" + } + }, + "AssetId": { + "$ref": "#/$defs/Hex32" + }, + "Txid": { + "$ref": "#/$defs/Hex32" + }, + "Script": { + "$ref": "#/$defs/Hex" + }, + "XOnlyPublicKey": { + "$ref": "#/$defs/Hex32" + }, + "PublicKey": { + "type": "string", + "pattern": "^(02|03)[0-9a-fA-F]{64}$" + }, + "SecretKey": { + "$ref": "#/$defs/Hex32" + }, + "OutPoint": { + "type": "string", + "pattern": "^[0-9a-fA-F]{64}:[0-9]+$" + }, + "SimplicityHLVersion": { + "type": "string", + "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$", + "description": "Exact SimplicityHL/Cargo compiler version requested by the caller, encoded as a SemVer-like string." + }, + "SimfName": { + "type": "string", + "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", + "description": "SimplicityHL argument or witness name. Exact accepted names are ultimately defined by the compiler/source." + }, + "SimfStaticValue": { + "type": "object", + "required": [ + "value", + "type" + ], + "additionalProperties": false, + "properties": { + "value": { + "type": "string", + "description": "SimplicityHL literal encoded as a string, for example \"100\", \"false\", \"Right(Left((false, 10, 1000)))\", or a 0x-prefixed signature." + }, + "type": { + "type": "string", + "description": "SimplicityHL type annotation encoded as a string, for example \"u64\", \"Signature\", \"(bool, u64)\", or \"Either<...>\"." + } + } + }, + "SimfStaticValues": { + "type": "object", + "description": "Caller-known static SIMF values keyed by SimplicityHL argument/witness name. Entries follow the WitnessValues/WitnessNames-style {value,type} shape.", + "propertyNames": { + "$ref": "#/$defs/SimfName" + }, + "additionalProperties": { + "$ref": "#/$defs/SimfStaticValue" + }, + "examples": [ + { + "PATH": { + "value": "Right(Right((false, 10, 1000)))", + "type": "Either>, Either<(bool, u64, u64), (bool, u64, u64)>>" + } + }, + { + "PATH": { + "value": "Right(Left((false, 10, 1000)))", + "type": "Either>, Either<(bool, u64, u64), (bool, u64, u64)>>" + } + }, + { + "PATH": { + "value": "Left(Right(Left((false, 10, 1000, 500))))", + "type": "Either>, Either<(bool, u64, u64), (bool, u64, u64)>>" + }, + "COLLATERAL_AMOUNT": { + "value": "10", + "type": "u32" + } + } + ] + }, + "LockTime": { + "oneOf": [ + { + "type": "object", + "required": [ + "Blocks" + ], + "additionalProperties": false, + "properties": { + "Blocks": { + "$ref": "#/$defs/U32" + } + } + }, + { + "type": "object", + "required": [ + "Seconds" + ], + "additionalProperties": false, + "properties": { + "Seconds": { + "$ref": "#/$defs/U32" + } + } + } + ] + }, + "AssetFilter": { + "oneOf": [ + { + "const": "none" + }, + { + "type": "object", + "required": [ + "exact" + ], + "additionalProperties": false, + "properties": { + "exact": { + "type": "object", + "required": [ + "asset_id" + ], + "additionalProperties": false, + "properties": { + "asset_id": { + "$ref": "#/$defs/AssetId" + } + } + } + } + } + ] + }, + "AmountFilter": { + "oneOf": [ + { + "const": "none" + }, + { + "type": "object", + "required": [ + "exact" + ], + "additionalProperties": false, + "properties": { + "exact": { + "type": "object", + "required": [ + "amount_sat" + ], + "additionalProperties": false, + "properties": { + "amount_sat": { + "$ref": "#/$defs/U64" + } + } + } + } + }, + { + "type": "object", + "required": [ + "min" + ], + "additionalProperties": false, + "properties": { + "min": { + "type": "object", + "required": [ + "amount_sat" + ], + "additionalProperties": false, + "properties": { + "amount_sat": { + "$ref": "#/$defs/U64" + } + } + } + } + } + ] + }, + "LockFilter": { + "oneOf": [ + { + "const": "none" + }, + { + "type": "object", + "required": [ + "script" + ], + "additionalProperties": false, + "properties": { + "script": { + "type": "object", + "required": [ + "script" + ], + "additionalProperties": false, + "properties": { + "script": { + "$ref": "#/$defs/Script" + } + } + } + } + } + ] + }, + "WalletSourceFilter": { + "type": "object", + "required": [ + "asset", + "amount", + "lock" + ], + "additionalProperties": false, + "properties": { + "asset": { + "$ref": "#/$defs/AssetFilter" + }, + "amount": { + "$ref": "#/$defs/AmountFilter" + }, + "lock": { + "$ref": "#/$defs/LockFilter" + } + } + }, + "UTXOSource": { + "oneOf": [ + { + "type": "object", + "required": [ + "wallet" + ], + "additionalProperties": false, + "properties": { + "wallet": { + "type": "object", + "required": [ + "filter" + ], + "additionalProperties": false, + "properties": { + "filter": { + "$ref": "#/$defs/WalletSourceFilter" + } + } + } + } + }, + { + "type": "object", + "required": [ + "provided" + ], + "additionalProperties": false, + "properties": { + "provided": { + "type": "object", + "required": [ + "outpoint" + ], + "additionalProperties": false, + "properties": { + "outpoint": { + "$ref": "#/$defs/OutPoint" + } + } + } + } + } + ] + }, + "InputUnblinding": { + "oneOf": [ + { + "const": "wallet" + }, + { + "const": "explicit" + }, + { + "type": "object", + "required": [ + "provided" + ], + "additionalProperties": false, + "properties": { + "provided": { + "type": "object", + "required": [ + "blinding_secret_key" + ], + "additionalProperties": false, + "properties": { + "blinding_secret_key": { + "$ref": "#/$defs/SecretKey" + } + } + } + } + } + ] + }, + "InputIssuance": { + "type": "object", + "required": [ + "kind", + "asset_amount_sat", + "inflation_amount_sat", + "entropy" + ], + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "new", + "reissue" + ] + }, + "asset_amount_sat": { + "$ref": "#/$defs/U64" + }, + "inflation_amount_sat": { + "$ref": "#/$defs/U64" + }, + "entropy": { + "type": "array", + "minItems": 32, + "maxItems": 32, + "items": { + "$ref": "#/$defs/Byte" + } + } + } + }, + "InternalKeySource": { + "description": "Stable wallet-abi-0.1 profile supports only bip0341. Future variants belong to a future ABI/capability profile.", + "const": "bip0341" + }, + "RuntimeSimfValue": { + "oneOf": [ + { + "type": "object", + "required": [ + "new_issuance_asset" + ], + "additionalProperties": false, + "properties": { + "new_issuance_asset": { + "type": "object", + "required": [ + "input_index" + ], + "additionalProperties": false, + "properties": { + "input_index": { + "$ref": "#/$defs/U32" + } + } + } + } + }, + { + "type": "object", + "required": [ + "new_issuance_token" + ], + "additionalProperties": false, + "properties": { + "new_issuance_token": { + "type": "object", + "required": [ + "input_index" + ], + "additionalProperties": false, + "properties": { + "input_index": { + "$ref": "#/$defs/U32" + } + } + } + } + } + ], + "description": "Runtime-resolved SIMF argument directive. The key containing this directive is the SimplicityHL argument name that will receive the runtime value." + }, + "RuntimeSimfWitness": { + "oneOf": [ + { + "type": "object", + "required": [ + "sig_hash_all" + ], + "additionalProperties": false, + "properties": { + "sig_hash_all": { + "type": "object", + "required": [ + "name", + "public_key" + ], + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "public_key": { + "$ref": "#/$defs/XOnlyPublicKey" + } + } + } + } + } + ], + "description": "Runtime-resolved SIMF witness directive. sig_hash_all is a draft/TODO signature-embedding directive." + }, + "SimfArguments": { + "type": "object", + "required": [ + "static_values", + "runtime_arguments" + ], + "additionalProperties": false, + "properties": { + "static_values": { + "$ref": "#/$defs/SimfStaticValues" + }, + "runtime_arguments": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/SimfName" + }, + "additionalProperties": { + "$ref": "#/$defs/RuntimeSimfValue" + } + } + } + }, + "SimfWitness": { + "type": "object", + "required": [ + "static_values", + "runtime_arguments" + ], + "additionalProperties": false, + "properties": { + "static_values": { + "$ref": "#/$defs/SimfStaticValues" + }, + "runtime_arguments": { + "type": "array", + "items": { + "$ref": "#/$defs/RuntimeSimfWitness" + } + } + } + }, + "FinalizerSpec": { + "oneOf": [ + { + "type": "object", + "required": [ + "type" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "wallet" + } + } + }, + { + "type": "object", + "required": [ + "type", + "source_simf", + "simplicity_hl_version", + "internal_key", + "arguments", + "witness" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "simf" + }, + "source_simf": { + "type": "string" + }, + "simplicity_hl_version": { + "$ref": "#/$defs/SimplicityHLVersion" + }, + "internal_key": { + "$ref": "#/$defs/InternalKeySource" + }, + "arguments": { + "$ref": "#/$defs/SimfArguments" + }, + "witness": { + "$ref": "#/$defs/SimfWitness" + } + } + } + ] + }, + "InputSchema": { + "type": "object", + "required": [ + "id", + "utxo_source", + "unblinding", + "sequence", + "finalizer" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "utxo_source": { + "$ref": "#/$defs/UTXOSource" + }, + "unblinding": { + "$ref": "#/$defs/InputUnblinding" + }, + "sequence": { + "$ref": "#/$defs/U32" + }, + "issuance": { + "$ref": "#/$defs/InputIssuance" + }, + "finalizer": { + "$ref": "#/$defs/FinalizerSpec" + } + } + }, + "LockVariant": { + "oneOf": [ + { + "type": "object", + "required": [ + "type" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "wallet" + } + } + }, + { + "type": "object", + "required": [ + "type", + "script" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "script" + }, + "script": { + "$ref": "#/$defs/Script" + } + } + }, + { + "type": "object", + "required": [ + "type", + "finalizer" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "finalizer" + }, + "finalizer": { + "$ref": "#/$defs/FinalizerSpec" + } + } + } + ] + }, + "AssetVariant": { + "oneOf": [ + { + "type": "object", + "required": [ + "type", + "asset_id" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "asset_id" + }, + "asset_id": { + "$ref": "#/$defs/AssetId" + } + } + }, + { + "type": "object", + "required": [ + "type", + "input_index" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "new_issuance_asset" + }, + "input_index": { + "$ref": "#/$defs/U32" + } + } + }, + { + "type": "object", + "required": [ + "type", + "input_index" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "new_issuance_token" + }, + "input_index": { + "$ref": "#/$defs/U32" + } + } + }, + { + "type": "object", + "required": [ + "type", + "input_index" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "re_issuance_asset" + }, + "input_index": { + "$ref": "#/$defs/U32" + } + } + } + ] + }, + "BlinderVariant": { + "oneOf": [ + { + "const": "wallet" + }, + { + "const": "explicit" + }, + { + "type": "object", + "required": [ + "provided" + ], + "additionalProperties": false, + "properties": { + "provided": { + "type": "object", + "required": [ + "pubkey" + ], + "additionalProperties": false, + "properties": { + "pubkey": { + "$ref": "#/$defs/PublicKey" + } + } + } + } + } + ] + }, + "OutputSchema": { + "type": "object", + "required": [ + "id", + "amount_sat", + "lock", + "asset", + "blinder" + ], + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "amount_sat": { + "$ref": "#/$defs/U64" + }, + "lock": { + "$ref": "#/$defs/LockVariant" + }, + "asset": { + "$ref": "#/$defs/AssetVariant" + }, + "blinder": { + "$ref": "#/$defs/BlinderVariant" + } + }, + "allOf": [ + { + "if": { + "properties": { + "asset": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "const": "new_issuance_token" + } + } + } + }, + "required": [ + "asset" + ] + }, + "then": { + "not": { + "properties": { + "blinder": { + "const": "explicit" + } + }, + "required": [ + "blinder" + ] + } + } + } + ] + }, + "RuntimeParams": { + "type": "object", + "required": [ + "inputs", + "outputs" + ], + "additionalProperties": false, + "properties": { + "inputs": { + "type": "array", + "items": { + "$ref": "#/$defs/InputSchema" + } + }, + "outputs": { + "type": "array", + "items": { + "$ref": "#/$defs/OutputSchema" + } + }, + "fee_rate_sat_kvb": { + "type": "number", + "minimum": 0 + }, + "lock_time": { + "$ref": "#/$defs/LockTime" + } + } + }, + "TxCreateRequest": { + "type": "object", + "required": [ + "abi_version", + "request_id", + "network", + "params", + "broadcast" + ], + "additionalProperties": false, + "properties": { + "abi_version": { + "const": "wallet-abi-0.1" + }, + "request_id": { + "$ref": "#/$defs/Uuid" + }, + "network": { + "$ref": "#/$defs/Bip122ChainId" + }, + "params": { + "$ref": "#/$defs/RuntimeParams" + }, + "broadcast": { + "type": "boolean" + } + } + }, + "TransactionInfo": { + "type": "object", + "required": [ + "tx_hex", + "txid" + ], + "additionalProperties": false, + "properties": { + "tx_hex": { + "$ref": "#/$defs/Hex" + }, + "txid": { + "$ref": "#/$defs/Txid" + } + } + }, + "ErrorInfo": { + "type": "object", + "required": [ + "code", + "message" + ], + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "details": true + } + }, + "TxCreateResponse": { + "oneOf": [ + { + "type": "object", + "required": [ + "abi_version", + "request_id", + "network", + "status", + "transaction" + ], + "additionalProperties": false, + "properties": { + "abi_version": { + "const": "wallet-abi-0.1" + }, + "request_id": { + "$ref": "#/$defs/Uuid" + }, + "network": { + "$ref": "#/$defs/Bip122ChainId" + }, + "status": { + "const": "ok" + }, + "transaction": { + "$ref": "#/$defs/TransactionInfo" + }, + "artifacts": { + "type": "object", + "additionalProperties": true + } + } + }, + { + "type": "object", + "required": [ + "abi_version", + "request_id", + "network", + "status", + "error" + ], + "additionalProperties": false, + "properties": { + "abi_version": { + "const": "wallet-abi-0.1" + }, + "request_id": { + "$ref": "#/$defs/Uuid" + }, + "network": { + "$ref": "#/$defs/Bip122ChainId" + }, + "status": { + "const": "error" + }, + "error": { + "$ref": "#/$defs/ErrorInfo" + }, + "artifacts": { + "type": "object", + "additionalProperties": true + } + } + } + ] + } + } +} From b19557ace92cb41a9df0a826f480f844263f9bf7 Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Tue, 12 May 2026 12:09:59 +0300 Subject: [PATCH 2/6] wallet abi: resolve comments from first review session --- elip-wallet-abi.mediawiki | 297 +++++++++++++++++++------------------- 1 file changed, 149 insertions(+), 148 deletions(-) diff --git a/elip-wallet-abi.mediawiki b/elip-wallet-abi.mediawiki index ab1e9fc..8377286 100644 --- a/elip-wallet-abi.mediawiki +++ b/elip-wallet-abi.mediawiki @@ -1,9 +1,9 @@
   ELIP: ?
   Layer: Wallet
-  Title: Wallet ABI Transaction Create Protocol
-  Author: Kyrylo Riabov
-          Artem Chystiakov
+  Title: Wallet ABI Transaction Creation Protocol
+  Author: Kyrylo Riabov 
+          Artem Chystiakov 
   Comments-Summary: No comments yet.
   Comments-URI: TBD
   Status: Draft
@@ -23,9 +23,7 @@ wallet snapshot, resolves wallet-owned and caller-provided prevouts, materialize
 outputs as needed, signs/finalizes inputs, optionally broadcasts, and returns either a finalized transaction or a structured error.
 
 The protocol is '''state-aware and non-idempotent'''. The same request may yield different successful transactions
-when wallet state, fee policy, UTXO availability, or broadcast state changes. For a single runtime request lifecycle,
-however, the runtime should use a stable wallet snapshot and deterministic output allocation so fee estimation and
-final build are internally consistent.
+when wallet state, fee policy, UTXO availability, or broadcast state changes.
 
 === Copyright ===
 
@@ -34,31 +32,28 @@ This document is licensed under the 3-clause BSD license.
 === Motivation ===
 
 Applications need a standard way to ask a wallet to construct and sign a transaction from an application-level intent
-while keeping wallet-owned UTXOs inside the wallet. This protocol provides a signing capability to the requester,
-but the wallet NEVER shares its UTXO set, balances, or wallet-internal selection state with the requester to facilitate the signing.
+while keeping wallet-owned UTXOs private to the wallet. This protocol defines a communication schema that provides a signing capability to the requester,
+allowing the wallet to never share its UTXO set, balances, or wallet-internal selection state with the requester to facilitate the signing.
 
 === Goals and non-goals ===
 
 ==== Goals ====
 
-# Provide a reviewable definition of all request and response fields.
-# Make the user experience clear enough for wallet UI design.
-# Make non-idempotency and runtime state dependence explicit.
-# Use genesis-hash-based BIP-122/CAIP-2-style network identifiers instead of bare network names.
-# Provide JSON examples and a review JSON Schema.
+# Provide a reviewable definition of all Wallet ABI request and response fields.
+# Make the user experience clear enough for wallet/application communication.
+# Provide JSON examples and a complete JSON schema.
 
 ==== Non-goals ====
 
 # Define a final WalletConnect, JSON-RPC, or transport-level standard. This document describes the ABI payload.
 # Define full SimplicityHL semantic validation. This document describes how the payload is carried and resolved.
 # Guarantee exact final transaction shape from declared outputs. The runtime may add fee and change outputs.
-# Treat request_id as replay protection. It is correlation only.
 
 == Specification ==
 
 === Normative language ===
 
-The words '''MUST''', '''SHOULD''', '''MAY''', and '''MUST NOT''' are used in the [https://www.rfc-editor.org/rfc/rfc2119 RFC 2119] sense for this draft.
+The words '''MUST''', '''SHOULD''', '''MAY''', and '''MUST NOT''' are used in the RFC 2119 sense for this draft.
 
 === Terminology ===
 
@@ -67,8 +62,8 @@ The words '''MUST''', '''SHOULD''', '''MAY''', and '''MUST NOT''' are used in th
 ! Term
 ! Definition
 |-
-| Caller / Producer / Dapp
-| Web app or protocol app that creates a TxCreateRequest.
+| Caller / Producer / Application
+| Application or protocol participant that creates a TxCreateRequest.
 |-
 | Consumer / runtime
 | Wallet/mobile/daemon side that processes the request.
@@ -89,7 +84,7 @@ The words '''MUST''', '''SHOULD''', '''MAY''', and '''MUST NOT''' are used in th
 | SimplicityHL finalization payload carrying source, compiler version, JSON arguments, JSON witness values, and internal key source.
 |-
 | Internal key source
-| Selector that must return a Taproot/BIP340 x-only public key for control-block/script derivation.
+| Selector that returns a Taproot/BIP340 x-only public key for control-block/script derivation.
 |-
 | BIP-122 chain id
 | A genesis-hash-based chain identifier represented in this ABI as a CAIP-2-style bip122:32-lowercase-hex string.
@@ -110,14 +105,14 @@ The words '''MUST''', '''SHOULD''', '''MAY''', and '''MUST NOT''' are used in th
 | Authenticated context that lets a wallet show which actor initiated the request. This ABI does not define the identity system; it only requires wallets not to trust self-declared JSON labels as identity.
 |}
 
-=== User experience contract ===
+=== Wallet/application user experience guidance ===
 
 ==== Caller-side flow ====
 
-# The web app builds a transaction intention in terms of wallet inputs, provided inputs, requested outputs, issuance outputs, and finalizers.
-# The web app generates a fresh request_id for this user action.
-# The web app sends a TxCreateRequest over the chosen transport.
-# The web app treats the returned TxCreateResponse as the only authoritative result for this processing attempt.
+# The caller builds a transaction intention in terms of wallet inputs, provided inputs, requested outputs, issuance outputs, and finalizers.
+# The caller generates a fresh request_id for this user action.
+# The caller sends a TxCreateRequest over the chosen transport.
+# The caller treats the returned TxCreateResponse as the only authoritative result for this processing attempt.
 
 ==== Wallet/consumer-side review UI ====
 
@@ -135,7 +130,7 @@ A wallet UI SHOULD present, before approval:
 | Prevents Liquid mainnet/testnet/localtest confusion. Show the BIP-122 chain id and, if known, a friendly network label.
 |-
 | request_id
-| Helps support/debug correlation. It should not be described as replay protection.
+| Helps support/debug correlation. It MUST NOT be described as replay protection.
 |-
 | broadcast
 | Distinguishes "build/sign only" from "publish to network".
@@ -147,7 +142,7 @@ A wallet UI SHOULD present, before approval:
 | The declared output set is not the final transaction set.
 |-
 | Wallet asset deltas
-| The user should approve net wallet effect, not just declared outputs.
+| Shows net wallet effect, not just declared outputs.
 |-
 | Explicit outputs
 | Warn when amount/asset confidentiality is disabled.
@@ -165,17 +160,14 @@ A wallet UI SHOULD present, before approval:
 | Warn that lock_time is ineffective when all sequences are final.
 |}
 
-App/request identity is intentionally not a new trusted JSON field in this ABI. A wallet MUST NOT identify
-the caller from self-declared labels inside the request payload. The authenticated caller context must come from the
-transport or platform binding, for example a browser origin/RP ID, native-app association, pairing session, signed
-registry entry, or another out-of-band identity system. This draft only says that such identity is important for UI review;
-exact discovery, registry, branding, and anti-phishing UI rules are out of scope for wallet-abi-0.1.
+A wallet MUST NOT identify the caller from self-declared labels inside the request payload.
+Authenticated app/request identity MUST come from the transport, platform binding, or another out-of-band trust system.
 
 ==== Response UX ====
 
 The response is not a deterministic preview of an abstract request. It is the result of a specific processing attempt
-against a specific wallet state. On success, the UI should show whether the transaction was merely built or was broadcast.
-On error, product logic should branch on error.code, while error.message should be treated as technical context.
+against a specific wallet state. On success, the UI SHOULD show whether the transaction was merely built or was broadcast.
+On error, application logic SHOULD branch on error.code, while error.message is technical context.
 
 === Non-idempotency and deterministic boundaries ===
 
@@ -189,9 +181,6 @@ The runtime SHOULD provide deterministic behavior only within this narrower boun
 # Return the same wallet output template for the same (session, request) pair.
 # Resolve declared inputs in order and update funding state sequentially.
 
-The same JSON request sent later MAY produce a different transaction because wallet UTXOs, already-spent state,
-chain height, fee policy, selected change outputs, and broadcast outcomes can change.
-
 === Wire-format rules ===
 
 # Payloads are JSON objects unless a variant is explicitly serialized as a string.
@@ -248,8 +237,7 @@ chain height, fee policy, selected change outputs, and broadcast outcomes can ch
 
 ==== Bip122ChainId ====
 
-network MUST use the [https://standards.chainagnostic.org/CAIPs/caip-2 CAIP-2] / [https://namespaces.chainagnostic.org/bip122/caip2 BIP122 namespace]
-wire shape derived from the [https://bips.dev/122/ BIP-122] chain-id concept:
+network MUST use the CAIP-2 BIP122 namespace wire shape derived from the BIP-122 chain-id concept:
 
 
bip122:00000000000000000000000000000000
where genesis-prefix is the first 16 bytes of the chain genesis block hash, encoded as 32 lowercase hex @@ -354,8 +342,24 @@ The ABI does not rely on bare strings such as liquid, testnet ==== UTXOSource ==== -
{ "wallet": { "filter": { "asset": "none", "amount": "none", "lock": "none" } } }
-
{ "provided": { "outpoint": "0000000000000000000000000000000000000000000000000000000000000000:0" } }
+
{
+  "wallet": {
+    "filter": {
+      "asset": "none",
+      "amount": "none",
+      "lock": "none"
+    }
+  }
+}
+ +or + +
{
+  "provided": {
+    "outpoint": "0000000000000000000000000000000000000000000000000000000000000000:0"
+  }
+}
+ {| class="wikitable" |- ! Variant @@ -406,14 +410,9 @@ The ABI does not rely on bare strings such as liquid, testnet | Use caller-supplied input blinding secret key for a confidential prevout. This is prevout-unblinding material, not a wallet signing key. Sensitive by default; '''never log'''. |- | "explicit" -| Require explicit non-confidential prevout values. Confidential prevouts should fail. +| Require explicit non-confidential prevout values. Runtime MUST reject confidential prevouts. |} -A dapp can provide blinding_secret_key only when it already knows the prevout unblinding material out -of band or the protocol intentionally uses shared/known blinding material. Some Simplicity contract constructions -can work with public or contract-known blinding material; the field is still named after its cryptographic role so -it is not confused with a spend key. Unless local policy explicitly classifies the material as public, the runtime MUST handle it as secret. - ==== InputIssuance ==== {| class="wikitable" @@ -432,7 +431,7 @@ it is not confused with a spend key. Unless local policy explicitly classifies t |- | inflation_amount_sat | style="text-align: right;"| u64 -| Amount of reissuance/inflation-token units to mint. Replaces the older token_amount_sat naming to avoid confusing token amount with ordinary asset amount. +| Amount of reissuance/inflation-token units to mint. |- | entropy | style="text-align: right;"| [u8; 32] @@ -492,7 +491,7 @@ inflation token must satisfy the confidentiality rule in [[#AssetVariant|AssetVa |- | script | {"type":"script","script":"0014aabbccddeeff00112233445566778899aabbccdd"} -| Use raw script-pubkey bytes (includes OP_RETURN, burn, etc.). Empty script should be rejected by runtime. +| Use raw script-pubkey bytes (includes OP_RETURN, burn, etc.). Runtime MUST reject empty scripts. |- | finalizer | {"type":"finalizer","finalizer": ...} @@ -524,10 +523,7 @@ inflation token must satisfy the confidentiality rule in [[#AssetVariant|AssetVa In this ABI, new_issuance_token denotes the confidential reissuance/inflation-token variant. Any output whose asset resolves to new_issuance_token MUST be confidential: -the runtime MUST reject blinder = "explicit" for that output. This is required for compatibility with -the current reissuance model on Liquid, where reissuance tokens must remain confidential to be usable; -see [https://github.com/BlockstreamResearch/SimplicityHL/issues/309 SimplicityHL issue #309]. -Explicit reissuance-token support, if added later, belongs in Future Work and would require an ABI/capability update. +the runtime MUST reject blinder = "explicit" for that output. ==== BlinderVariant ==== @@ -537,7 +533,7 @@ Explicit reissuance-token support, if added later, belongs in Future Work and wo ! Definition |- | "wallet" -| Use wallet output template blinding pubkey. Should be paired with lock.type = "wallet". +| Use wallet output template blinding pubkey. Normally paired with lock.type = "wallet". |- | {"provided":{"pubkey":"..."}} | Use caller-supplied blinding public key. @@ -613,33 +609,25 @@ Delegates input finalization to the wallet signer/miniscript stack. | SIMF witness payload as JSON. Contains caller-known static_values and runtime-resolved runtime_arguments. |} -simplicity_hl_version is intentionally part of the wire request because different -[https://github.com/BlockstreamResearch/SimplicityHL SimplicityHL] compiler versions may produce different -compiled programs, CMRs, addresses, script pubkeys, or finalization behavior from the same source_simf. - A runtime MUST compile source_simf with the requested simplicity_hl_version; it MUST NOT silently substitute a different compiler version. When a SIMF finalizer is used for an input, the runtime MUST derive the expected finalizer script pubkey from the explicitly requested SIMF source, version, internal_key, and finalizer payload. After resolving utxo_source, the runtime MUST verify that the resolved prevout script -pubkey matches that computed script pubkey before signing or finalizing. A mismatch MUST be rejected, because otherwise -the wallet could be tricked into signing a transaction for a UTXO locked by a different program. +pubkey matches that computed script pubkey before signing or finalizing. A mismatch MUST be rejected. === Internal key source === ==== Stable variant: bip0341 ==== -The only stable InternalKeySource variant in wallet-abi-0.1 is: -
"bip0341"
-It returns the fixed [https://bips.dev/341/ BIP-0341] NUMS/example x-only internal key: +A runtime MUST return this value:
50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0
-This variant is deterministic, portable, and safe as the initial interoperability baseline. === SIMF argument and witness payloads === FinalizerSpec::Simf.arguments and FinalizerSpec::Simf.witness are JSON objects -at the ABI wire level. They are not UTF-8 byte arrays in wallet-abi-0.1. +at the ABI wire level. They are not UTF-8 byte arrays in this standard. ==== static_values ==== @@ -647,9 +635,7 @@ at the ABI wire level. They are not UTF-8 byte arrays in wallet-abi-0.1WitnessValues / WitnessNames model: each top-level key is a SimplicityHL argument or -witness name, and each value has two string fields: +Each top-level key is a SimplicityHL argument or witness name, and each value has two string fields:
{
   "NAME": {
@@ -657,50 +643,13 @@ witness name, and each value has two string fields:
     "type": "Either(...)"
   }
 }
-value MUST be encoded as a JSON string, even for numbers and booleans, because the SimplicityHL parser -consumes Rust-like typed literals such as "100", "false", "(true, 376)", -"Left(...)", or "Right(...)". type MUST also be encoded as a JSON string, -for example "u64", "Signature", "(bool, u64)", or "Either(...)". -The runtime MUST treat both fields as untrusted compiler input and rely on the requested simplicity_hl_version -parser/type checker before using them. +value MUST be encoded as a JSON string, even for numbers and booleans. type MUST also be encoded as a JSON string. +The runtime MUST treat both fields as untrusted compiler input and parse/type-check them with the requested simplicity_hl_version. For arguments.static_values, keys are static SimplicityHL argument/parameter names. For witness.static_values, keys are static SimplicityHL witness names. The exact accepted names and types are defined by source_simf and the requested compiler version. -==== static_values examples ==== - -For readability, the inline examples below abbreviate long SimplicityHL sum types as Either(...). -The auxiliary request fixture contains concrete mock type strings. - -A single branch selector known by the app at request-construction time: - -
{
-  "PATH": {
-    "value": "Right(Right((false, 10, 1000)))",
-    "type": "Either(...)"
-  }
-}
-The same witness name selecting a different branch: - -
{
-  "PATH": {
-    "value": "Right(Left((false, 10, 1000)))",
-    "type": "Either(...)"
-  }
-}
-Multiple static witness values: - -
{
-  "PATH": {
-    "value": "Left(Right(Left((false, 10, 1000, 500))))",
-    "type": "Either(...)"
-  },
-  "COLLATERAL_AMOUNT": {
-    "value": "10",
-    "type": "u32"
-  }
-}
==== runtime_arguments ==== runtime_arguments carries directives for values the app cannot know at request-construction time. @@ -732,7 +681,7 @@ Supported runtime argument directives: | Resolve a u256 value from the confidential reissuance/inflation-token ID of a new issuance input. |} -For FinalizerSpec::Simf.witness, runtime_arguments is currently an array of witness directives: +For FinalizerSpec::Simf.witness, runtime_arguments is an array of witness directives:
{
   "static_values": {
@@ -752,41 +701,30 @@ For FinalizerSpec::Simf.witness, runtime_arguments is
 }
sig_hash_all.public_key MUST match the runtime signer x-only public key before the runtime signs. -==== TODO: witness signature embedding ==== - -sig_hash_all is intentionally still draft/TODO. The current shape names the target witness slot (name) and the -expected signer x-only public key (public_key), but this draft does not yet finalize how the generated BIP-340 signature -is embedded back into the SimplicityHL WitnessValues structure that could include branching (Right(Left((, ...)))). - === Runtime processing model === Provider-specific state objects and wallet output allocation internals are informative implementation details in Appendix B. A conforming runtime MAY process a request in this order: -# Decode JSON and reject unknown envelope/runtime fields. -# Validate abi_version and network against runtime context. -# Open one wallet request session. -# Resolve declared inputs in order. -# For any SIMF-finalized input, compile the requested source_simf with simplicity_hl_version, -derive the expected finalizer script pubkey, and reject if the resolved UTXO script pubkey does not match. -# Resolve issuance metadata for inputs and any issuance-linked output asset IDs. -# Materialize declared outputs in order. -# Estimate fee and balance supply/demand. -# Append wallet funding inputs if needed. -# Append fee output and per-asset change outputs as needed. -# Blind the transaction where requested. -# MAY present a review/approval stage once the runtime has enough information to show the materialized transaction effects, -including runtime-added inputs/outputs, fee/change, confidentiality choices, issuance/inflation-token effects, SIMF program -identity, and broadcast intent. Exact placement is runtime-dependent and may happen before finalization, during a -hardware-device signing flow, after finalization, or immediately before broadcast. -# Finalize wallet inputs and SIMF inputs. -# If broadcast = true, MAY perform a separate broadcast approval according to runtime policy, -then broadcast and return the backend-reported txid. -# Return TxCreateResponse with status = "ok" or status = "error". - -The review/approval stage is a MAY, not a mandatory protocol step, because some runtimes are non-interactive while -others split approval across wallet UI, hardware-device prompts, finalization, and broadcast confirmation. +
    +
  1. Decode JSON and reject unknown envelope/runtime fields.
  2. +
  3. Validate abi_version and network against runtime context.
  4. +
  5. Open one wallet request session.
  6. +
  7. Resolve declared inputs in order.
  8. +
  9. For any SIMF-finalized input, compile the requested source_simf with simplicity_hl_version, derive the expected finalizer script pubkey, and reject if the resolved UTXO script pubkey does not match.
  10. +
  11. Resolve issuance metadata for inputs and any issuance-linked output asset IDs.
  12. +
  13. Materialize declared outputs in order.
  14. +
  15. Estimate fee and balance supply/demand.
  16. +
  17. Append wallet funding inputs if needed.
  18. +
  19. Append fee output and per-asset change outputs as needed.
  20. +
  21. Blind the transaction where requested.
  22. +
  23. MAY present a review/approval stage after materialized transaction effects are available.
  24. +
  25. Finalize wallet inputs and SIMF inputs.
  26. +
  27. If broadcast = true, perform any separate broadcast approval required by runtime policy, then broadcast and return the backend-reported txid.
  28. +
  29. Return TxCreateResponse with status = "ok" or status = "error".
  30. +
+ The returned TxCreateResponse remains the only authoritative result of the processing attempt. === Response envelope: TxCreateResponse === @@ -832,11 +770,11 @@ The returned TxCreateResponse remains the only authoritative result |- | transaction.txid | style="text-align: right;"| txid -| Transaction ID of tx_hex; if broadcasted, should match backend-reported txid. +| Transaction ID of tx_hex; if broadcasted, SHOULD match backend-reported txid. |- | artifacts | style="text-align: right;"| object -| Optional producer metadata. Open-ended; consumers must ignore unknown keys. +| Optional producer metadata. Open-ended; consumers MUST ignore unknown keys. |} ==== Error ==== @@ -864,7 +802,7 @@ The returned TxCreateResponse remains the only authoritative result |- | error.code | style="text-align: right;"| string -| Stable machine category. Unknown strings should be preserved/tolerated. +| Stable machine category. Consumers SHOULD preserve/tolerate unknown strings. |- | error.message | style="text-align: right;"| string @@ -904,7 +842,7 @@ The returned TxCreateResponse remains the only authoritative result | Signer unavailable or configured with wrong key. |- | invalid_response -| Runtime/adapter response contract failure. +| Runtime/adapter response invariant failure. |- | pset | PSET construction/finalization failure. @@ -923,7 +861,7 @@ The returned TxCreateResponse remains the only authoritative result # abi_version changes are required for incompatible request/response shape changes. # New enum variants SHOULD be gated by ABI version or explicit capability negotiation. -# artifacts is the preferred place for producer-defined metadata that should not break older consumers. +# artifacts is the preferred place for producer-defined metadata that does not break older consumers. # Unknown request fields are rejected by the current Rust request/runtime parameter schemas; do not use unknown fields for extension. # Runtimes that cannot satisfy simplicity_hl_version MUST reject rather than silently compiling with another version. # A future ABI may define friendly network aliases, but wire-level matching in this ABI is by BIP-122 chain id. @@ -933,7 +871,7 @@ The returned TxCreateResponse remains the only authoritative result # Treat all request data as untrusted, including scripts, outpoints, finalizer source, and pubkeys. # Never log InputUnblinding.provided.blinding_secret_key or intermediate PSETs containing resolved input secrets. -# InputUnblinding.provided.blinding_secret_key is not a signing key, but it can reveal confidential prevout values and should be treated as sensitive unless explicitly policy-marked as public. +# InputUnblinding.provided.blinding_secret_key is not a signing key, but it can reveal confidential prevout values and is sensitive unless explicitly policy-marked as public. # broadcast = false does not mean offline/no-network; runtime may sync wallet state and fetch prevouts. # explicit outputs reveal amount and asset. # Outputs carrying new_issuance_token MUST NOT be explicit in this ABI. @@ -941,8 +879,8 @@ The returned TxCreateResponse remains the only authoritative result # lock_time can be ineffective if input sequences are final. # SIMF sig_hash_all.public_key must equal the runtime signer x-only key. # source_simf must be compiled with the requested simplicity_hl_version; runtimes MUST NOT silently substitute a different compiler version. -# Consumer UIs should make network and broadcast status prominent. -# Consumers should ignore unknown artifacts keys and sanitize error.message/error.details before rendering. +# Consumer UIs SHOULD make network and broadcast status prominent. +# Consumers SHOULD ignore unknown artifacts keys and sanitize error.message/error.details before rendering. # Wallets MUST NOT trust self-declared app names, labels, URLs, or icons in the request payload as authenticated caller identity. Authenticated app/request identity must come from the transport/platform binding or another out-of-band trust system. # static_values.value and static_values.type are untrusted SimplicityHL compiler inputs. Parse and type-check them with the requested simplicity_hl_version; do not evaluate them with an ad hoc parser outside the compiler boundary. # For SIMF-finalized inputs, the resolved UTXO script pubkey must match the script pubkey derived from the requested SIMF finalizer before signing/finalization. @@ -955,6 +893,17 @@ the genesis hash of the active Elements chain. This avoids ambiguity between Liq request_id is a correlation identifier rather than replay protection because wallet state, UTXO availability, fee policy, and broadcast status can change between attempts. Treating the request as non-idempotent avoids giving callers a false guarantee that the same JSON body will always produce the same transaction. +The same JSON request sent later may produce a different transaction because wallet UTXOs, already-spent state, +chain height, fee policy, selected change outputs, and broadcast outcomes can change. + +App/request identity is intentionally not a trusted JSON field in this ABI. The authenticated caller context can come from +a browser origin/RP ID, native-app association, pairing session, signed registry entry, or another out-of-band identity system. +Exact discovery, registry, branding, and anti-phishing UI rules are out of scope for this standard. + +Input blinding secret keys can be provided only when the caller already knows the prevout unblinding material out of band +or the protocol intentionally uses shared/known blinding material. Some Simplicity contract constructions can work with +public or contract-known blinding material; the field is still named after its cryptographic role so it is not confused +with a spend key. SIMF payloads are JSON objects at the wire level to make review, schema validation, and application construction easier. Static SIMF values use the SimplicityHL witness-style { "value": string, "type": string } shape because the @@ -964,9 +913,15 @@ compiler, not the ABI, is responsible for parsing and type-checking Rust-like Si intended by the caller. This is required because different compiler versions may produce different compiled programs, addresses, script pubkeys, or finalization behavior. +The stable bip0341 internal key source uses the BIP-341 NUMS/example x-only internal key because it is deterministic, +portable, and suitable as the initial interoperability baseline. + Outputs carrying new_issuance_token are required to be confidential in this ABI to match the current -Liquid reissuance-token constraint. Explicit reissuance-token support can be considered later if the underlying -validation model and ABI capability negotiation make it safe. +Liquid reissuance-token constraint. + +Review and approval staging is runtime-dependent. Some runtimes are non-interactive; others split approval across wallet UI, +hardware-device prompts, finalization, and broadcast confirmation. The response remains the authoritative result regardless +of how the runtime structures those local stages. == Backwards Compatibility == @@ -1013,12 +968,48 @@ and schema constraints, but they are expected to be corrected or replaced after | Issuance request using a SIMF finalizer, stable bip0341 internal key, simplicity_hl_version, JSON arguments/witness, static_values examples, inflation_amount_sat, and confidential new_issuance_token output. |- | [[elip-wallet-abi/wallet-abi-tx-create.schema.json|wallet-abi-tx-create.schema.json]] -| Review JSON Schema for request/response shape. It includes the BIP-122 chain-id pattern, blinding_secret_key, inflation_amount_sat, simplicity_hl_version, JSON SIMF payloads, static_values typed literals, stable bip0341, and a schema-level rejection of blinder = "explicit" when asset.type = "new_issuance_token". +| Complete JSON Schema for request/response shape. It includes the BIP-122 chain-id pattern, blinding_secret_key, inflation_amount_sat, simplicity_hl_version, JSON SIMF payloads, static_values typed literals, stable bip0341, and a schema-level rejection of blinder = "explicit" when asset.type = "new_issuance_token". |- | [[elip-wallet-abi/field-reference.json|field-reference.json]] | Machine-readable field reference for implementers and UI review. |} +=== Static value examples === + +For readability, the examples below abbreviate long SimplicityHL sum types as Either(...). +The auxiliary request fixture contains concrete mock type strings. + +A single branch selector known by the application at request-construction time: + +
{
+  "PATH": {
+    "value": "Right(Right((false, 10, 1000)))",
+    "type": "Either(...)"
+  }
+}
+ +The same witness name selecting a different branch: + +
{
+  "PATH": {
+    "value": "Right(Left((false, 10, 1000)))",
+    "type": "Either(...)"
+  }
+}
+ +Multiple static witness values: + +
{
+  "PATH": {
+    "value": "Left(Right(Left((false, 10, 1000, 500))))",
+    "type": "Either(...)"
+  },
+  "COLLATERAL_AMOUNT": {
+    "value": "10",
+    "type": "u32"
+  }
+}
+ == References == These links are intentionally listed directly so reviewers do not need to search for the underlying standards or context. @@ -1071,7 +1062,7 @@ These links are intentionally listed directly so reviewers do not need to search |- | Elements chainparams.cpp | https://raw.githubusercontent.com/ElementsProject/elements/master/src/chainparams.cpp -| Source reference for chain/network parameters such as liquidv1. Implementations should derive the active chain id from their node/runtime rather than trusting a hard-coded label. +| Source reference for chain/network parameters such as liquidv1. Implementations derive the active chain id from their node/runtime rather than trusting a hard-coded label. |- | Go Elements network parameters | https://pkg.go.dev/github.com/dirtyhighli/go-elements/network @@ -1135,6 +1126,16 @@ for enum variants; and supported simplicity_hl_version discovery. The wire network is a BIP-122 chain id in this draft. A future profile may define friendly labels, policy-asset metadata, and local/custom Elements network registry entries, but those aliases must not replace genesis-hash matching in the core validation path. +=== A.4 Explicit reissuance-token support === + +Explicit reissuance-token support, if added later, would require an ABI/capability update and a validation model that safely supports non-confidential token outputs. + +=== A.5 Witness signature embedding === + +sig_hash_all names the target witness slot (name) and expected signer x-only public key (public_key). +A future ABI will need to finalize how the generated BIP-340 signature is embedded back into the SimplicityHL WitnessValues structure, +including structures that contain branching such as Right(Left((, ...))). + == Appendix B: Informative consumer/runtime implementation notes == This appendix is not a caller-visible wire schema and is not required as provider API surface. It records one useful @@ -1186,7 +1187,7 @@ and UI-state machines remain out of scope for the core ABI payload. | Optional blinding public key for confidential outputs. |} -A wallet output allocator should be stable for the same (session, request) pair if the provider exposes +A wallet output allocator is expected to be stable for the same (session, request) pair if the provider exposes preview/final-build behavior, but this is an implementation note rather than a separate ABI field. == Appendix C: JSON Schema == From 543287b3516b30da4c2f3b838f0b6764eaebb69d Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Tue, 12 May 2026 13:11:31 +0300 Subject: [PATCH 3/6] wallet abi: reference elip 144 instead of bip 122, replace number encoding for the amounts with strings --- elip-wallet-abi.mediawiki | 182 ++++++++---------- .../01_request_wallet_to_script.json | 12 +- .../02_response_ok_build_only.json | 14 +- .../03_response_error_funding.json | 10 +- .../04_request_simf_bip0341_issuance.json | 18 +- elip-wallet-abi/field-reference.json | 24 +-- .../wallet-abi-tx-create.schema.json | 85 ++++---- 7 files changed, 170 insertions(+), 175 deletions(-) diff --git a/elip-wallet-abi.mediawiki b/elip-wallet-abi.mediawiki index 8377286..1f97b20 100644 --- a/elip-wallet-abi.mediawiki +++ b/elip-wallet-abi.mediawiki @@ -18,7 +18,7 @@ wallet-abi-0.1 defines a JSON request/response protocol for transaction construction. The caller declares intended inputs, outputs, fee hints, locktime hints, issuance metadata, and finalization rules. The wallet/runtime -validates the request against its active BIP-122/CAIP-2 chain identifier and wallet state, opens a request-scoped +validates the request against its active ELIP-0144 chain_id and wallet state, opens a request-scoped wallet snapshot, resolves wallet-owned and caller-provided prevouts, materializes declared outputs, appends fee/change outputs as needed, signs/finalizes inputs, optionally broadcasts, and returns either a finalized transaction or a structured error. @@ -86,8 +86,14 @@ The words '''MUST''', '''SHOULD''', '''MAY''', and '''MUST NOT''' are used in th | Internal key source | Selector that returns a Taproot/BIP340 x-only public key for control-block/script derivation. |- -| BIP-122 chain id -| A genesis-hash-based chain identifier represented in this ABI as a CAIP-2-style bip122:32-lowercase-hex string. +| ELIP-0144 chain ID +| The chain_id string defined by ELIP-0144, e.g. bip122:<32-lowercase-hex>. +|- +| ELIP-0144 asset ID +| The asset_id string defined by ELIP-0144, encoded as chain_id/elip144:asset_reference. +|- +| Asset reference +| The raw 32-byte Elements asset identifier carried inside an ELIP-0144 asset ID after /elip144:. It is used internally when materializing transaction outputs and SIMF u256 values. |- | Input blinding secret key | Secret key material used to unblind a confidential prevout. It is not a wallet signing key or spend authorization key. @@ -126,8 +132,8 @@ A wallet UI SHOULD present, before approval: | App/request identity | Helps the user connect request to the initiating action. |- -| network -| Prevents Liquid mainnet/testnet/localtest confusion. Show the BIP-122 chain id and, if known, a friendly network label. +| chain_id +| Prevents Liquid mainnet/testnet/regtest confusion. Show the ELIP-0144 chain ID and, if known, a friendly network label. |- | request_id | Helps support/debug correlation. It MUST NOT be described as replay protection. @@ -186,11 +192,11 @@ The runtime SHOULD provide deterministic behavior only within this narrower boun # Payloads are JSON objects unless a variant is explicitly serialized as a string. # Enum variants use snake_case. # TxCreateRequest and RuntimeParams reject unknown fields in the attached Rust schema. -# Numeric satoshi amounts are unsigned 64-bit values. JavaScript callers SHOULD avoid unsafe integer conversion for values above 2^53 - 1. +# Numeric satoshi amounts are unsigned 64-bit values encoded as decimal JSON strings, with no leading zeroes except "0". # Byte-array fields, such as issuance entropy, are serialized as JSON arrays of integers from 0 to 255. # FinalizerSpec::Simf.arguments and FinalizerSpec::Simf.witness are JSON objects. # Hex fields are lowercase by convention, but consumers SHOULD accept uppercase only if their underlying parsers do. -# network is a BIP-122/CAIP-2-style chain id string of the form bip122:32-lowercase-hex. +# chain_id and explicit asset_id values MUST use the ELIP-0144 wire shapes. # Secrets, including provided input blinding secret keys and intermediate PSET material, MUST NOT be logged. === Request envelope: TxCreateRequest === @@ -198,7 +204,7 @@ The runtime SHOULD provide deterministic behavior only within this narrower boun
{
   "abi_version": "wallet-abi-0.1",
   "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
-  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
+  "chain_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
   "params": { "inputs": [], "outputs": [] },
   "broadcast": false
 }
@@ -219,10 +225,10 @@ The runtime SHOULD provide deterministic behavior only within this narrower boun | style="text-align: center;"| yes | Caller-generated correlation identifier. Generate fresh per user action. Not replay protection. |- -| network -| style="text-align: right;"| Bip122ChainId +| chain_id +| style="text-align: right;"| Elip144ChainId | style="text-align: center;"| yes -| Target Elements/Liquid chain id. MUST match the runtime chain id before side effects. +| Target Elements/Liquid chain ID as defined by ELIP-0144. MUST match the runtime chain ID before side effects. |- | params | style="text-align: right;"| RuntimeParams @@ -235,38 +241,27 @@ The runtime SHOULD provide deterministic behavior only within this narrower boun | true means publish through wallet broadcaster after finalization. false means build/finalize only; runtime may still sync/fetch. |} -==== Bip122ChainId ==== +==== Elip144ChainId ==== -network MUST use the CAIP-2 BIP122 namespace wire shape derived from the BIP-122 chain-id concept: +chain_id MUST use the chain ID wire shape defined by ELIP-0144:
bip122:00000000000000000000000000000000
-where genesis-prefix is the first 16 bytes of the chain genesis block hash, encoded as 32 lowercase hex -characters. The runtime MUST derive its active chain id from the active Elements node or equivalent runtime context -and reject a request whose network does not match. +where the reference is the first 32 characters of the network genesis block hash. The runtime MUST derive its active +chain ID from the active Elements node or equivalent runtime context and reject a request whose chain_id does +not match. -Known Liquid/Elements examples: +==== Elip144AssetId ==== -{| class="wikitable" -|- -! Network -! Full genesis hash -! ABI network value -|- -| Liquid mainnet (liquidv1) -| 1466275836220db2944ca059a3a10ef6fd2ea684b0688d2c379296888a206003 -| bip122:1466275836220db2944ca059a3a10ef6 -|- -| Liquid testnet (liquidtestnet) -| a771da8e52ee6ad581ed1e9a99825e5b3b7992225534eaa2ae23244fe26ab1c1 -| bip122:a771da8e52ee6ad581ed1e9a99825e5b -|- -| Default Elements regtest/localtest -| 00902a6b70c2ca83b5d9c815d96a0e2f4202179316970d14ea1847dae5b1ca21 -| bip122:00902a6b70c2ca83b5d9c815d96a0e2f -|} +Explicit caller-provided asset IDs MUST use the ELIP-0144 asset ID wire shape: + +
bip122:00000000000000000000000000000000/elip144:0000000000000000000000000000000000000000000000000000000000000000
-The ABI does not rely on bare strings such as liquid, testnet-liquid, or -localtest-liquid. Implementations MAY display friendly labels, but matching MUST be done against the chain id. +The part before /elip144: is the ELIP-0144 chain_id. It MUST equal TxCreateRequest.chain_id. +The part after /elip144: is the 32-byte Elements asset reference encoded as 64 lowercase hex characters. +Raw asset references are not accepted as explicit caller-provided asset identifiers in this ABI. + +Transport profiles that expose account identity SHOULD use the ELIP-0144 account ID form chain_id:dwid and +MUST ensure that the account chain prefix matches TxCreateRequest.chain_id. === Runtime parameters: RuntimeParams === @@ -385,11 +380,11 @@ or |- | asset | "none" or {"exact":{"asset_id"}} -| No asset constraint, or exact asset match. +| No asset constraint, or exact ELIP-0144 asset ID match. The asset ID chain prefix MUST match TxCreateRequest.chain_id. |- | amount | "none", {"exact":{"amount_sat"}}, {"min":{"amount_sat"}} -| No amount constraint, exact amount, or minimum amount. +| No amount constraint, exact amount, or minimum amount. amount_sat is a u64 decimal string. |- | lock | "none" or {"script":{"script"}} @@ -426,11 +421,11 @@ or | One of "new" or "reissue". |- | asset_amount_sat -| style="text-align: right;"| u64 +| style="text-align: right;"| u64 decimal string | Amount of issued/reissued asset units to mint. |- | inflation_amount_sat -| style="text-align: right;"| u64 +| style="text-align: right;"| u64 decimal string | Amount of reissuance/inflation-token units to mint. |- | entropy @@ -439,7 +434,7 @@ or |} Issuance-derived outputs reference inputs by positional input_index. Reordering inputs changes -the derived asset IDs. If a new issuance mints inflation_amount_sat > 0, outputs that carry the derived +the derived asset references and therefore the derived ELIP-0144 asset IDs. If a new issuance mints a nonzero inflation_amount_sat, outputs that carry the derived inflation token must satisfy the confidentiality rule in [[#AssetVariant|AssetVariant]]. === Output schema: OutputSchema === @@ -457,7 +452,7 @@ inflation token must satisfy the confidentiality rule in [[#AssetVariant|AssetVa | Caller label for diagnostics/UI. |- | amount_sat -| style="text-align: right;"| u64 +| style="text-align: right;"| u64 decimal string | style="text-align: center;"| yes | Requested output amount. |- @@ -506,16 +501,16 @@ inflation token must satisfy the confidentiality rule in [[#AssetVariant|AssetVa ! Definition |- | asset_id -| Caller-provided asset ID. +| Caller-provided ELIP-0144 asset ID. The chain_id prefix MUST equal TxCreateRequest.chain_id. |- | new_issuance_asset -| Asset ID derived from a new issuance input. +| ELIP-0144 asset ID derived from a new issuance input using TxCreateRequest.chain_id and the derived asset reference. |- | new_issuance_token -| Confidential reissuance/inflation-token ID derived from a new issuance input. +| Confidential reissuance/inflation-token ELIP-0144 asset ID derived from a new issuance input using TxCreateRequest.chain_id and the derived token asset reference. |- | re_issuance_asset -| Asset ID derived from a reissue input. +| ELIP-0144 asset ID derived from a reissue input using TxCreateRequest.chain_id and the reissued asset reference. |} new_issuance_asset and new_issuance_token require params.inputs[input_index].issuance.kind == "new". @@ -653,8 +648,8 @@ The exact accepted names and types are defined by source_simf and t ==== runtime_arguments ==== runtime_arguments carries directives for values the app cannot know at request-construction time. -Examples include an issued asset ID that depends on the wallet-selected issuance input, a confidential reissuance -token ID, or a transaction signature that depends on the final transaction sighash. +Examples include an issued asset reference that depends on the wallet-selected issuance input, a confidential +reissuance-token asset reference, or a transaction signature that depends on the final transaction sighash. For FinalizerSpec::Simf.arguments, runtime_arguments is an object keyed by target SimplicityHL argument names: @@ -675,10 +670,10 @@ Supported runtime argument directives: ! Definition |- | new_issuance_asset -| Resolve a u256 value from the issued asset ID of a new issuance input. +| Resolve a u256 value from the issued asset reference of a new issuance input. |- | new_issuance_token -| Resolve a u256 value from the confidential reissuance/inflation-token ID of a new issuance input. +| Resolve a u256 value from the confidential reissuance/inflation-token asset reference of a new issuance input. |} For FinalizerSpec::Simf.witness, runtime_arguments is an array of witness directives: @@ -709,11 +704,12 @@ A conforming runtime MAY process a request in this order:
  1. Decode JSON and reject unknown envelope/runtime fields.
  2. -
  3. Validate abi_version and network against runtime context.
  4. +
  5. Validate abi_version and chain_id against runtime context.
  6. Open one wallet request session.
  7. Resolve declared inputs in order.
  8. For any SIMF-finalized input, compile the requested source_simf with simplicity_hl_version, derive the expected finalizer script pubkey, and reject if the resolved UTXO script pubkey does not match.
  9. Resolve issuance metadata for inputs and any issuance-linked output asset IDs.
  10. +
  11. For every explicit ELIP-0144 asset_id, verify that the asset chain prefix equals TxCreateRequest.chain_id, then extract the asset_reference for transaction construction.
  12. Materialize declared outputs in order.
  13. Estimate fee and balance supply/demand.
  14. Append wallet funding inputs if needed.
  15. @@ -734,7 +730,7 @@ The returned TxCreateResponse remains the only authoritative result
    {
       "abi_version": "wallet-abi-0.1",
       "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
    -  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
    +  "chain_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
       "status": "ok",
       "transaction": {
         "tx_hex": "02000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    @@ -756,9 +752,9 @@ The returned TxCreateResponse remains the only authoritative result
     | style="text-align: right;"| UUID
     | Copied from request.
     |-
    -| network
    -| style="text-align: right;"| Bip122ChainId
    -| Copied/confirmed network context.
    +| chain_id
    +| style="text-align: right;"| Elip144ChainId
    +| Copied/confirmed chain context.
     |-
     | status
     | style="text-align: right;"| "ok"
    @@ -782,7 +778,7 @@ The returned TxCreateResponse remains the only authoritative result
     
    {
       "abi_version": "wallet-abi-0.1",
       "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
    -  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
    +  "chain_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
       "status": "error",
       "error": {
         "code": "funding",
    @@ -821,7 +817,7 @@ The returned TxCreateResponse remains the only authoritative result
     ! Typical meaning
     |-
     | invalid_request
    -| Request shape, incompatible fields, bad network/version, missing referenced input.
    +| Request shape, incompatible fields, bad chain/version, missing referenced input.
     |-
     | serde
     | Serialization/deserialization failure.
    @@ -864,7 +860,7 @@ The returned TxCreateResponse remains the only authoritative result
     # artifacts is the preferred place for producer-defined metadata that does not break older consumers.
     # Unknown request fields are rejected by the current Rust request/runtime parameter schemas; do not use unknown fields for extension.
     # Runtimes that cannot satisfy simplicity_hl_version MUST reject rather than silently compiling with another version.
    -# A future ABI may define friendly network aliases, but wire-level matching in this ABI is by BIP-122 chain id.
    +# A future ABI may define friendly network aliases, but wire-level matching in this ABI is by ELIP-0144 chain_id.
     # Changes to the static_values {value,type} shape or the signature-embedding rules require an ABI update or explicit capability negotiation.
     
     == Security Considerations ==
    @@ -879,7 +875,7 @@ The returned TxCreateResponse remains the only authoritative result
     # lock_time can be ineffective if input sequences are final.
     # SIMF sig_hash_all.public_key must equal the runtime signer x-only key.
     # source_simf must be compiled with the requested simplicity_hl_version; runtimes MUST NOT silently substitute a different compiler version.
    -# Consumer UIs SHOULD make network and broadcast status prominent.
    +# Consumer UIs SHOULD make chain ID and broadcast status prominent.
     # Consumers SHOULD ignore unknown artifacts keys and sanitize error.message/error.details before rendering.
     # Wallets MUST NOT trust self-declared app names, labels, URLs, or icons in the request payload as authenticated caller identity. Authenticated app/request identity must come from the transport/platform binding or another out-of-band trust system.
     # static_values.value and static_values.type are untrusted SimplicityHL compiler inputs. Parse and type-check them with the requested simplicity_hl_version; do not evaluate them with an ad hoc parser outside the compiler boundary.
    @@ -887,8 +883,17 @@ The returned TxCreateResponse remains the only authoritative result
     
     == Rationale ==
     
    -The ABI uses BIP-122/CAIP-2-style chain identifiers instead of bare network names so wallets can match requests against
    -the genesis hash of the active Elements chain. This avoids ambiguity between Liquid mainnet, Liquid testnet, local Elements chains, and custom networks.
    +The ABI uses ELIP-0144 chain_id values instead of bare network names so wallets can match requests against
    +the identity of the active Elements chain. This avoids ambiguity between Liquid mainnet, Liquid testnet, Liquid regtest, and custom networks.
    +
    +Explicit caller-provided assets also use ELIP-0144 asset_id values. This lets wallet-connection transports,
    +review UIs, and cross-chain applications use one asset identifier syntax instead of translating between a Wallet ABI
    +asset format and the ELIP-0144 format. The runtime still extracts the raw Elements asset_reference when it
    +constructs transaction outputs or fills SIMF u256 arguments.
    +
    +Satoshi amounts are encoded as decimal strings so JSON parsers in JavaScript and other environments do not lose
    +precision for values above their native safe-integer range. The string form preserves the full unsigned 64-bit domain
    +without requiring a binary encoding or language-specific bigint extension at the ABI boundary.
     
     request_id is a correlation identifier rather than replay protection because wallet state, UTXO availability,
     fee policy, and broadcast status can change between attempts. Treating the request as non-idempotent avoids giving callers
    @@ -956,10 +961,10 @@ and schema constraints, but they are expected to be corrected or replaced after
     ! Purpose
     |-
     | [[elip-wallet-abi/01_request_wallet_to_script.json|01_request_wallet_to_script.json]]
    -| Simple wallet-funded build-only payment to an explicit script output using network = "bip122:a771da8e52ee6ad581ed1e9a99825e5b".
    +| Simple wallet-funded build-only payment to an explicit script output using chain_id = "bip122:a771da8e52ee6ad581ed1e9a99825e5b" and ELIP-0144 asset IDs.
     |-
     | [[elip-wallet-abi/02_response_ok_build_only.json|02_response_ok_build_only.json]]
    -| Success response for the build-only example, using the same Bip122ChainId and open-ended artifacts.
    +| Success response for the build-only example, using the same Elip144ChainId and open-ended artifacts.
     |-
     | [[elip-wallet-abi/03_response_error_funding.json|03_response_error_funding.json]]
     | Error response with canonical funding code and optional diagnostic details.
    @@ -968,7 +973,7 @@ and schema constraints, but they are expected to be corrected or replaced after
     | Issuance request using a SIMF finalizer, stable bip0341 internal key, simplicity_hl_version, JSON arguments/witness, static_values examples, inflation_amount_sat, and confidential new_issuance_token output.
     |-
     | [[elip-wallet-abi/wallet-abi-tx-create.schema.json|wallet-abi-tx-create.schema.json]]
    -| Complete JSON Schema for request/response shape. It includes the BIP-122 chain-id pattern, blinding_secret_key, inflation_amount_sat, simplicity_hl_version, JSON SIMF payloads, static_values typed literals, stable bip0341, and a schema-level rejection of blinder = "explicit" when asset.type = "new_issuance_token".
    +| Complete JSON Schema for request/response shape. It includes ELIP-0144 chain and asset ID patterns, decimal-string u64 amounts, blinding_secret_key, inflation_amount_sat, simplicity_hl_version, JSON SIMF payloads, static_values typed literals, stable bip0341, and a schema-level rejection of blinder = "explicit" when asset.type = "new_issuance_token".
     |-
     | [[elip-wallet-abi/field-reference.json|field-reference.json]]
     | Machine-readable field reference for implementers and UI review.
    @@ -1028,6 +1033,10 @@ These links are intentionally listed directly so reviewers do not need to search
     | https://github.com/ElementsProject/ELIPs/blob/main/elip-0001.mediawiki
     | Defines the ELIP process, MediaWiki format, header preamble, and auxiliary file rules.
     |-
    +| ELIP-0144
    +| https://github.com/ElementsProject/ELIPs/blob/main/elip-0144.mediawiki
    +| Defines the Liquid account ID, chain ID, and asset ID syntax used by this ABI.
    +|-
     | RFC 2119 requirement keywords
     | https://www.rfc-editor.org/rfc/rfc2119
     | Defines the normative meaning of '''MUST''', '''SHOULD''', '''MAY''', and related terms.
    @@ -1044,6 +1053,10 @@ These links are intentionally listed directly so reviewers do not need to search
     | https://standards.chainagnostic.org/CAIPs/caip-2
     | Defines the namespace:reference chain-id form.
     |-
    +| CAIP-19
    +| https://standards.chainagnostic.org/CAIPs/caip-19
    +| Defines the chain-agnostic asset ID shape adapted by ELIP-0144.
    +|-
     | CAIP BIP122 namespace
     | https://namespaces.chainagnostic.org/bip122/caip2
     | Defines bip122:32-character-lowercase-genesis-hash-prefix.
    @@ -1060,14 +1073,6 @@ These links are intentionally listed directly so reviewers do not need to search
     | https://github.com/ElementsProject/elements
     | Reference implementation for Elements/Liquid chain behavior.
     |-
    -| Elements chainparams.cpp
    -| https://raw.githubusercontent.com/ElementsProject/elements/master/src/chainparams.cpp
    -| Source reference for chain/network parameters such as liquidv1. Implementations derive the active chain id from their node/runtime rather than trusting a hard-coded label.
    -|-
    -| Go Elements network parameters
    -| https://pkg.go.dev/github.com/dirtyhighli/go-elements/network
    -| Convenient source for Liquid, Liquid testnet, and Elements regtest example genesis hashes used in this draft.
    -|-
     | SimplicityHL repository
     | https://github.com/BlockstreamResearch/SimplicityHL
     | Source project for source_simf and simplicity_hl_version context.
    @@ -1085,27 +1090,6 @@ These links are intentionally listed directly so reviewers do not need to search
     | Informative reference for the simplicity_hl_version string shape; the ABI requires an exact compiler version, not a numeric JSON value.
     |}
     
    -Known chain-id examples used by this ABI:
    -
    -{| class="wikitable"
    -|-
    -! Friendly label
    -! Full genesis hash
    -! ABI network value
    -|-
    -| Liquid mainnet (liquidv1)
    -| 1466275836220db2944ca059a3a10ef6fd2ea684b0688d2c379296888a206003
    -| bip122:1466275836220db2944ca059a3a10ef6
    -|-
    -| Liquid testnet (liquidtestnet)
    -| a771da8e52ee6ad581ed1e9a99825e5b3b7992225534eaa2ae23244fe26ab1c1
    -| bip122:a771da8e52ee6ad581ed1e9a99825e5b
    -|-
    -| Default Elements regtest/localtest
    -| 00902a6b70c2ca83b5d9c815d96a0e2f4202179316970d14ea1847dae5b1ca21
    -| bip122:00902a6b70c2ca83b5d9c815d96a0e2f
    -|}
    -
     == Appendix A: Future Work ==
     
     This appendix collects ideas that are intentionally not part of the wallet-abi-0.1 core.
    @@ -1123,8 +1107,8 @@ for enum variants; and supported simplicity_hl_version discovery.
     
     === A.3 Friendly network aliases and local-chain metadata ===
     
    -The wire network is a BIP-122 chain id in this draft. A future profile may define friendly labels,
    -policy-asset metadata, and local/custom Elements network registry entries, but those aliases must not replace genesis-hash matching in the core validation path.
    +The wire chain_id is the ELIP-0144 chain ID in this draft. A future profile may define friendly labels,
    +policy-asset metadata, and local/custom Elements network registry entries, but those aliases must not replace ELIP-0144 chain ID matching in the core validation path.
     
     === A.4 Explicit reissuance-token support ===
     
    @@ -1152,8 +1136,8 @@ and UI-state machines remain out of scope for the core ABI payload.
     | session_id
     | Opaque wallet-owned correlation ID.
     |-
    -| network
    -| BIP-122 chain id used for request validation and script derivation.
    +| chain_id
    +| ELIP-0144 chain ID used for request validation and script derivation.
     |-
     | spendable_utxos
     | Deterministic spendable UTXO snapshot used for input selection within one request lifecycle.
    @@ -1170,7 +1154,7 @@ and UI-state machines remain out of scope for the core ABI payload.
     | Deterministic zero-based receive-output index within a build pass.
     |-
     | Change { index, asset_id }
    -| Deterministic zero-based change-output index for a concrete residual asset.
    +| Deterministic zero-based change-output index for a concrete residual ELIP-0144 asset ID.
     |}
     
     === B.3 WalletOutputTemplate ===
    diff --git a/elip-wallet-abi/01_request_wallet_to_script.json b/elip-wallet-abi/01_request_wallet_to_script.json
    index 20e2959..af964cb 100644
    --- a/elip-wallet-abi/01_request_wallet_to_script.json
    +++ b/elip-wallet-abi/01_request_wallet_to_script.json
    @@ -1,7 +1,7 @@
     {
       "abi_version": "wallet-abi-0.1",
       "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
    -  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
    +  "chain_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
       "params": {
         "inputs": [
           {
    @@ -11,12 +11,12 @@
                 "filter": {
                   "asset": {
                     "exact": {
    -                  "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49"
    +                  "asset_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49"
                     }
                   },
                   "amount": {
                     "min": {
    -                  "amount_sat": 150000
    +                  "amount_sat": "150000"
                     }
                   },
                   "lock": "none"
    @@ -33,19 +33,19 @@
         "outputs": [
           {
             "id": "merchant-payment",
    -        "amount_sat": 100000,
    +        "amount_sat": "100000",
             "lock": {
               "type": "script",
               "script": "0014aabbccddeeff00112233445566778899aabbccdd"
             },
             "asset": {
               "type": "asset_id",
    -          "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49"
    +          "asset_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49"
             },
             "blinder": "explicit"
           }
         ],
    -    "fee_rate_sat_kvb": 1000.0
    +    "fee_rate_sat_kvb": 1000
       },
       "broadcast": false
     }
    diff --git a/elip-wallet-abi/02_response_ok_build_only.json b/elip-wallet-abi/02_response_ok_build_only.json
    index b38a090..ceba7a2 100644
    --- a/elip-wallet-abi/02_response_ok_build_only.json
    +++ b/elip-wallet-abi/02_response_ok_build_only.json
    @@ -1,7 +1,7 @@
     {
       "abi_version": "wallet-abi-0.1",
       "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
    -  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
    +  "chain_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
       "status": "ok",
       "transaction": {
         "tx_hex": "02000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    @@ -15,20 +15,20 @@
             "input_id": "wallet-lbtc-funding",
             "source": "wallet",
             "outpoint": "0101010101010101010101010101010101010101010101010101010101010101:0",
    -        "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    -        "amount_sat": 150000
    +        "asset_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    +        "amount_sat": "150000"
           }
         ],
         "appended_outputs": [
           {
             "kind": "fee",
    -        "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    -        "amount_sat": 450
    +        "asset_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    +        "amount_sat": "450"
           },
           {
             "kind": "change",
    -        "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    -        "amount_sat": 49550
    +        "asset_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    +        "amount_sat": "49550"
           }
         ]
       }
    diff --git a/elip-wallet-abi/03_response_error_funding.json b/elip-wallet-abi/03_response_error_funding.json
    index 9fd32eb..0a8c900 100644
    --- a/elip-wallet-abi/03_response_error_funding.json
    +++ b/elip-wallet-abi/03_response_error_funding.json
    @@ -1,15 +1,15 @@
     {
       "abi_version": "wallet-abi-0.1",
       "request_id": "0d6d53cd-a040-4f0c-8d28-c67b6608fb14",
    -  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
    +  "chain_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
       "status": "error",
       "error": {
         "code": "funding",
    -    "message": "insufficient wallet balance for asset 144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    +    "message": "insufficient wallet balance for asset bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
         "details": {
    -      "requested_asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    -      "requested_amount_sat": 100000,
    -      "available_amount_sat": 12345,
    +      "requested_asset_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49",
    +      "requested_amount_sat": "100000",
    +      "available_amount_sat": "12345",
           "broadcast_attempted": false
         }
       }
    diff --git a/elip-wallet-abi/04_request_simf_bip0341_issuance.json b/elip-wallet-abi/04_request_simf_bip0341_issuance.json
    index e21e024..c956ef0 100644
    --- a/elip-wallet-abi/04_request_simf_bip0341_issuance.json
    +++ b/elip-wallet-abi/04_request_simf_bip0341_issuance.json
    @@ -1,7 +1,7 @@
     {
       "abi_version": "wallet-abi-0.1",
       "request_id": "216113a8-8eb7-4d1f-8573-8b6ed04f4ad5",
    -  "network": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
    +  "chain_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
       "params": {
         "inputs": [
           {
    @@ -11,12 +11,12 @@
                 "filter": {
                   "asset": {
                     "exact": {
    -                  "asset_id": "144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49"
    +                  "asset_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49"
                     }
                   },
                   "amount": {
                     "min": {
    -                  "amount_sat": 250000
    +                  "amount_sat": "250000"
                     }
                   },
                   "lock": "none"
    @@ -27,8 +27,8 @@
             "sequence": 4294967294,
             "issuance": {
               "kind": "new",
    -          "asset_amount_sat": 1,
    -          "inflation_amount_sat": 1,
    +          "asset_amount_sat": "1",
    +          "inflation_amount_sat": "1",
               "entropy": [
                 7,
                 7,
    @@ -72,7 +72,7 @@
         "outputs": [
           {
             "id": "issued-asset-to-simf-lock",
    -        "amount_sat": 1,
    +        "amount_sat": "1",
             "lock": {
               "type": "finalizer",
               "finalizer": {
    @@ -134,7 +134,7 @@
           },
           {
             "id": "issued-token-to-wallet",
    -        "amount_sat": 1,
    +        "amount_sat": "1",
             "lock": {
               "type": "wallet"
             },
    @@ -145,9 +145,9 @@
             "blinder": "wallet"
           }
         ],
    -    "fee_rate_sat_kvb": 1000.0,
    +    "fee_rate_sat_kvb": 1000,
         "lock_time": {
    -      "Blocks": 900000
    +      "blocks": 900000
         }
       },
       "broadcast": true
    diff --git a/elip-wallet-abi/field-reference.json b/elip-wallet-abi/field-reference.json
    index 683f5cd..b652915 100644
    --- a/elip-wallet-abi/field-reference.json
    +++ b/elip-wallet-abi/field-reference.json
    @@ -12,10 +12,10 @@
         "definition": "Correlation identifier generated per user action. Not replay protection and not an idempotency key."
       },
       {
    -    "path": "TxCreateRequest.network",
    -    "type": "Bip122ChainId",
    +    "path": "TxCreateRequest.chain_id",
    +    "type": "Elip144ChainId",
         "required": true,
    -    "definition": "CAIP-2-style BIP-122 chain id string, bip122:<32-lowercase-hex genesis prefix>. Must match runtime chain id before side effects."
    +    "definition": "ELIP-0144 chain_id string, bip122:. Must match runtime chain ID before side effects."
       },
       {
         "path": "TxCreateRequest.params",
    @@ -27,7 +27,7 @@
         "path": "TxCreateRequest.broadcast",
         "type": "boolean",
         "required": true,
    -    "definition": "Whether runtime should publish the finalized transaction. false still permits sync/fetch/validation network calls."
    +    "definition": "Whether runtime should publish the finalized transaction. false still permits sync/fetch/validation calls."
       },
       {
         "path": "RuntimeParams.inputs",
    @@ -97,15 +97,15 @@
       },
       {
         "path": "InputIssuance.asset_amount_sat",
    -    "type": "u64",
    +    "type": "u64 decimal string",
         "required": true,
    -    "definition": "Amount of issued/reissued asset units to mint."
    +    "definition": "Amount of issued/reissued asset units to mint, encoded as a decimal string."
       },
       {
         "path": "InputIssuance.inflation_amount_sat",
    -    "type": "u64",
    +    "type": "u64 decimal string",
         "required": true,
    -    "definition": "Amount of reissuance/inflation-token units to mint. Replaces token_amount_sat."
    +    "definition": "Amount of reissuance/inflation-token units to mint, encoded as a decimal string. Replaces token_amount_sat."
       },
       {
         "path": "InputIssuance.entropy",
    @@ -127,9 +127,9 @@
       },
       {
         "path": "OutputSchema.amount_sat",
    -    "type": "u64",
    +    "type": "u64 decimal string",
         "required": true,
    -    "definition": "Requested output amount in satoshi/base units."
    +    "definition": "Requested output amount in satoshi/base units, encoded as a decimal string."
       },
       {
         "path": "OutputSchema.lock",
    @@ -141,13 +141,13 @@
         "path": "OutputSchema.asset",
         "type": "AssetVariant",
         "required": true,
    -    "definition": "Explicit asset ID or issuance-derived asset/token selector."
    +    "definition": "ELIP-0144 asset_id string or issuance-derived asset/token selector. Explicit ELIP-0144 asset_ids must have a chain_id matching TxCreateRequest.chain_id."
       },
       {
         "path": "OutputSchema.asset.new_issuance_token",
         "type": "AssetVariant",
         "required": false,
    -    "definition": "Confidential reissuance/inflation token derived from a new issuance input. Outputs using this asset MUST NOT use blinder = explicit."
    +    "definition": "Confidential reissuance/inflation token derived from a new issuance input. The resulting ELIP-0144 asset_id uses the request chain_id and the derived asset_reference. Outputs using this asset MUST NOT use blinder = explicit."
       },
       {
         "path": "OutputSchema.blinder",
    diff --git a/elip-wallet-abi/wallet-abi-tx-create.schema.json b/elip-wallet-abi/wallet-abi-tx-create.schema.json
    index 52934a2..b73933a 100644
    --- a/elip-wallet-abi/wallet-abi-tx-create.schema.json
    +++ b/elip-wallet-abi/wallet-abi-tx-create.schema.json
    @@ -2,7 +2,7 @@
       "$schema": "https://json-schema.org/draft/2020-12/schema",
       "$id": "https://example.invalid/wallet-abi/tx-create/wallet-abi-0.1.schema.json",
       "title": "Wallet ABI tx_create wallet-abi-0.1 review schema",
    -  "description": "Review schema for the Wallet ABI tx_create draft. Includes BIP-122 network ids, JSON SIMF payloads, static_values typed literals, runtime SIMF directives, and response shapes. Semantic validation remains the runtime's responsibility.",
    +  "description": "Review schema for the Wallet ABI tx_create draft. Chain and explicit asset identifiers follow ELIP-0144, u64 satoshi amounts are decimal strings, and semantic validation remains the runtime's responsibility.",
       "oneOf": [
         {
           "$ref": "#/$defs/TxCreateRequest"
    @@ -14,7 +14,8 @@
       "$defs": {
         "Hex": {
           "type": "string",
    -      "pattern": "^[0-9a-fA-F]*$"
    +      "pattern": "^(?:[0-9a-fA-F]{2})*$",
    +      "description": "Hex-encoded byte string. Empty is allowed only where the referencing field permits it."
         },
         "Hex32": {
           "type": "string",
    @@ -24,20 +25,10 @@
           "type": "string",
           "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
         },
    -    "Bip122ChainId": {
    -      "type": "string",
    -      "pattern": "^bip122:[0-9a-f]{32}$",
    -      "description": "CAIP-2-style BIP-122 chain id: bip122:.",
    -      "examples": [
    -        "bip122:1466275836220db2944ca059a3a10ef6",
    -        "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
    -        "bip122:00902a6b70c2ca83b5d9c815d96a0e2f"
    -      ]
    -    },
         "U64": {
    -      "type": "integer",
    -      "minimum": 0,
    -      "maximum": 18446744073709551615
    +      "type": "string",
    +      "pattern": "^(?:0|[1-9][0-9]{0,18}|1[0-7][0-9]{18}|18[0-3][0-9]{17}|184[0-3][0-9]{16}|1844[0-5][0-9]{15}|18446[0-6][0-9]{14}|184467[0-3][0-9]{13}|1844674[0-3][0-9]{12}|184467440[0-6][0-9]{10}|1844674407[0-2][0-9]{9}|18446744073[0-6][0-9]{8}|1844674407370[0-8][0-9]{6}|18446744073709[0-4][0-9]{5}|184467440737095[0-4][0-9]{4}|18446744073709550[0-9]{3}|18446744073709551[0-5][0-9]{2}|1844674407370955160[0-9]|1844674407370955161[0-5])$",
    +      "description": "Unsigned 64-bit integer encoded as a decimal JSON string, with no leading zeroes except \"0\"."
         },
         "U32": {
           "type": "integer",
    @@ -55,14 +46,13 @@
             "$ref": "#/$defs/Byte"
           }
         },
    -    "AssetId": {
    -      "$ref": "#/$defs/Hex32"
    -    },
         "Txid": {
           "$ref": "#/$defs/Hex32"
         },
         "Script": {
    -      "$ref": "#/$defs/Hex"
    +      "type": "string",
    +      "pattern": "^(?:[0-9a-fA-F]{2})+$",
    +      "description": "Non-empty hex-encoded scriptPubKey byte string."
         },
         "XOnlyPublicKey": {
           "$ref": "#/$defs/Hex32"
    @@ -76,7 +66,8 @@
         },
         "OutPoint": {
           "type": "string",
    -      "pattern": "^[0-9a-fA-F]{64}:[0-9]+$"
    +      "pattern": "^[0-9a-fA-F]{64}:(?:0|[1-9][0-9]{0,8}|[1-3][0-9]{9}|4[0-1][0-9]{8}|42[0-8][0-9]{7}|429[0-3][0-9]{6}|4294[0-8][0-9]{5}|42949[0-5][0-9]{4}|429496[0-6][0-9]{3}|4294967[0-1][0-9]{2}|42949672[0-8][0-9]|429496729[0-5])$",
    +      "description": "Outpoint encoded as txid:vout, with vout in uint32 range."
         },
         "SimplicityHLVersion": {
           "type": "string",
    @@ -145,11 +136,11 @@
             {
               "type": "object",
               "required": [
    -            "Blocks"
    +            "blocks"
               ],
               "additionalProperties": false,
               "properties": {
    -            "Blocks": {
    +            "blocks": {
                   "$ref": "#/$defs/U32"
                 }
               }
    @@ -157,11 +148,11 @@
             {
               "type": "object",
               "required": [
    -            "Seconds"
    +            "seconds"
               ],
               "additionalProperties": false,
               "properties": {
    -            "Seconds": {
    +            "seconds": {
                   "$ref": "#/$defs/U32"
                 }
               }
    @@ -188,7 +179,7 @@
                   "additionalProperties": false,
                   "properties": {
                     "asset_id": {
    -                  "$ref": "#/$defs/AssetId"
    +                  "$ref": "#/$defs/Elip144AssetId"
                     }
                   }
                 }
    @@ -471,7 +462,7 @@
                   "additionalProperties": false,
                   "properties": {
                     "name": {
    -                  "type": "string"
    +                  "$ref": "#/$defs/SimfName"
                     },
                     "public_key": {
                       "$ref": "#/$defs/XOnlyPublicKey"
    @@ -665,7 +656,7 @@
                   "const": "asset_id"
                 },
                 "asset_id": {
    -              "$ref": "#/$defs/AssetId"
    +              "$ref": "#/$defs/Elip144AssetId"
                 }
               }
             },
    @@ -846,7 +837,7 @@
           "required": [
             "abi_version",
             "request_id",
    -        "network",
    +        "chain_id",
             "params",
             "broadcast"
           ],
    @@ -858,8 +849,8 @@
             "request_id": {
               "$ref": "#/$defs/Uuid"
             },
    -        "network": {
    -          "$ref": "#/$defs/Bip122ChainId"
    +        "chain_id": {
    +          "$ref": "#/$defs/Elip144ChainId"
             },
             "params": {
               "$ref": "#/$defs/RuntimeParams"
    @@ -878,7 +869,7 @@
           "additionalProperties": false,
           "properties": {
             "tx_hex": {
    -          "$ref": "#/$defs/Hex"
    +          "$ref": "#/$defs/TransactionHex"
             },
             "txid": {
               "$ref": "#/$defs/Txid"
    @@ -909,7 +900,7 @@
               "required": [
                 "abi_version",
                 "request_id",
    -            "network",
    +            "chain_id",
                 "status",
                 "transaction"
               ],
    @@ -921,8 +912,8 @@
                 "request_id": {
                   "$ref": "#/$defs/Uuid"
                 },
    -            "network": {
    -              "$ref": "#/$defs/Bip122ChainId"
    +            "chain_id": {
    +              "$ref": "#/$defs/Elip144ChainId"
                 },
                 "status": {
                   "const": "ok"
    @@ -941,7 +932,7 @@
               "required": [
                 "abi_version",
                 "request_id",
    -            "network",
    +            "chain_id",
                 "status",
                 "error"
               ],
    @@ -953,8 +944,8 @@
                 "request_id": {
                   "$ref": "#/$defs/Uuid"
                 },
    -            "network": {
    -              "$ref": "#/$defs/Bip122ChainId"
    +            "chain_id": {
    +              "$ref": "#/$defs/Elip144ChainId"
                 },
                 "status": {
                   "const": "error"
    @@ -969,6 +960,26 @@
               }
             }
           ]
    +    },
    +    "Elip144ChainId": {
    +      "type": "string",
    +      "pattern": "^bip122:[0-9a-f]{32}$",
    +      "description": "ELIP-0144 chain_id: bip122:.",
    +      "examples": [
    +        "bip122:1466275836220db2944ca059a3a10ef6",
    +        "bip122:a771da8e52ee6ad581ed1e9a99825e5b",
    +        "bip122:cc2641af46f536fba45aab6016f63e12"
    +      ]
    +    },
    +    "Elip144AssetId": {
    +      "type": "string",
    +      "pattern": "^bip122:[0-9a-f]{32}/elip144:[0-9a-f]{64}$",
    +      "description": "ELIP-0144 asset_id: /elip144:<64-lowercase-hex Elements asset_reference>."
    +    },
    +    "TransactionHex": {
    +      "type": "string",
    +      "pattern": "^(?:[0-9a-fA-F]{2})+$",
    +      "description": "Non-empty hex-encoded finalized Elements transaction bytes."
         }
       }
     }
    
    From 7630f6c933faab024c354830fabbe48bb50cb1f7 Mon Sep 17 00:00:00 2001
    From: Kyryl R 
    Date: Tue, 12 May 2026 13:38:07 +0300
    Subject: [PATCH 4/6] wallet abi: clarify the type of the fee_rate_sat_kvb
    
    ---
     elip-wallet-abi.mediawiki                             | 2 +-
     elip-wallet-abi/01_request_wallet_to_script.json      | 2 +-
     elip-wallet-abi/04_request_simf_bip0341_issuance.json | 2 +-
     elip-wallet-abi/field-reference.json                  | 2 +-
     elip-wallet-abi/wallet-abi-tx-create.schema.json      | 3 ++-
     5 files changed, 6 insertions(+), 5 deletions(-)
    
    diff --git a/elip-wallet-abi.mediawiki b/elip-wallet-abi.mediawiki
    index 1f97b20..62f0ea3 100644
    --- a/elip-wallet-abi.mediawiki
    +++ b/elip-wallet-abi.mediawiki
    @@ -283,7 +283,7 @@ MUST ensure that the account chain prefix matches TxCreateRequest.chain_id
     | Declared outputs, materialized in declaration order. Runtime may append fee and change outputs.
     |-
     | fee_rate_sat_kvb
    -| style="text-align: right;"| number
    +| style="text-align: right;"| float
     | style="text-align: center;"| no
     | Fee-rate override in sat/kvB. MUST be finite and non-negative. If omitted, runtime policy applies.
     |-
    diff --git a/elip-wallet-abi/01_request_wallet_to_script.json b/elip-wallet-abi/01_request_wallet_to_script.json
    index af964cb..d8a8b82 100644
    --- a/elip-wallet-abi/01_request_wallet_to_script.json
    +++ b/elip-wallet-abi/01_request_wallet_to_script.json
    @@ -45,7 +45,7 @@
             "blinder": "explicit"
           }
         ],
    -    "fee_rate_sat_kvb": 1000
    +    "fee_rate_sat_kvb": 0.1
       },
       "broadcast": false
     }
    diff --git a/elip-wallet-abi/04_request_simf_bip0341_issuance.json b/elip-wallet-abi/04_request_simf_bip0341_issuance.json
    index c956ef0..23b2aed 100644
    --- a/elip-wallet-abi/04_request_simf_bip0341_issuance.json
    +++ b/elip-wallet-abi/04_request_simf_bip0341_issuance.json
    @@ -145,7 +145,7 @@
             "blinder": "wallet"
           }
         ],
    -    "fee_rate_sat_kvb": 1000,
    +    "fee_rate_sat_kvb": 0.1,
         "lock_time": {
           "blocks": 900000
         }
    diff --git a/elip-wallet-abi/field-reference.json b/elip-wallet-abi/field-reference.json
    index b652915..7b0632b 100644
    --- a/elip-wallet-abi/field-reference.json
    +++ b/elip-wallet-abi/field-reference.json
    @@ -43,7 +43,7 @@
       },
       {
         "path": "RuntimeParams.fee_rate_sat_kvb",
    -    "type": "number",
    +    "type": "float",
         "required": false,
         "definition": "Optional finite non-negative fee rate in sat/kvB."
       },
    diff --git a/elip-wallet-abi/wallet-abi-tx-create.schema.json b/elip-wallet-abi/wallet-abi-tx-create.schema.json
    index b73933a..c4e3bd7 100644
    --- a/elip-wallet-abi/wallet-abi-tx-create.schema.json
    +++ b/elip-wallet-abi/wallet-abi-tx-create.schema.json
    @@ -825,7 +825,8 @@
             },
             "fee_rate_sat_kvb": {
               "type": "number",
    -          "minimum": 0
    +          "minimum": 0,
    +          "description": "Finite non-negative floating-point fee rate in sat/kvB."
             },
             "lock_time": {
               "$ref": "#/$defs/LockTime"
    
    From fc8f132802554e77f21117e84484b884b8418e75 Mon Sep 17 00:00:00 2001
    From: Kyryl R 
    Date: Wed, 13 May 2026 11:33:01 +0300
    Subject: [PATCH 5/6] wallet abi: removed refs, appendix b. Cleaned up
     rationale. Fixed typos
    
    ---
     elip-wallet-abi.mediawiki                     | 233 ++++------------
     .../03_response_error_funding.json            |   2 +-
     elip-wallet-abi/field-reference.json          | 254 ------------------
     .../wallet-abi-tx-create.schema.json          |  68 ++---
     4 files changed, 95 insertions(+), 462 deletions(-)
     delete mode 100644 elip-wallet-abi/field-reference.json
    
    diff --git a/elip-wallet-abi.mediawiki b/elip-wallet-abi.mediawiki
    index 62f0ea3..0850f15 100644
    --- a/elip-wallet-abi.mediawiki
    +++ b/elip-wallet-abi.mediawiki
    @@ -32,8 +32,8 @@ This document is licensed under the 3-clause BSD license.
     === Motivation ===
     
     Applications need a standard way to ask a wallet to construct and sign a transaction from an application-level intent
    -while keeping wallet-owned UTXOs private to the wallet. This protocol defines a communication schema that provides a signing capability to the requester,
    -allowing the wallet to never share its UTXO set, balances, or wallet-internal selection state with the requester to facilitate the signing.
    +while keeping wallet-owned UTXOs private to the wallet. This protocol defines a communication schema that gives the requester
    +a signing/construction capability without requiring the wallet to share its UTXO set, balances, or wallet-internal selection state.
     
     === Goals and non-goals ===
     
    @@ -78,13 +78,13 @@ The words '''MUST''', '''SHOULD''', '''MAY''', and '''MUST NOT''' are used in th
     | Wallet input, fee output, or change output added by the runtime to satisfy funding/balancing.
     |-
     | Finalizer
    -| Rule for producing witness/finalization data or deriving a finalizer-owned input lock.
    +| Rule for producing input witness/finalization data or deriving a finalizer-owned output lock.
     |-
     | SIMF
     | SimplicityHL finalization payload carrying source, compiler version, JSON arguments, JSON witness values, and internal key source.
     |-
     | Internal key source
    -| Selector that returns a Taproot/BIP340 x-only public key for control-block/script derivation.
    +| Selector that returns a Taproot/BIP-340 x-only public key for control-block/script derivation.
     |-
     | ELIP-0144 chain ID
     | The chain_id string defined by ELIP-0144, e.g. bip122:<32-lowercase-hex>.
    @@ -191,11 +191,11 @@ The runtime SHOULD provide deterministic behavior only within this narrower boun
     
     # Payloads are JSON objects unless a variant is explicitly serialized as a string.
     # Enum variants use snake_case.
    -# TxCreateRequest and RuntimeParams reject unknown fields in the attached Rust schema.
    +# TxCreateRequest and RuntimeParams reject unknown fields in the attached JSON Schema.
     # Numeric satoshi amounts are unsigned 64-bit values encoded as decimal JSON strings, with no leading zeroes except "0".
     # Byte-array fields, such as issuance entropy, are serialized as JSON arrays of integers from 0 to 255.
     # FinalizerSpec::Simf.arguments and FinalizerSpec::Simf.witness are JSON objects.
    -# Hex fields are lowercase by convention, but consumers SHOULD accept uppercase only if their underlying parsers do.
    +# Hex fields other than ELIP-0144 chain_id and asset_id values are lowercase by convention.
     # chain_id and explicit asset_id values MUST use the ELIP-0144 wire shapes.
     # Secrets, including provided input blinding secret keys and intermediate PSET material, MUST NOT be logged.
     
    @@ -698,7 +698,7 @@ For FinalizerSpec::Simf.witness, runtime_arguments is
     
     === Runtime processing model ===
     
    -Provider-specific state objects and wallet output allocation internals are informative implementation details in Appendix B.
    +Provider-specific state objects and wallet output allocation internals are outside this specification and are left to runtime implementations.
     
     A conforming runtime MAY process a request in this order:
     
    @@ -858,7 +858,7 @@ The returned TxCreateResponse remains the only authoritative result
     # abi_version changes are required for incompatible request/response shape changes.
     # New enum variants SHOULD be gated by ABI version or explicit capability negotiation.
     # artifacts is the preferred place for producer-defined metadata that does not break older consumers.
    -# Unknown request fields are rejected by the current Rust request/runtime parameter schemas; do not use unknown fields for extension.
    +# Unknown request fields are rejected by the current JSON Schema request/runtime parameter definitions; do not use unknown fields for extension.
     # Runtimes that cannot satisfy simplicity_hl_version MUST reject rather than silently compiling with another version.
     # A future ABI may define friendly network aliases, but wire-level matching in this ABI is by ELIP-0144 chain_id.
     # Changes to the static_values {value,type} shape or the signature-embedding rules require an ABI update or explicit capability negotiation.
    @@ -883,57 +883,72 @@ The returned TxCreateResponse remains the only authoritative result
     
     == Rationale ==
     
    -The ABI uses ELIP-0144 chain_id values instead of bare network names so wallets can match requests against
    -the identity of the active Elements chain. This avoids ambiguity between Liquid mainnet, Liquid testnet, Liquid regtest, and custom networks.
    +=== Canonical identifiers and wire encoding ===
     
    -Explicit caller-provided assets also use ELIP-0144 asset_id values. This lets wallet-connection transports,
    -review UIs, and cross-chain applications use one asset identifier syntax instead of translating between a Wallet ABI
    -asset format and the ELIP-0144 format. The runtime still extracts the raw Elements asset_reference when it
    +The chain validation rules in [[#Elip144ChainId|Elip144ChainId]] use ELIP-0144 chain_id values
    +instead of bare network names. This gives wallets a canonical chain identity to compare against the active Elements
    +chain before producing side effects. It also avoids ambiguity between Liquid mainnet, Liquid testnet, Liquid regtest,
    +and custom Elements networks.
    +
    +The explicit asset rules in [[#Elip144AssetId|Elip144AssetId]] use ELIP-0144 asset_id values
    +for the same anti-confusion reason. Wallet-connection transports, review UIs, and cross-chain applications can use one
    +asset identifier syntax, while the runtime can still extract the raw Elements asset_reference when it
     constructs transaction outputs or fills SIMF u256 arguments.
     
    -Satoshi amounts are encoded as decimal strings so JSON parsers in JavaScript and other environments do not lose
    -precision for values above their native safe-integer range. The string form preserves the full unsigned 64-bit domain
    -without requiring a binary encoding or language-specific bigint extension at the ABI boundary.
    +The decimal-string amount rule in [[#Wire-format rules|Wire-format rules]] avoids precision loss in JavaScript and other
    +environments whose native JSON number handling cannot safely represent every unsigned 64-bit satoshi/base-unit amount.
    +The string form preserves the full u64 domain without requiring binary encoding or language-specific bigint extensions at the ABI boundary.
    +
    +=== Request identity, mutable wallet state, and caller identity ===
    +
    +The request identity and state model in [[#Non-idempotency and deterministic boundaries|Non-idempotency and deterministic boundaries]]
    +intentionally treats request_id as correlation data, not replay protection or an idempotency key.
    +Wallet state, UTXO availability, fee policy, chain height, change-output selection, and broadcast outcomes can change between attempts.
    +For that reason, promising that the same JSON body always produces the same transaction would be misleading.
    +
    +The caller-identity rule in [[#Wallet/consumer-side review UI|Wallet/consumer-side review UI]] keeps authenticated
    +app/request identity outside the JSON payload. A browser origin/RP ID, native-app association, pairing session,
    +signed registry entry, or another out-of-band identity system can supply that context.
    +Self-declared labels inside the request are therefore treated as review and diagnostic metadata, not trusted identity.
     
    -request_id is a correlation identifier rather than replay protection because wallet state, UTXO availability,
    -fee policy, and broadcast status can change between attempts. Treating the request as non-idempotent avoids giving callers
    -a false guarantee that the same JSON body will always produce the same transaction.
    -The same JSON request sent later may produce a different transaction because wallet UTXOs, already-spent state,
    -chain height, fee policy, selected change outputs, and broadcast outcomes can change.
    +=== Unblinding, spend authorization, and confidentiality boundaries ===
     
    -App/request identity is intentionally not a trusted JSON field in this ABI. The authenticated caller context can come from
    -a browser origin/RP ID, native-app association, pairing session, signed registry entry, or another out-of-band identity system.
    -Exact discovery, registry, branding, and anti-phishing UI rules are out of scope for this standard.
    +The unblinding options in [[#InputUnblinding|InputUnblinding]] separate prevout-unblinding material
    +from spend authorization. A caller may provide blinding_secret_key only when it already knows the prevout
    +unblinding material out of band or when a protocol intentionally uses shared or known blinding material.
    +The field is named after its cryptographic role so it is not confused with a wallet signing key.
     
    -Input blinding secret keys can be provided only when the caller already knows the prevout unblinding material out of band
    -or the protocol intentionally uses shared/known blinding material. Some Simplicity contract constructions can work with
    -public or contract-known blinding material; the field is still named after its cryptographic role so it is not confused
    -with a spend key.
    +The issuance rules in [[#AssetVariant|AssetVariant]] require outputs carrying new_issuance_token to be confidential.
    +This keeps the ABI aligned with the current Liquid reissuance-token constraint and avoids introducing an explicit-token
    +mode without a separate capability profile.
     
    -SIMF payloads are JSON objects at the wire level to make review, schema validation, and application construction easier.
    -Static SIMF values use the SimplicityHL witness-style { "value": string, "type": string } shape because the
    -compiler, not the ABI, is responsible for parsing and type-checking Rust-like SimplicityHL literals.
    +=== SIMF payloads, compiler versioning, and internal-key stability ===
     
    -simplicity_hl_version is part of the request so the same source_simf is compiled by the version
    -intended by the caller. This is required because different compiler versions may produce different compiled programs,
    -addresses, script pubkeys, or finalization behavior.
    +The SIMF payload rules in [[#SIMF argument and witness payloads|SIMF argument and witness payloads]] keep arguments
    +and witness as JSON objects at the ABI wire level.
    +Static values use the SimplicityHL witness-style { "value": string, "type": string } shape because
    +the requested compiler, not the ABI, is responsible for parsing and type-checking SimplicityHL literals.
     
    -The stable bip0341 internal key source uses the BIP-341 NUMS/example x-only internal key because it is deterministic,
    -portable, and suitable as the initial interoperability baseline.
    +The exact-version rule in [[#Finalizer specification: FinalizerSpec|FinalizerSpec]] requires simplicity_hl_version
    +because different compiler versions may produce different compiled programs, addresses, script pubkeys, or finalization behavior
    +for the same source_simf.
     
    -Outputs carrying new_issuance_token are required to be confidential in this ABI to match the current
    -Liquid reissuance-token constraint.
    +The stable bip0341 internal key source in [[#Stable variant: bip0341|Internal key source]] uses the
    +deterministic BIP-341 NUMS/example x-only internal key as the initial interoperability baseline. Future internal-key
    +variants require an ABI/capability update.
     
    -Review and approval staging is runtime-dependent. Some runtimes are non-interactive; others split approval across wallet UI,
    -hardware-device prompts, finalization, and broadcast confirmation. The response remains the authoritative result regardless
    -of how the runtime structures those local stages.
    +=== Runtime review, approval staging, and responses ===
    +
    +The review and response rules in [[#Runtime processing model|Runtime processing model]] and [[#Response envelope: TxCreateResponse|TxCreateResponse]]
    +leave approval staging to the runtime. Some runtimes are non-interactive; others split approval across wallet UI, hardware prompts, finalization, and broadcast confirmation.
    +In every case, the response remains the authoritative result of that processing attempt.
     
     == Backwards Compatibility ==
     
     This ELIP defines a new application/wallet ABI and does not change Elements consensus rules, peer-to-peer networking,
     transaction validity, or the PSET format. Existing wallets and applications that do not implement this ABI are unaffected.
     
    -Unknown request fields are rejected by the current request/runtime schemas. Incompatible wire-shape changes require
    +Unknown request fields are rejected by the current JSON Schema request/runtime definitions. Incompatible wire-shape changes require
     an abi_version change or explicit capability negotiation.
     
     == Reference Implementation ==
    @@ -974,9 +989,6 @@ and schema constraints, but they are expected to be corrected or replaced after
     |-
     | [[elip-wallet-abi/wallet-abi-tx-create.schema.json|wallet-abi-tx-create.schema.json]]
     | Complete JSON Schema for request/response shape. It includes ELIP-0144 chain and asset ID patterns, decimal-string u64 amounts, blinding_secret_key, inflation_amount_sat, simplicity_hl_version, JSON SIMF payloads, static_values typed literals, stable bip0341, and a schema-level rejection of blinder = "explicit" when asset.type = "new_issuance_token".
    -|-
    -| [[elip-wallet-abi/field-reference.json|field-reference.json]]
    -| Machine-readable field reference for implementers and UI review.
     |}
     
     === Static value examples ===
    @@ -1015,81 +1027,6 @@ Multiple static witness values:
       }
     }
    -== References == - -These links are intentionally listed directly so reviewers do not need to search for the underlying standards or context. - -{| class="wikitable" -|- -! Topic -! Link -! Relevance -|- -| ELIP repository -| https://github.com/ElementsProject/ELIPs -| Repository that hosts Elements Improvement Proposals and review process context. -|- -| ELIP purpose and format -| https://github.com/ElementsProject/ELIPs/blob/main/elip-0001.mediawiki -| Defines the ELIP process, MediaWiki format, header preamble, and auxiliary file rules. -|- -| ELIP-0144 -| https://github.com/ElementsProject/ELIPs/blob/main/elip-0144.mediawiki -| Defines the Liquid account ID, chain ID, and asset ID syntax used by this ABI. -|- -| RFC 2119 requirement keywords -| https://www.rfc-editor.org/rfc/rfc2119 -| Defines the normative meaning of '''MUST''', '''SHOULD''', '''MAY''', and related terms. -|- -| JSON Schema draft 2020-12 -| https://json-schema.org/draft/2020-12/json-schema-core -| Version used by wallet-abi-tx-create.schema.json. -|- -| BIP-122 -| https://bips.dev/122/ -| Defines chain identity by genesis block hash for blockchain references. -|- -| CAIP-2 -| https://standards.chainagnostic.org/CAIPs/caip-2 -| Defines the namespace:reference chain-id form. -|- -| CAIP-19 -| https://standards.chainagnostic.org/CAIPs/caip-19 -| Defines the chain-agnostic asset ID shape adapted by ELIP-0144. -|- -| CAIP BIP122 namespace -| https://namespaces.chainagnostic.org/bip122/caip2 -| Defines bip122:32-character-lowercase-genesis-hash-prefix. -|- -| BIP-340 -| https://bips.dev/340/ -| Defines Schnorr signatures and 32-byte x-only public keys used by Taproot. -|- -| BIP-341 -| https://bips.dev/341/ -| Defines Taproot, internal keys, script-path control blocks, and the NUMS/example internal key used by bip0341. -|- -| Elements Project -| https://github.com/ElementsProject/elements -| Reference implementation for Elements/Liquid chain behavior. -|- -| SimplicityHL repository -| https://github.com/BlockstreamResearch/SimplicityHL -| Source project for source_simf and simplicity_hl_version context. -|- -| SimplicityHL witness documentation -| https://docs.simplicity-lang.org/documentation/witness/ -| Describes .wit JSON files where each top-level entry has value and type string fields and names are used as witness::NAME. -|- -| SimplicityHL issue #309 -| https://github.com/BlockstreamResearch/SimplicityHL/issues/309 -| Tracks the confidential-only reissuance-token constraint motivating the new_issuance_token confidentiality rule. -|- -| Semantic Versioning 2.0.0 -| https://semver.org/ -| Informative reference for the simplicity_hl_version string shape; the ABI requires an exact compiler version, not a numeric JSON value. -|} - == Appendix A: Future Work == This appendix collects ideas that are intentionally not part of the wallet-abi-0.1 core. @@ -1120,61 +1057,7 @@ Explicit reissuance-token support, if added later, would require an ABI/capabili A future ABI will need to finalize how the generated BIP-340 signature is embedded back into the SimplicityHL WitnessValues structure, including structures that contain branching such as Right(Left((, ...))). -== Appendix B: Informative consumer/runtime implementation notes == - -This appendix is not a caller-visible wire schema and is not required as provider API surface. It records one useful -runtime implementation model for wallet providers. Transport bindings, provider session objects, UTXO-cache structure, -and UI-state machines remain out of scope for the core ABI payload. - -=== B.1 WalletRequestSession === - -{| class="wikitable" -|- -! Field -! Definition -|- -| session_id -| Opaque wallet-owned correlation ID. -|- -| chain_id -| ELIP-0144 chain ID used for request validation and script derivation. -|- -| spendable_utxos -| Deterministic spendable UTXO snapshot used for input selection within one request lifecycle. -|} - -=== B.2 WalletOutputRequest === - -{| class="wikitable" -|- -! Variant -! Definition -|- -| Receive { index } -| Deterministic zero-based receive-output index within a build pass. -|- -| Change { index, asset_id } -| Deterministic zero-based change-output index for a concrete residual ELIP-0144 asset ID. -|} - -=== B.3 WalletOutputTemplate === - -{| class="wikitable" -|- -! Field -! Definition -|- -| script_pubkey -| Wallet-selected script for receive/change output. -|- -| blinding_pubkey -| Optional blinding public key for confidential outputs. -|} - -A wallet output allocator is expected to be stable for the same (session, request) pair if the provider exposes -preview/final-build behavior, but this is an implementation note rather than a separate ABI field. - -== Appendix C: JSON Schema == +== Appendix B: JSON Schema == The review schema for wallet-abi-0.1 request/response payloads is provided as [[elip-wallet-abi/wallet-abi-tx-create.schema.json|wallet-abi-tx-create.schema.json]]. diff --git a/elip-wallet-abi/03_response_error_funding.json b/elip-wallet-abi/03_response_error_funding.json index 0a8c900..c92e45d 100644 --- a/elip-wallet-abi/03_response_error_funding.json +++ b/elip-wallet-abi/03_response_error_funding.json @@ -8,7 +8,7 @@ "message": "insufficient wallet balance for asset bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49", "details": { "requested_asset_id": "bip122:a771da8e52ee6ad581ed1e9a99825e5b/elip144:144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49", - "requested_amount_sat": "100000", + "requested_amount_sat": "150000", "available_amount_sat": "12345", "broadcast_attempted": false } diff --git a/elip-wallet-abi/field-reference.json b/elip-wallet-abi/field-reference.json deleted file mode 100644 index 7b0632b..0000000 --- a/elip-wallet-abi/field-reference.json +++ /dev/null @@ -1,254 +0,0 @@ -[ - { - "path": "TxCreateRequest.abi_version", - "type": "string", - "required": true, - "definition": "ABI contract version. Must equal wallet-abi-0.1." - }, - { - "path": "TxCreateRequest.request_id", - "type": "uuid", - "required": true, - "definition": "Correlation identifier generated per user action. Not replay protection and not an idempotency key." - }, - { - "path": "TxCreateRequest.chain_id", - "type": "Elip144ChainId", - "required": true, - "definition": "ELIP-0144 chain_id string, bip122:. Must match runtime chain ID before side effects." - }, - { - "path": "TxCreateRequest.params", - "type": "RuntimeParams", - "required": true, - "definition": "Transaction-construction request body." - }, - { - "path": "TxCreateRequest.broadcast", - "type": "boolean", - "required": true, - "definition": "Whether runtime should publish the finalized transaction. false still permits sync/fetch/validation calls." - }, - { - "path": "RuntimeParams.inputs", - "type": "InputSchema[]", - "required": true, - "definition": "Declared inputs resolved in order. Order can affect wallet selection and issuance-linked references." - }, - { - "path": "RuntimeParams.outputs", - "type": "OutputSchema[]", - "required": true, - "definition": "Declared outputs materialized in order. Runtime may append fee and per-asset change outputs." - }, - { - "path": "RuntimeParams.fee_rate_sat_kvb", - "type": "float", - "required": false, - "definition": "Optional finite non-negative fee rate in sat/kvB." - }, - { - "path": "RuntimeParams.lock_time", - "type": "LockTime", - "required": false, - "definition": "Optional fallback locktime. Effective only when input sequence semantics activate locktime." - }, - { - "path": "InputSchema.id", - "type": "string", - "required": true, - "definition": "Caller-facing label for diagnostics and review UI." - }, - { - "path": "InputSchema.utxo_source", - "type": "UTXOSource", - "required": true, - "definition": "Prevout source selector: wallet-selected from filters or caller-provided outpoint." - }, - { - "path": "InputSchema.unblinding", - "type": "InputUnblinding", - "required": true, - "definition": "How runtime obtains prevout values/secrets: wallet, provided blinding_secret_key, or explicit." - }, - { - "path": "InputUnblinding.provided.blinding_secret_key", - "type": "SecretKey", - "required": "provided only", - "definition": "Caller-supplied input blinding secret key for prevout unblinding. This is not a spend/signing private key; handle as sensitive unless explicitly policy-marked public." - }, - { - "path": "InputSchema.sequence", - "type": "u32", - "required": true, - "definition": "Bitcoin/Elements input sequence for finality, locktime, relative locktime, and RBF semantics." - }, - { - "path": "InputSchema.issuance", - "type": "InputIssuance?", - "required": false, - "definition": "Optional issuance/reissuance metadata used for PSET issuance fields and issuance-linked output asset IDs." - }, - { - "path": "InputIssuance.kind", - "type": "new | reissue", - "required": true, - "definition": "Issuance kind for this input." - }, - { - "path": "InputIssuance.asset_amount_sat", - "type": "u64 decimal string", - "required": true, - "definition": "Amount of issued/reissued asset units to mint, encoded as a decimal string." - }, - { - "path": "InputIssuance.inflation_amount_sat", - "type": "u64 decimal string", - "required": true, - "definition": "Amount of reissuance/inflation-token units to mint, encoded as a decimal string. Replaces token_amount_sat." - }, - { - "path": "InputIssuance.entropy", - "type": "[u8; 32]", - "required": true, - "definition": "For new issuance, contract-hash entropy; for reissue, already-derived asset entropy." - }, - { - "path": "InputSchema.finalizer", - "type": "FinalizerSpec", - "required": true, - "definition": "Input finalization strategy: wallet/miniscript or SimplicityHL finalizer." - }, - { - "path": "OutputSchema.id", - "type": "string", - "required": true, - "definition": "Caller-facing output label for diagnostics and UI." - }, - { - "path": "OutputSchema.amount_sat", - "type": "u64 decimal string", - "required": true, - "definition": "Requested output amount in satoshi/base units, encoded as a decimal string." - }, - { - "path": "OutputSchema.lock", - "type": "LockVariant", - "required": true, - "definition": "How runtime determines scriptPubKey: wallet receive template, raw script, or finalizer-derived script." - }, - { - "path": "OutputSchema.asset", - "type": "AssetVariant", - "required": true, - "definition": "ELIP-0144 asset_id string or issuance-derived asset/token selector. Explicit ELIP-0144 asset_ids must have a chain_id matching TxCreateRequest.chain_id." - }, - { - "path": "OutputSchema.asset.new_issuance_token", - "type": "AssetVariant", - "required": false, - "definition": "Confidential reissuance/inflation token derived from a new issuance input. The resulting ELIP-0144 asset_id uses the request chain_id and the derived asset_reference. Outputs using this asset MUST NOT use blinder = explicit." - }, - { - "path": "OutputSchema.blinder", - "type": "BlinderVariant", - "required": true, - "definition": "Output confidentiality policy: wallet blinding key, provided blinding pubkey, or explicit output." - }, - { - "path": "FinalizerSpec.type", - "type": "wallet | simf", - "required": true, - "definition": "Finalization variant tag." - }, - { - "path": "FinalizerSpec.source_simf", - "type": "string", - "required": "simf only", - "definition": "UTF-8 SimplicityHL source loaded/instantiated at runtime." - }, - { - "path": "FinalizerSpec.simplicity_hl_version", - "type": "string", - "required": "simf only", - "definition": "Exact Cargo/SimplicityHL compiler version the runtime must use for compilation/address derivation/finalization." - }, - { - "path": "FinalizerSpec.internal_key", - "type": "InternalKeySource", - "required": "simf only", - "definition": "Source for Taproot x-only internal key. Stable wallet-abi-0.1 supports only bip0341." - }, - { - "path": "FinalizerSpec.arguments", - "type": "SimfArguments JSON object", - "required": "simf only", - "definition": "SIMF argument payload as a JSON object at the ABI wire level; no UTF-8 byte-array wrapper." - }, - { - "path": "FinalizerSpec.witness", - "type": "SimfWitness JSON object", - "required": "simf only", - "definition": "SIMF witness payload as a JSON object at the ABI wire level; no UTF-8 byte-array wrapper." - }, - { - "path": "TxCreateResponse.status", - "type": "ok | error", - "required": true, - "definition": "High-level outcome." - }, - { - "path": "TxCreateResponse.transaction", - "type": "TransactionInfo?", - "required": "ok only", - "definition": "Finalized transaction hex and txid." - }, - { - "path": "TxCreateResponse.artifacts", - "type": "object?", - "required": false, - "definition": "Open-ended producer metadata. Consumers must ignore unknown keys." - }, - { - "path": "TxCreateResponse.error", - "type": "ErrorInfo?", - "required": "error only", - "definition": "Structured error code, technical message, and optional details." - }, - { - "path": "FinalizerSpec.simf.arguments.static_values", - "type": "SimfStaticValues", - "required": true, - "definition": "Caller-known compile-time/static SIMF argument values. Map from SimplicityHL argument name to {value,type} strings; values are parsed/type-checked by the requested SimplicityHL compiler." - }, - { - "path": "FinalizerSpec.simf.arguments.runtime_arguments", - "type": "object", - "required": true, - "definition": "Runtime-resolved SIMF argument directives, keyed by the target SimplicityHL argument name, such as deriving COLLATERAL_ASSET_ID from a selected issuance input." - }, - { - "path": "FinalizerSpec.simf.witness.static_values", - "type": "SimfStaticValues", - "required": true, - "definition": "Caller-known static witness values, keyed by SimplicityHL witness name. Examples include PATH branch selectors or COLLATERAL_AMOUNT constants encoded as typed literal strings." - }, - { - "path": "FinalizerSpec.simf.witness.runtime_arguments", - "type": "RuntimeSimfWitness[]", - "required": true, - "definition": "Runtime-resolved witness directives. sig_hash_all signature embedding is still TODO/draft and must be finalized before production compatibility is claimed." - }, - { - "path": "SimfStaticValues..value", - "type": "string", - "required": true, - "definition": "SimplicityHL literal string, for example Right(Left((false, 10, 1000))) or 100. Numeric values remain strings, following SimplicityHL witness-file conventions." - }, - { - "path": "SimfStaticValues..type", - "type": "string", - "required": true, - "definition": "SimplicityHL type annotation string, for example u64, Signature, (bool, u64), or Either<...>." - } -] diff --git a/elip-wallet-abi/wallet-abi-tx-create.schema.json b/elip-wallet-abi/wallet-abi-tx-create.schema.json index c4e3bd7..26d23a7 100644 --- a/elip-wallet-abi/wallet-abi-tx-create.schema.json +++ b/elip-wallet-abi/wallet-abi-tx-create.schema.json @@ -472,7 +472,7 @@ } } ], - "description": "Runtime-resolved SIMF witness directive. sig_hash_all is a draft/TODO signature-embedding directive." + "description": "Runtime-resolved SIMF witness directive. sig_hash_all embeds a runtime-generated signature into the named witness slot." }, "SimfArguments": { "type": "object", @@ -515,6 +515,39 @@ } } }, + "SimfFinalizerSpec": { + "type": "object", + "required": [ + "type", + "source_simf", + "simplicity_hl_version", + "internal_key", + "arguments", + "witness" + ], + "additionalProperties": false, + "properties": { + "type": { + "const": "simf" + }, + "source_simf": { + "type": "string", + "minLength": 1 + }, + "simplicity_hl_version": { + "$ref": "#/$defs/SimplicityHLVersion" + }, + "internal_key": { + "$ref": "#/$defs/InternalKeySource" + }, + "arguments": { + "$ref": "#/$defs/SimfArguments" + }, + "witness": { + "$ref": "#/$defs/SimfWitness" + } + } + }, "FinalizerSpec": { "oneOf": [ { @@ -530,36 +563,7 @@ } }, { - "type": "object", - "required": [ - "type", - "source_simf", - "simplicity_hl_version", - "internal_key", - "arguments", - "witness" - ], - "additionalProperties": false, - "properties": { - "type": { - "const": "simf" - }, - "source_simf": { - "type": "string" - }, - "simplicity_hl_version": { - "$ref": "#/$defs/SimplicityHLVersion" - }, - "internal_key": { - "$ref": "#/$defs/InternalKeySource" - }, - "arguments": { - "$ref": "#/$defs/SimfArguments" - }, - "witness": { - "$ref": "#/$defs/SimfWitness" - } - } + "$ref": "#/$defs/SimfFinalizerSpec" } ] }, @@ -636,7 +640,7 @@ "const": "finalizer" }, "finalizer": { - "$ref": "#/$defs/FinalizerSpec" + "$ref": "#/$defs/SimfFinalizerSpec" } } } From c946695f75f98477008bad0059d2894696bbaadd Mon Sep 17 00:00:00 2001 From: Kyryl R Date: Wed, 13 May 2026 16:43:23 +0300 Subject: [PATCH 6/6] wallet abi: added A.6 State Management, removed note about ELIP number --- elip-wallet-abi.mediawiki | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/elip-wallet-abi.mediawiki b/elip-wallet-abi.mediawiki index 0850f15..a6ce481 100644 --- a/elip-wallet-abi.mediawiki +++ b/elip-wallet-abi.mediawiki @@ -965,7 +965,6 @@ dispatch, finalizer script-pubkey verification tests, and fixtures covering conf == Test Vectors and Auxiliary Files == The auxiliary files below are intended to be committed with this draft in the elip-wallet-abi/ subdirectory. -After an ELIP number is assigned, the directory and links can be renamed according to editor preference. The example request and response files are mock fixtures for the current draft. They exercise the proposed JSON shape and schema constraints, but they are expected to be corrected or replaced after the first proper wallet/runtime implementation is available. @@ -1057,6 +1056,11 @@ Explicit reissuance-token support, if added later, would require an ABI/capabili A future ABI will need to finalize how the generated BIP-340 signature is embedded back into the SimplicityHL WitnessValues structure, including structures that contain branching such as Right(Left((, ...))). +=== A.6 State Management === + +A future ABI MAY extend [[#Finalizer specification: FinalizerSpec|FinalizerSpec]] and/or [[#InternalKeySource|InternalKeySource]] +to support Simplicity covenants whose Taproot output commits to contract state. + == Appendix B: JSON Schema == The review schema for wallet-abi-0.1 request/response payloads is provided as