@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,6 @@
1
1
  import { getThorClient } from "./getThorClient";
2
2
  import { ThorClient } from "@vechain/sdk-network";
3
- import { setCoinConfig } from "../config";
3
+ import type { VechainCurrencyConfig } from "../config";
4
4
 
5
5
  // Mock the ThorClient
6
6
  jest.mock("@vechain/sdk-network", () => ({
@@ -10,14 +10,14 @@ jest.mock("@vechain/sdk-network", () => ({
10
10
  }));
11
11
 
12
12
  const NODE_URL = "https://testnet.veblocks.net";
13
+ // The endpoint comes from the coin config, threaded in explicitly.
14
+ const config: VechainCurrencyConfig = { status: { type: "active" }, node: { url: NODE_URL } };
13
15
 
14
16
  const mockedThorClient = jest.mocked(ThorClient);
15
17
 
16
18
  describe("getThorClient", () => {
17
19
  beforeEach(() => {
18
20
  jest.clearAllMocks();
19
- // The endpoint comes from the coin config, not from the environment.
20
- setCoinConfig(() => ({ status: { type: "active" }, node: { url: NODE_URL } }));
21
21
  });
22
22
 
23
23
  it("should create a ThorClient instance with the configured node url", () => {
@@ -26,7 +26,7 @@ describe("getThorClient", () => {
26
26
  };
27
27
  mockedThorClient.at.mockReturnValue(mockClient as any);
28
28
 
29
- const result = getThorClient();
29
+ const result = getThorClient(config);
30
30
 
31
31
  expect(mockedThorClient.at).toHaveBeenCalledWith(NODE_URL);
32
32
  expect(result).toBe(mockClient);
@@ -40,7 +40,7 @@ describe("getThorClient", () => {
40
40
  };
41
41
  mockedThorClient.at.mockReturnValue(mockClient as any);
42
42
 
43
- const result = getThorClient();
43
+ const result = getThorClient(config);
44
44
 
45
45
  expect(result).toEqual(mockClient);
46
46
  });
@@ -49,7 +49,7 @@ describe("getThorClient", () => {
49
49
  const mockClient = {};
50
50
  mockedThorClient.at.mockReturnValue(mockClient as any);
51
51
 
52
- getThorClient();
52
+ getThorClient(config);
53
53
 
54
54
  expect(mockedThorClient.at).toHaveBeenCalledTimes(1);
55
55
  });
@@ -58,7 +58,7 @@ describe("getThorClient", () => {
58
58
  const mockClient = {};
59
59
  mockedThorClient.at.mockReturnValue(mockClient as any);
60
60
 
61
- getThorClient();
61
+ getThorClient(config);
62
62
 
63
63
  expect(mockedThorClient.at).toHaveBeenCalledWith("https://testnet.veblocks.net");
64
64
  });
@@ -1,10 +1,10 @@
1
1
  import { ThorClient } from "@vechain/sdk-network";
2
- import { getNodeUrl } from "../config";
2
+ import { getNodeUrl, type VechainCurrencyConfig } from "../config";
3
3
 
4
4
  /**
5
5
  * Returns a ThorClient instance configured with the VeChain node URL
6
6
  * @returns {ThorClient} Configured ThorClient instance for interacting with the VeChain network
7
7
  */
8
- export const getThorClient = (): ThorClient => {
9
- return ThorClient.at(getNodeUrl());
8
+ export const getThorClient = (config: VechainCurrencyConfig): ThorClient => {
9
+ return ThorClient.at(getNodeUrl(config));
10
10
  };
@@ -25,6 +25,7 @@ import {
25
25
  mapTokenTransfersToOperations,
26
26
  } from "./mapTransfersToOperations";
27
27
  import { getFees } from "../network/getFees";
28
+ import { mockVechainConfig } from "../test/context";
28
29
 
29
30
  const { ABIEvent, Hex, VIP180_ABI } = jest.requireMock("@vechain/sdk-core");
30
31
 
@@ -76,6 +77,7 @@ describe("mapVetTransfersToOperations", () => {
76
77
 
77
78
  it("should map incoming VET transfers to operations", async () => {
78
79
  const result = await mapVetTransfersToOperations(
80
+ mockVechainConfig,
79
81
  [mockTransferLogs[0]],
80
82
  mockAccountId,
81
83
  mockAddr,
@@ -100,6 +102,7 @@ describe("mapVetTransfersToOperations", () => {
100
102
 
101
103
  it("should map outgoing VET transfers to operations", async () => {
102
104
  const result = await mapVetTransfersToOperations(
105
+ mockVechainConfig,
103
106
  [mockTransferLogs[1]],
104
107
  mockAccountId,
105
108
  mockAddr,
@@ -123,7 +126,12 @@ describe("mapVetTransfersToOperations", () => {
123
126
  });
124
127
 
125
128
  it("should handle multiple transfers", async () => {
126
- const result = await mapVetTransfersToOperations(mockTransferLogs, mockAccountId, mockAddr);
129
+ const result = await mapVetTransfersToOperations(
130
+ mockVechainConfig,
131
+ mockTransferLogs,
132
+ mockAccountId,
133
+ mockAddr,
134
+ );
127
135
 
128
136
  expect(result).toHaveLength(2);
129
137
  expect(result[0].type).toBe("IN");
@@ -131,11 +139,11 @@ describe("mapVetTransfersToOperations", () => {
131
139
  });
132
140
 
133
141
  it("should call getFees for each transfer", async () => {
134
- await mapVetTransfersToOperations(mockTransferLogs, mockAccountId, mockAddr);
142
+ await mapVetTransfersToOperations(mockVechainConfig, mockTransferLogs, mockAccountId, mockAddr);
135
143
 
136
144
  expect(mockedGetFees).toHaveBeenCalledTimes(2);
137
- expect(mockedGetFees).toHaveBeenCalledWith("0xtx123");
138
- expect(mockedGetFees).toHaveBeenCalledWith("0xtx456");
145
+ expect(mockedGetFees).toHaveBeenCalledWith(mockVechainConfig, "0xtx123");
146
+ expect(mockedGetFees).toHaveBeenCalledWith(mockVechainConfig, "0xtx456");
139
147
  });
140
148
 
141
149
  it("should handle case-insensitive address comparison", async () => {
@@ -146,6 +154,7 @@ describe("mapVetTransfersToOperations", () => {
146
154
  };
147
155
 
148
156
  const result = await mapVetTransfersToOperations(
157
+ mockVechainConfig,
149
158
  [transferWithUpperCase],
150
159
  mockAccountId,
151
160
  mockAddr,
@@ -162,6 +171,7 @@ describe("mapVetTransfersToOperations", () => {
162
171
  };
163
172
 
164
173
  const result = await mapVetTransfersToOperations(
174
+ mockVechainConfig,
165
175
  [transferWithMixedCase],
166
176
  mockAccountId,
167
177
  mockAddr,
@@ -216,7 +226,12 @@ describe("mapTokenTransfersToOperations", () => {
216
226
  });
217
227
 
218
228
  it("should map incoming token transfers to operations", async () => {
219
- const result = await mapTokenTransfersToOperations(mockEventLogs, mockAccountId, mockAddr);
229
+ const result = await mapTokenTransfersToOperations(
230
+ mockVechainConfig,
231
+ mockEventLogs,
232
+ mockAccountId,
233
+ mockAddr,
234
+ );
220
235
 
221
236
  expect(result).toHaveLength(1);
222
237
  expect(result[0]).toEqual({
@@ -246,14 +261,19 @@ describe("mapTokenTransfersToOperations", () => {
246
261
  };
247
262
  mockedABIEvent.parseLog.mockReturnValue(outgoingEvent);
248
263
 
249
- const result = await mapTokenTransfersToOperations(mockEventLogs, mockAccountId, mockAddr);
264
+ const result = await mapTokenTransfersToOperations(
265
+ mockVechainConfig,
266
+ mockEventLogs,
267
+ mockAccountId,
268
+ mockAddr,
269
+ );
250
270
 
251
271
  expect(result[0].type).toBe("OUT");
252
272
  expect(result[0].value).toEqual(new BigNumber("2000000000000000000"));
253
273
  });
254
274
 
255
275
  it("should decode event logs correctly", async () => {
256
- await mapTokenTransfersToOperations(mockEventLogs, mockAccountId, mockAddr);
276
+ await mapTokenTransfersToOperations(mockVechainConfig, mockEventLogs, mockAccountId, mockAddr);
257
277
 
258
278
  expect(mockedHex.of).toHaveBeenCalledWith(mockEventLogs[0].data);
259
279
  expect(mockedHex.of).toHaveBeenCalledWith(mockEventLogs[0].topics[0]);
@@ -280,16 +300,21 @@ describe("mapTokenTransfersToOperations", () => {
280
300
  };
281
301
  mockedABIEvent.parseLog.mockReturnValue(largeValueEvent);
282
302
 
283
- const result = await mapTokenTransfersToOperations(mockEventLogs, mockAccountId, mockAddr);
303
+ const result = await mapTokenTransfersToOperations(
304
+ mockVechainConfig,
305
+ mockEventLogs,
306
+ mockAccountId,
307
+ mockAddr,
308
+ );
284
309
 
285
310
  expect(result[0].value).toEqual(new BigNumber("123456789012345678901234567890"));
286
311
  });
287
312
 
288
313
  it("should call getFees for each event", async () => {
289
- await mapTokenTransfersToOperations(mockEventLogs, mockAccountId, mockAddr);
314
+ await mapTokenTransfersToOperations(mockVechainConfig, mockEventLogs, mockAccountId, mockAddr);
290
315
 
291
316
  expect(mockedGetFees).toHaveBeenCalledTimes(1);
292
- expect(mockedGetFees).toHaveBeenCalledWith("0xtx789");
317
+ expect(mockedGetFees).toHaveBeenCalledWith(mockVechainConfig, "0xtx789");
293
318
  });
294
319
 
295
320
  it("should handle multiple events", async () => {
@@ -301,7 +326,7 @@ describe("mapTokenTransfersToOperations", () => {
301
326
  },
302
327
  ];
303
328
 
304
- await mapTokenTransfersToOperations(multipleEvents, mockAccountId, mockAddr);
329
+ await mapTokenTransfersToOperations(mockVechainConfig, multipleEvents, mockAccountId, mockAddr);
305
330
 
306
331
  expect(mockedGetFees).toHaveBeenCalledTimes(2);
307
332
  expect(mockedABIEvent.parseLog).toHaveBeenCalledTimes(2);
@@ -318,7 +343,12 @@ describe("mapTokenTransfersToOperations", () => {
318
343
  };
319
344
  mockedABIEvent.parseLog.mockReturnValue(upperCaseEvent);
320
345
 
321
- const result = await mapTokenTransfersToOperations(mockEventLogs, mockAccountId, mockAddr);
346
+ const result = await mapTokenTransfersToOperations(
347
+ mockVechainConfig,
348
+ mockEventLogs,
349
+ mockAccountId,
350
+ mockAddr,
351
+ );
322
352
 
323
353
  expect(result[0].type).toBe("IN");
324
354
  });
@@ -334,7 +364,12 @@ describe("mapTokenTransfersToOperations", () => {
334
364
  };
335
365
  mockedABIEvent.parseLog.mockReturnValue(mixedCaseEvent);
336
366
 
337
- const result = await mapTokenTransfersToOperations(mockEventLogs, mockAccountId, mockAddr);
367
+ const result = await mapTokenTransfersToOperations(
368
+ mockVechainConfig,
369
+ mockEventLogs,
370
+ mockAccountId,
371
+ mockAddr,
372
+ );
338
373
 
339
374
  expect(result[0].senders[0]).toBe("0x5034aa590125b64023a0262112b98d72e3c8e40e");
340
375
  expect(result[0].recipients[0]).toBe("0x742d35cc6634c0532925a3b8d0b251d8c1743ec4");
@@ -4,15 +4,17 @@ import { EventLog, TransferLog } from "../types";
4
4
  import { encodeOperationId } from "@ledgerhq/ledger-wallet-framework/operation";
5
5
  import { getFees } from "../network/getFees";
6
6
  import { ABIEvent, Hex, VIP180_ABI } from "@vechain/sdk-core";
7
+ import type { VechainCurrencyConfig } from "../config";
7
8
 
8
9
  export const mapVetTransfersToOperations = async (
10
+ config: VechainCurrencyConfig,
9
11
  txs: TransferLog[],
10
12
  accountId: string,
11
13
  addr: string,
12
14
  ): Promise<Operation[]> => {
13
15
  return Promise.all(
14
16
  txs.map(async tx => {
15
- const fees = await getFees(tx.meta.txID);
17
+ const fees = await getFees(config, tx.meta.txID);
16
18
  return {
17
19
  id: encodeOperationId(
18
20
  accountId,
@@ -36,6 +38,7 @@ export const mapVetTransfersToOperations = async (
36
38
  };
37
39
 
38
40
  export const mapTokenTransfersToOperations = async (
41
+ config: VechainCurrencyConfig,
39
42
  events: EventLog[],
40
43
  accountId: string,
41
44
  addr: string,
@@ -57,7 +60,7 @@ export const mapTokenTransfersToOperations = async (
57
60
  const to = decoded.args.to;
58
61
  const value = decoded.args.value;
59
62
  const type = to.toLowerCase() === addr.toLowerCase() ? "IN" : "OUT";
60
- const fees = await getFees(event.meta.txID);
63
+ const fees = await getFees(config, event.meta.txID);
61
64
  return {
62
65
  id: encodeOperationId(accountId, event.meta.txID, type),
63
66
  hash: event.meta.txID,
@@ -49,7 +49,7 @@ describe("getChainTag", () => {
49
49
  chainTag: 39,
50
50
  }));
51
51
 
52
- expect(getChainTag()).toBe(39);
52
+ expect(getChainTag(getCoinConfig())).toBe(39);
53
53
  });
54
54
 
55
55
  it("falls back to mainnet when the currency config omits a chainTag", () => {
@@ -58,7 +58,7 @@ describe("getChainTag", () => {
58
58
  node: { url: "https://vechain.coin.ledger.com" },
59
59
  }));
60
60
 
61
- expect(getChainTag()).toBe(MAINNET_CHAIN_TAG);
61
+ expect(getChainTag(getCoinConfig())).toBe(MAINNET_CHAIN_TAG);
62
62
  });
63
63
 
64
64
  it.each([-1, 256, 74.5, NaN])(
@@ -70,7 +70,7 @@ describe("getChainTag", () => {
70
70
  chainTag: invalid,
71
71
  }));
72
72
 
73
- expect(getChainTag()).toBe(MAINNET_CHAIN_TAG);
73
+ expect(getChainTag(getCoinConfig())).toBe(MAINNET_CHAIN_TAG);
74
74
  },
75
75
  );
76
76
  });
package/src/config.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CurrencyConfig, CoinConfig } from "@ledgerhq/coin-module-framework/config";
1
+ import { CurrencyConfig, CoinConfig, type Context } from "@ledgerhq/coin-module-framework/config";
2
2
  import { MissingCoinConfig } from "@ledgerhq/coin-module-framework/errors";
3
3
  import { MAINNET_CHAIN_TAG } from "./types";
4
4
 
@@ -15,6 +15,9 @@ export type VechainCurrencyConfig = CurrencyConfig & {
15
15
 
16
16
  export type VechainCoinConfig = () => VechainCurrencyConfig;
17
17
 
18
+ /** The {@link Context} threaded through the coin-vechain API layer (ADR-019). */
19
+ export type VechainContext = Context<VechainCurrencyConfig>;
20
+
18
21
  let coinConfig: CoinConfig<VechainCurrencyConfig> | undefined;
19
22
 
20
23
  export function setCoinConfig(config: CoinConfig<VechainCurrencyConfig>): void {
@@ -29,9 +32,13 @@ export function getCoinConfig(): VechainCurrencyConfig {
29
32
  return coinConfig();
30
33
  }
31
34
 
32
- /** Thor REST endpoint, resolved per call so a config change is picked up without a reload. */
33
- export function getNodeUrl(): string {
34
- const { node } = getCoinConfig();
35
+ /**
36
+ * Thor REST endpoint. Config is threaded in explicitly by every caller: the Alpaca (`createApi`)
37
+ * path resolves it from `context.config()`, and the classic bridge resolves it once from the
38
+ * {@link getCoinConfig} singleton at its entry points and passes it down.
39
+ */
40
+ export function getNodeUrl(config: VechainCurrencyConfig): string {
41
+ const { node } = config;
35
42
 
36
43
  if (!node?.url) {
37
44
  throw new Error("vechain: node.url is missing from the coin config");
@@ -40,8 +47,8 @@ export function getNodeUrl(): string {
40
47
  return node.url;
41
48
  }
42
49
 
43
- export function getChainTag(): number {
44
- const { chainTag } = getCoinConfig();
50
+ export function getChainTag(config: VechainCurrencyConfig): number {
51
+ const { chainTag } = config;
45
52
  return typeof chainTag === "number" &&
46
53
  Number.isInteger(chainTag) &&
47
54
  chainTag >= 0 &&
@@ -1,5 +1,6 @@
1
1
  import type { AssetInfo, Balance } from "@ledgerhq/coin-module-framework/api/index";
2
2
  import { VTHO_ADDRESS } from "@vechain/sdk-core";
3
+ import type { VechainContext } from "../../config";
3
4
  import { getAccount } from "../../network";
4
5
 
5
6
  export const NATIVE_ASSET: AssetInfo = { type: "native", name: "VET" };
@@ -14,8 +15,9 @@ export const vthoAsset = (address: string): AssetInfo => ({
14
15
  });
15
16
 
16
17
  // VET + VTHO balances from Thor's /accounts/{address} (both returned in one call); 0 if absent.
17
- export async function getBalance(address: string): Promise<Balance[]> {
18
- const { balance, energy } = await getAccount(address);
18
+ export async function getBalance(context: VechainContext, address: string): Promise<Balance[]> {
19
+ const config = await context.config();
20
+ const { balance, energy } = await getAccount(config, address);
19
21
 
20
22
  return [
21
23
  { value: BigInt(balance || "0"), asset: NATIVE_ASSET },
@@ -1,9 +1,11 @@
1
1
  import { getAccount } from "../../network";
2
+ import { createMockVechainContext, mockVechainConfig } from "../../test/context";
2
3
  import { getBalance, NATIVE_ASSET, vthoAsset } from "./getBalance";
3
4
 
4
5
  jest.mock("../../network", () => ({ getAccount: jest.fn() }));
5
6
 
6
7
  const ADDRESS = "0x0fe6688548f0C303932bB197B0A96034f1d74dba";
8
+ const context = createMockVechainContext();
7
9
 
8
10
  describe("getBalance", () => {
9
11
  afterEach(() => {
@@ -17,9 +19,9 @@ describe("getBalance", () => {
17
19
  hasCode: false,
18
20
  });
19
21
 
20
- const balances = await getBalance(ADDRESS);
22
+ const balances = await getBalance(context, ADDRESS);
21
23
 
22
- expect(getAccount).toHaveBeenCalledWith(ADDRESS);
24
+ expect(getAccount).toHaveBeenCalledWith(mockVechainConfig, ADDRESS);
23
25
  expect(balances).toEqual([
24
26
  { value: BigInt("0x1bc16d674ec80000"), asset: NATIVE_ASSET },
25
27
  { value: BigInt("0xde0b6b3a7640000"), asset: vthoAsset(ADDRESS) },
@@ -29,7 +31,7 @@ describe("getBalance", () => {
29
31
  it("defaults both balances to 0 for a pristine account", async () => {
30
32
  jest.mocked(getAccount).mockResolvedValueOnce({ balance: "", energy: "", hasCode: false });
31
33
 
32
- const balances = await getBalance(ADDRESS);
34
+ const balances = await getBalance(context, ADDRESS);
33
35
 
34
36
  expect(balances).toEqual([
35
37
  { value: 0n, asset: NATIVE_ASSET },
@@ -42,7 +44,7 @@ describe("getBalance", () => {
42
44
  .mocked(getAccount)
43
45
  .mockResolvedValueOnce({ balance: "0x1", energy: "0x2", hasCode: false });
44
46
 
45
- const [nativeBalance, tokenBalance] = await getBalance(ADDRESS);
47
+ const [nativeBalance, tokenBalance] = await getBalance(context, ADDRESS);
46
48
 
47
49
  expect(nativeBalance.asset.type).toBe("native");
48
50
  expect(tokenBalance.asset.type).not.toBe("native");
@@ -3,14 +3,16 @@ import type {
3
3
  BlockOperation,
4
4
  BlockTransaction,
5
5
  } from "@ledgerhq/coin-module-framework/api/index";
6
+ import type { VechainContext } from "../../config";
6
7
  import { getBlock as getBlockFromNetwork } from "../../network";
7
8
  import type { ApiResponseBlockTransaction } from "../../types";
8
9
  import { toBlockInfo } from "./getBlockInfo";
9
10
 
10
11
  // Full expanded block; block info is derived from it (no separate fetch). Only native VET transfers
11
12
  // map to operations; VTHO (VIP-180) movements are ABI-encoded events, not decoded here.
12
- export async function getBlock(height: number): Promise<Block> {
13
- const block = await getBlockFromNetwork(height, true);
13
+ export async function getBlock(context: VechainContext, height: number): Promise<Block> {
14
+ const config = await context.config();
15
+ const block = await getBlockFromNetwork(config, height, true);
14
16
 
15
17
  if (!block) {
16
18
  throw new Error(`vechain: no block at height ${height}`);
@@ -1,8 +1,11 @@
1
1
  import { getBlock as getBlockFromNetwork } from "../../network";
2
+ import { createMockVechainContext, mockVechainConfig } from "../../test/context";
2
3
  import { getBlock } from "./getBlock";
3
4
 
4
5
  jest.mock("../../network", () => ({ getBlock: jest.fn() }));
5
6
 
7
+ const context = createMockVechainContext();
8
+
6
9
  describe("getBlock", () => {
7
10
  afterEach(() => {
8
11
  jest.clearAllMocks();
@@ -31,10 +34,10 @@ describe("getBlock", () => {
31
34
  ],
32
35
  });
33
36
 
34
- const block = await getBlock(10);
37
+ const block = await getBlock(context, 10);
35
38
 
36
39
  expect(getBlockFromNetwork).toHaveBeenCalledTimes(1);
37
- expect(getBlockFromNetwork).toHaveBeenCalledWith(10, true);
40
+ expect(getBlockFromNetwork).toHaveBeenCalledWith(mockVechainConfig, 10, true);
38
41
  expect(block.info).toEqual({
39
42
  height: 10,
40
43
  hash: "0xabc",
@@ -69,7 +72,7 @@ describe("getBlock", () => {
69
72
  ],
70
73
  });
71
74
 
72
- const block = await getBlock(10);
75
+ const block = await getBlock(context, 10);
73
76
 
74
77
  expect(block.transactions[0].failed).toBe(true);
75
78
  expect(block.transactions[0].operations).toEqual([]);
@@ -78,7 +81,7 @@ describe("getBlock", () => {
78
81
  it("throws when there is no block at the given height", async () => {
79
82
  jest.mocked(getBlockFromNetwork).mockResolvedValueOnce(null);
80
83
 
81
- await expect(getBlock(1)).rejects.toThrow("vechain: no block at height 1");
84
+ await expect(getBlock(context, 1)).rejects.toThrow("vechain: no block at height 1");
82
85
  });
83
86
 
84
87
  it("uses the VIP-191 gasPayer as feesPayer when a tx is fee-delegated", async () => {
@@ -99,7 +102,7 @@ describe("getBlock", () => {
99
102
  ],
100
103
  });
101
104
 
102
- const block = await getBlock(10);
105
+ const block = await getBlock(context, 10);
103
106
 
104
107
  expect(block.transactions[0].feesPayer).toBe("0xdelegate");
105
108
  });
@@ -1,4 +1,5 @@
1
1
  import type { BlockInfo } from "@ledgerhq/coin-module-framework/api/index";
2
+ import type { VechainContext } from "../../config";
2
3
  import { getBlock as getBlockFromNetwork } from "../../network";
3
4
  import type { ApiResponseBlock } from "../../types";
4
5
 
@@ -13,8 +14,9 @@ export function toBlockInfo(block: ApiResponseBlock): BlockInfo {
13
14
  }
14
15
 
15
16
  /** Block metadata (height/hash/time) at a given block height, via Thor `GET /blocks/{height}`. */
16
- export async function getBlockInfo(height: number): Promise<BlockInfo> {
17
- const block = await getBlockFromNetwork(height);
17
+ export async function getBlockInfo(context: VechainContext, height: number): Promise<BlockInfo> {
18
+ const config = await context.config();
19
+ const block = await getBlockFromNetwork(config, height, false);
18
20
 
19
21
  if (!block) {
20
22
  throw new Error(`vechain: no block at height ${height}`);
@@ -1,8 +1,11 @@
1
1
  import { getBlock as getBlockFromNetwork } from "../../network";
2
+ import { createMockVechainContext, mockVechainConfig } from "../../test/context";
2
3
  import { getBlockInfo } from "./getBlockInfo";
3
4
 
4
5
  jest.mock("../../network", () => ({ getBlock: jest.fn() }));
5
6
 
7
+ const context = createMockVechainContext();
8
+
6
9
  describe("getBlockInfo", () => {
7
10
  afterEach(() => {
8
11
  jest.clearAllMocks();
@@ -16,15 +19,15 @@ describe("getBlockInfo", () => {
16
19
  transactions: [],
17
20
  });
18
21
 
19
- const info = await getBlockInfo(42);
22
+ const info = await getBlockInfo(context, 42);
20
23
 
21
- expect(getBlockFromNetwork).toHaveBeenCalledWith(42);
24
+ expect(getBlockFromNetwork).toHaveBeenCalledWith(mockVechainConfig, 42, false);
22
25
  expect(info).toEqual({ height: 42, hash: "0xabc", time: new Date(1_700_000_000 * 1000) });
23
26
  });
24
27
 
25
28
  it("throws when there is no block at the given height", async () => {
26
29
  jest.mocked(getBlockFromNetwork).mockResolvedValueOnce(null);
27
30
 
28
- await expect(getBlockInfo(999)).rejects.toThrow("vechain: no block at height 999");
31
+ await expect(getBlockInfo(context, 999)).rejects.toThrow("vechain: no block at height 999");
29
32
  });
30
33
  });
@@ -1,9 +1,11 @@
1
1
  import type { BlockInfo } from "@ledgerhq/coin-module-framework/api/index";
2
+ import type { VechainContext } from "../../config";
2
3
  import { getLastBlockHeight } from "../../network";
3
4
  import { getBlockInfo } from "./getBlockInfo";
4
5
 
5
6
  // Latest block; /blocks/best exposes only the height, so hash/time come from getBlockInfo.
6
- export async function lastBlock(): Promise<BlockInfo> {
7
- const height = await getLastBlockHeight();
8
- return getBlockInfo(height);
7
+ export async function lastBlock(context: VechainContext): Promise<BlockInfo> {
8
+ const config = await context.config();
9
+ const height = await getLastBlockHeight(config);
10
+ return getBlockInfo(context, height);
9
11
  }
@@ -1,10 +1,13 @@
1
1
  import { getLastBlockHeight } from "../../network";
2
+ import { createMockVechainContext } from "../../test/context";
2
3
  import { getBlockInfo } from "./getBlockInfo";
3
4
  import { lastBlock } from "./lastBlock";
4
5
 
5
6
  jest.mock("../../network", () => ({ getLastBlockHeight: jest.fn() }));
6
7
  jest.mock("./getBlockInfo", () => ({ getBlockInfo: jest.fn() }));
7
8
 
9
+ const context = createMockVechainContext();
10
+
8
11
  describe("lastBlock", () => {
9
12
  afterEach(() => {
10
13
  jest.clearAllMocks();
@@ -15,16 +18,16 @@ describe("lastBlock", () => {
15
18
  const info = { height: 123, hash: "0xabc", time: new Date() };
16
19
  jest.mocked(getBlockInfo).mockResolvedValueOnce(info);
17
20
 
18
- const result = await lastBlock();
21
+ const result = await lastBlock(context);
19
22
 
20
- expect(getBlockInfo).toHaveBeenCalledWith(123);
23
+ expect(getBlockInfo).toHaveBeenCalledWith(context, 123);
21
24
  expect(result).toBe(info);
22
25
  });
23
26
 
24
27
  it("propagates an error from the height lookup", async () => {
25
28
  jest.mocked(getLastBlockHeight).mockRejectedValueOnce(new Error("network down"));
26
29
 
27
- await expect(lastBlock()).rejects.toThrow("network down");
30
+ await expect(lastBlock(context)).rejects.toThrow("network down");
28
31
  expect(getBlockInfo).not.toHaveBeenCalled();
29
32
  });
30
33
  });
@@ -7,6 +7,7 @@ import type {
7
7
  } from "@ledgerhq/coin-module-framework/api/index";
8
8
  import type { Operation as LegacyOperation } from "@ledgerhq/types-live";
9
9
  import { VTHO_ADDRESS } from "@vechain/sdk-core";
10
+ import type { VechainContext } from "../../config";
10
11
  import { getLastBlockHeight, getOperations, getTokenOperations } from "../../network";
11
12
  import { NATIVE_ASSET, vthoAsset } from "../account/getBalance";
12
13
 
@@ -37,19 +38,21 @@ function parseCursor(options: ListOperationsOptions): number {
37
38
 
38
39
  // Merged VET + VTHO operations; `next` is one block past the current head for incremental resume.
39
40
  export async function listOperations(
41
+ context: VechainContext,
40
42
  address: string,
41
43
  options: ListOperationsOptions,
42
44
  ): Promise<Page<Operation<MemoNotSupported>>> {
45
+ const config = await context.config();
43
46
  const startAt = parseCursor(options);
44
- const stopAt = await getLastBlockHeight();
47
+ const stopAt = await getLastBlockHeight(config);
45
48
 
46
49
  if (startAt > stopAt) {
47
50
  return { items: [], next: String(startAt) };
48
51
  }
49
52
 
50
53
  const [vetOps, vthoOps] = await Promise.all([
51
- getOperations(address, address, startAt, stopAt),
52
- getTokenOperations(address, address, VTHO_ADDRESS, startAt, stopAt),
54
+ getOperations(config, address, address, startAt, stopAt),
55
+ getTokenOperations(config, address, address, VTHO_ADDRESS, startAt, stopAt),
53
56
  ]);
54
57
 
55
58
  const items = [