@onekeyfe/hd-core 1.2.0-alpha.36 → 1.2.0-alpha.37
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/__tests__/AllNetworkGetAddressBase.tracing.test.ts +5 -1
- package/__tests__/deviceUploadNft.test.ts +187 -0
- package/__tests__/homescreen.test.ts +41 -1
- package/__tests__/logBlockEvent.test.ts +1 -1
- package/__tests__/open-wallet-session.test.ts +161 -44
- package/__tests__/pro2Nft.test.ts +108 -0
- package/__tests__/protocol-v2-unlock-policy.test.ts +86 -35
- package/__tests__/protocol-v2.test.ts +168 -444
- package/__tests__/public-pro2-api-boundary.test.ts +1 -0
- package/dist/api/BaseMethod.d.ts +3 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +2 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +30 -0
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/index.d.ts +34 -2
- package/dist/index.js +500 -462
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +2 -1
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +3 -0
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/utils/homescreen.d.ts +4 -0
- package/dist/utils/homescreen.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2Nft.d.ts +29 -0
- package/dist/utils/pro2Nft.d.ts.map +1 -0
- package/dist/utils/pro2Wallpaper.d.ts +10 -0
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +7 -9
- package/src/api/OpenWalletSession.ts +37 -15
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +29 -30
- package/src/api/helpers/protocolV2FileWrite.ts +11 -4
- package/src/api/index.ts +1 -0
- package/src/api/protocol-v2/DeviceUploadNft.ts +166 -0
- package/src/core/index.ts +76 -81
- package/src/data/messages/messages-protocol-v2.json +10 -15
- package/src/events/logBlockEvent.ts +1 -0
- package/src/inject.ts +1 -0
- package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +117 -0
- package/src/protocols/protocol-v2/walletSession.ts +18 -51
- package/src/types/api/index.ts +2 -0
- package/src/types/api/protocolV2.ts +13 -0
- package/src/utils/homescreen.ts +32 -6
- package/src/utils/index.ts +6 -1
- package/src/utils/pro2Nft.ts +91 -0
- package/src/utils/pro2Wallpaper.ts +35 -8
- package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
- package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
- package/src/protocols/protocol-v2/lockedError.ts +0 -10
- package/src/protocols/protocol-v2/unlockRetry.ts +0 -131
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { blake2s } from '@noble/hashes/blake2s';
|
|
2
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
PRO2_NFT_IMAGE_HEIGHT,
|
|
6
|
+
PRO2_NFT_IMAGE_WIDTH,
|
|
7
|
+
PRO2_NFT_THUMBNAIL_HEIGHT,
|
|
8
|
+
PRO2_NFT_THUMBNAIL_WIDTH,
|
|
9
|
+
buildPro2NftBundle,
|
|
10
|
+
} from '../src/utils/pro2Nft';
|
|
11
|
+
|
|
12
|
+
const rgba = (width: number, height: number, alpha = 0xff) => {
|
|
13
|
+
const data = new Uint8Array(width * height * 4);
|
|
14
|
+
for (let index = 3; index < data.length; index += 4) data[index] = alpha;
|
|
15
|
+
return data;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe('buildPro2NftBundle', () => {
|
|
19
|
+
test('builds the exact Pro2 RGB565 triplet and basename', () => {
|
|
20
|
+
const bundle = buildPro2NftBundle({
|
|
21
|
+
image: {
|
|
22
|
+
width: PRO2_NFT_IMAGE_WIDTH,
|
|
23
|
+
height: PRO2_NFT_IMAGE_HEIGHT,
|
|
24
|
+
rgba: rgba(PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT),
|
|
25
|
+
},
|
|
26
|
+
thumbnail: {
|
|
27
|
+
width: PRO2_NFT_THUMBNAIL_WIDTH,
|
|
28
|
+
height: PRO2_NFT_THUMBNAIL_HEIGHT,
|
|
29
|
+
rgba: rgba(PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT),
|
|
30
|
+
},
|
|
31
|
+
title: 'CryptoPunk #3100',
|
|
32
|
+
subtitle: 'CryptoPunks',
|
|
33
|
+
timestampMs: 1_760_000_000_000,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(bundle.image.byteLength).toBe(583_212);
|
|
37
|
+
expect(bundle.thumbnail.byteLength).toBe(138_876);
|
|
38
|
+
expect(Array.from(bundle.image.slice(0, 12))).toEqual([
|
|
39
|
+
0x19, 0x12, 0, 0, 28, 2, 28, 2, 56, 4, 0, 0,
|
|
40
|
+
]);
|
|
41
|
+
expect(Array.from(bundle.thumbnail.slice(0, 12))).toEqual([
|
|
42
|
+
0x19, 0x12, 0, 0, 7, 1, 7, 1, 16, 2, 0, 0,
|
|
43
|
+
]);
|
|
44
|
+
expect(new TextDecoder().decode(bundle.metadata)).toBe(
|
|
45
|
+
'{"title":"CryptoPunk #3100","subtitle":"CryptoPunks"}'
|
|
46
|
+
);
|
|
47
|
+
expect(bytesToHex(blake2s(bundle.image))).toBe(
|
|
48
|
+
'af4b5f8fe216cfd0ef4a9162a42b5c66a73466f2491066f66f756c4e28cc869e'
|
|
49
|
+
);
|
|
50
|
+
expect(bytesToHex(blake2s(bundle.thumbnail))).toBe(
|
|
51
|
+
'44591afae1163cc14651d77644501c6a110f96506889b825cab0351ff4de857d'
|
|
52
|
+
);
|
|
53
|
+
expect(bytesToHex(blake2s(bundle.metadata))).toBe(
|
|
54
|
+
'e30d4dc2cddd441c9f1438c783e05a623ccf76f2f6219d4281769dda1b3635b5'
|
|
55
|
+
);
|
|
56
|
+
expect(bundle.basename).toBe('nft-af4b5f8f-1760000000000');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('composites transparent pixels onto black without an alpha plane', () => {
|
|
60
|
+
const image = rgba(PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT);
|
|
61
|
+
image.set([255, 255, 255, 0], 0);
|
|
62
|
+
const bundle = buildPro2NftBundle({
|
|
63
|
+
image: { width: PRO2_NFT_IMAGE_WIDTH, height: PRO2_NFT_IMAGE_HEIGHT, rgba: image },
|
|
64
|
+
thumbnail: {
|
|
65
|
+
width: PRO2_NFT_THUMBNAIL_WIDTH,
|
|
66
|
+
height: PRO2_NFT_THUMBNAIL_HEIGHT,
|
|
67
|
+
rgba: rgba(PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT, 0),
|
|
68
|
+
},
|
|
69
|
+
title: 'NFT',
|
|
70
|
+
subtitle: '',
|
|
71
|
+
timestampMs: 1,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(bundle.image[1]).toBe(0x12);
|
|
75
|
+
expect(Array.from(bundle.image.slice(12, 14))).toEqual([0, 0]);
|
|
76
|
+
expect(bundle.thumbnail.byteLength).toBe(138_876);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('rejects invalid dimensions and metadata byte lengths', () => {
|
|
80
|
+
const validThumbnail = {
|
|
81
|
+
width: PRO2_NFT_THUMBNAIL_WIDTH,
|
|
82
|
+
height: PRO2_NFT_THUMBNAIL_HEIGHT,
|
|
83
|
+
rgba: rgba(PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT),
|
|
84
|
+
};
|
|
85
|
+
expect(() =>
|
|
86
|
+
buildPro2NftBundle({
|
|
87
|
+
image: { width: 1, height: 1, rgba: new Uint8Array(4) },
|
|
88
|
+
thumbnail: validThumbnail,
|
|
89
|
+
title: 'NFT',
|
|
90
|
+
subtitle: '',
|
|
91
|
+
timestampMs: 1,
|
|
92
|
+
})
|
|
93
|
+
).toThrow('540x540');
|
|
94
|
+
expect(() =>
|
|
95
|
+
buildPro2NftBundle({
|
|
96
|
+
image: {
|
|
97
|
+
width: PRO2_NFT_IMAGE_WIDTH,
|
|
98
|
+
height: PRO2_NFT_IMAGE_HEIGHT,
|
|
99
|
+
rgba: rgba(PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT),
|
|
100
|
+
},
|
|
101
|
+
thumbnail: validThumbnail,
|
|
102
|
+
title: 'a'.repeat(64),
|
|
103
|
+
subtitle: '',
|
|
104
|
+
timestampMs: 1,
|
|
105
|
+
})
|
|
106
|
+
).toThrow('1 to 63');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -1,45 +1,96 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
getProtocolV2UnlockPolicy,
|
|
5
|
-
} from '../src/protocols/protocol-v2/unlockPolicy';
|
|
1
|
+
import ConfluxSignMessageCIP23 from '../src/api/conflux/ConfluxSignMessageCIP23';
|
|
2
|
+
import DeviceLock from '../src/api/device/DeviceLock';
|
|
3
|
+
import { runMethodWithUnlockPolicy } from '../src/protocols/protocol-v2/unlockPolicyRunner';
|
|
6
4
|
|
|
7
5
|
jest.mock('../src/data/config', () => ({
|
|
8
6
|
DEFAULT_DOMAIN: 'https://example.com/',
|
|
9
7
|
getSDKVersion: () => '0.0.0-test',
|
|
10
8
|
}));
|
|
11
9
|
|
|
12
|
-
describe('Protocol V2
|
|
13
|
-
test('
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
10
|
+
describe('Protocol V2 unlock semantics', () => {
|
|
11
|
+
test('wallet business methods inherit the wallet-session unlock requirement', () => {
|
|
12
|
+
const method = new ConfluxSignMessageCIP23({
|
|
13
|
+
id: 1,
|
|
14
|
+
payload: { method: 'confluxSignMessageCIP23' },
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
expect(method.useDevicePassphraseState).toBe(true);
|
|
18
|
+
expect(method.unlockPolicy).toBe('none');
|
|
19
|
+
expect(method.getSupportedProtocols()).toContain('V2');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('lock-free Protocol V2 controls explicitly opt out of wallet-session handling', () => {
|
|
23
|
+
const method = new DeviceLock({
|
|
24
|
+
id: 1,
|
|
25
|
+
payload: { method: 'deviceLock' },
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
method.init();
|
|
29
|
+
|
|
30
|
+
expect(method.useDevicePassphraseState).toBe(false);
|
|
31
|
+
expect(method.unlockPolicy).toBe('none');
|
|
31
32
|
});
|
|
32
33
|
|
|
33
|
-
test
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
test('pre-unlocks an unregistered wallet business method', async () => {
|
|
35
|
+
const features = { unlocked: false };
|
|
36
|
+
const method = {
|
|
37
|
+
name: 'newWalletBusinessMethod',
|
|
38
|
+
unlockPolicy: 'none',
|
|
39
|
+
useDevicePassphraseState: true,
|
|
40
|
+
run: jest.fn().mockResolvedValue({ message: 'ok' }),
|
|
41
|
+
};
|
|
42
|
+
const device = {
|
|
43
|
+
features,
|
|
44
|
+
commands: {
|
|
45
|
+
typedCall: jest.fn().mockResolvedValue({ message: { unlocked: false } }),
|
|
46
|
+
},
|
|
47
|
+
isProtocolV2: () => true,
|
|
48
|
+
isBootloader: () => false,
|
|
49
|
+
isRomloader: () => false,
|
|
50
|
+
updateProtocolV2Status: jest.fn(() => features),
|
|
51
|
+
unlockDevice: jest.fn().mockImplementation(() => {
|
|
52
|
+
features.unlocked = true;
|
|
53
|
+
return Promise.resolve(features);
|
|
54
|
+
}),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
await expect(runMethodWithUnlockPolicy(method as any, device as any)).resolves.toEqual({
|
|
58
|
+
message: 'ok',
|
|
59
|
+
});
|
|
60
|
+
expect(device.unlockDevice).toHaveBeenCalledTimes(1);
|
|
61
|
+
expect(method.run).toHaveBeenCalledTimes(1);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('runs fresh-status validation before starting unlock', async () => {
|
|
65
|
+
const identityError = new Error('Unexpected device');
|
|
66
|
+
const method = {
|
|
67
|
+
name: 'walletBusinessMethod',
|
|
68
|
+
unlockPolicy: 'none',
|
|
69
|
+
useDevicePassphraseState: true,
|
|
70
|
+
run: jest.fn(),
|
|
71
|
+
};
|
|
72
|
+
const features = { unlocked: false };
|
|
73
|
+
const device = {
|
|
74
|
+
features,
|
|
75
|
+
commands: {
|
|
76
|
+
typedCall: jest.fn().mockResolvedValue({ message: { unlocked: false } }),
|
|
77
|
+
},
|
|
78
|
+
isProtocolV2: () => true,
|
|
79
|
+
isBootloader: () => false,
|
|
80
|
+
isRomloader: () => false,
|
|
81
|
+
updateProtocolV2Status: jest.fn(() => features),
|
|
82
|
+
unlockDevice: jest.fn(),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
await expect(
|
|
86
|
+
runMethodWithUnlockPolicy(method as any, device as any, {
|
|
87
|
+
afterStatusBeforeUnlock: () => {
|
|
88
|
+
throw identityError;
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
).rejects.toBe(identityError);
|
|
92
|
+
|
|
93
|
+
expect(device.unlockDevice).not.toHaveBeenCalled();
|
|
94
|
+
expect(method.run).not.toHaveBeenCalled();
|
|
44
95
|
});
|
|
45
96
|
});
|