@thru/browser-sdk 0.0.4 → 0.0.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/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { AddressType, ConnectResult, WalletAddress, IThruChain } from '@thru/chain-interfaces';
2
- export { ConnectResult, IThruChain, SignMessageParams, SignMessageResult, WalletAddress } from '@thru/chain-interfaces';
1
+ import { AddressType, ConnectResult, WalletAccount, IThruChain } from '@thru/chain-interfaces';
2
+ export { ConnectResult, IThruChain, SignMessageParams, SignMessageResult, WalletAccount } from '@thru/chain-interfaces';
3
3
  import { ConnectMetadataInput } from '@thru/protocol';
4
- import { Thru } from '@thru/thru-sdk';
4
+ import { Thru } from '@thru/thru-sdk/client';
5
5
  export { ErrorCode } from '@thru/embedded-provider';
6
6
 
7
7
  interface BrowserSDKConfig {
@@ -12,7 +12,7 @@ interface BrowserSDKConfig {
12
12
  interface ConnectOptions {
13
13
  metadata?: ConnectMetadataInput;
14
14
  }
15
- type SDKEvent = 'connect' | 'disconnect' | 'lock' | 'error';
15
+ type SDKEvent = 'connect' | 'disconnect' | 'lock' | 'error' | 'accountChanged';
16
16
  type EventCallback = (...args: any[]) => void;
17
17
  /**
18
18
  * Browser SDK - Main entry point for dApp developers
@@ -45,9 +45,11 @@ declare class BrowserSDK {
45
45
  */
46
46
  isConnected(): boolean;
47
47
  /**
48
- * Get all addresses
48
+ * Get all accounts
49
49
  */
50
- getAddresses(): WalletAddress[];
50
+ getAccounts(): WalletAccount[];
51
+ getSelectedAccount(): WalletAccount | null;
52
+ selectAccount(publicKey: string): Promise<WalletAccount>;
51
53
  /**
52
54
  * Get Thru chain API (iframe-backed signer)
53
55
  */
@@ -80,6 +82,7 @@ declare class BrowserSDK {
80
82
  private resolveAppUrl;
81
83
  private deriveAppName;
82
84
  getThru(): Thru;
85
+ private refreshCachedAccounts;
83
86
  }
84
87
 
85
88
  export { BrowserSDK, type BrowserSDKConfig, type ConnectOptions, type EventCallback, type SDKEvent };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { EmbeddedProvider } from '@thru/embedded-provider';
2
2
  export { ErrorCode } from '@thru/embedded-provider';
3
3
  import { EMBEDDED_PROVIDER_EVENTS } from '@thru/protocol';
4
- import { createThruClient } from '@thru/thru-sdk';
4
+ import { createThruClient } from '@thru/thru-sdk/client';
5
5
 
6
6
  // ../chain-interfaces/dist/index.js
7
7
  var AddressType = {
@@ -86,10 +86,20 @@ var BrowserSDK = class {
86
86
  return this.provider.isConnected();
87
87
  }
88
88
  /**
89
- * Get all addresses
89
+ * Get all accounts
90
90
  */
91
- getAddresses() {
92
- return this.provider.getAddresses();
91
+ getAccounts() {
92
+ const accounts = this.provider.getAccounts();
93
+ this.refreshCachedAccounts(accounts);
94
+ return accounts;
95
+ }
96
+ getSelectedAccount() {
97
+ return this.provider.getSelectedAccount();
98
+ }
99
+ async selectAccount(publicKey) {
100
+ const account = await this.provider.selectAccount(publicKey);
101
+ this.refreshCachedAccounts(this.provider.getAccounts(), account);
102
+ return account;
93
103
  }
94
104
  /**
95
105
  * Get Thru chain API (iframe-backed signer)
@@ -150,6 +160,11 @@ var BrowserSDK = class {
150
160
  this.emit("lock", data);
151
161
  this.emit("disconnect", { reason: "locked" });
152
162
  });
163
+ this.provider.on(EMBEDDED_PROVIDER_EVENTS.ACCOUNT_CHANGED, (data) => {
164
+ const account = data?.account ?? data;
165
+ this.refreshCachedAccounts(this.provider.getAccounts(), account ?? null);
166
+ this.emit("accountChanged", account);
167
+ });
153
168
  }
154
169
  /**
155
170
  * Destroy SDK and cleanup
@@ -202,6 +217,21 @@ var BrowserSDK = class {
202
217
  getThru() {
203
218
  return this.thruClient;
204
219
  }
220
+ refreshCachedAccounts(accounts, selectedAccount) {
221
+ let nextAccounts = accounts;
222
+ if (selectedAccount) {
223
+ const hasAccount = accounts.some((acc) => acc.address === selectedAccount.address);
224
+ if (!hasAccount) {
225
+ nextAccounts = [...accounts, selectedAccount];
226
+ }
227
+ }
228
+ if (this.lastConnectResult) {
229
+ this.lastConnectResult = {
230
+ ...this.lastConnectResult,
231
+ accounts: nextAccounts
232
+ };
233
+ }
234
+ }
205
235
  };
206
236
 
207
237
  export { BrowserSDK };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../chain-interfaces/src/types.ts","../src/BrowserSDK.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export const AddressType = {\n THRU: 'thru',\n} as const;\n\nexport type AddressType = typeof AddressType[keyof typeof AddressType];\n\nexport interface WalletAddress {\n addressType: AddressType;\n address: string;\n}\n\nexport interface AppMetadata {\n appId: string;\n appName: string;\n appUrl: string;\n imageUrl?: string;\n}\n\nexport interface ConnectResult {\n walletId?: string;\n addresses: WalletAddress[];\n status?: 'pending' | 'completed';\n metadata?: AppMetadata;\n}\n\nexport interface ConnectedApp {\n accountId: number;\n appId: string;\n origin: string;\n metadata: AppMetadata;\n connectedAt: number;\n updatedAt: number;\n}\n\nexport interface SignMessageParams {\n message: string | Uint8Array;\n networkId: string;\n}\n\nexport interface SignMessageResult {\n signature: Uint8Array;\n publicKey: string;\n}\n","import type {\n AddressType as AddressTypeValue,\n ConnectResult,\n IThruChain,\n WalletAddress,\n} from '@thru/chain-interfaces';\nimport { AddressType } from '@thru/chain-interfaces';\nimport { EmbeddedProvider } from '@thru/embedded-provider';\nimport { EMBEDDED_PROVIDER_EVENTS, type ConnectMetadataInput } from '@thru/protocol';\nimport { createThruClient, Thru } from '@thru/thru-sdk';\n\nexport interface BrowserSDKConfig {\n iframeUrl?: string;\n addressTypes?: AddressTypeValue[];\n rpcUrl?: string;\n}\n\nexport interface ConnectOptions {\n metadata?: ConnectMetadataInput;\n}\n\nexport type SDKEvent = 'connect' | 'disconnect' | 'lock' | 'error';\n\nexport type EventCallback = (...args: any[]) => void;\n\n/**\n * Browser SDK - Main entry point for dApp developers\n * Wraps EmbeddedProvider with a clean, simple API\n */\nexport class BrowserSDK {\n private provider: EmbeddedProvider;\n private eventListeners = new Map<SDKEvent, Set<EventCallback>>();\n private initialized = false;\n private thruClient: Thru;\n private connectInFlight: Promise<ConnectResult> | null = null;\n private lastConnectResult: ConnectResult | null = null;\n\n constructor(config: BrowserSDKConfig = {}) {\n this.provider = new EmbeddedProvider({\n iframeUrl: config.iframeUrl,\n addressTypes: config.addressTypes || [AddressType.THRU],\n });\n\n this.thruClient = createThruClient({\n baseUrl: config.rpcUrl,\n });\n\n // Forward provider events to SDK events\n this.setupEventForwarding();\n }\n\n /**\n * Initialize the SDK (creates iframe)\n * Must be called before using the SDK\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.provider.initialize();\n this.initialized = true;\n }\n\n /**\n * Connect to wallet\n * Shows wallet modal and requests connection\n */\n async connect(options?: ConnectOptions): Promise<ConnectResult> {\n // Auto-initialize if not done yet\n if (!this.initialized) {\n await this.initialize();\n }\n\n if (this.connectInFlight) {\n return this.connectInFlight;\n }\n\n if (this.lastConnectResult && this.provider.isConnected()) {\n return this.lastConnectResult;\n }\n\n this.emit('connect', { status: 'connecting' });\n\n const inFlight = (async () => {\n try {\n const metadata = this.resolveMetadata(options?.metadata);\n const providerOptions = metadata ? { metadata } : undefined;\n const result = await this.provider.connect(providerOptions);\n this.lastConnectResult = result;\n this.emit('connect', result);\n return result;\n } catch (error) {\n this.emit('error', error);\n throw error;\n } finally {\n this.connectInFlight = null;\n }\n })();\n\n this.connectInFlight = inFlight;\n return inFlight;\n }\n\n /**\n * Disconnect from wallet\n */\n async disconnect(): Promise<void> {\n try {\n await this.provider.disconnect();\n this.emit('disconnect', {});\n this.lastConnectResult = null;\n } catch (error) {\n this.emit('error', error);\n throw error;\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.provider.isConnected();\n }\n\n /**\n * Get all addresses\n */\n getAddresses(): WalletAddress[] {\n return this.provider.getAddresses();\n }\n\n /**\n * Get Thru chain API (iframe-backed signer)\n */\n get thru(): IThruChain {\n return this.provider.thru;\n }\n\n /**\n * Event emitter: on\n */\n on(event: SDKEvent, callback: EventCallback): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(callback);\n }\n\n /**\n * Event emitter: off\n */\n off(event: SDKEvent, callback: EventCallback): void {\n this.eventListeners.get(event)?.delete(callback);\n }\n\n /**\n * Event emitter: once (listen once and auto-remove)\n */\n once(event: SDKEvent, callback: EventCallback): void {\n const wrappedCallback = (...args: any[]) => {\n callback(...args);\n this.off(event, wrappedCallback);\n };\n this.on(event, wrappedCallback);\n }\n\n /**\n * Emit event to all listeners\n */\n private emit(event: SDKEvent, data?: any): void {\n this.eventListeners.get(event)?.forEach(callback => {\n try {\n callback(data);\n } catch (error) {\n console.error(`Error in SDK event listener for ${event}:`, error);\n }\n });\n }\n\n /**\n * Set up event forwarding from provider to SDK\n */\n private setupEventForwarding(): void {\n // Forward all relevant provider events to SDK events\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.CONNECT, (data: any) => {\n // Already handled in connect() method\n });\n\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.DISCONNECT, (data: any) => {\n this.emit('disconnect', data);\n });\n\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.ERROR, (data: any) => {\n this.emit('error', data);\n });\n\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.LOCK, (data: any) => {\n this.emit('lock', data);\n this.emit('disconnect', { reason: 'locked' });\n });\n }\n\n /**\n * Destroy SDK and cleanup\n */\n destroy(): void {\n this.provider.destroy();\n this.eventListeners.clear();\n this.initialized = false;\n this.connectInFlight = null;\n this.lastConnectResult = null;\n }\n\n private resolveMetadata(input?: ConnectMetadataInput): ConnectMetadataInput | undefined {\n const defaultOrigin = typeof window !== 'undefined' ? window.location.origin : undefined;\n if (!defaultOrigin && !input) {\n return undefined;\n }\n\n const appId = input?.appId || defaultOrigin;\n const appUrl = this.resolveAppUrl(defaultOrigin, input?.appUrl);\n const appName = input?.appName || this.deriveAppName(appUrl ?? appId);\n\n const metadata: ConnectMetadataInput = {};\n if (appId) metadata.appId = appId;\n if (appUrl) metadata.appUrl = appUrl;\n if (appName) metadata.appName = appName;\n if (input?.imageUrl) metadata.imageUrl = input.imageUrl;\n\n return metadata;\n }\n\n private resolveAppUrl(defaultOrigin?: string, providedUrl?: string): string | undefined {\n const candidate = providedUrl || defaultOrigin;\n if (!candidate) {\n return undefined;\n }\n\n try {\n const url = new URL(candidate, defaultOrigin);\n return url.toString();\n } catch {\n return defaultOrigin;\n }\n }\n\n private deriveAppName(source?: string): string | undefined {\n if (!source) {\n return undefined;\n }\n\n try {\n const hostname = new URL(source).hostname;\n return hostname || source;\n } catch {\n return source;\n }\n }\n\n public getThru(): Thru {\n return this.thruClient;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../chain-interfaces/src/types.ts","../src/BrowserSDK.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export const AddressType = {\n THRU: 'thru',\n} as const;\n\nexport type AddressType = typeof AddressType[keyof typeof AddressType];\n\nexport interface WalletAccount {\n accountType: AddressType;\n address: string;\n label: string;\n}\n\nexport interface AppMetadata {\n appId: string;\n appName: string;\n appUrl: string;\n imageUrl?: string;\n}\n\nexport interface ConnectResult {\n walletId?: string;\n accounts: WalletAccount[];\n status?: 'pending' | 'completed';\n metadata?: AppMetadata;\n}\n\nexport interface ConnectedApp {\n accountId: number;\n appId: string;\n origin: string;\n metadata: AppMetadata;\n connectedAt: number;\n updatedAt: number;\n}\n\nexport interface SignMessageParams {\n message: string | Uint8Array;\n networkId: string;\n}\n\nexport interface SignMessageResult {\n signature: Uint8Array;\n publicKey: string;\n}\n","import type {\n AddressType as AddressTypeValue,\n ConnectResult,\n IThruChain,\n WalletAccount,\n} from '@thru/chain-interfaces';\nimport { AddressType } from '@thru/chain-interfaces';\nimport { EmbeddedProvider } from '@thru/embedded-provider';\nimport { EMBEDDED_PROVIDER_EVENTS, type ConnectMetadataInput } from '@thru/protocol';\nimport { createThruClient, Thru } from '@thru/thru-sdk/client';\n\nexport interface BrowserSDKConfig {\n iframeUrl?: string;\n addressTypes?: AddressTypeValue[];\n rpcUrl?: string;\n}\n\nexport interface ConnectOptions {\n metadata?: ConnectMetadataInput;\n}\n\nexport type SDKEvent = 'connect' | 'disconnect' | 'lock' | 'error' | 'accountChanged';\n\nexport type EventCallback = (...args: any[]) => void;\n\n/**\n * Browser SDK - Main entry point for dApp developers\n * Wraps EmbeddedProvider with a clean, simple API\n */\nexport class BrowserSDK {\n private provider: EmbeddedProvider;\n private eventListeners = new Map<SDKEvent, Set<EventCallback>>();\n private initialized = false;\n private thruClient: Thru;\n private connectInFlight: Promise<ConnectResult> | null = null;\n private lastConnectResult: ConnectResult | null = null;\n\n constructor(config: BrowserSDKConfig = {}) {\n this.provider = new EmbeddedProvider({\n iframeUrl: config.iframeUrl,\n addressTypes: config.addressTypes || [AddressType.THRU],\n });\n\n this.thruClient = createThruClient({\n baseUrl: config.rpcUrl,\n });\n\n // Forward provider events to SDK events\n this.setupEventForwarding();\n }\n\n /**\n * Initialize the SDK (creates iframe)\n * Must be called before using the SDK\n */\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n\n await this.provider.initialize();\n this.initialized = true;\n }\n\n /**\n * Connect to wallet\n * Shows wallet modal and requests connection\n */\n async connect(options?: ConnectOptions): Promise<ConnectResult> {\n // Auto-initialize if not done yet\n if (!this.initialized) {\n await this.initialize();\n }\n\n if (this.connectInFlight) {\n return this.connectInFlight;\n }\n\n if (this.lastConnectResult && this.provider.isConnected()) {\n return this.lastConnectResult;\n }\n\n this.emit('connect', { status: 'connecting' });\n\n const inFlight = (async () => {\n try {\n const metadata = this.resolveMetadata(options?.metadata);\n const providerOptions = metadata ? { metadata } : undefined;\n const result = await this.provider.connect(providerOptions);\n this.lastConnectResult = result;\n this.emit('connect', result);\n return result;\n } catch (error) {\n this.emit('error', error);\n throw error;\n } finally {\n this.connectInFlight = null;\n }\n })();\n\n this.connectInFlight = inFlight;\n return inFlight;\n }\n\n /**\n * Disconnect from wallet\n */\n async disconnect(): Promise<void> {\n try {\n await this.provider.disconnect();\n this.emit('disconnect', {});\n this.lastConnectResult = null;\n } catch (error) {\n this.emit('error', error);\n throw error;\n }\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.provider.isConnected();\n }\n\n /**\n * Get all accounts\n */\n getAccounts(): WalletAccount[] {\n const accounts = this.provider.getAccounts();\n this.refreshCachedAccounts(accounts);\n return accounts;\n }\n\n getSelectedAccount(): WalletAccount | null {\n return this.provider.getSelectedAccount();\n }\n\n async selectAccount(publicKey: string): Promise<WalletAccount> {\n const account = await this.provider.selectAccount(publicKey);\n this.refreshCachedAccounts(this.provider.getAccounts(), account);\n return account;\n }\n\n /**\n * Get Thru chain API (iframe-backed signer)\n */\n get thru(): IThruChain {\n return this.provider.thru;\n }\n\n /**\n * Event emitter: on\n */\n on(event: SDKEvent, callback: EventCallback): void {\n if (!this.eventListeners.has(event)) {\n this.eventListeners.set(event, new Set());\n }\n this.eventListeners.get(event)!.add(callback);\n }\n\n /**\n * Event emitter: off\n */\n off(event: SDKEvent, callback: EventCallback): void {\n this.eventListeners.get(event)?.delete(callback);\n }\n\n /**\n * Event emitter: once (listen once and auto-remove)\n */\n once(event: SDKEvent, callback: EventCallback): void {\n const wrappedCallback = (...args: any[]) => {\n callback(...args);\n this.off(event, wrappedCallback);\n };\n this.on(event, wrappedCallback);\n }\n\n /**\n * Emit event to all listeners\n */\n private emit(event: SDKEvent, data?: any): void {\n this.eventListeners.get(event)?.forEach(callback => {\n try {\n callback(data);\n } catch (error) {\n console.error(`Error in SDK event listener for ${event}:`, error);\n }\n });\n }\n\n /**\n * Set up event forwarding from provider to SDK\n */\n private setupEventForwarding(): void {\n // Forward all relevant provider events to SDK events\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.CONNECT, (data: any) => {\n // Already handled in connect() method\n });\n\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.DISCONNECT, (data: any) => {\n this.emit('disconnect', data);\n });\n\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.ERROR, (data: any) => {\n this.emit('error', data);\n });\n\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.LOCK, (data: any) => {\n this.emit('lock', data);\n this.emit('disconnect', { reason: 'locked' });\n });\n\n this.provider.on(EMBEDDED_PROVIDER_EVENTS.ACCOUNT_CHANGED, (data: any) => {\n const account = data?.account ?? data;\n this.refreshCachedAccounts(this.provider.getAccounts(), account ?? null);\n this.emit('accountChanged', account);\n });\n }\n\n /**\n * Destroy SDK and cleanup\n */\n destroy(): void {\n this.provider.destroy();\n this.eventListeners.clear();\n this.initialized = false;\n this.connectInFlight = null;\n this.lastConnectResult = null;\n }\n\n private resolveMetadata(input?: ConnectMetadataInput): ConnectMetadataInput | undefined {\n const defaultOrigin = typeof window !== 'undefined' ? window.location.origin : undefined;\n if (!defaultOrigin && !input) {\n return undefined;\n }\n\n const appId = input?.appId || defaultOrigin;\n const appUrl = this.resolveAppUrl(defaultOrigin, input?.appUrl);\n const appName = input?.appName || this.deriveAppName(appUrl ?? appId);\n\n const metadata: ConnectMetadataInput = {};\n if (appId) metadata.appId = appId;\n if (appUrl) metadata.appUrl = appUrl;\n if (appName) metadata.appName = appName;\n if (input?.imageUrl) metadata.imageUrl = input.imageUrl;\n\n return metadata;\n }\n\n private resolveAppUrl(defaultOrigin?: string, providedUrl?: string): string | undefined {\n const candidate = providedUrl || defaultOrigin;\n if (!candidate) {\n return undefined;\n }\n\n try {\n const url = new URL(candidate, defaultOrigin);\n return url.toString();\n } catch {\n return defaultOrigin;\n }\n }\n\n private deriveAppName(source?: string): string | undefined {\n if (!source) {\n return undefined;\n }\n\n try {\n const hostname = new URL(source).hostname;\n return hostname || source;\n } catch {\n return source;\n }\n }\n\n public getThru(): Thru {\n return this.thruClient;\n }\n\n private refreshCachedAccounts(accounts: WalletAccount[], selectedAccount?: WalletAccount | null): void {\n let nextAccounts = accounts;\n\n if (selectedAccount) {\n const hasAccount = accounts.some(acc => acc.address === selectedAccount.address);\n if (!hasAccount) {\n nextAccounts = [...accounts, selectedAccount];\n }\n }\n\n if (this.lastConnectResult) {\n this.lastConnectResult = {\n ...this.lastConnectResult,\n accounts: nextAccounts,\n };\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thru/browser-sdk",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -11,10 +11,10 @@
11
11
  }
12
12
  },
13
13
  "dependencies": {
14
- "@thru/embedded-provider": "0.0.4",
15
- "@thru/chain-interfaces": "0.0.4",
16
- "@thru/protocol": "0.0.4",
17
- "@thru/thru-sdk": "0.0.4"
14
+ "@thru/embedded-provider": "0.0.5",
15
+ "@thru/protocol": "0.0.5",
16
+ "@thru/thru-sdk": "0.0.5",
17
+ "@thru/chain-interfaces": "0.0.5"
18
18
  },
19
19
  "scripts": {
20
20
  "build": "tsup",
package/src/BrowserSDK.ts CHANGED
@@ -2,12 +2,12 @@ import type {
2
2
  AddressType as AddressTypeValue,
3
3
  ConnectResult,
4
4
  IThruChain,
5
- WalletAddress,
5
+ WalletAccount,
6
6
  } from '@thru/chain-interfaces';
7
7
  import { AddressType } from '@thru/chain-interfaces';
8
8
  import { EmbeddedProvider } from '@thru/embedded-provider';
9
9
  import { EMBEDDED_PROVIDER_EVENTS, type ConnectMetadataInput } from '@thru/protocol';
10
- import { createThruClient, Thru } from '@thru/thru-sdk';
10
+ import { createThruClient, Thru } from '@thru/thru-sdk/client';
11
11
 
12
12
  export interface BrowserSDKConfig {
13
13
  iframeUrl?: string;
@@ -19,7 +19,7 @@ export interface ConnectOptions {
19
19
  metadata?: ConnectMetadataInput;
20
20
  }
21
21
 
22
- export type SDKEvent = 'connect' | 'disconnect' | 'lock' | 'error';
22
+ export type SDKEvent = 'connect' | 'disconnect' | 'lock' | 'error' | 'accountChanged';
23
23
 
24
24
  export type EventCallback = (...args: any[]) => void;
25
25
 
@@ -124,10 +124,22 @@ export class BrowserSDK {
124
124
  }
125
125
 
126
126
  /**
127
- * Get all addresses
127
+ * Get all accounts
128
128
  */
129
- getAddresses(): WalletAddress[] {
130
- return this.provider.getAddresses();
129
+ getAccounts(): WalletAccount[] {
130
+ const accounts = this.provider.getAccounts();
131
+ this.refreshCachedAccounts(accounts);
132
+ return accounts;
133
+ }
134
+
135
+ getSelectedAccount(): WalletAccount | null {
136
+ return this.provider.getSelectedAccount();
137
+ }
138
+
139
+ async selectAccount(publicKey: string): Promise<WalletAccount> {
140
+ const account = await this.provider.selectAccount(publicKey);
141
+ this.refreshCachedAccounts(this.provider.getAccounts(), account);
142
+ return account;
131
143
  }
132
144
 
133
145
  /**
@@ -199,6 +211,12 @@ export class BrowserSDK {
199
211
  this.emit('lock', data);
200
212
  this.emit('disconnect', { reason: 'locked' });
201
213
  });
214
+
215
+ this.provider.on(EMBEDDED_PROVIDER_EVENTS.ACCOUNT_CHANGED, (data: any) => {
216
+ const account = data?.account ?? data;
217
+ this.refreshCachedAccounts(this.provider.getAccounts(), account ?? null);
218
+ this.emit('accountChanged', account);
219
+ });
202
220
  }
203
221
 
204
222
  /**
@@ -261,4 +279,22 @@ export class BrowserSDK {
261
279
  public getThru(): Thru {
262
280
  return this.thruClient;
263
281
  }
282
+
283
+ private refreshCachedAccounts(accounts: WalletAccount[], selectedAccount?: WalletAccount | null): void {
284
+ let nextAccounts = accounts;
285
+
286
+ if (selectedAccount) {
287
+ const hasAccount = accounts.some(acc => acc.address === selectedAccount.address);
288
+ if (!hasAccount) {
289
+ nextAccounts = [...accounts, selectedAccount];
290
+ }
291
+ }
292
+
293
+ if (this.lastConnectResult) {
294
+ this.lastConnectResult = {
295
+ ...this.lastConnectResult,
296
+ accounts: nextAccounts,
297
+ };
298
+ }
299
+ }
264
300
  }
package/src/index.ts CHANGED
@@ -1,19 +1,13 @@
1
1
  // Main exports
2
2
  export {
3
3
  BrowserSDK,
4
- type BrowserSDKConfig,
5
- type SDKEvent,
6
- type EventCallback,
7
- type ConnectOptions,
4
+ type BrowserSDKConfig, type ConnectOptions, type EventCallback, type SDKEvent
8
5
  } from './BrowserSDK';
9
6
 
10
7
  // Re-export types from chain-interfaces for convenience
11
8
  export type {
12
- IThruChain,
13
- WalletAddress,
14
- ConnectResult,
15
- SignMessageParams,
16
- SignMessageResult,
9
+ ConnectResult, IThruChain, SignMessageParams,
10
+ SignMessageResult, WalletAccount
17
11
  } from '@thru/chain-interfaces';
18
12
 
19
13
  // Re-export error codes from embedded-provider