Owner: Abimbola
Stack: React Native 0.73+ · TypeScript · React Navigation · Zustand · react-native-nfc-manager · Squad Soft POS SDK (if available) · Reanimated 3
Time: 60 minutes hard stop · Depends on: Nothing
This spike decides everything about Day 4. Run it tonight.
Paste this into Claude Code:
You are verifying that the Squad Soft POS Android SDK works in a sandbox
environment before our team commits to using it in our hackathon demo
(Squad Hackathon 3.0, Challenge 02 — SquadTrust).
HARD TIME LIMIT: 60 minutes. If the SDK is not invoking by then, write up
the blockers and stop. Do not spiral into Android Gradle dependency hell.
We have a documented fallback path (Dynamic VA + QR code) that works
without this SDK — this spike's only job is to tell us which path we take.
CONTEXT YOU MUST KNOW:
1. We have sandbox credentials with confirmed SDK access (per the team).
2. Squad Soft POS is an Android SDK, not a REST API. It uses the phone's
NFC hardware to read contactless cards (or other NFC-enabled phones)
directly — no external card reader.
3. NFC does NOT work on Android emulators. You MUST test on a physical
Android phone with NFC enabled.
4. Common gotchas with payment SDKs on Android:
- minSdkVersion mismatches (Soft POS typically needs API 24+)
- Missing NFC permissions in AndroidManifest.xml
- Missing internet permission
- Hermes/JSC compatibility issues with native modules
- Gradle / Android Gradle Plugin version conflicts
PHASE 1 — DOCS DISCOVERY (max 15 minutes)
Find the Squad Soft POS Android SDK documentation. Search in this order:
1. docs.squadco.com — look for "Soft POS" / "softpos" / "NFC"
2. squadco.com/developers
3. github.com/squadinc (or similar Squad org)
4. The Squad sandbox/merchant dashboard itself
What you need to find:
- SDK installation method (Maven coordinate? .aar file? npm package?)
- Minimum Android SDK version
- Required permissions
- Initialization code (API key setup, merchant ID, environment toggle)
- The function that triggers an NFC payment
- Callback / listener interface for payment results
If after 15 minutes you cannot find clear Android SDK documentation:
- Skip to PHASE 3 (write the help@squadco.com email and stop)
- Do NOT guess at SDK shape or invent API calls
Document everything found in SOFTPOS_SETUP.md as you go.
PHASE 2 — MINIMAL SPIKE PROJECT (max 35 minutes)
If docs were found, create a minimal React Native (TypeScript) project:
npx @react-native-community/cli init softpos_spike --skip-install
cd softpos_spike
npm install
Project must target Android only — do not configure iOS.
Add the Squad Soft POS SDK per the docs. If the SDK is delivered as:
- A Maven dependency: add it to android/app/build.gradle dependencies
- An .aar file: place in android/app/libs/ and add the flatDir + impl line
- An npm package: install it and link if needed
Update android/app/src/main/AndroidManifest.xml to add (whatever the
docs require, typically):
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
Build one screen, App.tsx — a single-file spike, no navigation, no tabs:
Top: "SquadTrust Soft POS Spike"
Middle: A big button "Accept ₦100 Test Payment"
(Tap → invokes the SDK with amount = 10000 Kobo,
transactionReference = `spike_${randomUUID()}`)
Below: A scrollable log view showing every SDK callback and event,
newest first, with timestamps.
Wire the SDK with whatever initialization the docs prescribe. Use hardcoded
constants at the top of App.tsx (clearly labeled `// TODO: move to .env`):
const SQUAD_SANDBOX_KEY = "sandbox_sk_PASTE_HERE";
const SQUAD_MERCHANT_ID = "SBWCKYR7RP";
Tap-button behavior:
- Append "TAP: starting payment, ref=spike_..." to the log
- Invoke the SDK's NFC payment function
- On EVERY callback (NFC_READY, CARD_DETECTED, PROCESSING, SUCCESS,
FAILED, CANCELED): append a log line with the event name and any payload
- On final terminal callback: append "DONE: <verdict>"
- Also `console.log` everything so it shows in `adb logcat -s ReactNativeJS`
Build and run on a physical NFC Android phone:
npx react-native run-android --device
Even an error callback is a SUCCESSFUL spike outcome. The bar tonight is
"the SDK is wired up and responding." We are NOT trying to complete a
real card payment.
PHASE 3 — DOCUMENT EVERYTHING (10 minutes regardless of outcome)
SOFTPOS_SETUP.md must contain:
# Squad Soft POS SDK Spike — Findings
## Outcome
One of:
- ✅ SDK invokes and returns callbacks
- ⚠️ SDK installs but throws on invocation — error: <exact error>
- ❌ SDK could not be installed — blocker: <one line>
- ❌ SDK docs not found — escalate to Squad
## Setup details (if SDK was installed)
- SDK source: <Maven coord / aar URL / npm package>
- SDK version: <exact version>
- minSdkVersion required: <number>
- Permissions added: <list>
- Initialization snippet: <code block>
- Payment invocation snippet: <code block>
## Callbacks observed during test tap
<pasted log output, or "none observed">
## Blockers (if any)
<bulleted list — be specific. "Doesn't work" is not useful.
"ClassNotFoundException: com.squadco.softpos.SDKInitializer when
calling SquadSoftPos.initialize()" IS useful.>
## Recommendation for Day 4
One of:
- GO with SDK path — works as expected
- GO with SDK path WITH ESCALATION — needs Squad to <X> first
- PIVOT to Dynamic VA + QR fallback — SDK path is blocked
If the spike could not proceed, draft (but DO NOT SEND) an email to
help@squadco.com. Save it as ESCALATION_EMAIL.md:
Subject: Soft POS Android SDK access for Squad Hackathon 3.0 team
Hi Squad team,
We are a shortlisted team for Squad Hackathon 3.0 building SquadTrust
for Challenge 02. Our sandbox smoke test passed against
/transaction/initiate and other endpoints. We need to confirm Soft POS
Android SDK access for our hackathon demo.
Specifically we are blocked on:
<bulleted list of the specific blockers from SOFTPOS_SETUP.md>
Our sandbox merchant ID is: SBWCKYR7RP
Submission date: <date>
Could you confirm:
1. Is the Soft POS SDK available in our sandbox environment?
2. If yes, where do we download it and what is the documentation URL?
3. Are there merchant profiling steps we need to complete first?
We have a working fallback (Dynamic Virtual Accounts) but Soft POS is
central to our pitch. Any guidance appreciated.
DO NOT:
- Spend more than 60 minutes total — set a timer
- Try to make a real card payment work tonight — that is Day 4's job
- Add anything beyond the one button + log view
- Try to integrate with our backend API yet — this spike is standalone
- Send the escalation email automatically
DONE WHEN EITHER:
(a) The button tap produces ANY SDK callback (success OR error), AND
SOFTPOS_SETUP.md contains the full installation recipe, OR
(b) You have hit the 60-minute mark with a clear written reason why this
is blocked, AND ESCALATION_EMAIL.md is drafted.
Either outcome is a successful spike. The goal is information, not
working software.
Done when: Either SOFTPOS_SETUP.md confirms SDK is wired up, OR a blockers list is ready to send to help@squadco.com at 9am Day 1. Stop at 60 minutes regardless.
If the SDK is blocked: The fallback flow (Dynamic VA + QR code) built in Prompt 1.3 is your demo path and can be rebranded as "tap-to-pay" on stage — the NFC tag just carries the payment link. Tell the team tonight so Day 1 plans accordingly.
Depends on: Prompt 0.2 (either outcome — the scaffold handles both)
Paste this into Claude Code:
Scaffold the merchant mobile app for SquadTrust. Repo: squadtrust-mobile.
Stack: React Native 0.73+, TypeScript, React Navigation, Zustand for state,
react-native-nfc-manager (fallback path), Squad Soft POS SDK if available.
App structure:
src/
screens/
LoginScreen.tsx — Phone + OTP placeholder
DashboardScreen.tsx — Today's sales, trust score (read-only mirror of web)
AcceptPaymentScreen.tsx — The Soft POS / NFC flow
EscrowSalesScreen.tsx — List of pending/completed escrow transactions
TransactionDetailScreen.tsx
components/
AmountKeypad.tsx — Big touch-friendly Naira keypad
TapAnimation.tsx — Animated "tap your phone here" guidance
services/
api.ts — Backend client
payment.ts — Wraps either Soft POS SDK OR the fallback flow
state/
merchant.ts — Zustand store for logged-in merchant
AcceptPaymentScreen behavior (this is the demo-critical screen):
1. Merchant enters amount on AmountKeypad
2. Taps "Accept Payment"
3. Screen shows "Tap buyer's phone here" with NFC animation
4. Behind the scenes, payment.ts checks if Soft POS SDK is available:
- YES: invoke SDK.startNfcPayment(amount_kobo, transaction_ref)
- NO: hit POST /softpos/initiate on our backend (which creates a Dynamic VA),
show a QR code as fallback, AND start polling /softpos/status/{ref}
5. On success: show green checkmark + receipt screen with merchant copy +
"Send receipt to buyer" button
6. On failure: show red X + retry button with the exact error message
Build the app to support BOTH SDK and fallback modes via a feature flag in
.env (SOFTPOS_MODE=sdk | fallback). Default to fallback so the demo always
works even if the SDK has issues on day-of.
Done when:
- App installs on a physical Android device
- Login → Dashboard → Accept Payment → fake success flow runs end-to-end with
mocked data
- The fallback QR code mode renders a real QR (use react-native-qrcode-svg)
Done when: App installs on physical Android. Full mocked flow runs. Fallback QR renders.
Depends on: 0.2 confirmed SDK access · Backend endpoints from Abideen (coordinate with him on Day 3)
This is the day the real NFC payment flows. Ask Abideen to add the four backend endpoints first (/softpos/initiate, /softpos/confirm, /softpos/fail, GET /softpos) — you'll need them wired before you can test end-to-end.
Paste this into Claude Code:
Wire the Squad Soft POS SDK into the squadtrust-mobile React Native app.
The 0.2 spike confirmed SDK access — now make it production-ready for our demo.
Goals:
1. AcceptPaymentScreen invokes the real Soft POS SDK
2. Backend logs every Soft POS transaction
3. Trust Score recomputes on success
Implementation:
1. src/services/payment.ts:
export async function startSoftPosPayment(
amountKobo: number,
onProgress: (state) => void
): Promise<PaymentResult>
Internally:
- Generate transaction_ref = `spos_${uuid.v4()}`
- Call our backend POST /softpos/initiate to register the pending txn
(returns 200 immediately with transaction_ref)
- Invoke SquadSoftPos.startNfcPayment({
amount: amountKobo,
transactionReference: transaction_ref,
merchantId: currentMerchant.squadMerchantId
})
- Listen to SDK callbacks: NFC_READY, CARD_DETECTED, PROCESSING,
SUCCESS, FAILED — forward each to onProgress for UI animations
- On SUCCESS: call backend POST /softpos/confirm with the SDK's response
- On FAILED: call backend POST /softpos/fail with the error code
- Return: { success: bool, transactionRef, amount, errorMessage? }
2. AcceptPaymentScreen state machine:
IDLE → AMOUNT_ENTRY → TAP_PROMPT → READING_CARD → PROCESSING →
(SUCCESS | FAILED) → RECEIPT
Use Reanimated 3 for smooth transitions. The TAP_PROMPT state must show
a clear visual: pulsing NFC ring + "Tap card or phone here" + amount.
3. Receipt screen:
- Large green checkmark
- "₦{amount} received from {card_last4 or "Buyer"}"
- Timestamp
- Two buttons: "Send SMS receipt" (just log for hackathon) and "Done"
- Auto-return to IDLE after 8 seconds
4. Backend additions (have Abideen add these to squadtrust-api):
POST /softpos/initiate → creates softpos_transactions row, status=pending
POST /softpos/confirm → updates to status=success, sets card_last4, triggers
trust score recompute
POST /softpos/fail → updates to status=failed with error_code
GET /softpos → list merchant's softpos transactions
5. Fallback mode (KEEP IT WORKING — it's the demo safety net):
If SOFTPOS_MODE=fallback or SDK invocation throws, switch to the
Dynamic VA + QR code flow built in 1.3. Both code paths must work; the
demo runner toggles which one is active.
Done when:
- A real NFC payment on a physical Android phone completes end-to-end
- The transaction appears in the web dashboard within 3 seconds
- Trust score updates after a successful Soft POS transaction
- Fallback QR mode still works when SOFTPOS_MODE=fallback is set
Done when: Real NFC tap completes end-to-end. Transaction appears on Fiopefoluwa's web dashboard within 3 seconds. Fallback QR still works.
Polish the README, then make this repo public. The README must tell someone how to build and install the APK in a few commands. Test it yourself on a fresh machine.
SOFTPOS_MODE in your .env controls which payment path runs:
| Value | Behaviour |
|---|---|
fallback |
Dynamic VA + QR code (default — always works, demo-safe) |
sdk |
Squad Soft POS SDK NFC flow (requires physical NFC phone + SDK access) |
Both paths must stay working at all times. The demo operator flips the flag the morning of demo day. Switching must not require a rebuild.
IDLE → AMOUNT_ENTRY → TAP_PROMPT → READING_CARD → PROCESSING → SUCCESS
↘ FAILED
SUCCESS / FAILED → RECEIPT → (auto back to IDLE after 8 seconds)
AmountKeypad captures Naira from the merchant. Convert before any API call:
const amountKobo = Math.round(amountNaira * 100) // always integerNever pass floats to the backend or the SDK.
npm install
npx react-native run-androidRequires a physical Android device — NFC does not work on emulator.
Type check: npx tsc --noEmit
| Variable | Description |
|---|---|
API_BASE_URL |
Backend LAN IP — use http://192.168.x.x:8000, not localhost |
SOFTPOS_MODE |
sdk or fallback — default fallback |