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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +21 -0
  3. package/lib/api/getBalance.integ.test.js +9 -5
  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 -25
  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 +3 -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 +14 -11
  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.d.ts.map +1 -1
  31. package/lib/bridge/prepareTransaction.js +5 -7
  32. package/lib/bridge/prepareTransaction.js.map +1 -1
  33. package/lib/bridge/serialization.d.ts +4 -0
  34. package/lib/bridge/serialization.d.ts.map +1 -0
  35. package/lib/bridge/serialization.js +31 -0
  36. package/lib/bridge/serialization.js.map +1 -0
  37. package/lib/bridge/signOperation.d.ts.map +1 -1
  38. package/lib/bridge/signOperation.js +14 -11
  39. package/lib/bridge/signOperation.js.map +1 -1
  40. package/lib/bridge/sync.d.ts +2 -1
  41. package/lib/bridge/sync.d.ts.map +1 -1
  42. package/lib/bridge/sync.integ.test.d.ts +2 -0
  43. package/lib/bridge/sync.integ.test.d.ts.map +1 -0
  44. package/lib/bridge/sync.integ.test.js +175 -0
  45. package/lib/bridge/sync.integ.test.js.map +1 -0
  46. package/lib/bridge/sync.js +50 -27
  47. package/lib/bridge/sync.js.map +1 -1
  48. package/lib/bridge/updateTransaction.d.ts.map +1 -1
  49. package/lib/bridge/updateTransaction.js +0 -4
  50. package/lib/bridge/updateTransaction.js.map +1 -1
  51. package/lib/common-logic/account/getBalance.d.ts +2 -1
  52. package/lib/common-logic/account/getBalance.d.ts.map +1 -1
  53. package/lib/common-logic/account/getBalance.js +7 -7
  54. package/lib/common-logic/account/getBalance.js.map +1 -1
  55. package/lib/common-logic/account/getBalance.unit.test.js +6 -3
  56. package/lib/common-logic/account/getBalance.unit.test.js.map +1 -1
  57. package/lib/common-logic/history/lastBlock.d.ts +2 -1
  58. package/lib/common-logic/history/lastBlock.d.ts.map +1 -1
  59. package/lib/common-logic/history/lastBlock.js +3 -3
  60. package/lib/common-logic/history/lastBlock.js.map +1 -1
  61. package/lib/common-logic/history/lastBlock.test.js +5 -2
  62. package/lib/common-logic/history/lastBlock.test.js.map +1 -1
  63. package/lib/common-logic/history/listOperations.d.ts +2 -1
  64. package/lib/common-logic/history/listOperations.d.ts.map +1 -1
  65. package/lib/common-logic/history/listOperations.js +2 -2
  66. package/lib/common-logic/history/listOperations.js.map +1 -1
  67. package/lib/common-logic/transaction/broadcast.d.ts +2 -1
  68. package/lib/common-logic/transaction/broadcast.d.ts.map +1 -1
  69. package/lib/common-logic/transaction/broadcast.js +5 -4
  70. package/lib/common-logic/transaction/broadcast.js.map +1 -1
  71. package/lib/common-logic/transaction/broadcast.test.js +8 -5
  72. package/lib/common-logic/transaction/broadcast.test.js.map +1 -1
  73. package/lib/common-logic/transaction/combine.d.ts +1 -1
  74. package/lib/common-logic/transaction/combine.d.ts.map +1 -1
  75. package/lib/common-logic/transaction/combine.js +2 -3
  76. package/lib/common-logic/transaction/combine.js.map +1 -1
  77. package/lib/common-logic/transaction/combine.test.js +3 -13
  78. package/lib/common-logic/transaction/combine.test.js.map +1 -1
  79. package/lib/common-logic/transaction/craftTransaction.d.ts +8 -4
  80. package/lib/common-logic/transaction/craftTransaction.d.ts.map +1 -1
  81. package/lib/common-logic/transaction/craftTransaction.js +15 -12
  82. package/lib/common-logic/transaction/craftTransaction.js.map +1 -1
  83. package/lib/common-logic/transaction/estimateFees.d.ts +2 -1
  84. package/lib/common-logic/transaction/estimateFees.d.ts.map +1 -1
  85. package/lib/common-logic/transaction/estimateFees.js +7 -3
  86. package/lib/common-logic/transaction/estimateFees.js.map +1 -1
  87. package/lib/config.d.ts +1 -0
  88. package/lib/config.d.ts.map +1 -1
  89. package/lib/config.js.map +1 -1
  90. package/lib/network/gateway.d.ts +41 -17
  91. package/lib/network/gateway.d.ts.map +1 -1
  92. package/lib/network/gateway.integ.test.js +19 -15
  93. package/lib/network/gateway.integ.test.js.map +1 -1
  94. package/lib/network/gateway.js +74 -48
  95. package/lib/network/gateway.js.map +1 -1
  96. package/lib/network/node.d.ts +2 -2
  97. package/lib/network/node.d.ts.map +1 -1
  98. package/lib/network/node.js.map +1 -1
  99. package/lib/network/types.d.ts +1 -1
  100. package/lib/network/types.d.ts.map +1 -1
  101. package/lib/signer/getAddress.d.ts.map +1 -1
  102. package/lib/signer/getAddress.js +2 -2
  103. package/lib/signer/getAddress.js.map +1 -1
  104. package/lib/types/bridge.d.ts +18 -3
  105. package/lib/types/bridge.d.ts.map +1 -1
  106. package/lib/types/index.d.ts +0 -10
  107. package/lib/types/index.d.ts.map +1 -1
  108. package/lib/types/onboard.d.ts +2 -0
  109. package/lib/types/onboard.d.ts.map +1 -1
  110. package/lib/types/onboard.js.map +1 -1
  111. package/lib/types/signer.d.ts +2 -1
  112. package/lib/types/signer.d.ts.map +1 -1
  113. package/lib-es/api/getBalance.integ.test.js +9 -5
  114. package/lib-es/api/getBalance.integ.test.js.map +1 -1
  115. package/lib-es/api/index.d.ts.map +1 -1
  116. package/lib-es/api/index.js +19 -24
  117. package/lib-es/api/index.js.map +1 -1
  118. package/lib-es/api/lastBlock.integ.test.js +1 -1
  119. package/lib-es/api/lastBlock.integ.test.js.map +1 -1
  120. package/lib-es/api/listOperations.integ.test.js +1 -1
  121. package/lib-es/api/listOperations.integ.test.js.map +1 -1
  122. package/lib-es/bridge/broadcast.d.ts.map +1 -1
  123. package/lib-es/bridge/broadcast.js +3 -2
  124. package/lib-es/bridge/broadcast.js.map +1 -1
  125. package/lib-es/bridge/broadcast.test.js +9 -0
  126. package/lib-es/bridge/broadcast.test.js.map +1 -1
  127. package/lib-es/bridge/createTransaction.js +1 -1
  128. package/lib-es/bridge/createTransaction.js.map +1 -1
  129. package/lib-es/bridge/getTransactionStatus.js +1 -1
  130. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  131. package/lib-es/bridge/index.d.ts.map +1 -1
  132. package/lib-es/bridge/index.js +3 -0
  133. package/lib-es/bridge/index.js.map +1 -1
  134. package/lib-es/bridge/onboard.d.ts +7 -5
  135. package/lib-es/bridge/onboard.d.ts.map +1 -1
  136. package/lib-es/bridge/onboard.integ.test.js +14 -11
  137. package/lib-es/bridge/onboard.integ.test.js.map +1 -1
  138. package/lib-es/bridge/onboard.js +107 -42
  139. package/lib-es/bridge/onboard.js.map +1 -1
  140. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
  141. package/lib-es/bridge/prepareTransaction.js +6 -8
  142. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  143. package/lib-es/bridge/serialization.d.ts +4 -0
  144. package/lib-es/bridge/serialization.d.ts.map +1 -0
  145. package/lib-es/bridge/serialization.js +27 -0
  146. package/lib-es/bridge/serialization.js.map +1 -0
  147. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  148. package/lib-es/bridge/signOperation.js +15 -12
  149. package/lib-es/bridge/signOperation.js.map +1 -1
  150. package/lib-es/bridge/sync.d.ts +2 -1
  151. package/lib-es/bridge/sync.d.ts.map +1 -1
  152. package/lib-es/bridge/sync.integ.test.d.ts +2 -0
  153. package/lib-es/bridge/sync.integ.test.d.ts.map +1 -0
  154. package/lib-es/bridge/sync.integ.test.js +137 -0
  155. package/lib-es/bridge/sync.integ.test.js.map +1 -0
  156. package/lib-es/bridge/sync.js +51 -28
  157. package/lib-es/bridge/sync.js.map +1 -1
  158. package/lib-es/bridge/updateTransaction.d.ts.map +1 -1
  159. package/lib-es/bridge/updateTransaction.js +0 -4
  160. package/lib-es/bridge/updateTransaction.js.map +1 -1
  161. package/lib-es/common-logic/account/getBalance.d.ts +2 -1
  162. package/lib-es/common-logic/account/getBalance.d.ts.map +1 -1
  163. package/lib-es/common-logic/account/getBalance.js +7 -7
  164. package/lib-es/common-logic/account/getBalance.js.map +1 -1
  165. package/lib-es/common-logic/account/getBalance.unit.test.js +6 -3
  166. package/lib-es/common-logic/account/getBalance.unit.test.js.map +1 -1
  167. package/lib-es/common-logic/history/lastBlock.d.ts +2 -1
  168. package/lib-es/common-logic/history/lastBlock.d.ts.map +1 -1
  169. package/lib-es/common-logic/history/lastBlock.js +3 -3
  170. package/lib-es/common-logic/history/lastBlock.js.map +1 -1
  171. package/lib-es/common-logic/history/lastBlock.test.js +5 -2
  172. package/lib-es/common-logic/history/lastBlock.test.js.map +1 -1
  173. package/lib-es/common-logic/history/listOperations.d.ts +2 -1
  174. package/lib-es/common-logic/history/listOperations.d.ts.map +1 -1
  175. package/lib-es/common-logic/history/listOperations.js +2 -2
  176. package/lib-es/common-logic/history/listOperations.js.map +1 -1
  177. package/lib-es/common-logic/transaction/broadcast.d.ts +2 -1
  178. package/lib-es/common-logic/transaction/broadcast.d.ts.map +1 -1
  179. package/lib-es/common-logic/transaction/broadcast.js +5 -4
  180. package/lib-es/common-logic/transaction/broadcast.js.map +1 -1
  181. package/lib-es/common-logic/transaction/broadcast.test.js +8 -5
  182. package/lib-es/common-logic/transaction/broadcast.test.js.map +1 -1
  183. package/lib-es/common-logic/transaction/combine.d.ts +1 -1
  184. package/lib-es/common-logic/transaction/combine.d.ts.map +1 -1
  185. package/lib-es/common-logic/transaction/combine.js +2 -3
  186. package/lib-es/common-logic/transaction/combine.js.map +1 -1
  187. package/lib-es/common-logic/transaction/combine.test.js +3 -13
  188. package/lib-es/common-logic/transaction/combine.test.js.map +1 -1
  189. package/lib-es/common-logic/transaction/craftTransaction.d.ts +8 -4
  190. package/lib-es/common-logic/transaction/craftTransaction.d.ts.map +1 -1
  191. package/lib-es/common-logic/transaction/craftTransaction.js +15 -12
  192. package/lib-es/common-logic/transaction/craftTransaction.js.map +1 -1
  193. package/lib-es/common-logic/transaction/estimateFees.d.ts +2 -1
  194. package/lib-es/common-logic/transaction/estimateFees.d.ts.map +1 -1
  195. package/lib-es/common-logic/transaction/estimateFees.js +4 -3
  196. package/lib-es/common-logic/transaction/estimateFees.js.map +1 -1
  197. package/lib-es/config.d.ts +1 -0
  198. package/lib-es/config.d.ts.map +1 -1
  199. package/lib-es/config.js.map +1 -1
  200. package/lib-es/network/gateway.d.ts +41 -17
  201. package/lib-es/network/gateway.d.ts.map +1 -1
  202. package/lib-es/network/gateway.integ.test.js +19 -15
  203. package/lib-es/network/gateway.integ.test.js.map +1 -1
  204. package/lib-es/network/gateway.js +73 -48
  205. package/lib-es/network/gateway.js.map +1 -1
  206. package/lib-es/network/node.d.ts +2 -2
  207. package/lib-es/network/node.d.ts.map +1 -1
  208. package/lib-es/network/node.js.map +1 -1
  209. package/lib-es/network/types.d.ts +1 -1
  210. package/lib-es/network/types.d.ts.map +1 -1
  211. package/lib-es/signer/getAddress.d.ts.map +1 -1
  212. package/lib-es/signer/getAddress.js +2 -2
  213. package/lib-es/signer/getAddress.js.map +1 -1
  214. package/lib-es/types/bridge.d.ts +18 -3
  215. package/lib-es/types/bridge.d.ts.map +1 -1
  216. package/lib-es/types/index.d.ts +0 -10
  217. package/lib-es/types/index.d.ts.map +1 -1
  218. package/lib-es/types/onboard.d.ts +2 -0
  219. package/lib-es/types/onboard.d.ts.map +1 -1
  220. package/lib-es/types/onboard.js.map +1 -1
  221. package/lib-es/types/signer.d.ts +2 -1
  222. package/lib-es/types/signer.d.ts.map +1 -1
  223. package/package.json +8 -8
  224. package/src/api/getBalance.integ.test.ts +9 -6
  225. package/src/api/index.ts +22 -44
  226. package/src/api/lastBlock.integ.test.ts +1 -1
  227. package/src/api/listOperations.integ.test.ts +1 -1
  228. package/src/bridge/broadcast.test.ts +11 -0
  229. package/src/bridge/broadcast.ts +4 -2
  230. package/src/bridge/createTransaction.ts +1 -1
  231. package/src/bridge/getTransactionStatus.ts +1 -1
  232. package/src/bridge/index.ts +3 -0
  233. package/src/bridge/onboard.integ.test.ts +25 -13
  234. package/src/bridge/onboard.ts +143 -51
  235. package/src/bridge/prepareTransaction.ts +6 -15
  236. package/src/bridge/serialization.ts +36 -0
  237. package/src/bridge/signOperation.ts +26 -20
  238. package/src/bridge/sync.integ.test.ts +180 -0
  239. package/src/bridge/sync.ts +61 -33
  240. package/src/bridge/updateTransaction.ts +0 -5
  241. package/src/common-logic/account/getBalance.ts +12 -7
  242. package/src/common-logic/account/getBalance.unit.test.ts +8 -3
  243. package/src/common-logic/history/lastBlock.test.ts +7 -2
  244. package/src/common-logic/history/lastBlock.ts +5 -3
  245. package/src/common-logic/history/listOperations.ts +3 -2
  246. package/src/common-logic/transaction/broadcast.test.ts +10 -5
  247. package/src/common-logic/transaction/broadcast.ts +7 -3
  248. package/src/common-logic/transaction/combine.test.ts +3 -13
  249. package/src/common-logic/transaction/combine.ts +2 -4
  250. package/src/common-logic/transaction/craftTransaction.ts +30 -15
  251. package/src/common-logic/transaction/estimateFees.ts +8 -3
  252. package/src/config.ts +1 -0
  253. package/src/network/gateway.integ.test.ts +31 -12
  254. package/src/network/gateway.ts +141 -62
  255. package/src/network/node.ts +3 -3
  256. package/src/network/types.ts +1 -1
  257. package/src/signer/getAddress.ts +6 -4
  258. package/src/types/bridge.ts +21 -0
  259. package/src/types/index.ts +0 -11
  260. package/src/types/onboard.ts +3 -0
  261. 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
  };
@@ -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(account.currency)).toString());
22
14
  }
23
-
24
- return transaction;
15
+ return updateTransaction(transaction, { fee });
25
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,10 +1,11 @@
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";
5
6
  import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
6
- import { combine, craftTransaction, getNextValidSequence } from "../common-logic";
7
- import { Transaction, CantonSigner, BoilerplateNativeTransaction } from "../types";
7
+ import { combine, craftTransaction } from "../common-logic";
8
+ import { Transaction, CantonSigner } from "../types";
8
9
 
9
10
  export const buildSignOperation =
10
11
  (signerContext: SignerContext<CantonSigner>): AccountBridge<Transaction>["signOperation"] =>
@@ -20,30 +21,36 @@ export const buildSignOperation =
20
21
  type: "device-signature-requested",
21
22
  });
22
23
 
23
- const nextSequenceNumber = await getNextValidSequence(account.freshAddress);
24
-
25
24
  const signature = await signerContext(deviceId, async signer => {
26
25
  const { freshAddressPath: derivationPath } = account;
27
- const { publicKey } = await signer.getAddress(derivationPath);
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
+ }
28
43
 
29
- const { nativeTransaction, serializedTransaction } = await craftTransaction(
30
- {
31
- address: account.freshAddress,
32
- publicKey,
33
- },
44
+ const { hash, serializedTransaction } = await craftTransaction(
45
+ account.currency,
34
46
  {
35
- recipient: transaction.recipient,
36
- amount: transaction.amount,
37
- fee: fee,
47
+ address: partyId,
38
48
  },
49
+ params,
39
50
  );
51
+ const transactionSignature = await signer.signTransaction(derivationPath, hash);
40
52
 
41
- const transactionSignature = await signer.signTransaction(
42
- derivationPath,
43
- serializedTransaction,
44
- );
45
-
46
- return combine(serializedTransaction, transactionSignature);
53
+ return combine(serializedTransaction, `${transactionSignature}__PARTY__${partyId}`);
47
54
  });
48
55
 
49
56
  o.next({
@@ -64,7 +71,6 @@ export const buildSignOperation =
64
71
  senders: [account.freshAddress],
65
72
  recipients: [transaction.recipient],
66
73
  date: new Date(),
67
- transactionSequenceNumber: nextSequenceNumber,
68
74
  extra: {},
69
75
  };
70
76
 
@@ -0,0 +1,180 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { AccountShapeInfo } from "@ledgerhq/coin-framework/bridge/jsHelpers";
3
+ import {
4
+ getDerivationModesForCurrency,
5
+ getDerivationScheme,
6
+ runDerivationScheme,
7
+ } from "@ledgerhq/coin-framework/derivation";
8
+ import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
9
+ import { Account, Operation } from "@ledgerhq/types-live";
10
+ import coinConfig from "../config";
11
+ import * as gateway from "../network/gateway";
12
+ import { getAccountShape } from "./sync";
13
+
14
+ const TEST_ADDRESS =
15
+ "b6400f93ea1c74aea86be39b0ccc846fc5de01f12b2ad0d7c31848d6fb6eb6d9::1220c81315e2bf2524a9141bcc6cbf19b61c151e0dcaa95343c0ccf53aed7415c4ec";
16
+ const currency = getCryptoCurrencyById("canton_network");
17
+ const derivationMode = getDerivationModesForCurrency(currency)[0];
18
+ const derivationPath = runDerivationScheme(
19
+ getDerivationScheme({ derivationMode, currency }),
20
+ currency,
21
+ {
22
+ account: 0,
23
+ },
24
+ );
25
+ const ACCOUNT_SHAPE_INFO: AccountShapeInfo = {
26
+ address: TEST_ADDRESS,
27
+ currency,
28
+ derivationMode,
29
+ derivationPath,
30
+ index: 0,
31
+ };
32
+
33
+ describe("sync (devnet)", () => {
34
+ beforeAll(async () => {
35
+ coinConfig.setCoinConfig(() => ({
36
+ gatewayUrl: "https://canton-gateway.api.live.ledger-test.com",
37
+ useGateway: true,
38
+ networkType: "devnet",
39
+ status: {
40
+ type: "active",
41
+ },
42
+ }));
43
+ });
44
+
45
+ describe("getAccountShape", () => {
46
+ it("should fetch account shape for a valid address", async () => {
47
+ const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
48
+
49
+ expect(result).toBeDefined();
50
+ expect(result.id).toBeDefined();
51
+ expect(result.xpub).toBe(TEST_ADDRESS.replace(/:/g, "_"));
52
+ expect(result.blockHeight).toBeGreaterThan(0);
53
+ expect(result.balance).toBeDefined();
54
+ expect(result.spendableBalance).toBeDefined();
55
+ expect(result.operations).toBeDefined();
56
+ expect(result.operationsCount).toBeGreaterThanOrEqual(0);
57
+
58
+ expect(result.balance).toBeInstanceOf(Object);
59
+ expect(result.balance?.toNumber).toBeDefined();
60
+ expect(result.spendableBalance).toBeInstanceOf(Object);
61
+ expect(result.spendableBalance?.toNumber).toBeDefined();
62
+
63
+ expect(result.spendableBalance?.toNumber()).toBeLessThanOrEqual(
64
+ result.balance?.toNumber() || 0,
65
+ );
66
+ });
67
+
68
+ it("should handle address with colons correctly", async () => {
69
+ const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
70
+
71
+ expect(result.xpub).toBe(TEST_ADDRESS.replace(/:/g, "_"));
72
+ });
73
+
74
+ it("should merge operations correctly with initial account", async () => {
75
+ const operations: Operation[] = [
76
+ {
77
+ id: "test-op-1",
78
+ hash: "test-hash-1",
79
+ accountId: "test-account",
80
+ type: "OUT" as const,
81
+ value: new BigNumber(1000000),
82
+ fee: new BigNumber(100000),
83
+ blockHash: "block-hash-1",
84
+ blockHeight: 100,
85
+ senders: [TEST_ADDRESS],
86
+ recipients: ["recipient-1"],
87
+ date: new Date("2023-01-01"),
88
+ transactionSequenceNumber: 100,
89
+ extra: { uid: "uid-1" },
90
+ },
91
+ ];
92
+
93
+ const result = await getAccountShape(
94
+ {
95
+ ...ACCOUNT_SHAPE_INFO,
96
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
97
+ initialAccount: { operations } as Account,
98
+ },
99
+ { paginationConfig: {} },
100
+ );
101
+
102
+ expect(result.operations).toBeDefined();
103
+ expect(result.operationsCount).toBeGreaterThanOrEqual(1);
104
+ const initialOp = result.operations?.find(op => op.id === "test-op-1");
105
+ expect(initialOp).toBeDefined();
106
+ });
107
+
108
+ it("should take locked balance into account when calculating spendable balance", async () => {
109
+ const mockGetBalance = jest.spyOn(gateway, "getBalance");
110
+
111
+ mockGetBalance.mockResolvedValue([
112
+ {
113
+ instrument_id: "Amulet",
114
+ amount: 1000000,
115
+ locked: true,
116
+ },
117
+ ]);
118
+
119
+ const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
120
+
121
+ expect(result.balance?.toNumber()).toBe(1000000);
122
+ expect(result.spendableBalance?.toNumber()).toBe(0);
123
+
124
+ mockGetBalance.mockRestore();
125
+ });
126
+
127
+ it("should call getOperations with correct cursor based with initial account", async () => {
128
+ const mockGetOperations = jest.spyOn(gateway, "getOperations");
129
+ const operation: Operation = {
130
+ id: "test-op-1",
131
+ hash: "test-hash-1",
132
+ accountId: "test-account",
133
+ type: "OUT" as const,
134
+ value: new BigNumber(1000000),
135
+ fee: new BigNumber(100000),
136
+ blockHash: "block-hash-1",
137
+ blockHeight: 100,
138
+ senders: [TEST_ADDRESS],
139
+ recipients: ["recipient-1"],
140
+ date: new Date("2023-01-01"),
141
+ transactionSequenceNumber: 100,
142
+ extra: { uid: "uid-1" },
143
+ };
144
+
145
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
146
+ const initialAccount = { operations: [operation] } as Account;
147
+
148
+ const result = await getAccountShape(
149
+ {
150
+ ...ACCOUNT_SHAPE_INFO,
151
+ initialAccount,
152
+ },
153
+ { paginationConfig: {} },
154
+ );
155
+
156
+ expect(mockGetOperations).toHaveBeenCalledWith(TEST_ADDRESS, {
157
+ cursor: (operation.blockHeight || 0) + 1,
158
+ limit: 100,
159
+ });
160
+ expect(result.operations).toBeDefined();
161
+ expect(result.operationsCount).toBeGreaterThan(1);
162
+ });
163
+
164
+ it("should call getOperations with cursor 0 when no initial account", async () => {
165
+ const mockGetOperations = jest.spyOn(gateway, "getOperations");
166
+
167
+ const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
168
+
169
+ expect(result.operations).toBeDefined();
170
+ expect(result.operationsCount).toBeGreaterThanOrEqual(1);
171
+
172
+ expect(mockGetOperations).toHaveBeenCalledWith(TEST_ADDRESS, {
173
+ cursor: 0,
174
+ limit: 100,
175
+ });
176
+
177
+ mockGetOperations.mockRestore();
178
+ });
179
+ });
180
+ });