Skip to content

Lazy wallet creation #3103

Merged
koutst merged 12 commits intomainfrom
circle-proposal
Feb 18, 2026
Merged

Lazy wallet creation #3103
koutst merged 12 commits intomainfrom
circle-proposal

Conversation

@koutst
Copy link
Contributor

@koutst koutst commented Feb 16, 2026

No description provided.

@koutst koutst requested a review from a team as a code owner February 16, 2026 21:18
@chatgpt-codex-connector
Copy link

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@koutst koutst changed the title Lazy wallet creation on deposit wallet get Lazy wallet creation Feb 16, 2026
Copy link
Member

@gzurowski gzurowski left a comment

Choose a reason for hiding this comment

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

LGTM 👍

return author.author_score

def get_wallet(self, obj):
from purchase.serializers import WalletSerializer
Copy link
Contributor

Choose a reason for hiding this comment

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

Top import?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Circular import

wallet = response.data.wallet.actual_instance

if wallet.state != WalletState.LIVE:
raise CircleWalletNotReadyError(
Copy link
Contributor

Choose a reason for hiding this comment

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

Wonder if we should put exception handling in calling code. Given the name of the function, I'd expect it to return CircleWalletResult and not raise.

return Response(
{
"message": "Wallet is being provisioned. Please retry.",
"retry_after": 3,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the frontend expected to do anything here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, retry after 3 seconds. Is that alright from a front end perspective? For reference https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After

Copy link
Contributor

Choose a reason for hiding this comment

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

Would that be a loop every retry_after seconds that keeps hitting this endpoint until a success?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is something I wanted to test but I just removed it for now and will add back if testing shows it's necessary

wallet, _ = Wallet.objects.select_for_update().get_or_create(user=user)

# Already fully provisioned
if wallet.circle_wallet_id and wallet.address:
Copy link
Contributor

Choose a reason for hiding this comment

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

One thing isn't fully clear to me: How does a wallet go "LIVE" ?

Seems like a wallet can have the following states

  • wallet.circle_wallet_id exists
  • wallet.address exists
  • wallet.state is "LIVE"
  • wallet.state is not "LIVE" (not sure what other states can exist here)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe it just takes time for a wallet to be deployed on Circle's side. So it will go from a pending state to a live state. The only other state I'm aware of is frozen which I think is more relevant to user controlled wallets. This is something that will become more clear when testing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's a chance it's immediately live on response which if that's the case we don't need to worry about retrial

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good

@codecov
Copy link

codecov bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 94.11765% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.44%. Comparing base (b6d717c) to head (ed494e4).
⚠️ Report is 51 commits behind head on main.

Files with missing lines Patch % Lines
src/user/serializers.py 45.45% 6 Missing ⚠️
src/purchase/circle/client.py 95.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3103      +/-   ##
==========================================
+ Coverage   77.36%   77.44%   +0.07%     
==========================================
  Files         581      597      +16     
  Lines       31245    32093     +848     
==========================================
+ Hits        24174    24853     +679     
- Misses       7071     7240     +169     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sonarqubecloud
Copy link

@koutst koutst merged commit 912c3fb into main Feb 18, 2026
5 checks passed
@koutst koutst deleted the circle-proposal branch February 18, 2026 19:07
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.

3 participants

Comments