@0xio/sdk 2.7.0 → 2.7.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  All notable changes to the 0xio Wallet SDK will be documented in this file.
4
4
 
5
+ ## [2.7.1] - 2026-05-27
6
+
7
+ ### Security
8
+
9
+ - **LOW (re-assessed from HIGH):** Removed `this.config.networkId` silent fallback in `connect()` and `getConnectionStatus()`. If neither `networkInfo` nor `networkId` can be resolved from the response, `connect()` now throws `NETWORK_ERROR` and `getConnectionStatus()` returns cached state. The current extension always returns valid `networkInfo`; this hardens against malformed responses from custom or future adapters.
10
+ - **MED-1:** Added `SDKConfig.trustedParentOrigins` — when set, only listed origins (+ `tauri://`) are trusted as parent iframe bridges; implicit localhost trust is disabled. Omitting the field keeps existing dev-friendly behavior.
11
+ - **LOW-2:** `validateNetworkInfo()` now rejects `http://` `rpcUrl` values on non-testnet networks. Testnet networks (`isTestnet: true`) and localhost are unaffected. Prevents a malicious bridge from injecting an insecure RPC endpoint.
12
+ - **LOW-19:** `encryptBalance()`, `decryptBalance()`, `sendPrivateTransfer()`, and `callContract()` now throw `INVALID_AMOUNT` when a numeric amount cannot be represented exactly in micro-OCT (6 decimal places). Pass a string (e.g. `"0.300000"`) for exact control.
13
+ - **LOW-28 (docs):** `ContractCallData.amount` JSDoc corrected — field is OCT, not micro-units. No behavior change.
14
+
15
+ ### Added
16
+
17
+ - **`OctraProviderAdapter`** (`src/supports/octra-provider.ts`): RFC-O-1 compliant transport adapter that uses `window.octra.request()` instead of the postMessage bridge. Detects any wallet exposing `window.octra.isOctra === true`. Translates SDK method names to RFC-O-1 method names (`send_transaction` → `octra_sendTransaction`, etc.) and maps events back to SDK vocabulary. Registered second in the adapter registry — existing DApps using the postMessage bridge are unaffected.
18
+ - **`listenForReady`** in `OctraProviderAdapter` now also listens for `octra#initialized` CustomEvent (dispatched by 0xio extension v2.4.3+) in addition to `octraWalletReady`, ensuring the provider is detected immediately on page load.
19
+
20
+ ### Fixed
21
+
22
+ - Mainnet RPC URL in docs updated to `https://octra.network` (was stale `http://46.101.86.250:8080`)
23
+
24
+ ### Compatibility
25
+
26
+ - No breaking changes — `ZeroXIOAdapter` (postMessage bridge) remains the default and takes priority when `window.wallet0xio` is present
27
+ - Old DApps work unchanged; new DApps can opt into `OctraProviderAdapter` explicitly or via `detectWalletAdapter()`
28
+ - Requires 0xio Wallet Extension v2.4.3+ for `octra#initialized` event; falls back to `octraWalletReady` on older versions
29
+
5
30
  ## [2.7.0] - 2026-05-16
6
31
 
7
32
  ### Security (post-audit remediation)
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 0xio Wallet SDK
2
2
 
3
- **Version:** 2.7.0
3
+ **Version:** 2.7.1
4
4
 
5
5
  Official TypeScript SDK for integrating DApps with 0xio Wallet on Octra Network.
6
6
 
@@ -272,7 +272,7 @@ console.log(devnet.isTestnet); // true
272
272
 
273
273
  // Get mainnet config
274
274
  const mainnet = getNetworkConfig('mainnet');
275
- console.log(mainnet.rpcUrl); // http://46.101.86.250:8080
275
+ console.log(mainnet.rpcUrl); // https://octra.network
276
276
  console.log(mainnet.supportsPrivacy); // true
277
277
  ```
278
278
 
@@ -339,6 +339,37 @@ const wallet = new ZeroXIOWallet({ appName: 'My DApp', adapter: ZeroXIOAdapter }
339
339
 
340
340
  See `DOCUMENTATION.md → Wallet Adapter System` for the full interface spec.
341
341
 
342
+ ## RFC-O-1 Provider Interface (`window.octra`)
343
+
344
+ The 0xio extension exposes a standard `window.octra` provider per the RFC-O-1 spec in addition to the legacy `window.wallet0xio` bridge. The SDK supports both automatically.
345
+
346
+ ```typescript
347
+ // window.octra shape (injected by the extension)
348
+ window.octra.isOctra // true — standard wallet detection
349
+ window.octra.request({ method: 'octra_requestAccounts', params: [{}] })
350
+ window.octra.on('accountsChanged', handler)
351
+ window.octra.removeListener('accountsChanged', handler)
352
+ ```
353
+
354
+ ### How adapter priority works
355
+
356
+ When the SDK initializes, `detectWalletAdapter()` runs detection in order:
357
+
358
+ 1. **`ZeroXIOAdapter`** — detected via `window.wallet0xio` / `window.ZeroXIOWallet` (postMessage bridge). Priority when the 0xio extension is installed — existing DApps are unaffected.
359
+ 2. **`OctraProviderAdapter`** — detected via `window.octra.isOctra === true`. Used when only the RFC-O-1 provider is present (third-party RFC-O-1 wallets, or DApps that explicitly request it).
360
+
361
+ Old DApps using the postMessage bridge continue to work unchanged. New DApps can opt into `OctraProviderAdapter` directly:
362
+
363
+ ```typescript
364
+ import { ZeroXIOWallet, OctraProviderAdapter } from '@0xio/sdk';
365
+
366
+ // Explicitly use the RFC-O-1 window.octra provider
367
+ const wallet = new ZeroXIOWallet({
368
+ appName: 'My DApp',
369
+ adapter: OctraProviderAdapter,
370
+ });
371
+ ```
372
+
342
373
  ## Requirements
343
374
 
344
375
  - 0xio Wallet Extension v2.0.1 or higher (Mainnet Alpha)
package/dist/index.d.ts CHANGED
@@ -187,8 +187,8 @@ interface ContractCallData {
187
187
  */
188
188
  readonly params: ContractParams;
189
189
  /**
190
- * Native OCT to send with the call (in micro-units, 1 OCT = 1000000).
191
- * Set to 0 for calls that don't transfer native tokens.
190
+ * Native OCT to send with the call (in OCT, same unit as sendTransaction.amount).
191
+ * Set to '0' for calls that don't transfer native tokens.
192
192
  */
193
193
  readonly amount?: string | number;
194
194
  /**
@@ -221,8 +221,16 @@ interface SignedTransaction {
221
221
  }
222
222
  type TransactionFinality = 'pending' | 'confirmed' | 'rejected' | 'dropped';
223
223
  interface TransactionResult {
224
- readonly txHash: string;
225
- readonly success: boolean;
224
+ /** RFC-O-1 canonical hash field */
225
+ readonly hash?: string;
226
+ /** RFC-O-1 canonical accepted field */
227
+ readonly accepted?: boolean;
228
+ /** RFC-O-1 status field */
229
+ readonly status?: TransactionFinality;
230
+ /** @deprecated Use hash */
231
+ readonly txHash?: string;
232
+ /** @deprecated Use accepted */
233
+ readonly success?: boolean;
226
234
  readonly finality?: TransactionFinality;
227
235
  readonly message?: string;
228
236
  readonly explorerUrl?: string;
@@ -257,11 +265,14 @@ interface ConnectionInfo {
257
265
  permissions?: Permission[];
258
266
  }
259
267
  interface ConnectOptions {
268
+ /** RFC-O-1 canonical field name */
269
+ readonly permissions?: Permission[];
270
+ /** @deprecated Use permissions */
260
271
  readonly requestPermissions?: Permission[];
261
272
  readonly networkId?: string;
262
273
  }
263
- type Permission = 'read_address' | 'read_balance' | 'send_transactions' | 'sign_messages' | 'view_private_balance' | 'private_transfers';
264
- type WalletEventType = 'connect' | 'disconnect' | 'accountChanged' | 'balanceChanged' | 'networkChanged' | 'transactionConfirmed' | 'error' | 'extensionLocked' | 'extensionUnlocked';
274
+ type Permission = 'read_address' | 'read_balance' | 'read_public_key' | 'send_transactions' | 'sign_messages' | 'contract_calls' | 'view_private_balance' | 'view_encrypted_balance' | 'private_transfers' | 'encrypt_balance' | 'decrypt_balance' | 'stealth_scan' | 'stealth_claim';
275
+ type WalletEventType = 'connect' | 'disconnect' | 'accountChanged' | 'balanceChanged' | 'networkChanged' | 'transactionConfirmed' | 'permissionsChanged' | 'message' | 'error' | 'extensionLocked' | 'extensionUnlocked';
265
276
  interface WalletEvent<T = any> {
266
277
  readonly type: WalletEventType;
267
278
  readonly data: T;
@@ -355,6 +366,12 @@ interface SDKConfig {
355
366
  readonly requiredPermissions?: Permission[];
356
367
  readonly networkId?: string;
357
368
  readonly debug?: boolean;
369
+ /**
370
+ * Exact origins allowed as parent iframe bridge (e.g. 'https://app.example.com').
371
+ * When set, only these origins (plus tauri://) are trusted — implicit localhost trust
372
+ * is disabled. Leave unset for development (all localhost trusted by default).
373
+ */
374
+ readonly trustedParentOrigins?: string[];
358
375
  /**
359
376
  * Custom wallet transport adapter.
360
377
  * Defaults to ZeroXIOAdapter (0xio extension postMessage protocol).
@@ -384,55 +401,20 @@ interface ExtensionResponse<T = any> {
384
401
  readonly timestamp: number;
385
402
  }
386
403
 
387
- /**
388
- * 0xio Wallet SDK - Event System
389
- * Type-safe event emitter for wallet events
390
- */
391
-
392
404
  type EventListener<T = any> = (event: WalletEvent<T>) => void;
393
405
  declare class EventEmitter {
394
406
  private listeners;
395
- private debug;
396
- constructor(debug?: boolean);
397
- /**
398
- * Add event listener
399
- */
407
+ constructor(_debug?: boolean);
400
408
  on<T = any>(eventType: WalletEventType, listener: EventListener<T>): void;
401
- /**
402
- * Remove event listener
403
- */
404
409
  off<T = any>(eventType: WalletEventType, listener: EventListener<T>): void;
405
- /**
406
- * Add one-time event listener
407
- */
408
410
  once<T = any>(eventType: WalletEventType, listener: EventListener<T>): void;
409
- /**
410
- * Emit event to all listeners
411
- */
412
411
  emit<T = any>(eventType: WalletEventType, data: T): void;
413
- /**
414
- * Remove all listeners for a specific event type
415
- */
416
412
  removeAllListeners(eventType?: WalletEventType): void;
417
- /**
418
- * Get number of listeners for an event type
419
- */
420
413
  listenerCount(eventType: WalletEventType): number;
421
- /**
422
- * Get all event types that have listeners
423
- */
424
414
  eventTypes(): WalletEventType[];
425
- /**
426
- * Check if there are any listeners for an event type
427
- */
428
415
  hasListeners(eventType: WalletEventType): boolean;
429
416
  }
430
417
 
431
- /**
432
- * 0xio Wallet SDK - Main Wallet Class
433
- * Primary interface for DApp developers to interact with 0xio Wallet
434
- */
435
-
436
418
  declare class ZeroXIOWallet extends EventEmitter {
437
419
  private communicator;
438
420
  private config;
@@ -442,18 +424,8 @@ declare class ZeroXIOWallet extends EventEmitter {
442
424
  private _sessionVersion;
443
425
  private logger;
444
426
  constructor(config: SDKConfig);
445
- /**
446
- * Initialize the SDK
447
- * Must be called before using any other methods
448
- */
449
427
  initialize(): Promise<boolean>;
450
- /**
451
- * Check if SDK is initialized
452
- */
453
428
  isReady(): boolean;
454
- /**
455
- * Connect to wallet
456
- */
457
429
  connect(options?: ConnectOptions): Promise<ConnectEvent>;
458
430
  /**
459
431
  * Disconnect from wallet
@@ -484,22 +456,22 @@ declare class ZeroXIOWallet extends EventEmitter {
484
456
  * Get the extension's current network ID ('mainnet' or 'devnet')
485
457
  */
486
458
  getNetworkId(): string | null;
487
- /**
488
- * Get current wallet address
489
- */
490
459
  getAddress(): string | null;
491
- /**
492
- * Get current balance
493
- */
494
460
  getBalance(forceRefresh?: boolean): Promise<Balance>;
461
+ getNetworkInfo(): Promise<NetworkInfo>;
462
+ sendTransaction(txData: TransactionData): Promise<TransactionResult>;
495
463
  /**
496
- * Get network information
464
+ * Sign a transaction without broadcasting it (RFC-O-1 octra_signTransaction).
465
+ * Returns the signed transaction object for manual submission via submitTransaction().
497
466
  */
498
- getNetworkInfo(): Promise<NetworkInfo>;
467
+ signTransaction(txData: TransactionData): Promise<{
468
+ signedTx: any;
469
+ }>;
499
470
  /**
500
- * Send transaction
471
+ * Broadcast a pre-signed transaction (RFC-O-1 octra_submitTransaction).
472
+ * Use after signTransaction() to submit the signed tx to the network.
501
473
  */
502
- sendTransaction(txData: TransactionData): Promise<TransactionResult>;
474
+ submitTransaction(signedTx: any): Promise<TransactionResult>;
503
475
  /**
504
476
  * Call a smart contract method (state-changing).
505
477
  * The extension builds, signs, and submits the transaction via octra_submit.
@@ -518,9 +490,6 @@ declare class ZeroXIOWallet extends EventEmitter {
518
490
  * Get transaction history
519
491
  */
520
492
  getTransactionHistory(page?: number, limit?: number): Promise<TransactionHistory>;
521
- /**
522
- * Get private balance information
523
- */
524
493
  getPrivateBalanceInfo(): Promise<PrivateBalanceInfo>;
525
494
  /**
526
495
  * Encrypt public balance to private
@@ -576,48 +545,21 @@ declare class ZeroXIOWallet extends EventEmitter {
576
545
  private ensureInitialized;
577
546
  private ensureConnected;
578
547
  private setupExtensionEventListeners;
579
- /**
580
- * Handle account changed event from extension
581
- */
582
548
  private handleAccountChanged;
583
- /**
584
- * Handle network changed event from extension
585
- */
586
549
  private handleNetworkChanged;
587
- /**
588
- * Handle balance changed event from extension
589
- */
590
550
  private handleBalanceChanged;
591
- /**
592
- * Handle extension locked event
593
- */
594
551
  private handleExtensionLocked;
595
- /**
596
- * Handle extension unlocked event
597
- */
598
552
  private handleExtensionUnlocked;
599
- /**
600
- * Handle transaction confirmed event
601
- */
602
553
  private handleTransactionConfirmed;
603
554
  /**
604
- * Clean up SDK resources
555
+ * Reject numeric amounts that cannot be represented exactly in micro-OCT.
556
+ * e.g. 0.1 + 0.2 = 0.30000000000000004 — the extension would sign the wrong value.
557
+ * String amounts bypass this check (caller is responsible for correctness).
605
558
  */
559
+ private assertExactOCTAmount;
606
560
  cleanup(): void;
607
561
  }
608
562
 
609
- /**
610
- * 0xio Wallet SDK - Extension Communication Module
611
- *
612
- * @fileoverview Manages secure communication between the SDK and browser extension.
613
- * Implements message passing, request/response handling, rate limiting, and origin validation
614
- * to ensure secure wallet interactions.
615
- *
616
- * @module communication
617
- * @version 2.7.0
618
- * @license MIT
619
- */
620
-
621
563
  declare class ExtensionCommunicator extends EventEmitter {
622
564
  private pendingRequests;
623
565
  private isInitialized;
@@ -779,29 +721,15 @@ declare function isValidNetworkId(networkId: string): boolean;
779
721
  * Accepts a numeric total or undefined — never pass a Balance object here.
780
722
  */
781
723
  declare function createDefaultBalance(total?: number): Balance;
782
- /**
783
- * SDK Configuration constants
784
- */
785
724
  declare const SDK_CONFIG: {
786
- readonly version: "2.7.0";
725
+ readonly version: "2.7.1";
787
726
  readonly defaultNetworkId: "mainnet";
788
727
  readonly communicationTimeout: 30000;
789
728
  readonly retryAttempts: 3;
790
729
  readonly retryDelay: 1000;
791
730
  };
792
- /**
793
- * Get default network configuration
794
- */
795
731
  declare function getDefaultNetwork(): NetworkInfo;
796
732
 
797
- /**
798
- * 0xio Wallet SDK - Utilities
799
- * Helper functions for validation, formatting, and common operations
800
- */
801
-
802
- /**
803
- * Validate wallet address for Octra blockchain
804
- */
805
733
  declare function isValidAddress(address: string): boolean;
806
734
  /**
807
735
  * Validate transaction amount.
@@ -809,13 +737,7 @@ declare function isValidAddress(address: string): boolean;
809
737
  * String amounts avoid JS number precision loss for very large values.
810
738
  */
811
739
  declare function isValidAmount(amount: string | number): boolean;
812
- /**
813
- * Validate transaction message
814
- */
815
740
  declare function isValidMessage(message: string): boolean;
816
- /**
817
- * Validate fee level
818
- */
819
741
  declare function isValidFeeLevel(feeLevel: number): boolean;
820
742
  /**
821
743
  * Derive the canonical Octra address from a base64-encoded Ed25519 public key.
@@ -823,56 +745,20 @@ declare function isValidFeeLevel(feeLevel: number): boolean;
823
745
  * Source of truth: ocho-push-server/src/index.ts#deriveAddressFromPubkey
824
746
  */
825
747
  declare function deriveOctraAddress(publicKeyBase64: string): Promise<string>;
826
- /**
827
- * Format OCT amount for display
828
- */
829
748
  declare function formatOCT(amount: number | string, decimals?: number): string;
830
- /**
831
- * Format address for display (truncated)
832
- */
833
749
  declare function formatAddress(address: string, prefixLength?: number, suffixLength?: number): string;
834
- /**
835
- * Format timestamp for display
836
- */
837
750
  declare function formatTimestamp(timestamp: number): string;
838
- /**
839
- * Format transaction hash for display
840
- */
841
751
  declare function formatTxHash(hash: string, length?: number): string;
842
- /**
843
- * Convert OCT to micro OCT (for network transmission)
844
- */
845
752
  declare function toMicroOCT(amount: number): string;
846
- /**
847
- * Convert micro OCT to OCT (for display)
848
- */
849
753
  declare function fromMicroOCT(microAmount: string | number): number;
850
- /**
851
- * Create standardized error messages
852
- */
853
754
  declare function createErrorMessage(code: ErrorCode, context?: string): string;
854
- /**
855
- * Check if error is a specific type
856
- */
857
755
  declare function isErrorType(error: any, code: ErrorCode): boolean;
858
- /**
859
- * Create a promise that resolves after a delay
860
- */
861
756
  declare function delay(ms: number): Promise<void>;
862
- /**
863
- * Check if running in browser environment
864
- */
865
757
  declare function isBrowser(): boolean;
866
- /**
867
- * Check if browser supports required features
868
- */
869
758
  declare function checkBrowserSupport(): {
870
759
  supported: boolean;
871
760
  missingFeatures: string[];
872
761
  };
873
- /**
874
- * Generate mock data for development/testing
875
- */
876
762
  declare function generateMockData(): {
877
763
  address: string;
878
764
  balance: {
@@ -893,9 +779,6 @@ declare function generateMockData(): {
893
779
  isTestnet: boolean;
894
780
  };
895
781
  };
896
- /**
897
- * Create development logger
898
- */
899
782
  declare function createLogger(prefix: string, debug: boolean): {
900
783
  log: (...args: any[]) => void;
901
784
  warn: (...args: any[]) => void;
@@ -906,7 +789,7 @@ declare function createLogger(prefix: string, debug: boolean): {
906
789
  groupEnd: () => void;
907
790
  };
908
791
 
909
- declare const SDK_VERSION = "2.7.0";
792
+ declare const SDK_VERSION = "2.7.1";
910
793
  declare const MIN_EXTENSION_VERSION = "2.0.1";
911
794
  declare const MIN_EXTENSION_VERSION_DEVNET = "2.2.1";
912
795
  declare const SUPPORTED_EXTENSION_VERSIONS = "^2.0.1";