Skip to content

Add swap service - #173

Open
watersRand wants to merge 5 commits into
Byte-Barn:masterfrom
watersRand:feat/Swap
Open

Add swap service#173
watersRand wants to merge 5 commits into
Byte-Barn:masterfrom
watersRand:feat/Swap

Conversation

@watersRand

Copy link
Copy Markdown
Collaborator

Description

This PR introduces the SIM Swap Detection Service (/imsi/v2/checkATI) to support checking when a subscriber's SIM card was last swapped. This helps detect and mitigate account takeover and fraud risks prior to completing high-value transactions.

Key changes included:

  • Service & Facades: Implemented SwapService and AsyncSwapService with swap_query(customer_number) and swap_request(request) methods.
  • Data Validation & Schemas: Added SwapRequest (with MSISDN auto-normalization) and SwapResponse Pydantic models.
  • Fraud Detection Helpers: Added is_successful and is_recently_swapped properties to SwapResponse to handle Safaricom's sentinel non-swapped date (01-01-1900).
  • Type Stubs & Documentation: Added .pyi type stubs, updated docs/swap.md, and updated landing page status/feature data.

Fixes #160

Type of Change

  • New feature (non-breaking change that adds functionality)
  • This change requires documentation update

How Has This Been Tested?

  • Unit Tests: Added tests covering SwapRequest phone number auto-normalization, SwapResponse.is_recently_swapped sentinel date evaluation (01-01-1900 vs active timestamp), and sync/async service call execution.
  • Ruff & Type Linting: Executed ruff check and type assertions with .pyi stub files to verify clean linting across the package.

Checklist

  • My code follows the project's coding style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings or errors
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Screenshots (if applicable)

N/A (Backend API addition & documentation update)

Additional Context

  • SIM Swap Detection (checkATI) is a paid API product on Safaricom Daraja. Documentation and docstrings reflect onboarding guidance for sandbox and production.

@RafaelJohn9 RafaelJohn9 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @watersRand , thanks for the awesome PR, a few changes to consider 🤝

Comment thread mpesakit/swap/schemas.py
Comment thread mpesakit/swap/swap.py Outdated
Comment thread mpesakit/swap/swap.py Outdated

@RafaelJohn9 RafaelJohn9 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for the late review. you can always tag me for a review, no worries 🤝 ,

Thanks for the changes and we have a few things to do before we become ready to merge.

Then we will be good to go 👍

Comment thread mpesakit/swap/swap.py Outdated

http_client: HttpClient
token_manager: TokenManager
environment: Literal["sandbox", "production"] = "sandbox"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can deprecate the environment parameter that we have across the different swap files, since this is handled by our http client file.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RafaelJohn9 ready

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.

[Feature] Swap

2 participants