Skip to content

Conversation

@ertemann
Copy link
Contributor

Still a ton of issues, packages not at all ready.

  • UI is separated and provided by the user or wallets are autoselected
  • config determines mode, aa-api url and more
  • connect to localhost of: https://github.com/burnt-labs/account-abstraction-api/pull/83 to use this branch
  • adds a demo app that uses direct signer and adds its own UI modal
  • Connects to EarnOs for Trying turnkey (still very broken) - https://github.com/earn-os/earnos/pull/132
  • Can use a different AA-api and later could also add local mode for users signing/submitting themselves or some worker doingit

Creation, persistency etc all works for wallets and in the demo app, its now aboyt converting this to the EarnOs turnkey setup and cleaning up the packages and needed utils to make it work.

!!! - This comes from a branch prior to loading states merge so that has to be reimplemented/rebased still

@changeset-bot
Copy link

changeset-bot bot commented Oct 15, 2025

🦋 Changeset detected

Latest commit: a521968

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@burnt-labs/account-management Minor
@burnt-labs/abstraxion-core Minor
@burnt-labs/abstraxion Minor
@burnt-labs/constants Minor
@burnt-labs/signers Minor
demo-app Patch
@burnt-labs/abstraxion-react-native Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ertemann
Copy link
Contributor Author

base version already works through dashboard here: https://github.com/burnt-labs/xion-dashboard-app/pull/278

This PR is to disintermediate the dashboard.

@ertemann ertemann changed the title WIP - Allowing local and direct signer methods in signer.js - Wallet/Turnkey support WIP - Allowing local and direct signer methods in xion.js - Wallet/Turnkey support Oct 24, 2025
…need a ton more cleanup, demi app needs through check on, need to make more general utillities around the signing behaviour, need to add ed25119 signing method, need to fix the window.... calling for wallets, persitency for sessions works but local signer method with turnkey is still funky.
@ertemann ertemann force-pushed the extend-xionjs-to-forego-the-dashboard-flow-if-not-stytch-eng-1330 branch from 88a824c to 2842c25 Compare October 24, 2025 12:32
…direct mode barring grant warnings and removing logs. finalize demo app and split abstraxion providers, REMOVE direct signer as implementation eas bad
…query indexer, solve daodao indexer url issue, correctly manage client creation, simplify turnkey create wallet, handle double logout
- Remove direct mode (CosmosWalletConnector, EthereumWalletConnector)
- Add controller pattern (BaseController, RedirectController, SignerController)
- Add orchestrator pattern with flow modules (accountConnection, grantCreation,
  redirectFlow, sessionRestoration)
- Add state machine for predictable state management
- Reorganize account-management and grants code structure
- Move SignerConfig to abstraxion-core (fix circular dependency)
- Add signature utilities to signers package
- Remove old authentication components and hooks
- Improve type safety and error handling
*
* Uses local address calculation (no API call needed for prepare step)
*/
export async function createEthWalletAccount(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

File can be expanded to include passkeys, ED25519 and more for direct/signermode.

Logs to be removed if full implementation is tested conculsively

* Completes login after redirect callback and returns keypair and granter.
* Specifically designed for redirect flow to avoid reading from storage (prevents Client/Server inconsistencies).
*
* @returns {Promise<{ keypair: SignArbSecp256k1HdWallet; granter: string } | undefined>}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Simplifies the state management on returning from redirect, localstorage not always directly accesible so returning them solves this issue for SSR frameworks.

I tried verifyoiing that this is 100% secure, afaik it is but some checking wouldnt hurt.

* Create account via AA API v2 for JWT
* POST /api/v2/accounts/create/jwt
*/
export async function createJWTAccountV2(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

not used for now

Copy link
Contributor

Choose a reason for hiding this comment

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

Just remove it. JWT will be an internal only thing. If we make it available, we can make another release around it.

@@ -0,0 +1,59 @@
/**
Copy link
Contributor Author

Choose a reason for hiding this comment

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

it would be nice to just share these types with the account-abstraxion-api if this is possible

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the entire UI component setup that did:

Abstraxion (hook) --> Modal --> Signing/error/loading.

We now only have the context and the actual hooks to use abstraxion. There is no UI, just clear loading states people can use to show their own.

useEffect(() => {
const searchParams = new URLSearchParams(window.location.search);
const isAuth = searchParams.get("granted") === "true";
const unsubscribe = controller.subscribe((newState) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

using separate state management now so that we dont have 10s of useEffects handling these states which was very error prone. Works best if people dont use SSR frameworks but also navigates around that.

This also makes the intergation with react-native easier so we dont have to duplicate changes and this managament

);

// Create account strategy
const accountStrategy = createCompositeAccountStrategy({
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is a small discussion to be had about how and if we want to expose our indexers for people to use. EarnOs will need them if they want to get the most reliable version of the signer-mode. Else everything will fall back to using RPC through a new method added in account-management.

feeGranter: config.feeGranter,
} : undefined;

// TODO: review this logic or change dashboard
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should make a decision here on the expected logic or Alter the dashboard. Especially if latewr we introduce local mode where people might pay for gas themselves somehow.

"dependencies": {
"@burnt-labs/abstraxion-core": "workspace:*",
"@burnt-labs/signers": "workspace:*",
"@cosmjs/cosmwasm-stargate": "^0.36.0",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

should we match cosmjs versions accross all packages?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we enforce this via CI somehow?


const authenticatorIndex = matchingAuthenticator?.authenticatorIndex ?? 0;

console.log(`${logPrefix} ✅ Found existing account:`, {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Many logs like these still exist to prove the flow and provide feedback, will be removed once we merge.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably use a logger package anyway. I'll put a ticket in for that.

// Use configured codeId (same as AA API and Dashboard)
return [{
id: calculatedAddress,
codeId: this.config.codeId,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

couldnt reliably get this from the chain so its now required for Signer-mode.

authenticatorType = AUTHENTICATOR_TYPE.JWT;
} else if (authenticatorData.Passkey) {
authenticatorString = authenticatorData.Passkey.credential_id;
authenticatorType = AUTHENTICATOR_TYPE.Passkey;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Much of this is to be tested fully when moving the dashboard to use these utils instead of its own code.

Most of these hooks and strats are 1/1 copies with some better type safety or structure so it should be good but cant be tested until we move over the dashboard.

return await connectionResult.signMessage(hexMessage);
};

const result = await createEthWalletAccount(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

when dashboard moves to this code we can expand this with JWT,passkey and other options or create separate flows.

includeDirectQuery: true,
});

const threeMonthsFromNow = BigInt(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I took this from the dashboard but it seems to me this should be more defined.

Copy link
Contributor

Choose a reason for hiding this comment

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

Like configurable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, kinda strange we are just making all session keys work for 3 months even if logged out etc.

@ertemann ertemann changed the title WIP - Allowing local and direct signer methods in xion.js - Wallet/Turnkey support Allowing local and direct signer methods in xion.js - Wallet/Turnkey support Nov 10, 2025
@ertemann ertemann changed the title Allowing local and direct signer methods in xion.js - Wallet/Turnkey support Allowing signer methods in xion.js - Wallet/Turnkey support Nov 10, 2025
@ertemann ertemann marked this pull request as ready for review November 10, 2025 14:43
@ertemann
Copy link
Contributor Author

TODO:

Extensive test coverage
React-native rewrite


if (grantsExist) {
// Grants already exist - return success
return { success: true };

Choose a reason for hiding this comment

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

Question. Here we are checking if grants exist in storage and then returning true if we find them. Could we run into an issue if grants have changed? Like if grants were added or removed in the developer portal, would this effect the user in anyway besides just showing stale grants?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the creation flow, meaning the grants have literally just run. This is why it skips over validation.

Youll see that on session restoration etc it does run "authenticate" which checks for the grants existing from that granter address and being valid with the treasury contract.

To be clear this only works with the treasury contract configured, not with legacy permissions.

However as mentioned aboce in a comment all grants are valid for 3 weeks. so if permissions are removed alll it can do is logout and force you to make new session keys. which is what it does.

Nonetheless this is a good integration test i should create.

@ertemann
Copy link
Contributor Author

@claude

@ertemann
Copy link
Contributor Author

@claude can you take a look?

@claude
Copy link

claude bot commented Nov 18, 2025

Claude finished @ertemann's task —— View job


Code Review ✅

I've completed a comprehensive review of this large PR. This is an ambitious architectural refactoring that adds signer mode support alongside the existing redirect flow. Here are my findings:


🏗️ Architectural Assessment

Strengths:

  1. Clean separation of concerns - The new controller pattern (RedirectController, SignerController, BaseController) provides a solid abstraction for different authentication flows
  2. State machine approach - Using a reducer pattern for state management (packages/account-management) is much more predictable than the previous useEffect-heavy approach
  3. New packages well-organized - The account-management package provides good reusable abstractions for account discovery, grant management, and orchestration
  4. Connector abstraction - The ExternalSignerConnector provides a clean interface for integrating external signers (Turnkey, Privy, etc.)

Concerns:

  1. Size and scope - This is a massive PR (23k+ additions, 19k+ deletions, 100 files) that would benefit from being broken down into smaller, reviewable chunks
  2. Missing tests - You noted "extensive test coverage" as a TODO, but this is critical given the security-sensitive nature (auth, session management, grants)
  3. Breaking changes - Removing the entire UI layer from @burnt-labs/abstraxion is a major breaking change that needs clear migration docs

🔒 Security Review

High Priority Issues:

1. Session Management Security (packages/abstraxion-core/src/AbstraxionAuth.ts:660)
You flagged this yourself - returning session data via URL params needs careful security review:

const urlGranter = await this.redirectStrategy.getUrlParameter("granter");
const granter = storedGranter || urlGranter;
  • Risk: If URL parameters are being used to restore sessions, ensure they can't be manipulated
  • Recommendation: Validate that URL params are only used on initial redirect callback, not for arbitrary session restoration

2. Grant Expiration Hardcoded (packages/account-management/src/orchestrator/flow/grantCreation.ts:112-116)

const threeMonthsFromNow = BigInt(
  Math.floor(
    new Date(new Date().setMonth(new Date().getMonth() + 3)).getTime() / 1000,
  ),
);
  • Issue: All grants valid for 3 months regardless of logout, as you noted
  • Recommendation: Make this configurable and document the security implications

3. Account Creation Signature Validation
Good signature formatting/validation in ExternalSignerConnector.ts:

// packages/abstraxion-core/src/connectors/ExternalSignerConnector.ts:93-94
return formatEthSignature(signature);

✅ Validates signature length and format - good!

4. Error Messages Leaking Info (packages/abstraxion-core/src/api/client.ts:20-38)
The parseApiError function may expose sensitive details from API responses. Consider sanitizing error messages for production.


🐛 Code Quality Issues

Console Logs (HIGH - Remove before merge)

Found 23 files with console.log/warn/error statements. Examples:

Debugging logs to remove:

  • packages/account-management/src/accounts/discovery.ts:63 - "✅ Found existing account"
  • packages/abstraxion-core/src/api/createAccount.ts:40-70 - Multiple creation logs
  • packages/account-management/src/orchestrator/flow/grantCreation.ts:322 - Transaction hash logs

Review comments already flag some (packages/account-management/src/accounts/discovery.ts), but this is widespread.

Recommendation:

  • Keep only essential error logging (console.error)
  • Remove all debug/info logs (console.log)
  • Consider using a proper logger library (as justinbarry mentioned)

Type Safety Issues:

1. Type assertions that bypass safety:

// packages/abstraxion/src/components/AbstraxionContext/index.tsx:87-95
const accountInfo: AccountInfo = {
  keypair: (restorationResult as { restored: true } & AccountInfo).keypair,
  granterAddress: (restorationResult as { restored: true } & AccountInfo).granterAddress,
  // ...
};

This pattern appears in multiple places. Consider using type guards or restructuring types to avoid assertions.

2. Missing error types:

// packages/abstraxion-core/src/connectors/ExternalSignerConnector.ts:137
} catch (error: any) {
  throw new Error(`Failed to connect to ${this.config.name}: ${error.message || error}`);
}

Using any for errors loses type safety. Use unknown and type check.


📝 Specific File Reviews

packages/abstraxion/src/controllers/SignerController.ts

Good:

  • Clear initialization flow
  • Proper error handling with state transitions
  • Good separation between connector and orchestrator

Issues:

  • Lines 119, 186, 214: console.error calls should use a logger
  • Line 202: updateGetSignerConfig() is clever but adds complexity - document the usecase better

packages/abstraxion/src/components/AbstraxionContext/index.tsx

Good:

  • Clean state derivation from controller
  • Proper ref usage to persist controller
  • Good handling of SSR considerations

Issues:

  • Lines 206, 212: console.log calls should be removed
  • Lines 116-144: Complex ref/config comparison logic is hard to follow - could benefit from a helper function
  • Line 152: TODO comment about useEffect - should this be addressed?

packages/account-management/src/orchestrator/flow/grantCreation.ts

Good:

  • Comprehensive grant creation flow
  • Good fallback logic for treasury vs manual grants
  • Storage abstraction for RN compatibility

Issues:

  • Line 112: Hardcoded 3-month expiration (security concern noted above)
  • Line 166-173: Type assertion as any bypasses validation
  • Line 192: Error swallowing with console.warn - should surface to user?

packages/abstraxion-core/src/api/createAccount.ts

Issues:

  • Lines 40, 66, 97, 122: Multiple console.log statements to remove
  • Missing JSDoc for public functions beyond params
  • Consider extracting signature formatting logic to avoid duplication

packages/abstraxion/src/utils/controllerFactory.ts

Issues:

  • Line 76-77: Comment about type safety seems defensive - if types match, no comment needed
  • Lines 121-130: TODO comment + complex fallback logic needs clarification (you've flagged this)
  • Line 102-106: Error could be more descriptive about why feeGranter is needed

🔍 Review Comment Follow-ups

Addressing your own review comments:

  1. JWT removal (client.ts:160) - ✅ justinbarry confirmed removal - do it
  2. CosmJS version consistency - ✅ justinbarry wants this - should be enforced
  3. CI enforcement of versions - justinbarry asked about this - would be valuable
  4. Logs removal - Multiple comments about removing logs - critical before merge
  5. Treasury dashboard logic (controllerFactory.ts:121) - Needs decision and documentation
  6. Grant expiration - You're right, should be configurable (grantCreation.ts:112)

What's Working Well

  1. Connector abstraction - Clean interface, easy to add new wallet types
  2. Error handling in flows - Generally good try/catch patterns with meaningful messages
  3. TypeScript usage - Good use of union types, interfaces, and generics overall
  4. Documentation - Good JSDoc comments on most public interfaces
  5. Strategy patterns - Account discovery and treasury query strategies are extensible

🚨 Blockers Before Merge

  1. Remove all debug console logs (23 files affected)
  2. Add test coverage for:
    • Session restoration flows
    • Grant creation/validation
    • Controller state transitions
    • Signature validation
    • Error handling paths
  3. Security review of session/grant management
  4. Migration guide for breaking UI changes
  5. Decide on open TODOs in code comments

📋 Recommendations

High Priority:

  1. Split this PR - Consider breaking into:
    • Part 1: State machine + controller architecture (no signer mode yet)
    • Part 2: Signer mode implementation
    • Part 3: UI removal + migration
  2. Add integration tests - Test the full flows end-to-end
  3. Remove console logs - Use a logger or remove entirely
  4. Document breaking changes - Users need migration guides
  5. Security audit - External review of session/grant handling

Medium Priority:

  1. Consistent error handling - Use unknown instead of any for errors
  2. CI checks - Add version consistency checks for cosmjs packages
  3. Type safety improvements - Remove as any assertions
  4. Configuration validation - Add runtime validation of configs
  5. Performance testing - New orchestration flows add complexity

Low Priority:

  1. Cleanup TODOs - Resolve or ticket outstanding TODO comments
  2. Consistent naming - Some inconsistency in "authenticator" vs "signer" terminology
  3. Bundle size - New packages add weight, consider code splitting
  4. Documentation - Add architecture decision records (ADRs) for major changes

🎯 Summary

This is solid architectural work that will enable important use cases (Turnkey, wallet integrations). The controller pattern and state machine approach are big improvements. However:

  • The PR is too large to review safely
  • Console logs everywhere need cleanup
  • Security-sensitive code needs external audit
  • Test coverage is critical before shipping
  • Breaking changes need clear communication

I recommend breaking this into smaller PRs and adding comprehensive tests before proceeding. The architecture is sound, but the execution needs more rigor given the security implications.


Files reviewed: 20+ core files across abstraxion, abstraxion-core, and account-management packages
|

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.

4 participants