cilantro-react 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,54 +1,171 @@
1
1
  # cilantro-react
2
2
 
3
- React SDK/UI for [Cilantro Smart Wallet](https://www.npmjs.com/package/cilantro-sdk). Provides providers, hooks, and UI components so you can add auth, wallets, signers, and signing flows without wiring the low-level SDK directly. Components use [Shadcn/UI](https://ui.shadcn.com)-style primitives and are customizable via `className` and `classNames`.
3
+ React SDK/UI for [Cilantro Smart Wallet](https://www.npmjs.com/package/cilantro-sdk). Provides a single context provider, hooks, and UI components for auth, wallets, signers, and transactions. Install as **cilantro-react**; documentation may show `@cilantro/react-sdk` for illustration—use `cilantro-react` in install and imports.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npm install cilantro-react cilantro-sdk react
8
+ npm install cilantro-react cilantro-sdk
9
+ # or
10
+ yarn add cilantro-react cilantro-sdk
11
+ # or
12
+ pnpm add cilantro-react cilantro-sdk
9
13
  ```
10
14
 
11
- **Peer dependencies:** `react` (^18.0.0 || ^19.0.0), `cilantro-sdk` (^0.0.40). For transaction signing and Solana helpers, optionally install `@solana/web3.js` (^1.98.0).
15
+ **Peer dependencies:** React 18+, `cilantro-sdk`. Optionally `@solana/web3.js` for transaction/signing. Components use Tailwind-compatible class names; ensure your app has [Tailwind CSS](https://tailwindcss.com) configured.
12
16
 
13
- **Styling:** Components use Tailwind CSS and Shadcn-compatible class names. Ensure your app has [Tailwind CSS](https://tailwindcss.com) configured; for theming, use your own Shadcn theme or CSS variables so styles apply correctly.
17
+ ## Polyfills (browser)
14
18
 
15
- ## Polyfills
16
-
17
- Import the SDK polyfills once before any SDK usage (e.g. in your app entry or root layout):
19
+ Import at the very top of your entry file (e.g. `main.tsx`, `App.tsx`):
18
20
 
19
21
  ```ts
20
22
  import 'cilantro-sdk/polyfills'
21
23
  ```
22
24
 
23
- ## Setup
24
-
25
- Wrap your app with `CilantroProvider` and pass your platform API key:
25
+ ## Wrap your app
26
26
 
27
27
  ```tsx
28
28
  import { CilantroProvider } from 'cilantro-react'
29
29
 
30
- export default function RootLayout({ children }: { children: React.ReactNode }) {
30
+ function Root() {
31
31
  return (
32
- <CilantroProvider platformApiKey="your-platform-api-key">
33
- {children}
32
+ <CilantroProvider
33
+ apiKey={import.meta.env.VITE_API_KEY}
34
+ baseURL="https://api.cilantro.gg"
35
+ >
36
+ <App />
34
37
  </CilantroProvider>
35
38
  )
36
39
  }
37
40
  ```
38
41
 
39
- **CilantroProvider props:**
42
+ ### Storage adapter (device keys)
43
+
44
+ For email and phone signers, device keys must be stored. Configure a storage adapter:
45
+
46
+ ```tsx
47
+ import { CilantroProvider, createIndexedDBAdapter } from 'cilantro-react'
48
+
49
+ const storage = createIndexedDBAdapter()
50
+
51
+ <CilantroProvider apiKey={API_KEY} storageAdapter={storage}>
52
+ <App />
53
+ </CilantroProvider>
54
+ ```
55
+
56
+ | Adapter | Use case |
57
+ |---------|----------|
58
+ | `createIndexedDBAdapter()` | Production – persistent, large capacity |
59
+ | `createLocalStorageAdapter()` | Development – simple, limited capacity |
60
+ | `createMemoryAdapter()` | Testing – not persisted |
61
+
62
+ **CilantroProvider props (guide API):**
40
63
 
41
64
  | Prop | Type | Description |
42
65
  |------|------|-------------|
43
- | `platformApiKey` | `string` | **Required.** Your Cilantro platform API key. |
44
- | `apiUrl` | `string` | Optional API base URL. |
45
- | `jwtStorageKey` | `string` | localStorage key for JWT (default: `cilantro_jwt`). |
46
- | `walletStorageKey` | `string` | localStorage key for selected wallet id (default: `cilantro_selected_wallet_id`). |
47
- | `onLoginSuccess` | `() => void` | Callback after successful login. |
48
- | `onLogout` | `() => void` | Callback after logout. |
49
- | `onRegisterSuccess` | `() => void` | Callback after successful registration. |
66
+ | `apiKey` | `string` | Platform API key (optional if using JWT via login). |
67
+ | `baseURL` | `string` | API base URL (default: `https://api.cilantro.gg`). |
68
+ | `storageAdapter` | `DeviceKeyStorage` | Storage for device keys (default: IndexedDB in browser). |
69
+ | `children` | `ReactNode` | App content. |
70
+
71
+ Backward compatibility: `platformApiKey` / `apiUrl` are still supported (deprecated). See [API reference](#api-reference) for full props.
72
+
73
+ **Connection:** The library does not create a Solana RPC connection. For transaction sign-and-send, pass your own `connection` from `@solana/web3.js` into `useTransactionSigning` / `TransactionSigningForm`. See [Connection setup](#connection-setup-solana) below.
74
+
75
+ ---
76
+
77
+ ## Display logic and form visibility
78
+
79
+ Message and transaction signing forms only show the actual form when **both** a wallet and a signer are selected:
80
+
81
+ - **Wallet selected:** Use `useWallets().selectedWallet` as the single source of truth. Derive `walletId` and `hasWallet` from it:
82
+ `walletId = selectedWallet?.id ?? selectedWallet?.walletId ?? ""`,
83
+ `hasWallet = !!walletId`.
84
+ - **Signer selected:** Use `useSignerSelection().selectedSigner`; `hasSigner = !!selectedSigner`.
85
+
86
+ Show the form only when `hasWallet && hasSigner`. Do not rely only on `useSignerSelection().selectedWalletId` for “wallet selected” to avoid sync issues between the two hooks. When building custom pages, pass `selectedWalletId={walletId}` and `selectedSigner={selectedSigner}` explicitly into `MessageSigningForm` / `TransactionSigningForm` so the forms use the same wallet/signer state as your UI.
87
+
88
+ ---
89
+
90
+ ## Connection setup (Solana)
91
+
92
+ For transaction sign-and-send (wallet-adapter or passkey), the library expects a connection object with `sendRawTransaction`, `getLatestBlockhash`, and `confirmTransaction`. If you use `@solana/web3.js`, use the provided adapter so you don’t need type assertions:
93
+
94
+ ```tsx
95
+ import { Connection } from '@solana/web3.js'
96
+ import { adaptSolanaConnection, TransactionSigningForm } from 'cilantro-react'
97
+
98
+ const connection = new Connection('https://api.mainnet-beta.solana.com')
99
+
100
+ <TransactionSigningForm
101
+ connection={adaptSolanaConnection(connection)}
102
+ showContext
103
+ />
104
+ ```
105
+
106
+ `adaptSolanaConnection(connection)` returns an object that matches the library’s expected connection shape. You can pass it to `TransactionSigningForm` or `useTransactionSigning({ connection: adaptSolanaConnection(solanaConnection), ... })`.
107
+
108
+ ---
109
+
110
+ ## Headless usage and custom selectors
111
+
112
+ You can build your own wallet/signer UI with the hooks and render props instead of the built-in selectors:
113
+
114
+ - **Wallet:** Use `useWallets()` for `wallets`, `selectedWallet`, `selectWallet`, and `refreshWallets`. Use the `WalletSelector` `children` render prop to render your own list/dropdown; you get `{ wallets, selectedWallet, selectWallet, isLoading, refreshWallets }`.
115
+ - **Signer:** Use `useSignerSelection()` for `availableSigners`, `selectedSigner`, `setSelectedSigner`, and `isLoadingSigners`. Use the `SignerSelector` `children` or `renderList` prop to render your own list (e.g. Shadcn Select or custom buttons).
116
+
117
+ Example: custom wallet + signer selection and conditional form:
118
+
119
+ ```tsx
120
+ const { selectedWallet } = useWallets()
121
+ const { availableSigners, selectedSigner, setSelectedSigner, isLoadingSigners } = useSignerSelection()
122
+ const walletId = selectedWallet?.id ?? selectedWallet?.walletId ?? ''
123
+ const hasWallet = !!walletId
124
+ const hasSigner = !!selectedSigner
125
+
126
+ return (
127
+ <>
128
+ <WalletSelector>{({ wallets, selectedWallet, selectWallet, isLoading }) => (
129
+ /* your custom wallet dropdown */
130
+ )}</WalletSelector>
131
+ <SignerSelector
132
+ selectedWalletId={walletId}
133
+ availableSigners={availableSigners}
134
+ selectedSigner={selectedSigner}
135
+ onSignerSelect={setSelectedSigner}
136
+ isLoadingSigners={isLoadingSigners}
137
+ >
138
+ {({ signers, selectedSigner, onSignerSelect, isLoading }) => (
139
+ /* your custom signer list */
140
+ )}
141
+ </SignerSelector>
142
+ {hasWallet && hasSigner && (
143
+ <MessageSigningForm
144
+ selectedWalletId={walletId}
145
+ selectedSigner={selectedSigner}
146
+ showContext={false}
147
+ />
148
+ )}
149
+ </>
150
+ )
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Property names (SDK → library)
156
+
157
+ The library normalizes wallet and signer data at the boundary. You can rely on these fields in UI and hooks:
158
+
159
+ | SDK / API field | Normalized / library field | Notes |
160
+ |-------------------|----------------------------|--------------------------------|
161
+ | `walletId` | `id` | WalletData always has `id`. |
162
+ | `walletAddress` | `address` | WalletData always has `address`. |
163
+ | `isActive` | `active` | WalletData alias. |
164
+ | `signerId` | `id` | SignerData always has `id` and `signerId`. |
165
+ | `signerPubkey` / `publicKey` | `signerPubkey` and `publicKey` | SignerData has both. |
166
+ | `signerType` / `type` | `signerType` and `type` | SignerData has both. |
50
167
 
51
- **Connection:** The library does not create a Solana RPC connection. For transaction sign-and-send (wallet-adapter or passkey), pass your own `connection` from `@solana/web3.js` (or your Solana config) into `useTransactionSigning` / `TransactionSigningForm`. See [Transaction signing](#transaction-signing) below.
168
+ Use `normalizeWallet(dto)` and `normalizeSigner(dto, category)` at API boundaries if you ingest raw SDK responses; the provider and `loadSigners` already use normalized shapes.
52
169
 
53
170
  ---
54
171
 
@@ -291,7 +408,7 @@ Sign and/or send a transaction. Use inside `CilantroProvider`.
291
408
  | `selectedWalletId` | `string` | Wallet ID when using SDK signer. |
292
409
  | `walletAdapterSignTransaction` | `(transaction: Transaction) => Promise<Transaction>` | Optional; required for wallet-adapter signing. |
293
410
  | `walletAdapterPublicKey` | `string \| null` | Optional; required for wallet-adapter send. |
294
- | `connection` | `SignAndSendConnection \| null` | **Required for sign-and-send** when using wallet-adapter or passkey. Provide your Solana `Connection` (e.g. from `@solana/web3.js`). |
411
+ | `connection` | `SignAndSendConnection \| null` | **Required for sign-and-send** when using wallet-adapter or passkey. Use `adaptSolanaConnection(connection)` when you have a `@solana/web3.js` Connection; see [Connection setup](#connection-setup-solana). |
295
412
 
296
413
  **Returns:** `UseTransactionSigningResult`
297
414
 
@@ -304,7 +421,7 @@ Sign and/or send a transaction. Use inside `CilantroProvider`.
304
421
  | `signAndSendTransaction` | `(transaction: Transaction) => Promise<void>` | Sign and send. Requires `connection` for wallet-adapter and passkey. |
305
422
  | `reset` | `() => void` | Set `transactionResultState` back to idle. |
306
423
 
307
- **Connection:** For passkey or wallet-adapter sign-and-send, you must pass a `connection` that has `getLatestBlockhash`, `sendRawTransaction`, and `confirmTransaction`. The library does not create a connection.
424
+ **Connection:** For passkey or wallet-adapter sign-and-send, pass a `connection` that has `getLatestBlockhash`, `sendRawTransaction`, and `confirmTransaction`. Use `adaptSolanaConnection(connection)` when you have a `@solana/web3.js` Connection; see [Connection setup](#connection-setup-solana).
308
425
 
309
426
  ---
310
427
 
@@ -397,14 +514,15 @@ interface WalletData {
397
514
 
398
515
  From `useSigners().signers` or `useSignerSelection().availableSigners` / `selectedSigner`. Used by SignerSelector, MessageSigningForm, TransactionSigningForm. Contains at least: `id`, `signerId`, `type` or `signerType`, `walletId`, `publicKey` / `signerPubkey`, and optional `email`, `phone`, `isActive`, `signerConfig`, etc. See TypeScript type `SignerData` for full shape.
399
516
 
400
- #### SignAndSendConnection
517
+ #### SignAndSendConnection / adaptSolanaConnection
401
518
 
402
- Type for the `connection` prop when using sign-and-send (passkey or wallet-adapter). Your `Connection` from `@solana/web3.js` is compatible. Must have:
519
+ Type for the `connection` prop when using sign-and-send (passkey or wallet-adapter). Must have:
403
520
 
404
- - `getLatestBlockhash(commitment?)` → `Promise<{ blockhash, lastValidBlockHeight }>`
521
+ - `sendRawTransaction(buf: Buffer)` → `Promise<string>`
522
+ - `getLatestBlockhash()` → `Promise<{ blockhash, lastValidBlockHeight }>`
405
523
  - `confirmTransaction(opts: { signature, blockhash, lastValidBlockHeight })` → `Promise<void>`
406
524
 
407
- For wallet-adapter send, the hook also uses `sendRawTransaction(buf)` (standard Solana Connection has this).
525
+ If you use `@solana/web3.js`, call `adaptSolanaConnection(connection)` and pass the result; see [Connection setup](#connection-setup-solana).
408
526
 
409
527
  #### Other types
410
528