Wallet Owner API v3
The Owner API is how software drives a wallet: create it, read balances, build and finalise transfers, verify proofs. For most integrations it is the primary surface.
- Endpoint:
http://127.0.0.1:3420/v3/owner, started withepic-wallet owner_api - Protocol: JSON-RPC 2.0 over HTTP POST
- Credential: the
tokenreturned byopen_wallet, which takes the wallet password - Encryption: an ECDH handshake wraps every call after the first
Send the token inside the envelope on every method that declares one. Keep the port on loopback. See
owner access on the wallet.
Methods by what they can do
Can spend funds
Can spend funds These seven build, complete or abandon transfers.
| Method | Purpose |
|---|---|
init_send_tx() | Select inputs and build the first round of a slate |
tx_lock_outputs() | Reserve the selected inputs. Required in a manual send sequence. Takes token, slate, participant_id and addr_to |
finalize_tx() | Complete the aggregate signature |
post_tx() | Broadcast to the network |
issue_invoice_tx() | Create a payment request |
process_invoice_tx() | Fund someone else's payment request |
cancel_tx() | Abandon a transfer and release its reserved outputs |
Destructive
Destructive Deletes local wallet data.
| Method | Effect |
|---|---|
delete_wallet() | Deletes the wallet |
Exposes a secret
get_mnemonic() returns the recovery phrase.
Changes wallet state
change_password() re-encrypts the seed.
scan() rebuilds output state.
Read only
Read only Safe for anything you would allow to read your balance.
accounts(),
retrieve_outputs(),
retrieve_txs(),
retrieve_summary_info(),
node_height(),
get_stored_tx(),
get_public_address(),
get_public_proof_address(),
get_updater_messages().
Wallet lifecycle
create_config(),
create_wallet(),
open_wallet(),
close_wallet(),
get_top_level_directory(),
set_top_level_directory(),
create_account_path(),
set_active_account().
open_wallet returns the token that every other call requires.
Proofs
retrieve_payment_proof(),
verify_payment_proof(),
proof_address_from_onion_v3(),
verify_slate_messages(). See
payment proofs.
Configuration and background updates
set_tor_config(),
set_epicbox_config(),
start_updater(),
stop_updater().
Transport
The encrypted handshake
Every call after init_secure_api travels inside an encrypted envelope. The parameters are fixed and
declared at api/src/owner_rpc_s.rs:1453: AES-256 in GCM mode, a
12-byte nonce, a 16-byte tag appended to the ciphertext, and empty additional authenticated data.
- Generate a secp256k1 keypair in your client.
- Call
init_secure_apiwith your compressed public key as hex inecdh_pubkey. The wallet returns its own in the same form. - Multiply the wallet's public point by your private scalar and keep the 32-byte x coordinate. That
is the AES-256 key (
api/src/owner_rpc_s.rs:2433). - Serialise the call you want as a complete JSON-RPC request object. That inner request is what gets
encrypted, and it is where the
tokenand the method params go. - Encrypt it under a fresh 12-byte nonce and base64 the ciphertext with its tag appended.
- Post the method
encrypted_request_v3with two params,nonceas hex andbody_encas that base64 string. The envelope has no other fields (api/src/types.rs:59). - The reply is
encrypted_response_v3carrying its ownnonceandbody_enc. Decrypt with the same key to recover the inner JSON-RPC response, which then has its ownOkorErrenvelope. open_walletis the first call to send through the envelope. It returns the token every other method takes.
{"jsonrpc": "2.0", "id": 1, "method": "encrypted_request_v3", "params": {"nonce": "ef32...", "body_enc": "e0bcd..."}}
examples/python/epic_wallet.py
implements the sequence, including the second unwrap of the decrypted body. The client is listed in
full on connect and read.
Reading outputs and transactions
retrieve_outputs and retrieve_txs take limit, offset and sort_order.
InitTxArgs
Controls input selection and transaction shape.
| Field | Type | Meaning |
|---|---|---|
src_acct_name | string, optional | Source account. Null uses the active account |
amount | u64 | Amount in freemen. 1 EPIC is 100000000 |
minimum_confirmations | u64 | Confirmations required before an output is eligible |
max_outputs | u32 | Maximum number of inputs to select |
num_change_outputs | u32 | How many change outputs to create |
selection_strategy_is_use_all | bool | True consolidates every eligible output; false selects the minimum |
message | string, optional | Message committed into the slate |
target_slate_version | u16, optional | Slate version to emit, 2 or 3 |
ttl_blocks | u64, optional | Expiry in blocks. Defaults to none |
payment_proof_recipient_address | string, optional | Requests a payment proof |
estimate_only | bool, optional | Compute the fee without reserving anything |
send_args | object, optional | Destination and transport, to run the whole exchange in one call |
Additional behaviour:
selection_strategy_is_use_all has privacy consequences. True consolidates your outputs into one
transaction, which links them together for anyone analysing the chain. False keeps them separate at the
cost of a larger UTXO set later.
A payment proof needs slate V3. payment_proof_recipient_address puts the proof fields in the
slate, and only V3 carries them. Delivery over epicbox converts the slate to V2, so a transfer sent
that way completes and yields no proof. Pick the transport first:
choose the transport accordingly.
ttl_blocks does not release outputs on expiry. See
outputs and locking.
src_acct_name names the source account for one call. A label that accounts does not return
resolves to the active account (libwallet/src/api_impl/owner.rs:383).
See accounts.
send_args runs the exchange inside the call. It delivers the slate, then finalises and posts if you
asked it to, so the call blocks for as long as the counterparty takes.
With send_args.method set to epicbox, the call returns the round-one slate as soon as it is
posted to the relay and the inputs are locked
(api/src/owner.rs:761). finalize and post_tx apply to the
http and keybase paths. On the epicbox path the wallet's own subscription finalises and posts when
the counterparty's reply arrives, which is also where the mempool wait happens.
Fees
The fee is a function of transaction shape, not of network demand:
fee = max(4 × outputs + kernels − inputs, 1) × 0.001 EPIC
A typical two-input, two-output, one-kernel transfer costs 700,000 freemen, which is 0.007 EPIC. Because no base fee is supplied by the wallet, there is no fee market to bid into.
Version 2
An earlier, unencrypted Owner API with 17 methods is served from the same listener, at /v2/owner.
Its methods take no token. New work should target v3, and the listener belongs on loopback.
Full method reference
Ten methods. The handshake, the token, and account labels.
Eight methods. Balances, outputs, history, addresses.
Seven methods. The ones that move value.
Four methods, and the transport that discards them.
Four methods. Recovery phrase, password, deletion and scan.
Four methods. Relay settings and background refresh.
Source
api/src/owner_rpc_s.rsdefines every v3 method, most with a worked JSON request and response in its documentation commentapi/src/owner_rpc.rsfor the older v2 surfacelibwallet/src/api_impl/owner.rsfor the implementation behind the methodslibwallet/src/api_impl/types.rsforInitTxArgsand friendscontroller/src/controller.rs:123for how the listener and its middleware are wired