-
Couldn't load subscription status.
- Fork 29
feat(wallets): add shadow signer support for automatic delegated signers #1458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: wallets-v1
Are you sure you want to change the base?
feat(wallets): add shadow signer support for automatic delegated signers #1458
Conversation
- Add OnCreateConfig<C> type to wallets SDK types - Update WalletArgsFor<C> to include optional onCreateConfig field - Modify WalletFactory.createWallet() to use onCreateConfig admin signer when provided - Update validateExistingWalletConfig() to validate onCreateConfig parameters - Add validateSignerCanUseWallet() helper to ensure signer can use wallet - Add getSignerLocator() helper for determining signer locators - Remove server-side restriction from getWallet() method - Add comprehensive tests for onCreateConfig functionality - Update React Base SDK to export OnCreateConfig and support getWallet - Implement getWallet() in CrossmintWalletBaseProvider - Update getOrCreateWallet() to pass through onCreateConfig - Export OnCreateConfig type from React UI SDK This allows delegated signers to use the SDK by separating the concept of admin signer (who creates/owns the wallet) from usage signer (who interacts with it). Co-Authored-By: Guille <[email protected]>
- Export OnCreateConfig from wallets SDK index - Inline chainType logic in CrossmintWalletBaseProvider instead of accessing private method Co-Authored-By: Guille <[email protected]>
Breaking changes: - Remove delegatedSigners field from WalletArgsFor type - Remove delegatedSigners field from CreateOnLogin type - delegatedSigners now ONLY exist within onCreateConfig When onCreateConfig is provided: - args.signer = the signer that will USE the wallet (can be admin or delegated) - onCreateConfig.adminSigner = the admin who OWNS the wallet (only for creation) - onCreateConfig.delegatedSigners = delegated signers (only for creation) When onCreateConfig is NOT provided (backward compat): - args.signer acts as BOTH the admin and usage signer Updated: - WalletFactory validation logic to handle both cases - React providers to not pass delegatedSigners - Tests to only use onCreateConfig for delegated signers Co-Authored-By: Guille <[email protected]>
- Created WalletCreateArgs type that extends WalletArgsFor with required onCreateConfig - Updated getOrCreateWallet and createWallet to use WalletCreateArgs - Updated CreateOnLogin type to use WalletCreateArgs - Made onCreateConfig optional in WalletArgsFor for getWallet use cases - args.signer is now always the usage signer, not the admin signer Co-Authored-By: Guille <[email protected]>
Co-Authored-By: Guille <[email protected]>
- Updated smart-wallet/next, quickstart-devkit, and expo apps - All createOnLogin usages now include onCreateConfig with adminSigner - Delegated signers moved from top-level to onCreateConfig Co-Authored-By: Guille <[email protected]>
- Create tempArgs to capture mutation from mutateSignerFromCustomAuth - Reassign expectedAdminSigner from mutated tempArgs.signer - Ensures external wallet signer reassignment is captured correctly Co-Authored-By: Guille <[email protected]>
- Create tempArgs to capture mutation from mutateSignerFromCustomAuth - Reassign adminSignerConfig from mutated tempArgs.signer - Ensures external wallet signer reassignment works correctly Co-Authored-By: Guille <[email protected]>
- Add shadowSigner option to WalletOptions type - Create shadow-signer.ts utility for generating device-bound keypairs - Automatically generate shadow signers during wallet creation (client-side only) - Store shadow signer metadata in localStorage - Pass shadow signer configuration through React providers - Support ed25519 for Solana/Stellar and p256 passkeys for EVM chains - Gracefully handle shadow signer creation failures Co-Authored-By: Guille <[email protected]>
Original prompt from Guille2. Create Shadow Signer Generation UtilityFile: Create utilities for generating and storing shadow signers: import { WebAuthnP256 } from "ox";
import type { Chain } from "../chains/chains";
import type { DelegatedSigner } from "../wallets/types";
const SHADOW_SIGNER_STORAGE_KEY = "crossmint_shadow_signer";
export type ShadowSignerData = {
chain: Chain;
walletAddress: string;
publicKey: string;
createdAt: number;
};
export async function generateShadowSigner(
chain: Chain
): Promise<{ delegatedSigner: DelegatedSigner; ... (17104 chars truncated...) |
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
…sdk' of github.com:Crossmint/crossmint-sdk into guillea/wal-4751-allowing-delegated-signers-to-use-the-sdk
…sdk' into devin/wal-shadow-signers-1760630286
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments suggesting a refactor so the code lives closer to ncs-signer
packages/client/react-base/src/providers/CrossmintWalletBaseProvider.tsx
Outdated
Show resolved
Hide resolved
|
Thanks for the review @AlbertoElias! I understand the proposed refactor to move this into the NCS signer layer. Just to make sure I understand the architecture correctly:
A few questions before I proceed with the refactor:
Let me know if my understanding is correct and I'll proceed with the refactor! |
…devin/wal-shadow-signers-1760630286
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking really good! left some small comments, but leaving approved. remember to add changeset
packages/wallets/src/signers/non-custodial/ncs-stellar-signer.ts
Outdated
Show resolved
Hide resolved
| shadowSignerPrivateKey: CryptoKey | null; | ||
| }> { | ||
| const { | ||
| delegatedSigners: updatedDelegatedSigners, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would keep this called as delegatedSigners and the one below can have a more specific name for the changes/enhancements we do to signers
|
|
||
| const delegatedSigners = await Promise.all( | ||
| updatedDelegatedSigners?.map( | ||
| async (signer): Promise<DelegatedSigner | RegisterSignerParams | { signer: PasskeySignerConfig }> => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we should separate this to a separate function with a nice name to make it more declarative
- Replace all @ imports with relative imports - Change != null to == null for style consistency - Rename updatedDelegatedSigners to delegatedSigners for clarity - Extract delegated signer registration logic to registerDelegatedSigners method Co-Authored-By: Guille <[email protected]>
|
@AlbertoElias Thanks for the approval! I've addressed all your feedback: ✅ Fixed The refactoring makes the code more declarative and easier to maintain. All changes pushed! |
Co-Authored-By: Guille <[email protected]>
Description
This PR implements automatic "shadow" delegated signers for wallets created via
getOrCreateWallet. Shadow signers are device-bound keypairs (stored using Web Crypto API's non-extractable keys) that act as delegated signers, intended to allow transactions without requiring OTP authentication on the same device.Shadow signers are only added to Stellar and Solana wallets, a follow up PR will add it for EVM.
Important Notes:
shadowSigner: { enabled: false }to opt outChanges Made:
New
shadow-signer.tsutility:generateShadowSigner(): Creates device-bound keypairs using Web Crypto APIWalletFactory modifications:
React Provider updates:
shadowSignerprop toCrossmintWalletBaseProviderPropsTest plan
Manual tested in quickstart with solana and stellar wallets, no email otp was necessary for fulfilling transactions
Package updates
This are part of the delegated signers breaking changes, so it goes to the
wallets-v1branchSession Info: