element-x-ada/docs/build-logs/pay-flow-result.md

74 lines
3.5 KiB
Markdown

# /pay Fallback UX Implementation
**Date:** 2026-03-29
**Commit:** `2b93236229` on `phase1-dev`
**APK:** http://192.168.0.5:8888/
## What Was Implemented
### Flow B — Fallback When Recipient Has No Linked Wallet
When a user types `/pay 10` to a recipient who hasn't linked a Cardano wallet:
1. **Address lookup happens in background** - `CardanoAddressService.lookupAddress(@recipient)` is called
2. **Not found → Show banner card** with:
- Warning icon: "⚠️ @recipient hasn't linked a Cardano wallet"
- Instructional text: "Enter their Cardano address manually:"
- Embedded editable text field with placeholder "addr1... or addr_test1..."
3. **Live validation on manual address input**:
- Must start with `addr_test1` (preprod) or `addr1` (mainnet)
- Length between 58-108 characters
- Shows inline error if invalid
- Shows green checkmark "Valid address" when valid
4. **Continue button enables** when:
- Amount is valid (≥1 ADA)
- Manual address passes validation
5. **Resolved address is passed to confirmation screen** - The `PaymentEntryNode` now passes `state.resolvedAddress` (which comes from either the lookup or manual entry) instead of the raw `recipientInput`
## Files Changed
| File | Changes |
|------|---------|
| `PaymentFlowEvents.kt` | Added `ManualAddressChanged(address: String)` event |
| `PaymentEntryState.kt` | Added `manualAddressInput`, `manualAddressError`, `resolvedAddress` fields; added `needsManualAddressEntry` computed property |
| `PaymentEntryPresenter.kt` | Handle `ManualAddressChanged` event; `validateManualAddress()` function; updated `canContinue` logic to work with manual entry |
| `PaymentEntryView.kt` | Added `ManualAddressEntryCard` composable with embedded `OutlinedTextField`; updated preview states |
| `PaymentEntryNode.kt` | Changed to pass `state.resolvedAddress` instead of `state.recipientInput` to confirmation callback |
## Flow A — Happy Path (Already Working)
When recipient HAS a linked wallet:
1. User types `/pay 10`
2. Payment form opens with recipient pre-selected from DM context
3. `CardanoAddressService.lookupAddress(@recipient)` returns the address
4. Green card shows: "✓ Address loaded from @recipient's profile" with truncated address
5. Recipient field shows Matrix user ID (read-only context)
6. Amount field pre-filled with "10"
7. Continue button enabled immediately
8. Confirmation screen shows full transaction details with fee estimate
## Amount Pre-fill
When user types `/pay 10`, the `10` is parsed by `PayCommandParser` and passed via `ParsedPayCommand.AmountOnly` or `ParsedPayCommand.WithMatrixRecipient`. The `PaymentEntryPresenter.extractPrefills()` function extracts this and pre-fills the amount field.
## Address Validation Rules
```kotlin
private fun validateManualAddress(input: String): String? {
// Must start with addr_test1 (preprod) or addr1 (mainnet)
val isTestnet = input.startsWith("addr_test1")
val isMainnet = input.startsWith("addr1") && !input.startsWith("addr_test1")
if (!isTestnet && !isMainnet) return "Address must start with addr1 or addr_test1"
if (input.length < 58) return "Address too short"
if (input.length > 108) return "Address too long"
if (!CARDANO_ADDRESS_REGEX.matches(input)) return "Invalid Cardano address format"
return null
}
```
## Testing Notes
- Build passes with warnings only (no errors)
- All existing tests pass
- Preview states updated to include manual entry scenarios
- APK served on port 8888 for install testing