Skip to content

Support vault and watch wallets across the RPC, WalletConnect and Sage Apps - #1018

Open
Rigidity wants to merge 4 commits into
rigidity/vault-assets-offersfrom
rigidity/vault-external
Open

Rigidity wants to merge 4 commits into
rigidity/vault-assets-offersfrom
rigidity/vault-external

Conversation

@Rigidity

@Rigidity Rigidity commented Nov 15, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #956. Part of #945. Stacked on #1017.

Summary

The whole external surface now has defined behavior for BLS, vault and watch wallets: the RPC, WalletConnect and the Sage Apps bridge. Vaults can sign dApp spends and messages.

  • Endpoint audit:
  • Derivations for vaults:
    • get_derivations returns the P2 singleton addresses by nonce, with no public key, so DerivationRecord.public_key is now optional.
    • get_sync_status reports the number of vault addresses.
    • increase_derivation_index adds vault addresses and refuses hardened ones.
    • Watch wallets get an empty list.
  • Change address: only BLS wallets use one. set_change_address refuses vault and watch wallets, though clearing an address still works.
  • New errors: WalletKindNotSupported and VaultSignatureNotAllowed. Watch wallets keep the existing WatchOnly error for every signing request.
  • Signing:
    • sign_coin_spends for a vault signs only with its custody signers' keys, after clear signing checks the vault spend.
    • sign_message_by_address with a vault address signs as the vault with SDK 0.38.0's vault_message_envelope. It returns a vaultsig proof in signature, and the vault's vault1 id as public_key. ent-wallet has no convention for this response, so the format is new here.
    • sign_message_with_public_key is BLS only.
  • Asset coins: get_asset_coins returns real P2 singleton and P2-conditions-or-singleton puzzle reveals.
  • WalletConnect:
    • chip0002_getPublicKeys returns no keys for vaults, so dApps use chia_getAddress and chip0002_getAssetCoins instead.
    • Sending, signing, offers and bulk minting go through the vault pipeline.
  • Sage Apps bridge:
    • wallet.listWallets includes each wallet's kind.
    • Vaults can use the signing methods, except wallet.signMessage, which signs by public key.
    • A vault without signers is refused with no_vault_signers before the user is asked to approve.

This hardens #1014's signing

Before this PR, sign_with in #1014 would sign any spend that didn't include the vault coin. A dApp could send sign_coin_spends a spend asking the custody key for AGG_SIG_ME on some other coin. It could also include the vault coin twice, with the second spend's delegated puzzle never checked by clear signing.

Now a vault key signs AGG_SIG_ME only for the single vault spend that clear signing parsed, and both cases are refused. The stack lands together, so the hole is never released, but it's worth knowing when reviewing #1014 on its own.

Deferred

  • There are no bridge-level tests, since sage-apps has no test setup for wallet state. The bridge changes are only compile-checked.
  • Watch wallets still error on get_asset_coins, so WalletConnect's chip0002_getAssetBalance errors for them too.

Testing

  • sage-rpc, new vault_external.rs:
    • vault derivations and sync status, and the address gap
    • adding addresses, and refusing hardened ones and a change address
    • asset coin puzzle reveals that hash to the coin
    • signing a message by address, verified with verify_vault_signed_message
    • refusing another vault's address and signing by public key
    • refusing a dApp spend for another coin and a duplicated vault spend, then signing and submitting the real transaction
  • sage-rpc, watch_wallets.rs: checks the change address and sign-by-public-key refusals.
  • Sandbox, on the top of the stack:
    • sign_message_by_address returned a vaultsig1... proof with the vault1 id.
    • get_derivations listed vault addresses by nonce with no public keys.
    • sign_message_with_public_key was refused with a clear error.
  • Checks: all of them, at the top of the stack.

Screenshots

A vault's receive address
Addresses

@Rigidity
Rigidity added this pull request to stack #970 November 15, 2026 05:50
@Rigidity Rigidity changed the title rigidity/vault external Support vault and watch wallets across the RPC, WalletConnect and Sage Apps Nov 15, 2026
…for dApps

Vaults list their P2 singleton addresses as derivations, can add more by nonce,
and always send change back to the vault. A vault's keys only sign the vault's
own custody spend that clear signing checked, so a dApp's spend can't use them
for another coin or a second spend of the vault coin. Signing a message by a
vault address returns a vaultsig proof. Every RPC endpoint's OpenAPI
description says how it behaves for each wallet kind, and docs/wallet-kinds.md
covers the RPC, WalletConnect and Sage Apps.
@Rigidity
Rigidity force-pushed the rigidity/vault-external branch from 5f21b68 to 2b73c64 Compare November 15, 2026 06:00

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support vault and watch wallets across RPC, WalletConnect, and Sage Apps

1 participant