@ledgerhq/coin-canton 0.5.0-nightly.1 → 0.5.0-nightly.3

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 (199) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.unimportedrc.json +12 -4
  3. package/CHANGELOG.md +32 -0
  4. package/lib/api/getBalance.integ.test.js +1 -1
  5. package/lib/api/getBalance.integ.test.js.map +1 -1
  6. package/lib/api/index.d.ts.map +1 -1
  7. package/lib/api/index.js +11 -8
  8. package/lib/api/index.js.map +1 -1
  9. package/lib/bridge/broadcast.d.ts.map +1 -1
  10. package/lib/bridge/broadcast.js +2 -1
  11. package/lib/bridge/broadcast.js.map +1 -1
  12. package/lib/bridge/createTransaction.test.js +1 -1
  13. package/lib/bridge/createTransaction.test.js.map +1 -1
  14. package/lib/bridge/index.d.ts +3 -3
  15. package/lib/bridge/index.d.ts.map +1 -1
  16. package/lib/bridge/index.js +9 -1
  17. package/lib/bridge/index.js.map +1 -1
  18. package/lib/bridge/onboard.d.ts +10 -0
  19. package/lib/bridge/onboard.d.ts.map +1 -0
  20. package/lib/bridge/onboard.integ.test.d.ts +2 -0
  21. package/lib/bridge/onboard.integ.test.d.ts.map +1 -0
  22. package/lib/bridge/onboard.integ.test.js +156 -0
  23. package/lib/bridge/onboard.integ.test.js.map +1 -0
  24. package/lib/bridge/onboard.js +139 -0
  25. package/lib/bridge/onboard.js.map +1 -0
  26. package/lib/bridge/prepareTransaction.d.ts.map +1 -1
  27. package/lib/bridge/prepareTransaction.js +5 -7
  28. package/lib/bridge/prepareTransaction.js.map +1 -1
  29. package/lib/bridge/signOperation.d.ts.map +1 -1
  30. package/lib/bridge/signOperation.js +7 -9
  31. package/lib/bridge/signOperation.js.map +1 -1
  32. package/lib/bridge/sync.d.ts.map +1 -1
  33. package/lib/bridge/sync.integ.test.d.ts +2 -0
  34. package/lib/bridge/sync.integ.test.d.ts.map +1 -0
  35. package/lib/bridge/sync.integ.test.js +175 -0
  36. package/lib/bridge/sync.integ.test.js.map +1 -0
  37. package/lib/bridge/sync.js +40 -36
  38. package/lib/bridge/sync.js.map +1 -1
  39. package/lib/bridge/updateTransaction.d.ts.map +1 -1
  40. package/lib/bridge/updateTransaction.js +0 -4
  41. package/lib/bridge/updateTransaction.js.map +1 -1
  42. package/lib/common-logic/history/listOperations.d.ts.map +1 -1
  43. package/lib/common-logic/history/listOperations.js +19 -31
  44. package/lib/common-logic/history/listOperations.js.map +1 -1
  45. package/lib/common-logic/transaction/broadcast.d.ts.map +1 -1
  46. package/lib/common-logic/transaction/broadcast.js +2 -1
  47. package/lib/common-logic/transaction/broadcast.js.map +1 -1
  48. package/lib/common-logic/transaction/broadcast.test.js +3 -3
  49. package/lib/common-logic/transaction/broadcast.test.js.map +1 -1
  50. package/lib/common-logic/transaction/combine.d.ts +1 -1
  51. package/lib/common-logic/transaction/combine.d.ts.map +1 -1
  52. package/lib/common-logic/transaction/combine.js +2 -3
  53. package/lib/common-logic/transaction/combine.js.map +1 -1
  54. package/lib/common-logic/transaction/combine.test.js +3 -13
  55. package/lib/common-logic/transaction/combine.test.js.map +1 -1
  56. package/lib/common-logic/transaction/craftTransaction.d.ts +5 -3
  57. package/lib/common-logic/transaction/craftTransaction.d.ts.map +1 -1
  58. package/lib/common-logic/transaction/craftTransaction.js +11 -12
  59. package/lib/common-logic/transaction/craftTransaction.js.map +1 -1
  60. package/lib/network/gateway.d.ts +196 -5
  61. package/lib/network/gateway.d.ts.map +1 -1
  62. package/lib/network/gateway.integ.test.js +121 -11
  63. package/lib/network/gateway.integ.test.js.map +1 -1
  64. package/lib/network/gateway.js +99 -21
  65. package/lib/network/gateway.js.map +1 -1
  66. package/lib/network/node.d.ts +2 -2
  67. package/lib/network/node.d.ts.map +1 -1
  68. package/lib/network/node.js.map +1 -1
  69. package/lib/network/types.d.ts +1 -1
  70. package/lib/network/types.d.ts.map +1 -1
  71. package/lib/signer/getAddress.d.ts.map +1 -1
  72. package/lib/signer/getAddress.js +2 -2
  73. package/lib/signer/getAddress.js.map +1 -1
  74. package/lib/test/cantonTestUtils.d.ts +33 -0
  75. package/lib/test/cantonTestUtils.d.ts.map +1 -0
  76. package/lib/test/cantonTestUtils.js +159 -0
  77. package/lib/test/cantonTestUtils.js.map +1 -0
  78. package/lib/types/bridge.d.ts +7 -1
  79. package/lib/types/bridge.d.ts.map +1 -1
  80. package/lib/types/index.d.ts +1 -10
  81. package/lib/types/index.d.ts.map +1 -1
  82. package/lib/types/index.js +1 -0
  83. package/lib/types/index.js.map +1 -1
  84. package/lib/types/onboard.d.ts +55 -0
  85. package/lib/types/onboard.d.ts.map +1 -0
  86. package/lib/types/onboard.js +22 -0
  87. package/lib/types/onboard.js.map +1 -0
  88. package/lib-es/api/getBalance.integ.test.js +1 -1
  89. package/lib-es/api/getBalance.integ.test.js.map +1 -1
  90. package/lib-es/api/index.d.ts.map +1 -1
  91. package/lib-es/api/index.js +12 -9
  92. package/lib-es/api/index.js.map +1 -1
  93. package/lib-es/bridge/broadcast.d.ts.map +1 -1
  94. package/lib-es/bridge/broadcast.js +2 -1
  95. package/lib-es/bridge/broadcast.js.map +1 -1
  96. package/lib-es/bridge/createTransaction.test.js +1 -1
  97. package/lib-es/bridge/createTransaction.test.js.map +1 -1
  98. package/lib-es/bridge/index.d.ts +3 -3
  99. package/lib-es/bridge/index.d.ts.map +1 -1
  100. package/lib-es/bridge/index.js +9 -1
  101. package/lib-es/bridge/index.js.map +1 -1
  102. package/lib-es/bridge/onboard.d.ts +10 -0
  103. package/lib-es/bridge/onboard.d.ts.map +1 -0
  104. package/lib-es/bridge/onboard.integ.test.d.ts +2 -0
  105. package/lib-es/bridge/onboard.integ.test.d.ts.map +1 -0
  106. package/lib-es/bridge/onboard.integ.test.js +151 -0
  107. package/lib-es/bridge/onboard.integ.test.js.map +1 -0
  108. package/lib-es/bridge/onboard.js +133 -0
  109. package/lib-es/bridge/onboard.js.map +1 -0
  110. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
  111. package/lib-es/bridge/prepareTransaction.js +6 -8
  112. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  113. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  114. package/lib-es/bridge/signOperation.js +8 -10
  115. package/lib-es/bridge/signOperation.js.map +1 -1
  116. package/lib-es/bridge/sync.d.ts.map +1 -1
  117. package/lib-es/bridge/sync.integ.test.d.ts +2 -0
  118. package/lib-es/bridge/sync.integ.test.d.ts.map +1 -0
  119. package/lib-es/bridge/sync.integ.test.js +137 -0
  120. package/lib-es/bridge/sync.integ.test.js.map +1 -0
  121. package/lib-es/bridge/sync.js +39 -35
  122. package/lib-es/bridge/sync.js.map +1 -1
  123. package/lib-es/bridge/updateTransaction.d.ts.map +1 -1
  124. package/lib-es/bridge/updateTransaction.js +0 -4
  125. package/lib-es/bridge/updateTransaction.js.map +1 -1
  126. package/lib-es/common-logic/history/listOperations.d.ts.map +1 -1
  127. package/lib-es/common-logic/history/listOperations.js +20 -29
  128. package/lib-es/common-logic/history/listOperations.js.map +1 -1
  129. package/lib-es/common-logic/transaction/broadcast.d.ts.map +1 -1
  130. package/lib-es/common-logic/transaction/broadcast.js +2 -1
  131. package/lib-es/common-logic/transaction/broadcast.js.map +1 -1
  132. package/lib-es/common-logic/transaction/broadcast.test.js +3 -3
  133. package/lib-es/common-logic/transaction/broadcast.test.js.map +1 -1
  134. package/lib-es/common-logic/transaction/combine.d.ts +1 -1
  135. package/lib-es/common-logic/transaction/combine.d.ts.map +1 -1
  136. package/lib-es/common-logic/transaction/combine.js +2 -3
  137. package/lib-es/common-logic/transaction/combine.js.map +1 -1
  138. package/lib-es/common-logic/transaction/combine.test.js +3 -13
  139. package/lib-es/common-logic/transaction/combine.test.js.map +1 -1
  140. package/lib-es/common-logic/transaction/craftTransaction.d.ts +5 -3
  141. package/lib-es/common-logic/transaction/craftTransaction.d.ts.map +1 -1
  142. package/lib-es/common-logic/transaction/craftTransaction.js +11 -12
  143. package/lib-es/common-logic/transaction/craftTransaction.js.map +1 -1
  144. package/lib-es/network/gateway.d.ts +196 -5
  145. package/lib-es/network/gateway.d.ts.map +1 -1
  146. package/lib-es/network/gateway.integ.test.js +122 -12
  147. package/lib-es/network/gateway.integ.test.js.map +1 -1
  148. package/lib-es/network/gateway.js +93 -20
  149. package/lib-es/network/gateway.js.map +1 -1
  150. package/lib-es/network/node.d.ts +2 -2
  151. package/lib-es/network/node.d.ts.map +1 -1
  152. package/lib-es/network/node.js.map +1 -1
  153. package/lib-es/network/types.d.ts +1 -1
  154. package/lib-es/network/types.d.ts.map +1 -1
  155. package/lib-es/signer/getAddress.d.ts.map +1 -1
  156. package/lib-es/signer/getAddress.js +2 -2
  157. package/lib-es/signer/getAddress.js.map +1 -1
  158. package/lib-es/test/cantonTestUtils.d.ts +33 -0
  159. package/lib-es/test/cantonTestUtils.d.ts.map +1 -0
  160. package/lib-es/test/cantonTestUtils.js +151 -0
  161. package/lib-es/test/cantonTestUtils.js.map +1 -0
  162. package/lib-es/types/bridge.d.ts +7 -1
  163. package/lib-es/types/bridge.d.ts.map +1 -1
  164. package/lib-es/types/index.d.ts +1 -10
  165. package/lib-es/types/index.d.ts.map +1 -1
  166. package/lib-es/types/index.js +1 -0
  167. package/lib-es/types/index.js.map +1 -1
  168. package/lib-es/types/onboard.d.ts +55 -0
  169. package/lib-es/types/onboard.d.ts.map +1 -0
  170. package/lib-es/types/onboard.js +19 -0
  171. package/lib-es/types/onboard.js.map +1 -0
  172. package/package.json +7 -7
  173. package/src/api/getBalance.integ.test.ts +1 -2
  174. package/src/api/index.ts +33 -26
  175. package/src/bridge/broadcast.ts +2 -3
  176. package/src/bridge/createTransaction.test.ts +1 -1
  177. package/src/bridge/index.ts +14 -4
  178. package/src/bridge/onboard.integ.test.ts +219 -0
  179. package/src/bridge/onboard.ts +220 -0
  180. package/src/bridge/prepareTransaction.ts +6 -15
  181. package/src/bridge/signOperation.ts +9 -16
  182. package/src/bridge/sync.integ.test.ts +180 -0
  183. package/src/bridge/sync.ts +61 -49
  184. package/src/bridge/updateTransaction.ts +0 -5
  185. package/src/common-logic/history/listOperations.ts +20 -31
  186. package/src/common-logic/transaction/broadcast.test.ts +3 -3
  187. package/src/common-logic/transaction/broadcast.ts +2 -1
  188. package/src/common-logic/transaction/combine.test.ts +3 -13
  189. package/src/common-logic/transaction/combine.ts +2 -4
  190. package/src/common-logic/transaction/craftTransaction.ts +15 -17
  191. package/src/network/gateway.integ.test.ts +156 -17
  192. package/src/network/gateway.ts +337 -30
  193. package/src/network/node.ts +3 -3
  194. package/src/network/types.ts +1 -1
  195. package/src/signer/getAddress.ts +3 -5
  196. package/src/test/cantonTestUtils.ts +181 -0
  197. package/src/types/bridge.ts +20 -0
  198. package/src/types/index.ts +1 -11
  199. package/src/types/onboard.ts +65 -0
@@ -0,0 +1,219 @@
1
+ import { firstValueFrom, toArray } from "rxjs";
2
+ import { generateMockKeyPair, createMockSigner } from "../test/cantonTestUtils";
3
+ import { buildOnboardAccount, isAccountOnboarded, buildAuthorizePreapproval } from "./onboard";
4
+ import {
5
+ OnboardStatus,
6
+ PreApprovalStatus,
7
+ CantonOnboardProgress,
8
+ CantonOnboardResult,
9
+ CantonPreApprovalProgress,
10
+ CantonPreApprovalResult,
11
+ } from "../types/onboard";
12
+ import coinConfig from "../config";
13
+
14
+ describe("onboard (devnet)", () => {
15
+ const mockDeviceId = "test-device-id";
16
+ const mockDerivationPath = "44'/6767'/0'/0'/0'";
17
+
18
+ let onboardedAccount: {
19
+ keyPair: ReturnType<typeof generateMockKeyPair>;
20
+ mockSigner: ReturnType<typeof createMockSigner>;
21
+ mockSignerContext: jest.Mock;
22
+ onboardResult: CantonOnboardResult;
23
+ } | null = null;
24
+
25
+ beforeAll(() => {
26
+ coinConfig.setCoinConfig(() => ({
27
+ gatewayUrl: "https://canton-gateway.api.live.ledger-test.com",
28
+ useGateway: true,
29
+ networkType: "devnet",
30
+ status: {
31
+ type: "active",
32
+ },
33
+ }));
34
+ });
35
+
36
+ const getOnboardedAccount = () => {
37
+ if (!onboardedAccount) {
38
+ throw new Error(
39
+ "onboardedAccount is null. Ensure isAccountOnboarded test runs first to set it.",
40
+ );
41
+ }
42
+ return onboardedAccount;
43
+ };
44
+
45
+ describe("isAccountOnboarded", () => {
46
+ it("should return true for onboarded account", async () => {
47
+ // GIVEN
48
+ const keyPair = generateMockKeyPair();
49
+ const mockSigner = createMockSigner(keyPair);
50
+ const mockSignerContext = jest.fn().mockImplementation((deviceId, callback) => {
51
+ return callback(mockSigner);
52
+ });
53
+
54
+ const onboardObservable = buildOnboardAccount(mockSignerContext);
55
+ const onboardValues = await firstValueFrom(
56
+ onboardObservable(mockDeviceId, mockDerivationPath).pipe(toArray()),
57
+ );
58
+ const onboardResult = onboardValues.find(
59
+ (value): value is CantonOnboardResult => "partyId" in value,
60
+ );
61
+
62
+ if (!onboardResult) {
63
+ throw new Error("Failed to onboard account for shared test data");
64
+ }
65
+
66
+ // Save onboarded account for all tests that need a valid party ID
67
+ onboardedAccount = {
68
+ keyPair,
69
+ mockSigner,
70
+ mockSignerContext,
71
+ onboardResult,
72
+ };
73
+
74
+ // WHEN
75
+ const result = await isAccountOnboarded(keyPair.publicKeyHex);
76
+
77
+ // THEN
78
+ expect(result).not.toBe(false);
79
+ if (typeof result === "object") {
80
+ expect(result.party_id).toBeDefined();
81
+ expect(result.party_id).toBe(onboardResult!.partyId);
82
+ }
83
+ }, 30000);
84
+
85
+ it("should return false for non-onboarded account with fresh keypair", async () => {
86
+ // GIVEN
87
+ const keyPair = generateMockKeyPair();
88
+
89
+ // WHEN
90
+ const result = await isAccountOnboarded(keyPair.publicKeyHex);
91
+
92
+ // THEN
93
+ expect(result).toBe(false);
94
+ }, 15000);
95
+
96
+ it("should handle errors gracefully when checking non-existent party", async () => {
97
+ // GIVEN
98
+ const keyPair = generateMockKeyPair();
99
+
100
+ // WHEN
101
+ const result = await isAccountOnboarded(keyPair.publicKeyHex);
102
+
103
+ // THEN
104
+ expect(result).toBe(false);
105
+ }, 15000);
106
+ });
107
+
108
+ describe("buildOnboardAccount", () => {
109
+ it("should complete full onboarding flow with fresh keypair", async () => {
110
+ // GIVEN
111
+ const keyPair = generateMockKeyPair();
112
+ const mockSigner = createMockSigner(keyPair);
113
+ const mockSignerContext = jest.fn().mockImplementation((deviceId, callback) => {
114
+ return callback(mockSigner);
115
+ });
116
+ const onboardObservable = buildOnboardAccount(mockSignerContext);
117
+
118
+ // WHEN
119
+ const allValues = await firstValueFrom(
120
+ onboardObservable(mockDeviceId, mockDerivationPath).pipe(toArray()),
121
+ );
122
+ const progressValues = allValues.filter(
123
+ (value): value is CantonOnboardProgress => "status" in value && !("partyId" in value),
124
+ );
125
+ const resultValues = allValues.filter(
126
+ (value): value is CantonOnboardResult => "partyId" in value,
127
+ );
128
+
129
+ // THEN
130
+ // Check expected status progression
131
+ expect(progressValues.some(p => p.status === OnboardStatus.INIT)).toBe(true);
132
+ expect(progressValues.some(p => p.status === OnboardStatus.PREPARE)).toBe(true);
133
+ expect(progressValues.some(p => p.status === OnboardStatus.SIGN)).toBe(true);
134
+ expect(progressValues.some(p => p.status === OnboardStatus.SUBMIT)).toBe(true);
135
+
136
+ // Check final result
137
+ expect(resultValues.length).toBeGreaterThan(0);
138
+ const finalResult = resultValues[resultValues.length - 1];
139
+ expect(finalResult.partyId).toBeDefined();
140
+ expect(typeof finalResult.partyId).toBe("string");
141
+
142
+ expect(mockSignerContext).toHaveBeenCalled();
143
+ }, 30000);
144
+
145
+ it("should complete full onboarding flow with already onboarded account", async () => {
146
+ // GIVEN
147
+ const { keyPair, mockSignerContext, onboardResult: firstResult } = getOnboardedAccount();
148
+ const secondOnboardObservable = buildOnboardAccount(mockSignerContext);
149
+
150
+ // WHEN
151
+ const secondOnboardValues = await firstValueFrom(
152
+ secondOnboardObservable(mockDeviceId, mockDerivationPath).pipe(toArray()),
153
+ );
154
+ const secondResult = secondOnboardValues.find(
155
+ (value): value is CantonOnboardResult => "partyId" in value,
156
+ );
157
+
158
+ // THEN
159
+ expect(secondResult).toBeDefined();
160
+ expect(secondResult!.partyId).toBe(firstResult.partyId);
161
+ expect(typeof secondResult!.partyId).toBe("string");
162
+ }, 30000);
163
+ });
164
+
165
+ describe("buildAuthorizePreapproval", () => {
166
+ it("should complete preapproval flow for onboarded account", async () => {
167
+ // GIVEN
168
+ const { mockSignerContext, onboardResult } = getOnboardedAccount();
169
+ const preapprovalObservable = buildAuthorizePreapproval(mockSignerContext);
170
+
171
+ // WHEN
172
+ const preapprovalValues = await firstValueFrom(
173
+ preapprovalObservable(mockDeviceId, mockDerivationPath, onboardResult.partyId).pipe(
174
+ toArray(),
175
+ ),
176
+ );
177
+
178
+ const progressValues = preapprovalValues.filter(
179
+ (value): value is CantonPreApprovalProgress =>
180
+ "status" in value && !("isApproved" in value),
181
+ );
182
+ const resultValues = preapprovalValues.filter(
183
+ (value): value is CantonPreApprovalResult => "isApproved" in value,
184
+ );
185
+
186
+ // THEN
187
+ // Check expected status progression
188
+ expect(progressValues.some(p => p.status === PreApprovalStatus.PREPARE)).toBe(true);
189
+ expect(progressValues.some(p => p.status === PreApprovalStatus.SIGN)).toBe(true);
190
+ expect(progressValues.some(p => p.status === PreApprovalStatus.SUBMIT)).toBe(true);
191
+
192
+ // Check final result (should be approved)
193
+ expect(resultValues.length).toBeGreaterThan(0);
194
+ const finalResult = resultValues[resultValues.length - 1];
195
+ expect(finalResult.isApproved).toBe(true);
196
+ expect(typeof finalResult.isApproved).toBe("boolean");
197
+ }, 30000);
198
+
199
+ it("should handle invalid party ID gracefully", async () => {
200
+ // GIVEN
201
+ const keyPair = generateMockKeyPair();
202
+ const mockSigner = createMockSigner(keyPair);
203
+ const mockSignerContext = jest.fn().mockImplementation((deviceId, callback) => {
204
+ return callback(mockSigner);
205
+ });
206
+ const preapprovalObservable = buildAuthorizePreapproval(mockSignerContext);
207
+
208
+ // WHEN & THEN
209
+ try {
210
+ await firstValueFrom(
211
+ preapprovalObservable(mockDeviceId, mockDerivationPath, "invalid-party-id-123"),
212
+ );
213
+ expect(true).toBe(true);
214
+ } catch (error) {
215
+ expect(error).toBeDefined();
216
+ }
217
+ }, 30000);
218
+ });
219
+ });
@@ -0,0 +1,220 @@
1
+ import { Observable } from "rxjs";
2
+ import { SignerContext } from "@ledgerhq/coin-framework/signer";
3
+ import { CantonSigner } from "../types/signer";
4
+ import {
5
+ prepareOnboarding,
6
+ submitOnboarding,
7
+ getPartyByPubKey,
8
+ preparePreApprovalTransaction,
9
+ submitPreApprovalTransaction,
10
+ prepareTapRequest,
11
+ submitTapRequest,
12
+ } from "../network/gateway";
13
+ import {
14
+ OnboardStatus,
15
+ PreApprovalStatus,
16
+ CantonOnboardProgress,
17
+ CantonOnboardResult,
18
+ CantonPreApprovalProgress,
19
+ CantonPreApprovalResult,
20
+ PrepareTransactionResponse,
21
+ } from "../types/onboard";
22
+
23
+ async function getKeypair(
24
+ signerContext: SignerContext<CantonSigner>,
25
+ deviceId: string,
26
+ derivationPath: string,
27
+ ) {
28
+ return signerContext(deviceId, async signer => {
29
+ const { publicKey, address } = await signer.getAddress(derivationPath);
30
+ return { signer, publicKey: publicKey.replace("0x", ""), address };
31
+ });
32
+ }
33
+
34
+ export const isAccountOnboarded = async (
35
+ publicKey: string,
36
+ ): Promise<false | { party_id: string }> => {
37
+ try {
38
+ const { party_id } = await getPartyByPubKey(publicKey);
39
+
40
+ if (party_id) {
41
+ return { party_id };
42
+ } else {
43
+ return false;
44
+ }
45
+ } catch (err) {
46
+ log("[isAccountOnboarded] Error checking party status (likely not onboarded):", err);
47
+ return false;
48
+ }
49
+ };
50
+
51
+ export const buildOnboardAccount =
52
+ (signerContext: SignerContext<CantonSigner>) =>
53
+ (
54
+ deviceId: string,
55
+ derivationPath: string,
56
+ ): Observable<CantonOnboardProgress | CantonOnboardResult> =>
57
+ new Observable(observer => {
58
+ async function main() {
59
+ observer.next({
60
+ status: OnboardStatus.INIT,
61
+ });
62
+ const keypair = await getKeypair(signerContext, deviceId, derivationPath);
63
+
64
+ observer.next({
65
+ status: OnboardStatus.PREPARE,
66
+ });
67
+
68
+ const isOnboardedResult = await isAccountOnboarded(keypair.publicKey);
69
+ if (isOnboardedResult && isOnboardedResult.party_id) {
70
+ observer.next({
71
+ partyId: isOnboardedResult.party_id,
72
+ });
73
+ observer.complete();
74
+ return;
75
+ }
76
+
77
+ const preparedTransaction = await prepareOnboarding(keypair.publicKey, "ed25519");
78
+
79
+ observer.next({
80
+ status: OnboardStatus.SIGN,
81
+ });
82
+
83
+ const signature = await signerContext(deviceId, signer =>
84
+ signer.signTransaction(derivationPath, preparedTransaction.transactions.combined_hash),
85
+ );
86
+
87
+ observer.next({
88
+ status: OnboardStatus.SUBMIT,
89
+ });
90
+
91
+ const result = await submitOnboarding(
92
+ { public_key: keypair.publicKey, public_key_type: "ed25519" },
93
+ preparedTransaction,
94
+ signature,
95
+ ).catch(err => {
96
+ if (err.type === "PARTY_ALREADY_EXISTS") {
97
+ observer.next({
98
+ partyId: preparedTransaction.party_id,
99
+ });
100
+ return observer.complete();
101
+ }
102
+ throw err;
103
+ });
104
+
105
+ observer.next({
106
+ status: OnboardStatus.SUCCESS,
107
+ });
108
+
109
+ observer.next({
110
+ partyId: result?.party?.party_id || "unknown",
111
+ });
112
+
113
+ observer.complete();
114
+ }
115
+
116
+ main().then(
117
+ () => observer.complete(),
118
+ error => {
119
+ log("[onboardAccount] Error:", error);
120
+ observer.error(error);
121
+ },
122
+ );
123
+ });
124
+
125
+ export const buildAuthorizePreapproval =
126
+ (signerContext: SignerContext<CantonSigner>) =>
127
+ (
128
+ deviceId: string,
129
+ derivationPath: string,
130
+ partyId: string,
131
+ ): Observable<CantonPreApprovalProgress | CantonPreApprovalResult> =>
132
+ new Observable(observer => {
133
+ async function main() {
134
+ observer.next({
135
+ status: PreApprovalStatus.PREPARE,
136
+ });
137
+
138
+ const preparedTransaction: PrepareTransactionResponse =
139
+ await preparePreApprovalTransaction(partyId);
140
+
141
+ observer.next({
142
+ status: PreApprovalStatus.SIGN,
143
+ });
144
+
145
+ const signature = await signerContext(deviceId, signer =>
146
+ signer.signTransaction(derivationPath, preparedTransaction.hash),
147
+ );
148
+
149
+ observer.next({
150
+ status: PreApprovalStatus.SUBMIT,
151
+ });
152
+
153
+ const { isApproved } = await submitPreApprovalTransaction(
154
+ partyId,
155
+ preparedTransaction,
156
+ signature,
157
+ );
158
+
159
+ observer.next({
160
+ status: PreApprovalStatus.SUCCESS,
161
+ });
162
+
163
+ observer.next({
164
+ isApproved,
165
+ });
166
+
167
+ // TODO: remove after demo
168
+ const handleTapRequest = async () => {
169
+ try {
170
+ observer.next({
171
+ status: PreApprovalStatus.PREPARE,
172
+ });
173
+
174
+ const { serialized, hash } = await prepareTapRequest({
175
+ partyId,
176
+ });
177
+
178
+ observer.next({
179
+ status: PreApprovalStatus.SIGN,
180
+ });
181
+
182
+ const signature = await signerContext(deviceId, signer =>
183
+ signer.signTransaction(derivationPath, hash),
184
+ );
185
+
186
+ observer.next({
187
+ status: PreApprovalStatus.SUBMIT,
188
+ });
189
+
190
+ await submitTapRequest({
191
+ partyId,
192
+ serialized,
193
+ signature,
194
+ });
195
+
196
+ observer.next({
197
+ status: PreApprovalStatus.SUCCESS,
198
+ });
199
+ } catch (err) {
200
+ // Tap request failure should not break the pre-approval flow
201
+ }
202
+ };
203
+ await handleTapRequest();
204
+
205
+ observer.complete();
206
+ }
207
+
208
+ main().then(
209
+ () => observer.complete(),
210
+ error => {
211
+ log("[buildAuthorizePreapproval] Error:", error);
212
+ observer.error(error);
213
+ },
214
+ );
215
+ });
216
+
217
+ const log = (message: string, ...rest: any[]) => {
218
+ // eslint-disable-next-line no-console
219
+ console.log(message, ...rest);
220
+ };
@@ -1,25 +1,16 @@
1
1
  import { AccountBridge } from "@ledgerhq/types-live";
2
2
  import { Transaction } from "../types";
3
- import { craftTransaction, estimateFees } from "../common-logic";
4
- import { getNextSequence } from "../network/node";
3
+ import { estimateFees } from "../common-logic";
5
4
  import BigNumber from "bignumber.js";
5
+ import { updateTransaction } from "./updateTransaction";
6
6
 
7
7
  export const prepareTransaction: AccountBridge<Transaction>["prepareTransaction"] = async (
8
8
  account,
9
9
  transaction,
10
10
  ) => {
11
- const seq = await getNextSequence(account.freshAddress);
12
-
13
- const craftedTransaction = await craftTransaction(
14
- { address: account.freshAddress, nextSequenceNumber: seq },
15
- { amount: transaction.amount, recipient: transaction.recipient },
16
- );
17
-
18
- const fee = await estimateFees(craftedTransaction.serializedTransaction);
19
-
20
- if (transaction.fee !== new BigNumber(fee.toString())) {
21
- return { ...transaction, fee: new BigNumber(fee.toString()) };
11
+ let fee = transaction.fee;
12
+ if (!fee || fee.eq(0)) {
13
+ fee = BigNumber((await estimateFees("")).toString());
22
14
  }
23
-
24
- return transaction;
15
+ return updateTransaction(transaction, { fee });
25
16
  };
@@ -3,8 +3,8 @@ import { FeeNotLoaded } from "@ledgerhq/errors";
3
3
  import { AccountBridge, Operation } from "@ledgerhq/types-live";
4
4
  import { SignerContext } from "@ledgerhq/coin-framework/signer";
5
5
  import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
6
- import { combine, craftTransaction, getNextValidSequence } from "../common-logic";
7
- import { Transaction, CantonSigner, BoilerplateNativeTransaction } from "../types";
6
+ import { combine, craftTransaction } from "../common-logic";
7
+ import { Transaction, CantonSigner } from "../types";
8
8
 
9
9
  export const buildSignOperation =
10
10
  (signerContext: SignerContext<CantonSigner>): AccountBridge<Transaction>["signOperation"] =>
@@ -20,30 +20,24 @@ export const buildSignOperation =
20
20
  type: "device-signature-requested",
21
21
  });
22
22
 
23
- const nextSequenceNumber = await getNextValidSequence(account.freshAddress);
24
-
25
23
  const signature = await signerContext(deviceId, async signer => {
26
24
  const { freshAddressPath: derivationPath } = account;
27
- const { publicKey } = await signer.getAddress(derivationPath);
25
+ const partyId = account.freshAddress.replace("__", "::");
28
26
 
29
- const { nativeTransaction, serializedTransaction } = await craftTransaction(
27
+ const { hash, serializedTransaction } = await craftTransaction(
30
28
  {
31
- address: account.freshAddress,
32
- publicKey,
29
+ address: partyId,
33
30
  },
34
31
  {
35
32
  recipient: transaction.recipient,
36
33
  amount: transaction.amount,
37
- fee: fee,
34
+ expireInSeconds: 60 * 60,
35
+ tokenId: "Amulet",
38
36
  },
39
37
  );
38
+ const transactionSignature = await signer.signTransaction(derivationPath, hash);
40
39
 
41
- const transactionSignature = await signer.signTransaction(
42
- derivationPath,
43
- serializedTransaction,
44
- );
45
-
46
- return combine(serializedTransaction, transactionSignature);
40
+ return combine(serializedTransaction, `${transactionSignature}__PARTY__${partyId}`);
47
41
  });
48
42
 
49
43
  o.next({
@@ -64,7 +58,6 @@ export const buildSignOperation =
64
58
  senders: [account.freshAddress],
65
59
  recipients: [transaction.recipient],
66
60
  date: new Date(),
67
- transactionSequenceNumber: nextSequenceNumber,
68
61
  extra: {},
69
62
  };
70
63