@cookill/wallet-adapter 3.0.0 → 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,13 +1,14 @@
1
- # @cookill/wallet-adapter v3.0.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.0
5
+ ## 🚀 What's New in v3.1
6
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
7
10
  - **Anti-freeze architecture**: All provider calls wrapped with timeouts
8
- - **Clean separation**: Core (vanilla JS) vs React layer
9
- - **Silent auto-connect**: Uses `checkSession()` instead of `connect()` for session restoration
10
- - **No more hangs**: 20-second timeout on connection, 30-second on operations
11
+ - **Silent auto-connect**: Uses `checkSession()` for session restoration
11
12
 
12
13
  ## Installation
13
14
 
@@ -15,8 +16,6 @@ Official wallet adapter for **Sheep Wallet** on Rialo blockchain.
15
16
  npm install @cookill/wallet-adapter
16
17
  # or
17
18
  pnpm add @cookill/wallet-adapter
18
- # or
19
- yarn add @cookill/wallet-adapter
20
19
  ```
21
20
 
22
21
  ## Quick Start (React)
@@ -45,40 +44,16 @@ import { useWallet } from '@cookill/wallet-adapter/react';
45
44
 
46
45
  function MyComponent() {
47
46
  const {
48
- // State
49
- connected, // boolean
50
- connecting, // boolean
51
- activeAccount, // WalletAccount | null
52
- state, // Full state object
53
- chainId, // 'rialo:devnet' etc
54
- isInstalled, // boolean
55
-
56
- // Actions
57
- connect, // () => Promise<WalletAccount[]>
58
- disconnect, // () => Promise<void>
59
- switchNetwork, // (network) => Promise<void>
60
- refreshBalance, // () => Promise<void>
61
-
62
- // Transactions
63
- signMessage, // (message: string) => Promise<SignedMessage>
64
- signTransaction, // (tx) => Promise<string>
65
- sendTransaction, // (tx) => Promise<TransactionResult>
66
- signAndSendTransaction, // (tx) => Promise<TransactionResult>
67
-
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,
68
54
  // Modal
69
- openModal,
70
- closeModal,
55
+ openModal, closeModal,
71
56
  } = useWallet();
72
-
73
- return (
74
- <div>
75
- {connected ? (
76
- <p>Connected: {activeAccount?.address}</p>
77
- ) : (
78
- <button onClick={connect}>Connect</button>
79
- )}
80
- </div>
81
- );
82
57
  }
83
58
  ```
84
59
 
@@ -90,76 +65,157 @@ const { connect, connecting, isInstalled, error } = useConnectWallet();
90
65
  const { disconnect, connected } = useDisconnectWallet();
91
66
  const connected = useIsConnected();
92
67
 
93
- // Account
68
+ // Account & Balance
94
69
  const account = useActiveAccount();
95
70
  const accounts = useAccounts();
96
-
97
- // Balance
98
71
  const { balance, refresh } = useBalance();
99
72
 
100
73
  // Network
101
74
  const { network, chainId } = useNetwork();
102
75
  const { switchNetwork, network } = useSwitchNetwork();
103
76
 
104
- // Transactions
105
- const { signMessage, connected } = useSignMessage();
106
- const { sendTransaction, signAndSendTransaction, connected } = useSendTransaction();
77
+ // Transactions (now includes gasless)
78
+ const { sendTransaction, signAndSendTransaction, sendGaslessTransaction } = useSendTransaction();
79
+ const { signMessage } = useSignMessage();
107
80
  ```
108
81
 
109
- ## Vanilla JavaScript
82
+ ### useREX — Confidential Transactions
110
83
 
111
- ```typescript
112
- import { SheepWallet, isInstalled, formatBalance } from '@cookill/wallet-adapter';
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
+ };
113
104
 
114
- // Check if installed
115
- if (!isInstalled()) {
116
- console.log('Please install Sheep Wallet');
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
+ );
117
118
  }
119
+ ```
118
120
 
119
- // Create wallet instance
120
- const wallet = new SheepWallet();
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
+ };
121
147
 
122
- // Connect (with built-in timeout)
123
- try {
124
- const accounts = await wallet.connect();
125
- console.log('Connected:', accounts[0].address);
126
- } catch (error) {
127
- console.error('Connection failed:', error.message);
148
+ return (
149
+ <div>
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>
156
+ ) : (
157
+ <button onClick={handleGaslessSend}>Send (Gasless)</button>
158
+ )}
159
+ </div>
160
+ );
128
161
  }
162
+ ```
129
163
 
130
- // Get balance
131
- const balance = await wallet.getBalance();
132
- console.log('Balance:', formatBalance(balance), 'RLO');
164
+ ### useScanConnect — QR-based Cross-Device Pairing
133
165
 
134
- // Sign message
135
- const signed = await wallet.signMessage('Hello!');
166
+ ```tsx
167
+ import { useScanConnect } from '@cookill/wallet-adapter/react';
136
168
 
137
- // Send transaction
138
- const tx = await wallet.signAndSendTransaction({
139
- to: 'RecipientAddress...',
140
- value: '1000000000', // 1 RLO in kelvins
141
- });
142
- console.log('TX Hash:', tx.hash);
169
+ function ScanConnectDemo() {
170
+ const { scanURI, status, generateQR, approveSession, rejectSession } = useScanConnect();
143
171
 
144
- // Silent session check (for auto-connect, never triggers approval)
145
- const existingSession = await wallet.checkSession();
146
- if (existingSession) {
147
- console.log('Session restored:', existingSession[0].address);
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
+ );
148
183
  }
149
184
  ```
150
185
 
151
- ## Direct Provider Access
186
+ ## Vanilla JavaScript
152
187
 
153
188
  ```typescript
154
- // Access window.rialo directly
155
- if (window.rialo) {
156
- const accounts = await window.rialo.connect();
157
- const balance = await window.rialo.getBalance();
158
- const tx = await window.rialo.signAndSendTransaction({
159
- to: 'RecipientAddress...',
160
- value: '1000000000',
161
- });
162
- }
189
+ import { SheepWallet, isInstalled, formatBalance } from '@cookill/wallet-adapter';
190
+
191
+ const wallet = new SheepWallet();
192
+
193
+ // Standard connect
194
+ const accounts = await wallet.connect();
195
+
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
+ });
209
+
210
+ // SfS — Send gasless transaction
211
+ const result = await wallet.sendGaslessTransaction({
212
+ to: 'RecipientAddress...',
213
+ value: '1000000000',
214
+ });
215
+
216
+ // Scan-to-Connect — Generate session QR
217
+ const session = await wallet.createScanSession();
218
+ console.log('QR URI:', session.uri);
163
219
  ```
164
220
 
165
221
  ## Components
@@ -172,8 +228,7 @@ if (window.rialo) {
172
228
  disconnectLabel="Disconnect"
173
229
  showAddress={true}
174
230
  showBalance={false}
175
- className="my-button"
176
- style={{ backgroundColor: '#6EB9A8' }}
231
+ showFeatures={true} // Show REX/SfS badges
177
232
  />
178
233
  ```
179
234
 
@@ -181,9 +236,9 @@ if (window.rialo) {
181
236
 
182
237
  ```tsx
183
238
  <WalletProvider
184
- network="devnet" // 'mainnet' | 'testnet' | 'devnet' | 'localnet'
185
- autoConnect={true} // Restore session silently on mount
186
- wallets={[customWallet]} // Additional wallets to show
239
+ network="devnet"
240
+ autoConnect={true}
241
+ scanConnectRelay="wss://relay.rialo.io"
187
242
  onConnect={(accounts) => console.log('Connected', accounts)}
188
243
  onDisconnect={() => console.log('Disconnected')}
189
244
  onNetworkChange={(network) => console.log('Network:', network)}
@@ -193,47 +248,102 @@ if (window.rialo) {
193
248
  </WalletProvider>
194
249
  ```
195
250
 
196
- ### Error Boundary & Loading States
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)
197
254
 
198
- ```tsx
199
- import {
200
- WalletErrorBoundary,
201
- ApprovalPending,
202
- LoadingSpinner,
203
- ConnectionStatus,
204
- } from '@cookill/wallet-adapter/react';
205
-
206
- // Error Boundary
207
- <WalletErrorBoundary
208
- fallback={<CustomError />}
209
- onError={(error, info) => logError(error)}
210
- >
211
- <WalletProvider>...</WalletProvider>
212
- </WalletErrorBoundary>
213
-
214
- // Loading states
215
- <ApprovalPending
216
- title="Waiting for Approval"
217
- message="Please approve in Sheep Wallet"
218
- walletName="Sheep Wallet"
219
- onCancel={() => disconnect()}
220
- />
255
+ ## Networks
256
+
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 | ❌ | ❌ |
263
+
264
+ ## REX (Rialo Extended Execution)
265
+
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
271
+
272
+ ### REX Transaction Flow
221
273
 
222
- <LoadingSpinner size="md" color="#6EB9A8" />
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
+ ```
223
281
 
224
- <ConnectionStatus status="connecting" />
225
- <ConnectionStatus status="approving" message="Check your wallet" />
226
- <ConnectionStatus status="error" onRetry={() => connect()} />
282
+ ### REX Config Options
283
+
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
+ }
227
296
  ```
228
297
 
229
- ## Networks
298
+ ## SfS (Stake-for-Service)
299
+
300
+ Stake-for-Service converts staking yield into service credits that pay for gas automatically.
301
+
302
+ ### How It Works
303
+
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
310
+ ```
311
+
312
+ ### SfS Types
313
+
314
+ ```typescript
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;
330
+ }
331
+ ```
332
+
333
+ ## Scan-to-Connect
334
+
335
+ Connect wallet on one device to dApp on another via QR code.
230
336
 
231
- | Network | Chain ID | RPC URL | Symbol |
232
- |----------|-----------------|----------------------------------|--------|
233
- | Mainnet | rialo:mainnet | https://mainnet.rialo.io:4101 | RLO |
234
- | Testnet | rialo:testnet | https://testnet.rialo.io:4101 | tRLO |
235
- | Devnet | rialo:devnet | https://devnet.rialo.io:4101 | dRLO |
236
- | Localnet | rialo:localnet | http://localhost:4101 | lRLO |
337
+ ### Bidirectional Flow
338
+
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
+ ```
237
347
 
238
348
  ## Utilities
239
349
 
@@ -243,11 +353,7 @@ import {
243
353
  formatBalance, // (kelvins, decimals?) => "1.0000"
244
354
  parseBalance, // (rlo) => bigint (kelvins)
245
355
  isValidAddress, // (address) => boolean
246
- toChainId, // (network) => 'rialo:devnet'
247
- fromChainId, // (chainId) => 'devnet'
248
356
  isInstalled, // () => boolean
249
- getProvider, // () => RialoProvider | undefined
250
- waitForProvider, // (timeout?) => Promise<RialoProvider | undefined>
251
357
  NETWORKS, // Network configurations
252
358
  } from '@cookill/wallet-adapter';
253
359
  ```
@@ -256,57 +362,40 @@ import {
256
362
 
257
363
  ```typescript
258
364
  import type {
259
- WalletAccount,
260
- TransactionRequest,
261
- TransactionResult,
262
- SignedMessage,
263
- BalanceResult,
264
- NetworkConfig,
265
- WalletInfo,
266
- RialoProvider,
267
- RialoNetwork,
268
- RialoChainId,
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,
269
374
  } from '@cookill/wallet-adapter';
270
375
  ```
271
376
 
272
- ## Troubleshooting
273
-
274
- ### Connection hangs / freezes
275
-
276
- v3.0 has built-in 20-second timeout. If connection still hangs:
277
-
278
- 1. Make sure extension is installed and unlocked
279
- 2. Check if popup was blocked by browser
280
- 3. Try refreshing the page
281
-
282
- ### Auto-connect not working
283
-
284
- Auto-connect uses `checkSession()` which only restores **existing** sessions silently.
285
- It won't trigger the approval popup. User must explicitly call `connect()` first time.
286
-
287
- ### Modal not opening
288
-
289
- The `WalletProvider` renders the modal automatically. If you see issues:
290
-
291
- ```tsx
292
- // Make sure you're inside WalletProvider
293
- const { openModal } = useWallet();
294
- openModal(); // This should work
295
- ```
296
-
297
- ## Migration from v2.x
377
+ ## Migration from v3.0
298
378
 
299
379
  ```diff
300
- // Imports are the same
380
+ // Imports unchanged
301
381
  import { WalletProvider, ConnectButton } from '@cookill/wallet-adapter/react';
302
382
 
303
- // Hook usage is the same
383
+ // Hook usage unchanged
304
384
  const { connect, connected } = useWallet();
305
385
 
306
- // Main changes:
307
- // - connect() now has 20s timeout built-in
308
- // - autoConnect uses checkSession() (silent, never triggers popup)
309
- // - New SheepWallet class for vanilla JS (replaces RialoWallet)
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();
391
+
392
+ // WalletProvider now supports scanConnectRelay prop
393
+ + <WalletProvider scanConnectRelay="wss://relay.rialo.io">
394
+
395
+ // ConnectButton now shows feature badges
396
+ + <ConnectButton showFeatures={true} />
397
+
398
+ // Connect modal now has "Scan to Connect" tab built-in
310
399
  ```
311
400
 
312
401
  ## License