@meshconnect/uwc-core 2.7.1 → 2.7.2-snapshot.c393760

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.
Files changed (45) hide show
  1. package/dist/events.d.ts +10 -0
  2. package/dist/events.d.ts.map +1 -1
  3. package/dist/events.js.map +1 -1
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/observability/instrument-handoff.d.ts +3 -0
  9. package/dist/observability/instrument-handoff.d.ts.map +1 -1
  10. package/dist/observability/instrument-handoff.js +6 -0
  11. package/dist/observability/instrument-handoff.js.map +1 -1
  12. package/dist/observability/telemetry.d.ts +2 -0
  13. package/dist/observability/telemetry.d.ts.map +1 -1
  14. package/dist/observability/telemetry.js +6 -1
  15. package/dist/observability/telemetry.js.map +1 -1
  16. package/dist/services/connection-service.d.ts +6 -2
  17. package/dist/services/connection-service.d.ts.map +1 -1
  18. package/dist/services/connection-service.js +19 -9
  19. package/dist/services/connection-service.js.map +1 -1
  20. package/dist/services/index.d.ts +1 -0
  21. package/dist/services/index.d.ts.map +1 -1
  22. package/dist/services/index.js +1 -0
  23. package/dist/services/index.js.map +1 -1
  24. package/dist/services/network-selection.d.ts +34 -0
  25. package/dist/services/network-selection.d.ts.map +1 -0
  26. package/dist/services/network-selection.js +54 -0
  27. package/dist/services/network-selection.js.map +1 -0
  28. package/dist/universal-wallet-connector.d.ts +8 -1
  29. package/dist/universal-wallet-connector.d.ts.map +1 -1
  30. package/dist/universal-wallet-connector.js +2 -1
  31. package/dist/universal-wallet-connector.js.map +1 -1
  32. package/dist/version.d.ts +1 -1
  33. package/dist/version.js +1 -1
  34. package/package.json +5 -5
  35. package/src/events.ts +10 -0
  36. package/src/index.ts +4 -0
  37. package/src/observability/instrument-handoff.ts +9 -0
  38. package/src/observability/telemetry.ts +8 -1
  39. package/src/services/connection-service.test.ts +46 -6
  40. package/src/services/connection-service.ts +28 -11
  41. package/src/services/index.ts +1 -0
  42. package/src/services/network-selection.test.ts +152 -0
  43. package/src/services/network-selection.ts +86 -0
  44. package/src/universal-wallet-connector.ts +10 -1
  45. package/src/version.ts +1 -1
@@ -0,0 +1,152 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import type { Network, SupportedProvider } from '@meshconnect/uwc-types'
3
+ import {
4
+ DEFAULT_NAMESPACE_PRIORITY,
5
+ pickAutoNetwork
6
+ } from './network-selection'
7
+
8
+ const network = (id: string, namespace: Network['namespace']): Network =>
9
+ ({
10
+ id,
11
+ internalId: 0,
12
+ name: id,
13
+ namespace,
14
+ logoUrl: '',
15
+ networkType: 'evm',
16
+ nativeCurrency: { name: '', symbol: '', decimals: 18 }
17
+ }) as Network
18
+
19
+ const NETWORKS = [
20
+ network('eip155:1', 'eip155'),
21
+ network('eip155:81457', 'eip155'),
22
+ network('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', 'solana'),
23
+ network('tron:0x2b6653dc', 'tron'),
24
+ network('tvm:-239', 'tvm')
25
+ ]
26
+
27
+ /** An injected provider whose namespaces carry detection's `installed` flag. */
28
+ const injected = (
29
+ supportedNetworkIds: string[],
30
+ installed: Partial<Record<'eip155' | 'solana' | 'tron' | 'tvm', boolean>>
31
+ ): SupportedProvider =>
32
+ ({
33
+ supportedNetworkIds,
34
+ namespaceMetaData: {
35
+ eip155: { eip155Name: 'W', installed: installed.eip155 },
36
+ solana: { walletStandardName: 'W', installed: installed.solana },
37
+ tron: { injectedId: 'w.tron', installed: installed.tron },
38
+ tvm: { jsBridgeKey: 'w', installed: installed.tvm }
39
+ }
40
+ }) as unknown as SupportedProvider
41
+
42
+ describe('pickAutoNetwork', () => {
43
+ it('skips an undetected first network (Trust mobile: Tron first, not injected)', () => {
44
+ const provider = injected(
45
+ [
46
+ 'tron:0x2b6653dc',
47
+ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
48
+ 'eip155:1'
49
+ ],
50
+ { eip155: true, solana: true, tron: false, tvm: true }
51
+ )
52
+ expect(
53
+ pickAutoNetwork(
54
+ provider,
55
+ NETWORKS,
56
+ 'injected',
57
+ DEFAULT_NAMESPACE_PRIORITY
58
+ )
59
+ ).toEqual({ networkId: 'eip155:1', selection: 'detected' })
60
+ })
61
+
62
+ it('keeps catalog order within a namespace', () => {
63
+ const provider = injected(['eip155:81457', 'eip155:1'], { eip155: true })
64
+ expect(
65
+ pickAutoNetwork(
66
+ provider,
67
+ NETWORKS,
68
+ 'injected',
69
+ DEFAULT_NAMESPACE_PRIORITY
70
+ )?.networkId
71
+ ).toBe('eip155:81457')
72
+ })
73
+
74
+ it('honours a caller-supplied namespace preference', () => {
75
+ const provider = injected(
76
+ ['eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'],
77
+ { eip155: true, solana: true }
78
+ )
79
+ expect(
80
+ pickAutoNetwork(provider, NETWORKS, 'injected', ['solana', 'eip155'])
81
+ ).toEqual({
82
+ networkId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
83
+ selection: 'detected'
84
+ })
85
+ })
86
+
87
+ it('ranks a namespace missing from the preference list last', () => {
88
+ const provider = injected(['tvm:-239', 'tron:0x2b6653dc'], {
89
+ tvm: true,
90
+ tron: true
91
+ })
92
+ expect(
93
+ pickAutoNetwork(provider, NETWORKS, 'injected', ['tron'])?.networkId
94
+ ).toBe('tron:0x2b6653dc')
95
+ })
96
+
97
+ it('falls back to catalog order when nothing was detected (e.g. before detection)', () => {
98
+ const provider = injected(['tron:0x2b6653dc', 'eip155:1'], {})
99
+ expect(
100
+ pickAutoNetwork(
101
+ provider,
102
+ NETWORKS,
103
+ 'injected',
104
+ DEFAULT_NAMESPACE_PRIORITY
105
+ )
106
+ ).toEqual({ networkId: 'tron:0x2b6653dc', selection: 'catalogOrder' })
107
+ })
108
+
109
+ it('leaves non-injected modes on catalog order even with installed flags', () => {
110
+ const provider = injected(['tron:0x2b6653dc', 'eip155:1'], {
111
+ eip155: true
112
+ })
113
+ expect(
114
+ pickAutoNetwork(
115
+ provider,
116
+ NETWORKS,
117
+ 'walletConnect',
118
+ DEFAULT_NAMESPACE_PRIORITY
119
+ )
120
+ ).toEqual({ networkId: 'tron:0x2b6653dc', selection: 'catalogOrder' })
121
+ })
122
+
123
+ it('ignores supported networks that are not configured', () => {
124
+ const provider = injected(
125
+ ['eip155:999', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'],
126
+ {
127
+ eip155: true,
128
+ solana: true
129
+ }
130
+ )
131
+ expect(
132
+ pickAutoNetwork(
133
+ provider,
134
+ NETWORKS,
135
+ 'injected',
136
+ DEFAULT_NAMESPACE_PRIORITY
137
+ )?.networkId
138
+ ).toBe('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')
139
+ })
140
+
141
+ it('returns undefined when no supported network is configured', () => {
142
+ const provider = injected(['eip155:999'], { eip155: true })
143
+ expect(
144
+ pickAutoNetwork(
145
+ provider,
146
+ NETWORKS,
147
+ 'injected',
148
+ DEFAULT_NAMESPACE_PRIORITY
149
+ )
150
+ ).toBeUndefined()
151
+ })
152
+ })
@@ -0,0 +1,86 @@
1
+ import type {
2
+ ConnectionMode,
3
+ Namespace,
4
+ Network,
5
+ NetworkId,
6
+ SupportedProvider
7
+ } from '@meshconnect/uwc-types'
8
+
9
+ /**
10
+ * Default namespace preference for an auto-picked connect network (no
11
+ * `networkId` passed): EVM first, then Solana, Tron, TON, Bitcoin. A caller
12
+ * policy, not a correctness rule — override it with `UWCConfig.preferredNamespaces`.
13
+ * Same order as the namespace unions used across the connectors.
14
+ */
15
+ export const DEFAULT_NAMESPACE_PRIORITY: readonly Namespace[] = [
16
+ 'eip155',
17
+ 'solana',
18
+ 'tron',
19
+ 'tvm',
20
+ 'bip122'
21
+ ]
22
+
23
+ /**
24
+ * How the connect network was chosen, surfaced on the hand-off telemetry:
25
+ * - `explicit` — the caller passed a `networkId`.
26
+ * - `detected` — auto-picked among namespaces whose injected provider was
27
+ * detected, ranked by the namespace preference, catalog order breaking ties.
28
+ * - `catalogOrder` — legacy pick: the first configured network in the wallet's
29
+ * `supportedNetworkIds` (non-injected modes, or nothing detected yet).
30
+ */
31
+ export type NetworkSelection = 'explicit' | 'detected' | 'catalogOrder'
32
+
33
+ function isNamespaceInstalled(
34
+ provider: SupportedProvider,
35
+ namespace: Namespace
36
+ ): boolean {
37
+ if (!('namespaceMetaData' in provider)) return false
38
+ const meta = provider.namespaceMetaData[
39
+ namespace as keyof typeof provider.namespaceMetaData
40
+ ] as { installed?: boolean } | undefined
41
+ return meta?.installed === true
42
+ }
43
+
44
+ /**
45
+ * Picks the network for a connect that named none. Candidates are the wallet's
46
+ * `supportedNetworkIds` that are also configured, in catalog order.
47
+ *
48
+ * For an injected connect where detection marked at least one candidate's
49
+ * namespace installed, only installed namespaces are eligible (connecting on an
50
+ * undetected namespace can only fail — e.g. Trust mobile has no
51
+ * `trustWallet.tronLink`), ranked by `preferredNamespaces`, catalog order
52
+ * breaking ties. Every other case keeps the legacy first-candidate pick, so
53
+ * WalletConnect / TON Connect and pre-detection connects are unchanged.
54
+ * Returns `undefined` when no candidate exists (the caller throws).
55
+ */
56
+ export function pickAutoNetwork(
57
+ provider: SupportedProvider,
58
+ networks: readonly Network[],
59
+ connectionMode: ConnectionMode,
60
+ preferredNamespaces: readonly Namespace[]
61
+ ): { networkId: NetworkId; selection: NetworkSelection } | undefined {
62
+ const candidates = provider.supportedNetworkIds
63
+ .map(id => networks.find(n => n.id === id))
64
+ .filter((n): n is Network => n !== undefined)
65
+ const first = candidates[0]
66
+ if (!first) return undefined
67
+
68
+ if (connectionMode === 'injected') {
69
+ const installed = candidates.filter(n =>
70
+ isNamespaceInstalled(provider, n.namespace)
71
+ )
72
+ if (installed.length > 0) {
73
+ const rank = (namespace: Namespace) => {
74
+ const index = preferredNamespaces.indexOf(namespace)
75
+ return index === -1 ? preferredNamespaces.length : index
76
+ }
77
+ // Array.prototype.sort is stable, so equal ranks keep catalog order.
78
+ const [best] = [...installed].sort(
79
+ (a, b) => rank(a.namespace) - rank(b.namespace)
80
+ )
81
+ if (best) return { networkId: best.id, selection: 'detected' }
82
+ }
83
+ }
84
+
85
+ return { networkId: first.id, selection: 'catalogOrder' }
86
+ }
@@ -30,6 +30,7 @@ import type { TronConnectorConfig } from '@meshconnect/uwc-tron-connector'
30
30
  import { SessionManager } from './managers/session-manager'
31
31
  import { EventManager } from './managers/event-manager'
32
32
  import { ConnectionService } from './services/connection-service'
33
+ import { DEFAULT_NAMESPACE_PRIORITY } from './services/network-selection'
33
34
  import { NetworkSwitchService } from './services/network-switch-service'
34
35
  import { SignatureService } from './services/signature-service'
35
36
  import { TransactionService } from './services/transaction-service'
@@ -109,6 +110,13 @@ export interface UWCConfig {
109
110
  * Default 15_000.
110
111
  */
111
112
  secondaryGatherTimeoutMs?: number
113
+ /**
114
+ * Namespace preference for a connect that names no `networkId`. Injected mode
115
+ * only, and only among namespaces whose provider detection found installed —
116
+ * an undetected namespace is never auto-picked. Catalog order breaks ties.
117
+ * Default `DEFAULT_NAMESPACE_PRIORITY` (eip155, solana, tron, tvm, bip122).
118
+ */
119
+ preferredNamespaces?: readonly Namespace[]
112
120
  }
113
121
 
114
122
  /** Common options for user-initiated async operations. */
@@ -443,7 +451,8 @@ export class UniversalWalletConnector {
443
451
  this.connectors,
444
452
  configuredUsingIntegratedBrowser,
445
453
  this.eventManager,
446
- this.walletResponseTimeoutMs
454
+ this.walletResponseTimeoutMs,
455
+ config.preferredNamespaces ?? DEFAULT_NAMESPACE_PRIORITY
447
456
  )
448
457
  this.networkSwitchService = new NetworkSwitchService(
449
458
  networks,
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated from package.json by scripts/generate-version.mjs — do not edit.
2
- export const UWC_CORE_VERSION = '2.7.1'
2
+ export const UWC_CORE_VERSION = '2.7.2'