@ledgerhq/ledger-key-ring-protocol 0.5.1-nightly.0

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 (180) hide show
  1. package/.eslintrc.js +33 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/.unimportedrc.json +16 -0
  4. package/CHANGELOG.md +299 -0
  5. package/LICENSE.txt +21 -0
  6. package/README.md +3 -0
  7. package/jest.config.js +13 -0
  8. package/lib/HWDeviceProvider.d.ts +25 -0
  9. package/lib/HWDeviceProvider.d.ts.map +1 -0
  10. package/lib/HWDeviceProvider.js +88 -0
  11. package/lib/HWDeviceProvider.js.map +1 -0
  12. package/lib/api.d.ts +77 -0
  13. package/lib/api.d.ts.map +1 -0
  14. package/lib/api.js +150 -0
  15. package/lib/api.js.map +1 -0
  16. package/lib/auth.d.ts +3 -0
  17. package/lib/auth.d.ts.map +1 -0
  18. package/lib/auth.js +79 -0
  19. package/lib/auth.js.map +1 -0
  20. package/lib/errors.d.ts +40 -0
  21. package/lib/errors.d.ts.map +1 -0
  22. package/lib/errors.js +18 -0
  23. package/lib/errors.js.map +1 -0
  24. package/lib/index.d.ts +6 -0
  25. package/lib/index.d.ts.map +1 -0
  26. package/lib/index.js +17 -0
  27. package/lib/index.js.map +1 -0
  28. package/lib/mockSdk.d.ts +22 -0
  29. package/lib/mockSdk.d.ts.map +1 -0
  30. package/lib/mockSdk.js +208 -0
  31. package/lib/mockSdk.js.map +1 -0
  32. package/lib/qrcode/cipher.d.ts +12 -0
  33. package/lib/qrcode/cipher.d.ts.map +1 -0
  34. package/lib/qrcode/cipher.js +69 -0
  35. package/lib/qrcode/cipher.js.map +1 -0
  36. package/lib/qrcode/cipher.test.d.ts +2 -0
  37. package/lib/qrcode/cipher.test.d.ts.map +1 -0
  38. package/lib/qrcode/cipher.test.js +40 -0
  39. package/lib/qrcode/cipher.test.js.map +1 -0
  40. package/lib/qrcode/index.d.ts +70 -0
  41. package/lib/qrcode/index.d.ts.map +1 -0
  42. package/lib/qrcode/index.js +312 -0
  43. package/lib/qrcode/index.js.map +1 -0
  44. package/lib/qrcode/index.test.d.ts +2 -0
  45. package/lib/qrcode/index.test.d.ts.map +1 -0
  46. package/lib/qrcode/index.test.js +131 -0
  47. package/lib/qrcode/index.test.js.map +1 -0
  48. package/lib/qrcode/types.d.ts +69 -0
  49. package/lib/qrcode/types.d.ts.map +1 -0
  50. package/lib/qrcode/types.js +3 -0
  51. package/lib/qrcode/types.js.map +1 -0
  52. package/lib/sdk.d.ts +31 -0
  53. package/lib/sdk.d.ts.map +1 -0
  54. package/lib/sdk.js +380 -0
  55. package/lib/sdk.js.map +1 -0
  56. package/lib/store.d.ts +71 -0
  57. package/lib/store.d.ts.map +1 -0
  58. package/lib/store.js +62 -0
  59. package/lib/store.js.map +1 -0
  60. package/lib/types.d.ts +181 -0
  61. package/lib/types.d.ts.map +1 -0
  62. package/lib/types.js +10 -0
  63. package/lib/types.js.map +1 -0
  64. package/lib-es/HWDeviceProvider.d.ts +25 -0
  65. package/lib-es/HWDeviceProvider.d.ts.map +1 -0
  66. package/lib-es/HWDeviceProvider.js +81 -0
  67. package/lib-es/HWDeviceProvider.js.map +1 -0
  68. package/lib-es/api.d.ts +77 -0
  69. package/lib-es/api.d.ts.map +1 -0
  70. package/lib-es/api.js +145 -0
  71. package/lib-es/api.js.map +1 -0
  72. package/lib-es/auth.d.ts +3 -0
  73. package/lib-es/auth.d.ts.map +1 -0
  74. package/lib-es/auth.js +75 -0
  75. package/lib-es/auth.js.map +1 -0
  76. package/lib-es/errors.d.ts +40 -0
  77. package/lib-es/errors.d.ts.map +1 -0
  78. package/lib-es/errors.js +15 -0
  79. package/lib-es/errors.js.map +1 -0
  80. package/lib-es/index.d.ts +6 -0
  81. package/lib-es/index.d.ts.map +1 -0
  82. package/lib-es/index.js +13 -0
  83. package/lib-es/index.js.map +1 -0
  84. package/lib-es/mockSdk.d.ts +22 -0
  85. package/lib-es/mockSdk.d.ts.map +1 -0
  86. package/lib-es/mockSdk.js +201 -0
  87. package/lib-es/mockSdk.js.map +1 -0
  88. package/lib-es/qrcode/cipher.d.ts +12 -0
  89. package/lib-es/qrcode/cipher.d.ts.map +1 -0
  90. package/lib-es/qrcode/cipher.js +61 -0
  91. package/lib-es/qrcode/cipher.js.map +1 -0
  92. package/lib-es/qrcode/cipher.test.d.ts +2 -0
  93. package/lib-es/qrcode/cipher.test.d.ts.map +1 -0
  94. package/lib-es/qrcode/cipher.test.js +38 -0
  95. package/lib-es/qrcode/cipher.test.js.map +1 -0
  96. package/lib-es/qrcode/index.d.ts +70 -0
  97. package/lib-es/qrcode/index.d.ts.map +1 -0
  98. package/lib-es/qrcode/index.js +304 -0
  99. package/lib-es/qrcode/index.js.map +1 -0
  100. package/lib-es/qrcode/index.test.d.ts +2 -0
  101. package/lib-es/qrcode/index.test.d.ts.map +1 -0
  102. package/lib-es/qrcode/index.test.js +126 -0
  103. package/lib-es/qrcode/index.test.js.map +1 -0
  104. package/lib-es/qrcode/types.d.ts +69 -0
  105. package/lib-es/qrcode/types.d.ts.map +1 -0
  106. package/lib-es/qrcode/types.js +2 -0
  107. package/lib-es/qrcode/types.js.map +1 -0
  108. package/lib-es/sdk.d.ts +31 -0
  109. package/lib-es/sdk.d.ts.map +1 -0
  110. package/lib-es/sdk.js +371 -0
  111. package/lib-es/sdk.js.map +1 -0
  112. package/lib-es/store.d.ts +71 -0
  113. package/lib-es/store.d.ts.map +1 -0
  114. package/lib-es/store.js +51 -0
  115. package/lib-es/store.js.map +1 -0
  116. package/lib-es/types.d.ts +181 -0
  117. package/lib-es/types.d.ts.map +1 -0
  118. package/lib-es/types.js +7 -0
  119. package/lib-es/types.js.map +1 -0
  120. package/mocks/scenarios/addSameMemberMultipleTimes.json +426 -0
  121. package/mocks/scenarios/create2trustchainInARow.json +616 -0
  122. package/mocks/scenarios/getOrCreateTransactionCases.json +591 -0
  123. package/mocks/scenarios/member3implicitlyAdded.json +648 -0
  124. package/mocks/scenarios/membersManySelfAdd.json +1427 -0
  125. package/mocks/scenarios/randomMemberTryToDestroy.json +371 -0
  126. package/mocks/scenarios/removeMemberWithTheWrongSeed.json +510 -0
  127. package/mocks/scenarios/removedMemberEjectedOnDeletedTrustchain.json +481 -0
  128. package/mocks/scenarios/removedMemberEjectedOnGetMembers.json +648 -0
  129. package/mocks/scenarios/removedMemberEjectedOnRestore.json +648 -0
  130. package/mocks/scenarios/removingAMemberCreatesAnInteraction.json +593 -0
  131. package/mocks/scenarios/removingYourselfIsForbidden.json +397 -0
  132. package/mocks/scenarios/success.json +978 -0
  133. package/mocks/scenarios/tokenExpires.json +371 -0
  134. package/mocks/scenarios/twoAddMembersFollowedByDeviceAdd.json +705 -0
  135. package/mocks/scenarios/userRefusesAuth.json +40 -0
  136. package/mocks/scenarios/userRefusesRemoveMember.json +542 -0
  137. package/package.json +91 -0
  138. package/scripts/README.md +15 -0
  139. package/scripts/e2e.ts +57 -0
  140. package/src/HWDeviceProvider.ts +105 -0
  141. package/src/__tests__/integration/mock.sdk.test.ts +47 -0
  142. package/src/__tests__/integration/sdk.test.ts +20 -0
  143. package/src/__tests__/tsconfig.json +8 -0
  144. package/src/__tests__/unit/sdk.test.ts +236 -0
  145. package/src/api.ts +202 -0
  146. package/src/auth.ts +81 -0
  147. package/src/errors.ts +18 -0
  148. package/src/index.ts +20 -0
  149. package/src/mockSdk.ts +253 -0
  150. package/src/qrcode/cipher.test.ts +30 -0
  151. package/src/qrcode/cipher.ts +63 -0
  152. package/src/qrcode/index.test.ts +138 -0
  153. package/src/qrcode/index.ts +395 -0
  154. package/src/qrcode/types.ts +70 -0
  155. package/src/sdk.ts +542 -0
  156. package/src/store.ts +99 -0
  157. package/src/types.ts +242 -0
  158. package/tests/scenarios/_template.ts +18 -0
  159. package/tests/scenarios/addSameMemberMultipleTimes.ts +20 -0
  160. package/tests/scenarios/create2trustchainInARow.ts +14 -0
  161. package/tests/scenarios/getOrCreateTransactionCases.ts +74 -0
  162. package/tests/scenarios/member3implicitlyAdded.ts +51 -0
  163. package/tests/scenarios/membersManySelfAdd.ts +18 -0
  164. package/tests/scenarios/randomMemberTryToDestroy.ts +23 -0
  165. package/tests/scenarios/removeMemberWithTheWrongSeed.ts +28 -0
  166. package/tests/scenarios/removedMemberEjectedOnDeletedTrustchain.ts +31 -0
  167. package/tests/scenarios/removedMemberEjectedOnGetMembers.ts +29 -0
  168. package/tests/scenarios/removedMemberEjectedOnRestore.ts +31 -0
  169. package/tests/scenarios/removingAMemberCreatesAnInteraction.ts +42 -0
  170. package/tests/scenarios/removingYourselfIsForbidden.ts +11 -0
  171. package/tests/scenarios/success.ts +94 -0
  172. package/tests/scenarios/tokenExpires.ts +20 -0
  173. package/tests/scenarios/twoAddMembersFollowedByDeviceAdd.ts +49 -0
  174. package/tests/scenarios/userRefusesAuth.ts +28 -0
  175. package/tests/scenarios/userRefusesRemoveMember.ts +66 -0
  176. package/tests/test-helpers/recordTrustchainSdkTests.ts +178 -0
  177. package/tests/test-helpers/replayTrustchainSdkTests.ts +141 -0
  178. package/tests/test-helpers/types.ts +45 -0
  179. package/tests/tsconfig.json +8 -0
  180. package/tsconfig.json +15 -0
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const _1 = require(".");
16
+ const ws_1 = __importDefault(require("ws"));
17
+ const sdk_1 = require("../sdk");
18
+ const hw_ledger_key_ring_protocol_1 = require("@ledgerhq/hw-ledger-key-ring-protocol");
19
+ const errors_1 = require("../errors");
20
+ describe("Trustchain QR Code", () => {
21
+ let server;
22
+ let a;
23
+ let b;
24
+ beforeAll(() => {
25
+ server = new ws_1.default.Server({ port: 1234 });
26
+ server.on("connection", ws => {
27
+ if (!a) {
28
+ a = ws;
29
+ }
30
+ else if (!b) {
31
+ b = ws;
32
+ }
33
+ ws.on("message", message => {
34
+ if (ws === a && b) {
35
+ b.send(message);
36
+ }
37
+ else if (ws === b && a) {
38
+ a.send(message);
39
+ }
40
+ });
41
+ });
42
+ });
43
+ afterAll(() => {
44
+ server.close();
45
+ });
46
+ test("digits matching scenario", () => __awaiter(void 0, void 0, void 0, function* () {
47
+ const onDisplayDigits = jest.fn();
48
+ const trustchain = {
49
+ rootId: "test-root-id",
50
+ walletSyncEncryptionKey: "test-wallet-sync-encryption-key",
51
+ applicationPath: "m/0'/16'/0'",
52
+ };
53
+ const addMember = jest.fn(() => Promise.resolve(trustchain));
54
+ const memberCredentials = (0, sdk_1.convertKeyPairToLiveCredentials)(yield hw_ledger_key_ring_protocol_1.crypto.randomKeypair());
55
+ const memberName = "foo";
56
+ let scannedUrlResolve;
57
+ const scannedUrlPromise = new Promise(resolve => {
58
+ scannedUrlResolve = resolve;
59
+ });
60
+ const onDisplayQRCode = (url) => {
61
+ scannedUrlResolve(url);
62
+ };
63
+ const onRequestQRCodeInput = jest.fn((config, callback) => callback(onDisplayDigits.mock.calls[0][0]));
64
+ const hostP = (0, _1.createQRCodeHostInstance)({
65
+ trustchainApiBaseUrl: "ws://localhost:1234",
66
+ onDisplayQRCode,
67
+ onDisplayDigits,
68
+ addMember,
69
+ memberCredentials,
70
+ memberName,
71
+ initialTrustchainId: trustchain.rootId,
72
+ });
73
+ const scannedUrl = yield scannedUrlPromise;
74
+ const candidateP = (0, _1.createQRCodeCandidateInstance)({
75
+ memberCredentials,
76
+ memberName,
77
+ initialTrustchainId: undefined,
78
+ addMember,
79
+ scannedUrl,
80
+ onRequestQRCodeInput,
81
+ });
82
+ const [_, res] = yield Promise.all([hostP, candidateP]);
83
+ expect(onDisplayDigits).toHaveBeenCalledWith(expect.any(String));
84
+ expect(addMember).toHaveBeenCalled();
85
+ expect(onRequestQRCodeInput).toHaveBeenCalledWith({ digits: 3, connected: false }, expect.any(Function));
86
+ expect(res).toEqual(trustchain);
87
+ }));
88
+ test("invalid qr code scanned", () => __awaiter(void 0, void 0, void 0, function* () {
89
+ const trustchain = {
90
+ rootId: "test-root-id",
91
+ walletSyncEncryptionKey: "test-wallet-sync-encryption-key",
92
+ applicationPath: "m/0'/16'/0'",
93
+ };
94
+ const addMember = jest.fn(() => Promise.resolve(trustchain));
95
+ const memberCredentials = (0, sdk_1.convertKeyPairToLiveCredentials)(yield hw_ledger_key_ring_protocol_1.crypto.randomKeypair());
96
+ const memberName = "foo";
97
+ const onRequestQRCodeInput = jest.fn();
98
+ const scannedUrl = "https://example.com";
99
+ const candidateP = (0, _1.createQRCodeCandidateInstance)({
100
+ memberCredentials,
101
+ memberName,
102
+ initialTrustchainId: undefined,
103
+ addMember,
104
+ scannedUrl,
105
+ onRequestQRCodeInput,
106
+ });
107
+ yield expect(candidateP).rejects.toThrow(new errors_1.ScannedInvalidQrCode());
108
+ }));
109
+ test("old accounts export qr code scanned", () => __awaiter(void 0, void 0, void 0, function* () {
110
+ const trustchain = {
111
+ rootId: "test-root-id",
112
+ walletSyncEncryptionKey: "test-wallet-sync-encryption-key",
113
+ applicationPath: "m/0'/16'/0'",
114
+ };
115
+ const addMember = jest.fn(() => Promise.resolve(trustchain));
116
+ const memberCredentials = (0, sdk_1.convertKeyPairToLiveCredentials)(yield hw_ledger_key_ring_protocol_1.crypto.randomKeypair());
117
+ const memberName = "foo";
118
+ const onRequestQRCodeInput = jest.fn();
119
+ const scannedUrl = "ZAADAAIAAAAEd2JXMpuoYdzvkNzFTlmQLPcGf2LSjDOgqaB3nQoZqlimcCX6HNkescWKyT1DCGuwO7IesD7oYg+fdZPkiIfFL3V9swfZRePkaNN09IjXsWLsim9hK/qi/RC1/ofX3hYNKUxUAgYVVG82WKXIk47siWfUlRZsCYSAARQ6ASpUgidPjMHaOMK6w53wTZplwo7Zjv1HrIyKwr3Ci8OmrFye5g==";
120
+ const candidateP = (0, _1.createQRCodeCandidateInstance)({
121
+ memberCredentials,
122
+ memberName,
123
+ initialTrustchainId: undefined,
124
+ addMember,
125
+ scannedUrl,
126
+ onRequestQRCodeInput,
127
+ });
128
+ yield expect(candidateP).rejects.toThrow(new errors_1.ScannedOldImportQrCode());
129
+ }));
130
+ });
131
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/qrcode/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { Trustchain } from "../types";
2
+ export type Encrypted<T> = {
3
+ encrypted: string;
4
+ };
5
+ export type Message = {
6
+ version: number;
7
+ publisher: string;
8
+ message: "InitiateHandshake";
9
+ payload: {
10
+ ephemeral_public_key: string;
11
+ };
12
+ } | {
13
+ version: number;
14
+ publisher: string;
15
+ message: "Failure";
16
+ payload: {
17
+ message: string;
18
+ type: string;
19
+ };
20
+ } | {
21
+ version: number;
22
+ publisher: string;
23
+ message: "HandshakeChallenge";
24
+ payload: Encrypted<{
25
+ digits: number;
26
+ connected: boolean;
27
+ }>;
28
+ } | {
29
+ version: number;
30
+ publisher: string;
31
+ message: "CompleteHandshakeChallenge";
32
+ payload: Encrypted<{
33
+ digits: string;
34
+ }>;
35
+ } | {
36
+ version: number;
37
+ publisher: string;
38
+ message: "HandshakeCompletionSucceeded";
39
+ payload: Encrypted<Record<string, never>>;
40
+ } | {
41
+ version: number;
42
+ publisher: string;
43
+ message: "TrustchainRequestCredential";
44
+ payload: Encrypted<Record<string, never>>;
45
+ } | {
46
+ version: number;
47
+ publisher: string;
48
+ message: "TrustchainShareCredential";
49
+ payload: Encrypted<{
50
+ id: string;
51
+ name: string;
52
+ }>;
53
+ } | {
54
+ version: number;
55
+ publisher: string;
56
+ message: "TrustchainAddedMember";
57
+ payload: Encrypted<{
58
+ trustchain: Trustchain;
59
+ }>;
60
+ };
61
+ export type DecryptedPayload<M> = M extends {
62
+ payload: Encrypted<infer T>;
63
+ } ? T : M extends {
64
+ payload: infer T;
65
+ } ? T : never;
66
+ export type ExtractEncryptedPayloads<T> = T extends {
67
+ payload: Encrypted<infer P>;
68
+ } ? P : never;
69
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/qrcode/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,OAAO,GACf;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,OAAO,EAAE;QAAE,oBAAoB,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,GACD;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,SAAS,CAAC;IACnB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C,GACD;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE,SAAS,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC5D,GACD;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,4BAA4B,CAAC;IACtC,OAAO,EAAE,SAAS,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxC,GACD;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,8BAA8B,CAAC;IACxC,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;CAC3C,GACD;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,6BAA6B,CAAC;IACvC,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;CAC3C,GACD;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,2BAA2B,CAAC;IACrC,OAAO,EAAE,SAAS,CAAC;QAEjB,EAAE,EAAE,MAAM,CAAC;QAEX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ,GACD;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,uBAAuB,CAAC;IACjC,OAAO,EAAE,SAAS,CAAC;QACjB,UAAU,EAAE,UAAU,CAAC;KACxB,CAAC,CAAC;CACJ,CAAC;AAEN,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GACvE,CAAC,GACD,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAC,CAAA;CAAE,GAC5B,CAAC,GACD,KAAK,CAAC;AAEZ,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/qrcode/types.ts"],"names":[],"mappings":""}
package/lib/sdk.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { JWT, MemberCredentials, TrustchainSDKContext, Trustchain, TrustchainMember, TrustchainSDK, TrustchainDeviceCallbacks, AuthCachePolicy, TrustchainResult, TrustchainLifecycle, GetOrCreateTrustchainCallbacks } from "./types";
2
+ import { KeyPair as CryptoKeyPair } from "@ledgerhq/hw-ledger-key-ring-protocol/Crypto";
3
+ import { HWDeviceProvider } from "./HWDeviceProvider";
4
+ export declare class SDK implements TrustchainSDK {
5
+ private context;
6
+ private hwDeviceProvider;
7
+ private lifecycle?;
8
+ private api;
9
+ constructor(context: TrustchainSDKContext, hwDeviceProvider: HWDeviceProvider, lifecyle?: TrustchainLifecycle);
10
+ private jwt;
11
+ private jwtHash;
12
+ withAuth<T>(trustchain: Trustchain, memberCredentials: MemberCredentials, job: (jwt: JWT) => Promise<T>, policy?: AuthCachePolicy, ignorePermissionsChecks?: boolean): Promise<T>;
13
+ initMemberCredentials(): Promise<MemberCredentials>;
14
+ getOrCreateTrustchain(deviceId: string, memberCredentials: MemberCredentials, callbacks?: GetOrCreateTrustchainCallbacks, topic?: Uint8Array, currentTrustchain?: Trustchain): Promise<TrustchainResult>;
15
+ restoreTrustchain(trustchain: Trustchain, memberCredentials: MemberCredentials): Promise<Trustchain>;
16
+ getMembers(trustchain: Trustchain, memberCredentials: MemberCredentials): Promise<TrustchainMember[]>;
17
+ removeMember(deviceId: string, trustchain: Trustchain, memberCredentials: MemberCredentials, member: TrustchainMember, callbacks?: TrustchainDeviceCallbacks): Promise<Trustchain>;
18
+ addMember(trustchain: Trustchain, memberCredentials: MemberCredentials, member: TrustchainMember): Promise<void>;
19
+ invalidateJwt(): void;
20
+ destroyTrustchain(trustchain: Trustchain, memberCredentials: MemberCredentials): Promise<void>;
21
+ encryptUserData(trustchain: Trustchain, input: Uint8Array): Promise<Uint8Array>;
22
+ decryptUserData(trustchain: Trustchain, data: Uint8Array): Promise<Uint8Array>;
23
+ private fetchTrustchain;
24
+ private fetchTrustchainAndResolve;
25
+ private auth;
26
+ private pushMember;
27
+ private closeStream;
28
+ }
29
+ export declare function convertKeyPairToLiveCredentials(keyPair: CryptoKeyPair): MemberCredentials;
30
+ export declare function convertLiveCredentialsToKeyPair(memberCredentials: MemberCredentials): CryptoKeyPair;
31
+ //# sourceMappingURL=sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,iBAAiB,EACjB,oBAAoB,EACpB,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAEhB,mBAAmB,EACnB,8BAA8B,EAC/B,MAAM,SAAS,CAAC;AAYjB,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,8CAA8C,CAAC;AAUxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMtD,qBAAa,GAAI,YAAW,aAAa;IACvC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,SAAS,CAAC,CAAsB;IACxC,OAAO,CAAC,GAAG,CAA4B;gBAGrC,OAAO,EAAE,oBAAoB,EAC7B,gBAAgB,EAAE,gBAAgB,EAClC,QAAQ,CAAC,EAAE,mBAAmB;IAQhC,OAAO,CAAC,GAAG,CAA8B;IACzC,OAAO,CAAC,OAAO,CAAM;IACrB,QAAQ,CAAC,CAAC,EACR,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,iBAAiB,EACpC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,EAC7B,MAAM,CAAC,EAAE,eAAe,EACxB,uBAAuB,CAAC,EAAE,OAAO,GAChC,OAAO,CAAC,CAAC,CAAC;IA8BP,qBAAqB,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAKnD,qBAAqB,CACzB,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,iBAAiB,EACpC,SAAS,CAAC,EAAE,8BAA8B,EAC1C,KAAK,CAAC,EAAE,UAAU,EAClB,iBAAiB,CAAC,EAAE,UAAU,GAC7B,OAAO,CAAC,gBAAgB,CAAC;IAsFtB,iBAAiB,CACrB,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,iBAAiB,GACnC,OAAO,CAAC,UAAU,CAAC;IAqBhB,UAAU,CACd,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,iBAAiB,GACnC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAWxB,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,iBAAiB,EACpC,MAAM,EAAE,gBAAgB,EACxB,SAAS,CAAC,EAAE,yBAAyB,GACpC,OAAO,CAAC,UAAU,CAAC;IAqFhB,SAAS,CACb,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,iBAAiB,EACpC,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC;IAiBhB,aAAa;IAKP,iBAAiB,CACrB,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,iBAAiB,GACnC,OAAO,CAAC,IAAI,CAAC;IAOV,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAM/E,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;YAMtE,eAAe;YAMf,yBAAyB;YASzB,IAAI;YA4BJ,UAAU;YAoCV,WAAW;CAkB1B;AAED,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,aAAa,GAAG,iBAAiB,CAKzF;AAED,wBAAgB,+BAA+B,CAC7C,iBAAiB,EAAE,iBAAiB,GACnC,aAAa,CAKf"}
package/lib/sdk.js ADDED
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.convertLiveCredentialsToKeyPair = exports.convertKeyPairToLiveCredentials = exports.SDK = void 0;
16
+ const types_1 = require("./types");
17
+ const hw_ledger_key_ring_protocol_1 = require("@ledgerhq/hw-ledger-key-ring-protocol");
18
+ const api_1 = __importDefault(require("./api"));
19
+ const logs_1 = require("@ledgerhq/logs");
20
+ const errors_1 = require("@ledgerhq/errors");
21
+ const errors_2 = require("./errors");
22
+ const auth_1 = require("./auth");
23
+ class SDK {
24
+ constructor(context, hwDeviceProvider, lifecyle) {
25
+ this.jwt = undefined;
26
+ this.jwtHash = "";
27
+ this.context = context;
28
+ this.hwDeviceProvider = hwDeviceProvider;
29
+ this.lifecycle = lifecyle;
30
+ this.api = (0, api_1.default)(context.apiBaseUrl);
31
+ }
32
+ withAuth(trustchain, memberCredentials, job, policy, ignorePermissionsChecks) {
33
+ const hash = trustchain.rootId + " " + memberCredentials.pubkey;
34
+ if (this.jwtHash !== hash) {
35
+ this.jwt = undefined;
36
+ this.jwtHash = hash;
37
+ }
38
+ return (0, auth_1.genericWithJWT)(jwt => {
39
+ this.jwt = jwt;
40
+ if (!ignorePermissionsChecks) {
41
+ const permissions = jwt.permissions[trustchain.rootId];
42
+ if (!permissions) {
43
+ throw new errors_2.TrustchainNotAllowed("permissions not available for current trustchain");
44
+ }
45
+ // check if the application path is allowed
46
+ if (!permissions[trustchain.applicationPath]) {
47
+ throw new errors_2.TrustchainOutdated(`expected ${trustchain.applicationPath}, got: ${Object.keys(permissions)[0]}`);
48
+ }
49
+ }
50
+ return job(jwt);
51
+ }, this.jwt, () => this.auth(trustchain, memberCredentials), jwt => this.api.refreshAuth(jwt), policy);
52
+ }
53
+ initMemberCredentials() {
54
+ return __awaiter(this, void 0, void 0, function* () {
55
+ const kp = yield hw_ledger_key_ring_protocol_1.crypto.randomKeypair();
56
+ return convertKeyPairToLiveCredentials(kp);
57
+ });
58
+ }
59
+ getOrCreateTrustchain(deviceId, memberCredentials, callbacks, topic, currentTrustchain) {
60
+ return __awaiter(this, void 0, void 0, function* () {
61
+ var _a;
62
+ this.invalidateJwt();
63
+ let type = types_1.TrustchainResultType.restored;
64
+ const withJwt = job => this.hwDeviceProvider.withJwt(deviceId, job, "cache", callbacks);
65
+ const withHw = job => this.hwDeviceProvider.withHw(deviceId, job, callbacks);
66
+ let trustchains = yield withJwt(this.api.getTrustchains);
67
+ (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.onInitialResponse) === null || _a === void 0 ? void 0 : _a.call(callbacks, trustchains);
68
+ if (currentTrustchain) {
69
+ yield this.restoreTrustchain(currentTrustchain, memberCredentials).then(() => {
70
+ throw Object.keys(trustchains).includes(currentTrustchain.rootId)
71
+ ? new errors_2.TrustchainAlreadyInitialized()
72
+ : new errors_2.TrustchainAlreadyInitializedWithOtherSeed();
73
+ }, () => {
74
+ // The user was ejected from the trustchain therefore we can continue
75
+ });
76
+ }
77
+ if (Object.keys(trustchains).length === 0) {
78
+ (0, logs_1.log)("trustchain", "getOrCreateTrustchain: no trustchain yet, let's create one");
79
+ type = types_1.TrustchainResultType.created;
80
+ const streamTree = yield this.hwDeviceProvider.withHw(deviceId, hw => hw_ledger_key_ring_protocol_1.StreamTree.createNewTree(hw, { topic }));
81
+ yield streamTree.getRoot().resolve(); // double checks the signatures are correct before sending to the backend
82
+ const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode(streamTree.getRoot().blocks);
83
+ yield withJwt(jwt => this.api.postSeed(jwt, hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)));
84
+ // deviceJwt have changed, proactively refresh it
85
+ yield this.hwDeviceProvider.refreshJwt(deviceId, callbacks);
86
+ trustchains = yield withJwt(this.api.getTrustchains);
87
+ }
88
+ // we find our trustchain root id
89
+ let trustchainRootId;
90
+ const trustchainRootPath = "m/";
91
+ for (const [trustchainId, info] of Object.entries(trustchains)) {
92
+ for (const path in info) {
93
+ if (path === trustchainRootPath) {
94
+ trustchainRootId = trustchainId;
95
+ }
96
+ }
97
+ }
98
+ invariant(trustchainRootId, "trustchainRootId should be defined");
99
+ (0, logs_1.log)("trustchain", "getOrCreateTrustchain rootId=" + trustchainRootId);
100
+ // make a stream tree from all the trustchains associated to this root id
101
+ let { streamTree } = yield withJwt(jwt => this.fetchTrustchain(jwt, trustchainRootId));
102
+ const path = streamTree.getApplicationRootPath(this.context.applicationId);
103
+ const child = streamTree.getChild(path);
104
+ let shouldShare = true;
105
+ if (child) {
106
+ const resolved = yield child.resolve();
107
+ const members = resolved.getMembers();
108
+ shouldShare = !members.some(m => hw_ledger_key_ring_protocol_1.crypto.to_hex(m) === memberCredentials.pubkey); // not already a member
109
+ }
110
+ if (shouldShare) {
111
+ if (type === types_1.TrustchainResultType.restored)
112
+ type = types_1.TrustchainResultType.updated;
113
+ streamTree = yield this.pushMember(streamTree, path, trustchainRootId, withJwt, withHw, {
114
+ id: memberCredentials.pubkey,
115
+ name: this.context.name,
116
+ permissions: hw_ledger_key_ring_protocol_1.Permissions.OWNER,
117
+ });
118
+ }
119
+ const walletSyncEncryptionKey = yield extractEncryptionKey(streamTree, path, memberCredentials);
120
+ const trustchain = {
121
+ rootId: trustchainRootId,
122
+ walletSyncEncryptionKey,
123
+ applicationPath: path,
124
+ };
125
+ return { type, trustchain };
126
+ });
127
+ }
128
+ restoreTrustchain(trustchain, memberCredentials) {
129
+ return __awaiter(this, void 0, void 0, function* () {
130
+ const { streamTree, applicationRootPath } = yield this.withAuth(trustchain, memberCredentials, jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId), "refresh", true);
131
+ const walletSyncEncryptionKey = yield extractEncryptionKey(streamTree, applicationRootPath, memberCredentials);
132
+ return {
133
+ rootId: trustchain.rootId,
134
+ walletSyncEncryptionKey,
135
+ applicationPath: applicationRootPath,
136
+ };
137
+ });
138
+ }
139
+ getMembers(trustchain, memberCredentials) {
140
+ return __awaiter(this, void 0, void 0, function* () {
141
+ const { resolved } = yield this.withAuth(trustchain, memberCredentials, jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId));
142
+ const members = resolved.getMembersData();
143
+ if (!members.some(m => m.id === memberCredentials.pubkey)) {
144
+ throw new errors_2.TrustchainEjected("Not a member of trustchain");
145
+ }
146
+ return members;
147
+ });
148
+ }
149
+ removeMember(deviceId, trustchain, memberCredentials, member, callbacks) {
150
+ return __awaiter(this, void 0, void 0, function* () {
151
+ var _a;
152
+ this.invalidateJwt();
153
+ const withJwt = job => this.hwDeviceProvider.withJwt(deviceId, job, "cache", callbacks);
154
+ const withHw = job => this.hwDeviceProvider.withHw(deviceId, job, callbacks);
155
+ // invariant because the sdk does not support this case, and the UI should not allows it.
156
+ invariant(memberCredentials.pubkey !== member.id, "removeMember must not be used to remove the current member.");
157
+ const afterRotation = yield ((_a = this.lifecycle) === null || _a === void 0 ? void 0 : _a.onTrustchainRotation(this, trustchain, memberCredentials));
158
+ const applicationId = this.context.applicationId;
159
+ const trustchainId = trustchain.rootId;
160
+ // eslint-disable-next-line prefer-const
161
+ let { resolved, streamTree, applicationRootPath } = yield withJwt(jwt => this.fetchTrustchainAndResolve(jwt, trustchainId, applicationId));
162
+ const members = resolved.getMembersData();
163
+ const withoutMember = members.filter(m => m.id !== member.id);
164
+ invariant(withoutMember.length < members.length, "member not found"); // invariant because the UI should not allow this case.
165
+ const withoutMemberOrMe = withoutMember.filter(m => m.id !== memberCredentials.pubkey);
166
+ const softwareDevice = getSoftwareDevice(memberCredentials);
167
+ const newPath = streamTree.getApplicationRootPath(applicationId, 1);
168
+ // We close the current trustchain with the hardware wallet in order to get a user confirmation of the action
169
+ const sendCloseStreamToAPI = yield this.closeStream(streamTree, applicationRootPath, trustchainId, withJwt, withHw);
170
+ // derive a new branch of the tree on the new path
171
+ streamTree = yield this.pushMember(streamTree, newPath, trustchainId, withJwt, withHw, {
172
+ id: memberCredentials.pubkey,
173
+ name: this.context.name,
174
+ permissions: hw_ledger_key_ring_protocol_1.Permissions.OWNER,
175
+ });
176
+ // add the remaining members
177
+ const withSw = (job) => job(softwareDevice);
178
+ for (const m of withoutMemberOrMe) {
179
+ streamTree = yield this.pushMember(streamTree, newPath, trustchainId, withJwt, withSw, m);
180
+ }
181
+ const walletSyncEncryptionKey = yield extractEncryptionKey(streamTree, newPath, memberCredentials);
182
+ // we send the close stream to the API only after the new stream is created in case user cancelled the process in the middle.
183
+ yield sendCloseStreamToAPI();
184
+ // deviceJwt have changed, proactively refresh it
185
+ yield this.hwDeviceProvider.refreshJwt(deviceId, callbacks);
186
+ const newTrustchain = {
187
+ rootId: trustchainId,
188
+ walletSyncEncryptionKey,
189
+ applicationPath: newPath,
190
+ };
191
+ if (afterRotation)
192
+ yield afterRotation(newTrustchain);
193
+ // refresh the jwt with the new trustchain
194
+ this.jwt = yield this.withAuth(newTrustchain, memberCredentials, jwt => Promise.resolve(jwt), "refresh");
195
+ return newTrustchain;
196
+ });
197
+ }
198
+ addMember(trustchain, memberCredentials, member) {
199
+ return __awaiter(this, void 0, void 0, function* () {
200
+ const withJwt = f => this.withAuth(trustchain, memberCredentials, f);
201
+ const { streamTree, applicationRootPath } = yield withJwt(jwt => this.fetchTrustchainAndResolve(jwt, trustchain.rootId, this.context.applicationId));
202
+ const softwareDevice = getSoftwareDevice(memberCredentials);
203
+ const withSw = (job) => job(softwareDevice);
204
+ yield this.pushMember(streamTree, applicationRootPath, trustchain.rootId, withJwt, withSw, member);
205
+ });
206
+ }
207
+ invalidateJwt() {
208
+ this.jwt = undefined;
209
+ this.hwDeviceProvider.clearJwt();
210
+ }
211
+ destroyTrustchain(trustchain, memberCredentials) {
212
+ return __awaiter(this, void 0, void 0, function* () {
213
+ yield this.withAuth(trustchain, memberCredentials, jwt => this.api.deleteTrustchain(jwt, trustchain.rootId));
214
+ this.invalidateJwt();
215
+ });
216
+ }
217
+ encryptUserData(trustchain, input) {
218
+ return __awaiter(this, void 0, void 0, function* () {
219
+ const key = hw_ledger_key_ring_protocol_1.crypto.from_hex(trustchain.walletSyncEncryptionKey);
220
+ const encrypted = yield hw_ledger_key_ring_protocol_1.crypto.encryptUserData(key, input);
221
+ return encrypted;
222
+ });
223
+ }
224
+ decryptUserData(trustchain, data) {
225
+ return __awaiter(this, void 0, void 0, function* () {
226
+ const key = hw_ledger_key_ring_protocol_1.crypto.from_hex(trustchain.walletSyncEncryptionKey);
227
+ const decrypted = yield hw_ledger_key_ring_protocol_1.crypto.decryptUserData(key, data);
228
+ return decrypted;
229
+ });
230
+ }
231
+ fetchTrustchain(jwt, trustchainId) {
232
+ return __awaiter(this, void 0, void 0, function* () {
233
+ const trustchainData = yield this.api.getTrustchain(jwt, trustchainId);
234
+ const streamTree = hw_ledger_key_ring_protocol_1.StreamTree.deserialize(trustchainData);
235
+ return { streamTree };
236
+ });
237
+ }
238
+ fetchTrustchainAndResolve(jwt, trustchainId, applicationId) {
239
+ return __awaiter(this, void 0, void 0, function* () {
240
+ const { streamTree } = yield this.fetchTrustchain(jwt, trustchainId);
241
+ const applicationRootPath = streamTree.getApplicationRootPath(applicationId);
242
+ const applicationNode = streamTree.getChild(applicationRootPath);
243
+ invariant(applicationNode, "could not find the application stream.");
244
+ const resolved = yield applicationNode.resolve();
245
+ return { resolved, streamTree, applicationRootPath, applicationNode };
246
+ });
247
+ }
248
+ auth(trustchain, memberCredentials) {
249
+ return __awaiter(this, void 0, void 0, function* () {
250
+ const challenge = yield this.api.getAuthenticationChallenge();
251
+ const data = hw_ledger_key_ring_protocol_1.crypto.from_hex(challenge.tlv);
252
+ const [parsed, _] = hw_ledger_key_ring_protocol_1.Challenge.fromBytes(data);
253
+ const hash = yield hw_ledger_key_ring_protocol_1.crypto.hash(parsed.getUnsignedTLV());
254
+ const keypair = convertLiveCredentialsToKeyPair(memberCredentials);
255
+ const response = yield this.api
256
+ .postChallengeResponse({
257
+ challenge: challenge.json,
258
+ signature: {
259
+ credential: credentialForPubKey(memberCredentials.pubkey),
260
+ signature: hw_ledger_key_ring_protocol_1.crypto.to_hex(yield hw_ledger_key_ring_protocol_1.crypto.sign(hash, keypair)),
261
+ attestation: hw_ledger_key_ring_protocol_1.crypto.to_hex(liveAuthentication(trustchain.rootId)),
262
+ },
263
+ })
264
+ .catch(e => {
265
+ if (e instanceof errors_1.LedgerAPI4xx &&
266
+ (e.message.includes("Not a member of trustchain") ||
267
+ e.message.includes("You are not member"))) {
268
+ throw new errors_2.TrustchainEjected(e.message);
269
+ }
270
+ throw e;
271
+ });
272
+ return response;
273
+ });
274
+ }
275
+ pushMember(streamTree, path, trustchainId, withJwt, withDevice, member) {
276
+ return __awaiter(this, void 0, void 0, function* () {
277
+ const isMemberAlreadyInStreamTree = yield isMemberInStreamTree(streamTree, path, member);
278
+ if (isMemberAlreadyInStreamTree) {
279
+ return streamTree;
280
+ }
281
+ const isNewDerivation = !streamTree.getChild(path);
282
+ streamTree = yield withDevice(device => streamTree.share(path, device, hw_ledger_key_ring_protocol_1.crypto.from_hex(member.id), member.name, member.permissions));
283
+ const child = streamTree.getChild(path);
284
+ invariant(child, "StreamTree.share failed to create the child stream.");
285
+ yield child.resolve(); // double checks the signatures are correct before sending to the backend
286
+ if (isNewDerivation) {
287
+ const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode(child.blocks);
288
+ yield withJwt(jwt => this.api.postDerivation(jwt, trustchainId, hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)));
289
+ }
290
+ else {
291
+ const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode([child.blocks[child.blocks.length - 1]]);
292
+ const request = {
293
+ path,
294
+ blocks: [hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)],
295
+ };
296
+ yield withJwt(jwt => this.api.putCommands(jwt, trustchainId, request));
297
+ }
298
+ return streamTree;
299
+ });
300
+ }
301
+ closeStream(streamTree, path, trustchainId, withJwt, withDevice) {
302
+ return __awaiter(this, void 0, void 0, function* () {
303
+ streamTree = yield withDevice(device => streamTree.close(path, device));
304
+ const child = streamTree.getChild(path);
305
+ invariant(child, "StreamTree.close failed to create the child stream.");
306
+ yield child.resolve(); // double checks the signatures are correct before sending to the backend
307
+ const commandStream = hw_ledger_key_ring_protocol_1.CommandStreamEncoder.encode([child.blocks[child.blocks.length - 1]]);
308
+ const request = {
309
+ path,
310
+ blocks: [hw_ledger_key_ring_protocol_1.crypto.to_hex(commandStream)],
311
+ };
312
+ return () => withJwt(jwt => this.api.putCommands(jwt, trustchainId, request));
313
+ });
314
+ }
315
+ }
316
+ exports.SDK = SDK;
317
+ function convertKeyPairToLiveCredentials(keyPair) {
318
+ return {
319
+ pubkey: hw_ledger_key_ring_protocol_1.crypto.to_hex(keyPair.publicKey),
320
+ privatekey: hw_ledger_key_ring_protocol_1.crypto.to_hex(keyPair.privateKey),
321
+ };
322
+ }
323
+ exports.convertKeyPairToLiveCredentials = convertKeyPairToLiveCredentials;
324
+ function convertLiveCredentialsToKeyPair(memberCredentials) {
325
+ return {
326
+ publicKey: hw_ledger_key_ring_protocol_1.crypto.from_hex(memberCredentials.pubkey),
327
+ privateKey: hw_ledger_key_ring_protocol_1.crypto.from_hex(memberCredentials.privatekey),
328
+ };
329
+ }
330
+ exports.convertLiveCredentialsToKeyPair = convertLiveCredentialsToKeyPair;
331
+ function getSoftwareDevice(memberCredentials) {
332
+ const kp = convertLiveCredentialsToKeyPair(memberCredentials);
333
+ return new hw_ledger_key_ring_protocol_1.SoftwareDevice(kp);
334
+ }
335
+ function extractEncryptionKey(streamTree, path, memberCredentials) {
336
+ return __awaiter(this, void 0, void 0, function* () {
337
+ const softwareDevice = getSoftwareDevice(memberCredentials);
338
+ const pathNumbers = hw_ledger_key_ring_protocol_1.DerivationPath.toIndexArray(path);
339
+ try {
340
+ const key = yield softwareDevice.readKey(streamTree, pathNumbers);
341
+ // private key is in the first 32 bytes
342
+ return hw_ledger_key_ring_protocol_1.crypto.to_hex(key.slice(0, 32));
343
+ }
344
+ catch (e) {
345
+ if (e instanceof Error) {
346
+ throw new errors_2.TrustchainEjected(e.message);
347
+ }
348
+ throw e;
349
+ }
350
+ });
351
+ }
352
+ // spec https://ledgerhq.atlassian.net/wiki/spaces/TA/pages/4335960138/ARCH+LedgerLive+Auth+specifications
353
+ function liveAuthentication(rootId) {
354
+ const trustchainId = new TextEncoder().encode(rootId);
355
+ const att = new Uint8Array(2 + trustchainId.length);
356
+ att[0] = 0x02; // Prefix tag
357
+ att[1] = trustchainId.length;
358
+ att.set(trustchainId, 2);
359
+ return att;
360
+ }
361
+ function credentialForPubKey(publicKey) {
362
+ return { version: 0, curveId: 33, signAlgorithm: 1, publicKey };
363
+ }
364
+ function invariant(condition, message) {
365
+ if (!condition) {
366
+ throw new Error(message);
367
+ }
368
+ }
369
+ function isMemberInStreamTree(streamTree, path, member) {
370
+ return __awaiter(this, void 0, void 0, function* () {
371
+ const child = streamTree.getChild(path);
372
+ if (!child) {
373
+ return false;
374
+ }
375
+ const resolved = yield child.resolve();
376
+ const members = resolved.getMembersData();
377
+ return members.some(m => m.id === member.id);
378
+ });
379
+ }
380
+ //# sourceMappingURL=sdk.js.map