@beclab/olaresid 0.1.13 → 0.2.1
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/CLI-TREE.md +107 -0
- package/CLI.md +122 -1340
- package/README.md +30 -12
- package/SDK-TREE.md +151 -0
- package/TAG.md +95 -41
- package/config.json +6 -4
- package/dist/abi/TerminusDIDQueryABI.d.ts +397 -0
- package/dist/abi/TerminusDIDQueryABI.d.ts.map +1 -0
- package/dist/abi/TerminusDIDQueryABI.js +519 -0
- package/dist/abi/TerminusDIDQueryABI.js.map +1 -0
- package/dist/business/index.d.ts.map +1 -1
- package/dist/business/index.js +9 -23
- package/dist/business/index.js.map +1 -1
- package/dist/business/tag-context.d.ts +1 -0
- package/dist/business/tag-context.d.ts.map +1 -1
- package/dist/business/tag-context.js +13 -7
- package/dist/business/tag-context.js.map +1 -1
- package/dist/cli.js +177 -76
- package/dist/cli.js.map +1 -1
- package/dist/config/index.d.ts +16 -4
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +28 -14
- package/dist/config/index.js.map +1 -1
- package/dist/domain/core.d.ts +65 -0
- package/dist/domain/core.d.ts.map +1 -0
- package/dist/domain/core.js +317 -0
- package/dist/domain/core.js.map +1 -0
- package/dist/domain/index.d.ts +104 -57
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +188 -428
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/types.d.ts +56 -0
- package/dist/domain/types.d.ts.map +1 -0
- package/dist/domain/types.js +3 -0
- package/dist/domain/types.js.map +1 -0
- package/dist/index.d.ts +81 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +158 -143
- package/dist/index.js.map +1 -1
- package/dist/utils/crypto-utils.d.ts +110 -0
- package/dist/utils/crypto-utils.d.ts.map +1 -1
- package/dist/utils/crypto-utils.js +127 -8
- package/dist/utils/crypto-utils.js.map +1 -1
- package/dist/utils/error-parser.d.ts.map +1 -1
- package/dist/utils/error-parser.js +2 -1
- package/dist/utils/error-parser.js.map +1 -1
- package/dist/utils/event-parser.d.ts +161 -0
- package/dist/utils/event-parser.d.ts.map +1 -0
- package/dist/utils/event-parser.js +140 -0
- package/dist/utils/event-parser.js.map +1 -0
- package/dist/utils/tag-type-builder.d.ts +43 -0
- package/dist/utils/tag-type-builder.d.ts.map +1 -1
- package/dist/utils/tag-type-builder.js +122 -0
- package/dist/utils/tag-type-builder.js.map +1 -1
- package/dist/utils/tag-type-parser.d.ts +70 -0
- package/dist/utils/tag-type-parser.d.ts.map +1 -0
- package/dist/utils/tag-type-parser.js +190 -0
- package/dist/utils/tag-type-parser.js.map +1 -0
- package/examples/create-with-rpc-demo.ts +142 -0
- package/examples/fetch-all-flat-demo.ts +159 -0
- package/examples/fetch-by-indices-demo.ts +235 -0
- package/examples/fetch-domain-demo.ts +137 -0
- package/examples/fetch-domains-demo.ts +221 -0
- package/examples/frontend-demo/index.html +2 -2
- package/examples/frontend-demo/package-lock.json +4 -1
- package/examples/index.ts +3 -5
- package/jest.config.js +25 -0
- package/package.json +6 -2
- package/src/abi/TerminusDIDQueryABI.ts +516 -0
- package/src/business/index.ts +9 -33
- package/src/business/tag-context.ts +35 -7
- package/src/cli.ts +253 -90
- package/src/config/index.ts +34 -19
- package/src/domain/core.ts +382 -0
- package/src/domain/index.ts +271 -641
- package/src/domain/types.ts +59 -0
- package/src/index.ts +230 -207
- package/src/utils/crypto-utils.ts +205 -2
- package/src/utils/error-parser.ts +2 -1
- package/src/utils/event-parser.ts +353 -0
- package/src/utils/tag-type-builder.ts +138 -0
- package/src/utils/tag-type-parser.ts +246 -0
- package/tests/unit/crypto-utils.test.ts +338 -0
- package/tests/unit/ed25519-jwk.test.ts +201 -0
- package/tests/unit/event-parser.test.ts +690 -0
- package/tests/unit/generate-mnemonic.test.ts +268 -0
- package/tests/unit/olares-id-format.test.ts +321 -0
- package/tests/unit/tag-type-parser.test.ts +802 -0
- package/tests/unit/tag-types.test.ts +821 -0
- package/tests/unit/version.test.ts +14 -0
- package/tsconfig.json +3 -2
- package/dist/abi/ABITypeABI.d.ts +0 -88
- package/dist/abi/ABITypeABI.d.ts.map +0 -1
- package/dist/abi/ABITypeABI.js +0 -382
- package/dist/abi/ABITypeABI.js.map +0 -1
- package/dist/abi/RegistryABI.d.ts +0 -77
- package/dist/abi/RegistryABI.d.ts.map +0 -1
- package/dist/abi/RegistryABI.js +0 -462
- package/dist/abi/RegistryABI.js.map +0 -1
- package/dist/tag/address.d.ts +0 -11
- package/dist/tag/address.d.ts.map +0 -1
- package/dist/tag/address.js +0 -44
- package/dist/tag/address.js.map +0 -1
- package/dist/tag/array.d.ts +0 -14
- package/dist/tag/array.d.ts.map +0 -1
- package/dist/tag/array.js +0 -72
- package/dist/tag/array.js.map +0 -1
- package/dist/tag/bool.d.ts +0 -11
- package/dist/tag/bool.d.ts.map +0 -1
- package/dist/tag/bool.js +0 -43
- package/dist/tag/bool.js.map +0 -1
- package/dist/tag/bytes.d.ts +0 -11
- package/dist/tag/bytes.d.ts.map +0 -1
- package/dist/tag/bytes.js +0 -37
- package/dist/tag/bytes.js.map +0 -1
- package/dist/tag/flarray.d.ts +0 -15
- package/dist/tag/flarray.d.ts.map +0 -1
- package/dist/tag/flarray.js +0 -81
- package/dist/tag/flarray.js.map +0 -1
- package/dist/tag/flbytes.d.ts +0 -11
- package/dist/tag/flbytes.d.ts.map +0 -1
- package/dist/tag/flbytes.js +0 -47
- package/dist/tag/flbytes.js.map +0 -1
- package/dist/tag/index.d.ts +0 -32
- package/dist/tag/index.d.ts.map +0 -1
- package/dist/tag/index.js +0 -121
- package/dist/tag/index.js.map +0 -1
- package/dist/tag/int.d.ts +0 -12
- package/dist/tag/int.d.ts.map +0 -1
- package/dist/tag/int.js +0 -49
- package/dist/tag/int.js.map +0 -1
- package/dist/tag/string.d.ts +0 -11
- package/dist/tag/string.d.ts.map +0 -1
- package/dist/tag/string.js +0 -37
- package/dist/tag/string.js.map +0 -1
- package/dist/tag/tag.d.ts +0 -67
- package/dist/tag/tag.d.ts.map +0 -1
- package/dist/tag/tag.js +0 -157
- package/dist/tag/tag.js.map +0 -1
- package/dist/tag/tuple.d.ts +0 -17
- package/dist/tag/tuple.d.ts.map +0 -1
- package/dist/tag/tuple.js +0 -162
- package/dist/tag/tuple.js.map +0 -1
- package/dist/tag/uint.d.ts +0 -12
- package/dist/tag/uint.d.ts.map +0 -1
- package/dist/tag/uint.js +0 -49
- package/dist/tag/uint.js.map +0 -1
- package/dist/test/did.d.ts +0 -2
- package/dist/test/did.d.ts.map +0 -1
- package/dist/test/did.js +0 -177
- package/dist/test/did.js.map +0 -1
- package/dist/utils/tag-abi-codec.d.ts +0 -69
- package/dist/utils/tag-abi-codec.d.ts.map +0 -1
- package/dist/utils/tag-abi-codec.js +0 -144
- package/dist/utils/tag-abi-codec.js.map +0 -1
- package/examples/crypto-utilities.ts +0 -140
- package/examples/ed25519-jwk.ts +0 -73
- package/examples/generate-mnemonic.ts +0 -149
- package/examples/legacy.ts +0 -33
- package/examples/olares-id-format.ts +0 -197
- package/examples/tag-builder.ts +0 -235
- package/examples/tag-nested-tuple.ts +0 -190
- package/examples/tag-simple.ts +0 -149
- package/examples/tag-tagger.ts +0 -217
- package/examples/test-nested-tuple-conversion.ts +0 -143
- package/examples/test-type-bytes-parser.ts +0 -70
- package/src/abi/ABITypeABI.ts +0 -379
- package/src/abi/RegistryABI.ts +0 -459
- package/src/tag/address.ts +0 -48
- package/src/tag/array.ts +0 -80
- package/src/tag/bool.ts +0 -43
- package/src/tag/bytes.ts +0 -38
- package/src/tag/flarray.ts +0 -99
- package/src/tag/flbytes.ts +0 -48
- package/src/tag/index.ts +0 -170
- package/src/tag/int.ts +0 -51
- package/src/tag/string.ts +0 -38
- package/src/tag/tag.ts +0 -229
- package/src/tag/tuple.ts +0 -193
- package/src/tag/uint.ts +0 -51
- package/src/test/did.ts +0 -346
- package/src/utils/tag-abi-codec.ts +0 -158
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generateMnemonic,
|
|
3
|
+
getEthereumAddressFromMnemonic,
|
|
4
|
+
getDIDFromMnemonic,
|
|
5
|
+
getEVMPrivateKeyFromMnemonic,
|
|
6
|
+
deriveDIDFromMnemonic,
|
|
7
|
+
generateDIDKeyData
|
|
8
|
+
} from '../../src/utils/crypto-utils';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Unit tests for crypto utility functions
|
|
12
|
+
* Tests mnemonic generation, address derivation, DID generation, etc.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
describe('Crypto Utilities', () => {
|
|
16
|
+
// Test mnemonic for consistent testing
|
|
17
|
+
const testMnemonic =
|
|
18
|
+
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
|
19
|
+
|
|
20
|
+
// ========================================
|
|
21
|
+
// Generate Mnemonic
|
|
22
|
+
// ========================================
|
|
23
|
+
|
|
24
|
+
describe('generateMnemonic', () => {
|
|
25
|
+
it('should generate 12-word mnemonic', () => {
|
|
26
|
+
const mnemonic = generateMnemonic(12);
|
|
27
|
+
expect(typeof mnemonic).toBe('string');
|
|
28
|
+
expect(mnemonic.split(' ').length).toBe(12);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should generate 24-word mnemonic', () => {
|
|
32
|
+
const mnemonic = generateMnemonic(24);
|
|
33
|
+
expect(typeof mnemonic).toBe('string');
|
|
34
|
+
expect(mnemonic.split(' ').length).toBe(24);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should generate different mnemonics each time', () => {
|
|
38
|
+
const mnemonic1 = generateMnemonic(12);
|
|
39
|
+
const mnemonic2 = generateMnemonic(12);
|
|
40
|
+
expect(mnemonic1).not.toBe(mnemonic2);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should generate valid BIP39 mnemonics', () => {
|
|
44
|
+
const mnemonic = generateMnemonic(12);
|
|
45
|
+
// Check that it's lowercase words separated by spaces
|
|
46
|
+
expect(mnemonic).toMatch(/^[a-z]+( [a-z]+){11}$/);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// ========================================
|
|
51
|
+
// Ethereum Address Derivation
|
|
52
|
+
// ========================================
|
|
53
|
+
|
|
54
|
+
describe('getEthereumAddressFromMnemonic', () => {
|
|
55
|
+
it('should derive Ethereum address from mnemonic', async () => {
|
|
56
|
+
const address = await getEthereumAddressFromMnemonic(testMnemonic);
|
|
57
|
+
|
|
58
|
+
expect(typeof address).toBe('string');
|
|
59
|
+
expect(address).toMatch(/^0x[a-fA-F0-9]{40}$/);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should derive consistent address from same mnemonic', async () => {
|
|
63
|
+
const address1 = await getEthereumAddressFromMnemonic(testMnemonic);
|
|
64
|
+
const address2 = await getEthereumAddressFromMnemonic(testMnemonic);
|
|
65
|
+
|
|
66
|
+
expect(address1).toBe(address2);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should derive different addresses from different mnemonics', async () => {
|
|
70
|
+
const mnemonic1 = generateMnemonic(12);
|
|
71
|
+
const mnemonic2 = generateMnemonic(12);
|
|
72
|
+
|
|
73
|
+
const address1 = await getEthereumAddressFromMnemonic(mnemonic1);
|
|
74
|
+
const address2 = await getEthereumAddressFromMnemonic(mnemonic2);
|
|
75
|
+
|
|
76
|
+
expect(address1).not.toBe(address2);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should derive expected address for test mnemonic', async () => {
|
|
80
|
+
const address = await getEthereumAddressFromMnemonic(testMnemonic);
|
|
81
|
+
// Known address for this test mnemonic
|
|
82
|
+
expect(address.toLowerCase()).toBe(
|
|
83
|
+
'0x9858effd232b4033e47d90003d41ec34ecaeda94'
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ========================================
|
|
89
|
+
// DID Derivation
|
|
90
|
+
// ========================================
|
|
91
|
+
|
|
92
|
+
describe('getDIDFromMnemonic', () => {
|
|
93
|
+
it('should derive DID from mnemonic', async () => {
|
|
94
|
+
const did = await getDIDFromMnemonic(testMnemonic);
|
|
95
|
+
|
|
96
|
+
expect(typeof did).toBe('string');
|
|
97
|
+
expect(did).toMatch(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should derive consistent DID from same mnemonic', async () => {
|
|
101
|
+
const did1 = await getDIDFromMnemonic(testMnemonic);
|
|
102
|
+
const did2 = await getDIDFromMnemonic(testMnemonic);
|
|
103
|
+
|
|
104
|
+
expect(did1).toBe(did2);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should derive different DIDs from different mnemonics', async () => {
|
|
108
|
+
const mnemonic1 = generateMnemonic(12);
|
|
109
|
+
const mnemonic2 = generateMnemonic(12);
|
|
110
|
+
|
|
111
|
+
const did1 = await getDIDFromMnemonic(mnemonic1);
|
|
112
|
+
const did2 = await getDIDFromMnemonic(mnemonic2);
|
|
113
|
+
|
|
114
|
+
expect(did1).not.toBe(did2);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// ========================================
|
|
119
|
+
// EVM Private Key Derivation
|
|
120
|
+
// ========================================
|
|
121
|
+
|
|
122
|
+
describe('getEVMPrivateKeyFromMnemonic', () => {
|
|
123
|
+
it('should derive private key from mnemonic', async () => {
|
|
124
|
+
const privateKey = await getEVMPrivateKeyFromMnemonic(testMnemonic);
|
|
125
|
+
|
|
126
|
+
expect(typeof privateKey).toBe('string');
|
|
127
|
+
expect(privateKey).toMatch(/^0x[a-fA-F0-9]{64}$/);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should derive consistent private key from same mnemonic', async () => {
|
|
131
|
+
const privateKey1 = await getEVMPrivateKeyFromMnemonic(
|
|
132
|
+
testMnemonic
|
|
133
|
+
);
|
|
134
|
+
const privateKey2 = await getEVMPrivateKeyFromMnemonic(
|
|
135
|
+
testMnemonic
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
expect(privateKey1).toBe(privateKey2);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should derive different private keys from different mnemonics', async () => {
|
|
142
|
+
const mnemonic1 = generateMnemonic(12);
|
|
143
|
+
const mnemonic2 = generateMnemonic(12);
|
|
144
|
+
|
|
145
|
+
const privateKey1 = await getEVMPrivateKeyFromMnemonic(mnemonic1);
|
|
146
|
+
const privateKey2 = await getEVMPrivateKeyFromMnemonic(mnemonic2);
|
|
147
|
+
|
|
148
|
+
expect(privateKey1).not.toBe(privateKey2);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// ========================================
|
|
153
|
+
// Derive Owner and DID Together
|
|
154
|
+
// ========================================
|
|
155
|
+
|
|
156
|
+
describe('deriveDIDFromMnemonic', () => {
|
|
157
|
+
it('should derive both owner and DID from mnemonic', async () => {
|
|
158
|
+
const result = await deriveDIDFromMnemonic(testMnemonic);
|
|
159
|
+
|
|
160
|
+
expect(result).toHaveProperty('owner');
|
|
161
|
+
expect(result).toHaveProperty('did');
|
|
162
|
+
expect(result.owner).toMatch(/^0x[a-fA-F0-9]{40}$/);
|
|
163
|
+
expect(result.did).toMatch(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('should derive consistent results from same mnemonic', async () => {
|
|
167
|
+
const result1 = await deriveDIDFromMnemonic(testMnemonic);
|
|
168
|
+
const result2 = await deriveDIDFromMnemonic(testMnemonic);
|
|
169
|
+
|
|
170
|
+
expect(result1.owner).toBe(result2.owner);
|
|
171
|
+
expect(result1.did).toBe(result2.did);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should match individual derivation methods', async () => {
|
|
175
|
+
const combined = await deriveDIDFromMnemonic(testMnemonic);
|
|
176
|
+
const separateAddress = await getEthereumAddressFromMnemonic(
|
|
177
|
+
testMnemonic
|
|
178
|
+
);
|
|
179
|
+
const separateDid = await getDIDFromMnemonic(testMnemonic);
|
|
180
|
+
|
|
181
|
+
expect(combined.owner).toBe(separateAddress);
|
|
182
|
+
expect(combined.did).toBe(separateDid);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// ========================================
|
|
187
|
+
// Generate Complete Key Data
|
|
188
|
+
// ========================================
|
|
189
|
+
|
|
190
|
+
describe('generateDIDKeyData', () => {
|
|
191
|
+
it('should generate complete key data with 12 words', async () => {
|
|
192
|
+
const keyData = await generateDIDKeyData(12);
|
|
193
|
+
|
|
194
|
+
expect(keyData).toHaveProperty('mnemonic');
|
|
195
|
+
expect(keyData).toHaveProperty('owner');
|
|
196
|
+
expect(keyData).toHaveProperty('did');
|
|
197
|
+
|
|
198
|
+
expect(keyData.mnemonic.split(' ').length).toBe(12);
|
|
199
|
+
expect(keyData.owner).toMatch(/^0x[a-fA-F0-9]{40}$/);
|
|
200
|
+
expect(keyData.did).toMatch(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should generate complete key data with 24 words', async () => {
|
|
204
|
+
const keyData = await generateDIDKeyData(24);
|
|
205
|
+
|
|
206
|
+
expect(keyData.mnemonic.split(' ').length).toBe(24);
|
|
207
|
+
expect(keyData.owner).toMatch(/^0x[a-fA-F0-9]{40}$/);
|
|
208
|
+
expect(keyData.did).toMatch(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should generate unique key data each time', async () => {
|
|
212
|
+
const keyData1 = await generateDIDKeyData(12);
|
|
213
|
+
const keyData2 = await generateDIDKeyData(12);
|
|
214
|
+
|
|
215
|
+
expect(keyData1.mnemonic).not.toBe(keyData2.mnemonic);
|
|
216
|
+
expect(keyData1.owner).not.toBe(keyData2.owner);
|
|
217
|
+
expect(keyData1.did).not.toBe(keyData2.did);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should have consistent derivation within generated data', async () => {
|
|
221
|
+
const keyData = await generateDIDKeyData(12);
|
|
222
|
+
|
|
223
|
+
// Verify owner matches when derived separately
|
|
224
|
+
const separateOwner = await getEthereumAddressFromMnemonic(
|
|
225
|
+
keyData.mnemonic
|
|
226
|
+
);
|
|
227
|
+
expect(keyData.owner).toBe(separateOwner);
|
|
228
|
+
|
|
229
|
+
// Verify DID matches when derived separately
|
|
230
|
+
const separateDid = await getDIDFromMnemonic(keyData.mnemonic);
|
|
231
|
+
expect(keyData.did).toBe(separateDid);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// ========================================
|
|
236
|
+
// Cross-Validation Tests
|
|
237
|
+
// ========================================
|
|
238
|
+
|
|
239
|
+
describe('Cross-Validation', () => {
|
|
240
|
+
it('should have consistent address across all derivation methods', async () => {
|
|
241
|
+
const mnemonic = generateMnemonic(12);
|
|
242
|
+
|
|
243
|
+
const address1 = await getEthereumAddressFromMnemonic(mnemonic);
|
|
244
|
+
const { owner: address2 } = await deriveDIDFromMnemonic(mnemonic);
|
|
245
|
+
const { owner: address3 } = await generateDIDKeyData(12); // This uses different mnemonic
|
|
246
|
+
|
|
247
|
+
// Same mnemonic should produce same address
|
|
248
|
+
expect(address1).toBe(address2);
|
|
249
|
+
|
|
250
|
+
// Different mnemonics should produce different addresses
|
|
251
|
+
expect(address1).not.toBe(address3);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should have consistent DID across all derivation methods', async () => {
|
|
255
|
+
const mnemonic = generateMnemonic(12);
|
|
256
|
+
|
|
257
|
+
const did1 = await getDIDFromMnemonic(mnemonic);
|
|
258
|
+
const { did: did2 } = await deriveDIDFromMnemonic(mnemonic);
|
|
259
|
+
|
|
260
|
+
// Same mnemonic should produce same DID
|
|
261
|
+
expect(did1).toBe(did2);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('should derive matching private key and address', async () => {
|
|
265
|
+
const { ethers } = await import('ethers');
|
|
266
|
+
|
|
267
|
+
const privateKey = await getEVMPrivateKeyFromMnemonic(testMnemonic);
|
|
268
|
+
const address = await getEthereumAddressFromMnemonic(testMnemonic);
|
|
269
|
+
|
|
270
|
+
// Create wallet from private key and verify address matches
|
|
271
|
+
const wallet = new ethers.Wallet(privateKey);
|
|
272
|
+
expect(wallet.address).toBe(address);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// ========================================
|
|
277
|
+
// Edge Cases
|
|
278
|
+
// ========================================
|
|
279
|
+
|
|
280
|
+
describe('Edge Cases', () => {
|
|
281
|
+
it('should handle 12-word and 24-word mnemonics equally', async () => {
|
|
282
|
+
const mnemonic12 = generateMnemonic(12);
|
|
283
|
+
const mnemonic24 = generateMnemonic(24);
|
|
284
|
+
|
|
285
|
+
const address12 = await getEthereumAddressFromMnemonic(mnemonic12);
|
|
286
|
+
const address24 = await getEthereumAddressFromMnemonic(mnemonic24);
|
|
287
|
+
|
|
288
|
+
// Both should be valid addresses
|
|
289
|
+
expect(address12).toMatch(/^0x[a-fA-F0-9]{40}$/);
|
|
290
|
+
expect(address24).toMatch(/^0x[a-fA-F0-9]{40}$/);
|
|
291
|
+
|
|
292
|
+
const did12 = await getDIDFromMnemonic(mnemonic12);
|
|
293
|
+
const did24 = await getDIDFromMnemonic(mnemonic24);
|
|
294
|
+
|
|
295
|
+
// Both should be valid DIDs
|
|
296
|
+
expect(did12).toMatch(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/);
|
|
297
|
+
expect(did24).toMatch(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('should handle mnemonic with extra whitespace', async () => {
|
|
301
|
+
// Note: Most implementations trim whitespace before validation
|
|
302
|
+
// So we test that trimmed mnemonics work correctly
|
|
303
|
+
const mnemonicWithSpaces = ' ' + testMnemonic + ' ';
|
|
304
|
+
|
|
305
|
+
// The crypto-utils functions should handle trimming internally
|
|
306
|
+
// For now, we verify that trimmed version works
|
|
307
|
+
const trimmedMnemonic = mnemonicWithSpaces.trim();
|
|
308
|
+
const address = await getEthereumAddressFromMnemonic(
|
|
309
|
+
trimmedMnemonic
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
expect(address).toMatch(/^0x[a-fA-F0-9]{40}$/);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// ========================================
|
|
317
|
+
// Known Test Vectors
|
|
318
|
+
// ========================================
|
|
319
|
+
|
|
320
|
+
describe('Known Test Vectors', () => {
|
|
321
|
+
it('should match expected values for standard test mnemonic', async () => {
|
|
322
|
+
const address = await getEthereumAddressFromMnemonic(testMnemonic);
|
|
323
|
+
const privateKey = await getEVMPrivateKeyFromMnemonic(testMnemonic);
|
|
324
|
+
const did = await getDIDFromMnemonic(testMnemonic);
|
|
325
|
+
|
|
326
|
+
// Known values for "abandon abandon..." mnemonic
|
|
327
|
+
expect(address.toLowerCase()).toBe(
|
|
328
|
+
'0x9858effd232b4033e47d90003d41ec34ecaeda94'
|
|
329
|
+
);
|
|
330
|
+
expect(privateKey.toLowerCase()).toBe(
|
|
331
|
+
'0x1ab42cc412b618bdea3a599e3c9bae199ebf030895b039e9db1e30dafb12b727'
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
// DID should be consistent (exact value depends on ed25519 derivation)
|
|
335
|
+
expect(did).toMatch(/^did:key:z6Mk/);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
});
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { generateMnemonic, getEd25519JwkFromMnemonic } from '../../src/index';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Unit tests for Ed25519 JWK generation
|
|
5
|
+
* Tests Ed25519 key pair derivation from mnemonic and JWK format conversion
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
describe('Ed25519 JWK Generation', () => {
|
|
9
|
+
// Test mnemonic for consistent testing
|
|
10
|
+
const testMnemonic =
|
|
11
|
+
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
|
12
|
+
|
|
13
|
+
// ========================================
|
|
14
|
+
// Basic JWK Generation
|
|
15
|
+
// ========================================
|
|
16
|
+
|
|
17
|
+
describe('getEd25519JwkFromMnemonic', () => {
|
|
18
|
+
it('should generate Ed25519 JWK from mnemonic', async () => {
|
|
19
|
+
const result = await getEd25519JwkFromMnemonic(testMnemonic);
|
|
20
|
+
|
|
21
|
+
expect(result).toHaveProperty('publicJwk');
|
|
22
|
+
expect(result).toHaveProperty('privateJwk');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should generate valid public JWK structure', async () => {
|
|
26
|
+
const { publicJwk } = await getEd25519JwkFromMnemonic(testMnemonic);
|
|
27
|
+
|
|
28
|
+
expect(publicJwk).toHaveProperty('kty', 'OKP');
|
|
29
|
+
expect(publicJwk).toHaveProperty('crv', 'Ed25519');
|
|
30
|
+
expect(publicJwk).toHaveProperty('x');
|
|
31
|
+
expect(typeof publicJwk.x).toBe('string');
|
|
32
|
+
expect(publicJwk.x.length).toBeGreaterThan(0);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should generate valid private JWK structure', async () => {
|
|
36
|
+
const { privateJwk } = await getEd25519JwkFromMnemonic(
|
|
37
|
+
testMnemonic
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
expect(privateJwk).toHaveProperty('kty', 'OKP');
|
|
41
|
+
expect(privateJwk).toHaveProperty('crv', 'Ed25519');
|
|
42
|
+
expect(privateJwk).toHaveProperty('x');
|
|
43
|
+
expect(privateJwk).toHaveProperty('d');
|
|
44
|
+
expect(typeof privateJwk.x).toBe('string');
|
|
45
|
+
expect(typeof privateJwk.d).toBe('string');
|
|
46
|
+
expect(privateJwk.x.length).toBeGreaterThan(0);
|
|
47
|
+
expect(privateJwk.d.length).toBeGreaterThan(0);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should have matching public key in both JWKs', async () => {
|
|
51
|
+
const { publicJwk, privateJwk } = await getEd25519JwkFromMnemonic(
|
|
52
|
+
testMnemonic
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// The public key component (x) should match in both JWKs
|
|
56
|
+
expect(publicJwk.x).toBe(privateJwk.x);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should generate consistent JWKs from same mnemonic', async () => {
|
|
60
|
+
const result1 = await getEd25519JwkFromMnemonic(testMnemonic);
|
|
61
|
+
const result2 = await getEd25519JwkFromMnemonic(testMnemonic);
|
|
62
|
+
|
|
63
|
+
expect(result1.publicJwk.x).toBe(result2.publicJwk.x);
|
|
64
|
+
expect(result1.privateJwk.x).toBe(result2.privateJwk.x);
|
|
65
|
+
expect(result1.privateJwk.d).toBe(result2.privateJwk.d);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should generate different JWKs from different mnemonics', async () => {
|
|
69
|
+
const mnemonic1 = generateMnemonic(12);
|
|
70
|
+
const mnemonic2 = generateMnemonic(12);
|
|
71
|
+
|
|
72
|
+
const result1 = await getEd25519JwkFromMnemonic(mnemonic1);
|
|
73
|
+
const result2 = await getEd25519JwkFromMnemonic(mnemonic2);
|
|
74
|
+
|
|
75
|
+
expect(result1.publicJwk.x).not.toBe(result2.publicJwk.x);
|
|
76
|
+
expect(result1.privateJwk.d).not.toBe(result2.privateJwk.d);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// ========================================
|
|
81
|
+
// JWK Format Validation
|
|
82
|
+
// ========================================
|
|
83
|
+
|
|
84
|
+
describe('JWK Format Validation', () => {
|
|
85
|
+
it('should generate RFC 7517 compliant public JWK', async () => {
|
|
86
|
+
const { publicJwk } = await getEd25519JwkFromMnemonic(testMnemonic);
|
|
87
|
+
|
|
88
|
+
// RFC 7517: Public key must have kty, crv, x
|
|
89
|
+
expect(publicJwk.kty).toBe('OKP');
|
|
90
|
+
expect(publicJwk.crv).toBe('Ed25519');
|
|
91
|
+
expect(publicJwk.x).toBeDefined();
|
|
92
|
+
|
|
93
|
+
// Public JWK should NOT have private key component (d)
|
|
94
|
+
expect(publicJwk).not.toHaveProperty('d');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should generate RFC 7517 compliant private JWK', async () => {
|
|
98
|
+
const { privateJwk } = await getEd25519JwkFromMnemonic(
|
|
99
|
+
testMnemonic
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// RFC 7517: Private key must have kty, crv, x, d
|
|
103
|
+
expect(privateJwk.kty).toBe('OKP');
|
|
104
|
+
expect(privateJwk.crv).toBe('Ed25519');
|
|
105
|
+
expect(privateJwk.x).toBeDefined();
|
|
106
|
+
expect(privateJwk.d).toBeDefined();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should use base64url encoding for key components', async () => {
|
|
110
|
+
const { publicJwk, privateJwk } = await getEd25519JwkFromMnemonic(
|
|
111
|
+
testMnemonic
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// Base64url should not contain +, /, or =
|
|
115
|
+
expect(publicJwk.x).not.toMatch(/[+/=]/);
|
|
116
|
+
expect(privateJwk.x).not.toMatch(/[+/=]/);
|
|
117
|
+
expect(privateJwk.d).not.toMatch(/[+/=]/);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// ========================================
|
|
122
|
+
// Integration with Other Functions
|
|
123
|
+
// ========================================
|
|
124
|
+
|
|
125
|
+
describe('Integration Tests', () => {
|
|
126
|
+
it('should work with generated mnemonics', async () => {
|
|
127
|
+
const mnemonic = generateMnemonic(12);
|
|
128
|
+
const { publicJwk, privateJwk } = await getEd25519JwkFromMnemonic(
|
|
129
|
+
mnemonic
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(publicJwk.x).toBeDefined();
|
|
133
|
+
expect(privateJwk.d).toBeDefined();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('should work with 12-word and 24-word mnemonics', async () => {
|
|
137
|
+
const mnemonic12 = generateMnemonic(12);
|
|
138
|
+
const mnemonic24 = generateMnemonic(24);
|
|
139
|
+
|
|
140
|
+
const result12 = await getEd25519JwkFromMnemonic(mnemonic12);
|
|
141
|
+
const result24 = await getEd25519JwkFromMnemonic(mnemonic24);
|
|
142
|
+
|
|
143
|
+
// Both should generate valid JWKs
|
|
144
|
+
expect(result12.publicJwk.kty).toBe('OKP');
|
|
145
|
+
expect(result24.publicJwk.kty).toBe('OKP');
|
|
146
|
+
|
|
147
|
+
// Should be different keys
|
|
148
|
+
expect(result12.publicJwk.x).not.toBe(result24.publicJwk.x);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// ========================================
|
|
153
|
+
// Known Test Vectors
|
|
154
|
+
// ========================================
|
|
155
|
+
|
|
156
|
+
describe('Known Test Vectors', () => {
|
|
157
|
+
it('should generate expected JWK for standard test mnemonic', async () => {
|
|
158
|
+
const { publicJwk, privateJwk } = await getEd25519JwkFromMnemonic(
|
|
159
|
+
testMnemonic
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Verify structure
|
|
163
|
+
expect(publicJwk.kty).toBe('OKP');
|
|
164
|
+
expect(publicJwk.crv).toBe('Ed25519');
|
|
165
|
+
expect(privateJwk.kty).toBe('OKP');
|
|
166
|
+
expect(privateJwk.crv).toBe('Ed25519');
|
|
167
|
+
|
|
168
|
+
// Public and private JWK should have matching public key
|
|
169
|
+
expect(publicJwk.x).toBe(privateJwk.x);
|
|
170
|
+
|
|
171
|
+
// Keys should be valid base64url
|
|
172
|
+
expect(publicJwk.x).toMatch(/^[A-Za-z0-9_-]+$/);
|
|
173
|
+
expect(privateJwk.d).toMatch(/^[A-Za-z0-9_-]+$/);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// ========================================
|
|
178
|
+
// Security Tests
|
|
179
|
+
// ========================================
|
|
180
|
+
|
|
181
|
+
describe('Security Tests', () => {
|
|
182
|
+
it('should generate different keys for different mnemonics', async () => {
|
|
183
|
+
const result1 = await getEd25519JwkFromMnemonic(testMnemonic);
|
|
184
|
+
const result2 = await getEd25519JwkFromMnemonic(
|
|
185
|
+
generateMnemonic(12)
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// Keys should be completely different
|
|
189
|
+
expect(result1.publicJwk.x).not.toBe(result2.publicJwk.x);
|
|
190
|
+
expect(result1.privateJwk.d).not.toBe(result2.privateJwk.d);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should not expose private key in public JWK', async () => {
|
|
194
|
+
const { publicJwk } = await getEd25519JwkFromMnemonic(testMnemonic);
|
|
195
|
+
|
|
196
|
+
// Ensure private key component is not present
|
|
197
|
+
expect(publicJwk.d).toBeUndefined();
|
|
198
|
+
expect(Object.keys(publicJwk)).not.toContain('d');
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
});
|