@0xio/sdk 2.1.8 → 2.3.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/CHANGELOG.md CHANGED
@@ -2,6 +2,57 @@
2
2
 
3
3
  All notable changes to the 0xio Wallet SDK will be documented in this file.
4
4
 
5
+ ## [2.3.0] - 2026-03-10
6
+
7
+ ### Added
8
+ - **Smart Contract Interaction**: New `callContract()` method for state-changing contract calls. The extension builds, signs, and submits via `octra_submit` — works on both mainnet and devnet.
9
+ - **Contract View Calls**: New `contractCallView()` method for read-only contract queries. No wallet unlock or approval popup required.
10
+ - **Contract Storage**: New `getContractStorage()` method to read contract storage by key directly from the chain.
11
+ - **New Types**: `ContractCallData`, `ContractViewCallData`, and `ContractParams` for type-safe contract interaction.
12
+ - **Devnet Version Constant**: New `MIN_EXTENSION_VERSION_DEVNET` export (`'2.2.1'`) for programmatic devnet compatibility checks.
13
+
14
+ ### Improved
15
+ - **Type Safety**: Replaced `any` with `ContractParams` (`ReadonlyArray<string | number | boolean>`) in `ContractCallData.params` and `ContractViewCallData.params`.
16
+ - **Event Handler Typing**: Three internal event handlers (`handleAccountChanged`, `handleNetworkChanged`, `handleBalanceChanged`) now use properly typed parameters instead of `any`.
17
+ - **Error Consistency**: `getNetworkConfig()` now throws `ZeroXIOWalletError` with `ErrorCode.NETWORK_ERROR` instead of a generic `Error`.
18
+ - **UMD Global Name**: Fixed UMD build global from `OctraWalletSDK` to `ZeroXIOWalletSDK` to match SDK branding.
19
+
20
+ ### Security
21
+ - **Fixed wildcard origin**: `simulateExtensionEvent` now uses `window.location.origin` instead of `'*'` wildcard, preventing cross-origin message injection.
22
+ - **signMessage length limit**: Added 10,000 character max to prevent memory exhaustion from oversized signing requests.
23
+ - **Narrowed dev detection**: Removed overly broad `hostname.includes('dev')` check that would enable debug mode on any domain containing "dev" (e.g., `developer.mozilla.org`). Dev mode now only activates on `localhost`, `127.0.0.1`, or when `NODE_ENV=development`.
24
+
25
+ ### Fixed
26
+ - **Message validation**: Increased `isValidMessage()` limit from 280 to 100,000 characters. The 280-char limit was blocking contract call parameters which are serialized JSON and can be large.
27
+
28
+ ### Compatibility
29
+ - **Mainnet Alpha**: Requires 0xio Wallet Extension v2.0.1 or higher
30
+ - **Devnet**: Requires 0xio Wallet Extension v2.2.1 or higher (contract calls, privacy features)
31
+
32
+ ---
33
+
34
+ ## [2.2.0] - 2026-03-08
35
+
36
+ ### Added
37
+ - **Devnet Network Support**: Added full Octra Devnet configuration (`rpcUrl`, `explorerUrl`, `explorerAddressUrl`, `indexerUrl`) to the built-in `NETWORKS` registry.
38
+ - **Expanded `NetworkInfo` Type**: Added `explorerAddressUrl`, `indexerUrl`, and `supportsPrivacy` fields to the `NetworkInfo` interface for richer network metadata.
39
+ - **Privacy Flag**: Each network now exposes `supportsPrivacy: boolean` so DApps can detect FHE/encrypted balance support at the config level.
40
+ - **Devnet Validation**: `isValidNetworkId()` now accepts `'devnet'` in addition to `'mainnet'` and `'custom'`.
41
+
42
+ ### Fixed
43
+ - **Explorer URLs**: Mainnet `explorerUrl` and `explorerAddressUrl` now include trailing `/` to match all other 0xio platforms (extension, app, desktop).
44
+ - **Mock Data**: `generateMockData()` now returns a `NetworkInfo` object with all new fields (`explorerAddressUrl`, `indexerUrl`, `supportsPrivacy`, correct URLs).
45
+
46
+ ### Network Configurations
47
+
48
+ | Network | RPC | Explorer | Privacy | Testnet |
49
+ |---------|-----|----------|---------|---------|
50
+ | Mainnet Alpha | `https://octra.network` | `https://octrascan.io` | No | No |
51
+ | Devnet | `http://165.227.225.79:8080` | `https://devnet.octrascan.io` | Yes | Yes |
52
+ | Custom | User-defined | User-defined | No | No |
53
+
54
+ ---
55
+
5
56
  ## [2.1.8] - 2026-02-13
6
57
 
7
58
  ### Added
package/README.md CHANGED
@@ -1,14 +1,18 @@
1
1
  # 0xio Wallet SDK
2
2
 
3
- **Version:** 2.1.8
3
+ **Version:** 2.3.0
4
4
 
5
5
  Official TypeScript SDK for integrating DApps with 0xio Wallet on Octra Network.
6
6
 
7
- ## What's New in v2.1.8
7
+ ## What's New in v2.3.0
8
8
 
9
- - **Transaction Finality**: `TransactionResult` and `Transaction` now include `finality` field (`'pending' | 'confirmed' | 'rejected'`)
10
- - **RPC Error Types**: 7 new error codes from `octra_submit` and `octra_submitBatch` RPC methods: `MALFORMED_TRANSACTION`, `SELF_TRANSFER`, `SENDER_NOT_FOUND`, `INVALID_SIGNATURE`, `DUPLICATE_TRANSACTION`, `NONCE_TOO_FAR`, `INTERNAL_ERROR`
11
- - **Error Messages**: All new error codes have human-readable messages via `createErrorMessage()`
9
+ - **Smart Contract Calls**: New `callContract()` for state-changing contract interaction (signed, with approval popup)
10
+ - **Contract View Calls**: New `contractCallView()` for read-only queries (no signing, no popup)
11
+ - **Contract Storage**: New `getContractStorage()` to read on-chain contract storage by key
12
+ - **Type Safety**: New `ContractParams` type (`ReadonlyArray<string | number | boolean>`) replaces `any` in contract interfaces; typed event handlers
13
+ - **Error Consistency**: `getNetworkConfig()` now throws `ZeroXIOWalletError` instead of generic `Error`
14
+ - **Security Fixes**: Fixed wildcard origin in dev utils, added signMessage length limit, narrowed dev detection
15
+ - **Message Limit**: Raised `isValidMessage()` from 280 to 100K chars to support contract call parameters
12
16
 
13
17
  ## Installation
14
18
 
@@ -102,6 +106,42 @@ interface TransactionResult {
102
106
  }
103
107
  ```
104
108
 
109
+ ### Smart Contracts
110
+
111
+ #### `wallet.callContract(data: ContractCallData): Promise<TransactionResult>`
112
+ Execute a state-changing contract call. The extension signs and submits via `octra_submit`.
113
+
114
+ ```typescript
115
+ const result = await wallet.callContract({
116
+ contract: 'oct26Lia...', // Contract address
117
+ method: 'swap', // AML method name
118
+ params: [100, true, 90], // Method arguments (flat, not array-wrapped)
119
+ amount: '0', // Native OCT to send (optional, default '0')
120
+ ou: '10000', // Operational units (optional, default '10000')
121
+ });
122
+ console.log('TX Hash:', result.txHash);
123
+ ```
124
+
125
+ #### `wallet.contractCallView(data: ContractViewCallData): Promise<any>`
126
+ Read-only contract query. No signing, no approval popup, no wallet unlock required.
127
+
128
+ ```typescript
129
+ const price = await wallet.contractCallView({
130
+ contract: 'oct26Lia...',
131
+ method: 'get_active_price',
132
+ params: [],
133
+ });
134
+ console.log('Price:', price);
135
+ ```
136
+
137
+ #### `wallet.getContractStorage(contract: string, key: string): Promise<string | null>`
138
+ Read contract storage by key.
139
+
140
+ ```typescript
141
+ const value = await wallet.getContractStorage('oct26Lia...', 'total_supply');
142
+ console.log('Total supply:', value);
143
+ ```
144
+
105
145
  ### Message Signing
106
146
 
107
147
  #### `wallet.signMessage(message: string): Promise<string>`
@@ -168,9 +208,50 @@ try {
168
208
  }
169
209
  ```
170
210
 
211
+ ## Networks
212
+
213
+ The SDK ships with built-in configurations for Octra networks:
214
+
215
+ ```typescript
216
+ import { NETWORKS, getNetworkConfig } from '@0xio/sdk';
217
+
218
+ // Get devnet config
219
+ const devnet = getNetworkConfig('devnet');
220
+ console.log(devnet.rpcUrl); // http://165.227.225.79:8080
221
+ console.log(devnet.supportsPrivacy); // true
222
+ console.log(devnet.isTestnet); // true
223
+
224
+ // Get mainnet config
225
+ const mainnet = getNetworkConfig('mainnet');
226
+ console.log(mainnet.rpcUrl); // https://octra.network
227
+ console.log(mainnet.supportsPrivacy); // false
228
+ ```
229
+
230
+ | Network | Privacy (FHE) | Explorer |
231
+ |---------|:---:|---|
232
+ | Mainnet Alpha | No | [octrascan.io](https://octrascan.io) |
233
+ | Devnet | Yes | [devnet.octrascan.io](https://devnet.octrascan.io) |
234
+
235
+ ### NetworkInfo Type
236
+
237
+ ```typescript
238
+ interface NetworkInfo {
239
+ id: string;
240
+ name: string;
241
+ rpcUrl: string;
242
+ explorerUrl?: string; // Transaction explorer base URL
243
+ explorerAddressUrl?: string; // Address explorer base URL
244
+ indexerUrl?: string; // Indexer/API base URL
245
+ supportsPrivacy: boolean; // FHE encrypted balance support
246
+ color: string; // Brand color hex
247
+ isTestnet: boolean;
248
+ }
249
+ ```
250
+
171
251
  ## Requirements
172
252
 
173
- - 0xio Wallet Extension v2.0.1 or higher
253
+ - 0xio Wallet Extension v2.0.1 or higher (Mainnet Alpha)
254
+ - 0xio Wallet Extension v2.2.1 or higher (Devnet — required for contract calls and privacy features)
174
255
  - Modern browser (Chrome, Firefox, Edge, Brave)
175
256
 
176
257
  ## Documentation
package/dist/index.d.ts CHANGED
@@ -17,6 +17,9 @@ interface NetworkInfo {
17
17
  readonly name: string;
18
18
  readonly rpcUrl: string;
19
19
  readonly explorerUrl?: string;
20
+ readonly explorerAddressUrl?: string;
21
+ readonly indexerUrl?: string;
22
+ readonly supportsPrivacy: boolean;
20
23
  readonly color: string;
21
24
  readonly isTestnet: boolean;
22
25
  }
@@ -27,6 +30,30 @@ interface TransactionData {
27
30
  readonly feeLevel?: 1 | 3;
28
31
  readonly isPrivate?: boolean;
29
32
  }
33
+ /** Flat array of AML-compatible primitive values for contract method arguments. */
34
+ type ContractParams = ReadonlyArray<string | number | boolean>;
35
+ interface ContractCallData {
36
+ /** Contract address (oct-prefixed, 47 chars) */
37
+ readonly contract: string;
38
+ /** Contract method name (e.g. 'swap', 'approve') */
39
+ readonly method: string;
40
+ /** Method arguments — flat primitives, NOT array-wrapped: `[amount, flag]` not `[[amount, flag]]` */
41
+ readonly params: ContractParams;
42
+ /** Native OCT to send with call (human-readable for sendTransaction, micro-units for callContract) */
43
+ readonly amount?: string | number;
44
+ /** Operation units / gas limit (default: 10000) */
45
+ readonly ou?: string | number;
46
+ }
47
+ interface ContractViewCallData {
48
+ /** Contract address (oct-prefixed, 47 chars) */
49
+ readonly contract: string;
50
+ /** Contract method name (e.g. 'balance_of', 'get_active_bin') */
51
+ readonly method: string;
52
+ /** Method arguments — flat primitives, NOT array-wrapped */
53
+ readonly params: ContractParams;
54
+ /** Caller address for view context (defaults to connected wallet) */
55
+ readonly caller?: string;
56
+ }
30
57
  interface SignedTransaction {
31
58
  readonly from: string;
32
59
  readonly to_: string;
@@ -289,6 +316,20 @@ declare class ZeroXIOWallet extends EventEmitter {
289
316
  * Send transaction
290
317
  */
291
318
  sendTransaction(txData: TransactionData): Promise<TransactionResult>;
319
+ /**
320
+ * Call a smart contract method (state-changing).
321
+ * The extension builds, signs, and submits the transaction via octra_submit.
322
+ */
323
+ callContract(callData: ContractCallData): Promise<TransactionResult>;
324
+ /**
325
+ * Read-only contract view call (no signing, no approval popup).
326
+ * Use this to query contract state without submitting a transaction.
327
+ */
328
+ contractCallView(viewData: ContractViewCallData): Promise<any>;
329
+ /**
330
+ * Read contract storage by key.
331
+ */
332
+ getContractStorage(contract: string, key: string): Promise<string | null>;
292
333
  /**
293
334
  * Get transaction history
294
335
  */
@@ -371,7 +412,7 @@ declare class ZeroXIOWallet extends EventEmitter {
371
412
  * to ensure secure wallet interactions.
372
413
  *
373
414
  * @module communication
374
- * @version 2.1.8
415
+ * @version 2.2.0
375
416
  * @license MIT
376
417
  */
377
418
 
@@ -582,7 +623,7 @@ declare function createDefaultBalance(total?: number): Balance;
582
623
  * SDK Configuration constants
583
624
  */
584
625
  declare const SDK_CONFIG: {
585
- readonly version: "2.1.8";
626
+ readonly version: "2.3.0";
586
627
  readonly defaultNetworkId: "mainnet";
587
628
  readonly communicationTimeout: 30000;
588
629
  readonly retryAttempts: 3;
@@ -688,6 +729,10 @@ declare function generateMockData(): {
688
729
  id: string;
689
730
  name: string;
690
731
  rpcUrl: string;
732
+ explorerUrl: string;
733
+ explorerAddressUrl: string;
734
+ indexerUrl: string;
735
+ supportsPrivacy: boolean;
691
736
  color: string;
692
737
  isTestnet: boolean;
693
738
  };
@@ -705,8 +750,9 @@ declare function createLogger(prefix: string, debug: boolean): {
705
750
  groupEnd: () => void;
706
751
  };
707
752
 
708
- declare const SDK_VERSION = "2.1.8";
753
+ declare const SDK_VERSION = "2.3.0";
709
754
  declare const MIN_EXTENSION_VERSION = "2.0.1";
755
+ declare const MIN_EXTENSION_VERSION_DEVNET = "2.2.1";
710
756
  declare const SUPPORTED_EXTENSION_VERSIONS = "^2.0.1";
711
757
  declare function createZeroXIOWallet(config: {
712
758
  appName: string;
@@ -721,5 +767,5 @@ declare function checkSDKCompatibility(): {
721
767
  recommendations: string[];
722
768
  };
723
769
 
724
- export { DEFAULT_NETWORK_ID, ErrorCode, EventEmitter, ExtensionCommunicator, MIN_EXTENSION_VERSION, NETWORKS, SDK_CONFIG, SDK_VERSION, SUPPORTED_EXTENSION_VERSIONS, ZeroXIOWallet, ZeroXIOWalletError, checkBrowserSupport, checkSDKCompatibility, createDefaultBalance, createErrorMessage, createLogger, createOctraWallet, createZeroXIOWallet, delay, formatAddress, formatOCT, formatTimestamp, formatTxHash, formatOCT as formatZeroXIO, fromMicroOCT, fromMicroOCT as fromMicroZeroXIO, generateMockData, getAllNetworks, getDefaultNetwork, getNetworkConfig, isBrowser, isErrorType, isValidAddress, isValidAmount, isValidFeeLevel, isValidMessage, isValidNetworkId, retry, toMicroOCT, toMicroOCT as toMicroZeroXIO, withTimeout };
725
- export type { AccountChangedEvent, Balance, BalanceChangedEvent, ConnectEvent, ConnectOptions, ConnectionInfo, DisconnectEvent, ErrorEvent, ExtensionRequest, ExtensionResponse, NetworkChangedEvent, NetworkInfo, PendingPrivateTransfer, Permission, PrivateBalanceInfo, PrivateTransferData, SDKConfig, SignedTransaction, Transaction, TransactionConfirmedEvent, TransactionData, TransactionFinality, TransactionHistory, TransactionResult, WalletAddress, WalletEvent, WalletEventType };
770
+ export { DEFAULT_NETWORK_ID, ErrorCode, EventEmitter, ExtensionCommunicator, MIN_EXTENSION_VERSION, MIN_EXTENSION_VERSION_DEVNET, NETWORKS, SDK_CONFIG, SDK_VERSION, SUPPORTED_EXTENSION_VERSIONS, ZeroXIOWallet, ZeroXIOWalletError, checkBrowserSupport, checkSDKCompatibility, createDefaultBalance, createErrorMessage, createLogger, createOctraWallet, createZeroXIOWallet, delay, formatAddress, formatOCT, formatTimestamp, formatTxHash, formatOCT as formatZeroXIO, fromMicroOCT, fromMicroOCT as fromMicroZeroXIO, generateMockData, getAllNetworks, getDefaultNetwork, getNetworkConfig, isBrowser, isErrorType, isValidAddress, isValidAmount, isValidFeeLevel, isValidMessage, isValidNetworkId, retry, toMicroOCT, toMicroOCT as toMicroZeroXIO, withTimeout };
771
+ export type { AccountChangedEvent, Balance, BalanceChangedEvent, ConnectEvent, ConnectOptions, ConnectionInfo, ContractCallData, ContractParams, ContractViewCallData, DisconnectEvent, ErrorEvent, ExtensionRequest, ExtensionResponse, NetworkChangedEvent, NetworkInfo, PendingPrivateTransfer, Permission, PrivateBalanceInfo, PrivateTransferData, SDKConfig, SignedTransaction, Transaction, TransactionConfirmedEvent, TransactionData, TransactionFinality, TransactionHistory, TransactionResult, WalletAddress, WalletEvent, WalletEventType };
package/dist/index.esm.js CHANGED
@@ -171,7 +171,7 @@ function isValidNetworkId(networkId) {
171
171
  if (!networkId || typeof networkId !== 'string') {
172
172
  return false;
173
173
  }
174
- const validNetworks = ['mainnet', 'custom'];
174
+ const validNetworks = ['mainnet', 'devnet', 'custom'];
175
175
  return validNetworks.includes(networkId.toLowerCase());
176
176
  }
177
177
  /**
@@ -184,8 +184,8 @@ function isValidMessage(message) {
184
184
  if (typeof message !== 'string') {
185
185
  return false;
186
186
  }
187
- // Check length (adjust based on network limits)
188
- return message.length <= 280;
187
+ // 100KB limit contract call params can be large (serialized JSON)
188
+ return message.length <= 100000;
189
189
  }
190
190
  /**
191
191
  * Validate fee level
@@ -396,7 +396,11 @@ function generateMockData() {
396
396
  id: 'mainnet',
397
397
  name: 'Octra Mainnet Alpha',
398
398
  rpcUrl: 'https://octra.network',
399
- color: '#6366f1',
399
+ explorerUrl: 'https://octrascan.io/transactions/',
400
+ explorerAddressUrl: 'https://octrascan.io/addresses/',
401
+ indexerUrl: 'https://network.octrascan.com',
402
+ supportsPrivacy: false,
403
+ color: '#f59e0b',
400
404
  isTestnet: false
401
405
  }
402
406
  };
@@ -407,41 +411,44 @@ function generateMockData() {
407
411
  function createLogger(prefix, debug) {
408
412
  const isDevelopment = typeof window !== 'undefined' && (window.location.hostname === 'localhost' ||
409
413
  window.location.hostname === '127.0.0.1' ||
410
- window.location.hostname.includes('dev') ||
411
414
  window.__OCTRA_SDK_DEBUG__);
412
415
  // Only enable logging in development mode AND when debug is explicitly enabled
413
416
  const shouldLog = debug && isDevelopment;
417
+ const ts = () => {
418
+ const d = new Date();
419
+ return `${d.toTimeString().slice(0, 8)}.${String(d.getMilliseconds()).padStart(3, '0')}`;
420
+ };
414
421
  return {
415
422
  log: (...args) => {
416
423
  if (shouldLog) {
417
- console.log(`[${prefix}]`, ...args);
424
+ console.log(`[${ts()}][${prefix}]`, ...args);
418
425
  }
419
426
  },
420
427
  warn: (...args) => {
421
428
  if (shouldLog) {
422
- console.warn(`[${prefix}]`, ...args);
429
+ console.warn(`[${ts()}][${prefix}]`, ...args);
423
430
  }
424
431
  },
425
432
  error: (...args) => {
426
433
  // Always show errors in development, even without debug flag
427
434
  if (isDevelopment) {
428
- console.error(`[${prefix}]`, ...args);
435
+ console.error(`[${ts()}][${prefix}]`, ...args);
429
436
  }
430
437
  },
431
438
  debug: (...args) => {
432
439
  if (shouldLog) {
433
- console.debug(`[${prefix}]`, ...args);
440
+ console.debug(`[${ts()}][${prefix}]`, ...args);
434
441
  }
435
442
  },
436
443
  table: (data) => {
437
444
  if (shouldLog) {
438
- console.log(`[${prefix}] Table data:`);
445
+ console.log(`[${ts()}][${prefix}] Table data:`);
439
446
  console.table(data);
440
447
  }
441
448
  },
442
449
  group: (label) => {
443
450
  if (shouldLog) {
444
- console.group(`[${prefix}] ${label}`);
451
+ console.group(`[${ts()}][${prefix}] ${label}`);
445
452
  }
446
453
  },
447
454
  groupEnd: () => {
@@ -460,7 +467,7 @@ function createLogger(prefix, debug) {
460
467
  * to ensure secure wallet interactions.
461
468
  *
462
469
  * @module communication
463
- * @version 2.1.8
470
+ * @version 2.2.0
464
471
  * @license MIT
465
472
  */
466
473
  /**
@@ -982,17 +989,34 @@ const NETWORKS = {
982
989
  id: 'mainnet',
983
990
  name: 'Octra Mainnet Alpha',
984
991
  rpcUrl: 'https://octra.network',
985
- explorerUrl: 'https://octrascan.io/',
986
- color: '#6366f1',
992
+ explorerUrl: 'https://octrascan.io/transactions/',
993
+ explorerAddressUrl: 'https://octrascan.io/addresses/',
994
+ indexerUrl: 'https://network.octrascan.com',
995
+ supportsPrivacy: false,
996
+ color: '#f59e0b',
987
997
  isTestnet: false
988
998
  },
999
+ 'devnet': {
1000
+ id: 'devnet',
1001
+ name: 'Octra Devnet',
1002
+ rpcUrl: 'http://165.227.225.79:8080',
1003
+ explorerUrl: 'https://devnet.octrascan.io/tx.html?hash=',
1004
+ explorerAddressUrl: 'https://devnet.octrascan.io/address.html?addr=',
1005
+ indexerUrl: 'https://devnet.octrascan.io',
1006
+ supportsPrivacy: true,
1007
+ color: '#8b5cf6',
1008
+ isTestnet: true
1009
+ },
989
1010
  'custom': {
990
1011
  id: 'custom',
991
1012
  name: 'Custom Network',
992
1013
  rpcUrl: '',
993
1014
  explorerUrl: '',
1015
+ explorerAddressUrl: '',
1016
+ indexerUrl: '',
1017
+ supportsPrivacy: false,
994
1018
  color: '#64748b',
995
- isTestnet: false // User configurable - can be mainnet or testnet
1019
+ isTestnet: false
996
1020
  }
997
1021
  };
998
1022
  const DEFAULT_NETWORK_ID = 'mainnet';
@@ -1002,7 +1026,7 @@ const DEFAULT_NETWORK_ID = 'mainnet';
1002
1026
  function getNetworkConfig(networkId = DEFAULT_NETWORK_ID) {
1003
1027
  const network = NETWORKS[networkId];
1004
1028
  if (!network) {
1005
- throw new Error(`Unknown network ID: ${networkId}`);
1029
+ throw new ZeroXIOWalletError(ErrorCode.NETWORK_ERROR, `Unknown network ID: ${networkId}`);
1006
1030
  }
1007
1031
  return network;
1008
1032
  }
@@ -1031,7 +1055,7 @@ function createDefaultBalance(total = 0) {
1031
1055
  * SDK Configuration constants
1032
1056
  */
1033
1057
  const SDK_CONFIG = {
1034
- version: '2.1.8',
1058
+ version: '2.3.0',
1035
1059
  defaultNetworkId: DEFAULT_NETWORK_ID,
1036
1060
  communicationTimeout: 30000, // 30 seconds
1037
1061
  retryAttempts: 3,
@@ -1339,6 +1363,78 @@ class ZeroXIOWallet extends EventEmitter {
1339
1363
  throw new ZeroXIOWalletError(ErrorCode.TRANSACTION_FAILED, 'Failed to send transaction', error);
1340
1364
  }
1341
1365
  }
1366
+ /**
1367
+ * Call a smart contract method (state-changing).
1368
+ * The extension builds, signs, and submits the transaction via octra_submit.
1369
+ */
1370
+ async callContract(callData) {
1371
+ this.ensureConnected();
1372
+ try {
1373
+ this.logger.log('Calling contract:', callData);
1374
+ const result = await this.communicator.sendRequest('call_contract', {
1375
+ contract: callData.contract,
1376
+ method: callData.method,
1377
+ params: callData.params,
1378
+ amount: callData.amount != null ? String(callData.amount) : '0',
1379
+ ou: callData.ou != null ? String(callData.ou) : '10000',
1380
+ });
1381
+ this.logger.log('Contract call result:', result);
1382
+ return result;
1383
+ }
1384
+ catch (error) {
1385
+ this.logger.error('Contract call failed:', error);
1386
+ if (error instanceof ZeroXIOWalletError) {
1387
+ throw error;
1388
+ }
1389
+ throw new ZeroXIOWalletError(ErrorCode.TRANSACTION_FAILED, 'Failed to call contract', error);
1390
+ }
1391
+ }
1392
+ /**
1393
+ * Read-only contract view call (no signing, no approval popup).
1394
+ * Use this to query contract state without submitting a transaction.
1395
+ */
1396
+ async contractCallView(viewData) {
1397
+ this.ensureInitialized();
1398
+ try {
1399
+ this.logger.log('Contract view call:', viewData);
1400
+ const result = await this.communicator.sendRequest('contract_call_view', {
1401
+ contract: viewData.contract,
1402
+ method: viewData.method,
1403
+ params: viewData.params,
1404
+ caller: viewData.caller || this.getAddress() || '',
1405
+ });
1406
+ this.logger.log('Contract view result:', result);
1407
+ return result;
1408
+ }
1409
+ catch (error) {
1410
+ this.logger.error('Contract view call failed:', error);
1411
+ if (error instanceof ZeroXIOWalletError) {
1412
+ throw error;
1413
+ }
1414
+ throw new ZeroXIOWalletError(ErrorCode.NETWORK_ERROR, 'Failed to call contract view', error);
1415
+ }
1416
+ }
1417
+ /**
1418
+ * Read contract storage by key.
1419
+ */
1420
+ async getContractStorage(contract, key) {
1421
+ this.ensureInitialized();
1422
+ try {
1423
+ this.logger.log('Getting contract storage:', { contract, key });
1424
+ const result = await this.communicator.sendRequest('get_contract_storage', {
1425
+ contract,
1426
+ key,
1427
+ });
1428
+ return result;
1429
+ }
1430
+ catch (error) {
1431
+ this.logger.error('Get contract storage failed:', error);
1432
+ if (error instanceof ZeroXIOWalletError) {
1433
+ throw error;
1434
+ }
1435
+ throw new ZeroXIOWalletError(ErrorCode.NETWORK_ERROR, 'Failed to get contract storage', error);
1436
+ }
1437
+ }
1342
1438
  /**
1343
1439
  * Get transaction history
1344
1440
  */
@@ -1479,6 +1575,9 @@ class ZeroXIOWallet extends EventEmitter {
1479
1575
  if (!message || typeof message !== 'string') {
1480
1576
  throw new ZeroXIOWalletError(ErrorCode.SIGNATURE_FAILED, 'Message must be a non-empty string');
1481
1577
  }
1578
+ if (message.length > 10000) {
1579
+ throw new ZeroXIOWalletError(ErrorCode.SIGNATURE_FAILED, 'Message too long (max 10,000 characters)');
1580
+ }
1482
1581
  try {
1483
1582
  this.logger.log('Requesting message signature for:', message.substring(0, 100) + (message.length > 100 ? '...' : ''));
1484
1583
  const result = await this.communicator.sendRequest('signMessage', { message });
@@ -1543,7 +1642,7 @@ class ZeroXIOWallet extends EventEmitter {
1543
1642
  const accountChangedEvent = {
1544
1643
  previousAddress,
1545
1644
  newAddress: data.address,
1546
- balance: data.balance
1645
+ balance: data.balance ?? this.connectionInfo.balance
1547
1646
  };
1548
1647
  this.emit('accountChanged', accountChangedEvent);
1549
1648
  this.logger.log('Account changed:', accountChangedEvent);
@@ -1657,8 +1756,9 @@ var wallet = /*#__PURE__*/Object.freeze({
1657
1756
  */
1658
1757
  // Main exports
1659
1758
  // Version information
1660
- const SDK_VERSION = '2.1.8';
1661
- const MIN_EXTENSION_VERSION = '2.0.1';
1759
+ const SDK_VERSION = '2.3.0';
1760
+ const MIN_EXTENSION_VERSION = '2.0.1'; // Mainnet Alpha
1761
+ const MIN_EXTENSION_VERSION_DEVNET = '2.2.1'; // Devnet (contract calls, privacy)
1662
1762
  const SUPPORTED_EXTENSION_VERSIONS = '^2.0.1'; // Supports all versions >= 2.0.1
1663
1763
  // Quick setup function for simple use cases
1664
1764
  async function createZeroXIOWallet(config) {
@@ -1712,8 +1812,7 @@ if (typeof window !== 'undefined') {
1712
1812
  window.__ZEROXIO_SDK_VERSION__ = SDK_VERSION;
1713
1813
  // Development mode detection
1714
1814
  const isDevelopment = window.location.hostname === 'localhost' ||
1715
- window.location.hostname === '127.0.0.1' ||
1716
- window.location.hostname.includes('dev');
1815
+ window.location.hostname === '127.0.0.1';
1717
1816
  if (isDevelopment) {
1718
1817
  // Set debug flag but don't automatically log
1719
1818
  window.__OCTRA_SDK_DEBUG__ = true;
@@ -1741,7 +1840,7 @@ if (typeof window !== 'undefined') {
1741
1840
  window.postMessage({
1742
1841
  source: '0xio-sdk-bridge',
1743
1842
  event: { type: eventType, data }
1744
- }, '*');
1843
+ }, window.location.origin);
1745
1844
  console.log('[0xio SDK] Simulated extension event:', eventType, data);
1746
1845
  },
1747
1846
  showWelcome: () => {
@@ -1758,5 +1857,5 @@ if (typeof window !== 'undefined') {
1758
1857
  }
1759
1858
  }
1760
1859
 
1761
- export { DEFAULT_NETWORK_ID, ErrorCode, EventEmitter, ExtensionCommunicator, MIN_EXTENSION_VERSION, NETWORKS, SDK_CONFIG, SDK_VERSION, SUPPORTED_EXTENSION_VERSIONS, ZeroXIOWallet, ZeroXIOWalletError, checkBrowserSupport, checkSDKCompatibility, createDefaultBalance, createErrorMessage, createLogger, createOctraWallet, createZeroXIOWallet, delay, formatAddress, formatOCT, formatTimestamp, formatTxHash, formatOCT as formatZeroXIO, fromMicroOCT, fromMicroOCT as fromMicroZeroXIO, generateMockData, getAllNetworks, getDefaultNetwork, getNetworkConfig, isBrowser, isErrorType, isValidAddress, isValidAmount, isValidFeeLevel, isValidMessage, isValidNetworkId, retry, toMicroOCT, toMicroOCT as toMicroZeroXIO, withTimeout };
1860
+ export { DEFAULT_NETWORK_ID, ErrorCode, EventEmitter, ExtensionCommunicator, MIN_EXTENSION_VERSION, MIN_EXTENSION_VERSION_DEVNET, NETWORKS, SDK_CONFIG, SDK_VERSION, SUPPORTED_EXTENSION_VERSIONS, ZeroXIOWallet, ZeroXIOWalletError, checkBrowserSupport, checkSDKCompatibility, createDefaultBalance, createErrorMessage, createLogger, createOctraWallet, createZeroXIOWallet, delay, formatAddress, formatOCT, formatTimestamp, formatTxHash, formatOCT as formatZeroXIO, fromMicroOCT, fromMicroOCT as fromMicroZeroXIO, generateMockData, getAllNetworks, getDefaultNetwork, getNetworkConfig, isBrowser, isErrorType, isValidAddress, isValidAmount, isValidFeeLevel, isValidMessage, isValidNetworkId, retry, toMicroOCT, toMicroOCT as toMicroZeroXIO, withTimeout };
1762
1861
  //# sourceMappingURL=index.esm.js.map