Skip to content

feat: attribute shop and locks receipts to the paying contact #1387

Description

@ovitrif

Twin: synonymdev/bitkit-ios#849

Problem or use case

When a contact pays a creator's Shop order or unlocks one of their Locks posts, the creator's Bitkit records the on-chain receipt without the payer:

  • the activity row reads "Received", and its detail offers "Assign";
  • the receipt is missing from the payer's contact activity page.

A payment between the same two contacts made in Bitkit reads "Received from " and is listed on the contact page. In a regtest run on 25 Sep, the creator's contact page for the payer listed four Lightning payments and missed the Shop and Locks receipts ($120.14 and $5.47). The payer's contact page for the creator listed all six payments.

Proposed solution

  • When an on-chain payment arrives at a server-derived address, Bitkit sets the contact who paid it, next to the private-address lookup in handleOnchainTransactionReceived. The row then reads "Received from ", and the contact page lists the receipt.
  • This needs a Paykit Server change first, because the creator's wallet has no way to learn who a server-derived address was handed to. No Paykit Server issue exists yet (I checked the issues of pubky/paykit-server and BitcoinErrorLog/paykit-server). The change: the server already derives each address for one reader (invoices.reader_lookup_hash sits next to bitcoin_address_lookup_hash, paykit-server/migrations/0001_initial.sql:41-49 on 722ef26), so it can also hand the wallet the pair (address, reader pubky) when it derives the address, for example as a record the server writes for the wallet. Bitkit then looks the paying address up in those pairs.

Alternatives considered

  • The payer's Bitkit tells the creator's wallet, over their existing wallet link, which transaction paid a server request. This needs no server change, but it relies on the payer's wallet reporting every payment.
  • The creator assigns each receipt by hand with "Assign", which works today.

Additional context

Code on master (4d13a1d):

  • AppViewModel.kt:1655-1674 (handleOnchainTransactionReceived) sets a contact only when an output address is one the wallet reserved for a contact's private Paykit endpoint (:1661, lookup at PrivatePaykitRepo.kt:500-505):
    val contactPublicKey = privatePaykitRepo.contactPublicKeyForPrivateOnchainAddresses(addresses)
    A Shop or Locks payment goes to an address the Paykit Server derives from the creator's watch-only account, so it never matches.
  • The contact page and the row title read the same field. ActivityRepo.kt:459-467 keeps the activities where PubkyPublicKeyFormat.matches(it.contact(), normalizedKey), and ContactActivityTitle.kt:28-31 (contactForActivity) names the row from activity.contact(). The one missing attribution causes both gaps.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions