walletpair-sdk 1.0.2 → 1.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.
Files changed (74) hide show
  1. package/README.md +13 -0
  2. package/dist/ble/framing.d.ts.map +1 -1
  3. package/dist/ble/framing.js +2 -2
  4. package/dist/ble/framing.js.map +1 -1
  5. package/dist/ble/index.d.ts +2 -2
  6. package/dist/ble/index.d.ts.map +1 -1
  7. package/dist/ble/index.js +2 -2
  8. package/dist/ble/index.js.map +1 -1
  9. package/dist/ble/web-ble-transport.d.ts +1 -1
  10. package/dist/ble/web-ble-transport.d.ts.map +1 -1
  11. package/dist/ble/web-ble-transport.js +23 -12
  12. package/dist/ble/web-ble-transport.js.map +1 -1
  13. package/dist/crypto.d.ts.map +1 -1
  14. package/dist/crypto.js +29 -12
  15. package/dist/crypto.js.map +1 -1
  16. package/dist/dapp-session.d.ts.map +1 -1
  17. package/dist/dapp-session.js +15 -5
  18. package/dist/dapp-session.js.map +1 -1
  19. package/dist/emitter.d.ts +1 -3
  20. package/dist/emitter.d.ts.map +1 -1
  21. package/dist/emitter.js +4 -2
  22. package/dist/emitter.js.map +1 -1
  23. package/dist/evm/eip1193.d.ts +2 -2
  24. package/dist/evm/eip1193.d.ts.map +1 -1
  25. package/dist/evm/eip1193.js +32 -18
  26. package/dist/evm/eip1193.js.map +1 -1
  27. package/dist/evm/index.d.ts +2 -2
  28. package/dist/evm/index.d.ts.map +1 -1
  29. package/dist/evm/index.js.map +1 -1
  30. package/dist/wallet-session.d.ts.map +1 -1
  31. package/dist/wallet-session.js +4 -3
  32. package/dist/wallet-session.js.map +1 -1
  33. package/dist/ws-transport.d.ts +3 -2
  34. package/dist/ws-transport.d.ts.map +1 -1
  35. package/dist/ws-transport.js +13 -4
  36. package/dist/ws-transport.js.map +1 -1
  37. package/package.json +20 -1
  38. package/src/__tests__/adversarial/crypto-attacks.test.ts +240 -233
  39. package/src/__tests__/adversarial/malicious-dapp.test.ts +228 -194
  40. package/src/__tests__/adversarial/malicious-relay.test.ts +292 -220
  41. package/src/__tests__/adversarial/malicious-wallet.test.ts +246 -180
  42. package/src/__tests__/spec-compliance/canonical-json.test.ts +105 -105
  43. package/src/__tests__/spec-compliance/crypto-vectors.test.ts +149 -154
  44. package/src/__tests__/spec-compliance/message-format.test.ts +180 -151
  45. package/src/__tests__/spec-compliance/sequence-numbers.test.ts +142 -149
  46. package/src/__tests__/spec-compliance/state-machine.test.ts +203 -180
  47. package/src/ble/framing.test.ts +122 -114
  48. package/src/ble/framing.ts +48 -51
  49. package/src/ble/index.ts +7 -7
  50. package/src/ble/web-ble-transport.test.ts +93 -84
  51. package/src/ble/web-ble-transport.ts +70 -57
  52. package/src/ble/web-bluetooth.d.ts +19 -19
  53. package/src/canonical-json.test.ts +301 -285
  54. package/src/crypto-directional.test.ts +155 -129
  55. package/src/crypto-hardening.test.ts +292 -283
  56. package/src/crypto.test.ts +364 -346
  57. package/src/crypto.ts +185 -175
  58. package/src/dapp-session.test.ts +522 -385
  59. package/src/dapp-session.ts +17 -11
  60. package/src/emitter.test.ts +122 -122
  61. package/src/emitter.ts +20 -18
  62. package/src/evm/eip1193.test.ts +283 -205
  63. package/src/evm/eip1193.ts +162 -138
  64. package/src/evm/index.ts +5 -5
  65. package/src/evm/wagmi.test.ts +1 -1
  66. package/src/integration.test.ts +329 -201
  67. package/src/security.test.ts +331 -238
  68. package/src/sequence-validation.test.ts +6 -9
  69. package/src/test-helpers.ts +102 -78
  70. package/src/types.test.ts +45 -50
  71. package/src/wallet-session.test.ts +611 -383
  72. package/src/wallet-session.ts +7 -9
  73. package/src/ws-transport.test.ts +141 -139
  74. package/src/ws-transport.ts +52 -41
@@ -1,42 +1,47 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { WebBleCentralTransport, isWebBleSupported } from './web-ble-transport.js';
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import type { ProtocolMessage } from '../types.js'
3
+ import { isWebBleSupported, WebBleCentralTransport } from './web-ble-transport.js'
3
4
 
4
5
  // ── Mock Web Bluetooth API ──────────────────────────────────────────
5
6
 
6
7
  function createMockCharacteristic() {
7
- const listeners = new Map<string, Function>();
8
+ const listeners = new Map<string, (...args: unknown[]) => unknown>()
8
9
  return {
9
10
  writeValueWithoutResponse: vi.fn().mockResolvedValue(undefined),
10
11
  startNotifications: vi.fn().mockResolvedValue(undefined),
11
- addEventListener: vi.fn((evt: string, fn: Function) => { listeners.set(evt, fn); }),
12
- removeEventListener: vi.fn((evt: string) => { listeners.delete(evt); }),
13
- _fire: (evt: string, data: any) => listeners.get(evt)?.(data),
12
+ addEventListener: vi.fn((evt: string, fn: (...args: unknown[]) => unknown) => {
13
+ listeners.set(evt, fn)
14
+ }),
15
+ removeEventListener: vi.fn((evt: string) => {
16
+ listeners.delete(evt)
17
+ }),
18
+ _fire: (evt: string, data: unknown) => listeners.get(evt)?.(data),
14
19
  value: null as DataView | null,
15
- };
20
+ }
16
21
  }
17
22
 
18
23
  function createMockBleDevice() {
19
- const listeners = new Map<string, Function>();
20
- const writeChar = createMockCharacteristic();
21
- const notifyChar = createMockCharacteristic();
24
+ const listeners = new Map<string, (...args: unknown[]) => unknown>()
25
+ const writeChar = createMockCharacteristic()
26
+ const notifyChar = createMockCharacteristic()
22
27
 
23
28
  const service = {
24
29
  getCharacteristic: vi.fn((uuid: string) => {
25
30
  // BLE_WRITE_CHAR_UUID = 'e3a10002-...'
26
- if (uuid.includes('10002')) return Promise.resolve(writeChar);
27
- if (uuid.includes('10003')) return Promise.resolve(notifyChar);
28
- return Promise.reject(new Error('unknown characteristic'));
31
+ if (uuid.includes('10002')) return Promise.resolve(writeChar)
32
+ if (uuid.includes('10003')) return Promise.resolve(notifyChar)
33
+ return Promise.reject(new Error('unknown characteristic'))
29
34
  }),
30
- };
35
+ }
31
36
 
32
37
  const server = {
33
38
  connect: vi.fn().mockResolvedValue(undefined),
34
39
  getPrimaryService: vi.fn().mockResolvedValue(service),
35
40
  connected: true,
36
- };
41
+ }
37
42
 
38
43
  // Make connect() return the server with getPrimaryService
39
- server.connect.mockResolvedValue(server);
44
+ server.connect.mockResolvedValue(server)
40
45
 
41
46
  const device = {
42
47
  gatt: {
@@ -44,15 +49,19 @@ function createMockBleDevice() {
44
49
  connected: true,
45
50
  disconnect: vi.fn(),
46
51
  },
47
- addEventListener: vi.fn((evt: string, fn: Function) => { listeners.set(evt, fn); }),
48
- removeEventListener: vi.fn((evt: string) => { listeners.delete(evt); }),
52
+ addEventListener: vi.fn((evt: string, fn: (...args: unknown[]) => unknown) => {
53
+ listeners.set(evt, fn)
54
+ }),
55
+ removeEventListener: vi.fn((evt: string) => {
56
+ listeners.delete(evt)
57
+ }),
49
58
  _fireDisconnect: () => listeners.get('gattserverdisconnected')?.({} as Event),
50
- };
59
+ }
51
60
 
52
- return { device, writeChar, notifyChar, server };
61
+ return { device, writeChar, notifyChar, server }
53
62
  }
54
63
 
55
- function mockNavigatorBluetooth(device: any) {
64
+ function mockNavigatorBluetooth(device: unknown) {
56
65
  Object.defineProperty(globalThis, 'navigator', {
57
66
  value: {
58
67
  bluetooth: {
@@ -61,7 +70,7 @@ function mockNavigatorBluetooth(device: any) {
61
70
  },
62
71
  writable: true,
63
72
  configurable: true,
64
- });
73
+ })
65
74
  }
66
75
 
67
76
  function clearNavigatorBluetooth() {
@@ -69,124 +78,124 @@ function clearNavigatorBluetooth() {
69
78
  value: undefined,
70
79
  writable: true,
71
80
  configurable: true,
72
- });
81
+ })
73
82
  }
74
83
 
75
84
  // ── isWebBleSupported ───────────────────────────────────────────────
76
85
 
77
86
  describe('isWebBleSupported', () => {
78
87
  it('returns false when navigator is undefined', () => {
79
- clearNavigatorBluetooth();
80
- expect(isWebBleSupported()).toBe(false);
81
- });
88
+ clearNavigatorBluetooth()
89
+ expect(isWebBleSupported()).toBe(false)
90
+ })
82
91
 
83
92
  it('returns false when navigator.bluetooth is missing', () => {
84
93
  Object.defineProperty(globalThis, 'navigator', {
85
94
  value: {},
86
95
  writable: true,
87
96
  configurable: true,
88
- });
89
- expect(isWebBleSupported()).toBe(false);
90
- });
97
+ })
98
+ expect(isWebBleSupported()).toBe(false)
99
+ })
91
100
 
92
101
  it('returns true when navigator.bluetooth exists', () => {
93
102
  Object.defineProperty(globalThis, 'navigator', {
94
103
  value: { bluetooth: {} },
95
104
  writable: true,
96
105
  configurable: true,
97
- });
98
- expect(isWebBleSupported()).toBe(true);
99
- });
100
- });
106
+ })
107
+ expect(isWebBleSupported()).toBe(true)
108
+ })
109
+ })
101
110
 
102
111
  // ── WebBleCentralTransport ──────────────────────────────────────────
103
112
 
104
113
  describe('WebBleCentralTransport', () => {
105
- let transport: WebBleCentralTransport;
114
+ let transport: WebBleCentralTransport
106
115
 
107
116
  beforeEach(() => {
108
- transport = new WebBleCentralTransport();
109
- clearNavigatorBluetooth();
110
- });
117
+ transport = new WebBleCentralTransport()
118
+ clearNavigatorBluetooth()
119
+ })
111
120
 
112
121
  it('starts in disconnected state', () => {
113
- expect(transport.state).toBe('disconnected');
114
- });
122
+ expect(transport.state).toBe('disconnected')
123
+ })
115
124
 
116
125
  it('connect() throws when Web Bluetooth is not supported', async () => {
117
- await expect(transport.connect()).rejects.toThrow('Web Bluetooth is not supported');
118
- });
126
+ await expect(transport.connect()).rejects.toThrow('Web Bluetooth is not supported')
127
+ })
119
128
 
120
129
  it('connect() transitions through connecting to connected', async () => {
121
- const { device } = createMockBleDevice();
122
- mockNavigatorBluetooth(device);
130
+ const { device } = createMockBleDevice()
131
+ mockNavigatorBluetooth(device)
123
132
 
124
- const openHandler = vi.fn();
125
- transport.onOpen(openHandler);
133
+ const openHandler = vi.fn()
134
+ transport.onOpen(openHandler)
126
135
 
127
- await transport.connect();
136
+ await transport.connect()
128
137
 
129
- expect(transport.state).toBe('connected');
130
- expect(openHandler).toHaveBeenCalledTimes(1);
131
- });
138
+ expect(transport.state).toBe('connected')
139
+ expect(openHandler).toHaveBeenCalledTimes(1)
140
+ })
132
141
 
133
142
  it('connect() sets up GATT characteristics', async () => {
134
- const { device, notifyChar } = createMockBleDevice();
135
- mockNavigatorBluetooth(device);
143
+ const { device, notifyChar } = createMockBleDevice()
144
+ mockNavigatorBluetooth(device)
136
145
 
137
- await transport.connect();
146
+ await transport.connect()
138
147
 
139
- expect(notifyChar.startNotifications).toHaveBeenCalled();
148
+ expect(notifyChar.startNotifications).toHaveBeenCalled()
140
149
  expect(notifyChar.addEventListener).toHaveBeenCalledWith(
141
150
  'characteristicvaluechanged',
142
151
  expect.any(Function),
143
- );
144
- });
152
+ )
153
+ })
145
154
 
146
155
  it('disconnect() calls gatt.disconnect and cleans up', async () => {
147
- const { device } = createMockBleDevice();
148
- mockNavigatorBluetooth(device);
156
+ const { device } = createMockBleDevice()
157
+ mockNavigatorBluetooth(device)
149
158
 
150
- await transport.connect();
151
- transport.disconnect();
159
+ await transport.connect()
160
+ transport.disconnect()
152
161
 
153
- expect(device.gatt.disconnect).toHaveBeenCalled();
154
- expect(transport.state).toBe('disconnected');
155
- });
162
+ expect(device.gatt.disconnect).toHaveBeenCalled()
163
+ expect(transport.state).toBe('disconnected')
164
+ })
156
165
 
157
166
  it('disconnect() is safe to call when not connected', () => {
158
- expect(() => transport.disconnect()).not.toThrow();
159
- expect(transport.state).toBe('disconnected');
160
- });
167
+ expect(() => transport.disconnect()).not.toThrow()
168
+ expect(transport.state).toBe('disconnected')
169
+ })
161
170
 
162
171
  it('send() does nothing when not connected', () => {
163
- transport.send({ v: 1, t: 'ping', ch: 'abc' } as any);
172
+ transport.send({ v: 1, t: 'ping', ch: 'abc' } as unknown as ProtocolMessage)
164
173
  // Should not throw
165
- });
174
+ })
166
175
 
167
176
  it('onClose handler fires on GATT disconnect', async () => {
168
- const { device } = createMockBleDevice();
169
- mockNavigatorBluetooth(device);
177
+ const { device } = createMockBleDevice()
178
+ mockNavigatorBluetooth(device)
170
179
 
171
- const closeHandler = vi.fn();
172
- transport.onClose(closeHandler);
180
+ const closeHandler = vi.fn()
181
+ transport.onClose(closeHandler)
173
182
 
174
- await transport.connect();
175
- device._fireDisconnect();
183
+ await transport.connect()
184
+ device._fireDisconnect()
176
185
 
177
- expect(closeHandler).toHaveBeenCalledTimes(1);
178
- expect(transport.state).toBe('disconnected');
179
- });
186
+ expect(closeHandler).toHaveBeenCalledTimes(1)
187
+ expect(transport.state).toBe('disconnected')
188
+ })
180
189
 
181
190
  it('handler registration methods work', () => {
182
- const msgHandler = vi.fn();
183
- const closeHandler = vi.fn();
184
- const openHandler = vi.fn();
191
+ const msgHandler = vi.fn()
192
+ const closeHandler = vi.fn()
193
+ const openHandler = vi.fn()
185
194
 
186
- transport.onMessage(msgHandler);
187
- transport.onClose(closeHandler);
188
- transport.onOpen(openHandler);
195
+ transport.onMessage(msgHandler)
196
+ transport.onClose(closeHandler)
197
+ transport.onOpen(openHandler)
189
198
 
190
199
  // No throws — handlers registered
191
- });
192
- });
200
+ })
201
+ })
@@ -7,110 +7,123 @@
7
7
 
8
8
  /// <reference path="./web-bluetooth.d.ts" />
9
9
 
10
- import type { Transport, TransportState, ProtocolMessage } from '../types.js';
10
+ import type { ProtocolMessage, Transport, TransportState } from '../types.js'
11
11
  import {
12
+ BLE_NOTIFY_CHAR_UUID,
12
13
  BLE_SERVICE_UUID,
13
14
  BLE_WRITE_CHAR_UUID,
14
- BLE_NOTIFY_CHAR_UUID,
15
- frameMessage,
16
15
  Defragmenter,
17
- } from './framing.js';
16
+ frameMessage,
17
+ } from './framing.js'
18
18
 
19
19
  export function isWebBleSupported(): boolean {
20
- return typeof navigator !== 'undefined' && !!navigator.bluetooth;
20
+ return typeof navigator !== 'undefined' && !!navigator.bluetooth
21
21
  }
22
22
 
23
23
  export class WebBleCentralTransport implements Transport {
24
- state: TransportState = 'disconnected';
24
+ state: TransportState = 'disconnected'
25
25
 
26
- private device: BluetoothDevice | null = null;
27
- private writeChar: BluetoothRemoteGATTCharacteristic | null = null;
28
- private notifyChar: BluetoothRemoteGATTCharacteristic | null = null;
29
- private defrag = new Defragmenter();
30
- private mtuPayload = 509;
26
+ private device: BluetoothDevice | null = null
27
+ private writeChar: BluetoothRemoteGATTCharacteristic | null = null
28
+ private notifyChar: BluetoothRemoteGATTCharacteristic | null = null
29
+ private defrag = new Defragmenter()
30
+ private mtuPayload = 509
31
31
 
32
- private messageHandler: ((msg: ProtocolMessage) => void) | null = null;
33
- private closeHandler: (() => void) | null = null;
34
- private openHandler: (() => void) | null = null;
32
+ private messageHandler: ((msg: ProtocolMessage) => void) | null = null
33
+ private closeHandler: (() => void) | null = null
34
+ private openHandler: (() => void) | null = null
35
35
 
36
- onMessage(handler: (msg: ProtocolMessage) => void): void { this.messageHandler = handler; }
37
- onClose(handler: () => void): void { this.closeHandler = handler; }
38
- onOpen(handler: () => void): void { this.openHandler = handler; }
36
+ onMessage(handler: (msg: ProtocolMessage) => void): void {
37
+ this.messageHandler = handler
38
+ }
39
+ onClose(handler: () => void): void {
40
+ this.closeHandler = handler
41
+ }
42
+ onOpen(handler: () => void): void {
43
+ this.openHandler = handler
44
+ }
39
45
 
40
46
  async connect(): Promise<void> {
41
47
  if (!isWebBleSupported()) {
42
- throw new Error('Web Bluetooth is not supported in this environment');
48
+ throw new Error('Web Bluetooth is not supported in this environment')
43
49
  }
44
50
 
45
- this.state = 'connecting';
51
+ this.state = 'connecting'
46
52
 
47
- const device = await navigator.bluetooth!.requestDevice({
48
- filters: [
49
- { namePrefix: 'WalletPair' },
50
- { services: [BLE_SERVICE_UUID] },
51
- ],
53
+ const device = await navigator.bluetooth?.requestDevice({
54
+ filters: [{ namePrefix: 'WalletPair' }, { services: [BLE_SERVICE_UUID] }],
52
55
  optionalServices: [BLE_SERVICE_UUID],
53
- });
56
+ })
57
+
58
+ if (!device) throw new Error('No BLE device selected')
54
59
 
55
- this.device = device;
56
- device.addEventListener('gattserverdisconnected', this.onDisconnect);
60
+ this.device = device
61
+ device.addEventListener('gattserverdisconnected', this.onDisconnect)
57
62
 
58
- const server = await device.gatt!.connect();
59
- const service = await server.getPrimaryService(BLE_SERVICE_UUID);
63
+ const server = await device.gatt?.connect()
64
+ if (!server) throw new Error('Failed to connect to GATT server')
65
+ const service = await server.getPrimaryService(BLE_SERVICE_UUID)
60
66
 
61
- this.writeChar = await service.getCharacteristic(BLE_WRITE_CHAR_UUID);
62
- this.notifyChar = await service.getCharacteristic(BLE_NOTIFY_CHAR_UUID);
67
+ this.writeChar = await service.getCharacteristic(BLE_WRITE_CHAR_UUID)
68
+ this.notifyChar = await service.getCharacteristic(BLE_NOTIFY_CHAR_UUID)
63
69
 
64
- await this.notifyChar.startNotifications();
65
- this.notifyChar.addEventListener('characteristicvaluechanged', this.onNotification);
70
+ await this.notifyChar.startNotifications()
71
+ this.notifyChar.addEventListener('characteristicvaluechanged', this.onNotification)
66
72
 
67
- this.state = 'connected';
68
- this.openHandler?.();
73
+ this.state = 'connected'
74
+ this.openHandler?.()
69
75
  }
70
76
 
71
77
  send(msg: ProtocolMessage): void {
72
- if (!this.writeChar || this.state !== 'connected') return;
73
- const frames = frameMessage(JSON.stringify(msg), this.mtuPayload);
78
+ if (!this.writeChar || this.state !== 'connected') return
79
+ const frames = frameMessage(JSON.stringify(msg), this.mtuPayload)
74
80
  // Send frames sequentially
75
- let chain = Promise.resolve();
81
+ let chain = Promise.resolve()
76
82
  for (const frame of frames) {
77
- chain = chain.then(() => this.writeChar!.writeValueWithoutResponse(frame as unknown as ArrayBuffer));
83
+ chain = chain.then(() =>
84
+ this.writeChar?.writeValueWithoutResponse(frame as unknown as ArrayBuffer),
85
+ )
78
86
  }
79
87
  }
80
88
 
81
89
  disconnect(): void {
82
90
  if (this.device?.gatt?.connected) {
83
- this.device.gatt.disconnect();
91
+ this.device.gatt.disconnect()
84
92
  }
85
- this.cleanup();
93
+ this.cleanup()
86
94
  }
87
95
 
88
96
  private onNotification = (event: Event): void => {
89
- const target = event.target as BluetoothRemoteGATTCharacteristic;
90
- const dv = target.value!;
91
- const data = new Uint8Array(dv.buffer, dv.byteOffset, dv.byteLength);
92
- const json = this.defrag.push(data);
97
+ const target = event.target as BluetoothRemoteGATTCharacteristic
98
+ const dv = target.value
99
+ if (!dv) return
100
+ const data = new Uint8Array(dv.buffer, dv.byteOffset, dv.byteLength)
101
+ const json = this.defrag.push(data)
93
102
  if (json && this.messageHandler) {
94
- try { this.messageHandler(JSON.parse(json)); } catch { /* bad json */ }
103
+ try {
104
+ this.messageHandler(JSON.parse(json))
105
+ } catch {
106
+ /* bad json */
107
+ }
95
108
  }
96
- };
109
+ }
97
110
 
98
111
  private onDisconnect = (): void => {
99
- this.cleanup();
100
- this.closeHandler?.();
101
- };
112
+ this.cleanup()
113
+ this.closeHandler?.()
114
+ }
102
115
 
103
116
  private cleanup(): void {
104
117
  if (this.notifyChar) {
105
- this.notifyChar.removeEventListener('characteristicvaluechanged', this.onNotification);
118
+ this.notifyChar.removeEventListener('characteristicvaluechanged', this.onNotification)
106
119
  }
107
120
  if (this.device) {
108
- this.device.removeEventListener('gattserverdisconnected', this.onDisconnect);
121
+ this.device.removeEventListener('gattserverdisconnected', this.onDisconnect)
109
122
  }
110
- this.device = null;
111
- this.writeChar = null;
112
- this.notifyChar = null;
113
- this.defrag.reset();
114
- this.state = 'disconnected';
123
+ this.device = null
124
+ this.writeChar = null
125
+ this.notifyChar = null
126
+ this.defrag.reset()
127
+ this.state = 'disconnected'
115
128
  }
116
129
  }
@@ -4,44 +4,44 @@
4
4
  */
5
5
 
6
6
  interface BluetoothDevice extends EventTarget {
7
- readonly id: string;
8
- readonly name?: string | undefined;
9
- readonly gatt?: BluetoothRemoteGATTServer | undefined;
7
+ readonly id: string
8
+ readonly name?: string | undefined
9
+ readonly gatt?: BluetoothRemoteGATTServer | undefined
10
10
  }
11
11
 
12
12
  interface BluetoothRemoteGATTServer {
13
- readonly device: BluetoothDevice;
14
- readonly connected: boolean;
15
- connect(): Promise<BluetoothRemoteGATTServer>;
16
- disconnect(): void;
17
- getPrimaryService(service: string): Promise<BluetoothRemoteGATTService>;
13
+ readonly device: BluetoothDevice
14
+ readonly connected: boolean
15
+ connect(): Promise<BluetoothRemoteGATTServer>
16
+ disconnect(): void
17
+ getPrimaryService(service: string): Promise<BluetoothRemoteGATTService>
18
18
  }
19
19
 
20
20
  interface BluetoothRemoteGATTService {
21
- getCharacteristic(characteristic: string): Promise<BluetoothRemoteGATTCharacteristic>;
21
+ getCharacteristic(characteristic: string): Promise<BluetoothRemoteGATTCharacteristic>
22
22
  }
23
23
 
24
24
  interface BluetoothRemoteGATTCharacteristic extends EventTarget {
25
- readonly value: DataView | null;
26
- startNotifications(): Promise<BluetoothRemoteGATTCharacteristic>;
27
- stopNotifications(): Promise<BluetoothRemoteGATTCharacteristic>;
28
- writeValueWithoutResponse(value: BufferSource): Promise<void>;
25
+ readonly value: DataView | null
26
+ startNotifications(): Promise<BluetoothRemoteGATTCharacteristic>
27
+ stopNotifications(): Promise<BluetoothRemoteGATTCharacteristic>
28
+ writeValueWithoutResponse(value: BufferSource): Promise<void>
29
29
  }
30
30
 
31
31
  interface BluetoothRequestDeviceFilter {
32
- namePrefix?: string;
33
- services?: string[];
32
+ namePrefix?: string
33
+ services?: string[]
34
34
  }
35
35
 
36
36
  interface RequestDeviceOptions {
37
- filters?: BluetoothRequestDeviceFilter[];
38
- optionalServices?: string[];
37
+ filters?: BluetoothRequestDeviceFilter[]
38
+ optionalServices?: string[]
39
39
  }
40
40
 
41
41
  interface Bluetooth {
42
- requestDevice(options: RequestDeviceOptions): Promise<BluetoothDevice>;
42
+ requestDevice(options: RequestDeviceOptions): Promise<BluetoothDevice>
43
43
  }
44
44
 
45
45
  interface Navigator {
46
- bluetooth?: Bluetooth | undefined;
46
+ bluetooth?: Bluetooth | undefined
47
47
  }