refactor(billing): require wallet address in public wallet API responses - #3521
refactor(billing): require wallet address in public wallet API responses#3521baktun14 wants to merge 14 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughWallet initialization now guarantees initialized public wallet data, deployment provisioning handles orphan cleanup and idempotent close behavior, frontend hooks accept wallet presence independently of address presence, usage dates are materialized during parsing, and API schemas reflect updated wallet, trial, and idempotency contracts. ChangesWallet initialization and provisioning contracts
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3521 +/- ##
==========================================
- Coverage 76.33% 75.53% -0.80%
==========================================
Files 1134 1044 -90
Lines 29598 27247 -2351
Branches 7352 6898 -454
==========================================
- Hits 22593 20581 -2012
+ Misses 6174 5864 -310
+ Partials 831 802 -29
*This pull request uses carry forward flags. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
apps/api/src/billing/services/wallet-initializer/wallet-initializer.service.ts (1)
6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse type-only imports for wallet aliases.
UserWalletOutput,UserWalletPublicOutput, andWalletInitializedare type-only symbols, whileUserWalletRepositoryis a runtime dependency. Split or annotate these imports to satisfy the shared TypeScript import rule and avoid runtime import issues.
apps/api/src/billing/services/wallet-initializer/wallet-initializer.service.ts#L6-L6: mark the wallet aliases as type-only while keepingUserWalletRepositoryas a value import.apps/api/src/billing/services/wallet-reader/wallet-reader.service.ts#L6-L6: apply the same type-only import treatment.As per coding guidelines, TypeScript imports must use consistent type imports.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/api/src/billing/services/wallet-initializer/wallet-initializer.service.ts` at line 6, Update the imports in apps/api/src/billing/services/wallet-initializer/wallet-initializer.service.ts#L6-L6 and apps/api/src/billing/services/wallet-reader/wallet-reader.service.ts#L6-L6 so UserWalletOutput, UserWalletPublicOutput, and WalletInitialized use type-only imports, while UserWalletRepository remains a runtime import.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@apps/api/src/billing/services/wallet-initializer/wallet-initializer.service.ts`:
- Around line 87-94: Update `#ensureWalletVia` to perform the wallet address
mutation through the authorization-scoped repository argument by replacing
this.userWalletRepository.updateById with repository.updateById, while
preserving the existing update parameters and returned wallet behavior.
In `@apps/api/src/billing/services/wallet-reader/wallet-reader.service.ts`:
- Around line 22-24: Update the wallet filter in the wallet-reader mapping flow
to validate that address is present and non-empty before asserting
WalletInitialized; reject undefined, null, and empty or whitespace-only values
while preserving the activatedAt requirement and existing toPublic mapping.
In
`@apps/api/src/deployment/services/deployment-reader/deployment-reader.service.ts`:
- Around line 19-20: Change the WalletInitialized import in the deployment
reader service to a type-only import, while keeping WalletReaderService as a
regular import.
In `@apps/api/swagger/openapi.json`:
- Line 1790: Remove the generated static default value for dynamic endDate at
apps/api/swagger/openapi.json lines 1790-1790 and 1916-1916, omitting the
default property entirely at both sites so the OpenAPI schema does not contain a
date that becomes stale.
- Line 5: Update the OpenAPI server URL in the generator configuration to the
intended public API URL instead of localhost, then regenerate the specification
so Swagger UI and generated clients use the deployed server.
---
Nitpick comments:
In
`@apps/api/src/billing/services/wallet-initializer/wallet-initializer.service.ts`:
- Line 6: Update the imports in
apps/api/src/billing/services/wallet-initializer/wallet-initializer.service.ts#L6-L6
and apps/api/src/billing/services/wallet-reader/wallet-reader.service.ts#L6-L6
so UserWalletOutput, UserWalletPublicOutput, and WalletInitialized use type-only
imports, while UserWalletRepository remains a runtime import.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: cee7dad8-2ed7-4893-a71b-d7722cb62820
⛔ Files ignored due to path filters (1)
apps/api/test/functional/__snapshots__/docs.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (17)
apps/api/src/billing/http-schemas/wallet.schema.tsapps/api/src/billing/repositories/user-wallet/user-wallet.repository.tsapps/api/src/billing/services/refill/refill.service.spec.tsapps/api/src/billing/services/wallet-initializer/wallet-initializer.service.tsapps/api/src/billing/services/wallet-reader/wallet-reader.service.tsapps/api/src/deployment/services/deployment-reader/deployment-reader.service.spec.tsapps/api/src/deployment/services/deployment-reader/deployment-reader.service.tsapps/api/src/deployment/services/deployment-writer/deployment-writer.service.spec.tsapps/api/src/deployment/services/deployment-writer/deployment-writer.service.tsapps/api/src/deployment/services/lease/lease.service.spec.tsapps/api/swagger/openapi.jsonapps/api/test/seeders/user-wallet.seeder.tsapps/deploy-web/src/hooks/useEnsureTrialStarted.spec.tsapps/deploy-web/src/hooks/useEnsureTrialStarted.tsapps/deploy-web/src/hooks/useManagedWallet.spec.tsxapps/deploy-web/src/hooks/useManagedWallet.tspackages/console-api-types/src/schema.d.ts
💤 Files with no reviewable changes (1)
- apps/deploy-web/src/hooks/useEnsureTrialStarted.spec.ts
- merge duplicated @src/billing/repositories import in deployment-writer - flatten managed-wallet storage-sync effect to an early return + ternary - revert accidental openapi regeneration artifacts (localhost server url, today's date defaults, dropped trailing newline)
… guard Addresses review feedback on the wallet-address contract: - #ensureWalletVia now mutates through the CASL-scoped `repository` argument instead of the unscoped `this.userWalletRepository`, so the get/check/mutate sequence stays authorization-scoped during trial init. - getWallets filters activated wallets with a truthiness check on `address` so an empty-string address is also excluded and the `WalletInitialized` predicate holds. - Use type-only imports for the wallet type aliases and WalletInitialized.
…enAPI spec The usage-history query schema defaulted `endDate` with `.default(() => new Date()...)`. The OpenAPI generator evaluates that at generation time and freezes a static date into the spec, which then goes stale and misleads generated clients into sending an old default date. Move the "default to today" logic into the schema transform (next to the existing startDate-from-endDate derivation) so runtime behavior is unchanged but the generated spec no longer carries a static default. Regenerate openapi.json, update the docs snapshot, and drop the now-redundant non-null assertions in the router and refine.
9d75988 to
9e439e5
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/api/swagger/openapi.json (1)
2061-2069: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winRegenerate the client types for
isNewUser.This response now requires top-level
isNewUser, butpackages/console-api-types/src/schema.d.tsstill types/v1/register-useras containing onlydata. Consumers cannot access the required result without a cast.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/api/swagger/openapi.json` around lines 2061 - 2069, Regenerate the client types so the /v1/register-user response includes the required top-level isNewUser boolean alongside data. Update the generated schema definition in packages/console-api-types, preserving the required-property contract reflected by the OpenAPI response.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/api/src/billing/http-schemas/usage.schema.ts`:
- Around line 27-30: Update the startDate calculation in the schema’s date-range
logic to perform subtraction in UTC, replacing local getDate/setDate usage with
getUTCDate/setUTCDate or equivalent UTC millisecond arithmetic. Preserve the
existing 30-day offset and YYYY-MM-DD serialization for startDate and endDate.
---
Outside diff comments:
In `@apps/api/swagger/openapi.json`:
- Around line 2061-2069: Regenerate the client types so the /v1/register-user
response includes the required top-level isNewUser boolean alongside data.
Update the generated schema definition in packages/console-api-types, preserving
the required-property contract reflected by the OpenAPI response.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e5a334dc-c929-4816-af90-52af13d9f2cf
⛔ Files ignored due to path filters (1)
apps/api/test/functional/__snapshots__/docs.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (19)
apps/api/src/billing/http-schemas/usage.schema.tsapps/api/src/billing/http-schemas/wallet.schema.tsapps/api/src/billing/repositories/user-wallet/user-wallet.repository.tsapps/api/src/billing/routes/usage/usage.router.tsapps/api/src/billing/services/refill/refill.service.spec.tsapps/api/src/billing/services/wallet-initializer/wallet-initializer.service.tsapps/api/src/billing/services/wallet-reader/wallet-reader.service.tsapps/api/src/deployment/services/deployment-reader/deployment-reader.service.spec.tsapps/api/src/deployment/services/deployment-reader/deployment-reader.service.tsapps/api/src/deployment/services/deployment-writer/deployment-writer.service.spec.tsapps/api/src/deployment/services/deployment-writer/deployment-writer.service.tsapps/api/src/deployment/services/lease/lease.service.spec.tsapps/api/swagger/openapi.jsonapps/api/test/seeders/user-wallet.seeder.tsapps/deploy-web/src/hooks/useEnsureTrialStarted.spec.tsapps/deploy-web/src/hooks/useEnsureTrialStarted.tsapps/deploy-web/src/hooks/useManagedWallet.spec.tsxapps/deploy-web/src/hooks/useManagedWallet.tspackages/console-api-types/src/schema.d.ts
💤 Files with no reviewable changes (1)
- apps/deploy-web/src/hooks/useEnsureTrialStarted.spec.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/api/src/deployment/services/deployment-reader/deployment-reader.service.ts
- apps/api/src/billing/routes/usage/usage.router.ts
- apps/api/src/deployment/services/lease/lease.service.spec.ts
- apps/api/src/deployment/services/deployment-reader/deployment-reader.service.spec.ts
There was a problem hiding this comment.
LGTM — the wallet-address non-null contract change is well-supported by the CON-744 invariants, and all prior CodeRabbit findings (CASL-scoped update, address type predicate, type-only import, localhost server URL, stale OpenAPI date default) were addressed in follow-up commits with clear author explanations in the thread.
Extended reasoning...
Overview
This PR tightens the public wallet API contract (id, userId, address, createdAt) from nullable to required, now that upstream work (CON-744, already deployed) guarantees every wallet returned by GET /v1/wallets and POST /v1/start-trial has a derived address. It introduces a WalletInitialized type in the repository layer, threads it through WalletInitializerService, WalletReaderService, and toPublic, drops the now-impossible null-address handling in deploy-web's useManagedWallet/useEnsureTrialStarted, and regenerates the OpenAPI spec/snapshot/typed client. It also folds in an unrelated but small fix to usage.schema.ts making endDate's today-default computed in the transform instead of frozen via Zod .default(), avoiding stale dates baked into the generated spec.
Security risks
None identified. No auth/permission logic changes — the CASL-scoped repository boundary in #ensureWalletVia is preserved (CodeRabbit flagged a regression here and it was fixed to use repository.updateById instead of the unscoped this.userWalletRepository). The wallet-reader filter now correctly type-guards on both activatedAt and a truthy address before narrowing to WalletInitialized.
Level of scrutiny
Medium — this is a contract-tightening refactor in billing/wallet code (sensitive but not touching auth/crypto directly), proven mostly at compile time via TypeScript narrowing rather than new runtime asserts. The response schemas are docs-only (no response-validation middleware is wired into createRoute/OpenApiHonoHandler), so the nullability changes can't cause new runtime rejections — verified this directly in create-route.ts.
Other factors
The PR thread shows thorough back-and-forth: CodeRabbit raised 5 concerns, all addressed in commit 4adc9f9/aaf18a7, plus one date-default issue the author initially deferred and then reversed course on and fixed in-PR (9d75988) with a clear rationale. Test coverage is strong (new seeder, updated specs across wallet-initializer, wallet-reader, deployment-reader/writer, lease, and the two deploy-web hooks), and Codecov reports full coverage of changed lines with no failing tests.
new Date("YYYY-MM-DD") parses at UTC midnight, but getDate()/setDate()
operate in the process timezone, so the 30-day default window could land
one day early across a DST boundary in non-UTC deployments (e.g. endDate
2024-11-15 yielded 2024-10-15 under America/New_York instead of 2024-10-16).
Compute the offset with getUTCDate()/setUTCDate() so the derived startDate
is timezone-independent, and add usage.schema specs covering the window
derivation, boundary crossing, and timezone regression.
|
Re: CodeRabbit's outside-diff comment on Declining as out of scope for this PR, with evidence:
Tracking separately as a dedicated typed-client regeneration (canonical tooling version), same as the earlier pre-existing |
There was a problem hiding this comment.
I didn't find any bugs in the current state of this PR, but given it changes the wallet address nullability contract across the public billing API (schemas, repository, and both wallet-initialization/read services) and touches CASL-authorization-scoped wallet mutation code, I think it's worth a final human look before merging.
What was reviewed:
- The narrowing of
UserWalletOutput->WalletInitializedand its propagation throughtoPublic,WalletReaderService.getWallets, andWalletInitializerService#ensureWalletVia" — the CASL-scoped-repository mutation issue flagged earlier in review is fixed (mutates via the passed-inrepository`, not the singleton). - The address-presence filter in
getWallets(activatedAt !== null && !!wallet.address) correctly excludes any legacy addressless-but-activated row instead of emitting invalid data. - The usage-history
startDateUTC arithmetic fix and its new regression test (DST boundary case) look correct.
Extended reasoning...
Overview
This PR tightens the public wallet API contract so id, userId, address, and createdAt are non-nullable, backed by a new WalletInitialized type-predicate narrowing threaded through UserWalletRepository.toPublic, WalletReaderService, and WalletInitializerService. It also updates generated OpenAPI artifacts, deploy-web hooks (useManagedWallet, useEnsureTrialStarted) to drop null-address tolerance, and separately fixes a UTC-vs-local-timezone bug in the usage-history startDate derivation (with a DST-boundary regression test added the same day).
Security risks
The main risk surface is the wallet-mutation path in WalletInitializerService#ensureWalletVia, which reads through a CASL-authorization-scoped repository but originally mutated through the unscoped singleton — a real authorization-scoping gap flagged by CodeRabbit and fixed in-PR (now mutates via the scoped repository argument). No other injection/auth-bypass/data-exposure patterns stood out; response schemas here are compile-time/docs-only, not runtime validators.
Level of scrutiny
This warrants more than a rubber-stamp: it touches billing/wallet code (financial correctness and authorization scoping), is tagged size M, and changes a public API contract (nullability) consumed by generated client types and deploy-web. The bug-hunting pass found nothing outstanding, and the PR has already been through several rounds of substantive CodeRabbit findings that were all fixed and tested (CASL scoping, address-predicate validation, localhost server URL, stale OpenAPI defaults, UTC date arithmetic), which reduces residual risk but doesn't eliminate the value of a human sign-off given the domain.
Other factors
Test coverage is strong: new/updated specs cover the tightened wallet-initialization contract, the usage-history date derivation (including a TZ-specific DST regression test), and the frontend hooks' updated readiness semantics. Coverage tooling (Codecov) reports all modified/coverable lines covered. All prior CodeRabbit review threads on this PR are marked resolved/addressed by the author.
Reconcile #3542 (background-job trial activation) with this PR's wallet-address contract: - initializeAndGrantTrialLimits keeps main's background-job flow (no start-trial endpoint, no claimActivation/409, activatedAt folded into the grant, activation instrumentation) while ensureWallet still returns WalletInitialized and toPublic still requires it. The final toPublic narrows via { ...activatedWallet, address: userWallet.address }. - useEnsureTrialStarted / its spec: take main's server-side, readiness-only hook, which supersedes this PR's client-start tweak. The address guarantee is preserved by main's !!wallet?.address under the now-non-null contract. - Dropped the now-unused UserWalletOutput import from the service. - Regenerated openapi.json, @akashnetwork/console-api-types, and the docs snapshot from the merged source.
Resolve reviewer questions on the wallet-address refactor:
- Add an isWalletInitialized type guard next to WalletInitialized and use
it in WalletInitializerService.ensureWallet and WalletReaderService
.getWallets, replacing the { ...wallet, address: wallet.address } spread
that read as a no-op. That spread existed only to re-apply the narrowed
string type over the nullable field the object spread reintroduces.
- Inline #ensureWalletVia into ensureWallet: merging #3542 removed the
second, CASL-scoped caller, leaving a single caller that always passed
the plain repository, so the indirection no longer earned its keep.
- Drop returning: true on the address update. The returned row was
reconstructed as { ...wallet, address } regardless, so echoing the row
back from the DB was redundant; no consumer reads the other columns.
- Update the two specs that asserted returning: true on the address update.
A regeneration ran the generator with the default SERVER_ORIGIN (localhost:3080) and overwrote the sandbox URL that origin/main ships, making Swagger UI and generated clients target the caller's machine. Restore servers[0].url to https://console-api-sandbox.akash.network.
…ire-wallet-address-in-api # Conflicts: # apps/api/swagger/openapi.json
There was a problem hiding this comment.
This automated re-review found no new bugs. Given this PR changes security-sensitive wallet/billing code (CASL-scoped repository access, address-derivation invariants) and has already gone through several substantive fix rounds (CASL-scoped mutation, empty-string address validation, an accidental localhost server URL in the generated spec), a human look is still worthwhile before merge, especially since one nit-level review comment (type-only import in deployment-writer.service.ts) is still unaddressed.
Extended reasoning...
This run of the bug hunting system found no new issues in apps/api/src/billing (wallet schema, repository, wallet-initializer/wallet-reader services) or the deploy-web useManagedWallet changes. A previously-raised candidate issue (ensureWallet returning stale non-address fields) was examined and refuted this run.
Overview
The PR tightens the public wallet API contract so address/id/userId/createdAt are non-nullable, removing null-tolerant handling in deploy-web (useManagedWallet) and adding a narrowing WalletInitialized type plus an isWalletInitialized guard used across wallet-reader, wallet-initializer, and deployment reader/writer services. It also regenerates the OpenAPI spec/types and fixes an unrelated timezone bug in the usage-history date derivation.
Security risks
The core risk surface is authorization scoping around wallet mutations (CASL-scoped repository access) and the address-initialization invariant (an uninitialized/empty address must never reach the public API or be treated as usable). Both were flagged during review (by CodeRabbit and this bot) and fixed in-branch; no new authorization or address-validation issues surfaced this run.
Level of scrutiny
This warrants more than mechanical-change scrutiny: it touches billing/wallet code paths, changes a public API contract (nullability), and has already required several correction rounds during review (CASL scoping, address validation regression, a leaked localhost server URL in generated docs). That history, not any current unresolved bug, is why a human pass is still appropriate.
Other factors
Test coverage for the changed invariants (empty-string address, UTC date derivation, wallet initialization) was added alongside the fixes. One outstanding nit-level comment (type-only import in deployment-writer.service.ts) has not yet been addressed by the author, though it mirrors an already-accepted pattern elsewhere on main and is not functionally significant.
There was a problem hiding this comment.
I reviewed this PR and didn't find any new bugs in this pass. Because it's a large change touching billing wallet initialization/activation and several deployment services, a human look would still be worthwhile.
What was reviewed: the isWalletInitialized/WalletInitialized narrowing now shared across user-wallet.repository, wallet-reader, and wallet-initializer; the OpenAPI schema change making id/userId/address/createdAt non-nullable plus the regenerated swagger.json, docs snapshot, and console-api-types; and the deploy-web useManagedWallet hook reverting the null-address storage guard.
Extended reasoning...
Overview
The PR tightens the public wallet API contract so id, userId, address, and createdAt are required (non-nullable) instead of nullable, backed by a new WalletInitialized/isWalletInitialized type-predicate shared between UserWalletRepository, WalletReaderService, and WalletInitializerService. It also regenerates the OpenAPI artifacts (swagger.json, docs snapshot, console-api-types) and, in deploy-web, reverts a temporary null-address tolerance in useManagedWallet that a prior PR (CON-744) had introduced as a bridge.
Security risks
No new attack surface is introduced. The main risk class here is a logic regression that could let an uninitialized wallet (null or empty-string address) leak through the public API or bypass the trial-activation gate — this is exactly the class of bug that surfaced and was fixed twice during this PR's review cycle (the isWalletInitialized guard was briefly weakened to !== null during a refactor, allowing empty-string addresses through, then re-hardened to !!wallet.address in commit 6ca8e9e with new empty-string test coverage in both getWallets and ensureWallet).
Level of scrutiny
This warrants a human look rather than shadow-approval. It's a size-L PR touching billing wallet initialization and activation, which gates real financial/deployment allowances, and it has already been through several rounds of substantive back-and-forth — CodeRabbit, a human reviewer, and this bug-hunting system all found and the author fixed real issues (the empty-string address bypass, a no-op returning: true round-trip, and a regenerated openapi.json that briefly shipped a localhost server URL). That density of real findings on billing-adjacent code is a signal for continued human attention even though this pass found nothing new.
Other factors
The author has been responsive and precise in addressing every substantive finding with focused commits and added test coverage (e.g. the empty-string wallet tests in wallet-reader.service.spec.ts and wallet-initializer.service.spec.ts). One low-severity nit from a prior pass (a redundant { ...activatedWallet, address: userWallet.address } spread in wallet-initializer.service.ts:71, functionally inert but stylistically inconsistent with the sibling ensureWallet fix) remains open but is not a correctness concern.
Why
Closes CON-745
CON-744 (#3512, #3513, deployed) guarantees that every wallet returned by the public API has an address:
GET /v1/walletsonly returns activated wallets (activation happens strictly after address derivation), andPOST /v1/start-trialresponds only after the address is derived. The loosenullablecontract now only hides bugs and forces null-tolerant handling in API consumers.What
apps/api — declare
address(plusid,userId,createdAt, which are DB-non-null already) as required in the wallet response schema:WalletOutputSchema: drop.nullable()on the four fields;createdAtswitchesz.coerce.date()→z.date()because coercion makes the OpenAPI generator'sisNullable()probe succeed onnull(new Date(null)is valid), which kept a phantomnullable: truein the spec. Response schemas are compile-time/docs only — nothing parses them at runtime.toPublicnow requiresWalletInitialized(moved to the repository fromwallet-reader.service.ts),WalletReaderService.getWalletsfilters with a type predicate (which also silently excludes any pathological activated-but-addressless legacy row instead of 500ing), andWalletInitializerService.#ensureWalletViareturns the narrowed type its JSDoc already promised.createInitializedUserWalletseeder for fixtures that mock the narrowed contract.Generated artifacts — docs snapshot,
swagger/openapi.json, and@akashnetwork/console-api-typesregenerated. Note: the checked-in spec was stale (predates #3513 and the idempotent top-up work), so the regen also drops the long-removed202from/v1/start-trial, adds its409, and picks upidempotencyKeyon checkout — incidental drift, not introduced by this PR.apps/deploy-web — drop the null-address tolerance that CON-744 shipped as a temporary bridge:
useManagedWalletand remove its now-impossible null-address specs.useEnsureTrialStarted:isWalletReadyis now simply "a wallet came back from the API" (!!wallet).Verified end-to-end against a locally booted API: an activated wallet returns a non-null address, a pre-activation wallet is excluded from
GET /v1/wallets, and the served OpenAPI doc marks all four fields required (only the intentionally nullable 3DS fields remain nullable).Summary by CodeRabbit
idempotencyKeysupport for Stripe transaction confirmation requests and for trial start.409response for/v1/start-trialwhen trial provisioning is already in progress./v1/start-trialnow includes anisNewUserfield.id,userId,address, andcreatedAtwhere applicable.endDate/startDate.