Skip to content

feat(billing): splits master wallets and consolidates them in a single place#2254

Merged
ygrishajev merged 2 commits intomainfrom
feature/billing-master-wallets
Nov 20, 2025
Merged

feat(billing): splits master wallets and consolidates them in a single place#2254
ygrishajev merged 2 commits intomainfrom
feature/billing-master-wallets

Conversation

@ygrishajev
Copy link
Contributor

@ygrishajev ygrishajev commented Nov 19, 2025

Summary by CodeRabbit

  • Chores

    • Centralized transaction signing behind a new transaction manager to simplify signing and wallet-derivation flows.
  • Configuration

    • Renamed MASTER_WALLET_MNEMONIC → FUNDING_WALLET_MNEMONIC and added DERIVATION_WALLET_MNEMONIC.
    • Added environment settings for billing allowances, Stripe, feature flags, logging formats, analytics, proxy, notifications, and payment link options.
  • Tests

    • Updated tests and mocks for the new signing/derivation flows and switched HTTP request mocking to a new library.

✏️ Tip: You can customize this high-level summary in your review settings.

@ygrishajev ygrishajev requested a review from a team as a code owner November 19, 2025 14:48
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 19, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Replace direct master-wallet and signing-client wiring with a new TxManagerService centralizing funding and derived wallet signing; rename MASTER_WALLET_MNEMONIC → FUNDING_WALLET_MNEMONIC and add DERIVATION_WALLET_MNEMONIC; remove dedupe signing client and ChainErrorService dependency; update DI, method names, providers, and tests accordingly.

Changes

Cohort / File(s) Summary
Env & Config
apps/api/env/.env.unit.test, apps/api/env/.env.sample, apps/api/src/billing/config/env.config.ts
Rename MASTER_WALLET_MNEMONICFUNDING_WALLET_MNEMONIC, add DERIVATION_WALLET_MNEMONIC and many new env keys; update env zod schema to require FUNDING_WALLET_MNEMONIC and DERIVATION_WALLET_MNEMONIC.
Dependencies
apps/api/package.json
Add runtime dependency fetch-mock@^12.6.0.
New Service
apps/api/src/billing/services/tx-manager/tx-manager.service.ts, apps/api/src/billing/services/tx-manager/tx-manager.service.spec.ts
Add TxManagerService exposing funding/derived signing, address retrieval, per-derived-client caching and cleanup; include unit tests.
Batch Signing Client
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts, .../batch-signing-client.service.spec.ts
Remove ChainErrorService dependency; stop converting chain errors to app errors and rethrow original errors; update tests accordingly.
Provider / DI removal
apps/api/src/billing/providers/signing-client.provider.ts, apps/api/src/billing/providers/wallet.provider.ts, apps/api/src/billing/providers/index.ts, apps/api/src/billing/types/wallet.type.ts
Remove managed master wallet/signing-client tokens, Inject helpers, WALLET_FACTORY, and MasterWalletType re-exports; eliminate previous provider wiring.
Removed Service & Export
apps/api/src/billing/services/dedupe-signing-client/dedupe-signing-client.service.ts, apps/api/src/billing/services/index.ts
Delete DedupeSigningClientService and its re-export.
Managed Signer & Call Site Renames
apps/api/src/billing/services/managed-signer/*.ts, *.spec.ts
Replace Batch/Dedupe signing clients with TxManagerService; rename methods (e.g., executeManagedTxexecuteDerivedTx, executeDecodedTxByUserIdexecuteDerivedDecodedTxByUserId) and adapt error handling.
Wallet → TxManager Migration (services & tests)
multiple files under apps/api/src/billing/services/*, apps/api/src/provider/services/*, apps/api/src/deployment/services/*, apps/api/test/**/*, apps/api/test/functional/*
Replace direct Wallet/MASTER provider usage with TxManagerService; use getFundingWalletAddress() / getDerivedWalletAddress() and new signAndBroadcast methods across services and tests; update mocks and constructors.
ProviderJwtToken & WalletFactory removal
apps/api/src/provider/services/provider-jwt-token/*.ts, apps/api/src/billing/lib/wallet/wallet.ts
Replace WalletFactory and BillingConfigService usage with TxManagerService; remove walletFactory and WalletFactory type.
Test infra & mocking
apps/api/test/custom-jest-environment.ts, apps/api/test/setup-global-functional.ts, apps/api/test/services/test-wallet.service.ts, apps/api/test/functional/sign-and-broadcast-tx.spec.ts
Use FUNDING_WALLET_MNEMONIC and DERIVATION_WALLET_MNEMONIC; adapt Wallet constructor calls; switch one test from nock to fetch-mock and update mocks/reset calls.
Minor Projections / Misc
apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts
Reorder select projection fields (walletId position) with no behavior change.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ManagedSigner as ManagedSignerService
    participant TxMgr as TxManagerService
    participant DerivedClient as DerivedSigningClient
    participant FundingClient as FundingSigningClient
    participant Chain

    Client->>ManagedSigner: executeDerivedDecodedTxByUserId(userId, messages)
    ManagedSigner->>TxMgr: getDerivedWalletAddress(index)
    TxMgr-->>ManagedSigner: derivedAddress
    ManagedSigner->>TxMgr: signAndBroadcastWithDerivedWallet(index, messages)
    alt no cached client
        TxMgr->>DerivedClient: create client for derivedAddress
        Note right of DerivedClient `#E6FFEA`: DERIVED_SIGNING_CLIENT_CREATE
        DerivedClient-->>TxMgr: client ready
    end
    DerivedClient->>Chain: signAndBroadcast(messages)
    Chain-->>DerivedClient: txResult
    DerivedClient-->>TxMgr: txResult
    alt no pending txs after result
        Note right of TxMgr `#FFF4E6`: cleanup cached client & log
    end
    TxMgr-->>ManagedSigner: txResult
    ManagedSigner-->>Client: txResult
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–75 minutes

Areas needing extra attention:

  • TxManagerService: client cache lifecycle, concurrency, mnemonic handling, and cleanup semantics.
  • ManagedSignerService: method renames, error translation via chainErrorService, and preservation of lease/balance side effects.
  • Provider/DI removals: ensure no unresolved tokens/registrations remain and tests reflect DI changes.
  • BatchSigningClientService error semantics: consumers/tests that expected converted errors may need updates.
  • Broad test surface: many unit/functional mocks updated — verify functional test fidelity.

Possibly related PRs

Suggested reviewers

  • stalniy
  • baktun14

"🐰 I hopped through code with nimble feet,
Funding and derived now share their beat.
Mnemonics split, the routes align,
TxManager hums — transactions shine.
A carrot-cheer for refactor sweet! 🥕"

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: refactoring wallet architecture by splitting MASTER_WALLET_MNEMONIC into FUNDING_WALLET_MNEMONIC and DERIVATION_WALLET_MNEMONIC, and consolidating wallet management into TxManagerService.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12a1b07 and 10a2d6a.

📒 Files selected for processing (8)
  • apps/api/env/.env.sample (1 hunks)
  • apps/api/src/billing/lib/wallet/wallet.ts (0 hunks)
  • apps/api/src/billing/providers/index.ts (0 hunks)
  • apps/api/src/billing/providers/signing-client.provider.ts (0 hunks)
  • apps/api/src/billing/providers/wallet.provider.ts (0 hunks)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.spec.ts (1 hunks)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.ts (1 hunks)
  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts (2 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

@ygrishajev ygrishajev force-pushed the feature/billing-master-wallets branch from 103de10 to e4b64bf Compare November 19, 2025 14:48
"node": "24.11.1",
"npm": "^11.2.0"
}
},
Copy link
Contributor

@github-actions github-actions bot Nov 19, 2025

Choose a reason for hiding this comment

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

🔄 Carefully review the package-lock.json diff

Resolve the comment if everything is ok

+ node_modules/@types/glob-to-regexp                                                       0.4.4   
+ node_modules/fetch-mock                                                                  12.6.0  
+ node_modules/regexparam                                                                  3.0.0   

@codecov
Copy link

codecov bot commented Nov 19, 2025

❌ 4 Tests Failed:

Tests completed Failed Passed Skipped
1643 4 1639 0
View the top 3 failed test(s) by shortest run time
Managed Wallet API Deployment Flow should maintain read-only operations during blockchain node outages
Stack Traces | 32.6s run time
Error: expect(received).toMatchObject(expected)

Matcher error: received value must be a non-null object

Received has value: undefined
    at Object.<anonymous> (.../test/functional/managed-api-deployment-flow.spec.ts:201:21)
    at processTicksAndRejections (node:internal/process/task_queues:103:5)
Managed Wallet API Deployment Flow should execute a full deployment cycle with provider JWT auth
Stack Traces | 38.9s run time
Error: expect(received).toMatchObject(expected)

Matcher error: received value must be a non-null object

Received has value: undefined
    at .../test/functional/managed-api-deployment-flow.spec.ts:82:21
    at processTicksAndRejections (node:internal/process/task_queues:103:5)
Users stale anonymous users cleanup should remove anonymous users inactive for defined period
Stack Traces | 46.4s run time
Error: expect(received).toHaveLength(expected)

Expected length: 4
Received length: 1
Received array:  [{"bio": null, "createdAt": 2025-11-20T10:45:57.301Z, "email": null, "emailVerified": false, "githubUsername": null, "id": "822e3a98-8b0e-449e-9565-7aa9cc39f605", "lastActiveAt": 2025-08-21T10:46:10.698Z, "lastFingerprint": null, "lastIp": null, "lastUserAgent": null, "stripeCustomerId": null, "subscribedToNewsletter": false, "twitterUsername": null, "userId": null, "username": null, "youtubeUsername": null}]
    at Object.<anonymous> (.../test/functional/stale-anonymous-users-cleanup.spec.ts:57:21)
    at processTicksAndRejections (node:internal/process/task_queues:103:5)
Managed Wallet API Deployment Flow should execute a full deployment cycle with provider mTLS auth
Stack Traces | 57.9s run time
Error: expect(received).toMatchObject(expected)

Matcher error: received value must be a non-null object

Received has value: undefined
    at .../test/functional/managed-api-deployment-flow.spec.ts:82:21
    at processTicksAndRejections (node:internal/process/task_queues:103:5)

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (9)
apps/api/env/.env.unit.test (1)

3-4: Unit-test env updated correctly; dotenv key-order warning is purely cosmetic

The new FUNDING_WALLET_MNEMONIC and DERIVATION_WALLET_MNEMONIC entries line up with the updated envSchema, so unit tests should parse config fine.

The dotenv‑linter “UnorderedKey” warnings are non-functional; if you want a clean lint run you can reorder these two lines as suggested, but there’s no behavioral impact either way.

apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (1)

34-137: TxManager-based funding/derived flows look consistent; a couple of small cleanups

The refactor here reads well:

  • createAndAuthorizeTrialSpending / createWallet now derive addresses via txManagerService.getDerivedWalletAddress(addressIndex), so this service no longer needs direct access to mnemonics or wallet construction.
  • authorizeSpending, authorizeFeeSpending, authorizeDeploymentSpending, and revokeAll consistently use the funding wallet (getFundingWalletAddress) as the granter and execute via managedSignerService.executeFundingTx(...), which matches the new split‑wallet model.

Two minor follow-ups you might consider:

  1. PREFIX and HD_PATH are now unused in this class; if they’re not planned for future use, dropping them will keep the service focused.
  2. In authorizeFeeSpending / revokeAll you check hasFeeAllowance (any allowance) rather than hasValidFeeAllowance. If the intent is specifically “revoke only active / non‑expired allowances before re‑granting”, you may want to switch to the latter; if you do want to revoke even expired ones, current behavior is fine but perhaps worth an inline comment.
apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts (1)

47-47: executeDerivedTx migration in top-up tests is coherent

The setup stub and all expectations now consistently use executeDerivedTx(walletId, msgs), with unchanged payloads and call counts across success, dry-run, empty, and error scenarios, so the behavioral coverage is preserved. If you later align terminology from “master wallet” to “funding wallet” in logs and test descriptions, that’s probably best handled in a focused follow-up issue rather than this PR. Based on learnings

Also applies to: 108-110, 210-210, 237-238, 245-246, 277-278, 379-380, 407-408, 442-443, 464-465

apps/api/src/billing/services/chain-error/chain-error.service.spec.ts (1)

8-8: TxManagerService injection into ChainErrorService tests is sound

The tests now construct ChainErrorService with a mocked TxManagerService, and getFundingWalletAddress is safely stubbed, so existing toAppError scenarios remain valid under the new dependency. If you want stronger coupling to the funding-wallet behavior, you could optionally assert that txManagerService.getFundingWalletAddress is called in the insufficient-funds cases.

Also applies to: 175-179, 183-184, 191-196

apps/api/src/billing/services/financial-stats/financial-stats.service.ts (1)

11-19: Funding-wallet-based implementation of getMasterWalletBalanceUsdc looks correct

Switching getMasterWalletBalanceUsdc to resolve the address via txManagerService.getFundingWalletAddress() and then querying balances through CosmosHttpService keeps behavior intact while removing mnemonic handling from this service. At some point you might want to rename this method to reference the “funding” wallet rather than “master” for clarity, likely in a dedicated follow-up PR. Based on learnings

Also applies to: 25-27

apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (1)

21-23: executeDerivedDecodedTxByUserId tests align well with TxManagerService-based design

The spec now consistently targets executeDerivedDecodedTxByUserId and wires TxManagerService in via a strongly typed mock (signAndBroadcastWithDerivedWallet, getFundingWalletAddress), while preserving all behavioral coverage around allowances, feature flags, domain events, and chain-error handling. The success-path assertion against signAndBroadcastWithDerivedWallet(wallet.id, messages, { fee: { granter: expect.any(String) } }) is especially helpful to lock in the new calling convention.

Two optional nits:

  • Consider importing createAkashAddress via the existing @test/seeders/... alias for consistency with other tests.
  • If you later care about the exact granter value, you could bind the generated funding address to a constant reused both in the getFundingWalletAddress mock and in an expectation.

Also applies to: 29-40, 73-74, 93-94, 120-129, 157-166, 197-207, 242-254, 265-266, 298-308, 334-340, 361-369, 397-406, 434-443, 474-483, 498-503, 530-533, 551-552

apps/api/src/billing/services/balances/balances.service.ts (1)

7-8: BalancesService now correctly resolves grants via TxManagerService funding wallet

Switching both retrieveAndCalcFeeLimit and retrieveDeploymentLimit to use txManagerService.getFundingWalletAddress() keeps all grant lookups aligned with the new funding wallet source of truth and preserves prior logic around fee/deployment allowances. As a small clean-up, you could make txManagerService private readonly in the constructor for consistency with other injected dependencies since it’s never reassigned.

Also applies to: 13-19, 55-75

apps/api/src/billing/services/tx-manager/tx-manager.service.ts (2)

19-28: Validate FUNDING_WALLET_MNEMONIC presence and funding wallet index

Eagerly constructing fundingWallet and fundingSigningClient in field initializers is fine, but it does couple TxManagerService resolution to a valid FUNDING_WALLET_MNEMONIC and the hard‑coded derivation index 1. It would be safer to mirror the explicit guard you already have for DERIVATION_WALLET_MNEMONIC (e.g., throw a clear error if the funding mnemonic is empty) and to double‑check that index 1 indeed matches the on‑chain funding account you provisioned; otherwise funding and grants will silently point at the wrong account.

Also applies to: 31-38, 44-47, 80-87


48-59: Client cache and cleanup logic looks good; consider explicit client disposal on eviction

The per‑address cache with lazy creation in getClient and cleanup in signAndBroadcastWithDerivedWallet when !client.hasPendingTransactions is a solid approach and should avoid unbounded growth. As a non‑blocking improvement, when you delete an entry from clientsByAddress, consider also exposing and calling a lightweight “dispose”/“disconnect” on BatchSigningClientService so any underlying RPC resources are explicitly released rather than relying on GC alone. Given this would affect other callers of the signing client, it’s probably best tracked as a follow‑up issue rather than in this PR. Based on learnings

Also applies to: 65-78

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e58863a and e4b64bf.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (37)
  • apps/api/env/.env.unit.test (1 hunks)
  • apps/api/package.json (1 hunks)
  • apps/api/src/billing/config/env.config.ts (1 hunks)
  • apps/api/src/billing/controllers/wallet/wallet.controller.ts (1 hunks)
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1 hunks)
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (1 hunks)
  • apps/api/src/billing/providers/signing-client.provider.ts (0 hunks)
  • apps/api/src/billing/providers/wallet.provider.ts (1 hunks)
  • apps/api/src/billing/services/balances/balances.service.ts (5 hunks)
  • apps/api/src/billing/services/chain-error/chain-error.service.spec.ts (2 hunks)
  • apps/api/src/billing/services/chain-error/chain-error.service.ts (3 hunks)
  • apps/api/src/billing/services/dedupe-signing-client/dedupe-signing-client.service.ts (0 hunks)
  • apps/api/src/billing/services/financial-stats/financial-stats.service.ts (1 hunks)
  • apps/api/src/billing/services/index.ts (0 hunks)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (20 hunks)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.ts (3 hunks)
  • apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (5 hunks)
  • apps/api/src/billing/services/provider-cleanup/provider-cleanup.service.ts (2 hunks)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.ts (1 hunks)
  • apps/api/src/billing/types/wallet.type.ts (0 hunks)
  • apps/api/src/certificate/services/certificate/certificate.service.spec.ts (4 hunks)
  • apps/api/src/certificate/services/certificate/certificate.service.ts (1 hunks)
  • apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts (1 hunks)
  • apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts (3 hunks)
  • apps/api/src/deployment/services/lease/lease.service.ts (1 hunks)
  • apps/api/src/deployment/services/stale-managed-deployments-cleaner/stale-managed-deployments-cleaner.service.ts (2 hunks)
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts (9 hunks)
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts (1 hunks)
  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts (5 hunks)
  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.ts (3 hunks)
  • apps/api/test/custom-jest-environment.ts (2 hunks)
  • apps/api/test/functional/deployments.spec.ts (4 hunks)
  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts (2 hunks)
  • apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts (3 hunks)
  • apps/api/test/functional/start-trial.spec.ts (2 hunks)
  • apps/api/test/services/test-wallet.service.ts (1 hunks)
  • apps/api/test/setup-global-functional.ts (1 hunks)
💤 Files with no reviewable changes (4)
  • apps/api/src/billing/services/index.ts
  • apps/api/src/billing/types/wallet.type.ts
  • apps/api/src/billing/providers/signing-client.provider.ts
  • apps/api/src/billing/services/dedupe-signing-client/dedupe-signing-client.service.ts
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.

Applied to files:

  • apps/api/test/setup-global-functional.ts
  • apps/api/test/custom-jest-environment.ts
  • apps/api/test/services/test-wallet.service.ts
  • apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts
  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts
  • apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts
  • apps/api/test/functional/start-trial.spec.ts
  • apps/api/src/billing/services/chain-error/chain-error.service.spec.ts
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts
  • apps/api/src/certificate/services/certificate/certificate.service.spec.ts
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts
📚 Learning: 2025-05-28T20:42:58.200Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 1372
File: apps/api/src/dashboard/services/stats/stats.service.ts:0-0
Timestamp: 2025-05-28T20:42:58.200Z
Learning: The user successfully implemented CosmosHttpService with retry logic using axiosRetry, exponential backoff, and proper error handling for Cosmos API calls, replacing direct axios usage in StatsService.

Applied to files:

  • apps/api/src/billing/services/financial-stats/financial-stats.service.ts
🧬 Code graph analysis (12)
apps/api/src/billing/controllers/wallet/wallet.controller.ts (1)
apps/api/src/billing/http-schemas/tx.schema.ts (1)
  • SignTxResponseOutput (34-34)
apps/api/test/custom-jest-environment.ts (3)
apps/api/test/setup-global-functional.ts (1)
  • localConfig (4-8)
apps/api/test/services/test-wallet.service.ts (1)
  • TestWalletService (21-165)
apps/api/src/billing/lib/wallet/wallet.ts (1)
  • Wallet (7-65)
apps/api/src/billing/services/tx-manager/tx-manager.service.ts (5)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (2)
  • BatchSigningClientService (57-360)
  • SignAndBroadcastOptions (24-34)
apps/api/src/billing/lib/signing-stargate-client-factory/signing-stargate-client.factory.ts (1)
  • createSigningStargateClient (57-61)
apps/api/src/billing/providers/wallet.provider.ts (1)
  • WALLET_FACTORY (7-7)
apps/api/src/billing/lib/wallet/wallet.ts (2)
  • walletFactory (68-68)
  • WalletFactory (67-67)
apps/api/src/billing/providers/type-registry.provider.ts (1)
  • TYPE_REGISTRY (34-34)
apps/api/src/billing/services/financial-stats/financial-stats.service.ts (2)
apps/api/src/billing/services/balances/balances.service.ts (1)
  • singleton (11-106)
apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (1)
  • singleton (26-138)
apps/api/test/services/test-wallet.service.ts (1)
apps/api/src/billing/lib/wallet/wallet.ts (1)
  • Wallet (7-65)
apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts (1)
apps/api/test/services/stub.ts (1)
  • stub (2-2)
apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (3)
packages/http-sdk/src/authz/authz-http.service.ts (1)
  • AuthzHttpService (56-218)
apps/api/src/billing/services/rpc-message-service/rpc-message.service.ts (1)
  • SpendingAuthorizationMsgOptions (16-22)
apps/api/src/core/types/console.ts (1)
  • DryRunOptions (1-3)
apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts (1)
apps/api/src/billing/model-schemas/user-wallet/user-wallet.schema.ts (1)
  • UserWallets (5-16)
apps/api/src/billing/services/chain-error/chain-error.service.spec.ts (1)
packages/http-sdk/src/balance/balance-http.service.ts (1)
  • BalanceHttpService (20-29)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (1)
  • BatchSigningClientService (57-360)
apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (1)
apps/api/test/seeders/akash-address.seeder.ts (1)
  • createAkashAddress (4-12)
apps/api/src/billing/services/managed-signer/managed-signer.service.ts (3)
packages/http-sdk/src/lease/lease-http.service.ts (2)
  • LeaseHttpService (72-96)
  • hasLeases (89-95)
apps/api/src/billing/repositories/user-wallet/user-wallet.repository.ts (1)
  • UserWalletOutput (17-21)
apps/api/src/billing/events/trial-deployment-lease-created.ts (1)
  • TrialDeploymentLeaseCreated (4-21)
🪛 dotenv-linter (4.0.0)
apps/api/env/.env.unit.test

[warning] 3-3: [UnorderedKey] The FUNDING_WALLET_MNEMONIC key should go before the POSTGRES_DB_URI key

(UnorderedKey)


[warning] 4-4: [UnorderedKey] The DERIVATION_WALLET_MNEMONIC key should go before the FUNDING_WALLET_MNEMONIC key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: test-build
🔇 Additional comments (37)
apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts (1)

54-54: No functional changes; note pre-existing type-safety concern.

The field reordering in the SELECT projection (line 54) is cosmetic and doesn't affect logic. However, the adjacent BUGALERT comment (line 67) flags a pre-existing issue: the LEFT JOINs (lines 58-59) can produce null values for walletId, but the AutoTopUpDeployment type expects walletId: number (line 21). The unsafe type cast on line 68 compounds this risk.

Verify whether the LEFT JOINs should be INNER JOINs based on your business requirements, and align the type definition and cast accordingly.

apps/api/src/deployment/services/lease/lease.service.ts (1)

28-41: Switch to derived signer for lease txs looks correct

Using executeDerivedDecodedTxByUserId(wallet.userId, leaseMessages) here cleanly aligns lease creation with the derived-wallet flow introduced in this PR, without changing the message construction or manifest send logic.

apps/api/src/billing/config/env.config.ts (1)

5-8: New funding/derivation mnemonics are now required env vars

Making FUNDING_WALLET_MNEMONIC and DERIVATION_WALLET_MNEMONIC required is consistent with the split‑wallet design, but it means any environment that parses this schema (local dev, tests, CI, deployed envs) must define both, or startup will fail at envSchema.parse.

Please double‑check:

  • All .env variants used by the API (including functional/e2e test env files), and
  • Any deployment/runtime config (Helm, Doppler, etc.)

are updated to provide these two vars and no longer rely on MASTER_WALLET_MNEMONIC.

apps/api/src/billing/providers/wallet.provider.ts (1)

1-10: Simplified wallet DI registration looks good

Registering WALLET_FACTORY directly with walletFactory via container.register(... useValue: walletFactory) cleanly preserves the factory injection without the old master‑wallet wiring. No issues from a DI or typing standpoint.

apps/api/package.json (1)

86-86: Let me verify if there are other test files importing fetch-mock to confirm the scope:

Based on verification, the grep search found fetch-mock used only in the test file ./apps/api/test/functional/sign-and-broadcast-tx.spec.ts, and web search confirms that devDependencies should include testing frameworks and mock APIs used in projects. The recommendation to move fetch-mock to devDependencies is correct.

Move fetch-mock to devDependencies in apps/api/package.json

fetch-mock is a test-mocking library used only in test/functional/sign-and-broadcast-tx.spec.ts. Following npm best practices, testing utilities should be listed under devDependencies rather than production dependencies to keep the runtime install surface minimal.

apps/api/test/services/test-wallet.service.ts (1)

57-85: ****

The wallet index concern does not reflect an actual issue. Verification shows the mnemonics cached from new Wallet(undefined, 1) wallets are rehydrated in tx-manager.service.ts line 19 with this.walletFactory(...FUNDING_WALLET_MNEMONIC, 1), which explicitly passes the matching index=1. The index consistency is already maintained throughout the codebase, and no problematic rehydrations without the index parameter were found.

Likely an incorrect or invalid review comment.

apps/api/src/billing/controllers/wallet/wallet.controller.ts (1)

114-114: LGTM! Method name updated to reflect derived wallet signing.

The change from executeEncodedTxByUserId to executeDerivedEncodedTxByUserId correctly aligns with the new TxManagerService-based architecture.

apps/api/test/functional/deployments.spec.ts (1)

90-90: LGTM! Test spies updated to match the new method signatures.

All occurrences of executeDerivedDecodedTxByUserId spy definitions are correctly aligned with the production code changes.

Also applies to: 662-662, 758-758, 793-793

apps/api/src/certificate/services/certificate/certificate.service.ts (1)

34-34: LGTM! Certificate signing updated to use derived wallet flow.

The change from executeDecodedTxByUserId to executeDerivedDecodedTxByUserId is consistent with the architectural refactor.

apps/api/test/setup-global-functional.ts (1)

5-5: LGTM! Environment variable check updated correctly.

The condition now checks for FUNDING_WALLET_MNEMONIC instead of MASTER_WALLET_MNEMONIC, aligning with the new wallet architecture.

apps/api/src/deployment/services/stale-managed-deployments-cleaner/stale-managed-deployments-cleaner.service.ts (1)

65-65: LGTM! Deployment cleanup updated to use derived transactions.

Both calls to executeDerivedTx (main path and retry path) are correctly updated from executeManagedTx, maintaining the error handling logic.

Also applies to: 76-76

apps/api/src/billing/services/provider-cleanup/provider-cleanup.service.ts (1)

59-59: LGTM! Provider cleanup updated to use derived transactions.

Both calls to executeDerivedTx (primary and retry paths) are correctly updated from executeManagedTx, preserving the dryRun gating and error handling logic.

Also applies to: 71-71

apps/api/test/custom-jest-environment.ts (1)

18-28: Inconsistent wallet initialization strategy confirmed.

The review comment's concern is valid. FUNDING_WALLET_MNEMONIC uses TestWalletService for consistent test wallets, while DERIVATION_WALLET_MNEMONIC creates a fresh random wallet via new Wallet().getMnemonic().

In production, TxManagerService.getDerivedWallet(index) reads DERIVATION_WALLET_MNEMONIC to derive child wallets at specific indices. Each test file receiving a different seed mnemonic means derived wallets are not reproducible across test runs or test files.

This inconsistency may be intentional (derivation wallets need per-test isolation while funding wallet requires consistency), but it warrants explicit verification to ensure test expectations are met.

apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts (1)

149-152: LGTM! Method rename aligns with the new derived wallet architecture.

The change from executeManagedTx to executeDerivedTx is consistent with the broader refactoring to separate funding and derived wallets. The method signature and parameters remain unchanged.

apps/api/test/functional/start-trial.spec.ts (2)

9-9: LGTM! Import updated for new wallet architecture.


50-56: LGTM! Test correctly updated to use TxManagerService.

The funding wallet address is now obtained via TxManagerService.getFundingWalletAddress() instead of the previous MANAGED_MASTER_WALLET.getFirstAddress() pattern, which aligns with the PR's separation of funding and derived wallets.

apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts (3)

60-60: LGTM! Deployment creation now uses derived wallet signing.


92-92: LGTM! Deposit transactions now use derived wallet signing.


127-127: LGTM! Deployment updates now use derived wallet signing.

All three transaction paths (create, deposit, update) consistently use executeDerivedDecodedTxByUserId, which aligns with the new wallet architecture.

apps/api/src/billing/services/chain-error/chain-error.service.ts (3)

7-7: LGTM! Import updated for new wallet architecture.


72-76: LGTM! Constructor updated to use TxManagerService.

The dependency injection correctly shifts from the previous Wallet to TxManagerService, which provides a centralized interface for wallet operations.


95-105: LGTM! Funding wallet address correctly retrieved via TxManagerService.

The method now uses txManagerService.getFundingWalletAddress() to obtain the master/funding wallet address, which is semantically clearer than the previous wallet.getFirstAddress() approach.

apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.ts (2)

28-31: LGTM! Constructor simplified with TxManagerService.

Dependencies reduced from (jwtModule, billingConfigService, walletFactory) to (jwtModule, txManagerService), consolidating wallet management concerns in a single service.


52-59: LGTM! Wallet derivation now centralized via TxManagerService.

The change from walletFactory(masterWalletMnemonic, walletId) to txManagerService.getDerivedWallet(walletId) simplifies the interface and removes the need for direct mnemonic handling.

apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts (3)

7-7: LGTM! Import updated for new wallet architecture.


22-27: LGTM! Test setup correctly uses TxManagerService.

The funding wallet address is obtained in beforeAll via txManagerService.getFundingWalletAddress(), replacing the previous MANAGED_MASTER_WALLET.getFirstAddress() pattern.


70-82: LGTM! All assertions updated to use funding wallet address.

All authz service calls consistently use fundingMasterWallet instead of the previous masterAddress, verifying that grants are properly revoked during cleanup.

apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts (4)

7-7: LGTM! Import updated for new service dependency.


16-32: LGTM! Test correctly verifies TxManagerService usage.

The test expectations are updated to verify txManagerService.getDerivedWallet is called with the correct walletId, replacing the previous wallet factory verification.


34-42: LGTM! Memoization test correctly updated.

The test verifies that getDerivedWallet is called only once when generating multiple tokens, confirming the memoization behavior is preserved.


92-117: LGTM! Test setup correctly mocks TxManagerService.

The mock setup replaces walletFactory and billingConfigService with txManagerService, and the return values are updated to include the new dependencies.

apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (2)

185-191: Error handling change verified - callers properly handle raw errors.

The raw error propagation is appropriately handled by all callers:

  • managed-signer.service.ts catches errors from signAndBroadcastWithDerivedWallet (line 43) and signAndBroadcastWithFundingWallet (line 53), transforming them via chainErrorService.toAppError() at lines 47 and 55 respectively
  • tx-manager.service.ts passes errors through without transformation, which is correct by design
  • Tests validate this error propagation model with Promise.allSettled and raw Error expectations

The architectural improvement—moving error transformation from the library layer to the service boundary—is sound and maintains proper error handling throughout the call chain.


149-159: ChainErrorService dependency removal verified as safe.

Verification confirms ChainErrorService was never used in BatchSigningClientService—zero references found in the file. The service's signAndBroadcast() method throws raw errors directly to callers without any error transformation, and callers (e.g., tx-manager.service.ts) handle them naturally via try-finally patterns. The removal is a valid code cleanup that eliminates unused dependency injection with no behavioral impact.

apps/api/src/certificate/services/certificate/certificate.service.spec.ts (1)

33-34: executeDerivedDecodedTxByUserId wiring in certificate tests looks correct

The mock, type annotation, and expectation are consistently updated to executeDerivedDecodedTxByUserId, and the argument/return shapes match the existing usage, so behavior remains unchanged.

Also applies to: 42-42, 81-82, 95-95

apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1)

138-185: Spec setup correctly updated for new BatchSigningClientService signature

The test helper now matches the constructor (config, wallet, registry, createClientWithSigner) and still wires mocks as expected; the remaining tests exercise the key batch, error, and retry flows, so this change looks good.

apps/api/src/billing/services/managed-signer/managed-signer.service.ts (2)

13-14: TxManagerService‑based execute*Tx wrappers are wired correctly

executeDerivedTx and executeFundingTx now cleanly delegate signing/broadcasting to TxManagerService while still using ChainErrorService.toAppError to normalize chain errors, and the fee‑granter being the funding wallet for derived transactions matches the new split‑wallet model. This keeps ManagedSignerService focused on auth/balance checks and domain events while centralizing chain interactions in TxManagerService.

Also applies to: 26-38, 40-57


59-80: Confirm mapping between UserWallet and derived wallet index used in executeDerivedTx

In executeDerivedDecodedTxByUserId / executeDecodedTxByUserWallet, the actual send now goes through:

const tx = await this.executeDerivedTx(userWallet.id, messages);

TxManagerService interprets that argument as the derivation index. Please double‑check that userWallet.id is indeed the same index you used when creating the derived wallet (e.g., via createWallet({ addressIndex })), and not just the database primary key. If there is a dedicated “derivation index”/“address index” field on the wallet record, that field should be passed here instead to ensure we sign with the correct derived account that holds the allowances. The rest of the flow (trial lease event emission and refreshUserWalletLimits) looks consistent with the previous behaviour.

Also applies to: 115-144

@ygrishajev ygrishajev force-pushed the feature/billing-master-wallets branch from e4b64bf to 67b9ddd Compare November 19, 2025 15:20
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (12)
apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (2)

65-87: Funding wallet as granter and funding‑tx execution path

The new flow in authorizeSpending / authorizeFeeSpending / authorizeDeploymentSpending and revokeAll looks coherent:

  • Granter is now fundingWalletAddress from TxManagerService, which matches the PR’s shift away from a master wallet.
  • All grant/revoke operations are funneled through managedSignerService.executeFundingTx(...), ensuring the funding wallet pays fees for these authz ops.
  • Promise.all in authorizeSpending correctly runs deployment and fee authorization in parallel, and the 'deployment' in options.limits guard keeps the union type safe.

Two minor points to consider:

  1. In authorizeFeeSpending, you currently check hasFeeAllowance (any allowance) rather than hasValidFeeAllowance. If the intent is to revoke only non‑expired allowances before re‑granting, switching to the “valid” variant could avoid attempting to revoke already‑expired grants. If revoking stale grants is intentional, current behavior is fine.

  2. All these methods assume that getFundingWalletAddress() and executeFundingTx(...) are aligned on which physical key is the “funding” wallet. Worth a quick check in TxManagerService / ManagedSignerService that there’s no mismatch in index or mnemonic source.

Otherwise, the structure looks solid.

Also applies to: 89-105, 107-137


26-33: Remove now‑unused HD path / prefix constants

PREFIX and HD_PATH are no longer used after moving derivation into TxManagerService. They can likely be dropped to reduce noise and avoid confusion about whether this class is still responsible for key derivation.

-  private readonly PREFIX = "akash";
-
-  private readonly HD_PATH = "m/44'/118'/0'/0";
-
apps/api/test/functional/start-trial.spec.ts (1)

9-55: Funding wallet now resolved via TxManagerService in trial test

Resolving fundingWalletAddress via TxManagerService.getFundingWalletAddress() and using it as the granter in getValidDepositDeploymentGrantsForGranterAndGrantee keeps the test aligned with the new funding-wallet model.

As a minor style tweak, you could mirror other top-level constants by resolving TxManagerService once at the describe-scope instead of inside the test body, but this is optional.

apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts (1)

7-82: Stale-anonymous cleanup test correctly switched to funding wallet via TxManagerService

Using txManagerService.getFundingWalletAddress() in beforeAll and passing fundingMasterWallet into the various AuthzHttpService checks keeps the expectations consistent with the new funding-wallet model.

If you want to tighten readability, consider renaming fundingMasterWallet to something like fundingWalletAddress, but this is purely cosmetic.

apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.ts (1)

7-59: Verify TxManagerService.getDerivedWallet sync/async semantics in JWT token flow

In getJwtToken, you currently do:

const wallet = this.txManagerService.getDerivedWallet(walletId);
const jwtTokenManager = new this.jwtModule.JwtTokenManager(wallet);
const address = await wallet.getFirstAddress();

This assumes getDerivedWallet(walletId) is synchronous and returns a wallet object (with getFirstAddress()), not a Promise. If getDerivedWallet is actually async and returns a Promise<Wallet>, this would pass a Promise into JwtTokenManager and only work by accident (or fail at runtime/type-check).

Please double-check the TxManagerService.getDerivedWallet signature and adjust accordingly. For an async API, this method should look like:

-  private async getJwtToken(walletId: number): Promise<JwtTokenWithAddress> {
-    const wallet = this.txManagerService.getDerivedWallet(walletId);
+  private async getJwtToken(walletId: number): Promise<JwtTokenWithAddress> {
+    const wallet = await this.txManagerService.getDerivedWallet(walletId);
     const jwtTokenManager = new this.jwtModule.JwtTokenManager(wallet);
     const address = await wallet.getFirstAddress();
apps/api/src/billing/services/balances/balances.service.ts (1)

7-8: Centralizing funding wallet usage via TxManagerService and caching full balance is consistent and safe

  • Injecting TxManagerService in the constructor and using getFundingWalletAddress() in both retrieveAndCalcFeeLimit and retrieveDeploymentLimit correctly centralizes the funding wallet source, matching the broader TxManager refactor.
  • The existing authz calls now use the funding wallet as granter while keeping user wallet as grantee, which preserves the original authorization model.
  • Adding @Memoize({ ttlInSeconds: averageBlockTime }) on getFullBalance is a reasonable optimization: it avoids redundant network calls while staying aligned with on-chain update cadence.
  • Minor nit: you could mark txManagerService as private readonly for consistency with other injected services, but current code is functionally fine as-is.

Also applies to: 16-19, 55-58, 66-69, 94-95

apps/api/env/.env.unit.test (1)

3-4: Env mnemonic keys match new funding/derivation model; consider addressing dotenv-linter ordering warnings

Switching to FUNDING_WALLET_MNEMONIC and adding DERIVATION_WALLET_MNEMONIC is consistent with the TxManagerService-based split between funding and derived wallets.
Static analysis (dotenv-linter) flags key ordering for these two entries; if your CI enforces this, you may want to reorder them as suggested, otherwise current content is fine functionally.

apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (1)

21-22: Align createAkashAddress import with existing @test aliases

You currently import createAkashAddress via a deep relative path while other seeders in the same file use the @test/seeders/... alias. For consistency and easier refactoring, consider switching to the alias form, e.g. @test/seeders/akash-address.seeder, and optionally inlining a simple string literal if you don't need randomness in this spec.

Also applies to: 530-533

apps/api/src/billing/services/tx-manager/tx-manager.service.ts (2)

33-41: Consider tightening return types for signing methods

signAndBroadcastWithFundingWallet / signAndBroadcastWithDerivedWallet currently rely on the underlying client’s implicit return type (Promise<any>), which makes callers lose static guarantees about the shape of the transaction result. If BatchSigningClientService.signAndBroadcast is expected to return something IndexedTx-like, consider reflecting that in these method signatures so downstream services can rely on stronger typing.


73-80: Surface DERIVATION_WALLET_MNEMONIC misconfiguration earlier

getDerivedWallet throws if DERIVATION_WALLET_MNEMONIC is missing, but this only shows up on the first derived call at runtime. For operator-friendliness, you may want to validate this config on service initialization (or via BillingConfigService validation) so misconfiguration fails fast at startup instead of at the first transaction. This is a cross-cutting concern and might be better tracked as a follow‑up issue rather than expanding this PR.

apps/api/src/billing/services/managed-signer/managed-signer.service.ts (2)

119-143: Result normalization looks correct; consider tightening the typing

The pattern of picking { code, hash, transactionHash, rawLog } from tx and then normalizing transactionHash from hash ensures callers always get a transactionHash, which is good. However, result is cast as Pick<IndexedTx, "code" | "hash" | "rawLog">, even though transactionHash is also being selected and used. It would be cleaner to either introduce a small TxExecutionResult type that explicitly includes transactionHash, or extend the pick type to match the actual shape you expect from the underlying client.


40-49: Confirm the userWallet.id → derivation index mapping is intentional

executeDecodedTxByUserWallet ultimately calls executeDerivedTx(userWallet.id, messages), which then invokes txManagerService.signAndBroadcastWithDerivedWallet(walletIndex, ...). This effectively couples the DB wallet ID to the derivation index used by WalletFactory/Wallet. If this convention already existed before the refactor, keeping it is fine, but it’s subtle and long‑lived (e.g., DB IDs must stay within the derivation index range). It might be worth briefly documenting this assumption or adding a guard if there’s any risk of unexpected ID growth. Given the cross‑cutting nature, this could be a separate follow‑up issue rather than a change in this PR.

Also applies to: 82-120

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e4b64bf and 67b9ddd.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (37)
  • apps/api/env/.env.unit.test (1 hunks)
  • apps/api/package.json (1 hunks)
  • apps/api/src/billing/config/env.config.ts (1 hunks)
  • apps/api/src/billing/controllers/wallet/wallet.controller.ts (1 hunks)
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1 hunks)
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (1 hunks)
  • apps/api/src/billing/providers/signing-client.provider.ts (1 hunks)
  • apps/api/src/billing/providers/wallet.provider.ts (1 hunks)
  • apps/api/src/billing/services/balances/balances.service.ts (5 hunks)
  • apps/api/src/billing/services/chain-error/chain-error.service.spec.ts (2 hunks)
  • apps/api/src/billing/services/chain-error/chain-error.service.ts (3 hunks)
  • apps/api/src/billing/services/dedupe-signing-client/dedupe-signing-client.service.ts (0 hunks)
  • apps/api/src/billing/services/financial-stats/financial-stats.service.ts (1 hunks)
  • apps/api/src/billing/services/index.ts (0 hunks)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (20 hunks)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.ts (3 hunks)
  • apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (5 hunks)
  • apps/api/src/billing/services/provider-cleanup/provider-cleanup.service.ts (2 hunks)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.ts (1 hunks)
  • apps/api/src/billing/types/wallet.type.ts (0 hunks)
  • apps/api/src/certificate/services/certificate/certificate.service.spec.ts (4 hunks)
  • apps/api/src/certificate/services/certificate/certificate.service.ts (1 hunks)
  • apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts (1 hunks)
  • apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts (3 hunks)
  • apps/api/src/deployment/services/lease/lease.service.ts (1 hunks)
  • apps/api/src/deployment/services/stale-managed-deployments-cleaner/stale-managed-deployments-cleaner.service.ts (2 hunks)
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts (9 hunks)
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts (1 hunks)
  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts (5 hunks)
  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.ts (3 hunks)
  • apps/api/test/custom-jest-environment.ts (2 hunks)
  • apps/api/test/functional/deployments.spec.ts (4 hunks)
  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts (0 hunks)
  • apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts (3 hunks)
  • apps/api/test/functional/start-trial.spec.ts (2 hunks)
  • apps/api/test/services/test-wallet.service.ts (1 hunks)
  • apps/api/test/setup-global-functional.ts (1 hunks)
💤 Files with no reviewable changes (4)
  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts
  • apps/api/src/billing/services/index.ts
  • apps/api/src/billing/services/dedupe-signing-client/dedupe-signing-client.service.ts
  • apps/api/src/billing/types/wallet.type.ts
🚧 Files skipped from review as they are similar to previous changes (12)
  • apps/api/src/billing/controllers/wallet/wallet.controller.ts
  • apps/api/package.json
  • apps/api/test/functional/deployments.spec.ts
  • apps/api/test/custom-jest-environment.ts
  • apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts
  • apps/api/test/services/test-wallet.service.ts
  • apps/api/src/billing/config/env.config.ts
  • apps/api/src/certificate/services/certificate/certificate.service.spec.ts
  • apps/api/src/billing/services/chain-error/chain-error.service.spec.ts
  • apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts
  • apps/api/src/billing/providers/signing-client.provider.ts
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
📚 Learning: 2025-11-19T15:15:07.266Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.266Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.

Applied to files:

  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.

Applied to files:

  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts
  • apps/api/test/functional/start-trial.spec.ts
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts
  • apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts
  • apps/api/test/setup-global-functional.ts
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts
📚 Learning: 2025-05-28T20:42:58.200Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 1372
File: apps/api/src/dashboard/services/stats/stats.service.ts:0-0
Timestamp: 2025-05-28T20:42:58.200Z
Learning: The user successfully implemented CosmosHttpService with retry logic using axiosRetry, exponential backoff, and proper error handling for Cosmos API calls, replacing direct axios usage in StatsService.

Applied to files:

  • apps/api/src/billing/services/financial-stats/financial-stats.service.ts
🧬 Code graph analysis (7)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (1)
  • BatchSigningClientService (57-360)
apps/api/src/billing/services/financial-stats/financial-stats.service.ts (2)
apps/api/src/billing/services/balances/balances.service.ts (1)
  • singleton (11-106)
apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (1)
  • singleton (26-138)
apps/api/src/billing/services/tx-manager/tx-manager.service.ts (6)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (2)
  • BatchSigningClientService (57-360)
  • SignAndBroadcastOptions (24-34)
apps/api/src/billing/providers/wallet.provider.ts (2)
  • FUNDING_WALLET (10-10)
  • WALLET_FACTORY (18-18)
apps/api/src/billing/lib/wallet/wallet.ts (3)
  • Wallet (7-65)
  • walletFactory (68-68)
  • WalletFactory (67-67)
apps/api/src/billing/providers/signing-client.provider.ts (1)
  • FUNDING_SIGNING_CLIENT (11-11)
apps/api/src/billing/providers/type-registry.provider.ts (1)
  • TYPE_REGISTRY (34-34)
apps/api/src/billing/lib/signing-stargate-client-factory/signing-stargate-client.factory.ts (1)
  • createSigningStargateClient (57-61)
apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (1)
apps/api/test/seeders/akash-address.seeder.ts (1)
  • createAkashAddress (4-12)
apps/api/src/billing/services/managed-signer/managed-signer.service.ts (3)
packages/http-sdk/src/lease/lease-http.service.ts (2)
  • LeaseHttpService (72-96)
  • hasLeases (89-95)
apps/api/src/billing/repositories/user-wallet/user-wallet.repository.ts (1)
  • UserWalletOutput (17-21)
apps/api/src/billing/events/trial-deployment-lease-created.ts (1)
  • TrialDeploymentLeaseCreated (4-21)
apps/api/src/billing/providers/wallet.provider.ts (1)
apps/api/src/billing/lib/wallet/wallet.ts (1)
  • Wallet (7-65)
apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (3)
packages/http-sdk/src/authz/authz-http.service.ts (1)
  • AuthzHttpService (56-218)
apps/api/src/billing/services/rpc-message-service/rpc-message.service.ts (1)
  • SpendingAuthorizationMsgOptions (16-22)
apps/api/src/core/types/console.ts (1)
  • DryRunOptions (1-3)
🪛 dotenv-linter (4.0.0)
apps/api/env/.env.unit.test

[warning] 3-3: [UnorderedKey] The FUNDING_WALLET_MNEMONIC key should go before the POSTGRES_DB_URI key

(UnorderedKey)


[warning] 4-4: [UnorderedKey] The DERIVATION_WALLET_MNEMONIC key should go before the FUNDING_WALLET_MNEMONIC key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: validate (apps/provider-console) / validate-unsafe
  • GitHub Check: validate / validate-app
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (14)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (1)

185-191: Raw result.val throw changes error shape and type

You now throw result.val directly, which is typed as unknown. Callers may have been relying on ChainErrorService-normalized error types (e.g., specific Error subclasses / PaymentRequired mappings) and on instanceof Error checks.

If all producers of Err(error) in this pipeline guarantee an Error-like object, this is fine; otherwise, you might want to either:

  • Wrap non-Error values in a generic Error, or
  • Narrow unknown here before throwing to avoid surprising downstream behavior.

At minimum, worth double-checking the main call sites of signAndBroadcast for assumptions about the thrown error type/shape.

apps/api/src/billing/services/provider-cleanup/provider-cleanup.service.ts (1)

57-73: Confirm executeDerivedTx(wallet.id, [message]) semantics for cleanup flow

The cleanup path now uses executeDerivedTx(wallet.id, [message]) (both initially and after authorizeSpending). This looks consistent with the broader migration to derived wallets, but a couple of things are worth confirming:

  • wallet.id is indeed the right key for the derived-wallet path in ManagedSignerService (and not e.g. an address or userId).
  • The derived wallet used here is the expected fee payer in this cleanup scenario (vs funding wallet).

If both are true in the new TxManager/ManagedSigner design, this change is good.

apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (1)

34-37: Derived address usage via TxManagerService looks consistent

createAndAuthorizeTrialSpending and createWallet now rely on txManagerService.getDerivedWalletAddress(addressIndex) and return/log that address. Assuming TxManagerService deterministically maps (index) to the same derivation path you previously used here, this is a clean encapsulation of the derivation logic.

It would be good to sanity-check that:

  • The index semantics (e.g., which index corresponds to which user) remain unchanged, and
  • There’s no off‑by‑one between the derivation index here and any funding/derivation index conventions elsewhere.

Also applies to: 42-56, 58-63

apps/api/src/billing/providers/wallet.provider.ts (1)

2-16: FUNDING_WALLET registration aligns with TxManagerService, verify index and config

The FUNDING_WALLET wiring via BillingConfigService + WALLET_FACTORY looks good and matches the intent to centralize usage behind TxManagerService.

A couple of things to confirm:

  • config.get("FUNDING_WALLET_MNEMONIC") is guaranteed non‑empty at startup (or BillingConfigService will fail fast with a clear error if missing).
  • The hard‑coded index 1 matches the conventions in TxManagerService (i.e., funding wallet is always HD index 1, and derived wallets never collide with it).

Given the “do not use directly” comment, enforcing access via TxManagerService only is a good pattern.

apps/api/src/deployment/services/lease/lease.service.ts (1)

30-41: Lease signing routed through derived‑wallet path

Switching to executeDerivedDecodedTxByUserId(wallet.userId, leaseMessages) keeps the same inputs (userId + messages) while aligning with the new derived‑wallet‑centric signer API. As long as executeDerivedDecodedTxByUserId is wired to the correct derived account for this user, this is a safe and consistent change.

Looks good.

apps/api/src/certificate/services/certificate/certificate.service.ts (1)

34-40: Signer call correctly migrated to derived-tx API

Switching to executeDerivedDecodedTxByUserId(userWallet.userId, messages) is consistent with the new derived-wallet flow; inputs and behavior remain aligned with the previous implementation.

apps/api/test/setup-global-functional.ts (1)

5-7: Env gate aligned with funding wallet mnemonic

Using localConfig.FUNDING_WALLET_MNEMONIC here keeps the previous behavior while matching the new funding-wallet naming.

apps/api/src/deployment/services/stale-managed-deployments-cleaner/stale-managed-deployments-cleaner.service.ts (1)

64-77: Cleanup flow now consistently uses derived signer

Both the primary and retry paths call executeDerivedTx(wallet.id, messages), which keeps behavior consistent while routing through the new derived-wallet signer.

apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts (1)

147-153: Top-up signer call correctly switched to derived tx

Using executeDerivedTx(walletId, ownerInputs.map(i => i.message)) preserves existing behavior while aligning with the derived-wallet/TxManagerService-based flow.

apps/api/src/billing/services/chain-error/chain-error.service.ts (1)

7-105: Master/funding balance check correctly routed through TxManagerService

Replacing direct wallet injection with TxManagerService and using getFundingWalletAddress() in isMasterWalletInsufficientFundsError keeps the error-mapping behavior the same while centralizing funding wallet resolution.

apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts (1)

16-22: TxManagerService-based wallet resolution and memoization tests look correct

The updated tests correctly:

  • Delegate wallet resolution to txManagerService.getDerivedWallet(walletId) and assert it’s called with the expected walletId.
  • Ensure JWT creation uses the resolved wallet instance and generated token is as expected.
  • Verify memoization by asserting getDerivedWallet and JwtTokenManager are invoked only once across repeated generateJwtToken calls.
    The setup mock for TxManagerService and the constructor call new ProviderJwtTokenService(jwtModule, txManagerService) are consistent with the new dependency graph, with no apparent gaps.

Also applies to: 35-42, 92-95, 108-118

apps/api/src/billing/services/financial-stats/financial-stats.service.ts (1)

11-19: Funding wallet balance resolution via TxManagerService is aligned with the new architecture

The constructor and getMasterWalletBalanceUsdc changes cleanly switch from local/master-wallet configuration to txManagerService.getFundingWalletAddress(), making the funding wallet a shared concern. CosmosHttpService usage is unchanged, so the only behavioral difference is the centralized address source, which matches the TxManagerService introduction elsewhere. No issues noted.

Also applies to: 25-27

apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1)

182-185: BatchSigningClientService test setup matches the new constructor signature

The test setup now constructs BatchSigningClientService with (billingConfigService, wallet, registry, createClientWithSigner), which aligns with the updated constructor (no ChainErrorService argument). The returned { service, client } is still sufficient for the existing batching and retry tests, so coverage remains valid for the current behavior.

apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (1)

96-214: Derived path tests look solid and aligned with the new TxManagerService flow

The updated specs around executeDerivedDecodedTxByUserId (including feature-flag branches, successful execution, events, and chain error handling) exercise the new txManagerService.signAndBroadcastWithDerivedWallet usage and fee-granter behavior well. The expectation on signAndBroadcastWithDerivedWallet(wallet.id, messages, { fee: { granter: expect.any(String) } }) also guards the integration with getFundingWalletAddress.

stalniy
stalniy previously approved these changes Nov 20, 2025
@ygrishajev ygrishajev force-pushed the feature/billing-master-wallets branch from 9ff8bd5 to 2e703e9 Compare November 20, 2025 09:29
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts (1)

73-77: Update close() method to use derived wallet signing for consistency.

The close method at line 76 uses executeDecodedTxByUserWallet(wallet, [message]), but all other deployment operations in this service (create, deposit, ensureDeploymentIsUpToDate) use executeDerivedDecodedTxByUserId(wallet.userId, ...).

Update line 76 to:

await this.signerService.executeDerivedDecodedTxByUserId(wallet.userId, [message]);

This aligns with the established pattern and the refactoring goals across the codebase.

🧹 Nitpick comments (5)
apps/api/src/billing/services/balances/balances.service.ts (1)

7-19: TxManagerService integration for funding address looks correct; consider marking the dependency readonly

The switch to resolving the granter via txManagerService.getFundingWalletAddress() for both fee and deployment limits aligns with the new funding-wallet model and keeps BalancesService decoupled from wallet details. One small consistency tweak: other injected dependencies are readonly, but txManagerService is not.

You can make it immutable like the others:

-    private txManagerService: TxManagerService,
+    private readonly txManagerService: TxManagerService,

Also applies to: 55-75

apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts (1)

47-48: Tests correctly track the switch to executeDerivedTx; “master wallet” naming can be cleaned up later

Stubbing and expectations have been consistently updated to managedSignerService.executeDerivedTx, and the message payload/assertion logic around top‑ups and error paths still matches the intended behavior.

The remaining isMasterWalletInsufficientFundsError/MASTER_WALLET_INSUFFICIENT_FUNDS naming is now conceptually a bit off given the funding/derived split, but that’s cosmetic and cross‑cutting; it’s reasonable to keep as‑is here and, if needed, track a broader terminology cleanup in a separate issue. Based on learnings.

Also applies to: 108-111, 210-211, 237-238, 245-246, 277-279, 378-379, 407-408, 442-443, 464-465

apps/api/src/billing/services/tx-manager/tx-manager.service.ts (2)

16-48: DI setup for funding and derived wallets is coherent; tighten WalletFactory typing

The DI registrations for FUNDING_WALLET, DERIVED_WALLET_FACTORY, FUNDING_SIGNING_CLIENT, and BATCH_SIGNING_CLIENT_FACTORY line up with how TxManagerService is constructed and used; this cleanly replaces the old wallet/signing‑client providers.

One small type‑safety improvement: WalletFactory is declared with an optional index, but all usages require an index and the concrete factory implementation takes a number. You can align the type:

-export type WalletFactory = (walletIndex?: number) => Wallet;
+export type WalletFactory = (walletIndex: number) => Wallet;

50-107: Client caching/cleanup for derived wallets is sound; consider passing logger context for better tracing

The per‑address cache in #clientsByAddress plus #getClient ensures only one BatchSigningClientService instance is reused per derived address, and the finally block in signAndBroadcastWithDerivedWallet guarantees cleanup when there are no pending transactions. This matches the intended dedupe behavior and is well covered by the new spec.

If you want more granular observability, you could propagate a context that includes the address into the derived client factory:

-      this.#clientsByAddress.set(address, {
-        address,
-        client: this.batchSigningClientServiceFactory(wallet)
-      });
+      this.#clientsByAddress.set(address, {
+        address,
+        client: this.batchSigningClientServiceFactory(wallet, `DERIVED_SIGNING_CLIENT:${address}`)
+      });

This would make BatchSigningClientService logs easier to correlate back to specific derived wallets.

apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (1)

21-23: TxManagerService wiring in tests looks consistent with the implementation

Importing TxManagerService for typing, using createAkashAddress to back getFundingWalletAddress, and passing mocks.txManagerService into ManagedSignerService matches the new production constructor and keeps the mocks strongly typed via TxManagerService["signAndBroadcastWithDerivedWallet"].

As a minor follow-up, you might later add a focused unit test around executeFundingTx (and possibly assert getFundingWalletAddress usage) to mirror the derived-wallet coverage, but that can be deferred or tracked as a separate task.

Also applies to: 490-553

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67b9ddd and 2e703e9.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (40)
  • apps/api/env/.env.unit.test (1 hunks)
  • apps/api/package.json (1 hunks)
  • apps/api/src/billing/config/env.config.ts (1 hunks)
  • apps/api/src/billing/controllers/wallet/wallet.controller.ts (1 hunks)
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1 hunks)
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (1 hunks)
  • apps/api/src/billing/lib/wallet/wallet.ts (0 hunks)
  • apps/api/src/billing/providers/index.ts (0 hunks)
  • apps/api/src/billing/providers/signing-client.provider.ts (0 hunks)
  • apps/api/src/billing/providers/wallet.provider.ts (0 hunks)
  • apps/api/src/billing/services/balances/balances.service.ts (5 hunks)
  • apps/api/src/billing/services/chain-error/chain-error.service.spec.ts (2 hunks)
  • apps/api/src/billing/services/chain-error/chain-error.service.ts (3 hunks)
  • apps/api/src/billing/services/dedupe-signing-client/dedupe-signing-client.service.ts (0 hunks)
  • apps/api/src/billing/services/financial-stats/financial-stats.service.ts (1 hunks)
  • apps/api/src/billing/services/index.ts (0 hunks)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (20 hunks)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.ts (3 hunks)
  • apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (5 hunks)
  • apps/api/src/billing/services/provider-cleanup/provider-cleanup.service.ts (2 hunks)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.spec.ts (1 hunks)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.ts (1 hunks)
  • apps/api/src/billing/types/wallet.type.ts (0 hunks)
  • apps/api/src/certificate/services/certificate/certificate.service.spec.ts (4 hunks)
  • apps/api/src/certificate/services/certificate/certificate.service.ts (1 hunks)
  • apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts (1 hunks)
  • apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts (3 hunks)
  • apps/api/src/deployment/services/lease/lease.service.ts (1 hunks)
  • apps/api/src/deployment/services/stale-managed-deployments-cleaner/stale-managed-deployments-cleaner.service.ts (2 hunks)
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts (9 hunks)
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts (1 hunks)
  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts (5 hunks)
  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.ts (3 hunks)
  • apps/api/test/custom-jest-environment.ts (2 hunks)
  • apps/api/test/functional/deployments.spec.ts (4 hunks)
  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts (2 hunks)
  • apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts (3 hunks)
  • apps/api/test/functional/start-trial.spec.ts (2 hunks)
  • apps/api/test/services/test-wallet.service.ts (1 hunks)
  • apps/api/test/setup-global-functional.ts (1 hunks)
💤 Files with no reviewable changes (7)
  • apps/api/src/billing/types/wallet.type.ts
  • apps/api/src/billing/lib/wallet/wallet.ts
  • apps/api/src/billing/services/index.ts
  • apps/api/src/billing/providers/signing-client.provider.ts
  • apps/api/src/billing/providers/index.ts
  • apps/api/src/billing/services/dedupe-signing-client/dedupe-signing-client.service.ts
  • apps/api/src/billing/providers/wallet.provider.ts
🚧 Files skipped from review as they are similar to previous changes (15)
  • apps/api/package.json
  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts
  • apps/api/src/billing/services/chain-error/chain-error.service.ts
  • apps/api/src/deployment/repositories/deployment-setting/deployment-setting.repository.ts
  • apps/api/src/billing/services/chain-error/chain-error.service.spec.ts
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.ts
  • apps/api/src/billing/config/env.config.ts
  • apps/api/test/setup-global-functional.ts
  • apps/api/src/certificate/services/certificate/certificate.service.ts
  • apps/api/test/functional/start-trial.spec.ts
  • apps/api/src/deployment/services/stale-managed-deployments-cleaner/stale-managed-deployments-cleaner.service.ts
  • apps/api/src/billing/services/provider-cleanup/provider-cleanup.service.ts
  • apps/api/test/functional/deployments.spec.ts
  • apps/api/src/certificate/services/certificate/certificate.service.spec.ts
  • apps/api/src/billing/services/financial-stats/financial-stats.service.ts
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
📚 Learning: 2025-11-19T15:15:07.266Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.266Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.

Applied to files:

  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts
  • apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts
  • apps/api/src/billing/services/tx-manager/tx-manager.service.spec.ts
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.

Applied to files:

  • apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts
  • apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts
  • apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts
  • apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts
  • apps/api/test/services/test-wallet.service.ts
  • apps/api/test/custom-jest-environment.ts
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts
🧬 Code graph analysis (9)
apps/api/src/billing/services/tx-manager/tx-manager.service.ts (4)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (2)
  • BatchSigningClientService (57-360)
  • SignAndBroadcastOptions (24-34)
apps/api/src/billing/lib/wallet/wallet.ts (1)
  • Wallet (7-65)
apps/api/src/billing/providers/type-registry.provider.ts (1)
  • TYPE_REGISTRY (34-34)
apps/api/src/billing/lib/signing-stargate-client-factory/signing-stargate-client.factory.ts (1)
  • createSigningStargateClient (57-61)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (1)
  • BatchSigningClientService (57-360)
apps/api/src/deployment/services/top-up-managed-deployments/top-up-managed-deployments.service.spec.ts (2)
apps/api/test/services/stub.ts (1)
  • stub (2-2)
packages/logging/src/services/logger/logger.service.ts (1)
  • error (141-143)
apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (3)
packages/http-sdk/src/authz/authz-http.service.ts (1)
  • AuthzHttpService (56-218)
apps/api/src/billing/services/rpc-message-service/rpc-message.service.ts (1)
  • SpendingAuthorizationMsgOptions (16-22)
apps/api/src/core/types/console.ts (1)
  • DryRunOptions (1-3)
apps/api/src/billing/services/tx-manager/tx-manager.service.spec.ts (3)
apps/api/test/seeders/akash-address.seeder.ts (1)
  • createAkashAddress (4-12)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (1)
  • SignAndBroadcastOptions (24-34)
apps/api/src/billing/lib/wallet/wallet.ts (1)
  • Wallet (7-65)
apps/api/test/services/test-wallet.service.ts (1)
apps/api/src/billing/lib/wallet/wallet.ts (1)
  • Wallet (7-65)
apps/api/test/custom-jest-environment.ts (3)
apps/api/test/setup-global-functional.ts (1)
  • localConfig (4-8)
apps/api/test/services/test-wallet.service.ts (1)
  • TestWalletService (21-165)
apps/api/src/billing/lib/wallet/wallet.ts (1)
  • Wallet (7-65)
apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (1)
apps/api/test/seeders/akash-address.seeder.ts (1)
  • createAkashAddress (4-12)
apps/api/src/billing/services/managed-signer/managed-signer.service.ts (3)
packages/http-sdk/src/lease/lease-http.service.ts (2)
  • LeaseHttpService (72-96)
  • hasLeases (89-95)
apps/api/src/billing/repositories/user-wallet/user-wallet.repository.ts (1)
  • UserWalletOutput (17-21)
apps/api/src/billing/events/trial-deployment-lease-created.ts (1)
  • TrialDeploymentLeaseCreated (4-21)
🪛 dotenv-linter (4.0.0)
apps/api/env/.env.unit.test

[warning] 3-3: [UnorderedKey] The FUNDING_WALLET_MNEMONIC key should go before the POSTGRES_DB_URI key

(UnorderedKey)


[warning] 4-4: [UnorderedKey] The DERIVATION_WALLET_MNEMONIC key should go before the FUNDING_WALLET_MNEMONIC key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: validate (apps/provider-proxy) / validate-unsafe
  • GitHub Check: validate (apps/notifications) / validate-unsafe
  • GitHub Check: validate (apps/provider-console) / validate-unsafe
  • GitHub Check: validate (apps/stats-web) / validate-unsafe
  • GitHub Check: validate (apps/api) / validate-unsafe
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (21)
apps/api/src/deployment/services/lease/lease.service.ts (1)

40-40: Verification confirms the change is correct.

The method executeDerivedDecodedTxByUserId performs comprehensive validation including:

  • Wallet fee allowance checks
  • Lease provider and auditor validation
  • Derived wallet signing via funding wallet fee granter pattern
  • Proper permission gating ("sign" ability)

The migration is complete with no remaining old method calls, and tests are updated. Derived wallet signing is the appropriate mechanism for lease operations within this refactoring.

apps/api/src/deployment/services/deployment-writer/deployment-writer.service.ts (4)

24-33: LGTM! Constructor properly updated.

The removal of the masterWallet injection aligns with the PR's objective to centralize wallet management. All necessary services for the new signing approach are correctly injected.


60-60: LGTM! Signing method updated correctly.

The migration to executeDerivedDecodedTxByUserId properly implements the new derived wallet signing approach.


92-92: LGTM! Deposit signing updated correctly.

The migration to executeDerivedDecodedTxByUserId is consistent with the other updated methods.


127-127: LGTM! Update deployment signing migrated correctly.

The use of executeDerivedDecodedTxByUserId is consistent with the other deployment operation updates.

apps/api/test/services/test-wallet.service.ts (1)

65-65: Verify the hardcoded wallet index is intentional.

The wallet instantiation now explicitly uses index 1 for all test wallets. Note that prepareFaucetWallet at line 114 still creates a wallet without an index, which will use the default HD path. Ensure this difference is intentional for your test setup.

apps/api/test/custom-jest-environment.ts (1)

4-4: LGTM! Environment variable migration looks correct.

The changes properly split the master wallet into two distinct concepts (funding and derivation wallets) with appropriate fallbacks when config values aren't provided.

Also applies to: 18-28

apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (2)

149-159: LGTM! Simplified constructor signature.

The removal of ChainErrorService dependency streamlines the service dependencies and aligns with the broader refactor to centralize wallet management in TxManagerService.


190-190: I'll examine the error handling in the caller methods and review the change in detail to verify if there's a breaking change.

Now let me examine the actual code changes in batch-signing-client.service.ts and search for ChainErrorService:Based on the verification of callers, the review comment cannot be fully substantiated without examining the actual code changes and error handling patterns in the repository. Here is my rewritten review:

Verify that thrown errors won't break existing callers.

The change removes error transformation through ChainErrorService.toError(), directly throwing result.val instead. Before approval, confirm: (1) result.val contains the expected error object type that callers receive, and (2) no caller code inspects error properties or type-checks expecting a transformed error structure. Callers identified at gpu-bids-creator.service.ts:152,166, tx-manager.service.ts:65,76, closeDeployments.ts:52, and test-wallet.service.ts:94 should be reviewed for any error-specific handling.

apps/api/env/.env.unit.test (1)

3-4: LGTM! Wallet mnemonic separation is properly configured.

The split into FUNDING_WALLET_MNEMONIC and DERIVATION_WALLET_MNEMONIC with distinct values correctly implements the intended wallet separation architecture.

apps/api/src/billing/controllers/wallet/wallet.controller.ts (1)

114-114: LGTM! Method rename aligns with derived wallet architecture.

The change from executeEncodedTxByUserId to executeDerivedEncodedTxByUserId correctly reflects the new derived wallet signing flow introduced by TxManagerService.

apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.ts (1)

28-31: LGTM! Excellent dependency consolidation.

Replacing BillingConfigService and WalletFactory with a single TxManagerService dependency significantly simplifies the service's dependency graph while maintaining the same functionality through getDerivedWallet().

Also applies to: 54-54

apps/api/test/functional/stale-anonymous-users-cleanup.spec.ts (1)

7-7: LGTM! Test correctly migrated to TxManagerService.

The test properly adopts the new TxManagerService architecture, replacing direct master wallet address access with getFundingWalletAddress(). All assertions are consistently updated to use the funding wallet.

Also applies to: 22-27, 70-80

apps/api/src/provider/services/provider-jwt-token/provider-jwt-token.service.spec.ts (1)

7-7: LGTM! Test correctly updated to match service refactor.

All test setup, mocks, and expectations properly reflect the migration from WalletFactory to TxManagerService.getDerivedWallet(). The test maintains the same behavioral coverage with the new dependency.

Also applies to: 16-17, 21-21, 35-36, 40-41, 92-96, 116-117

apps/api/src/billing/services/managed-user-wallet/managed-user-wallet.service.ts (1)

3-4: Funding/derived wallet split is wired correctly through TxManagerService

Using txManagerService.getDerivedWalletAddress for wallet creation and getFundingWalletAddress + executeFundingTx for fee/deployment grants and revocations cleanly separates derived from funding responsibilities while preserving existing behavior around limits and dry‑run handling. The transitions in authorizeSpending, authorizeFeeSpending, authorizeDeploymentSpending, and revokeAll all look consistent with the new model.

Also applies to: 8-9, 34-40, 42-63, 65-87, 89-132

apps/api/src/billing/services/tx-manager/tx-manager.service.spec.ts (1)

12-185: TxManagerService test coverage is comprehensive and aligned with the implementation

The spec exercises all key behaviors: funding vs derived signing, client creation and reuse, cleanup with and without pending transactions, error propagation, and wallet/address resolution via the factory. The setup helper cleanly isolates dependencies with mocks, and the log expectations match the events emitted in the service.

Also applies to: 187-236

apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.spec.ts (1)

182-185: Setup helper correctly reflects updated BatchSigningClientService constructor

Using (billingConfigService, wallet, registry, createClientWithSigner) and returning { service, client } matches the new service signature and keeps the test helper minimal and accurate.

apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts (2)

29-75: Derived-tx error handling and auth semantics are well covered

The updated tests around executeDerivedDecodedTxByUserId exercise the key negative paths (null/undefined userId, missing wallet, missing user, zero fee/deployment allowance) and confirm that:

  • 404/403 messages match the assert usage in the service.
  • userWalletRepository.accessibleBy and userRepository.findById are called with the expected parameters.
  • Chain errors from signAndBroadcastWithDerivedWallet are translated via chainErrorService.toAppError.
  • When the requested userId matches authService.currentUser.userId, the repository is not queried.

These align tightly with the new TxManagerService-based implementation and should catch most regressions in the derived-tx path.

Also applies to: 172-214, 312-341, 343-371


96-170: Trial/feature-flag behavior and domain events are thoroughly tested

The scenarios around anonymous trial flags and trial wallets cover the important combinations:

  • When ANONYMOUS_FREE_TRIAL is enabled, validateLeaseProviders and validateTrialLimit are invoked per message, and domain events are suppressed.
  • When it’s disabled, trial wallets with MsgCreateLease trigger TrialDeploymentLeaseCreated with the correct walletId, dseq, and isFirstLease derived from LeaseHttpService.hasLeases.
  • Lease provider validation (validateLeaseProvidersAuditors) is asserted for both trial and non-trial wallets and also in anonymous mode.

These tests closely mirror the control flow and conditionals in executeDecodedTxByUserWallet, giving good confidence that the new TxManagerService-backed flow preserves the existing business semantics.

Also applies to: 216-274, 276-310, 373-488

apps/api/src/billing/services/managed-signer/managed-signer.service.ts (2)

13-57: TxManagerService injection and helper methods keep signing logic centralized

Injecting TxManagerService and introducing executeDerivedTx / executeFundingTx to wrap sign/broadcast calls (with getFundingWalletAddress for the granter and consistent chainErrorService.toAppError handling) is a clean separation of concerns and removes direct dependency on lower-level signing clients from this service.

This design should make it easier to evolve signing/backoff behavior in one place without touching ManagedSignerService again.


59-61: Derived-by-user flow and tx result normalization align with the new signer abstraction

Routing executeDerivedEncodedTxByUserIdexecuteDerivedDecodedTxByUserIdexecuteDecodedTxByUserWalletexecuteDerivedTx(userWallet.id, messages) keeps user lookup, validations, and event logic unchanged while delegating the actual signing/broadcast to TxManagerService.

The normalization:

  • Picks { code, hash, transactionHash, rawLog } from the returned tx.
  • Ensures transactionHash is always populated, falling back to hash when needed.

This matches how the tests assert the shape of the result and should make callers resilient to minor differences in what the underlying client returns.

Also applies to: 119-144

stalniy
stalniy previously approved these changes Nov 20, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/api/src/billing/services/tx-manager/tx-manager.service.ts (1)

42-48: Consider simplifying the factory resolution.

As previously suggested, this registration could be simplified by directly chaining the resolution and call:

 container.register(FUNDING_SIGNING_CLIENT, {
   useFactory: instancePerContainerCachingFactory(c => {
-    const factory = c.resolve<BatchSigningClientServiceFactory>(BATCH_SIGNING_CLIENT_FACTORY);
-    return factory(c.resolve(FUNDING_WALLET), "FUNDING_SIGNING_CLIENT");
+    return c.resolve(BATCH_SIGNING_CLIENT_FACTORY)(c.resolve(FUNDING_WALLET), "FUNDING_SIGNING_CLIENT");
   })
 });
🧹 Nitpick comments (1)
apps/api/src/billing/services/tx-manager/tx-manager.service.ts (1)

104-106: Consider the visibility of getDerivedWallet.

This method is currently public, which exposes direct wallet instance access. If this is only used internally (by getDerivedWalletAddress), consider making it private or protected to better encapsulate the implementation. However, if external consumers or tests need direct wallet access, the current public visibility is appropriate.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e703e9 and 12a1b07.

📒 Files selected for processing (7)
  • apps/api/src/billing/lib/wallet/wallet.ts (0 hunks)
  • apps/api/src/billing/providers/index.ts (0 hunks)
  • apps/api/src/billing/providers/signing-client.provider.ts (0 hunks)
  • apps/api/src/billing/providers/wallet.provider.ts (0 hunks)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.spec.ts (1 hunks)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.ts (1 hunks)
  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts (2 hunks)
💤 Files with no reviewable changes (4)
  • apps/api/src/billing/providers/signing-client.provider.ts
  • apps/api/src/billing/providers/wallet.provider.ts
  • apps/api/src/billing/providers/index.ts
  • apps/api/src/billing/lib/wallet/wallet.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/src/billing/services/tx-manager/tx-manager.service.spec.ts
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
📚 Learning: 2025-11-19T15:15:07.266Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.266Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.

Applied to files:

  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts
📚 Learning: 2025-07-24T17:00:52.361Z
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.

Applied to files:

  • apps/api/test/functional/sign-and-broadcast-tx.spec.ts
🧬 Code graph analysis (1)
apps/api/src/billing/services/tx-manager/tx-manager.service.ts (4)
apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts (2)
  • BatchSigningClientService (57-360)
  • SignAndBroadcastOptions (24-34)
apps/api/src/billing/lib/wallet/wallet.ts (1)
  • Wallet (7-65)
apps/api/src/billing/providers/type-registry.provider.ts (1)
  • TYPE_REGISTRY (34-34)
apps/api/src/billing/lib/signing-stargate-client-factory/signing-stargate-client.factory.ts (1)
  • createSigningStargateClient (57-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: test-build
🔇 Additional comments (6)
apps/api/test/functional/sign-and-broadcast-tx.spec.ts (2)

4-4: Importing fetch-mock here is appropriate for native fetch tests

Using fetch-mock instead of nock matches the project convention for mocking native Node 18+ fetch in this test; the import is correctly scoped and used below, no extra changes needed.

Based on learnings


121-128: Fetch-mock setup/teardown around RPC node calls looks correct

blockNode’s fetchMock.mockGlobal().route(RPC_NODE_ENDPOINT, { code, message }) plus unblockNode’s fetchMock.hardReset() gives a clean, isolated mock of the RPC endpoint and restores global fetch after each use (via the try/finally in the test), which aligns with fetch-mock 12’s recommended pattern. Just ensure the installed fetch-mock version supports mockGlobal and hardReset (12.0.0+/12.2.0+).

Based on learnings

apps/api/src/billing/services/tx-manager/tx-manager.service.ts (4)

64-70: LGTM!

Both methods provide clean, straightforward delegation to the underlying wallet and signing client. The public API surface is well-designed.


72-83: Excellent cleanup logic in the finally block.

The conditional cleanup strategy is well-designed:

  • Prevents memory leaks by removing idle clients
  • Preserves active clients that have pending transactions
  • Logs cleanup events for observability
  • Uses finally to ensure cleanup runs even on errors

This approach effectively balances memory management with performance for frequently-used wallets.


89-102: Cache management implementation is solid.

The lazy client creation and caching strategy is well-implemented:

  • Efficiently reuses clients for the same derivation index
  • Logs client creation for debugging
  • Non-null assertion on line 101 is safe within this controlled context

16-22: Funding wallet index choice is not a concern.

The review comment's concern about separation is based on a misunderstanding. The FUNDING_WALLET and DERIVED_WALLET_FACTORY use different mnemonics ("FUNDING_WALLET_MNEMONIC" vs "DERIVATION_WALLET_MNEMONIC"), so they generate completely separate accounts regardless of index. The choice of index 1 for the funding wallet (versus 0) is a design decision but not related to wallet separation. Separation is already guaranteed by the mnemonic selection.

Likely an incorrect or invalid review comment.

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.

2 participants

Comments