walletpair-sdk 1.0.3 → 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 +1 -1
  34. package/dist/ws-transport.d.ts.map +1 -1
  35. package/dist/ws-transport.js +12 -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 +51 -41
@@ -6,11 +6,11 @@
6
6
  * handles all documented edge cases.
7
7
  */
8
8
 
9
- import { describe, expect, it } from 'vitest';
10
- import { canonicalJson, sha256Hex } from '../../crypto.js';
9
+ import { describe, expect, it } from 'vitest'
10
+ import { canonicalJson, sha256Hex } from '../../crypto.js'
11
11
 
12
12
  function hash(s: string): string {
13
- return sha256Hex(new TextEncoder().encode(s));
13
+ return sha256Hex(new TextEncoder().encode(s))
14
14
  }
15
15
 
16
16
  // ---------------------------------------------------------------------------
@@ -22,19 +22,19 @@ describe('Section 6.3 — Vector 1: capabilities (key sorting, nested objects)',
22
22
  methods: ['wallet_signTransaction', 'wallet_signMessage'],
23
23
  events: ['accountsChanged', 'chainChanged'],
24
24
  chains: ['eip155:1', 'eip155:137'],
25
- };
25
+ }
26
26
  const expected =
27
- '{"chains":["eip155:1","eip155:137"],"events":["accountsChanged","chainChanged"],"methods":["wallet_signTransaction","wallet_signMessage"]}';
28
- const expectedHash = '4da366e2aae26b47b3d90fff52410752348733350ce2525dce7d64510f571333';
27
+ '{"chains":["eip155:1","eip155:137"],"events":["accountsChanged","chainChanged"],"methods":["wallet_signTransaction","wallet_signMessage"]}'
28
+ const expectedHash = '4da366e2aae26b47b3d90fff52410752348733350ce2525dce7d64510f571333'
29
29
 
30
30
  it('produces the correct canonical output', () => {
31
- expect(canonicalJson(input)).toBe(expected);
32
- });
31
+ expect(canonicalJson(input)).toBe(expected)
32
+ })
33
33
 
34
34
  it('SHA-256 of output matches the spec', () => {
35
- expect(hash(canonicalJson(input))).toBe(expectedHash);
36
- });
37
- });
35
+ expect(hash(canonicalJson(input))).toBe(expectedHash)
36
+ })
37
+ })
38
38
 
39
39
  describe('Section 6.3 — Vector 2: join plaintext (nested + meta)', () => {
40
40
  const input = {
@@ -49,75 +49,75 @@ describe('Section 6.3 — Vector 2: join plaintext (nested + meta)', () => {
49
49
  url: 'https://mywallet.app',
50
50
  icon: 'https://mywallet.app/icon.png',
51
51
  },
52
- };
52
+ }
53
53
  const expected =
54
- '{"capabilities":{"chains":["eip155:1","eip155:137"],"events":["accountsChanged","chainChanged"],"methods":["wallet_signTransaction","wallet_signMessage"]},"meta":{"description":"A multi-chain wallet","icon":"https://mywallet.app/icon.png","name":"MyWallet","url":"https://mywallet.app"}}';
55
- const expectedHash = '9f4f3b71b0db39ba8b86173b8c78182799d0a745c68b6e89e5d8f0d3def52594';
54
+ '{"capabilities":{"chains":["eip155:1","eip155:137"],"events":["accountsChanged","chainChanged"],"methods":["wallet_signTransaction","wallet_signMessage"]},"meta":{"description":"A multi-chain wallet","icon":"https://mywallet.app/icon.png","name":"MyWallet","url":"https://mywallet.app"}}'
55
+ const expectedHash = '9f4f3b71b0db39ba8b86173b8c78182799d0a745c68b6e89e5d8f0d3def52594'
56
56
 
57
57
  it('produces the correct canonical output', () => {
58
- expect(canonicalJson(input)).toBe(expected);
59
- });
58
+ expect(canonicalJson(input)).toBe(expected)
59
+ })
60
60
 
61
61
  it('SHA-256 of output matches the spec', () => {
62
- expect(hash(canonicalJson(input))).toBe(expectedHash);
63
- });
64
- });
62
+ expect(hash(canonicalJson(input))).toBe(expectedHash)
63
+ })
64
+ })
65
65
 
66
66
  describe('Section 6.3 — Vector 3: primitives', () => {
67
67
  it('null -> "null"', () => {
68
- const output = canonicalJson(null);
69
- expect(output).toBe('null');
70
- expect(hash(output)).toBe('74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b');
71
- });
68
+ const output = canonicalJson(null)
69
+ expect(output).toBe('null')
70
+ expect(hash(output)).toBe('74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b')
71
+ })
72
72
 
73
73
  it('true -> "true"', () => {
74
- const output = canonicalJson(true);
75
- expect(output).toBe('true');
76
- expect(hash(output)).toBe('b5bea41b6c623f7c09f1bf24dcae58ebab3c0cdd90ad966bc43a45b44867e12b');
77
- });
74
+ const output = canonicalJson(true)
75
+ expect(output).toBe('true')
76
+ expect(hash(output)).toBe('b5bea41b6c623f7c09f1bf24dcae58ebab3c0cdd90ad966bc43a45b44867e12b')
77
+ })
78
78
 
79
79
  it('42 -> "42"', () => {
80
- const output = canonicalJson(42);
81
- expect(output).toBe('42');
82
- expect(hash(output)).toBe('73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049');
83
- });
80
+ const output = canonicalJson(42)
81
+ expect(output).toBe('42')
82
+ expect(hash(output)).toBe('73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049')
83
+ })
84
84
 
85
85
  it('"hello" -> \'"hello"\'', () => {
86
- const output = canonicalJson('hello');
87
- expect(output).toBe('"hello"');
88
- expect(hash(output)).toBe('5aa762ae383fbb727af3c7a36d4940a5b8c40a989452d2304fc958ff3f354e7a');
89
- });
90
- });
86
+ const output = canonicalJson('hello')
87
+ expect(output).toBe('"hello"')
88
+ expect(hash(output)).toBe('5aa762ae383fbb727af3c7a36d4940a5b8c40a989452d2304fc958ff3f354e7a')
89
+ })
90
+ })
91
91
 
92
92
  describe('Section 6.3 — Vector 4: empty containers', () => {
93
93
  it('{} -> "{}"', () => {
94
- const output = canonicalJson({});
95
- expect(output).toBe('{}');
96
- expect(hash(output)).toBe('44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a');
97
- });
94
+ const output = canonicalJson({})
95
+ expect(output).toBe('{}')
96
+ expect(hash(output)).toBe('44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a')
97
+ })
98
98
 
99
99
  it('[] -> "[]"', () => {
100
- const output = canonicalJson([]);
101
- expect(output).toBe('[]');
102
- expect(hash(output)).toBe('4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945');
103
- });
104
- });
100
+ const output = canonicalJson([])
101
+ expect(output).toBe('[]')
102
+ expect(hash(output)).toBe('4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945')
103
+ })
104
+ })
105
105
 
106
106
  describe('Section 6.3 — Vector 5: negative zero', () => {
107
107
  it('-0 -> "0"', () => {
108
- const output = canonicalJson(-0);
109
- expect(output).toBe('0');
110
- expect(hash(output)).toBe('5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9');
111
- });
112
- });
108
+ const output = canonicalJson(-0)
109
+ expect(output).toBe('0')
110
+ expect(hash(output)).toBe('5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9')
111
+ })
112
+ })
113
113
 
114
114
  describe('Section 6.3 — Vector 6: escaped control character', () => {
115
115
  it('U+0001 -> "\\u0001" (lowercase hex)', () => {
116
- const output = canonicalJson('\u0001');
117
- expect(output).toBe('"\\u0001"');
118
- expect(hash(output)).toBe('b81cfb0a6715e53b373345b49e8ad94eb55fd777519dc539373d0634973c186e');
119
- });
120
- });
116
+ const output = canonicalJson('\u0001')
117
+ expect(output).toBe('"\\u0001"')
118
+ expect(hash(output)).toBe('b81cfb0a6715e53b373345b49e8ad94eb55fd777519dc539373d0634973c186e')
119
+ })
120
+ })
121
121
 
122
122
  // ---------------------------------------------------------------------------
123
123
  // Edge cases from Section 6.3 rules
@@ -125,89 +125,89 @@ describe('Section 6.3 — Vector 6: escaped control character', () => {
125
125
 
126
126
  describe('Section 6.3 — Edge cases', () => {
127
127
  it('negative zero inside an object serializes as 0', () => {
128
- expect(canonicalJson({ value: -0 })).toBe('{"value":0}');
129
- });
128
+ expect(canonicalJson({ value: -0 })).toBe('{"value":0}')
129
+ })
130
130
 
131
131
  it('negative zero inside an array serializes as 0', () => {
132
- expect(canonicalJson([-0])).toBe('[0]');
133
- });
132
+ expect(canonicalJson([-0])).toBe('[0]')
133
+ })
134
134
 
135
135
  it('NaN is rejected', () => {
136
- expect(() => canonicalJson(NaN)).toThrow();
137
- });
136
+ expect(() => canonicalJson(NaN)).toThrow()
137
+ })
138
138
 
139
139
  it('Infinity is rejected', () => {
140
- expect(() => canonicalJson(Infinity)).toThrow();
141
- expect(() => canonicalJson(-Infinity)).toThrow();
142
- });
140
+ expect(() => canonicalJson(Infinity)).toThrow()
141
+ expect(() => canonicalJson(-Infinity)).toThrow()
142
+ })
143
143
 
144
144
  it('forward slash is NOT escaped', () => {
145
- const output = canonicalJson('/');
146
- expect(output).toBe('"/"');
147
- });
145
+ const output = canonicalJson('/')
146
+ expect(output).toBe('"/"')
147
+ })
148
148
 
149
149
  it('non-ASCII Unicode is output as literal UTF-8', () => {
150
- expect(canonicalJson('中文')).toBe('"中文"');
151
- });
150
+ expect(canonicalJson('中文')).toBe('"中文"')
151
+ })
152
152
 
153
153
  it('control characters U+0000-U+001F use correct escape forms', () => {
154
154
  // Short forms
155
- expect(canonicalJson('\b')).toBe('"\\b"');
156
- expect(canonicalJson('\t')).toBe('"\\t"');
157
- expect(canonicalJson('\n')).toBe('"\\n"');
158
- expect(canonicalJson('\f')).toBe('"\\f"');
159
- expect(canonicalJson('\r')).toBe('"\\r"');
155
+ expect(canonicalJson('\b')).toBe('"\\b"')
156
+ expect(canonicalJson('\t')).toBe('"\\t"')
157
+ expect(canonicalJson('\n')).toBe('"\\n"')
158
+ expect(canonicalJson('\f')).toBe('"\\f"')
159
+ expect(canonicalJson('\r')).toBe('"\\r"')
160
160
 
161
161
  // All other C0 controls use lowercase \\uXXXX
162
- expect(canonicalJson('\x00')).toBe('"\\u0000"');
163
- expect(canonicalJson('\x01')).toBe('"\\u0001"');
164
- expect(canonicalJson('\x1f')).toBe('"\\u001f"');
165
- });
162
+ expect(canonicalJson('\x00')).toBe('"\\u0000"')
163
+ expect(canonicalJson('\x01')).toBe('"\\u0001"')
164
+ expect(canonicalJson('\x1f')).toBe('"\\u001f"')
165
+ })
166
166
 
167
167
  it('\\uXXXX escapes use lowercase hex digits only', () => {
168
168
  for (let cp = 0; cp <= 0x1f; cp++) {
169
- const result = canonicalJson(String.fromCharCode(cp));
169
+ const result = canonicalJson(String.fromCharCode(cp))
170
170
  // Verify no uppercase hex digits in any \u escape
171
- const matches = result.match(/\\u[0-9a-fA-F]{4}/g);
171
+ const matches = result.match(/\\u[0-9a-fA-F]{4}/g)
172
172
  if (matches) {
173
173
  for (const m of matches) {
174
- expect(m).toBe(m.toLowerCase());
174
+ expect(m).toBe(m.toLowerCase())
175
175
  }
176
176
  }
177
177
  }
178
- });
178
+ })
179
179
 
180
180
  it('no whitespace in structural output', () => {
181
181
  const complex = {
182
182
  z: [3, 1, 2],
183
183
  a: { y: 'value', x: true },
184
184
  m: null,
185
- };
186
- const output = canonicalJson(complex);
185
+ }
186
+ const output = canonicalJson(complex)
187
187
  // Remove string content, then check structural chars only
188
- const structural = output.replace(/"[^"]*"/g, '""');
189
- expect(structural).not.toMatch(/\s/);
190
- });
188
+ const structural = output.replace(/"[^"]*"/g, '""')
189
+ expect(structural).not.toMatch(/\s/)
190
+ })
191
191
 
192
192
  it('array order is preserved (NOT sorted)', () => {
193
- expect(canonicalJson([3, 1, 2])).toBe('[3,1,2]');
194
- });
193
+ expect(canonicalJson([3, 1, 2])).toBe('[3,1,2]')
194
+ })
195
195
 
196
196
  it('object keys are sorted alphabetically at every nesting level', () => {
197
- const input = { z: { b: 2, a: 1 }, a: 0 };
198
- expect(canonicalJson(input)).toBe('{"a":0,"z":{"a":1,"b":2}}');
199
- });
197
+ const input = { z: { b: 2, a: 1 }, a: 0 }
198
+ expect(canonicalJson(input)).toBe('{"a":0,"z":{"a":1,"b":2}}')
199
+ })
200
200
 
201
201
  it('no trailing .0 on whole-number floats', () => {
202
- expect(canonicalJson(100.0)).toBe('100');
203
- });
202
+ expect(canonicalJson(100.0)).toBe('100')
203
+ })
204
204
 
205
205
  it('numbers have no leading zeroes or + prefix', () => {
206
- expect(canonicalJson(42)).toBe('42');
207
- expect(canonicalJson(0)).toBe('0');
208
- expect(canonicalJson(-1)).toBe('-1');
209
- });
210
- });
206
+ expect(canonicalJson(42)).toBe('42')
207
+ expect(canonicalJson(0)).toBe('0')
208
+ expect(canonicalJson(-1)).toBe('-1')
209
+ })
210
+ })
211
211
 
212
212
  // ---------------------------------------------------------------------------
213
213
  // Idempotency
@@ -219,9 +219,9 @@ describe('Section 6.3 — Idempotency', () => {
219
219
  methods: ['wallet_signTransaction', 'wallet_signMessage'],
220
220
  events: ['accountsChanged', 'chainChanged'],
221
221
  chains: ['eip155:1', 'eip155:137'],
222
- };
223
- const first = canonicalJson(input);
224
- const reparsed = JSON.parse(first);
225
- expect(canonicalJson(reparsed)).toBe(first);
226
- });
227
- });
222
+ }
223
+ const first = canonicalJson(input)
224
+ const reparsed = JSON.parse(first)
225
+ expect(canonicalJson(reparsed)).toBe(first)
226
+ })
227
+ })