device-signer: added support for device signer#1602
device-signer: added support for device signer#1602guilleasz-crossmint merged 27 commits intowallets-v1from
Conversation
🦋 Changeset detectedLatest commit: 60cd5d3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 8 packages
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 |
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🔥 Smoke Test Results |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…m:Crossmint/crossmint-sdk into guillea/wal-9094-create-sdk-device-signer
Additional Comments (1)
The The function signature also only accepts Prompt To Fix With AIThis is a comment left during a code review.
Path: packages/client/react-base/src/providers/CrossmintWalletBaseProvider.tsx
Line: 300-307
Comment:
**`getWallet` missing `deviceSignerKeyStorage` in options**
The `getWallet` callback does not pass `deviceSignerKeyStorage` through `options`, unlike `getOrCreateWallet` (line 260). When a user calls `getWallet` with a device signer, the `toInternalSignerConfig` method in `wallet-factory.ts` will call `options?.deviceSignerKeyStorage?.getKey(...)` which will evaluate to `undefined`, causing it to throw `"Device signer not found"`.
The function signature also only accepts `Pick<WalletArgsFor<C>, "chain" | "signer">`, which excludes `options` entirely. To support device signers via `getWallet`, you would need to either expand the accepted props to include `options` or find another way to thread `deviceSignerKeyStorage` through.
How can I resolve this? If you propose a fix, please make it concise. |
…ge.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Additional Comments (2)
This applies to both Prompt To Fix With AIThis is a comment left during a code review.
Path: packages/client/react-base/src/providers/CrossmintWalletBaseProvider.tsx
Line: 276-287
Comment:
**Missing `deviceSignerKeyStorage` in dependency arrays**
`deviceSignerKeyStorage` is captured inside both the `getOrCreateWallet` callback (line 263) and the `getWallet` callback (line 309), but it is not listed in either dependency array. If the prop changes, these callbacks will continue using the stale reference from the previous render.
This applies to both `getOrCreateWallet` (here) and `getWallet` (line 318-325).
```suggestion
[
crossmint,
experimental_customAuth,
walletStatus,
wallet,
resolveSignerConfig,
initializeWebViewIfNeeded,
updateCallbacks?.onWalletCreationStart,
updateCallbacks?.onTransactionStart,
clientTEEConnection,
callbacks,
deviceSignerKeyStorage,
]
```
How can I resolve this? If you propose a fix, please make it concise.
Same issue as Prompt To Fix With AIThis is a comment left during a code review.
Path: packages/client/react-base/src/providers/CrossmintWalletBaseProvider.tsx
Line: 318-326
Comment:
**Missing `deviceSignerKeyStorage` in `getWallet` deps**
Same issue as `getOrCreateWallet` — `deviceSignerKeyStorage` is used on line 309 but not in this dependency array.
```suggestion
[
crossmint,
experimental_customAuth,
resolveSignerConfig,
initializeWebViewIfNeeded,
clientTEEConnection,
callbacks,
deviceSignerKeyStorage,
]
```
How can I resolve this? If you propose a fix, please make it concise. |
…m:Crossmint/crossmint-sdk into guillea/wal-9094-create-sdk-device-signer
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…m:Crossmint/crossmint-sdk into guillea/wal-9094-create-sdk-device-signer
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…m:Crossmint/crossmint-sdk into guillea/wal-9094-create-sdk-device-signer
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…m:Crossmint/crossmint-sdk into guillea/wal-9094-create-sdk-device-signer
| private async saveDeviceSignerKeyIfNeeded( | ||
| address: string, | ||
| delegatedSigners: Awaited<ReturnType<typeof this.buildDelegatedSigners>>, | ||
| deviceSignerKeyStorage?: DeviceSignerKeyStorage | ||
| ) { | ||
| const deviceSigner = delegatedSigners.find( | ||
| (delegatedSigner): delegatedSigner is DelegatedSigner => | ||
| typeof delegatedSigner.signer === "string" && delegatedSigner.signer.startsWith("device:") | ||
| ); | ||
| if (deviceSigner && deviceSignerKeyStorage == null) { | ||
| throw new WalletCreationError("Device signer key storage is required for device signers"); | ||
| } | ||
| if (deviceSigner && deviceSignerKeyStorage) { | ||
| await deviceSignerKeyStorage.mapAddressToKey(address, deviceSigner.signer.split(":")[1]); | ||
| } | ||
| } |
There was a problem hiding this comment.
Missing unit tests for device signer validation logic
This PR adds substantial new validation and error handling logic across wallet-factory.ts, signers/index.ts, and device.ts — including checks for missing deviceSignerKeyStorage, admin signer restrictions, and key mapping — but no corresponding unit tests were added. The existing wallet-factory.test.ts has no coverage of device signer scenarios.
At minimum, tests should cover:
- Device signer as admin signer is rejected (line 172)
- Missing
deviceSignerKeyStoragethrows intoInternalSignerConfig(line 317) saveDeviceSignerKeyIfNeededcorrectly maps keys and throws when storage is missingassembleSignerthrows whendeviceSignerKeyStorageis null for device config
Context Used: Rule from dashboard - Add unit tests when implementing new validation logic or error handling features. (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/wallets/src/wallets/wallet-factory.ts
Line: 216-231
Comment:
**Missing unit tests for device signer validation logic**
This PR adds substantial new validation and error handling logic across `wallet-factory.ts`, `signers/index.ts`, and `device.ts` — including checks for missing `deviceSignerKeyStorage`, admin signer restrictions, and key mapping — but no corresponding unit tests were added. The existing `wallet-factory.test.ts` has no coverage of device signer scenarios.
At minimum, tests should cover:
- Device signer as admin signer is rejected (line 172)
- Missing `deviceSignerKeyStorage` throws in `toInternalSignerConfig` (line 317)
- `saveDeviceSignerKeyIfNeeded` correctly maps keys and throws when storage is missing
- `assembleSigner` throws when `deviceSignerKeyStorage` is null for device config
**Context Used:** Rule from `dashboard` - Add unit tests when implementing new validation logic or error handling features. ([source](https://app.greptile.com/review/custom-context?memory=9dc35ad5-5868-49a3-bbcb-a42edc5ee697))
How can I resolve this? If you propose a fix, please make it concise.* wallets: Add onCreateConfig support for delegated signer workflows (#1454)
* feat: add onCreateConfig support to separate admin and usage signers
- 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 <guille.a@paella.dev>
* fix: export OnCreateConfig and fix getChainType access
- Export OnCreateConfig from wallets SDK index
- Inline chainType logic in CrossmintWalletBaseProvider instead of accessing private method
Co-Authored-By: Guille <guille.a@paella.dev>
* refactor: remove args.delegatedSigners field (BREAKING CHANGE)
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 <guille.a@paella.dev>
* feat: make onCreateConfig required via WalletCreateArgs type
- 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 <guille.a@paella.dev>
* chore: fix lint issues
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: update demo apps to use onCreateConfig
- 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 <guille.a@paella.dev>
* fix: correctly mutate signer in validateExistingWalletConfig
- 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 <guille.a@paella.dev>
* fix: correctly mutate adminSignerConfig in createWallet
- Create tempArgs to capture mutation from mutateSignerFromCustomAuth
- Reassign adminSignerConfig from mutated tempArgs.signer
- Ensures external wallet signer reassignment works correctly
Co-Authored-By: Guille <guille.a@paella.dev>
* remove unnecesary type
* reuse common functionality from get and create
* remove redundant comments
* fix tsc issue
* fix linter
* added client side specific get wallet
* fix signers and transactions
* fix delegated signer
* remove redundant check
* fix unit test
* make oncreateconfig optional
* remove unnecesary format changes
* unify getWallet functionality
* remove admin from name
* fix react provider
* remove unnecessary types
* remove optional param
* refactor: replace 'as any' with custom SmartWalletConfig type
- Create SmartWalletConfig type to properly type wallet.config
- Replace all 'as any' casts with SmartWalletConfig type
- Improve error message clarity by avoiding 'args' in developer-facing text
- Addresses PR feedback from Alberto
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: format error message to meet line length requirements
Co-Authored-By: Guille <guille.a@paella.dev>
* add passkey logic to delegate signer comparison
* fix wallet with multiple passkey signers
* remove console.log
* appplied albertos comment
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix merge conflict change
* add change set
* feat(wallets): add shadow signer support for automatic delegated signers (#1458)
* feat: add onCreateConfig support to separate admin and usage signers
- 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 <guille.a@paella.dev>
* fix: export OnCreateConfig and fix getChainType access
- Export OnCreateConfig from wallets SDK index
- Inline chainType logic in CrossmintWalletBaseProvider instead of accessing private method
Co-Authored-By: Guille <guille.a@paella.dev>
* refactor: remove args.delegatedSigners field (BREAKING CHANGE)
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 <guille.a@paella.dev>
* feat: make onCreateConfig required via WalletCreateArgs type
- 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 <guille.a@paella.dev>
* chore: fix lint issues
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: update demo apps to use onCreateConfig
- 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 <guille.a@paella.dev>
* fix: correctly mutate signer in validateExistingWalletConfig
- 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 <guille.a@paella.dev>
* fix: correctly mutate adminSignerConfig in createWallet
- Create tempArgs to capture mutation from mutateSignerFromCustomAuth
- Reassign adminSignerConfig from mutated tempArgs.signer
- Ensures external wallet signer reassignment works correctly
Co-Authored-By: Guille <guille.a@paella.dev>
* remove unnecesary type
* reuse common functionality from get and create
* remove redundant comments
* fix tsc issue
* fix linter
* added client side specific get wallet
* fix signers and transactions
* fix delegated signer
* remove redundant check
* fix unit test
* make oncreateconfig optional
* remove unnecesary format changes
* unify getWallet functionality
* remove admin from name
* fix react provider
* remove unnecessary types
* remove optional param
* feat(wallets): add shadow signer support for automatic delegated signers
- 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 <guille.a@paella.dev>
* fix: remove unused @ts-expect-error directive
Co-Authored-By: Guille <guille.a@paella.dev>
* refactor: replace 'as any' with custom SmartWalletConfig type
- Create SmartWalletConfig type to properly type wallet.config
- Replace all 'as any' casts with SmartWalletConfig type
- Improve error message clarity by avoiding 'args' in developer-facing text
- Addresses PR feedback from Alberto
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: format error message to meet line length requirements
Co-Authored-By: Guille <guille.a@paella.dev>
* refactor: remove Flow-specific check, let API handle incompatible chains
Co-Authored-By: Guille <guille.a@paella.dev>
* feat: use shadow signer as active signer for wallet instances
- Modified createWallet to set shadow signer as the active signer
- Updated getOrCreateWallet to use shadow signer when retrieving existing wallets
- Shadow signer now becomes the default signer instead of the one passed by the user
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: apply biome lint formatting
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: add localStorage checks for Node.js test environment
Co-Authored-By: Guille <guille.a@paella.dev>
* wip shadow
* remove support for evm
* add passkey logic to delegate signer comparison
* fix wallet with multiple passkey signers
* remove console.log
* remove all shadow passkey references
* appplied albertos comment
* differentiate wallet creation for stellar and solana
* fix shadow signer for stellar
* move signing shado logic to signer
* change shado signer option config
* move delegated signer logic to a new function
* abstract signature
* remove unnecessary change
* restructure folder
* improve has shadow signer condition
* fix import
* fix import
* fix vitest test in wallets package
* refactor: address PR feedback from Alberto
- 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 <guille.a@paella.dev>
* fix: apply biome formatting
Co-Authored-By: Guille <guille.a@paella.dev>
* applied comments
* added changeset
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* shadow-signers: Support for React Native (#1465)
* feat: add onCreateConfig support to separate admin and usage signers
- 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 <guille.a@paella.dev>
* fix: export OnCreateConfig and fix getChainType access
- Export OnCreateConfig from wallets SDK index
- Inline chainType logic in CrossmintWalletBaseProvider instead of accessing private method
Co-Authored-By: Guille <guille.a@paella.dev>
* refactor: remove args.delegatedSigners field (BREAKING CHANGE)
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 <guille.a@paella.dev>
* feat: make onCreateConfig required via WalletCreateArgs type
- 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 <guille.a@paella.dev>
* chore: fix lint issues
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: update demo apps to use onCreateConfig
- 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 <guille.a@paella.dev>
* fix: correctly mutate signer in validateExistingWalletConfig
- 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 <guille.a@paella.dev>
* fix: correctly mutate adminSignerConfig in createWallet
- Create tempArgs to capture mutation from mutateSignerFromCustomAuth
- Reassign adminSignerConfig from mutated tempArgs.signer
- Ensures external wallet signer reassignment works correctly
Co-Authored-By: Guille <guille.a@paella.dev>
* remove unnecesary type
* reuse common functionality from get and create
* remove redundant comments
* fix tsc issue
* fix linter
* added client side specific get wallet
* fix signers and transactions
* fix delegated signer
* remove redundant check
* fix unit test
* make oncreateconfig optional
* remove unnecesary format changes
* unify getWallet functionality
* remove admin from name
* fix react provider
* remove unnecessary types
* remove optional param
* feat(wallets): add shadow signer support for automatic delegated signers
- 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 <guille.a@paella.dev>
* fix: remove unused @ts-expect-error directive
Co-Authored-By: Guille <guille.a@paella.dev>
* refactor: replace 'as any' with custom SmartWalletConfig type
- Create SmartWalletConfig type to properly type wallet.config
- Replace all 'as any' casts with SmartWalletConfig type
- Improve error message clarity by avoiding 'args' in developer-facing text
- Addresses PR feedback from Alberto
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: format error message to meet line length requirements
Co-Authored-By: Guille <guille.a@paella.dev>
* refactor: remove Flow-specific check, let API handle incompatible chains
Co-Authored-By: Guille <guille.a@paella.dev>
* feat: use shadow signer as active signer for wallet instances
- Modified createWallet to set shadow signer as the active signer
- Updated getOrCreateWallet to use shadow signer when retrieving existing wallets
- Shadow signer now becomes the default signer instead of the one passed by the user
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: apply biome lint formatting
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: add localStorage checks for Node.js test environment
Co-Authored-By: Guille <guille.a@paella.dev>
* wip shadow
* remove support for evm
* add passkey logic to delegate signer comparison
* fix wallet with multiple passkey signers
* remove console.log
* remove all shadow passkey references
* appplied albertos comment
* differentiate wallet creation for stellar and solana
* fix shadow signer for stellar
* implement shadow signers for react native
* move signing shado logic to signer
* change shado signer option config
* move delegated signer logic to a new function
* abstract signature
* remove unnecessary change
* restructure folder
* improve has shadow signer condition
* fix import
* fix import
* move shadow signers
* fix naming
* fix vitest test in wallets package
* refactor: address PR feedback from Alberto
- 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 <guille.a@paella.dev>
* fix: apply biome formatting
Co-Authored-By: Guille <guille.a@paella.dev>
* move storage to rn package
* make shad signer work for react native
* applied comments
* added changeset
* cleanup PR
* change back to string
* revert chain change
* move back to usdc
* fix browser storage
* add changeset
* make browserstorage a string to inject in webview
* add all the == null missing
* move shadow signer to its own class
* fix imports
* applied comments
* avoid injectin javascript
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* device-signers: handle shadow signers as a separate signer type (#1483)
* device signer for solana working
* change shadow signer config
* improve isShadowSignerEnabled logic
* fix options
* improve signature type
* fix tsc issue
* added changeset
* fix passkey creation
* improve founding signer logic
* improve browser storage
* disable shadow signer
* fix build issues
* feat(wallets): remove owner parameter from client-side getOrCreateWallet calls (#1559)
BREAKING CHANGE: The owner field can no longer be specified in client-side
getOrCreateWallet calls. Owner is now determined from JWT authentication.
- Add validation in WalletFactory to throw WalletCreationError when owner is provided
- Create ClientSideWalletArgsFor and ClientSideWalletCreateArgs types
- Update CreateOnLogin type to use client-side types without owner
- Remove owner parameter from CrossmintWalletBaseProvider wallet creation
Addresses WAL-8180
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* device-signers: remove device signers code (#1590)
* remove device signers code
* fix lint
* remove related changesets
* restore change
* fix import
* fix method name
* fix unit tests
* device-signer: added support for device signer (#1602)
* add device signer config
* fix issues on device signer
* add changeset
* Update packages/wallets/src/wallets/wallet-factory.ts
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Update packages/wallets/src/wallets/wallet-factory.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* add device signer to all chains
* receive key storage as prop
* Update packages/wallets/src/utils/device-signers/DeviceSignerKeyStorage.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* add dependency to use callback
* throw error if admin signer is device signer
* Update packages/wallets/src/wallets/wallet-factory.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* don't use generic error
* apply greptile suggestion
* Update packages/wallets/src/wallets/wallet-factory.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix wait for signing email
* Apply suggestion from @greptile-apps[bot]
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* change savedevice signer method name
* add defensive check
---------
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* device-signer: create browser device signer storage communication layer with iframe (#1605)
* add device signer config
* fix issues on device signer
* add changeset
* Update packages/wallets/src/wallets/wallet-factory.ts
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Update packages/wallets/src/wallets/wallet-factory.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* add device signer to all chains
* receive key storage as prop
* Update packages/wallets/src/utils/device-signers/DeviceSignerKeyStorage.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* add dependency to use callback
* throw error if admin signer is device signer
* Update packages/wallets/src/wallets/wallet-factory.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* don't use generic error
* apply greptile suggestion
* Update packages/wallets/src/wallets/wallet-factory.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix wait for signing email
* added iframe key storage
* remove unnecessary change
* add changeset
* add origin validation
* Update packages/wallets/src/utils/device-signers/IframeDeviceSignerKeyStorage.ts
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* unmount iframe when provider is unmounted
* fix unit tests
---------
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* device-signers: Apply biometric policies in sdk (#1607)
* added biometric check
* send signature back to iframe
* panos comments
* device-signer Add device signer when not available in the device (#1609)
* add device signer to new device
* add changeset
* remove unnecessary code
* put ensure in a more general method
* apply ais comments
* apply comments
* remove reactive signer
* make biopolicy optional
* device-signer: Fix Solana Message for Device Signer (#1611)
* fix device signer solana
* add changeset
* added changset
* feat: add SDK logger decorator to device signer flows (#1612)
* feat: add SDK logger decorator to device signer key storage methods
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: add changeset for device signer logger decorator
Co-Authored-By: Guille <guille.a@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* udpate iframe urls
* feat: handle device signer IDB fatal errors with iframe reload and retry (#1613)
* feat: handle device signer IDB fatal errors with iframe reload and retry
- Detect 'indexeddb-fatal' error code from device signer iframe responses
- Add reloadIframe() with single-flight pattern to prevent concurrent reloads
- Split rpc() into rpc() + sendRpc() for clean retry flow
- On fatal IDB error: reload iframe and retry the operation once
- Throw descriptive error if fatal persists after reload
WAL-9179
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: add changeset for wallets package
Co-Authored-By: Guille <guille.a@paella.dev>
* Apply suggestions from code review
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Apply suggestions from code review
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* refactor: flatten nested if statements in sendRpc handler
Co-Authored-By: Guille <guille.a@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* auth: remove farcaster login (#1629)
* auth: remove farcaster login
Remove all Farcaster authentication code including:
- signInWithFarcaster method from CrossmintAuthClient
- FarcasterSignIn component
- FarcasterProvider component
- Farcaster icon
- FarcasterMetadata type
- 'farcaster' from LoginMethod union type
- @farcaster/auth-kit dependencies
- Farcaster test cases
- Farcaster from demo app loginMethods
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: update pnpm-lock.yaml after removing @farcaster/auth-kit
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Remove Dynamic crypto wallet authentication from Crossmint Auth (#1626)
* feat: remove Dynamic crypto wallet authentication from React UI
Remove the Dynamic (dynamic-xyz) integration for authenticating with
crypto wallets via Crossmint Auth. This removes:
- DynamicWalletProvider and DynamicContextProviderWrapper
- Web3 auth flow components (Web3AuthFlow, Web3AuthFlowButton, Web3Connectors)
- CryptoWalletConnectionHandler and transaction handling utils
- web3 login method variants from LoginMethod type
- experimental_externalWalletSigner from auth context
- All @dynamic-labs/* dependencies
- Dynamic-related tsup/esbuild configuration
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: add changeset for Dynamic wallet auth removal
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: update pnpm-lock.yaml after removing @dynamic-labs dependencies
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* feat: remove Dynamic Labs integration from quickstart-devkit demo app
- Remove @dynamic-labs/* imports and dependencies from package.json
- Remove EVMDynamicLabsProvider and SolanaDynamicLabsProvider components
- Remove DynamicLabsLoginButton and DynamicLabsLogoutButton components
- Delete useDynamicConnector hook
- Remove web3/web3:solana-only from loginMethods arrays
- Remove 'dynamic' case from QueryParamsProvider switch statements
- Clean up commented Dynamic references in home.tsx
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: remove stale web3 LoginMethod references from smart-wallet demo app
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: format smart-wallet providers.tsx for Biome lint
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: restore Dynamic Labs in quickstart-devkit as third-party provider
Keep Dynamic Labs integration in the quickstart-devkit demo app since it's
used as a third-party provider example. Only remove the web3 LoginMethod
type references (web3:solana-only, web3) from CrossmintAuthProvider props
since those types were removed from the SDK.
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: restore Dynamic checkout flow components in react-ui
Keep Dynamic Labs integration for checkout flows (CryptoWalletConnectionHandler,
transaction handlers) while removing it only from Crossmint Auth.
Restored:
- CryptoWalletConnectionHandler and transaction utils (EVM, Solana, SUI)
- DynamicContextProviderWrapper (used by checkout)
- dynamicChainToCrossmintChain utility
- @dynamic-labs/* dependencies in package.json
- Dynamic-related tsup/esbuild configuration
- noop.ts shim for Apple loader
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: restore original lockfile (no dependency changes needed)
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: update changeset to remove CryptoWalletConnectionHandler line
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: split getOrCreateWallet into separate get/create methods with device signer support (#1622)
* feat: split getOrCreateWallet into separate get/create methods, add device signer support, read-only wallets
- Remove getOrCreateWallet, add separate getWallet and createWallet methods (both work client+server)
- Make signer optional for read-only wallets (methods requiring signer throw immediately)
- Add device signer resolution logic in getWallet (3-step: check assigned, check device, leave empty)
- Add createDeviceSigner helper function for client+server device signer creation
- Support device signers with pre-existing locators in registerDelegatedSigners
- Add hasKey method to DeviceSignerKeyStorage for device signer lookup
- Export createDeviceSigner and DeviceSignerDescriptor from index
- Update tests for new API
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: add changeset for wallet API refactor
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: update downstream packages for optional signer in wallet API
Co-Authored-By: Guille <guille.a@paella.dev>
* Apply suggestion from @greptile-apps[bot]
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix syntax error
* fix: resolve BiometricPolicy type mismatch and use get-then-create pattern in provider
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: add early return guard for pre-resolved device signer locator and warn log on read-only fallback
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: address PR review comments - move adminSigner/delegatedSigners to top level, add biometricPolicy to createDeviceSigner, validate walletLocator server-side, check WalletNotAvailableError in provider, add alias to getWallet, combine filter+loop, return signer as-is in step 3, change to major version
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: format test file for biome lint
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: remove unnecessary 'as any' cast in external-wallet signer check
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: address review comments - simplify locator handling, use != null check, move locator validation to validateSignerCanUseWallet
Co-Authored-By: Guille <guille.a@paella.dev>
* add createDeviceSigner to sdk
* remove unused import
* refactor: migrate onCreateConfig to top-level adminSigner/delegatedSigners in quickstart app
Co-Authored-By: Guille <guille.a@paella.dev>
* applied Alberto's comments
* update lock file
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* refactor: rename adminSigner to recovery and delegatedSigners to signers (WAL-9286) (#1637)
* refactor: rename adminSigner to recovery and delegatedSigners to signers (WAL-9286)
SDK-facing naming change:
- adminSigner → recovery
- delegatedSigners → signers
- addDelegatedSigner() → addSigner()
- delegatedSigners() → signers()
API layer unchanged - still sends adminSigner/delegatedSigners to the API.
Backward-compatible deprecated aliases and method wrappers added.
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: add changeset for WAL-9286 signer terminology rename
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: correct changeset package name and update stale comment/method in registerDeviceSigner
Co-Authored-By: Guille <guille.a@paella.dev>
* refactor: remove all deprecated wrappers per review feedback
- Remove addDelegatedSigner() and delegatedSigners() deprecated methods from Wallet
- Remove AddDelegatedSignerOptions and AddDelegatedSignerReturnType deprecated type aliases
- Remove deprecated adminSigner/delegatedSigners fields from WalletCreateArgs
- Remove fallback logic in wallet-factory.ts and CrossmintWalletBaseProvider.tsx
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: remove remaining references to deprecated adminSigner/delegatedSigners in validateExistingWalletConfig
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: update changeset to major, fix stale error message, update generate-reference.mjs
Co-Authored-By: Guille <guille.a@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: remove biometric policy from device signers (#1638)
* refactor: remove biometric policy from device signers
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: add changeset for biometric policy removal
Co-Authored-By: Guille <guille.a@paella.dev>
* Apply suggestions from code review
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* refactor: revert changes to IframeDeviceSignerKeyStorage.ts and DeviceSignerKeyStorage.ts per review
Co-Authored-By: Guille <guille.a@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* readd owner error
* remove unused improts
* fix hasKey
* feat: remove customAuth (experimental_customAuth, experimental_setCustomAuth) (#1614)
* feat: remove customAuth (experimental_customAuth, experimental_setCustomAuth, CustomAuth type)
- Remove CustomAuth type and experimental_customAuth from Crossmint config
- Remove experimental_setCustomAuth from Crossmint and all providers
- Replace experimental_customAuth?.jwt with crossmint.jwt throughout
- Remove mutateSignerFromCustomAuth from WalletFactory
- Simplify resolveSignerConfig to not fallback to customAuth fields
- Update CrossmintAuthProvider (react-ui & react-native) to use setJwt
- Update tests to use setJwt instead of experimental_setCustomAuth
- Simplify CrossmintProvider proxy to only track jwt changes
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: add changeset for customAuth removal
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: update app-level files to use setJwt instead of experimental_setCustomAuth
- Update useFirebaseConnector to use setJwt
- Update usePrivyConnector (EVM + Solana) to use setJwt
- Update useDynamicConnector (EVM + Solana) to use setJwt
- Update headless-signing expo component to use user.email instead of experimental_customAuth
- Remove unused imports (VersionedTransaction, dynamicClient, dynamicSigner)
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: add crossmint.jwt to dependency arrays for createOnLogin reactivity
- Add crossmint.jwt to getOrCreateWallet useCallback deps so it recreates when JWT changes
- Add crossmint.jwt to createOnLogin useEffect deps to re-trigger wallet creation when JWT becomes available
- Fixes issue where crossmint (Proxy reference) is stable and doesn't trigger re-renders on JWT change
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* feat: adapt third-party auth patterns from PR #1339
- Update useDynamicConnector to use two-phase pattern (JWT sync + wallet creation with explicit signer config)
- Update usePrivyConnector with helper functions and signer type detection for direct wallet creation
- Add processedCreateOnLogin to CrossmintWalletProvider (react-ui) to inject email/externalWalletSigner from auth context
- Add guards in CrossmintWalletBaseProvider to prevent wallet creation with missing email/address
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* feat: add getOrCreateWallet to Firebase connector and remove createOnLogin from third-party providers
- Firebase connector now calls getOrCreateWallet with explicit email/phone signer from Firebase user
- Removed createOnLogin from EVMPrivyProvider, SolanaPrivyProvider, EVMDynamicLabsProvider, SolanaDynamicLabsProvider, EVMFirebaseProvider, SolanaFirebaseProvider
- Third-party providers now rely on connector hooks to call getOrCreateWallet directly
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* Apply suggestion from @devin-ai-integration[bot]
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: use != null checks instead of truthy checks in Firebase connector
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: remove stray closing brace in useSolanaDynamicConnector
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: avoid stale closure in processedCreateOnLogin email resolution
Return early after triggering getUser() and let the effect re-run
when authContext.user.email updates via the dependency array, instead
of awaiting getUser() and reading the stale closure value.
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: pass explicit email to getOrCreateWallet in expo headless-signing
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* default chain
* fix: adapt processedCreateOnLogin to optional signer type and remove externalWalletSigner
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* refactor: move processedCreateOnLogin logic to CrossmintWalletBaseProvider for shared react-ui/react-native usage
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Alberto Elias <hi@albertoelias.me>
* wallets: make device signer the default operational signer (#1646)
* feat(WAL-9287): make device signer the default operational signer
BREAKING CHANGE: Remove signer property from WalletArgsFor and WalletCreateArgs.
Device signer is now always set as the operational signer.
- Remove signer from WalletArgsFor type
- Make recovery required on WalletCreateArgs
- resolveDeviceSignerForGetWallet returns DeviceSignerConfig and passes to createWalletInstance
- Always include device signer in signers array on client-side createWallet
- Remove onChangeSigner callback, assembleSigner public method, mutateSignerFromCustomAuth
- Expose getWallet and createWallet separately on React provider (remove getOrCreateWallet from public API)
- getWallet accepts alias parameter
- Remove resolveSignerConfig from React provider
Co-Authored-By: Guille <guille.a@paella.dev>
* chore: add changeset for WAL-9287
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: update quickstart-devkit to use recovery instead of signer in createOnLogin
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: address PR review comments for WAL-9287
- Rename createWalletFn to createWallet
- Use ClientSideWalletCreateArgs for createWallet context type
- Fix passkey check to use recovery.type instead of showPasskeyHelpers alone
- Restore resolveSignerConfig for recovery signer
- Restore initializeWebViewIfNeeded for recovery signer
- Extract buildWalletOptions helper with deep merge of experimental_callbacks
- Remove jwt null check from createWallet
- Restore experimental_callbacks override via buildWalletOptions
- Restore mutateSignerFromCustomAuth for recovery signer in wallet-factory
- Use createArgs.recovery directly in validateExistingWalletConfig
- Switch to recovery signer before addSigner in ensureDeviceSignerReady
- Export WalletOptions type from wallets SDK
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: add in-progress guard to createWallet to prevent concurrent calls
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: address additional PR review comments
- Restore jwt null check with in-progress guard on createWallet
- Add resolveSignerConfig/initializeWebViewIfNeeded for wallet.recovery in getWallet
- Add public recovery getter on Wallet class
- Fix ensureDeviceSignerReady: remove finally block, reassemble device signer outside !isRegistered
- Fix JSDoc on mutateSignerFromCustomAuth
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: format dependency array for lint compliance
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: pass onAuthRequired through options.experimental_callbacks
- Add onAuthRequired to Callbacks type in WalletOptions
- In ensureDeviceSignerReady, include onAuthRequired from options when building recovery signer
- In React provider buildWalletOptions, pass wrappedOnAuthRequired through callbacks
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: update getWallet to set wallet and status state
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: format onAuthRequired line for lint compliance
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: remove onAuthRequired from signer config, keep only in options; restore createOnLogin guard
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: add locator to EmailSignerConfig and PhoneSignerConfig to match API response
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: use ClientSideWalletArgsFor for getWallet args in React provider
Co-Authored-By: Guille <guille.a@paella.dev>
* fix: remove unused WalletArgsFor import
Co-Authored-By: Guille <guille.a@paella.dev>
* change onAuthrequiered source
* fix recovery signers
* expose createDeviceSigner
* added jsdoc
* apply devin comments
* fix type error
* fix: correct JSDoc on recovery getter
Co-Authored-By: Guille <guille.a@paella.dev>
* remove buildSigners
* fix linter
* apply comments
* fix dynamic connector
* fix connectors
* fix method to recovery
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* wallets-v1: added useSigner (#1650)
* added useSigner
* remove unnecessary change for passkey
* remove unnecessary key
* fix type errors
* fix unnecessary anys
* handle when initDeviceSigner fails
* non-device signers no need to recover
* fix passkey signer string
* restore original signer
* fix unit test
* fix linter
* change order for preAuthifneedd
* handle recovery concurrency
* improve error message
* feat: unify OTP signer API with useWalletOtpSigner hook (#1648)
* feat: unify OTP signer API with useWalletOtpSigner hook
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: rename sendOtpRef to sendEmailOtpRef, remove useWalletEmailSigner
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: remove experimental_ prefixes from wallets SDK (#1649)
* feat: remove experimental_ prefixes from wallets SDK
Renames:
- experimental_prepareOnly => prepareOnly
- experimental_callbacks => _callbacks
- experimental_loginWithOAuth => loginWithOAuth
- experimental_getNfts => nfts (wallet method), getNfts (API client)
- experimental_activity => transfers (wallet method), getTransfers (API client)
- experimental_signer => signer
- experimental_approval => approval
- experimental_transaction => transaction
- experimental_transactions => transactions
Updates all type definitions, wallet classes (EVM, Solana, Stellar),
API client, wallet factory, React providers, test files, and demo apps.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: add changeset for experimental prefix removal
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Apply suggestion from @greptile-apps[bot]
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Apply suggestion from @greptile-apps[bot]
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: update stale JSDoc on transfers() method
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* updates openapi json
* feat: migrate getTransfers to unstable list transfers API
- Update getTransfers() to use GET /api/unstable/wallets/{walletLocator}/transfers
- Add required params: tokens, status
- Replace legacy 2022-06-09 activity endpoint with unstable transfers endpoint
- Rename types: GetActivityResponse -> GetTransfersResponse, Activity -> Transfers
- Update types.ts imports to match regenerated OpenAPI types
- Update activity.tsx app to use new response shape (data[] instead of events[])
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: resolve build errors from OpenAPI spec update
- evm.ts: cast transaction params to CreateTransactionParams to satisfy union type discrimination
- wallet.ts: cast chain to RegisterSignerChain in addSigner() to match narrower DTO enum
- test-utils.ts: narrow fundWallet/fundWalletAndWait/ensureWalletFunded token param to 'usdxm' only (usdc removed from FundWalletAmountDto)
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: rename Activity to Transfers in react-ui and react-native exports
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: add RegisterSignerChain cast in addSigner after merge
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: add type-only import annotations (biome lint)
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Alberto Elias <hi@albertoelias.me>
* feat!: remove useAuth alias in favor of useCrossmintAuth (#1656)
BREAKING CHANGE: The useAuth export has been removed from all packages.
Use useCrossmintAuth instead, which provides the same functionality.
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* updates openapi json (#1664)
Co-authored-by: Alberto Elias <hi@albertoelias.me>
* release: enter beta prerelease mode (#1666)
Co-authored-by: Alberto Elias <hi@albertoelias.me>
* Merge server signers into wallets-v1 branch (#1660)
* Release packages (#1644)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* bt: change package (#1651)
* a
* change
* fix
* bt: upgrade again (#1654)
* a
* chaneg
* feat(hosted-checkout): add orderId + clientSecret support for pre-created orders (#1647)
* Add orderId + clientSecret support to hosted checkout
* Simplify URL param appending for hosted checkout v3
* Make fiat and crypto payment configs optional for existing orders
* Encode orderId in URL path to handle special characters securely
* Wallets SDK: Server signer (evm, stellar, solana) (#1643)
* Feat: add server key signers
* added solana and stellar support, cleaned up changes
* added changeset
* added tests
* update lockfile
* lint fix
* address Greptile review comments: hex validation, signer checks, docs
Co-Authored-By: Jonathan Derbyshire <jonathan.temp@paella.dev>
* fix: replace any cast with unknown, add base64 validation for stellar signer
Co-Authored-By: Jonathan Derbyshire <jonathan.temp@paella.dev>
* fix: enforce 64-char minimum secret length in key derivation
Co-Authored-By: Jonathan Derbyshire <jonathan.temp@paella.dev>
* fixed txn signing, and cleanup
* fix lint
* fix tests
* lint fix
* revert some signer wallet logic and cleanup
* reverted alias stuff
* cleanup
* add pragmatic server side env check
* fix messed up previous commits
* update schema to assume backend wallet changes
* fix lint
* update schema to align with backend changes
* add server signer type to delegate signer
* lint fix
* improved delegated signer check for server signers
* review feedback
* reverted type in openapi.json
* fix type issue breaking change revert
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Release packages (#1652)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fixed a few build issues surrounding server signer
* followup fix with server locator
* removed unused comment
* fixes linting
* ci: add wallets-v1 beta release workflow (#1665)
Co-authored-by: Alberto Elias <hi@albertoelias.me>
* fixes
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: mPaella <93682696+mPaella@users.noreply.github.com>
Co-authored-by: Pedro Pablo Aparicio <pedro.pablo@paella.dev>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Alberto Elias <hi@albertoelias.me>
Co-authored-by: Alberto Elias <alberto.elias@paella.dev>
* fix: prevent duplicate TEE initialization race condition in NonCustodialSigner (#1663)
* fix: prevent duplicate TEE initialization race condition in NonCustodialSigner
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: wrap initialize() in try/finally to clear _initializationPromise on failure
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Release beta packages (beta) (#1668)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* wallets: homogenize signer management with full objects and status (#1661)
* feat: homogenize signer management to always use full objects with status
- Update addSigner() to accept full signer config objects (SignerConfigForChain<C>) instead of locator strings
- Update addSigner() to return DelegatedSigner with approval status
- Update signers() to return full DelegatedSigner objects with per-chain status
- Add getSigner() API client method to fetch individual signer details
- For EVM wallets, filter out signers without approvals for the instantiated chain
- Add helper functions to map API responses to SDK DelegatedSigner types
- Export SignerStatus and DelegatedSigner types
- Update all tests to match new signer object structure
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: add changeset for signer management homogenization
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: use DistributiveOmit for union type in extractSignerBase
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: update quickstart-devkit permissions to use full signer objects
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: address review feedback - remove unused getSigners, add null guards, handle device signers
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: update changeset wording - signers filtered to instantiated chain
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* refactor: move signer mapping utils to dedicated file, add device variant to DelegatedSigner
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* refactor: move signer-mapping.ts to utils/
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: throw error when signer registration fails on EVM chain
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* Update packages/wallets/src/utils/signer-mapping.ts
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add server variant to DelegatedSigner type and extractSignerBase
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: special-case device signers with locator in addSigner input resolution
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: add RegisterSignerParams import and type assertion for signerInput
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* refactor: simplify signerInput resolution in addSigner
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Add NativeDeviceSignerKeyStorage with iOS/Android native bridge (#1653)
* Add @crossmint/expo-device-signer native module
* Align NativeDeviceSignerKeyStorage with wallets-v1 interface and wire up RN provider
* Regenerate lockfile after rebase onto wallets-v1
* fix: use recovery instead of signer in createOnLogin
* feat: Android BiometricPrompt integration for always policy keys
* feat: iOS DeviceSignerModule simulator biometric workaround
* chore(rn): address PR review comments - instantiate NativeDeviceSignerKeyStorage internally, remove biometric type exports
* feat(expo-device-signer): remove biometric support from native module (Android + iOS + TS)
* chore(expo-demo): add expo-device-signer dep + autolinking config, fix headless-signing component
* feat(android): replace inline KeyStorage with com.crossmint:sdk-device-signer:0.0.15
* Changed author on pdospec
* Undo BiometricRequestHandler removal from intdex.ts
* Clean up stale and biometric docs
* Replace KeychainKeyStorage with SoftwareDeviceSignerKeyStorage in iOS Expo module
* Untrack public key only after successful Keychain deletion
* Pin CrossmintDeviceSigner to tagged release 0.11.0
* Register device signer with wallet after creation in demo
* Remove nativeModulesDir relative path from demo app
* Remove debug logs from headless signing demo
* Clean up headless signing demo, remove test sign button
* Revert headless signing demo to original structure, swap email for device signer
* Remove headlessSigningFlow flag and add @hpke metro resolver to expo demo
* Add email OTP login alongside Google and switch to USDXM in expo demo
* Address Greptile review: optional dep, lazy import, wallet guard, dynamic hpke paths, Podfile assertions
* Fix Biome formatting errors
* Update lockfile for optionalDependencies change
* Fix Biome formatting on app.json and tsconfig.json
* Store public key index in Keychain instead of UserDefaults so it survives reinstall
* Device Signers: Skipping solana on initial wallet creation (#1667)
skipping solana
* ci: publish wallets-v1 from trusted workflow (#1669)
* ci: publish wallets-v1 from trusted workflow
* ci: remove duplicate wallets-v1 beta workflow
---------
Co-authored-by: Alberto Elias <hi@albertoelias.me>
* fix: check device signer approval instead of needsRecovery flag in recover() (#1662)
* fix: check device signer approval instead of needsRecovery flag in recover()
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: add changeset for wallets-sdk patch
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* small fixes
* fix: prevent duplicate TEE initialization race condition in NonCustodialSigner
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* revert: restore original tsconfig.json for wallets package
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* Revert "fix: prevent duplicate TEE initialization race condition in NonCustodialSigner"
This reverts commit 4f8ac9ff8c121136e2444b008267b4272f41c7cd.
* fix: add cached fast-path, remove redundant null check, update JSDoc in recover()
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* Update packages/wallets/src/wallets/wallet.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: remove duplicate brace, invalidate deviceSignerApproved cache when signer changes
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* refactor: use .type check instead of instanceof, remove device: guard, drop unused import
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Alberto Elias <hi@albertoelias.me>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* feat!: unified onSign callback for external wallets + prepareOnly pattern (#1657)
* feat!: unified onSign callback for external wallets + autoApprove pattern
- Replace chain-specific external wallet signer configs (provider/viemAccount for EVM, onSignTransaction for Solana, onSignStellarTransaction for Stellar) with unified onSign callback
- Use conditional TypeScript types: Solana gets (VersionedTransaction) => Promise<VersionedTransaction>, EVM/Stellar get (payload: string) => Promise<string>
- Invert prepareOnly to autoApprove: operations now prepare-by-default, pass autoApprove: true to auto-sign
- Create base ExternalWalletSigner class with chain-specific subclasses
- Update all tests to reflect new autoApprove semantics
BREAKING CHANGE: External wallet signer config now uses onSign instead of provider/onSignTransaction/onSignStellarTransaction. Default behavior is now prepare-only (was auto-approve).
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: update quickstart-devkit to remove prepareOnly (now prepare-by-default)
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: add autoApprove to consumer wallet.send() calls for completed transactions
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: update dynamic and privy connectors to use onSign instead of viemAccount/provider/onSignTransaction
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: format useDynamicConnector.tsx for biome lint
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* cleanup
* refactor: revert autoApprove pattern back to prepareOnly (auto-approve by default)
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* Apply suggestion from @greptile-apps[bot]
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* do get or create with 3rd party auth
* fixes prepareOnly check
* fix: address PR feedback - remove AutoApprove, simplify signer types, fix generic inference
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* style: fix biome formatting in usePrivyConnector.tsx
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: add useRef guard to prevent race condition in connector hooks
getWallet sets status to 'in-progress' then back to 'not-loaded' when
no wallet is found, which re-triggers the useEffect. Added isSyncingRef
guard to all 5 connector hooks (Firebase, EVM/Solana Privy, EVM/Solana
Dynamic) to prevent concurrent getWallet/createWallet calls.
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* feat!: make onSign required for external-wallet signer configs
onSign is no longer optional - external wallets must always provide
a signing callback. Removed null checks in signer implementations
since the type system now enforces this at compile time.
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: add ExternalWalletRegistrationConfig for addSigner/signers + guard useSigner for external-wallet locators
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: add runtime null guards for onSign, support useSigner with full config, fix build errors
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Alberto Elias <hi@albertoelias.me>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* WAL-9427: Fix useSigner carry over and chain status checks (#1674)
fix useSigner carry over, and chain status checks
* Rename: callbacks (#1673)
rename callbacks
* Release beta packages (beta) (#1670)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix: simplify null check in recover() and make apiClient public (#1676)
* fix: simplify null check in recover() and make apiClient public
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: add changeset
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* ci: prevent duplicate CI runs on wallets-v1 (#1678)
ci: exclude wallets-v1 from ci.yml to prevent duplicate CI runs
main.yml already handles wallets-v1 explicitly (with the release job),
so ci.yml was firing twice on every push to that branch.
Co-authored-by: Alberto Elias <hi@albertoelias.me>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Signer: Defaulting signer (#1675)
* defaulting the signer
* lint
* add changeset
* add selected signer again
* revert comment
---------
Co-authored-by: Maximiliano Schultheis <max@paella.dev>
* fix: make tokens and status optional in wallet.transfers() (#1681)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: normalize hex publicKey values to decimal for device signer comparison (WAL-9445) (#1684)
* fix: normalize hex publicKey values to decimal for device signer comparison
createDeviceSigner() returns publicKey.x/y as 0x-prefixed hex strings,
but the API stores them as decimal strings. During idempotency validation,
compareSignerConfigs compared these formats as plain strings and threw a
WalletCreationError mismatch.
Fixes WAL-9445
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: add changeset for WAL-9445 fix
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* refactor: scope hex normalization to publicKey coordinate fields only
Address review feedback: hex→decimal normalization now only applies when
the field path ends with .x or .y (publicKey coordinates), preventing
unintended normalization of Ethereum addresses or other hex identifiers.
Also improved test for non-hex strings and added tests ensuring
external-wallet addresses are compared as-is.
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* style: fix Biome line length formatting
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* device-signer: add device name to device signer (#1655)
* add name to device signer
* fix brave recognition
* update comment
* add name when recovering wallet
* fix createDeviceSigner public method
* remove unused import
* Update packages/wallets/src/utils/device-signers/createDeviceSigner.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix: implement getDeviceName in NativeDeviceSignerKeyStorage
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: update test assertion for new device signer format and add getDeviceName to mocks
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* feat: use expo-device APIs for real device name in NativeDeviceSignerKeyStorage
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* chore: update pnpm-lock.yaml for expo-device dependency
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* fix: pass device name/publicKey in addSigner recovery path and reorder expo-device fallback
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Alberto Elias <alberto.elias@paella.dev>
* fix: validate transfer amount to reject zero/negative values (WAL-9452) (#1682)
* fix: validate transfer amount to reject zero/negative values in wallet.send()
Adds client-side validation in wallet.send() to throw InvalidTransferAmountError
for zero, negative, or non-numeric transfer amounts before any on-chain call.
Fixes WAL-9452
Co-Authored-By: Alberto Elias <alberto.elias@paella.dev>
* Update packages/wallets/src/wallet…
Description
Added support for device signer in wallets-v1.
User can select device signer as signer and sign transactions with it.
It requires a
DeviceSignerKeyStoragethat is sent through optionsTest plan
Package updates
wallets-sdk: minor
react-base: minor