@ledgerhq/coin-vechain 3.0.0 → 4.0.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 (249) hide show
  1. package/.unimportedrc.json +2 -1
  2. package/CHANGELOG.md +42 -2699
  3. package/lib/api/index.d.ts +2 -2
  4. package/lib/api/index.d.ts.map +1 -1
  5. package/lib/api/index.js +25 -22
  6. package/lib/api/index.js.map +1 -1
  7. package/lib/bridge/broadcast.d.ts.map +1 -1
  8. package/lib/bridge/broadcast.js +2 -1
  9. package/lib/bridge/broadcast.js.map +1 -1
  10. package/lib/bridge/createTransaction.js +1 -1
  11. package/lib/bridge/createTransaction.js.map +1 -1
  12. package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -1
  13. package/lib/bridge/estimateMaxSpendable.js +2 -1
  14. package/lib/bridge/estimateMaxSpendable.js.map +1 -1
  15. package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
  16. package/lib/bridge/getTransactionStatus.js +2 -1
  17. package/lib/bridge/getTransactionStatus.js.map +1 -1
  18. package/lib/bridge/prepareTransaction.d.ts.map +1 -1
  19. package/lib/bridge/prepareTransaction.js +4 -2
  20. package/lib/bridge/prepareTransaction.js.map +1 -1
  21. package/lib/bridge/synchronisation.d.ts.map +1 -1
  22. package/lib/bridge/synchronisation.js +6 -4
  23. package/lib/bridge/synchronisation.js.map +1 -1
  24. package/lib/common-logic/calculateGasFees.d.ts +2 -1
  25. package/lib/common-logic/calculateGasFees.d.ts.map +1 -1
  26. package/lib/common-logic/calculateGasFees.js +3 -3
  27. package/lib/common-logic/calculateGasFees.js.map +1 -1
  28. package/lib/common-logic/calculateTransactionInfo.d.ts +2 -1
  29. package/lib/common-logic/calculateTransactionInfo.d.ts.map +1 -1
  30. package/lib/common-logic/calculateTransactionInfo.js +2 -2
  31. package/lib/common-logic/calculateTransactionInfo.js.map +1 -1
  32. package/lib/common-logic/estimateGas.d.ts +2 -1
  33. package/lib/common-logic/estimateGas.d.ts.map +1 -1
  34. package/lib/common-logic/estimateGas.js +2 -2
  35. package/lib/common-logic/estimateGas.js.map +1 -1
  36. package/lib/common-logic/getThorClient.d.ts +2 -1
  37. package/lib/common-logic/getThorClient.d.ts.map +1 -1
  38. package/lib/common-logic/getThorClient.js +2 -2
  39. package/lib/common-logic/getThorClient.js.map +1 -1
  40. package/lib/common-logic/mapTransfersToOperations.d.ts +3 -2
  41. package/lib/common-logic/mapTransfersToOperations.d.ts.map +1 -1
  42. package/lib/common-logic/mapTransfersToOperations.js +4 -4
  43. package/lib/common-logic/mapTransfersToOperations.js.map +1 -1
  44. package/lib/config.d.ts +10 -4
  45. package/lib/config.d.ts.map +1 -1
  46. package/lib/config.js +9 -5
  47. package/lib/config.js.map +1 -1
  48. package/lib/logic/account/getBalance.d.ts +2 -1
  49. package/lib/logic/account/getBalance.d.ts.map +1 -1
  50. package/lib/logic/account/getBalance.js +3 -2
  51. package/lib/logic/account/getBalance.js.map +1 -1
  52. package/lib/logic/history/getBlock.d.ts +2 -1
  53. package/lib/logic/history/getBlock.d.ts.map +1 -1
  54. package/lib/logic/history/getBlock.js +3 -2
  55. package/lib/logic/history/getBlock.js.map +1 -1
  56. package/lib/logic/history/getBlockInfo.d.ts +2 -1
  57. package/lib/logic/history/getBlockInfo.d.ts.map +1 -1
  58. package/lib/logic/history/getBlockInfo.js +3 -2
  59. package/lib/logic/history/getBlockInfo.js.map +1 -1
  60. package/lib/logic/history/lastBlock.d.ts +2 -1
  61. package/lib/logic/history/lastBlock.d.ts.map +1 -1
  62. package/lib/logic/history/lastBlock.js +4 -3
  63. package/lib/logic/history/lastBlock.js.map +1 -1
  64. package/lib/logic/history/listOperations.d.ts +2 -1
  65. package/lib/logic/history/listOperations.d.ts.map +1 -1
  66. package/lib/logic/history/listOperations.js +5 -4
  67. package/lib/logic/history/listOperations.js.map +1 -1
  68. package/lib/logic/transaction/broadcast.d.ts +2 -1
  69. package/lib/logic/transaction/broadcast.d.ts.map +1 -1
  70. package/lib/logic/transaction/broadcast.js +3 -2
  71. package/lib/logic/transaction/broadcast.js.map +1 -1
  72. package/lib/logic/transaction/combine.d.ts +1 -1
  73. package/lib/logic/transaction/combine.d.ts.map +1 -1
  74. package/lib/logic/transaction/combine.js +4 -1
  75. package/lib/logic/transaction/combine.js.map +1 -1
  76. package/lib/logic/transaction/craftTransaction.d.ts +2 -1
  77. package/lib/logic/transaction/craftTransaction.d.ts.map +1 -1
  78. package/lib/logic/transaction/craftTransaction.js +11 -10
  79. package/lib/logic/transaction/craftTransaction.js.map +1 -1
  80. package/lib/logic/transaction/estimateFees.d.ts +2 -1
  81. package/lib/logic/transaction/estimateFees.d.ts.map +1 -1
  82. package/lib/logic/transaction/estimateFees.js +2 -2
  83. package/lib/logic/transaction/estimateFees.js.map +1 -1
  84. package/lib/network/getBlock.d.ts +2 -1
  85. package/lib/network/getBlock.d.ts.map +1 -1
  86. package/lib/network/getBlock.js +2 -2
  87. package/lib/network/getBlock.js.map +1 -1
  88. package/lib/network/getFees.d.ts +2 -1
  89. package/lib/network/getFees.d.ts.map +1 -1
  90. package/lib/network/getFees.js +2 -2
  91. package/lib/network/getFees.js.map +1 -1
  92. package/lib/network/sdk.d.ts +7 -6
  93. package/lib/network/sdk.d.ts.map +1 -1
  94. package/lib/network/sdk.js +18 -18
  95. package/lib/network/sdk.js.map +1 -1
  96. package/lib/test/context.d.ts +6 -0
  97. package/lib/test/context.d.ts.map +1 -0
  98. package/lib/test/context.js +15 -0
  99. package/lib/test/context.js.map +1 -0
  100. package/lib-es/api/index.d.ts +2 -2
  101. package/lib-es/api/index.d.ts.map +1 -1
  102. package/lib-es/api/index.js +25 -22
  103. package/lib-es/api/index.js.map +1 -1
  104. package/lib-es/bridge/broadcast.d.ts.map +1 -1
  105. package/lib-es/bridge/broadcast.js +2 -1
  106. package/lib-es/bridge/broadcast.js.map +1 -1
  107. package/lib-es/bridge/createTransaction.js +2 -2
  108. package/lib-es/bridge/createTransaction.js.map +1 -1
  109. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -1
  110. package/lib-es/bridge/estimateMaxSpendable.js +2 -1
  111. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
  112. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
  113. package/lib-es/bridge/getTransactionStatus.js +2 -1
  114. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  115. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
  116. package/lib-es/bridge/prepareTransaction.js +4 -2
  117. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  118. package/lib-es/bridge/synchronisation.d.ts.map +1 -1
  119. package/lib-es/bridge/synchronisation.js +6 -4
  120. package/lib-es/bridge/synchronisation.js.map +1 -1
  121. package/lib-es/common-logic/calculateGasFees.d.ts +2 -1
  122. package/lib-es/common-logic/calculateGasFees.d.ts.map +1 -1
  123. package/lib-es/common-logic/calculateGasFees.js +3 -3
  124. package/lib-es/common-logic/calculateGasFees.js.map +1 -1
  125. package/lib-es/common-logic/calculateTransactionInfo.d.ts +2 -1
  126. package/lib-es/common-logic/calculateTransactionInfo.d.ts.map +1 -1
  127. package/lib-es/common-logic/calculateTransactionInfo.js +2 -2
  128. package/lib-es/common-logic/calculateTransactionInfo.js.map +1 -1
  129. package/lib-es/common-logic/estimateGas.d.ts +2 -1
  130. package/lib-es/common-logic/estimateGas.d.ts.map +1 -1
  131. package/lib-es/common-logic/estimateGas.js +2 -2
  132. package/lib-es/common-logic/estimateGas.js.map +1 -1
  133. package/lib-es/common-logic/getThorClient.d.ts +2 -1
  134. package/lib-es/common-logic/getThorClient.d.ts.map +1 -1
  135. package/lib-es/common-logic/getThorClient.js +2 -2
  136. package/lib-es/common-logic/getThorClient.js.map +1 -1
  137. package/lib-es/common-logic/mapTransfersToOperations.d.ts +3 -2
  138. package/lib-es/common-logic/mapTransfersToOperations.d.ts.map +1 -1
  139. package/lib-es/common-logic/mapTransfersToOperations.js +4 -4
  140. package/lib-es/common-logic/mapTransfersToOperations.js.map +1 -1
  141. package/lib-es/config.d.ts +10 -4
  142. package/lib-es/config.d.ts.map +1 -1
  143. package/lib-es/config.js +9 -5
  144. package/lib-es/config.js.map +1 -1
  145. package/lib-es/logic/account/getBalance.d.ts +2 -1
  146. package/lib-es/logic/account/getBalance.d.ts.map +1 -1
  147. package/lib-es/logic/account/getBalance.js +3 -2
  148. package/lib-es/logic/account/getBalance.js.map +1 -1
  149. package/lib-es/logic/history/getBlock.d.ts +2 -1
  150. package/lib-es/logic/history/getBlock.d.ts.map +1 -1
  151. package/lib-es/logic/history/getBlock.js +3 -2
  152. package/lib-es/logic/history/getBlock.js.map +1 -1
  153. package/lib-es/logic/history/getBlockInfo.d.ts +2 -1
  154. package/lib-es/logic/history/getBlockInfo.d.ts.map +1 -1
  155. package/lib-es/logic/history/getBlockInfo.js +3 -2
  156. package/lib-es/logic/history/getBlockInfo.js.map +1 -1
  157. package/lib-es/logic/history/lastBlock.d.ts +2 -1
  158. package/lib-es/logic/history/lastBlock.d.ts.map +1 -1
  159. package/lib-es/logic/history/lastBlock.js +4 -3
  160. package/lib-es/logic/history/lastBlock.js.map +1 -1
  161. package/lib-es/logic/history/listOperations.d.ts +2 -1
  162. package/lib-es/logic/history/listOperations.d.ts.map +1 -1
  163. package/lib-es/logic/history/listOperations.js +5 -4
  164. package/lib-es/logic/history/listOperations.js.map +1 -1
  165. package/lib-es/logic/transaction/broadcast.d.ts +2 -1
  166. package/lib-es/logic/transaction/broadcast.d.ts.map +1 -1
  167. package/lib-es/logic/transaction/broadcast.js +3 -2
  168. package/lib-es/logic/transaction/broadcast.js.map +1 -1
  169. package/lib-es/logic/transaction/combine.d.ts +1 -1
  170. package/lib-es/logic/transaction/combine.d.ts.map +1 -1
  171. package/lib-es/logic/transaction/combine.js +4 -1
  172. package/lib-es/logic/transaction/combine.js.map +1 -1
  173. package/lib-es/logic/transaction/craftTransaction.d.ts +2 -1
  174. package/lib-es/logic/transaction/craftTransaction.d.ts.map +1 -1
  175. package/lib-es/logic/transaction/craftTransaction.js +11 -10
  176. package/lib-es/logic/transaction/craftTransaction.js.map +1 -1
  177. package/lib-es/logic/transaction/estimateFees.d.ts +2 -1
  178. package/lib-es/logic/transaction/estimateFees.d.ts.map +1 -1
  179. package/lib-es/logic/transaction/estimateFees.js +2 -2
  180. package/lib-es/logic/transaction/estimateFees.js.map +1 -1
  181. package/lib-es/network/getBlock.d.ts +2 -1
  182. package/lib-es/network/getBlock.d.ts.map +1 -1
  183. package/lib-es/network/getBlock.js +2 -2
  184. package/lib-es/network/getBlock.js.map +1 -1
  185. package/lib-es/network/getFees.d.ts +2 -1
  186. package/lib-es/network/getFees.d.ts.map +1 -1
  187. package/lib-es/network/getFees.js +2 -2
  188. package/lib-es/network/getFees.js.map +1 -1
  189. package/lib-es/network/sdk.d.ts +7 -6
  190. package/lib-es/network/sdk.d.ts.map +1 -1
  191. package/lib-es/network/sdk.js +18 -18
  192. package/lib-es/network/sdk.js.map +1 -1
  193. package/lib-es/test/context.d.ts +6 -0
  194. package/lib-es/test/context.d.ts.map +1 -0
  195. package/lib-es/test/context.js +11 -0
  196. package/lib-es/test/context.js.map +1 -0
  197. package/package.json +6 -6
  198. package/src/api/index.integ.test.ts +21 -24
  199. package/src/api/index.ts +74 -27
  200. package/src/api/index.unit.test.ts +68 -48
  201. package/src/bridge/broadcast.integ.test.ts +2 -1
  202. package/src/bridge/broadcast.test.ts +1 -1
  203. package/src/bridge/broadcast.ts +2 -1
  204. package/src/bridge/createTransaction.ts +2 -2
  205. package/src/bridge/estimateMaxSpendable.test.ts +19 -3
  206. package/src/bridge/estimateMaxSpendable.ts +2 -0
  207. package/src/bridge/getTransactionStatus.test.ts +11 -6
  208. package/src/bridge/getTransactionStatus.ts +2 -0
  209. package/src/bridge/prepareTransaction.test.ts +5 -1
  210. package/src/bridge/prepareTransaction.ts +4 -2
  211. package/src/bridge/synchronisation.ts +7 -3
  212. package/src/common-logic/calculateGasFees.test.ts +101 -27
  213. package/src/common-logic/calculateGasFees.ts +4 -2
  214. package/src/common-logic/calculateTransactionInfo.test.ts +71 -16
  215. package/src/common-logic/calculateTransactionInfo.ts +3 -1
  216. package/src/common-logic/estimateGas.test.ts +13 -10
  217. package/src/common-logic/estimateGas.ts +3 -1
  218. package/src/common-logic/getThorClient.test.ts +7 -7
  219. package/src/common-logic/getThorClient.ts +3 -3
  220. package/src/common-logic/mapTransfersToOperations.test.ts +48 -13
  221. package/src/common-logic/mapTransfersToOperations.ts +5 -2
  222. package/src/config.test.ts +3 -3
  223. package/src/config.ts +13 -6
  224. package/src/logic/account/getBalance.ts +4 -2
  225. package/src/logic/account/getBalance.unit.test.ts +6 -4
  226. package/src/logic/history/getBlock.ts +4 -2
  227. package/src/logic/history/getBlock.unit.test.ts +8 -5
  228. package/src/logic/history/getBlockInfo.ts +4 -2
  229. package/src/logic/history/getBlockInfo.unit.test.ts +6 -3
  230. package/src/logic/history/lastBlock.ts +5 -3
  231. package/src/logic/history/lastBlock.unit.test.ts +6 -3
  232. package/src/logic/history/listOperations.ts +6 -3
  233. package/src/logic/history/listOperations.unit.test.ts +10 -6
  234. package/src/logic/transaction/broadcast.msw.test.ts +7 -2
  235. package/src/logic/transaction/broadcast.ts +8 -2
  236. package/src/logic/transaction/broadcast.unit.test.ts +6 -3
  237. package/src/logic/transaction/combine.ts +6 -2
  238. package/src/logic/transaction/combine.unit.test.ts +3 -3
  239. package/src/logic/transaction/craftTransaction.ts +16 -9
  240. package/src/logic/transaction/craftTransaction.unit.test.ts +29 -28
  241. package/src/logic/transaction/estimateFees.ts +3 -0
  242. package/src/logic/transaction/estimateFees.unit.test.ts +15 -12
  243. package/src/network/getBlock.ts +3 -2
  244. package/src/network/getBlock.unit.test.ts +11 -6
  245. package/src/network/getFees.ts +6 -3
  246. package/src/network/sdk.integ.test.ts +8 -1
  247. package/src/network/sdk.test.ts +18 -7
  248. package/src/network/sdk.ts +25 -15
  249. package/src/test/context.ts +15 -0
@@ -1,6 +1,7 @@
1
1
  import BigNumber from "bignumber.js";
2
2
  import type { Operation as LegacyOperation } from "@ledgerhq/types-live";
3
3
  import { getLastBlockHeight, getOperations, getTokenOperations } from "../../network";
4
+ import { createMockVechainContext } from "../../test/context";
4
5
  import { listOperations } from "./listOperations";
5
6
 
6
7
  jest.mock("../../network", () => ({
@@ -10,6 +11,7 @@ jest.mock("../../network", () => ({
10
11
  }));
11
12
 
12
13
  const ADDRESS = "0x0fe6688548f0C303932bB197B0A96034f1d74dba";
14
+ const context = createMockVechainContext();
13
15
 
14
16
  function makeLegacyOp(overrides: Partial<LegacyOperation> = {}): LegacyOperation {
15
17
  return {
@@ -41,7 +43,7 @@ describe("listOperations", () => {
41
43
  .mocked(getTokenOperations)
42
44
  .mockResolvedValueOnce([makeLegacyOp({ id: "vtho-op", type: "IN" })]);
43
45
 
44
- const page = await listOperations(ADDRESS, { minHeight: 0 });
46
+ const page = await listOperations(context, ADDRESS, { minHeight: 0 });
45
47
 
46
48
  expect(page.items).toHaveLength(2);
47
49
  expect(page.items.find(op => op.id === "vet-op")?.asset).toEqual({
@@ -67,7 +69,7 @@ describe("listOperations", () => {
67
69
  makeLegacyOp({ id: "vtho-1", date: new Date("2024-01-02T00:00:00Z") }),
68
70
  ]);
69
71
 
70
- const page = await listOperations(ADDRESS, { minHeight: 0 });
72
+ const page = await listOperations(context, ADDRESS, { minHeight: 0 });
71
73
 
72
74
  const ids = page.items.map(op => op.id);
73
75
  expect(ids).toHaveLength(3);
@@ -87,7 +89,7 @@ describe("listOperations", () => {
87
89
  jest.mocked(getOperations).mockResolvedValueOnce([outOp]);
88
90
  jest.mocked(getTokenOperations).mockResolvedValueOnce([]);
89
91
 
90
- const page = await listOperations(ADDRESS, { minHeight: 0 });
92
+ const page = await listOperations(context, ADDRESS, { minHeight: 0 });
91
93
 
92
94
  expect(page.items[0].value).toBe(BigInt("1000000000000000000"));
93
95
  expect(page.items[0].tx.fees).toBe(0n);
@@ -103,7 +105,7 @@ describe("listOperations", () => {
103
105
  jest.mocked(getOperations).mockResolvedValueOnce([]);
104
106
  jest.mocked(getTokenOperations).mockResolvedValueOnce([vthoOut]);
105
107
 
106
- const page = await listOperations(ADDRESS, { minHeight: 0 });
108
+ const page = await listOperations(context, ADDRESS, { minHeight: 0 });
107
109
 
108
110
  expect(page.items[0].value).toBe(BigInt("5000000000000000000"));
109
111
  expect(page.items[0].tx.fees).toBe(BigInt("21000000000000000"));
@@ -112,7 +114,7 @@ describe("listOperations", () => {
112
114
  it("returns an empty page (with a resumable cursor) when the range is already exhausted", async () => {
113
115
  jest.mocked(getLastBlockHeight).mockResolvedValueOnce(50);
114
116
 
115
- const page = await listOperations(ADDRESS, { minHeight: 0, cursor: "100" });
117
+ const page = await listOperations(context, ADDRESS, { minHeight: 0, cursor: "100" });
116
118
 
117
119
  expect(page.items).toEqual([]);
118
120
  expect(getOperations).not.toHaveBeenCalled();
@@ -124,6 +126,8 @@ describe("listOperations", () => {
124
126
  jest.mocked(getOperations).mockRejectedValueOnce(new Error("network down"));
125
127
  jest.mocked(getTokenOperations).mockResolvedValueOnce([]);
126
128
 
127
- await expect(listOperations(ADDRESS, { minHeight: 0 })).rejects.toThrow("network down");
129
+ await expect(listOperations(context, ADDRESS, { minHeight: 0 })).rejects.toThrow(
130
+ "network down",
131
+ );
128
132
  });
129
133
  });
@@ -1,8 +1,13 @@
1
1
  import { http, HttpResponse } from "msw";
2
2
  import { server, TEST_VECHAIN_ENDPOINT } from "../../test/msw.mock";
3
+ import { createMockVechainContext } from "../../test/context";
3
4
  import { broadcast } from "./broadcast";
4
5
 
5
6
  const SUBMIT_URL = `${TEST_VECHAIN_ENDPOINT}/transactions`;
7
+ const context = createMockVechainContext({
8
+ status: { type: "active" },
9
+ node: { url: TEST_VECHAIN_ENDPOINT },
10
+ });
6
11
 
7
12
  beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
8
13
  afterEach(() => server.resetHandlers());
@@ -12,12 +17,12 @@ describe("broadcast via MSW", () => {
12
17
  it("submits the signed raw transaction and returns the transaction id", async () => {
13
18
  server.use(http.post(SUBMIT_URL, () => HttpResponse.json({ id: "0xtxid" })));
14
19
 
15
- expect(await broadcast("0xaabbcc")).toBe("0xtxid");
20
+ expect(await broadcast(context, "0xaabbcc")).toBe("0xtxid");
16
21
  });
17
22
 
18
23
  it("throws on an HTTP 200 whose body carries no transaction id (never swallows an error body)", async () => {
19
24
  server.use(http.post(SUBMIT_URL, () => HttpResponse.json({})));
20
25
 
21
- await expect(broadcast("0xaabbcc")).rejects.toThrow("Expected an ID to be returned");
26
+ await expect(broadcast(context, "0xaabbcc")).rejects.toThrow("Expected an ID to be returned");
22
27
  });
23
28
  });
@@ -1,10 +1,16 @@
1
1
  import type { BroadcastConfig } from "@ledgerhq/coin-module-framework/api/types";
2
+ import type { VechainContext } from "../../config";
2
3
  import { submit } from "../../network";
3
4
  import type { VechainSDKTransaction } from "../../types";
4
5
 
5
6
  // Submit a signed tx (hex from combine) via Thor POST /transactions.
6
- export async function broadcast(tx: string, _broadcastConfig?: BroadcastConfig): Promise<string> {
7
+ export async function broadcast(
8
+ context: VechainContext,
9
+ tx: string,
10
+ _broadcastConfig?: BroadcastConfig,
11
+ ): Promise<string> {
12
+ const config = await context.config();
7
13
  const encoded = Uint8Array.from(Buffer.from(tx.replace(/^0x/, ""), "hex"));
8
14
 
9
- return submit({ encoded } as VechainSDKTransaction);
15
+ return submit(config, { encoded } as VechainSDKTransaction);
10
16
  }
@@ -1,8 +1,11 @@
1
1
  import { submit } from "../../network";
2
+ import { createMockVechainContext } from "../../test/context";
2
3
  import { broadcast } from "./broadcast";
3
4
 
4
5
  jest.mock("../../network", () => ({ submit: jest.fn() }));
5
6
 
7
+ const context = createMockVechainContext();
8
+
6
9
  describe("broadcast", () => {
7
10
  afterEach(() => {
8
11
  jest.clearAllMocks();
@@ -11,16 +14,16 @@ describe("broadcast", () => {
11
14
  it("decodes the hex raw transaction and delegates to submit", async () => {
12
15
  jest.mocked(submit).mockResolvedValueOnce("0xtxid");
13
16
 
14
- const id = await broadcast("0xaabbcc");
17
+ const id = await broadcast(context, "0xaabbcc");
15
18
 
16
19
  expect(id).toBe("0xtxid");
17
- const [passed] = jest.mocked(submit).mock.calls[0];
20
+ const [, passed] = jest.mocked(submit).mock.calls[0];
18
21
  expect(Array.from(passed.encoded as Uint8Array)).toEqual([0xaa, 0xbb, 0xcc]);
19
22
  });
20
23
 
21
24
  it("propagates an error from submit", async () => {
22
25
  jest.mocked(submit).mockRejectedValueOnce(new Error("vechain: broadcast rejected"));
23
26
 
24
- await expect(broadcast("0xaabbcc")).rejects.toThrow("vechain: broadcast rejected");
27
+ await expect(broadcast(context, "0xaabbcc")).rejects.toThrow("vechain: broadcast rejected");
25
28
  });
26
29
  });
@@ -2,9 +2,13 @@ import type { VechainSDKTransactionBody } from "../../types";
2
2
  import { VechainSDKTransaction } from "../../types";
3
3
 
4
4
  // Attach the signature to the crafted body and return the signed, hex-encoded tx for broadcast.
5
- export function combine(tx: string, signature: string): string {
5
+ export function combine(tx: string, signature: string[]): string {
6
+ if (signature.length !== 1) {
7
+ throw new Error(`VeChain combine expects exactly one signature, got ${signature.length}`);
8
+ }
9
+
6
10
  const body = JSON.parse(tx) as VechainSDKTransactionBody;
7
- const signed = VechainSDKTransaction.of(body, Buffer.from(signature, "hex"));
11
+ const signed = VechainSDKTransaction.of(body, Buffer.from(signature[0], "hex"));
8
12
 
9
13
  return `0x${Buffer.from(signed.encoded).toString("hex")}`;
10
14
  }
@@ -17,7 +17,7 @@ describe("combine", () => {
17
17
  it("returns a hex-encoded signed transaction", () => {
18
18
  const signature = "aa".repeat(65);
19
19
 
20
- const signed = combine(JSON.stringify(BODY), signature);
20
+ const signed = combine(JSON.stringify(BODY), [signature]);
21
21
 
22
22
  expect(signed).toMatch(/^0x[0-9a-f]+$/);
23
23
  });
@@ -25,13 +25,13 @@ describe("combine", () => {
25
25
  it("produces a different (longer) payload than the unsigned body JSON, reflecting the signature", () => {
26
26
  const signature = "bb".repeat(65);
27
27
 
28
- const signed = combine(JSON.stringify(BODY), signature);
28
+ const signed = combine(JSON.stringify(BODY), [signature]);
29
29
 
30
30
  expect(signed.length).toBeGreaterThan(0);
31
31
  expect(signed).not.toBe(JSON.stringify(BODY));
32
32
  });
33
33
 
34
34
  it("throws on a malformed transaction payload", () => {
35
- expect(() => combine("not-json", "aa".repeat(65))).toThrow();
35
+ expect(() => combine("not-json", ["aa".repeat(65)])).toThrow();
36
36
  });
37
37
  });
@@ -12,7 +12,7 @@ import {
12
12
  } from "../../common-logic";
13
13
  import { estimateGas } from "../../common-logic/estimateGas";
14
14
  import { getThorClient } from "../../common-logic/getThorClient";
15
- import { getChainTag } from "../../config";
15
+ import { getChainTag, type VechainContext, type VechainCurrencyConfig } from "../../config";
16
16
  import { getAccount, getBlockRef } from "../../network";
17
17
  import type { VechainSDKTransactionBody, VechainSDKTransactionClause } from "../../types";
18
18
 
@@ -28,16 +28,21 @@ function isTokenAsset(intent: TransactionIntent): boolean {
28
28
  return intent.asset.type !== "native";
29
29
  }
30
30
 
31
- async function resolveAmount(intent: TransactionIntent, isToken: boolean): Promise<BigNumber> {
31
+ async function resolveAmount(
32
+ config: VechainCurrencyConfig,
33
+ intent: TransactionIntent,
34
+ isToken: boolean,
35
+ ): Promise<BigNumber> {
32
36
  if (!intent.useAllAmount) {
33
37
  return new BigNumber(intent.amount.toString());
34
38
  }
35
39
 
36
- const { balance, energy } = await getAccount(intent.sender);
40
+ const { balance, energy } = await getAccount(config, intent.sender);
37
41
  return new BigNumber((isToken ? energy : balance) || "0");
38
42
  }
39
43
 
40
44
  async function resolveGasFees(
45
+ config: VechainCurrencyConfig,
41
46
  clauses: VechainSDKTransactionClause[],
42
47
  sender: string,
43
48
  customFees?: FeeEstimation,
@@ -57,8 +62,8 @@ async function resolveGasFees(
57
62
  };
58
63
  }
59
64
 
60
- const gasResult = await estimateGas(clauses, sender);
61
- const thorClient = getThorClient();
65
+ const gasResult = await estimateGas(config, clauses, sender);
66
+ const thorClient = getThorClient(config);
62
67
  const body = await thorClient.transactions.buildTransactionBody(clauses, gasResult.totalGas, {});
63
68
 
64
69
  // Partial override: apply each provided field individually over the estimate, so e.g. a
@@ -75,6 +80,7 @@ async function resolveGasFees(
75
80
  // Craft an unsigned single-clause Thor tx (VET transfer, or VIP-180 transfer for VTHO). The returned
76
81
  // transaction is the JSON VechainSDKTransactionBody that combine() parses back — keep them in sync.
77
82
  export async function craftTransaction(
83
+ context: VechainContext,
78
84
  intent: TransactionIntent,
79
85
  customFees?: FeeEstimation,
80
86
  ): Promise<CraftedTransaction> {
@@ -87,8 +93,9 @@ export async function craftTransaction(
87
93
  throw new Error("vechain: invalid sender address");
88
94
  }
89
95
 
96
+ const config = await context.config();
90
97
  const isToken = isTokenAsset(intent);
91
- let amount = await resolveAmount(intent, isToken);
98
+ let amount = await resolveAmount(config, intent, isToken);
92
99
  if (amount.lte(0)) {
93
100
  throw new Error("vechain: transaction amount must be positive");
94
101
  }
@@ -98,8 +105,8 @@ export async function craftTransaction(
98
105
  : await calculateClausesVet(intent.recipient, amount);
99
106
 
100
107
  const [{ gas, maxFeePerGas, maxPriorityFeePerGas }, blockRef] = await Promise.all([
101
- resolveGasFees(clauses, intent.sender, customFees),
102
- getBlockRef(),
108
+ resolveGasFees(config, clauses, intent.sender, customFees),
109
+ getBlockRef(config),
103
110
  ]);
104
111
 
105
112
  const fee = new BigNumber(maxFeePerGas).times(gas);
@@ -113,7 +120,7 @@ export async function craftTransaction(
113
120
  }
114
121
 
115
122
  const body: VechainSDKTransactionBody = {
116
- chainTag: getChainTag(),
123
+ chainTag: getChainTag(config),
117
124
  blockRef,
118
125
  expiration: EXPIRATION,
119
126
  clauses,
@@ -3,7 +3,8 @@ import type { TransactionIntent } from "@ledgerhq/coin-module-framework/api/inde
3
3
  import { calculateClausesVet, calculateClausesVtho, parseAddress } from "../../common-logic";
4
4
  import { estimateGas } from "../../common-logic/estimateGas";
5
5
  import { getThorClient } from "../../common-logic/getThorClient";
6
- import { setCoinConfig } from "../../config";
6
+ import type { VechainCurrencyConfig } from "../../config";
7
+ import { createMockVechainContext } from "../../test/context";
7
8
  import { getAccount, getBlockRef } from "../../network";
8
9
  import { craftTransaction } from "./craftTransaction";
9
10
 
@@ -44,7 +45,14 @@ function mockBuildTransactionBody() {
44
45
  };
45
46
  }
46
47
 
48
+ const DEFAULT_CONFIG: VechainCurrencyConfig = {
49
+ status: { type: "active" },
50
+ node: { url: "https://vechain.coin.ledger.com" },
51
+ };
52
+
47
53
  describe("craftTransaction", () => {
54
+ let context = createMockVechainContext(DEFAULT_CONFIG);
55
+
48
56
  beforeEach(() => {
49
57
  jest
50
58
  .mocked(calculateClausesVet)
@@ -55,10 +63,7 @@ describe("craftTransaction", () => {
55
63
  jest.mocked(estimateGas).mockResolvedValue({ totalGas: 21000 } as never);
56
64
  jest.mocked(getThorClient).mockReturnValue(mockBuildTransactionBody() as never);
57
65
  jest.mocked(getBlockRef).mockResolvedValue("0xblockref12345678");
58
- setCoinConfig(() => ({
59
- status: { type: "active" },
60
- node: { url: "https://vechain.coin.ledger.com" },
61
- }));
66
+ context = createMockVechainContext(DEFAULT_CONFIG);
62
67
  });
63
68
 
64
69
  afterEach(() => {
@@ -66,7 +71,7 @@ describe("craftTransaction", () => {
66
71
  });
67
72
 
68
73
  it("crafts a native VET transaction using calculateClausesVet", async () => {
69
- const crafted = await craftTransaction(NATIVE_INTENT);
74
+ const crafted = await craftTransaction(context, NATIVE_INTENT);
70
75
 
71
76
  expect(calculateClausesVet).toHaveBeenCalled();
72
77
  expect(calculateClausesVtho).not.toHaveBeenCalled();
@@ -78,27 +83,23 @@ describe("craftTransaction", () => {
78
83
  });
79
84
 
80
85
  it("defaults chainTag to mainnet (74) when the config has no chainTag", async () => {
81
- const crafted = await craftTransaction(NATIVE_INTENT);
86
+ const crafted = await craftTransaction(context, NATIVE_INTENT);
82
87
 
83
88
  const body = JSON.parse(crafted.transaction);
84
89
  expect(body.chainTag).toBe(74);
85
90
  });
86
91
 
87
92
  it("uses the config-provided chainTag when set", async () => {
88
- setCoinConfig(() => ({
89
- status: { type: "active" },
90
- node: { url: "https://vechain.coin.ledger.com" },
91
- chainTag: 39,
92
- }));
93
+ context = createMockVechainContext({ ...DEFAULT_CONFIG, chainTag: 39 });
93
94
 
94
- const crafted = await craftTransaction(NATIVE_INTENT);
95
+ const crafted = await craftTransaction(context, NATIVE_INTENT);
95
96
 
96
97
  const body = JSON.parse(crafted.transaction);
97
98
  expect(body.chainTag).toBe(39);
98
99
  });
99
100
 
100
101
  it("crafts a VTHO transaction using calculateClausesVtho", async () => {
101
- const crafted = await craftTransaction(TOKEN_INTENT);
102
+ const crafted = await craftTransaction(context, TOKEN_INTENT);
102
103
 
103
104
  expect(calculateClausesVtho).toHaveBeenCalled();
104
105
  expect(calculateClausesVet).not.toHaveBeenCalled();
@@ -106,7 +107,7 @@ describe("craftTransaction", () => {
106
107
  });
107
108
 
108
109
  it("computes the fee as maxFeePerGas * gas", async () => {
109
- const crafted = await craftTransaction(NATIVE_INTENT);
110
+ const crafted = await craftTransaction(context, NATIVE_INTENT);
110
111
 
111
112
  expect(crafted.details?.fee).toBe((1000 * 21000).toString());
112
113
  });
@@ -118,14 +119,14 @@ describe("craftTransaction", () => {
118
119
  hasCode: false,
119
120
  });
120
121
 
121
- await craftTransaction({ ...NATIVE_INTENT, useAllAmount: true, amount: 0n });
122
+ await craftTransaction(context, { ...NATIVE_INTENT, useAllAmount: true, amount: 0n });
122
123
 
123
- expect(getAccount).toHaveBeenCalledWith(SENDER);
124
+ expect(getAccount).toHaveBeenCalledWith(DEFAULT_CONFIG, SENDER);
124
125
  expect(calculateClausesVet).toHaveBeenCalledWith(RECIPIENT, expect.any(Object));
125
126
  });
126
127
 
127
128
  it("uses custom fee parameters instead of re-estimating gas when provided", async () => {
128
- await craftTransaction(NATIVE_INTENT, {
129
+ await craftTransaction(context, NATIVE_INTENT, {
129
130
  value: 5000n,
130
131
  parameters: { gas: 30000, maxFeePerGas: 50, maxPriorityFeePerGas: 5 },
131
132
  });
@@ -134,7 +135,7 @@ describe("craftTransaction", () => {
134
135
  });
135
136
 
136
137
  it("applies a partial fee override (gas only) over the estimate instead of discarding it", async () => {
137
- const crafted = await craftTransaction(NATIVE_INTENT, {
138
+ const crafted = await craftTransaction(context, NATIVE_INTENT, {
138
139
  value: 0n,
139
140
  parameters: { gas: 30000 },
140
141
  });
@@ -149,7 +150,7 @@ describe("craftTransaction", () => {
149
150
  it("coerces bigint fee parameters to numbers so the body stays JSON-serializable", async () => {
150
151
  // The generic coin-framework hands fee parameters back as bigint; JSON.stringify cannot
151
152
  // serialize a bigint, so craftTransaction must coerce them to numbers before building the body.
152
- const crafted = await craftTransaction(NATIVE_INTENT, {
153
+ const crafted = await craftTransaction(context, NATIVE_INTENT, {
153
154
  value: 5000n,
154
155
  parameters: { gas: 30000n, maxFeePerGas: 50n, maxPriorityFeePerGas: 5n },
155
156
  } as never);
@@ -162,7 +163,7 @@ describe("craftTransaction", () => {
162
163
  });
163
164
 
164
165
  it("throws when the recipient is missing", async () => {
165
- await expect(craftTransaction({ ...NATIVE_INTENT, recipient: "" })).rejects.toThrow(
166
+ await expect(craftTransaction(context, { ...NATIVE_INTENT, recipient: "" })).rejects.toThrow(
166
167
  "vechain: recipient is required",
167
168
  );
168
169
  });
@@ -170,13 +171,13 @@ describe("craftTransaction", () => {
170
171
  it("throws when the sender is not a valid address", async () => {
171
172
  jest.mocked(parseAddress).mockReturnValueOnce(false);
172
173
 
173
- await expect(craftTransaction({ ...NATIVE_INTENT, sender: "0xbad" })).rejects.toThrow(
174
+ await expect(craftTransaction(context, { ...NATIVE_INTENT, sender: "0xbad" })).rejects.toThrow(
174
175
  "vechain: invalid sender address",
175
176
  );
176
177
  });
177
178
 
178
179
  it("throws when the resolved amount is not positive", async () => {
179
- await expect(craftTransaction({ ...NATIVE_INTENT, amount: 0n })).rejects.toThrow(
180
+ await expect(craftTransaction(context, { ...NATIVE_INTENT, amount: 0n })).rejects.toThrow(
180
181
  "vechain: transaction amount must be positive",
181
182
  );
182
183
  });
@@ -186,7 +187,7 @@ describe("craftTransaction", () => {
186
187
  .mocked(getAccount)
187
188
  .mockResolvedValueOnce({ balance: "0x0", energy: "0x5F5E100", hasCode: false });
188
189
 
189
- await craftTransaction({ ...TOKEN_INTENT, useAllAmount: true, amount: 0n });
190
+ await craftTransaction(context, { ...TOKEN_INTENT, useAllAmount: true, amount: 0n });
190
191
 
191
192
  const calls = jest.mocked(calculateClausesVtho).mock.calls;
192
193
  expect(calls).toHaveLength(2);
@@ -199,12 +200,12 @@ describe("craftTransaction", () => {
199
200
  .mockResolvedValueOnce({ balance: "0x0", energy: "0x3E8", hasCode: false });
200
201
 
201
202
  await expect(
202
- craftTransaction({ ...TOKEN_INTENT, useAllAmount: true, amount: 0n }),
203
+ craftTransaction(context, { ...TOKEN_INTENT, useAllAmount: true, amount: 0n }),
203
204
  ).rejects.toThrow("vechain: VTHO balance too low to cover the transaction gas fee");
204
205
  });
205
206
 
206
207
  it("crafts a dust native amount (1 wei)", async () => {
207
- const crafted = await craftTransaction({ ...NATIVE_INTENT, amount: 1n });
208
+ const crafted = await craftTransaction(context, { ...NATIVE_INTENT, amount: 1n });
208
209
 
209
210
  expect(calculateClausesVet).toHaveBeenCalledWith(RECIPIENT, expect.any(Object));
210
211
  expect(JSON.parse(crafted.transaction).gas).toBe(21000);
@@ -215,7 +216,7 @@ describe("craftTransaction", () => {
215
216
  .mocked(getAccount)
216
217
  .mockResolvedValueOnce({ balance: "0x0", energy: "21000001", hasCode: false });
217
218
 
218
- await craftTransaction({ ...TOKEN_INTENT, useAllAmount: true, amount: 0n });
219
+ await craftTransaction(context, { ...TOKEN_INTENT, useAllAmount: true, amount: 0n });
219
220
 
220
221
  const calls = jest.mocked(calculateClausesVtho).mock.calls;
221
222
  expect(calls[calls.length - 1][1].toString()).toBe("1");
@@ -227,7 +228,7 @@ describe("craftTransaction", () => {
227
228
  .mockResolvedValueOnce({ balance: "0x0", energy: "21000000", hasCode: false });
228
229
 
229
230
  await expect(
230
- craftTransaction({ ...TOKEN_INTENT, useAllAmount: true, amount: 0n }),
231
+ craftTransaction(context, { ...TOKEN_INTENT, useAllAmount: true, amount: 0n }),
231
232
  ).rejects.toThrow("vechain: VTHO balance too low to cover the transaction gas fee");
232
233
  });
233
234
  });
@@ -1,9 +1,11 @@
1
1
  import type { FeeEstimation, TransactionIntent } from "@ledgerhq/coin-module-framework/api/index";
2
2
  import { parseAddress } from "../../common-logic";
3
+ import type { VechainContext } from "../../config";
3
4
  import { craftTransaction } from "./craftTransaction";
4
5
 
5
6
  // Estimate VTHO gas by crafting the unsigned tx and reading back its settled fee/gas parameters.
6
7
  export async function estimateFees(
8
+ context: VechainContext,
7
9
  intent: TransactionIntent,
8
10
  customFeesParameters?: FeeEstimation["parameters"],
9
11
  ): Promise<FeeEstimation> {
@@ -15,6 +17,7 @@ export async function estimateFees(
15
17
  !intent.useAllAmount && intent.amount <= 0n ? { ...intent, amount: 1n } : intent;
16
18
 
17
19
  const { details } = await craftTransaction(
20
+ context,
18
21
  estimationIntent,
19
22
  customFeesParameters ? { value: 0n, parameters: customFeesParameters } : undefined,
20
23
  );
@@ -1,9 +1,12 @@
1
1
  import type { TransactionIntent } from "@ledgerhq/coin-module-framework/api/index";
2
+ import { createMockVechainContext } from "../../test/context";
2
3
  import { craftTransaction } from "./craftTransaction";
3
4
  import { estimateFees } from "./estimateFees";
4
5
 
5
6
  jest.mock("./craftTransaction", () => ({ craftTransaction: jest.fn() }));
6
7
 
8
+ const context = createMockVechainContext();
9
+
7
10
  const INTENT: TransactionIntent = {
8
11
  intentType: "transaction",
9
12
  type: "send",
@@ -24,9 +27,9 @@ describe("estimateFees", () => {
24
27
  details: { fee: "21000000", gas: 21000, maxFeePerGas: 1000, maxPriorityFeePerGas: 100 },
25
28
  });
26
29
 
27
- const fees = await estimateFees(INTENT);
30
+ const fees = await estimateFees(context, INTENT);
28
31
 
29
- expect(craftTransaction).toHaveBeenCalledWith(INTENT, undefined);
32
+ expect(craftTransaction).toHaveBeenCalledWith(context, INTENT, undefined);
30
33
  expect(fees).toEqual({
31
34
  value: 21000000n,
32
35
  parameters: { gas: 21000, maxFeePerGas: 1000, maxPriorityFeePerGas: 100 },
@@ -39,9 +42,9 @@ describe("estimateFees", () => {
39
42
  details: { fee: "1", gas: 1, maxFeePerGas: 1, maxPriorityFeePerGas: 1 },
40
43
  });
41
44
 
42
- await estimateFees(INTENT, { gas: 30000 });
45
+ await estimateFees(context, INTENT, { gas: 30000 });
43
46
 
44
- expect(craftTransaction).toHaveBeenCalledWith(INTENT, {
47
+ expect(craftTransaction).toHaveBeenCalledWith(context, INTENT, {
45
48
  value: 0n,
46
49
  parameters: { gas: 30000 },
47
50
  });
@@ -50,7 +53,7 @@ describe("estimateFees", () => {
50
53
  it("defaults the fee to 0 when craftTransaction returns no details", async () => {
51
54
  jest.mocked(craftTransaction).mockResolvedValueOnce({ transaction: "{}" });
52
55
 
53
- const fees = await estimateFees(INTENT);
56
+ const fees = await estimateFees(context, INTENT);
54
57
 
55
58
  expect(fees.value).toBe(0n);
56
59
  });
@@ -60,7 +63,7 @@ describe("estimateFees", () => {
60
63
  .mocked(craftTransaction)
61
64
  .mockRejectedValueOnce(new Error("vechain: recipient is required"));
62
65
 
63
- await expect(estimateFees(INTENT)).rejects.toThrow("vechain: recipient is required");
66
+ await expect(estimateFees(context, INTENT)).rejects.toThrow("vechain: recipient is required");
64
67
  });
65
68
 
66
69
  it("substitutes a 1-wei placeholder amount for a zero-amount pre-estimation", async () => {
@@ -69,9 +72,9 @@ describe("estimateFees", () => {
69
72
  details: { fee: "21000000", gas: 21000, maxFeePerGas: 1000, maxPriorityFeePerGas: 100 },
70
73
  });
71
74
 
72
- await estimateFees({ ...INTENT, amount: 0n });
75
+ await estimateFees(context, { ...INTENT, amount: 0n });
73
76
 
74
- expect(craftTransaction).toHaveBeenCalledWith({ ...INTENT, amount: 1n }, undefined);
77
+ expect(craftTransaction).toHaveBeenCalledWith(context, { ...INTENT, amount: 1n }, undefined);
75
78
  });
76
79
 
77
80
  it("does not substitute a placeholder when useAllAmount is set (craftTransaction resolves the balance)", async () => {
@@ -81,20 +84,20 @@ describe("estimateFees", () => {
81
84
  });
82
85
 
83
86
  const maxIntent = { ...INTENT, amount: 0n, useAllAmount: true };
84
- await estimateFees(maxIntent);
87
+ await estimateFees(context, maxIntent);
85
88
 
86
- expect(craftTransaction).toHaveBeenCalledWith(maxIntent, undefined);
89
+ expect(craftTransaction).toHaveBeenCalledWith(context, maxIntent, undefined);
87
90
  });
88
91
 
89
92
  it("returns a zero estimate without crafting when the recipient is missing", async () => {
90
- const fees = await estimateFees({ ...INTENT, recipient: "" });
93
+ const fees = await estimateFees(context, { ...INTENT, recipient: "" });
91
94
 
92
95
  expect(fees).toEqual({ value: 0n, parameters: {} });
93
96
  expect(craftTransaction).not.toHaveBeenCalled();
94
97
  });
95
98
 
96
99
  it("returns a zero estimate without crafting when the recipient is not a valid address", async () => {
97
- const fees = await estimateFees({ ...INTENT, recipient: "0xnot-an-address" });
100
+ const fees = await estimateFees(context, { ...INTENT, recipient: "0xnot-an-address" });
98
101
 
99
102
  expect(fees).toEqual({ value: 0n, parameters: {} });
100
103
  expect(craftTransaction).not.toHaveBeenCalled();
@@ -1,10 +1,11 @@
1
1
  import network from "@ledgerhq/live-network";
2
- import { getNodeUrl } from "../config";
2
+ import { getNodeUrl, type VechainCurrencyConfig } from "../config";
3
3
  import type { ApiResponseBlock } from "../types";
4
4
 
5
5
  // Thor GET /blocks/{revision}. `expanded` returns full clause/output detail (getBlock) vs. tx
6
6
  // hashes only (getBlockInfo/lastBlock).
7
7
  export const getBlock = async (
8
+ config: VechainCurrencyConfig,
8
9
  revision: number,
9
10
  expanded = false,
10
11
  ): Promise<ApiResponseBlock | null> => {
@@ -16,7 +17,7 @@ export const getBlock = async (
16
17
 
17
18
  const { data } = await network<ApiResponseBlock | null>({
18
19
  method: "GET",
19
- url: `${getNodeUrl()}/blocks/${revision}?${query}`,
20
+ url: `${getNodeUrl(config)}/blocks/${revision}?${query}`,
20
21
  });
21
22
 
22
23
  return data;
@@ -1,5 +1,6 @@
1
1
  import network from "@ledgerhq/live-network";
2
2
  import { getBlock } from "./getBlock";
3
+ import { mockVechainConfig } from "../test/context";
3
4
 
4
5
  jest.mock("@ledgerhq/live-network", () => jest.fn());
5
6
 
@@ -12,7 +13,7 @@ describe("getBlock", () => {
12
13
  const block = { id: "0xabc", number: 42, timestamp: 1_700_000_000, transactions: [] };
13
14
  jest.mocked(network).mockResolvedValueOnce({ data: block, status: 200 });
14
15
 
15
- const result = await getBlock(42);
16
+ const result = await getBlock(mockVechainConfig, 42, undefined);
16
17
 
17
18
  expect(result).toEqual(block);
18
19
  });
@@ -20,7 +21,7 @@ describe("getBlock", () => {
20
21
  it("requests expanded=false by default", async () => {
21
22
  jest.mocked(network).mockResolvedValueOnce({ data: null, status: 200 });
22
23
 
23
- await getBlock(42);
24
+ await getBlock(mockVechainConfig, 42, undefined);
24
25
 
25
26
  expect(network).toHaveBeenCalledWith(
26
27
  expect.objectContaining({
@@ -33,7 +34,7 @@ describe("getBlock", () => {
33
34
  it("requests expanded=true when asked", async () => {
34
35
  jest.mocked(network).mockResolvedValueOnce({ data: null, status: 200 });
35
36
 
36
- await getBlock(42, true);
37
+ await getBlock(mockVechainConfig, 42, true);
37
38
 
38
39
  expect(network).toHaveBeenCalledWith(
39
40
  expect.objectContaining({ url: expect.stringContaining("expanded=true") }),
@@ -41,18 +42,22 @@ describe("getBlock", () => {
41
42
  });
42
43
 
43
44
  it("rejects a negative revision without making a network call", async () => {
44
- await expect(getBlock(-1)).rejects.toThrow("vechain: getBlock: invalid revision -1");
45
+ await expect(getBlock(mockVechainConfig, -1, undefined)).rejects.toThrow(
46
+ "vechain: getBlock: invalid revision -1",
47
+ );
45
48
  expect(network).not.toHaveBeenCalled();
46
49
  });
47
50
 
48
51
  it("rejects a non-integer revision without making a network call", async () => {
49
- await expect(getBlock(1.5)).rejects.toThrow("vechain: getBlock: invalid revision 1.5");
52
+ await expect(getBlock(mockVechainConfig, 1.5, undefined)).rejects.toThrow(
53
+ "vechain: getBlock: invalid revision 1.5",
54
+ );
50
55
  expect(network).not.toHaveBeenCalled();
51
56
  });
52
57
 
53
58
  it("propagates a network error", async () => {
54
59
  jest.mocked(network).mockRejectedValueOnce(new Error("status 500"));
55
60
 
56
- await expect(getBlock(42)).rejects.toThrow("status 500");
61
+ await expect(getBlock(mockVechainConfig, 42, undefined)).rejects.toThrow("status 500");
57
62
  });
58
63
  });