Skip to content

Commit 9a140cb

Browse files
authored
Merge pull request #147 from synonymdev/feat/pubky-profile
Feat/pubky profile e2e tests
2 parents c3d5348 + 3e0e6e5 commit 9a140cb

18 files changed

Lines changed: 1756 additions & 33 deletions

AGENTS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ Notes:
4444
- `BACKEND=local` uses local Electrum (default).
4545
- `BACKEND=regtest` sets network Electrum against regtest.
4646

47+
### Test fixtures (images for profile avatar, etc.)
48+
49+
Images in `test/fixtures/` can be pushed to a running Android emulator (`/sdcard/Pictures/`) and iOS Simulator (Photos) via:
50+
51+
```bash
52+
./scripts/push-fixture-media-to-devices.sh
53+
```
54+
55+
See `docs/pubky-profile-manual-e2e.md` (preconditions).
56+
4757
## Running Tests
4858

4959
**Important:** The `BACKEND` env var controls which infrastructure the tests use for deposits/mining:

docs/pubky-profile-manual-e2e.md

Lines changed: 250 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
# Public Contact Payments — Manual QA Charter
2+
3+
Manual test plan for public Paykit payments to Pubky contacts.
4+
5+
PR context:
6+
7+
- Android: synonymdev/bitkit-android#924
8+
- iOS: synonymdev/bitkit-ios#531
9+
10+
## Scope
11+
12+
Verify that Bitkit can discover public payment endpoints from a Pubky profile/contact and route payments through the existing send flow.
13+
14+
Covered surfaces:
15+
16+
- Pay Contacts endpoint publishing.
17+
- Payment from saved contact and non-saved Pubky.
18+
- Payment via Add Contact, Contact Detail, QR scanner, paste/manual send flow.
19+
- On-chain, Lightning/Bolt11, and combined public payment requests.
20+
- Contact-tagged activity and contact activity screen.
21+
- On-chain boosts (RBF/CPFP) preserving expected activity behavior.
22+
23+
## Preconditions
24+
25+
Run on both Android and iOS where possible.
26+
27+
Use staging/regtest builds unless explicitly testing mainnet. Mainnet Pubky profile creation may depend on current Pubky stack rollout status.
28+
29+
Recommended accounts/devices:
30+
31+
- **Wallet A / Sender**: funded wallet used to pay.
32+
- **Wallet B / Recipient**: wallet with Pubky profile and Pay Contacts enabled.
33+
- Optional **Wallet C / Non-contact recipient**: useful for testing payment to a Pubky that is not yet in Wallet A's contact list.
34+
35+
Funding recommendations:
36+
37+
- Sender has enough on-chain funds for on-chain sends and RBF/CPFP scenarios.
38+
- Sender has an active Lightning channel and spending balance for Bolt11/contact Lightning payments.
39+
- Recipient has completed Pubky profile creation.
40+
41+
## Setup Checks
42+
43+
### S1. Publish public endpoints
44+
45+
1. On Wallet B, create or restore a Pubky profile.
46+
2. On first-time **Pay Contacts** screen, keep public payments enabled and continue.
47+
3. If settings expose the Pay Contacts toggle, turn it off and on again.
48+
4. Confirm no error toast appears.
49+
5. If available, verify public endpoints on `payky.app` or equivalent tooling.
50+
51+
Expected:
52+
53+
- With Pay Contacts enabled, Wallet B publishes public payment endpoints.
54+
- With Pay Contacts disabled, Wallet B does not publish endpoints or removes previously published endpoints.
55+
- Toggling the setting is resilient if Lightning is not immediately ready, as long as on-chain endpoint publishing is possible.
56+
57+
### S2. Disabled recipient
58+
59+
1. On another recipient wallet/profile, disable Pay Contacts.
60+
2. Try to pay that Pubky from Wallet A.
61+
62+
Expected:
63+
64+
- App does not offer a broken send flow.
65+
- User sees clear unavailable/no payment methods messaging.
66+
67+
## Core Payment Matrix
68+
69+
Run the following combinations at minimum once on Android and once on iOS.
70+
71+
| Case | Contact state | Entry point | Payment method | Expected |
72+
| --- | --- | --- | --- | --- |
73+
| P1 | Saved contact | Contact Detail → Send | On-chain | Payment succeeds; activity is tagged to contact. |
74+
| P2 | Saved contact | Contact Detail → Send | Bolt11/Lightning | Payment succeeds; activity is tagged to contact. |
75+
| P3 | Saved contact | Contact Detail → Send | Combined/BIP21 | App chooses valid route or lets user choose; activity is tagged to contact. |
76+
| P4 | Not in contacts | Add Contact flow | On-chain | User can pay public endpoint if supported by product; contact creation state stays correct. |
77+
| P5 | Not in contacts | Add Contact flow | Bolt11/Lightning | User can pay public endpoint if supported; no contact is silently created unless explicitly saved. |
78+
| P6 | Not in contacts | QR scanner with Pubky | Any available | Routes to Add Contact / Contact Detail as appropriate, then payment succeeds. |
79+
| P7 | Not in contacts | Send → manual/paste Pubky | Any available | Routes to Pubky/contact payment flow, not invalid-address error. |
80+
| P8 | Existing contact | Send → manual/paste Pubky | Any available | Routes to existing contact rather than Add Contact. |
81+
82+
For each successful payment, verify:
83+
84+
- Review screen shows contact name/pubky context.
85+
- Amount and asset selection are correct.
86+
- Swipe/confirm sends successfully.
87+
- Main activity shows a sent payment with the expected amount.
88+
- Contact activity screen shows the sent payment under the contact.
89+
- Contact context is not leaked to the next unrelated payment.
90+
91+
## Detailed Test Cases
92+
93+
### T1. Saved contact, on-chain payment
94+
95+
1. Wallet A adds Wallet B as a contact.
96+
2. Open Wallet B contact detail.
97+
3. Tap Send/Pay.
98+
4. Choose or confirm on-chain route.
99+
5. Enter a small amount.
100+
6. Send.
101+
7. Mine/confirm if needed.
102+
103+
Expected:
104+
105+
- Payment succeeds.
106+
- Wallet A main activity shows `Sent to {contact name}` or equivalent contact title where supported.
107+
- Contact Activity for Wallet B includes the sent on-chain payment.
108+
- Wallet B receives the on-chain payment.
109+
110+
### T2. Saved contact, Lightning payment
111+
112+
1. Ensure Wallet A has spending balance and Wallet B has public Lightning endpoint.
113+
2. Open Wallet B contact detail.
114+
3. Tap Send/Pay.
115+
4. Choose or confirm Lightning route.
116+
5. Send a small amount.
117+
118+
Expected:
119+
120+
- Payment succeeds.
121+
- Activity is tagged to Wallet B.
122+
- If payment goes pending, pending screen and later success/failure keep the correct contact context.
123+
- Retrying or sending a later unrelated payment does not reuse stale Wallet B contact context.
124+
125+
### T3. Saved contact, combined public request
126+
127+
1. Use a recipient with both on-chain and Lightning endpoints available.
128+
2. Start payment from contact detail.
129+
3. Check default method and asset switch behavior.
130+
4. Send via default route.
131+
5. Repeat and switch to the other available route if UI allows.
132+
133+
Expected:
134+
135+
- Route priority matches product expectations.
136+
- Asset switching does not lose contact context.
137+
- Activity is tagged correctly for both routes.
138+
139+
### T4. Add Contact screen, Pubky not saved
140+
141+
1. On Wallet A, open Contacts → Add Contact.
142+
2. Enter/paste Wallet C pubky.
143+
3. Let the profile/payment details load.
144+
4. If the Send/Pay button is present by design, tap it.
145+
5. Complete on-chain and Lightning payment variants where endpoints exist.
146+
6. Return to Contacts.
147+
148+
Expected:
149+
150+
- Payment can be made to public endpoints if product accepts paying non-contacts.
151+
- User is not forced to save contact unless required by design.
152+
- If contact is not saved, Contacts list remains unchanged after payment.
153+
- Add Contact copy matches design, especially wording around public vs private payments.
154+
155+
### T5. QR scanner Pubky route
156+
157+
1. Display or generate Wallet B Pubky QR.
158+
2. On Wallet A, open scanner from Send or global scan.
159+
3. Scan Wallet B pubky.
160+
161+
Expected:
162+
163+
- If Wallet B is saved, app opens Wallet B contact detail.
164+
- If Wallet B is not saved, app opens Add Contact / payment-capable Pubky flow.
165+
- Payment from the routed screen succeeds and is tagged only when a contact relationship exists or when product intentionally tags public Pubky payments.
166+
167+
### T6. Send flow manual/paste Pubky route
168+
169+
1. On Wallet A, open Send.
170+
2. Choose manual recipient entry.
171+
3. Paste Wallet B pubky.
172+
4. Continue.
173+
174+
Expected:
175+
176+
- Saved contact routes to Contact Detail/payment flow.
177+
- Non-saved pubky routes to Add Contact/payment flow.
178+
- Own pubky routes to own profile or shows self-add/self-pay guard, according to product decision.
179+
- Invalid pubky remains blocked with clear validation.
180+
181+
### T7. Recipient without public endpoints
182+
183+
1. Use a Pubky profile with Pay Contacts disabled or no endpoints.
184+
2. Try payment from Contact Detail, Add Contact, QR scanner, and Send/manual.
185+
186+
Expected:
187+
188+
- No crash or stuck loading.
189+
- Clear message that payment methods are unavailable.
190+
- Contact can still be added/viewed if profile exists.
191+
192+
### T8. Endpoint lifecycle
193+
194+
1. Wallet B enables Pay Contacts.
195+
2. Wallet A confirms payment methods are available for Wallet B.
196+
3. Wallet B disables Pay Contacts.
197+
4. Wallet A refreshes contact/profile or restarts app.
198+
5. Try payment again.
199+
200+
Expected:
201+
202+
- Disabled endpoints stop being offered after refresh/reload.
203+
- Re-enabling endpoints makes payment available again.
204+
- No stale invoice/address is used after disable.
205+
206+
### T9. Existing wallet upgrade path
207+
208+
1. Use an existing wallet/profile created before public Paykit endpoints existed.
209+
2. Enable Pay Contacts.
210+
3. Try receiving public contact payments.
211+
4. Add Lightning channel after profile already exists.
212+
5. Refresh/restart.
213+
6. Try Lightning contact payment.
214+
215+
Expected:
216+
217+
- Existing profile can publish endpoints after upgrade.
218+
- On-chain works before Lightning is ready.
219+
- Lightning endpoint appears after channel/spending balance is available.
220+
221+
## Activity Checks
222+
223+
For each successful payment type:
224+
225+
1. Check Home activity row.
226+
2. Open full Activity list.
227+
3. Open Contact Activity from contact detail.
228+
4. Open payment detail.
229+
230+
Expected:
231+
232+
- Sent public contact payments show contact-aware title where supported.
233+
- Contact Activity contains the matching sent payment.
234+
- Received public payments may not show `Received from {name}` if sender identity is not known for public payments; confirm copy/product expectation.
235+
- Replaced/boosted transactions do not appear as duplicate stale entries in Contact Activity.
236+
- Pending → success, pending → failure, and retry flows keep or clear contact context correctly.
237+
238+
## Boost / Replacement Checks
239+
240+
### B1. RBF on contact on-chain send
241+
242+
1. Create a low-fee on-chain payment to a contact.
243+
2. Before confirmation, open activity details.
244+
3. Use RBF boost.
245+
4. Confirm boosted transaction.
246+
247+
Expected:
248+
249+
- Boost succeeds.
250+
- Main Activity shows boosted/replaced state correctly.
251+
- Contact Activity shows the final/relevant payment only.
252+
- Contact context remains attached after replacement.
253+
254+
### B2. CPFP involving contact payment
255+
256+
1. Create an unconfirmed incoming or outgoing transaction that allows CPFP.
257+
2. Use CPFP boost from activity details.
258+
3. Confirm boosted transaction.
259+
260+
Expected:
261+
262+
- Boost succeeds.
263+
- Contact-related activity does not duplicate or lose context.
264+
- Parent/child transaction details remain understandable.
265+
266+
### B3. Failed/pending contact payment context
267+
268+
1. Start a contact payment likely to go pending or fail.
269+
2. Without closing the send sheet, retry or start a different payment to a normal address/invoice.
270+
271+
Expected:
272+
273+
- Stale contact context is cleared or moved correctly.
274+
- The unrelated payment is not tagged to the previous contact.
275+
276+
## Negative / Edge Cases
277+
278+
- Recipient pubky has malformed endpoint document.
279+
- Endpoint document has only on-chain endpoint.
280+
- Endpoint document has only Lightning endpoint.
281+
- Lightning invoice generation fails.
282+
- On-chain address is unavailable.
283+
- Endpoint fetch times out or is offline.
284+
- Wallet has no on-chain balance.
285+
- Wallet has no spending balance.
286+
- User disables Pay Contacts while another wallet has the contact detail screen open.
287+
- Contact is deleted after a payment; historical activity remains readable.
288+
- Contact is renamed locally after payment; activity title uses the expected current or historical name per product decision.
289+
- Wallet reset/sign-out removes published endpoints best-effort and never blocks local wipe.
290+
291+
## Suggested Future E2E Coverage
292+
293+
Start small and keep these behind a Pubky/contact-payments tag until stable.
294+
295+
1. **Public contact on-chain payment happy path**
296+
- Wallet A funded, Wallet B profile with Pay Contacts enabled.
297+
- Add Wallet B as contact.
298+
- Pay Wallet B on-chain from Contact Detail.
299+
- Verify send success and contact activity row.
300+
301+
2. **Public contact Lightning payment happy path**
302+
- Same setup, with Wallet A spending balance.
303+
- Pay Wallet B via Lightning from Contact Detail.
304+
- Verify send success and contact activity row.
305+
306+
3. **Pubky routing from Send/manual**
307+
- Paste saved contact pubky → opens existing contact payment route.
308+
- Paste unknown pubky → opens Add Contact/payment route.
309+
- Invalid/self pubky remains blocked.
310+
311+
4. **Endpoint disabled**
312+
- Recipient disables Pay Contacts.
313+
- Sender refreshes and sees payment unavailable.
314+
315+
5. **RBF contact payment**
316+
- Create on-chain contact payment.
317+
- Boost with RBF.
318+
- Verify final activity state and contact activity do not show stale duplicate replacement rows.
319+
320+
6. **Contact context isolation**
321+
- Start contact payment, force pending/failure if possible.
322+
- Send unrelated payment.
323+
- Verify unrelated activity is not tagged to the contact.
324+
325+
## Notes / Known Product Questions
326+
327+
- Public contact payments are not private payments. If copy says both users must add each other to pay privately, verify whether public-payment behavior needs separate copy.
328+
- If Send/Pay is shown on Add Contact before saving, confirm design/product acceptance.
329+
- For public incoming payments, sender identity may not be knowable; do not expect `Received from {name}` unless private payment metadata exists.
330+
- Mainnet demo testing should wait until mainnet Pubky profile creation and Paykit endpoint publishing are available and stable.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"e2e:android": "PLATFORM=android wdio run ./wdio.conf.ts",
66
"e2e:ios": "PLATFORM=ios wdio run ./wdio.conf.ts",
77
"lint": "eslint './**/*.{ts,js}'",
8-
"format": "prettier --write './**/*.{ts,js,json,md}'"
8+
"format": "prettier --write './**/*.{ts,js,json}' '!./docker/**'"
99
},
1010
"keywords": [],
1111
"author": "",

scripts/adb-reverse.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
for d in $(adb devices | awk 'NR>1 && $2=="device" {print $1}'); do
4+
echo "Setting reverse ports for $d"
5+
6+
adb -s "$d" reverse tcp:60001 tcp:60001
7+
adb -s "$d" reverse tcp:9735 tcp:9735
8+
adb -s "$d" reverse tcp:30001 tcp:30001
9+
adb -s "$d" reverse tcp:6288 tcp:6288
10+
done
11+
12+
echo "Done."

0 commit comments

Comments
 (0)