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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +24 -0
  3. package/lib/api/getBalance.integ.test.js +8 -4
  4. package/lib/api/getBalance.integ.test.js.map +1 -1
  5. package/lib/api/index.d.ts.map +1 -1
  6. package/lib/api/index.js +20 -28
  7. package/lib/api/index.js.map +1 -1
  8. package/lib/api/lastBlock.integ.test.js +1 -1
  9. package/lib/api/lastBlock.integ.test.js.map +1 -1
  10. package/lib/api/listOperations.integ.test.js +1 -1
  11. package/lib/api/listOperations.integ.test.js.map +1 -1
  12. package/lib/bridge/broadcast.d.ts.map +1 -1
  13. package/lib/bridge/broadcast.js +2 -2
  14. package/lib/bridge/broadcast.js.map +1 -1
  15. package/lib/bridge/broadcast.test.js +9 -0
  16. package/lib/bridge/broadcast.test.js.map +1 -1
  17. package/lib/bridge/createTransaction.js +1 -1
  18. package/lib/bridge/createTransaction.js.map +1 -1
  19. package/lib/bridge/getTransactionStatus.js +1 -1
  20. package/lib/bridge/getTransactionStatus.js.map +1 -1
  21. package/lib/bridge/index.d.ts.map +1 -1
  22. package/lib/bridge/index.js +3 -0
  23. package/lib/bridge/index.js.map +1 -1
  24. package/lib/bridge/onboard.d.ts +7 -5
  25. package/lib/bridge/onboard.d.ts.map +1 -1
  26. package/lib/bridge/onboard.integ.test.js +13 -10
  27. package/lib/bridge/onboard.integ.test.js.map +1 -1
  28. package/lib/bridge/onboard.js +110 -42
  29. package/lib/bridge/onboard.js.map +1 -1
  30. package/lib/bridge/prepareTransaction.js +1 -1
  31. package/lib/bridge/prepareTransaction.js.map +1 -1
  32. package/lib/bridge/serialization.d.ts +4 -0
  33. package/lib/bridge/serialization.d.ts.map +1 -0
  34. package/lib/bridge/serialization.js +31 -0
  35. package/lib/bridge/serialization.js.map +1 -0
  36. package/lib/bridge/signOperation.d.ts.map +1 -1
  37. package/lib/bridge/signOperation.js +10 -5
  38. package/lib/bridge/signOperation.js.map +1 -1
  39. package/lib/bridge/sync.d.ts +2 -1
  40. package/lib/bridge/sync.d.ts.map +1 -1
  41. package/lib/bridge/sync.integ.test.js +2 -2
  42. package/lib/bridge/sync.integ.test.js.map +1 -1
  43. package/lib/bridge/sync.js +33 -20
  44. package/lib/bridge/sync.js.map +1 -1
  45. package/lib/common-logic/account/getBalance.d.ts +2 -1
  46. package/lib/common-logic/account/getBalance.d.ts.map +1 -1
  47. package/lib/common-logic/account/getBalance.js +7 -7
  48. package/lib/common-logic/account/getBalance.js.map +1 -1
  49. package/lib/common-logic/account/getBalance.unit.test.js +6 -3
  50. package/lib/common-logic/account/getBalance.unit.test.js.map +1 -1
  51. package/lib/common-logic/history/lastBlock.d.ts +2 -1
  52. package/lib/common-logic/history/lastBlock.d.ts.map +1 -1
  53. package/lib/common-logic/history/lastBlock.js +3 -3
  54. package/lib/common-logic/history/lastBlock.js.map +1 -1
  55. package/lib/common-logic/history/lastBlock.test.js +5 -2
  56. package/lib/common-logic/history/lastBlock.test.js.map +1 -1
  57. package/lib/common-logic/history/listOperations.d.ts +2 -1
  58. package/lib/common-logic/history/listOperations.d.ts.map +1 -1
  59. package/lib/common-logic/history/listOperations.js +2 -2
  60. package/lib/common-logic/history/listOperations.js.map +1 -1
  61. package/lib/common-logic/transaction/broadcast.d.ts +2 -1
  62. package/lib/common-logic/transaction/broadcast.d.ts.map +1 -1
  63. package/lib/common-logic/transaction/broadcast.js +4 -4
  64. package/lib/common-logic/transaction/broadcast.js.map +1 -1
  65. package/lib/common-logic/transaction/broadcast.test.js +6 -3
  66. package/lib/common-logic/transaction/broadcast.test.js.map +1 -1
  67. package/lib/common-logic/transaction/craftTransaction.d.ts +3 -1
  68. package/lib/common-logic/transaction/craftTransaction.d.ts.map +1 -1
  69. package/lib/common-logic/transaction/craftTransaction.js +8 -4
  70. package/lib/common-logic/transaction/craftTransaction.js.map +1 -1
  71. package/lib/common-logic/transaction/estimateFees.d.ts +2 -1
  72. package/lib/common-logic/transaction/estimateFees.d.ts.map +1 -1
  73. package/lib/common-logic/transaction/estimateFees.js +7 -3
  74. package/lib/common-logic/transaction/estimateFees.js.map +1 -1
  75. package/lib/config.d.ts +1 -0
  76. package/lib/config.d.ts.map +1 -1
  77. package/lib/config.js.map +1 -1
  78. package/lib/network/gateway.d.ts +28 -26
  79. package/lib/network/gateway.d.ts.map +1 -1
  80. package/lib/network/gateway.integ.test.js +19 -15
  81. package/lib/network/gateway.integ.test.js.map +1 -1
  82. package/lib/network/gateway.js +40 -33
  83. package/lib/network/gateway.js.map +1 -1
  84. package/lib/signer/getAddress.d.ts.map +1 -1
  85. package/lib/signer/getAddress.js +2 -2
  86. package/lib/signer/getAddress.js.map +1 -1
  87. package/lib/types/bridge.d.ts +18 -3
  88. package/lib/types/bridge.d.ts.map +1 -1
  89. package/lib/types/onboard.d.ts +2 -0
  90. package/lib/types/onboard.d.ts.map +1 -1
  91. package/lib/types/onboard.js.map +1 -1
  92. package/lib/types/signer.d.ts +2 -1
  93. package/lib/types/signer.d.ts.map +1 -1
  94. package/lib-es/api/getBalance.integ.test.js +8 -4
  95. package/lib-es/api/getBalance.integ.test.js.map +1 -1
  96. package/lib-es/api/index.d.ts.map +1 -1
  97. package/lib-es/api/index.js +19 -27
  98. package/lib-es/api/index.js.map +1 -1
  99. package/lib-es/api/lastBlock.integ.test.js +1 -1
  100. package/lib-es/api/lastBlock.integ.test.js.map +1 -1
  101. package/lib-es/api/listOperations.integ.test.js +1 -1
  102. package/lib-es/api/listOperations.integ.test.js.map +1 -1
  103. package/lib-es/bridge/broadcast.d.ts.map +1 -1
  104. package/lib-es/bridge/broadcast.js +2 -2
  105. package/lib-es/bridge/broadcast.js.map +1 -1
  106. package/lib-es/bridge/broadcast.test.js +9 -0
  107. package/lib-es/bridge/broadcast.test.js.map +1 -1
  108. package/lib-es/bridge/createTransaction.js +1 -1
  109. package/lib-es/bridge/createTransaction.js.map +1 -1
  110. package/lib-es/bridge/getTransactionStatus.js +1 -1
  111. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  112. package/lib-es/bridge/index.d.ts.map +1 -1
  113. package/lib-es/bridge/index.js +3 -0
  114. package/lib-es/bridge/index.js.map +1 -1
  115. package/lib-es/bridge/onboard.d.ts +7 -5
  116. package/lib-es/bridge/onboard.d.ts.map +1 -1
  117. package/lib-es/bridge/onboard.integ.test.js +13 -10
  118. package/lib-es/bridge/onboard.integ.test.js.map +1 -1
  119. package/lib-es/bridge/onboard.js +107 -42
  120. package/lib-es/bridge/onboard.js.map +1 -1
  121. package/lib-es/bridge/prepareTransaction.js +1 -1
  122. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  123. package/lib-es/bridge/serialization.d.ts +4 -0
  124. package/lib-es/bridge/serialization.d.ts.map +1 -0
  125. package/lib-es/bridge/serialization.js +27 -0
  126. package/lib-es/bridge/serialization.js.map +1 -0
  127. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  128. package/lib-es/bridge/signOperation.js +10 -5
  129. package/lib-es/bridge/signOperation.js.map +1 -1
  130. package/lib-es/bridge/sync.d.ts +2 -1
  131. package/lib-es/bridge/sync.d.ts.map +1 -1
  132. package/lib-es/bridge/sync.integ.test.js +2 -2
  133. package/lib-es/bridge/sync.integ.test.js.map +1 -1
  134. package/lib-es/bridge/sync.js +34 -21
  135. package/lib-es/bridge/sync.js.map +1 -1
  136. package/lib-es/common-logic/account/getBalance.d.ts +2 -1
  137. package/lib-es/common-logic/account/getBalance.d.ts.map +1 -1
  138. package/lib-es/common-logic/account/getBalance.js +7 -7
  139. package/lib-es/common-logic/account/getBalance.js.map +1 -1
  140. package/lib-es/common-logic/account/getBalance.unit.test.js +6 -3
  141. package/lib-es/common-logic/account/getBalance.unit.test.js.map +1 -1
  142. package/lib-es/common-logic/history/lastBlock.d.ts +2 -1
  143. package/lib-es/common-logic/history/lastBlock.d.ts.map +1 -1
  144. package/lib-es/common-logic/history/lastBlock.js +3 -3
  145. package/lib-es/common-logic/history/lastBlock.js.map +1 -1
  146. package/lib-es/common-logic/history/lastBlock.test.js +5 -2
  147. package/lib-es/common-logic/history/lastBlock.test.js.map +1 -1
  148. package/lib-es/common-logic/history/listOperations.d.ts +2 -1
  149. package/lib-es/common-logic/history/listOperations.d.ts.map +1 -1
  150. package/lib-es/common-logic/history/listOperations.js +2 -2
  151. package/lib-es/common-logic/history/listOperations.js.map +1 -1
  152. package/lib-es/common-logic/transaction/broadcast.d.ts +2 -1
  153. package/lib-es/common-logic/transaction/broadcast.d.ts.map +1 -1
  154. package/lib-es/common-logic/transaction/broadcast.js +4 -4
  155. package/lib-es/common-logic/transaction/broadcast.js.map +1 -1
  156. package/lib-es/common-logic/transaction/broadcast.test.js +6 -3
  157. package/lib-es/common-logic/transaction/broadcast.test.js.map +1 -1
  158. package/lib-es/common-logic/transaction/craftTransaction.d.ts +3 -1
  159. package/lib-es/common-logic/transaction/craftTransaction.d.ts.map +1 -1
  160. package/lib-es/common-logic/transaction/craftTransaction.js +9 -5
  161. package/lib-es/common-logic/transaction/craftTransaction.js.map +1 -1
  162. package/lib-es/common-logic/transaction/estimateFees.d.ts +2 -1
  163. package/lib-es/common-logic/transaction/estimateFees.d.ts.map +1 -1
  164. package/lib-es/common-logic/transaction/estimateFees.js +4 -3
  165. package/lib-es/common-logic/transaction/estimateFees.js.map +1 -1
  166. package/lib-es/config.d.ts +1 -0
  167. package/lib-es/config.d.ts.map +1 -1
  168. package/lib-es/config.js.map +1 -1
  169. package/lib-es/network/gateway.d.ts +28 -26
  170. package/lib-es/network/gateway.d.ts.map +1 -1
  171. package/lib-es/network/gateway.integ.test.js +19 -15
  172. package/lib-es/network/gateway.integ.test.js.map +1 -1
  173. package/lib-es/network/gateway.js +40 -33
  174. package/lib-es/network/gateway.js.map +1 -1
  175. package/lib-es/signer/getAddress.d.ts.map +1 -1
  176. package/lib-es/signer/getAddress.js +2 -2
  177. package/lib-es/signer/getAddress.js.map +1 -1
  178. package/lib-es/types/bridge.d.ts +18 -3
  179. package/lib-es/types/bridge.d.ts.map +1 -1
  180. package/lib-es/types/onboard.d.ts +2 -0
  181. package/lib-es/types/onboard.d.ts.map +1 -1
  182. package/lib-es/types/onboard.js.map +1 -1
  183. package/lib-es/types/signer.d.ts +2 -1
  184. package/lib-es/types/signer.d.ts.map +1 -1
  185. package/package.json +4 -4
  186. package/src/api/getBalance.integ.test.ts +8 -4
  187. package/src/api/index.ts +22 -51
  188. package/src/api/lastBlock.integ.test.ts +1 -1
  189. package/src/api/listOperations.integ.test.ts +1 -1
  190. package/src/bridge/broadcast.test.ts +11 -0
  191. package/src/bridge/broadcast.ts +5 -2
  192. package/src/bridge/createTransaction.ts +1 -1
  193. package/src/bridge/getTransactionStatus.ts +1 -1
  194. package/src/bridge/index.ts +3 -0
  195. package/src/bridge/onboard.integ.test.ts +24 -12
  196. package/src/bridge/onboard.ts +143 -51
  197. package/src/bridge/prepareTransaction.ts +1 -1
  198. package/src/bridge/serialization.ts +36 -0
  199. package/src/bridge/signOperation.ts +20 -7
  200. package/src/bridge/sync.integ.test.ts +2 -2
  201. package/src/bridge/sync.ts +40 -29
  202. package/src/common-logic/account/getBalance.ts +12 -7
  203. package/src/common-logic/account/getBalance.unit.test.ts +8 -3
  204. package/src/common-logic/history/lastBlock.test.ts +7 -2
  205. package/src/common-logic/history/lastBlock.ts +5 -3
  206. package/src/common-logic/history/listOperations.ts +3 -2
  207. package/src/common-logic/transaction/broadcast.test.ts +8 -3
  208. package/src/common-logic/transaction/broadcast.ts +6 -3
  209. package/src/common-logic/transaction/craftTransaction.ts +22 -5
  210. package/src/common-logic/transaction/estimateFees.ts +7 -3
  211. package/src/config.ts +1 -0
  212. package/src/network/gateway.integ.test.ts +31 -12
  213. package/src/network/gateway.ts +78 -53
  214. package/src/signer/getAddress.ts +6 -4
  215. package/src/types/bridge.ts +21 -0
  216. package/src/types/onboard.ts +3 -0
  217. package/src/types/signer.ts +2 -1
@@ -1,6 +1,10 @@
1
1
  import { Observable } from "rxjs";
2
2
  import { SignerContext } from "@ledgerhq/coin-framework/signer";
3
- import { CantonSigner } from "../types/signer";
3
+ import { emptyHistoryCache } from "@ledgerhq/coin-framework/account/index";
4
+ import { getDerivationModesForCurrency } from "@ledgerhq/coin-framework/derivation";
5
+ import { getAccountShape } from "./sync";
6
+ import { CantonAccount, CantonSigner } from "../types";
7
+ import type { Account, DerivationMode } from "@ledgerhq/types-live";
4
8
  import {
5
9
  prepareOnboarding,
6
10
  submitOnboarding,
@@ -19,8 +23,10 @@ import {
19
23
  CantonPreApprovalResult,
20
24
  PrepareTransactionResponse,
21
25
  } from "../types/onboard";
26
+ import resolver from "../signer";
27
+ import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
22
28
 
23
- async function getKeypair(
29
+ async function _getKeypair(
24
30
  signerContext: SignerContext<CantonSigner>,
25
31
  deviceId: string,
26
32
  derivationPath: string,
@@ -32,25 +38,27 @@ async function getKeypair(
32
38
  }
33
39
 
34
40
  export const isAccountOnboarded = async (
41
+ currency: CryptoCurrency,
35
42
  publicKey: string,
36
- ): Promise<false | { party_id: string }> => {
43
+ ): Promise<{ isOnboarded: boolean; party_id?: string }> => {
37
44
  try {
38
- const { party_id } = await getPartyByPubKey(publicKey);
45
+ const { party_id } = await getPartyByPubKey(currency, publicKey);
39
46
 
40
47
  if (party_id) {
41
- return { party_id };
48
+ return { isOnboarded: true, party_id };
42
49
  } else {
43
- return false;
50
+ return { isOnboarded: false };
44
51
  }
45
52
  } catch (err) {
46
53
  log("[isAccountOnboarded] Error checking party status (likely not onboarded):", err);
47
- return false;
54
+ return { isOnboarded: false };
48
55
  }
49
56
  };
50
57
 
51
58
  export const buildOnboardAccount =
52
59
  (signerContext: SignerContext<CantonSigner>) =>
53
60
  (
61
+ currency: CryptoCurrency,
54
62
  deviceId: string,
55
63
  derivationPath: string,
56
64
  ): Observable<CantonOnboardProgress | CantonOnboardResult> =>
@@ -59,22 +67,36 @@ export const buildOnboardAccount =
59
67
  observer.next({
60
68
  status: OnboardStatus.INIT,
61
69
  });
62
- const keypair = await getKeypair(signerContext, deviceId, derivationPath);
70
+ const derivationMode = getDerivationModesForCurrency(currency)[0];
71
+ const getAddress = resolver(signerContext);
72
+ const { address, publicKey } = await getAddress(deviceId, {
73
+ path: derivationPath,
74
+ currency,
75
+ derivationMode: derivationMode || "",
76
+ });
63
77
 
64
78
  observer.next({
65
79
  status: OnboardStatus.PREPARE,
66
80
  });
67
81
 
68
- const isOnboardedResult = await isAccountOnboarded(keypair.publicKey);
69
- if (isOnboardedResult && isOnboardedResult.party_id) {
82
+ const { party_id: partyId } = await isAccountOnboarded(currency, publicKey);
83
+ if (partyId) {
84
+ const account = await createAccount({
85
+ address,
86
+ derivationPath,
87
+ partyId,
88
+ currency,
89
+ derivationMode,
90
+ });
70
91
  observer.next({
71
- partyId: isOnboardedResult.party_id,
92
+ partyId,
93
+ account,
72
94
  });
73
95
  observer.complete();
74
96
  return;
75
97
  }
76
98
 
77
- const preparedTransaction = await prepareOnboarding(keypair.publicKey, "ed25519");
99
+ const preparedTransaction = await prepareOnboarding(currency, publicKey, "ed25519");
78
100
 
79
101
  observer.next({
80
102
  status: OnboardStatus.SIGN,
@@ -89,26 +111,44 @@ export const buildOnboardAccount =
89
111
  });
90
112
 
91
113
  const result = await submitOnboarding(
92
- { public_key: keypair.publicKey, public_key_type: "ed25519" },
114
+ currency,
115
+ { public_key: publicKey, public_key_type: "ed25519" },
93
116
  preparedTransaction,
94
117
  signature,
95
- ).catch(err => {
118
+ ).catch(async err => {
96
119
  if (err.type === "PARTY_ALREADY_EXISTS") {
120
+ const account = await createAccount({
121
+ address,
122
+ derivationPath,
123
+ partyId: preparedTransaction.party_id,
124
+ currency,
125
+ derivationMode,
126
+ });
97
127
  observer.next({
98
128
  partyId: preparedTransaction.party_id,
129
+ account,
99
130
  });
100
131
  return observer.complete();
101
132
  }
102
133
  throw err;
103
134
  });
104
135
 
105
- observer.next({
106
- status: OnboardStatus.SUCCESS,
107
- });
108
-
109
- observer.next({
110
- partyId: result?.party?.party_id || "unknown",
111
- });
136
+ if (result) {
137
+ observer.next({
138
+ status: OnboardStatus.SUCCESS,
139
+ });
140
+ const account = await createAccount({
141
+ address,
142
+ derivationPath,
143
+ partyId: result.party.party_id,
144
+ currency,
145
+ derivationMode,
146
+ });
147
+ observer.next({
148
+ partyId: result.party.party_id,
149
+ account,
150
+ });
151
+ }
112
152
 
113
153
  observer.complete();
114
154
  }
@@ -125,6 +165,7 @@ export const buildOnboardAccount =
125
165
  export const buildAuthorizePreapproval =
126
166
  (signerContext: SignerContext<CantonSigner>) =>
127
167
  (
168
+ currency: CryptoCurrency,
128
169
  deviceId: string,
129
170
  derivationPath: string,
130
171
  partyId: string,
@@ -135,8 +176,10 @@ export const buildAuthorizePreapproval =
135
176
  status: PreApprovalStatus.PREPARE,
136
177
  });
137
178
 
138
- const preparedTransaction: PrepareTransactionResponse =
139
- await preparePreApprovalTransaction(partyId);
179
+ const preparedTransaction: PrepareTransactionResponse = await preparePreApprovalTransaction(
180
+ currency,
181
+ partyId,
182
+ );
140
183
 
141
184
  observer.next({
142
185
  status: PreApprovalStatus.SIGN,
@@ -151,6 +194,7 @@ export const buildAuthorizePreapproval =
151
194
  });
152
195
 
153
196
  const { isApproved } = await submitPreApprovalTransaction(
197
+ currency,
154
198
  partyId,
155
199
  preparedTransaction,
156
200
  signature,
@@ -164,38 +208,35 @@ export const buildAuthorizePreapproval =
164
208
  isApproved,
165
209
  });
166
210
 
167
- // TODO: remove after demo
168
211
  const handleTapRequest = async () => {
169
212
  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({
213
+ const { serialized, hash } = await prepareTapRequest(currency, {
191
214
  partyId,
192
- serialized,
193
- signature,
194
215
  });
195
216
 
196
- observer.next({
197
- status: PreApprovalStatus.SUCCESS,
198
- });
217
+ if (serialized && hash) {
218
+ observer.next({
219
+ status: PreApprovalStatus.SIGN,
220
+ });
221
+
222
+ const signature = await signerContext(deviceId, signer =>
223
+ signer.signTransaction(derivationPath, hash),
224
+ );
225
+
226
+ observer.next({
227
+ status: PreApprovalStatus.SUBMIT,
228
+ });
229
+
230
+ await submitTapRequest(currency, {
231
+ partyId,
232
+ serialized,
233
+ signature,
234
+ });
235
+
236
+ observer.next({
237
+ status: PreApprovalStatus.SUCCESS,
238
+ });
239
+ }
199
240
  } catch (err) {
200
241
  // Tap request failure should not break the pre-approval flow
201
242
  }
@@ -214,7 +255,58 @@ export const buildAuthorizePreapproval =
214
255
  );
215
256
  });
216
257
 
217
- const log = (message: string, ...rest: any[]) => {
258
+ const createAccount = async ({
259
+ address,
260
+ partyId,
261
+ derivationPath,
262
+ currency,
263
+ derivationMode,
264
+ index = 0,
265
+ }: {
266
+ address: string;
267
+ derivationPath: string;
268
+ partyId: string;
269
+ currency: CryptoCurrency;
270
+ derivationMode: DerivationMode;
271
+ index?: number;
272
+ }): Promise<Partial<Account>> => {
273
+ const accountShape = await getAccountShape(
274
+ {
275
+ address,
276
+ currency,
277
+ derivationMode,
278
+ derivationPath,
279
+ index,
280
+ rest: {
281
+ cantonResources: {
282
+ partyId,
283
+ },
284
+ },
285
+ },
286
+ { paginationConfig: {} },
287
+ );
288
+
289
+ const account: Partial<CantonAccount> = {
290
+ ...accountShape,
291
+ type: "Account",
292
+ xpub: partyId.replace(/:/g, "_"),
293
+ index,
294
+ // operations: [],
295
+ currency,
296
+ derivationMode,
297
+ lastSyncDate: new Date(),
298
+ pendingOperations: [],
299
+ seedIdentifier: address,
300
+ balanceHistoryCache: emptyHistoryCache,
301
+ cantonResources: {
302
+ partyId,
303
+ },
304
+ };
305
+
306
+ return account;
307
+ };
308
+
309
+ const log = (message: string, ...rest: unknown[]) => {
218
310
  // eslint-disable-next-line no-console
219
311
  console.log(message, ...rest);
220
312
  };
@@ -10,7 +10,7 @@ export const prepareTransaction: AccountBridge<Transaction>["prepareTransaction"
10
10
  ) => {
11
11
  let fee = transaction.fee;
12
12
  if (!fee || fee.eq(0)) {
13
- fee = BigNumber((await estimateFees("")).toString());
13
+ fee = BigNumber((await estimateFees(account.currency)).toString());
14
14
  }
15
15
  return updateTransaction(transaction, { fee });
16
16
  };
@@ -0,0 +1,36 @@
1
+ import type { Account, AccountRaw } from "@ledgerhq/types-live";
2
+ import type {
3
+ CantonAccount,
4
+ CantonAccountRaw,
5
+ CantonResources,
6
+ CantonResourcesRaw,
7
+ } from "../types";
8
+
9
+ function toResourcesRaw(r: CantonResources): CantonResourcesRaw {
10
+ const { partyId } = r;
11
+ return {
12
+ partyId,
13
+ };
14
+ }
15
+ function fromResourcesRaw(r: CantonResourcesRaw): CantonResources {
16
+ const { partyId } = r;
17
+ return {
18
+ partyId,
19
+ };
20
+ }
21
+
22
+ export function assignToAccountRaw(account: Account, accountRaw: AccountRaw): void {
23
+ const cantonAccount = account as CantonAccount;
24
+ const cantonAccountRaw = accountRaw as CantonAccountRaw;
25
+ if (cantonAccount.cantonResources) {
26
+ cantonAccountRaw.cantonResources = toResourcesRaw(cantonAccount.cantonResources);
27
+ }
28
+ }
29
+
30
+ export function assignFromAccountRaw(accountRaw: AccountRaw, account: Account): void {
31
+ const cantonResourcesRaw = (accountRaw as CantonAccountRaw).cantonResources;
32
+ const cantonAccount = account as CantonAccount;
33
+ if (cantonResourcesRaw) {
34
+ cantonAccount.cantonResources = fromResourcesRaw(cantonResourcesRaw);
35
+ }
36
+ }
@@ -1,4 +1,5 @@
1
1
  import { Observable } from "rxjs";
2
+ import BigNumber from "bignumber.js";
2
3
  import { FeeNotLoaded } from "@ledgerhq/errors";
3
4
  import { AccountBridge, Operation } from "@ledgerhq/types-live";
4
5
  import { SignerContext } from "@ledgerhq/coin-framework/signer";
@@ -22,18 +23,30 @@ export const buildSignOperation =
22
23
 
23
24
  const signature = await signerContext(deviceId, async signer => {
24
25
  const { freshAddressPath: derivationPath } = account;
25
- const partyId = account.freshAddress.replace("__", "::");
26
+ const partyId = (account as unknown as { cantonResources: { partyId: string } })
27
+ .cantonResources.partyId;
28
+ const params: {
29
+ recipient?: string;
30
+ amount: BigNumber;
31
+ tokenId: string;
32
+ expireInSeconds: number;
33
+ memo?: string;
34
+ } = {
35
+ recipient: transaction.recipient,
36
+ amount: transaction.amount,
37
+ expireInSeconds: 60 * 60,
38
+ tokenId: "Amulet",
39
+ };
40
+ if (transaction.memo) {
41
+ params.memo = transaction.memo;
42
+ }
26
43
 
27
44
  const { hash, serializedTransaction } = await craftTransaction(
45
+ account.currency,
28
46
  {
29
47
  address: partyId,
30
48
  },
31
- {
32
- recipient: transaction.recipient,
33
- amount: transaction.amount,
34
- expireInSeconds: 60 * 60,
35
- tokenId: "Amulet",
36
- },
49
+ params,
37
50
  );
38
51
  const transactionSignature = await signer.signTransaction(derivationPath, hash);
39
52
 
@@ -110,7 +110,7 @@ describe("sync (devnet)", () => {
110
110
 
111
111
  mockGetBalance.mockResolvedValue([
112
112
  {
113
- instrument_id: "canton_network",
113
+ instrument_id: "Amulet",
114
114
  amount: 1000000,
115
115
  locked: true,
116
116
  },
@@ -167,7 +167,7 @@ describe("sync (devnet)", () => {
167
167
  const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
168
168
 
169
169
  expect(result.operations).toBeDefined();
170
- expect(result.operationsCount).toBeGreaterThan(1);
170
+ expect(result.operationsCount).toBeGreaterThanOrEqual(1);
171
171
 
172
172
  expect(mockGetOperations).toHaveBeenCalledWith(TEST_ADDRESS, {
173
173
  cursor: 0,
@@ -1,14 +1,14 @@
1
1
  import BigNumber from "bignumber.js";
2
- import { Operation } from "@ledgerhq/types-live";
3
- import { encodeAccountId } from "@ledgerhq/coin-framework/account/index";
2
+ import { Operation, OperationType } from "@ledgerhq/types-live";
3
+ import { decodeAccountId, encodeAccountId } from "@ledgerhq/coin-framework/account/index";
4
4
  import { GetAccountShape, mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
5
- import { getBalance, getLedgerEnd, getOperations, type OperationInfo } from "../network/gateway";
6
-
7
5
  import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
6
+ import { getBalance, getLedgerEnd, getOperations, type OperationInfo } from "../network/gateway";
7
+ import { CantonAccount } from "../types";
8
8
  import coinConfig from "../config";
9
9
 
10
10
  const txInfoToOperationAdapter =
11
- (accountId: string, address: string) =>
11
+ (accountId: string, partyId: string) =>
12
12
  (txInfo: OperationInfo): Operation => {
13
13
  const {
14
14
  transaction_hash,
@@ -18,11 +18,17 @@ const txInfoToOperationAdapter =
18
18
  recipients,
19
19
  transaction_timestamp,
20
20
  fee: { value: fee },
21
- transfers: [{ value: transferValue }],
21
+ transfers: [{ value: transferValue, details }],
22
22
  } = txInfo;
23
- const type = senders.includes(address) ? "OUT" : "IN";
23
+ let type: OperationType = "UNKNOWN";
24
+ if (txInfo.type === "Send") {
25
+ type = senders.includes(partyId) ? "OUT" : "IN";
26
+ } else if (txInfo.type === "Receive") {
27
+ type = "IN";
28
+ }
24
29
  const value = new BigNumber(transferValue);
25
30
  const feeValue = new BigNumber(fee);
31
+ const memo = details.metadata.reason;
26
32
 
27
33
  const op: Operation = {
28
34
  id: encodeOperationId(accountId, transaction_hash, type),
@@ -39,6 +45,7 @@ const txInfoToOperationAdapter =
39
45
  transactionSequenceNumber: height,
40
46
  extra: {
41
47
  uid,
48
+ memo,
42
49
  },
43
50
  };
44
51
 
@@ -48,42 +55,43 @@ const txInfoToOperationAdapter =
48
55
  const filterOperations = (
49
56
  transactions: OperationInfo[],
50
57
  accountId: string,
51
- address: string,
58
+ partyId: string,
52
59
  ): Operation[] => {
53
- return transactions
54
- .filter(tx => tx.type === "Receive" || tx.type === "Send")
55
- .map(txInfoToOperationAdapter(accountId, address));
60
+ return transactions.map(txInfoToOperationAdapter(accountId, partyId));
56
61
  };
57
62
 
58
- export const getAccountShape: GetAccountShape = async info => {
59
- const { address, initialAccount, currency, derivationMode } = info;
60
- // TODO: we need better solution ?
61
- const xpubOrAddress = address?.replace(/:/g, "_") || "";
63
+ export const getAccountShape: GetAccountShape<CantonAccount> = async info => {
64
+ const { address, initialAccount, currency, derivationMode, derivationPath, rest } = info;
65
+
66
+ const xpubOrAddress = (
67
+ (initialAccount && initialAccount.id && decodeAccountId(initialAccount.id).xpubOrAddress) ||
68
+ ""
69
+ ).replace(/:/g, "_");
70
+ const partyId =
71
+ rest?.cantonResources?.partyId ||
72
+ initialAccount?.cantonResources?.partyId ||
73
+ xpubOrAddress.replace(/_/g, ":");
62
74
 
63
75
  const accountId = encodeAccountId({
64
76
  type: "js",
65
77
  version: "2",
66
78
  currencyId: currency.id,
67
79
  xpubOrAddress,
68
- derivationMode: "",
80
+ derivationMode,
69
81
  });
70
82
 
71
- // blockheight retrieval
72
- const blockHeight = await getLedgerEnd();
73
-
74
83
  // Account info retrieval + spendable balance calculation
75
84
  // const accountInfo = await getAccountInfo(address);
76
- const balances = await getBalance(address);
85
+ const balances = await getBalance(currency, partyId);
77
86
 
78
- // TODO change to balance.instrument_id === "Amulet" after update on backend
79
- const balanceData = balances.find(balance => balance.instrument_id.includes("Amulet")) || {
87
+ const balanceData = balances.find(balance => balance.instrument_id === "Amulet") || {
80
88
  instrument_id: "Amulet",
81
89
  amount: 0,
82
90
  locked: false,
83
91
  };
84
92
 
85
93
  const balance = new BigNumber(balanceData.amount);
86
- const reserveMin = coinConfig.getCoinConfig().minReserve || 0;
94
+ const reserveMin = coinConfig.getCoinConfig(currency).minReserve || 0;
87
95
  const lockedAmount = balanceData.locked ? balance : new BigNumber(0);
88
96
  const spendableBalance = BigNumber.max(
89
97
  0,
@@ -93,16 +101,14 @@ export const getAccountShape: GetAccountShape = async info => {
93
101
  // Tx history fetching
94
102
  const oldOperations = initialAccount?.operations || [];
95
103
  const startAt = oldOperations.length ? (oldOperations[0].blockHeight || 0) + 1 : 0;
96
- const transactionData = await getOperations(address, {
104
+ const transactionData = await getOperations(currency, partyId, {
97
105
  cursor: startAt,
98
106
  limit: 100,
99
107
  });
108
+ // blockheight retrieval
109
+ const blockHeight = await getLedgerEnd(currency);
100
110
 
101
- const newOperations = filterOperations(
102
- transactionData.operations,
103
- accountId,
104
- address.replace(/_/g, ":"),
105
- );
111
+ const newOperations = filterOperations(transactionData.operations, accountId, partyId);
106
112
  const operations = mergeOps(oldOperations, newOperations);
107
113
 
108
114
  // We return the new account shape
@@ -114,6 +120,11 @@ export const getAccountShape: GetAccountShape = async info => {
114
120
  spendableBalance,
115
121
  operations,
116
122
  operationsCount: operations.length,
123
+ freshAddress: address,
124
+ freshAddressPath: derivationPath,
125
+ cantonResources: {
126
+ partyId,
127
+ },
117
128
  };
118
129
 
119
130
  return shape;
@@ -1,23 +1,28 @@
1
1
  import { Balance } from "@ledgerhq/coin-framework/api/types";
2
2
  import { getBalance as gatewayGetBalance, type InstrumentBalance } from "../../network/gateway";
3
3
  import coinConfig from "../../config";
4
+ import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
4
5
 
5
- const useGateway = () => coinConfig.getCoinConfig().useGateway === true;
6
- const getNativeId = () => coinConfig.getCoinConfig().nativeInstrumentId;
6
+ const useGateway = (currency: CryptoCurrency) =>
7
+ coinConfig.getCoinConfig(currency).useGateway === true;
8
+ const getNativeId = (currency: CryptoCurrency) =>
9
+ coinConfig.getCoinConfig(currency).nativeInstrumentId;
7
10
 
8
- function adaptInstrument(instrument: InstrumentBalance): Balance {
11
+ function adaptInstrument(currency: CryptoCurrency, instrument: InstrumentBalance): Balance {
9
12
  return {
10
13
  value: BigInt(instrument.amount),
11
14
  locked: instrument.locked === true ? BigInt(instrument.amount) : BigInt(0),
12
15
  asset:
13
- getNativeId() === instrument.instrument_id
16
+ getNativeId(currency) === instrument.instrument_id
14
17
  ? { type: "native" }
15
18
  : { type: "token", assetReference: instrument.instrument_id },
16
19
  };
17
20
  }
18
21
 
19
- export async function getBalance(partyId: string): Promise<Balance[]> {
20
- if (useGateway())
21
- return (await gatewayGetBalance(partyId)).map(instrument => adaptInstrument(instrument));
22
+ export async function getBalance(currency: CryptoCurrency, partyId: string): Promise<Balance[]> {
23
+ if (useGateway(currency))
24
+ return (await gatewayGetBalance(currency, partyId)).map(instrument =>
25
+ adaptInstrument(currency, instrument),
26
+ );
22
27
  else throw new Error("Not implemented");
23
28
  }
@@ -2,6 +2,11 @@ import { getBalance as getBalanceFromNetwork } from "../../network/gateway";
2
2
  import * as coinConfigModule from "../../config";
3
3
  import { getBalance } from "./getBalance";
4
4
  import { Balance } from "@ledgerhq/coin-framework/api/types";
5
+ import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
6
+
7
+ const mockCurrency = {
8
+ id: "canton_network",
9
+ } as unknown as CryptoCurrency;
5
10
 
6
11
  jest.mock("../../network/gateway", () => ({
7
12
  getBalance: jest.fn(),
@@ -35,9 +40,9 @@ describe("getBalance", () => {
35
40
 
36
41
  (getBalanceFromNetwork as jest.Mock).mockResolvedValue(mockInstruments);
37
42
 
38
- const result = await getBalance("party-id");
43
+ const result = await getBalance(mockCurrency, "party-id");
39
44
 
40
- expect(getBalanceFromNetwork).toHaveBeenCalledWith("party-id");
45
+ expect(getBalanceFromNetwork).toHaveBeenCalledWith(mockCurrency, "party-id");
41
46
  expect(result).toEqual<Balance[]>([
42
47
  {
43
48
  value: BigInt(1000),
@@ -57,7 +62,7 @@ describe("getBalance", () => {
57
62
  useGateway: false,
58
63
  } as any);
59
64
 
60
- await expect(getBalance("party-id")).rejects.toThrow("Not implemented");
65
+ await expect(getBalance(mockCurrency, "party-id")).rejects.toThrow("Not implemented");
61
66
  expect(getBalanceFromNetwork).not.toHaveBeenCalled();
62
67
  });
63
68
  });
@@ -1,6 +1,7 @@
1
1
  import { lastBlock } from "./lastBlock";
2
2
  import { getLedgerEnd as gatewayGetLedgerEnd } from "../../network/gateway";
3
3
  import { getLedgerEnd as nodeGetLedgerEnd } from "../../network/node";
4
+ import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
4
5
 
5
6
  jest.mock("../../network/gateway", () => ({
6
7
  getLedgerEnd: jest.fn(),
@@ -18,6 +19,10 @@ jest.mock("../../config", () => ({
18
19
 
19
20
  import coinConfig from "../../config";
20
21
 
22
+ const mockCurrency = {
23
+ id: "canton_network",
24
+ } as unknown as CryptoCurrency;
25
+
21
26
  describe("lastBlock", () => {
22
27
  beforeEach(() => {
23
28
  jest.clearAllMocks();
@@ -27,7 +32,7 @@ describe("lastBlock", () => {
27
32
  (coinConfig.getCoinConfig as jest.Mock).mockReturnValue({ useGateway: true });
28
33
  (gatewayGetLedgerEnd as jest.Mock).mockResolvedValue(100);
29
34
 
30
- const result = await lastBlock();
35
+ const result = await lastBlock(mockCurrency);
31
36
 
32
37
  expect(result).toEqual({ height: 100 });
33
38
  expect(gatewayGetLedgerEnd).toHaveBeenCalledTimes(1);
@@ -38,7 +43,7 @@ describe("lastBlock", () => {
38
43
  (coinConfig.getCoinConfig as jest.Mock).mockReturnValue({ useGateway: false });
39
44
  (nodeGetLedgerEnd as jest.Mock).mockResolvedValue(200);
40
45
 
41
- const result = await lastBlock();
46
+ const result = await lastBlock(mockCurrency);
42
47
 
43
48
  expect(result).toEqual({ height: 200 });
44
49
  expect(nodeGetLedgerEnd).toHaveBeenCalledTimes(1);
@@ -2,11 +2,13 @@ import type { BlockInfo } from "@ledgerhq/coin-framework/api/index";
2
2
  import { getLedgerEnd as nodeGetLedgerEnd } from "../../network/node";
3
3
  import { getLedgerEnd } from "../../network/gateway";
4
4
  import coinConfig from "../../config";
5
+ import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
5
6
 
6
- const useGateway = () => coinConfig.getCoinConfig().useGateway === true;
7
+ const useGateway = (currency: CryptoCurrency) =>
8
+ coinConfig.getCoinConfig(currency).useGateway === true;
7
9
 
8
- export async function lastBlock(): Promise<BlockInfo> {
10
+ export async function lastBlock(currency: CryptoCurrency): Promise<BlockInfo> {
9
11
  return {
10
- height: useGateway() ? await getLedgerEnd() : await nodeGetLedgerEnd(),
12
+ height: useGateway(currency) ? await getLedgerEnd(currency) : await nodeGetLedgerEnd(),
11
13
  };
12
14
  }