@cookill/wallet-adapter 2.5.4 → 3.1.0

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,48 +1,27 @@
1
- # @cookill/wallet-adapter v2.5.0
1
+ # @cookill/wallet-adapter v3.1.0
2
2
 
3
3
  Official wallet adapter for **Sheep Wallet** on Rialo blockchain.
4
4
 
5
+ ## 🚀 What's New in v3.1
6
+
7
+ - **REX (Rialo Extended Execution)**: Submit confidential transactions using TEE/MPC/FHE
8
+ - **SfS (Stake-for-Service)**: Gasless transactions — pay fees from staking yield
9
+ - **Scan-to-Connect**: Bidirectional QR code pairing across devices
10
+ - **Anti-freeze architecture**: All provider calls wrapped with timeouts
11
+ - **Silent auto-connect**: Uses `checkSession()` for session restoration
12
+
5
13
  ## Installation
6
14
 
7
15
  ```bash
8
16
  npm install @cookill/wallet-adapter
17
+ # or
18
+ pnpm add @cookill/wallet-adapter
9
19
  ```
10
20
 
11
- ## ⚠️ IMPORTANT: Vite Configuration
12
-
13
- **If you're using Vite**, you MUST add React deduplication to prevent "stuck connection" issues:
14
-
15
- ```typescript
16
- // vite.config.ts
17
- import { defineConfig } from "vite";
18
- import react from "@vitejs/plugin-react";
19
- import path from "path";
20
-
21
- export default defineConfig({
22
- plugins: [react()],
23
- resolve: {
24
- alias: {
25
- "@": path.resolve(__dirname, "./src"),
26
- },
27
- // CRITICAL: Prevent duplicate React instances
28
- dedupe: ["react", "react-dom", "react/jsx-runtime"],
29
- },
30
- optimizeDeps: {
31
- include: ["react", "react-dom"],
32
- },
33
- });
34
- ```
35
-
36
- **Without this configuration**, the wallet modal may not open and connections will appear "stuck".
37
-
38
- ## Quick Start
21
+ ## Quick Start (React)
39
22
 
40
23
  ```tsx
41
- import {
42
- WalletProvider,
43
- ConnectButton,
44
- WalletErrorBoundary,
45
- } from '@cookill/wallet-adapter/react';
24
+ import { WalletProvider, ConnectButton, WalletErrorBoundary } from '@cookill/wallet-adapter/react';
46
25
 
47
26
  function App() {
48
27
  return (
@@ -60,112 +39,206 @@ function App() {
60
39
 
61
40
  ### useWallet
62
41
 
63
- Main hook for wallet state and actions:
64
-
65
42
  ```tsx
66
43
  import { useWallet } from '@cookill/wallet-adapter/react';
67
44
 
68
45
  function MyComponent() {
69
46
  const {
70
- // State
71
- connected, // boolean - is wallet connected
72
- connecting, // boolean - connection in progress
73
- accounts, // WalletAccount[] - all connected accounts
74
- activeAccount, // WalletAccount | null - primary account
75
- network, // 'mainnet' | 'testnet' | 'devnet' | 'localnet'
76
- chainId, // 'rialo:devnet' etc
77
- balance, // string | null (in kelvins)
78
- error, // Error | null
79
-
80
- // Actions
81
- connect, // () => Promise<WalletAccount[]>
82
- disconnect, // () => Promise<void>
83
- switchNetwork, // (network) => Promise<void>
84
- refreshBalance, // () => Promise<void>
85
-
86
- // Transactions
87
- signMessage, // (message: string) => Promise<SignedMessage>
88
- signTransaction, // (tx) => Promise<string>
89
- sendTransaction, // (tx) => Promise<TransactionResult>
90
- signAndSendTransaction, // (tx) => Promise<TransactionResult>
91
-
47
+ connected, connecting, activeAccount, state, chainId, isInstalled,
48
+ connect, disconnect, switchNetwork, refreshBalance,
49
+ signMessage, signTransaction, sendTransaction, signAndSendTransaction,
50
+ // REX
51
+ getREXCapabilities, submitREXTransaction,
52
+ // SfS (Gasless)
53
+ sendGaslessTransaction, getSfSPositions, createSfSPosition, getSfSCredits,
92
54
  // Modal
93
- isModalOpen,
94
- openModal,
95
- closeModal,
55
+ openModal, closeModal,
96
56
  } = useWallet();
57
+ }
58
+ ```
59
+
60
+ ### Specialized Hooks
61
+
62
+ ```tsx
63
+ // Connection
64
+ const { connect, connecting, isInstalled, error } = useConnectWallet();
65
+ const { disconnect, connected } = useDisconnectWallet();
66
+ const connected = useIsConnected();
67
+
68
+ // Account & Balance
69
+ const account = useActiveAccount();
70
+ const accounts = useAccounts();
71
+ const { balance, refresh } = useBalance();
72
+
73
+ // Network
74
+ const { network, chainId } = useNetwork();
75
+ const { switchNetwork, network } = useSwitchNetwork();
76
+
77
+ // Transactions (now includes gasless)
78
+ const { sendTransaction, signAndSendTransaction, sendGaslessTransaction } = useSendTransaction();
79
+ const { signMessage } = useSignMessage();
80
+ ```
81
+
82
+ ### useREX — Confidential Transactions
83
+
84
+ ```tsx
85
+ import { useREX } from '@cookill/wallet-adapter/react';
86
+
87
+ function ConfidentialTransfer() {
88
+ const { capabilities, supported, submitREXTransaction } = useREX();
89
+
90
+ const handleConfidentialSend = async () => {
91
+ const result = await submitREXTransaction({
92
+ to: 'RecipientAddress...',
93
+ value: '1000000000',
94
+ rex: {
95
+ confidential: true,
96
+ privacyMode: 'auto', // 'tee' | 'mpc' | 'fhe' | 'auto'
97
+ keepEncrypted: false, // true = output stays encrypted
98
+ },
99
+ });
100
+
101
+ console.log('TX hash:', result.hash);
102
+ console.log('Attestation:', result.attestation);
103
+ };
104
+
105
+ return (
106
+ <div>
107
+ <p>REX supported: {supported ? 'Yes' : 'No'}</p>
108
+ {supported && (
109
+ <div>
110
+ <p>Privacy modes: {capabilities?.privacyModes.join(', ')}</p>
111
+ <button onClick={handleConfidentialSend}>
112
+ Send Confidential Transaction
113
+ </button>
114
+ </div>
115
+ )}
116
+ </div>
117
+ );
118
+ }
119
+ ```
120
+
121
+ ### useSfS — Gasless Transactions (Stake-for-Service)
122
+
123
+ ```tsx
124
+ import { useSfS } from '@cookill/wallet-adapter/react';
125
+
126
+ function GaslessDemo() {
127
+ const { positions, credits, hasCredits, createPosition, sendGasless, refresh } = useSfS();
128
+
129
+ // Create an SfS position to generate service credits
130
+ const handleStake = async () => {
131
+ await createPosition({
132
+ amount: '10000000000', // 10 RLO in kelvins
133
+ validator: 'ValidatorAddr...',
134
+ routingFraction: 0.5, // Route 50% of yield to service credits
135
+ });
136
+ await refresh();
137
+ };
138
+
139
+ // Send a gasless transaction (paid from SfS credits)
140
+ const handleGaslessSend = async () => {
141
+ const result = await sendGasless({
142
+ to: 'RecipientAddress...',
143
+ value: '1000000000', // 1 RLO
144
+ });
145
+ console.log('Gasless TX:', result.hash);
146
+ };
97
147
 
98
148
  return (
99
149
  <div>
100
- {connected ? (
101
- <p>Connected: {activeAccount?.address}</p>
150
+ <p>SfS Positions: {positions.length}</p>
151
+ <p>Available Credits: {credits?.available || '0'}</p>
152
+ <p>Credits/Epoch: {credits?.estimatedPerEpoch || '0'}</p>
153
+
154
+ {!hasCredits ? (
155
+ <button onClick={handleStake}>Stake for Gasless TX</button>
102
156
  ) : (
103
- <button onClick={openModal}>Connect</button>
157
+ <button onClick={handleGaslessSend}>Send (Gasless)</button>
104
158
  )}
105
159
  </div>
106
160
  );
107
161
  }
108
162
  ```
109
163
 
110
- ### Convenience Hooks
164
+ ### useScanConnect — QR-based Cross-Device Pairing
111
165
 
112
166
  ```tsx
113
- // Check connection status
114
- const connected = useIsConnected();
167
+ import { useScanConnect } from '@cookill/wallet-adapter/react';
115
168
 
116
- // Get active account
117
- const account = useActiveAccount();
169
+ function ScanConnectDemo() {
170
+ const { scanURI, status, generateQR, approveSession, rejectSession } = useScanConnect();
118
171
 
119
- // Get all accounts
120
- const accounts = useAccounts();
172
+ return (
173
+ <div>
174
+ <button onClick={generateQR}>Generate QR</button>
175
+ {scanURI && (
176
+ <div>
177
+ <p>Scan this URI: {scanURI.uri}</p>
178
+ <p>Status: {status}</p>
179
+ </div>
180
+ )}
181
+ </div>
182
+ );
183
+ }
184
+ ```
121
185
 
122
- // Balance with formatting
123
- const { balance, formatted, refresh } = useBalance();
124
- // formatted: "1,234.5678 RLO"
186
+ ## Vanilla JavaScript
125
187
 
126
- // Network info
127
- const { network, chainId, config } = useNetwork();
188
+ ```typescript
189
+ import { SheepWallet, isInstalled, formatBalance } from '@cookill/wallet-adapter';
128
190
 
129
- // Switch network with loading state
130
- const { switchNetwork, switching, error } = useSwitchNetwork();
191
+ const wallet = new SheepWallet();
131
192
 
132
- // Connect with modal
133
- const { connect, connecting, isInstalled, error } = useConnectWallet();
193
+ // Standard connect
194
+ const accounts = await wallet.connect();
134
195
 
135
- // Disconnect
136
- const { disconnect, connected } = useDisconnectWallet();
196
+ // REX — Confidential transaction
197
+ const rexResult = await wallet.submitREXTransaction({
198
+ to: 'RecipientAddress...',
199
+ value: '1000000000',
200
+ rex: { confidential: true, privacyMode: 'auto' },
201
+ });
202
+
203
+ // SfS — Create staking position for gasless TX
204
+ await wallet.createSfSPosition({
205
+ amount: '10000000000',
206
+ validator: 'ValidatorAddr...',
207
+ routingFraction: 0.5,
208
+ });
137
209
 
138
- // Sign message with loading state
139
- const { sign, signing, signature, error } = useSignMessage();
210
+ // SfS Send gasless transaction
211
+ const result = await wallet.sendGaslessTransaction({
212
+ to: 'RecipientAddress...',
213
+ value: '1000000000',
214
+ });
140
215
 
141
- // Send transaction with loading state
142
- const { send, sending, txHash, error, reset } = useSendTransaction();
216
+ // Scan-to-Connect Generate session QR
217
+ const session = await wallet.createScanSession();
218
+ console.log('QR URI:', session.uri);
143
219
  ```
144
220
 
145
221
  ## Components
146
222
 
147
223
  ### ConnectButton
148
224
 
149
- Pre-styled connect button:
150
-
151
225
  ```tsx
152
226
  <ConnectButton
153
227
  connectLabel="Connect Wallet"
154
228
  disconnectLabel="Disconnect"
155
229
  showAddress={true}
156
230
  showBalance={false}
157
- className="my-button"
231
+ showFeatures={true} // Show REX/SfS badges
158
232
  />
159
233
  ```
160
234
 
161
235
  ### WalletProvider
162
236
 
163
- Wrap your app to provide wallet context:
164
-
165
237
  ```tsx
166
238
  <WalletProvider
167
239
  network="devnet"
168
240
  autoConnect={true}
241
+ scanConnectRelay="wss://relay.rialo.io"
169
242
  onConnect={(accounts) => console.log('Connected', accounts)}
170
243
  onDisconnect={() => console.log('Disconnected')}
171
244
  onNetworkChange={(network) => console.log('Network:', network)}
@@ -175,150 +248,156 @@ Wrap your app to provide wallet context:
175
248
  </WalletProvider>
176
249
  ```
177
250
 
178
- ### WalletErrorBoundary
251
+ The connect modal includes two tabs:
252
+ - **Extension**: Direct browser extension connection
253
+ - **Scan to Connect**: Bidirectional QR code (show QR or scan QR)
179
254
 
180
- Prevents blank screens from uncaught errors:
255
+ ## Networks
181
256
 
182
- ```tsx
183
- <WalletErrorBoundary
184
- fallback={<div>Something went wrong</div>}
185
- onError={(error, errorInfo) => logError(error)}
186
- >
187
- <YourComponent />
188
- </WalletErrorBoundary>
189
- ```
257
+ | Network | Chain ID | RPC URL | Symbol | REX | SfS |
258
+ |----------|-----------------|----------------------------------|--------|-----|-----|
259
+ | Mainnet | rialo:mainnet | https://mainnet.rialo.io:4101 | RLO | ✅ | ✅ |
260
+ | Testnet | rialo:testnet | https://testnet.rialo.io:4101 | tRLO | ✅ | ✅ |
261
+ | Devnet | rialo:devnet | https://devnet.rialo.io:4101 | dRLO | ✅ | ✅ |
262
+ | Localnet | rialo:localnet | http://localhost:4101 | lRLO | ❌ | ❌ |
190
263
 
191
- ## Vanilla JavaScript (Non-React)
264
+ ## REX (Rialo Extended Execution)
192
265
 
193
- ```typescript
194
- import { RialoWallet, isRialoInstalled, formatBalance } from '@cookill/wallet-adapter';
266
+ REX enables privacy-preserving computation on Rialo using:
267
+ - **TEE** (Trusted Execution Environments) fastest, hardware-isolated
268
+ - **MPC** (Multi-Party Computation) — distributed, no single trust point
269
+ - **FHE** (Fully Homomorphic Encryption) — compute on encrypted data
270
+ - **Auto** — protocol selects optimal privacy technology
195
271
 
196
- // Check if extension is installed
197
- if (!isRialoInstalled()) {
198
- console.log('Please install Sheep Wallet');
199
- window.open('https://rialo.io/wallet', '_blank');
200
- }
272
+ ### REX Transaction Flow
273
+
274
+ ```
275
+ 1. User encrypts inputs with network public key
276
+ 2. Wallet submits encrypted TX to REX execution layer
277
+ 3. Nodes execute confidentially (inputs never exposed)
278
+ 4. Result is cryptographically attested
279
+ 5. Only authorized parties can decrypt output
280
+ ```
201
281
 
202
- // Create wallet instance
203
- const wallet = new RialoWallet();
282
+ ### REX Config Options
204
283
 
205
- // Connect
206
- const accounts = await wallet.connect();
207
- console.log('Connected:', accounts[0].address);
284
+ ```typescript
285
+ interface REXConfig {
286
+ confidential: boolean; // Enable REX execution
287
+ privacyMode?: 'tee' | 'mpc' | 'fhe' | 'auto';
288
+ encryptedInputs?: string; // Pre-encrypted data (base64)
289
+ programId?: string; // REX program to execute
290
+ keepEncrypted?: boolean; // Keep output encrypted
291
+ accessPolicy?: {
292
+ allowedDecryptors: string[]; // Who can decrypt
293
+ expiresAt?: number; // Access expiry
294
+ };
295
+ }
296
+ ```
208
297
 
209
- // Get balance
210
- const balance = await wallet.getBalance();
211
- console.log('Balance:', formatBalance(balance), 'RLO');
298
+ ## SfS (Stake-for-Service)
212
299
 
213
- // Sign message
214
- const signed = await wallet.signMessage('Hello!');
215
- console.log('Signature:', signed.signature);
300
+ Stake-for-Service converts staking yield into service credits that pay for gas automatically.
216
301
 
217
- // Send transaction
218
- const tx = await wallet.signAndSendTransaction({
219
- to: 'RecipientAddress...',
220
- value: '1000000000', // 1 RLO in kelvins
221
- });
222
- console.log('TX Hash:', tx.hash);
302
+ ### How It Works
223
303
 
224
- // Listen to events
225
- wallet.on('disconnect', () => {
226
- console.log('Wallet disconnected');
227
- });
304
+ ```
305
+ 1. User stakes RLO with a validator
306
+ 2. Sets routingFraction (0.0 - 1.0) of yield → service credits
307
+ 3. ServicePaymaster mints credits from routed yield
308
+ 4. Credits auto-pay gas for transactions
309
+ 5. No more manual gas top-ups
228
310
  ```
229
311
 
230
- ## Direct Provider Access
231
-
232
- Access `window.rialo` directly:
312
+ ### SfS Types
233
313
 
234
314
  ```typescript
235
- if (window.rialo) {
236
- const accounts = await window.rialo.connect();
237
- const balance = await window.rialo.getBalance();
238
- const tx = await window.rialo.signAndSendTransaction({
239
- to: 'RecipientAddress...',
240
- value: '1000000000',
241
- });
315
+ interface SfSPosition {
316
+ id: string;
317
+ principal: string; // Staked amount (kelvins)
318
+ validator: string; // Validator address
319
+ routingFraction: number; // 0.0 - 1.0
320
+ creditBalance: string; // Current credits
321
+ creditsPerEpoch: string; // Estimated yield
322
+ status: 'active' | 'pending' | 'closed';
323
+ }
324
+
325
+ interface SfSCreditBalance {
326
+ available: string;
327
+ usedThisEpoch: string;
328
+ totalEarned: string;
329
+ estimatedPerEpoch: string;
242
330
  }
243
331
  ```
244
332
 
245
- ## Networks
333
+ ## Scan-to-Connect
334
+
335
+ Connect wallet on one device to dApp on another via QR code.
336
+
337
+ ### Bidirectional Flow
246
338
 
247
- | Network | Chain ID | RPC URL | Symbol |
248
- |----------|-----------------|----------------------------------|--------|
249
- | Mainnet | rialo:mainnet | https://mainnet.rialo.io:4101 | RLO |
250
- | Testnet | rialo:testnet | https://testnet.rialo.io:4101 | tRLO |
251
- | Devnet | rialo:devnet | https://devnet.rialo.io:4101 | dRLO |
252
- | Localnet | rialo:localnet | http://localhost:4101 | lRLO |
339
+ **dApp Wallet**: dApp shows QR, user scans with mobile Sheep Wallet
340
+ **Wallet → dApp**: Wallet shows QR (Settings → Show Connect QR), dApp scans
341
+
342
+ ### URI Format
343
+
344
+ ```
345
+ rialo-wc://{sessionId}?relay={relayUrl}&topic={topic}&networks=devnet
346
+ ```
253
347
 
254
348
  ## Utilities
255
349
 
256
350
  ```typescript
257
- import {
258
- formatAddress, // (address, chars?) => "5YNm...VWr8"
259
- formatBalance, // (kelvins, decimals?) => "1.0000"
260
- parseBalance, // (rlo) => bigint (kelvins)
261
- isValidAddress, // (address) => boolean
262
- toChainId, // (network) => 'rialo:devnet'
263
- fromChainId, // (chainId) => 'devnet'
264
- isRialoInstalled, // () => boolean
265
- getRialoProvider, // () => RialoProvider | undefined
266
- waitForRialoProvider, // (timeout?) => Promise<RialoProvider>
267
- NETWORKS, // Network configurations
351
+ import {
352
+ formatAddress, // (address, chars?) => "5YNm...VWr8"
353
+ formatBalance, // (kelvins, decimals?) => "1.0000"
354
+ parseBalance, // (rlo) => bigint (kelvins)
355
+ isValidAddress, // (address) => boolean
356
+ isInstalled, // () => boolean
357
+ NETWORKS, // Network configurations
268
358
  } from '@cookill/wallet-adapter';
269
359
  ```
270
360
 
271
361
  ## TypeScript
272
362
 
273
- Full TypeScript support with all types exported:
274
-
275
363
  ```typescript
276
364
  import type {
277
- WalletAccount,
278
- TransactionRequest,
279
- TransactionResult,
280
- SignedMessage,
281
- BalanceResult,
282
- NetworkConfig,
283
- WalletInfo,
284
- RialoProvider,
285
- RialoNetwork,
286
- RialoChain,
365
+ WalletAccount, TransactionRequest, TransactionResult,
366
+ SignedMessage, NetworkConfig, WalletInfo, RialoProvider,
367
+ RialoNetwork, RialoChainId,
368
+ // REX
369
+ REXConfig, REXCapabilities, REXTransactionResult, REXPrivacyMode,
370
+ // SfS
371
+ SfSPosition, SfSCreateParams, SfSUpdateParams, SfSCreditBalance,
372
+ // Scan-to-Connect
373
+ ScanConnectSession, ScanConnectURI, ScanConnectStatus,
287
374
  } from '@cookill/wallet-adapter';
288
375
  ```
289
376
 
290
- ## Troubleshooting
291
-
292
- ### Modal not opening / Connection stuck
377
+ ## Migration from v3.0
293
378
 
294
- 1. **Add Vite dedupe config** (see top of this README)
295
- 2. Clear `node_modules` and reinstall: `rm -rf node_modules && npm install`
296
- 3. Check console for errors
379
+ ```diff
380
+ // Imports unchanged
381
+ import { WalletProvider, ConnectButton } from '@cookill/wallet-adapter/react';
297
382
 
298
- ### Extension not detected
383
+ // Hook usage unchanged
384
+ const { connect, connected } = useWallet();
299
385
 
300
- 1. Make sure Sheep Wallet extension is installed
301
- 2. Refresh the page after installing
302
- 3. Check if `window.rialo` exists in browser console
386
+ // New in v3.1:
387
+ + import { useREX, useSfS, useScanConnect } from '@cookill/wallet-adapter/react';
388
+ + const { submitREXTransaction } = useREX();
389
+ + const { sendGasless, hasCredits } = useSfS();
390
+ + const { generateQR, scanURI } = useScanConnect();
303
391
 
304
- ### Transaction fails
392
+ // WalletProvider now supports scanConnectRelay prop
393
+ + <WalletProvider scanConnectRelay="wss://relay.rialo.io">
305
394
 
306
- 1. Ensure wallet is unlocked
307
- 2. Check you have sufficient balance
308
- 3. Verify recipient address is valid
395
+ // ConnectButton now shows feature badges
396
+ + <ConnectButton showFeatures={true} />
309
397
 
310
- ## Changelog
311
-
312
- ### v2.5.0
313
- - Fixed bundling to properly externalize React
314
- - Added WalletErrorBoundary component
315
- - Added loading states (ApprovalPending, ConnectionStatus)
316
- - Improved modal with singleton pattern
317
- - Updated Vite configuration requirements
318
-
319
- ### v2.4.x
320
- - Initial public release
398
+ // Connect modal now has "Scan to Connect" tab built-in
399
+ ```
321
400
 
322
401
  ## License
323
402
 
324
- MIT
403
+ MIT