@ledgerhq/coin-casper 1.7.3 → 2.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.unimportedrc.json +11 -35
  3. package/CHANGELOG.md +14 -0
  4. package/jest.config.js +2 -5
  5. package/lib/api/index.d.ts +8 -6
  6. package/lib/api/index.d.ts.map +1 -1
  7. package/lib/api/index.integ.test.js +12 -3
  8. package/lib/api/index.integ.test.js.map +1 -1
  9. package/lib/api/index.js +53 -91
  10. package/lib/api/index.js.map +1 -1
  11. package/lib/api/index.test.d.ts +2 -0
  12. package/lib/api/index.test.d.ts.map +1 -0
  13. package/lib/api/index.test.js +274 -0
  14. package/lib/api/index.test.js.map +1 -0
  15. package/lib/api/types.d.ts +2 -67
  16. package/lib/api/types.d.ts.map +1 -1
  17. package/lib/bridge/bridgeHelpers/accountShape.d.ts.map +1 -1
  18. package/lib/bridge/bridgeHelpers/accountShape.js +5 -7
  19. package/lib/bridge/bridgeHelpers/accountShape.js.map +1 -1
  20. package/lib/bridge/bridgeHelpers/accountShape.test.d.ts +2 -0
  21. package/lib/bridge/bridgeHelpers/accountShape.test.d.ts.map +1 -0
  22. package/lib/bridge/bridgeHelpers/accountShape.test.js +94 -0
  23. package/lib/bridge/bridgeHelpers/accountShape.test.js.map +1 -0
  24. package/lib/bridge/bridgeHelpers/addresses.d.ts +3 -9
  25. package/lib/bridge/bridgeHelpers/addresses.d.ts.map +1 -1
  26. package/lib/bridge/bridgeHelpers/addresses.js +5 -62
  27. package/lib/bridge/bridgeHelpers/addresses.js.map +1 -1
  28. package/lib/bridge/bridgeHelpers/txn.d.ts +2 -2
  29. package/lib/bridge/bridgeHelpers/txn.d.ts.map +1 -1
  30. package/lib/bridge/bridgeHelpers/txn.js +9 -11
  31. package/lib/bridge/bridgeHelpers/txn.js.map +1 -1
  32. package/lib/bridge/bridgeHelpers/txn.test.d.ts +2 -0
  33. package/lib/bridge/bridgeHelpers/txn.test.d.ts.map +1 -0
  34. package/lib/bridge/bridgeHelpers/txn.test.js +306 -0
  35. package/lib/bridge/bridgeHelpers/txn.test.js.map +1 -0
  36. package/lib/bridge/broadcast.d.ts.map +1 -1
  37. package/lib/bridge/broadcast.js +7 -6
  38. package/lib/bridge/broadcast.js.map +1 -1
  39. package/lib/bridge/broadcast.test.d.ts +2 -0
  40. package/lib/bridge/broadcast.test.d.ts.map +1 -0
  41. package/lib/bridge/broadcast.test.js +72 -0
  42. package/lib/bridge/broadcast.test.js.map +1 -0
  43. package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -1
  44. package/lib/bridge/buildOptimisticOperation.js +2 -0
  45. package/lib/bridge/buildOptimisticOperation.js.map +1 -1
  46. package/lib/bridge/buildOptimisticOperation.test.d.ts +2 -0
  47. package/lib/bridge/buildOptimisticOperation.test.d.ts.map +1 -0
  48. package/lib/bridge/buildOptimisticOperation.test.js +76 -0
  49. package/lib/bridge/buildOptimisticOperation.test.js.map +1 -0
  50. package/lib/bridge/createTransaction.test.d.ts +2 -0
  51. package/lib/bridge/createTransaction.test.d.ts.map +1 -0
  52. package/lib/bridge/createTransaction.test.js +41 -0
  53. package/lib/bridge/createTransaction.test.js.map +1 -0
  54. package/lib/bridge/deviceTransactionConfig.d.ts.map +1 -1
  55. package/lib/bridge/deviceTransactionConfig.js +13 -0
  56. package/lib/bridge/deviceTransactionConfig.js.map +1 -1
  57. package/lib/bridge/deviceTransactionConfig.test.d.ts +2 -0
  58. package/lib/bridge/deviceTransactionConfig.test.d.ts.map +1 -0
  59. package/lib/bridge/deviceTransactionConfig.test.js +148 -0
  60. package/lib/bridge/deviceTransactionConfig.test.js.map +1 -0
  61. package/lib/bridge/estimateMaxSpendable.test.d.ts +2 -0
  62. package/lib/bridge/estimateMaxSpendable.test.d.ts.map +1 -0
  63. package/lib/bridge/estimateMaxSpendable.test.js +133 -0
  64. package/lib/bridge/estimateMaxSpendable.test.js.map +1 -0
  65. package/lib/bridge/getTransactionStatus.test.d.ts +2 -0
  66. package/lib/bridge/getTransactionStatus.test.d.ts.map +1 -0
  67. package/lib/bridge/getTransactionStatus.test.js +214 -0
  68. package/lib/bridge/getTransactionStatus.test.js.map +1 -0
  69. package/lib/bridge/index.d.ts +2 -1
  70. package/lib/bridge/index.d.ts.map +1 -1
  71. package/lib/bridge/index.js +3 -1
  72. package/lib/bridge/index.js.map +1 -1
  73. package/lib/bridge/prepareTransaction.js +1 -1
  74. package/lib/bridge/prepareTransaction.js.map +1 -1
  75. package/lib/bridge/prepareTransaction.test.d.ts +2 -0
  76. package/lib/bridge/prepareTransaction.test.d.ts.map +1 -0
  77. package/lib/bridge/prepareTransaction.test.js +159 -0
  78. package/lib/bridge/prepareTransaction.test.js.map +1 -0
  79. package/lib/bridge/signOperation.d.ts.map +1 -1
  80. package/lib/bridge/signOperation.js +14 -12
  81. package/lib/bridge/signOperation.js.map +1 -1
  82. package/lib/bridge/transaction.test.d.ts +2 -0
  83. package/lib/bridge/transaction.test.d.ts.map +1 -0
  84. package/lib/bridge/transaction.test.js +179 -0
  85. package/lib/bridge/transaction.test.js.map +1 -0
  86. package/lib/common-logic/utils.additional.test.d.ts +2 -0
  87. package/lib/common-logic/utils.additional.test.d.ts.map +1 -0
  88. package/lib/common-logic/utils.additional.test.js +58 -0
  89. package/lib/common-logic/utils.additional.test.js.map +1 -0
  90. package/lib/common-logic/utils.unit.test.js +6 -4
  91. package/lib/common-logic/utils.unit.test.js.map +1 -1
  92. package/lib/config.d.ts +10 -0
  93. package/lib/config.d.ts.map +1 -0
  94. package/lib/config.js +16 -0
  95. package/lib/config.js.map +1 -0
  96. package/lib/consts.d.ts +3 -0
  97. package/lib/consts.d.ts.map +1 -1
  98. package/lib/consts.js +5 -1
  99. package/lib/consts.js.map +1 -1
  100. package/lib/hw-signMessage.test.d.ts +2 -0
  101. package/lib/hw-signMessage.test.d.ts.map +1 -0
  102. package/lib/hw-signMessage.test.js +80 -0
  103. package/lib/hw-signMessage.test.js.map +1 -0
  104. package/lib/signer/getAddress.js +1 -1
  105. package/lib/signer/getAddress.js.map +1 -1
  106. package/lib/signer/getAddress.test.d.ts +2 -0
  107. package/lib/signer/getAddress.test.d.ts.map +1 -0
  108. package/lib/signer/getAddress.test.js +133 -0
  109. package/lib/signer/getAddress.test.js.map +1 -0
  110. package/lib/test/bot-specs.d.ts.map +1 -1
  111. package/lib/test/bot-specs.js +1 -0
  112. package/lib/test/bot-specs.js.map +1 -1
  113. package/lib/test/fixtures.d.ts +131 -0
  114. package/lib/test/fixtures.d.ts.map +1 -0
  115. package/lib/test/fixtures.js +395 -0
  116. package/lib/test/fixtures.js.map +1 -0
  117. package/lib/test/index.d.ts +2 -0
  118. package/lib/test/index.d.ts.map +1 -1
  119. package/lib/test/index.js +2 -0
  120. package/lib/test/index.js.map +1 -1
  121. package/lib/test/speculos-deviceActions.d.ts.map +1 -1
  122. package/lib/test/speculos-deviceActions.js +4 -3
  123. package/lib/test/speculos-deviceActions.js.map +1 -1
  124. package/lib-es/api/index.d.ts +8 -6
  125. package/lib-es/api/index.d.ts.map +1 -1
  126. package/lib-es/api/index.integ.test.js +13 -4
  127. package/lib-es/api/index.integ.test.js.map +1 -1
  128. package/lib-es/api/index.js +51 -90
  129. package/lib-es/api/index.js.map +1 -1
  130. package/lib-es/api/index.test.d.ts +2 -0
  131. package/lib-es/api/index.test.d.ts.map +1 -0
  132. package/lib-es/api/index.test.js +269 -0
  133. package/lib-es/api/index.test.js.map +1 -0
  134. package/lib-es/api/types.d.ts +2 -67
  135. package/lib-es/api/types.d.ts.map +1 -1
  136. package/lib-es/bridge/bridgeHelpers/accountShape.d.ts.map +1 -1
  137. package/lib-es/bridge/bridgeHelpers/accountShape.js +6 -8
  138. package/lib-es/bridge/bridgeHelpers/accountShape.js.map +1 -1
  139. package/lib-es/bridge/bridgeHelpers/accountShape.test.d.ts +2 -0
  140. package/lib-es/bridge/bridgeHelpers/accountShape.test.d.ts.map +1 -0
  141. package/lib-es/bridge/bridgeHelpers/accountShape.test.js +89 -0
  142. package/lib-es/bridge/bridgeHelpers/accountShape.test.js.map +1 -0
  143. package/lib-es/bridge/bridgeHelpers/addresses.d.ts +3 -9
  144. package/lib-es/bridge/bridgeHelpers/addresses.d.ts.map +1 -1
  145. package/lib-es/bridge/bridgeHelpers/addresses.js +5 -60
  146. package/lib-es/bridge/bridgeHelpers/addresses.js.map +1 -1
  147. package/lib-es/bridge/bridgeHelpers/txn.d.ts +2 -2
  148. package/lib-es/bridge/bridgeHelpers/txn.d.ts.map +1 -1
  149. package/lib-es/bridge/bridgeHelpers/txn.js +10 -12
  150. package/lib-es/bridge/bridgeHelpers/txn.js.map +1 -1
  151. package/lib-es/bridge/bridgeHelpers/txn.test.d.ts +2 -0
  152. package/lib-es/bridge/bridgeHelpers/txn.test.d.ts.map +1 -0
  153. package/lib-es/bridge/bridgeHelpers/txn.test.js +278 -0
  154. package/lib-es/bridge/bridgeHelpers/txn.test.js.map +1 -0
  155. package/lib-es/bridge/broadcast.d.ts.map +1 -1
  156. package/lib-es/bridge/broadcast.js +8 -7
  157. package/lib-es/bridge/broadcast.js.map +1 -1
  158. package/lib-es/bridge/broadcast.test.d.ts +2 -0
  159. package/lib-es/bridge/broadcast.test.d.ts.map +1 -0
  160. package/lib-es/bridge/broadcast.test.js +70 -0
  161. package/lib-es/bridge/broadcast.test.js.map +1 -0
  162. package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -1
  163. package/lib-es/bridge/buildOptimisticOperation.js +2 -0
  164. package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
  165. package/lib-es/bridge/buildOptimisticOperation.test.d.ts +2 -0
  166. package/lib-es/bridge/buildOptimisticOperation.test.d.ts.map +1 -0
  167. package/lib-es/bridge/buildOptimisticOperation.test.js +74 -0
  168. package/lib-es/bridge/buildOptimisticOperation.test.js.map +1 -0
  169. package/lib-es/bridge/createTransaction.test.d.ts +2 -0
  170. package/lib-es/bridge/createTransaction.test.d.ts.map +1 -0
  171. package/lib-es/bridge/createTransaction.test.js +36 -0
  172. package/lib-es/bridge/createTransaction.test.js.map +1 -0
  173. package/lib-es/bridge/deviceTransactionConfig.d.ts.map +1 -1
  174. package/lib-es/bridge/deviceTransactionConfig.js +13 -0
  175. package/lib-es/bridge/deviceTransactionConfig.js.map +1 -1
  176. package/lib-es/bridge/deviceTransactionConfig.test.d.ts +2 -0
  177. package/lib-es/bridge/deviceTransactionConfig.test.d.ts.map +1 -0
  178. package/lib-es/bridge/deviceTransactionConfig.test.js +143 -0
  179. package/lib-es/bridge/deviceTransactionConfig.test.js.map +1 -0
  180. package/lib-es/bridge/estimateMaxSpendable.test.d.ts +2 -0
  181. package/lib-es/bridge/estimateMaxSpendable.test.d.ts.map +1 -0
  182. package/lib-es/bridge/estimateMaxSpendable.test.js +131 -0
  183. package/lib-es/bridge/estimateMaxSpendable.test.js.map +1 -0
  184. package/lib-es/bridge/getTransactionStatus.test.d.ts +2 -0
  185. package/lib-es/bridge/getTransactionStatus.test.d.ts.map +1 -0
  186. package/lib-es/bridge/getTransactionStatus.test.js +212 -0
  187. package/lib-es/bridge/getTransactionStatus.test.js.map +1 -0
  188. package/lib-es/bridge/index.d.ts +2 -1
  189. package/lib-es/bridge/index.d.ts.map +1 -1
  190. package/lib-es/bridge/index.js +3 -1
  191. package/lib-es/bridge/index.js.map +1 -1
  192. package/lib-es/bridge/prepareTransaction.js +1 -1
  193. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  194. package/lib-es/bridge/prepareTransaction.test.d.ts +2 -0
  195. package/lib-es/bridge/prepareTransaction.test.d.ts.map +1 -0
  196. package/lib-es/bridge/prepareTransaction.test.js +157 -0
  197. package/lib-es/bridge/prepareTransaction.test.js.map +1 -0
  198. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  199. package/lib-es/bridge/signOperation.js +16 -14
  200. package/lib-es/bridge/signOperation.js.map +1 -1
  201. package/lib-es/bridge/transaction.test.d.ts +2 -0
  202. package/lib-es/bridge/transaction.test.d.ts.map +1 -0
  203. package/lib-es/bridge/transaction.test.js +154 -0
  204. package/lib-es/bridge/transaction.test.js.map +1 -0
  205. package/lib-es/common-logic/utils.additional.test.d.ts +2 -0
  206. package/lib-es/common-logic/utils.additional.test.d.ts.map +1 -0
  207. package/lib-es/common-logic/utils.additional.test.js +56 -0
  208. package/lib-es/common-logic/utils.additional.test.js.map +1 -0
  209. package/lib-es/common-logic/utils.unit.test.js +7 -5
  210. package/lib-es/common-logic/utils.unit.test.js.map +1 -1
  211. package/lib-es/config.d.ts +10 -0
  212. package/lib-es/config.d.ts.map +1 -0
  213. package/lib-es/config.js +11 -0
  214. package/lib-es/config.js.map +1 -0
  215. package/lib-es/consts.d.ts +3 -0
  216. package/lib-es/consts.d.ts.map +1 -1
  217. package/lib-es/consts.js +4 -0
  218. package/lib-es/consts.js.map +1 -1
  219. package/lib-es/hw-signMessage.test.d.ts +2 -0
  220. package/lib-es/hw-signMessage.test.d.ts.map +1 -0
  221. package/lib-es/hw-signMessage.test.js +78 -0
  222. package/lib-es/hw-signMessage.test.js.map +1 -0
  223. package/lib-es/signer/getAddress.js +2 -2
  224. package/lib-es/signer/getAddress.js.map +1 -1
  225. package/lib-es/signer/getAddress.test.d.ts +2 -0
  226. package/lib-es/signer/getAddress.test.d.ts.map +1 -0
  227. package/lib-es/signer/getAddress.test.js +105 -0
  228. package/lib-es/signer/getAddress.test.js.map +1 -0
  229. package/lib-es/test/bot-specs.d.ts.map +1 -1
  230. package/lib-es/test/bot-specs.js +1 -0
  231. package/lib-es/test/bot-specs.js.map +1 -1
  232. package/lib-es/test/fixtures.d.ts +131 -0
  233. package/lib-es/test/fixtures.d.ts.map +1 -0
  234. package/lib-es/test/fixtures.js +381 -0
  235. package/lib-es/test/fixtures.js.map +1 -0
  236. package/lib-es/test/index.d.ts +2 -0
  237. package/lib-es/test/index.d.ts.map +1 -1
  238. package/lib-es/test/index.js +2 -0
  239. package/lib-es/test/index.js.map +1 -1
  240. package/lib-es/test/speculos-deviceActions.d.ts.map +1 -1
  241. package/lib-es/test/speculos-deviceActions.js +5 -4
  242. package/lib-es/test/speculos-deviceActions.js.map +1 -1
  243. package/package.json +17 -12
  244. package/src/api/index.integ.test.ts +14 -4
  245. package/src/api/index.test.ts +386 -0
  246. package/src/api/index.ts +59 -117
  247. package/src/api/types.ts +2 -75
  248. package/src/bridge/bridgeHelpers/accountShape.test.ts +122 -0
  249. package/src/bridge/bridgeHelpers/accountShape.ts +7 -9
  250. package/src/bridge/bridgeHelpers/addresses.ts +6 -73
  251. package/src/bridge/bridgeHelpers/txn.test.ts +339 -0
  252. package/src/bridge/bridgeHelpers/txn.ts +18 -18
  253. package/src/bridge/broadcast.test.ts +89 -0
  254. package/src/bridge/broadcast.ts +9 -7
  255. package/src/bridge/buildOptimisticOperation.test.ts +89 -0
  256. package/src/bridge/buildOptimisticOperation.ts +2 -0
  257. package/src/bridge/createTransaction.test.ts +43 -0
  258. package/src/bridge/deviceTransactionConfig.test.ts +171 -0
  259. package/src/bridge/deviceTransactionConfig.ts +14 -0
  260. package/src/bridge/estimateMaxSpendable.test.ts +155 -0
  261. package/src/bridge/getTransactionStatus.test.ts +264 -0
  262. package/src/bridge/index.ts +8 -1
  263. package/src/bridge/prepareTransaction.test.ts +174 -0
  264. package/src/bridge/prepareTransaction.ts +1 -1
  265. package/src/bridge/signOperation.ts +16 -25
  266. package/src/bridge/transaction.test.ts +182 -0
  267. package/src/common-logic/utils.additional.test.ts +75 -0
  268. package/src/common-logic/utils.unit.test.ts +9 -7
  269. package/src/config.ts +22 -0
  270. package/src/consts.ts +5 -0
  271. package/src/hw-signMessage.test.ts +123 -0
  272. package/src/signer/getAddress.test.ts +134 -0
  273. package/src/signer/getAddress.ts +2 -2
  274. package/src/test/bot-specs.ts +1 -0
  275. package/src/test/fixtures.ts +448 -0
  276. package/src/test/index.ts +2 -0
  277. package/src/test/speculos-deviceActions.ts +6 -4
  278. package/tsconfig.json +1 -4
package/src/api/index.ts CHANGED
@@ -1,35 +1,33 @@
1
1
  import { log } from "@ledgerhq/logs";
2
2
 
3
- import {
4
- NDeployMessagePutResponse,
5
- IndexerResponseRoot,
6
- ITxnHistoryData,
7
- NAccountBalance,
8
- NAccountInfo,
9
- NNetworkStatusResponse,
10
- NodeResponseRoot,
11
- NodeRPCPayload,
12
- NStateRootHashResponse,
13
- } from "./types";
3
+ import { IndexerResponseRoot, ITxnHistoryData, RpcError } from "./types";
14
4
 
15
5
  import network from "@ledgerhq/live-network";
16
- import { AccessRights, CLURef, DeployUtil } from "casper-js-sdk";
17
- import { getEnv } from "@ledgerhq/live-env";
6
+ import { AccountIdentifier, HttpHandler, PublicKey, RpcClient, Transaction } from "casper-js-sdk";
7
+ import { getCoinConfig } from "../config";
8
+ import BigNumber from "bignumber.js";
9
+ import { NodeErrorCodeAccountNotFound, NodeErrorCodeQueryFailed } from "../consts";
18
10
 
19
11
  const getCasperIndexerURL = (path: string): string => {
20
- const baseUrl = getEnv("API_CASPER_INDEXER_ENDPOINT");
12
+ const baseUrl = getCoinConfig().infra.API_CASPER_INDEXER;
21
13
  if (!baseUrl) throw new Error("API base URL not available");
22
14
 
23
- return `${baseUrl}${path}`;
15
+ return new URL(path, baseUrl).toString();
24
16
  };
25
17
 
26
18
  const getCasperNodeURL = (): string => {
27
- const baseUrl = getEnv("API_CASPER_NODE_ENDPOINT");
19
+ const baseUrl = getCoinConfig().infra.API_CASPER_NODE_ENDPOINT;
28
20
  if (!baseUrl) throw new Error("API base URL not available");
29
21
 
30
22
  return baseUrl;
31
23
  };
32
24
 
25
+ export const getCasperNodeRpcClient = (): RpcClient => {
26
+ const url = getCasperNodeURL();
27
+ const handler = new HttpHandler(url);
28
+ return new RpcClient(handler);
29
+ };
30
+
33
31
  const casperIndexerWrapper = async <T>(path: string) => {
34
32
  const url = getCasperIndexerURL(path);
35
33
 
@@ -51,74 +49,30 @@ const casperIndexerWrapper = async <T>(path: string) => {
51
49
  }
52
50
  };
53
51
 
54
- const casperNodeWrapper = async <T>(payload: NodeRPCPayload) => {
55
- const url = getCasperNodeURL();
56
-
57
- try {
58
- const rawResponse = await network<NodeResponseRoot<T>>({
59
- method: "POST",
60
- url,
61
- data: payload,
62
- });
63
- log("http", `${url} - ${payload.method}`);
64
-
65
- const { data, status } = rawResponse;
66
-
67
- if (status >= 300) {
68
- log("http", `${url} - Status: ${status}`, data);
69
- throw new Error(`HTTP error: ${status}`);
70
- }
71
-
72
- if (data.error) {
73
- const errorMessage = data.error.message + ". " + data.error.data || "Unknown error";
74
- log("http", `${payload.method} - ${errorMessage}`);
75
- throw new Error(`Casper node error: ${errorMessage}`);
76
- }
77
-
78
- if (!data.result) {
79
- throw new Error(`Casper node returned no result for method: ${payload.method}`);
80
- }
81
-
82
- return data.result;
83
- } catch (error) {
84
- log("error", `Failed to execute ${payload.method}`, error);
85
- throw error instanceof Error
86
- ? error
87
- : new Error(`Unknown error during Casper node request: ${String(error)}`);
88
- }
89
- };
90
-
91
52
  export const fetchAccountStateInfo = async (
92
53
  publicKey: string,
93
54
  ): Promise<{
94
- purseUref: CLURef | undefined;
55
+ purseUref: string | undefined;
95
56
  accountHash: string | undefined;
96
57
  }> => {
58
+ const client = getCasperNodeRpcClient();
97
59
  try {
98
- const accountStateInfo = await casperNodeWrapper<NAccountInfo>({
99
- jsonrpc: "2.0",
100
- method: "state_get_account_info",
101
- params: {
102
- public_key: publicKey,
103
- },
104
- id: 1,
105
- });
106
-
107
- if (!accountStateInfo) {
108
- return {
109
- purseUref: undefined,
110
- accountHash: undefined,
111
- };
112
- }
113
-
114
- const accountHash = accountStateInfo.account.account_hash.split("-")[2];
115
- const purseURefString = accountStateInfo.account.main_purse.split("-")[1];
60
+ const { account } = await client.getAccountInfo(
61
+ null,
62
+ new AccountIdentifier(undefined, PublicKey.fromHex(publicKey)),
63
+ );
116
64
 
117
- const uRef = new CLURef(Buffer.from(purseURefString, "hex"), AccessRights.READ_ADD_WRITE);
65
+ const accountHash = account.accountHash.toHex();
66
+ const purseURefString = account.mainPurse.toPrefixedString();
118
67
 
119
- return { purseUref: uRef, accountHash };
68
+ return { purseUref: purseURefString, accountHash };
120
69
  } catch (error) {
121
- if (error instanceof Error && error.message.includes("No such account")) {
70
+ if (
71
+ error instanceof Error &&
72
+ [NodeErrorCodeAccountNotFound, NodeErrorCodeQueryFailed].includes(
73
+ (error as RpcError).statusCode,
74
+ )
75
+ ) {
122
76
  return {
123
77
  purseUref: undefined,
124
78
  accountHash: undefined,
@@ -128,37 +82,27 @@ export const fetchAccountStateInfo = async (
128
82
  }
129
83
  };
130
84
 
131
- export const fetchBalance = async (purseUref: CLURef): Promise<NAccountBalance> => {
132
- const stateRootInfo = await casperNodeWrapper<NStateRootHashResponse>({
133
- jsonrpc: "2.0",
134
- method: "chain_get_state_root_hash",
135
- params: null,
136
- id: 1,
137
- });
138
-
139
- const accountBalance = await casperNodeWrapper<NAccountBalance>({
140
- jsonrpc: "2.0",
141
- method: "state_get_balance",
142
- params: {
143
- purse_uref: purseUref.toFormattedStr(),
144
- state_root_hash: stateRootInfo.state_root_hash,
145
- },
146
- id: 1,
147
- });
148
-
149
- return accountBalance;
85
+ export const fetchBalance = async (purseUref: string): Promise<BigNumber> => {
86
+ const client = getCasperNodeRpcClient();
87
+ try {
88
+ const { stateRootHash } = await client.getStateRootHashLatest();
89
+ const balance = await client.getBalanceByStateRootHash(purseUref, stateRootHash.toHex());
90
+ return new BigNumber(balance.balanceValue.toString());
91
+ } catch (error) {
92
+ log("error", "Failed to fetch balance", error);
93
+ throw error;
94
+ }
150
95
  };
151
96
 
152
- export const fetchNetworkStatus = async (): Promise<NNetworkStatusResponse> => {
153
- const payload: NodeRPCPayload = {
154
- id: 1,
155
- jsonrpc: "2.0",
156
- method: "info_get_status",
157
- params: null,
158
- };
159
- const data = await casperNodeWrapper<NNetworkStatusResponse>(payload);
160
-
161
- return data;
97
+ export const fetchBlockHeight = async (): Promise<number> => {
98
+ const client = getCasperNodeRpcClient();
99
+ try {
100
+ const latestBlock = await client.getLatestBlock();
101
+ return latestBlock.block.height;
102
+ } catch (error) {
103
+ log("error", "Failed to fetch block height", error);
104
+ throw error;
105
+ }
162
106
  };
163
107
 
164
108
  export const fetchTxs = async (addr: string): Promise<ITxnHistoryData[]> => {
@@ -167,29 +111,27 @@ export const fetchTxs = async (addr: string): Promise<ITxnHistoryData[]> => {
167
111
  const limit = 100;
168
112
 
169
113
  let response = await casperIndexerWrapper<ITxnHistoryData>(
170
- `/accounts/${addr}/ledgerlive-deploys?limit=${limit}&page=${page}`,
114
+ `accounts/${addr}/ledgerlive-deploys?limit=${limit}&page=${page}`,
171
115
  );
172
116
  res = res.concat(response.data);
173
117
 
174
118
  while (response.pageCount > page) {
175
119
  page++;
176
120
  response = await casperIndexerWrapper<ITxnHistoryData>(
177
- `/accounts/${addr}/ledgerlive-deploys?limit=${limit}&page=${page}`,
121
+ `accounts/${addr}/ledgerlive-deploys?limit=${limit}&page=${page}`,
178
122
  );
179
123
  res = res.concat(response.data);
180
124
  }
181
125
  return res;
182
126
  };
183
127
 
184
- export const broadcastTx = async (
185
- deploy: DeployUtil.Deploy,
186
- ): Promise<NDeployMessagePutResponse> => {
187
- const response = await casperNodeWrapper<NDeployMessagePutResponse>({
188
- id: 1,
189
- jsonrpc: "2.0",
190
- method: "account_put_deploy",
191
- params: DeployUtil.deployToJson(deploy),
192
- });
193
-
194
- return response;
128
+ export const broadcastTx = async (transaction: Transaction): Promise<string> => {
129
+ const client = getCasperNodeRpcClient();
130
+ try {
131
+ const response = await client.putTransaction(transaction);
132
+ return response.transactionHash.toHex();
133
+ } catch (error) {
134
+ log("error", "Failed to broadcast transaction", error);
135
+ throw error;
136
+ }
195
137
  };
package/src/api/types.ts CHANGED
@@ -1,15 +1,3 @@
1
- export interface NodeRPCPayload {
2
- jsonrpc: "2.0";
3
- method:
4
- | "info_get_status"
5
- | "chain_get_state_root_hash"
6
- | "state_get_account_info"
7
- | "state_get_balance"
8
- | "account_put_deploy";
9
- params: any;
10
- id: 1;
11
- }
12
-
13
1
  export interface IndexerResponseRoot<T> {
14
2
  data: T[];
15
3
  pageCount: number;
@@ -52,67 +40,6 @@ export interface ITxnHistoryData {
52
40
  amount: string;
53
41
  }
54
42
 
55
- export interface NodeResponseRoot<T> {
56
- jsonrpc: string;
57
- id: string;
58
- result?: T;
59
- error?: {
60
- code: number;
61
- message: string;
62
- data: string;
63
- };
64
- }
65
-
66
- export interface NNetworkStatusResponse {
67
- api_version: string;
68
- chainspec_name: string;
69
- starting_state_root_hash: string;
70
- peers: { node_id: string; address: string }[];
71
- last_added_block_info: {
72
- hash: string;
73
- timestamp: string;
74
- era_id: number;
75
- height: number;
76
- state_root_hash: string;
77
- creator: string;
78
- };
79
- our_public_signing_key: string;
80
- round_length?: any;
81
- next_upgrade?: any;
82
- build_version: string;
83
- uptime: string;
84
- }
85
-
86
- export interface NStateRootHashResponse {
87
- api_version: string;
88
- state_root_hash: string;
89
- }
90
-
91
- export interface NAccountBalance {
92
- api_version: string;
93
- balance_value: string;
94
- merkle_proof: string;
95
- }
96
-
97
- export interface NAccountInfo {
98
- api_version: string;
99
- account: {
100
- account_hash: string;
101
- named_keys: any[];
102
- main_purse: string;
103
- associated_keys: {
104
- account_hash: string;
105
- weight: number;
106
- }[];
107
- action_thresholds: {
108
- deployment: number;
109
- key_management: number;
110
- };
111
- };
112
- merkle_proof: string;
113
- }
114
-
115
- export interface NDeployMessagePutResponse {
116
- api_version: string;
117
- deploy_hash: string;
43
+ export interface RpcError extends Error {
44
+ statusCode: number;
118
45
  }
@@ -0,0 +1,122 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { fetchBalance, fetchBlockHeight, fetchAccountStateInfo, fetchTxs } from "../../api/index";
3
+ import { mapTxToOps } from "./txn";
4
+ import { getAccountShape } from "./accountShape";
5
+ import { createMockAccountShapeData } from "../../test/fixtures";
6
+ import { SyncConfig } from "@ledgerhq/types-live";
7
+
8
+ // Mock dependencies
9
+ jest.mock("../../api/index");
10
+ jest.mock("./txn");
11
+
12
+ describe("getAccountShape", () => {
13
+ const {
14
+ mockAddress,
15
+ mockAccountInfo,
16
+ mockAccountId,
17
+ mockBlockHeight,
18
+ mockPurseUref,
19
+ mockAccountHash,
20
+ mockBalance,
21
+ mockTxs,
22
+ mockOperations,
23
+ } = createMockAccountShapeData();
24
+
25
+ // Define a mock SyncConfig as required by the getAccountShape function
26
+ const mockSyncConfig: SyncConfig = {
27
+ paginationConfig: {},
28
+ };
29
+
30
+ beforeEach(() => {
31
+ jest.clearAllMocks();
32
+
33
+ // Default mock implementations
34
+ (fetchAccountStateInfo as jest.Mock).mockResolvedValue({
35
+ purseUref: mockPurseUref,
36
+ accountHash: mockAccountHash,
37
+ });
38
+
39
+ (fetchBlockHeight as jest.Mock).mockResolvedValue(mockBlockHeight);
40
+
41
+ (fetchBalance as jest.Mock).mockResolvedValue(mockBalance);
42
+
43
+ (fetchTxs as jest.Mock).mockResolvedValue(mockTxs);
44
+
45
+ (mapTxToOps as jest.Mock).mockImplementation(() => () => mockOperations);
46
+ });
47
+
48
+ test("should return the correct account shape for an account with balance", async () => {
49
+ const accountShape = await getAccountShape(mockAccountInfo, mockSyncConfig);
50
+
51
+ expect(fetchAccountStateInfo).toHaveBeenCalledWith(mockAddress);
52
+ expect(fetchBlockHeight).toHaveBeenCalled();
53
+ expect(fetchBalance).toHaveBeenCalledWith(mockPurseUref);
54
+ expect(fetchTxs).toHaveBeenCalledWith(mockAddress);
55
+ expect(mapTxToOps).toHaveBeenCalledWith(mockAccountId, mockAccountHash);
56
+
57
+ expect(accountShape).toEqual({
58
+ id: mockAccountId,
59
+ balance: mockBalance,
60
+ spendableBalance: mockBalance,
61
+ operations: mockOperations,
62
+ blockHeight: mockBlockHeight,
63
+ });
64
+ });
65
+
66
+ test("should return account with zero balance when purseUref is not found", async () => {
67
+ (fetchAccountStateInfo as jest.Mock).mockResolvedValue({
68
+ purseUref: undefined,
69
+ accountHash: mockAccountHash,
70
+ });
71
+
72
+ const accountShape = await getAccountShape(mockAccountInfo, mockSyncConfig);
73
+
74
+ expect(fetchAccountStateInfo).toHaveBeenCalledWith(mockAddress);
75
+ expect(fetchBlockHeight).toHaveBeenCalled();
76
+ expect(fetchBalance).not.toHaveBeenCalled();
77
+ expect(fetchTxs).not.toHaveBeenCalled();
78
+
79
+ expect(accountShape).toEqual({
80
+ id: mockAccountId,
81
+ balance: new BigNumber(0),
82
+ spendableBalance: new BigNumber(0),
83
+ operations: [],
84
+ blockHeight: mockBlockHeight,
85
+ });
86
+ });
87
+
88
+ test("should return account with operations even when accountHash is not found", async () => {
89
+ (fetchAccountStateInfo as jest.Mock).mockResolvedValue({
90
+ purseUref: mockPurseUref,
91
+ accountHash: undefined,
92
+ });
93
+
94
+ const accountShape = await getAccountShape(mockAccountInfo, mockSyncConfig);
95
+
96
+ expect(fetchAccountStateInfo).toHaveBeenCalledWith(mockAddress);
97
+ expect(fetchBlockHeight).toHaveBeenCalled();
98
+ expect(fetchBalance).toHaveBeenCalledWith(mockPurseUref);
99
+ expect(fetchTxs).toHaveBeenCalledWith(mockAddress);
100
+ expect(mapTxToOps).toHaveBeenCalledWith(mockAccountId, "");
101
+
102
+ expect(accountShape).toEqual({
103
+ id: mockAccountId,
104
+ balance: mockBalance,
105
+ spendableBalance: mockBalance,
106
+ operations: mockOperations,
107
+ blockHeight: mockBlockHeight,
108
+ });
109
+ });
110
+
111
+ test("should handle API errors appropriately", async () => {
112
+ const errorMessage = "API Error";
113
+ (fetchAccountStateInfo as jest.Mock).mockRejectedValue(new Error(errorMessage));
114
+
115
+ await expect(getAccountShape(mockAccountInfo, mockSyncConfig)).rejects.toThrow(errorMessage);
116
+
117
+ expect(fetchAccountStateInfo).toHaveBeenCalledWith(mockAddress);
118
+ expect(fetchBlockHeight).not.toHaveBeenCalled();
119
+ expect(fetchBalance).not.toHaveBeenCalled();
120
+ expect(fetchTxs).not.toHaveBeenCalled();
121
+ });
122
+ });
@@ -3,9 +3,9 @@ import { log } from "@ledgerhq/logs";
3
3
  import BigNumber from "bignumber.js";
4
4
  import { encodeAccountId } from "@ledgerhq/coin-framework/account/index";
5
5
  import { GetAccountShape } from "@ledgerhq/coin-framework/bridge/jsHelpers";
6
- import { fetchBalance, fetchNetworkStatus, fetchTxs, fetchAccountStateInfo } from "../../api/index";
6
+ import { fetchBalance, fetchBlockHeight, fetchAccountStateInfo, fetchTxs } from "../../api/index";
7
7
  import { mapTxToOps } from "./txn";
8
- import { NAccountBalance, ITxnHistoryData } from "../../api/types";
8
+ import { ITxnHistoryData } from "../../api/types";
9
9
 
10
10
  export const getAccountShape: GetAccountShape = async info => {
11
11
  const { address, currency, derivationMode } = info;
@@ -22,18 +22,16 @@ export const getAccountShape: GetAccountShape = async info => {
22
22
 
23
23
  const { purseUref, accountHash } = await fetchAccountStateInfo(address);
24
24
 
25
- const blockHeight = await fetchNetworkStatus();
25
+ const blockHeight = await fetchBlockHeight();
26
26
 
27
- const balance: NAccountBalance = purseUref
28
- ? await fetchBalance(purseUref)
29
- : { balance_value: "0", api_version: "", merkle_proof: "" };
27
+ const balance = purseUref ? await fetchBalance(purseUref) : new BigNumber(0);
30
28
  const txs: ITxnHistoryData[] = purseUref ? await fetchTxs(address) : [];
31
29
 
32
30
  return {
33
31
  id: accountId,
34
- balance: new BigNumber(balance.balance_value),
35
- spendableBalance: new BigNumber(balance.balance_value),
32
+ balance,
33
+ spendableBalance: balance,
36
34
  operations: flatMap(txs, mapTxToOps(accountId, accountHash ?? "")),
37
- blockHeight: blockHeight.last_added_block_info.height,
35
+ blockHeight,
38
36
  };
39
37
  };
@@ -1,7 +1,5 @@
1
1
  import { Account } from "@ledgerhq/types-live";
2
- import { blake2bFinal, blake2bInit, blake2bUpdate } from "blakejs";
3
- import { CLPublicKey, CLPublicKeyTag } from "casper-js-sdk";
4
- import { CASPER_CHECKSUM_HEX_LEN } from "../../consts";
2
+ import { PublicKey, KeyAlgorithm } from "casper-js-sdk";
5
3
 
6
4
  export const getAddress = (
7
5
  a: Account,
@@ -11,84 +9,19 @@ export const getAddress = (
11
9
  } => ({ address: a.freshAddress, derivationPath: a.freshAddressPath });
12
10
 
13
11
  export function isAddressValid(pubKey: string): boolean {
12
+ const checksummed = pubKey.toLowerCase() !== pubKey && pubKey.toUpperCase() !== pubKey;
14
13
  try {
15
- casperGetCLPublicKey(pubKey);
14
+ PublicKey.fromHex(pubKey, checksummed).accountHash().toHex();
16
15
  return true;
17
16
  } catch (err) {
18
17
  return false;
19
18
  }
20
19
  }
21
20
 
22
- export function casperGetCLPublicKey(pubkey: string): CLPublicKey {
23
- let checksummed = true;
24
-
25
- if (pubkey.toLowerCase() === pubkey) checksummed = false;
26
- if (pubkey.toUpperCase() === pubkey) checksummed = false;
27
-
28
- return CLPublicKey.fromHex(pubkey, checksummed);
29
- }
30
-
31
- export function casperAccountHashFromPublicKey(
32
- pubKey: string,
33
- checksummed: boolean = false,
34
- ): string {
35
- const accountHashBuff = casperGetCLPublicKey(pubKey).toAccountHash();
36
-
37
- if (checksummed === false) return Buffer.from(accountHashBuff).toString("hex");
38
-
39
- return casperAddressEncode(Buffer.from(accountHashBuff));
21
+ export function casperAccountHashFromPublicKey(pubKey: string): string {
22
+ return PublicKey.fromHex(pubKey).accountHash().toHex();
40
23
  }
41
24
 
42
- export function casperAddressFromPubKey(pubkey: Buffer, keySig: CLPublicKeyTag): string {
25
+ export function casperAddressFromPubKey(pubkey: Buffer, keySig: KeyAlgorithm): string {
43
26
  return `${keySig.toString().padStart(2, "0")}${Buffer.from(pubkey).toString("hex")}`;
44
27
  }
45
-
46
- function numberToBin(num: number) {
47
- let binStr = (num >>> 0).toString(2);
48
- while (binStr.length < 8) {
49
- binStr = "0" + binStr;
50
- }
51
- return binStr.split("").reverse().join("");
52
- }
53
-
54
- function bytesToBitsString(buf: Buffer | Uint8Array) {
55
- const bitsArray: string[] = [];
56
-
57
- for (const num of buf) {
58
- const bin = numberToBin(num);
59
- bitsArray.push(bin);
60
- }
61
-
62
- return bitsArray.join("");
63
- }
64
-
65
- /**
66
- * Returns the bytes encoded as hexadecimal with mixed-case based checksums following a scheme
67
- * similar to [EIP-55](https://eips.ethereum.org/EIPS/eip-55).
68
- */
69
- export function casperAddressEncode(inputBytes: Buffer): string {
70
- const context = blake2bInit(CASPER_CHECKSUM_HEX_LEN);
71
- blake2bUpdate(context, inputBytes);
72
- const blakeHash = blake2bFinal(context);
73
-
74
- const nibbles = inputBytes
75
- .toString("hex")
76
- .split("")
77
- .map(v => parseInt(v, 16));
78
-
79
- const bitsArray = bytesToBitsString(blakeHash);
80
-
81
- const res: Array<number | string> = [];
82
-
83
- let steamIndex = -1;
84
- for (const num of nibbles) {
85
- if (num < 10) res.push(num);
86
- else {
87
- steamIndex += 1;
88
- if (parseInt(bitsArray[steamIndex], 10)) res.push(num.toString(16).toUpperCase());
89
- else res.push(num.toString(16).toLowerCase());
90
- }
91
- }
92
-
93
- return res.join("");
94
- }