@ledgerhq/coin-filecoin 1.3.2

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 (316) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.unimportedrc.json +21 -0
  3. package/CHANGELOG.md +19 -0
  4. package/LICENSE.txt +21 -0
  5. package/jest.config.js +8 -0
  6. package/lib/api/api.d.ts +9 -0
  7. package/lib/api/api.d.ts.map +1 -0
  8. package/lib/api/api.js +99 -0
  9. package/lib/api/api.js.map +1 -0
  10. package/lib/api/index.d.ts +2 -0
  11. package/lib/api/index.d.ts.map +1 -0
  12. package/lib/api/index.js +18 -0
  13. package/lib/api/index.js.map +1 -0
  14. package/lib/bridge/broadcast.d.ts +4 -0
  15. package/lib/bridge/broadcast.d.ts.map +1 -0
  16. package/lib/bridge/broadcast.js +27 -0
  17. package/lib/bridge/broadcast.js.map +1 -0
  18. package/lib/bridge/buildOptimisticOperation.d.ts +5 -0
  19. package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -0
  20. package/lib/bridge/buildOptimisticOperation.js +62 -0
  21. package/lib/bridge/buildOptimisticOperation.js.map +1 -0
  22. package/lib/bridge/createTransaction.d.ts +4 -0
  23. package/lib/bridge/createTransaction.d.ts.map +1 -0
  24. package/lib/bridge/createTransaction.js +24 -0
  25. package/lib/bridge/createTransaction.js.map +1 -0
  26. package/lib/bridge/deviceTransactionConfig.d.ts +33 -0
  27. package/lib/bridge/deviceTransactionConfig.d.ts.map +1 -0
  28. package/lib/bridge/deviceTransactionConfig.js +71 -0
  29. package/lib/bridge/deviceTransactionConfig.js.map +1 -0
  30. package/lib/bridge/estimateMaxSpendable.d.ts +4 -0
  31. package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -0
  32. package/lib/bridge/estimateMaxSpendable.js +100 -0
  33. package/lib/bridge/estimateMaxSpendable.js.map +1 -0
  34. package/lib/bridge/getTransactionStatus.d.ts +4 -0
  35. package/lib/bridge/getTransactionStatus.d.ts.map +1 -0
  36. package/lib/bridge/getTransactionStatus.js +84 -0
  37. package/lib/bridge/getTransactionStatus.js.map +1 -0
  38. package/lib/bridge/index.d.ts +8 -0
  39. package/lib/bridge/index.d.ts.map +1 -0
  40. package/lib/bridge/index.js +54 -0
  41. package/lib/bridge/index.js.map +1 -0
  42. package/lib/bridge/prepareTransaction.d.ts +4 -0
  43. package/lib/bridge/prepareTransaction.d.ts.map +1 -0
  44. package/lib/bridge/prepareTransaction.js +75 -0
  45. package/lib/bridge/prepareTransaction.js.map +1 -0
  46. package/lib/bridge/serializer.d.ts +13 -0
  47. package/lib/bridge/serializer.d.ts.map +1 -0
  48. package/lib/bridge/serializer.js +65 -0
  49. package/lib/bridge/serializer.js.map +1 -0
  50. package/lib/bridge/signOperation.d.ts +5 -0
  51. package/lib/bridge/signOperation.d.ts.map +1 -0
  52. package/lib/bridge/signOperation.js +80 -0
  53. package/lib/bridge/signOperation.js.map +1 -0
  54. package/lib/bridge/transaction.d.ts +14 -0
  55. package/lib/bridge/transaction.d.ts.map +1 -0
  56. package/lib/bridge/transaction.js +41 -0
  57. package/lib/bridge/transaction.js.map +1 -0
  58. package/lib/bridge/utils.d.ts +26 -0
  59. package/lib/bridge/utils.d.ts.map +1 -0
  60. package/lib/bridge/utils.js +67 -0
  61. package/lib/bridge/utils.js.map +1 -0
  62. package/lib/bridge/utils.unit.test.d.ts +2 -0
  63. package/lib/bridge/utils.unit.test.d.ts.map +1 -0
  64. package/lib/bridge/utils.unit.test.js +23 -0
  65. package/lib/bridge/utils.unit.test.js.map +1 -0
  66. package/lib/common-logic/index.d.ts +2 -0
  67. package/lib/common-logic/index.d.ts.map +1 -0
  68. package/lib/common-logic/index.js +13 -0
  69. package/lib/common-logic/index.js.map +1 -0
  70. package/lib/common-logic/utils.d.ts +22 -0
  71. package/lib/common-logic/utils.d.ts.map +1 -0
  72. package/lib/common-logic/utils.js +189 -0
  73. package/lib/common-logic/utils.js.map +1 -0
  74. package/lib/erc20/ERC20.json +12 -0
  75. package/lib/erc20/tokenAccounts.d.ts +10 -0
  76. package/lib/erc20/tokenAccounts.d.ts.map +1 -0
  77. package/lib/erc20/tokenAccounts.js +169 -0
  78. package/lib/erc20/tokenAccounts.js.map +1 -0
  79. package/lib/errors.d.ts +7 -0
  80. package/lib/errors.d.ts.map +1 -0
  81. package/lib/errors.js +13 -0
  82. package/lib/errors.js.map +1 -0
  83. package/lib/hw-signMessage.d.ts +12 -0
  84. package/lib/hw-signMessage.d.ts.map +1 -0
  85. package/lib/hw-signMessage.js +32 -0
  86. package/lib/hw-signMessage.js.map +1 -0
  87. package/lib/index.d.ts +2 -0
  88. package/lib/index.d.ts.map +1 -0
  89. package/lib/index.js +6 -0
  90. package/lib/index.js.map +1 -0
  91. package/lib/network/addresses.d.ts +16 -0
  92. package/lib/network/addresses.d.ts.map +1 -0
  93. package/lib/network/addresses.js +75 -0
  94. package/lib/network/addresses.js.map +1 -0
  95. package/lib/network/index.d.ts +2 -0
  96. package/lib/network/index.d.ts.map +1 -0
  97. package/lib/network/index.js +18 -0
  98. package/lib/network/index.js.map +1 -0
  99. package/lib/signer/getAddress.d.ts +6 -0
  100. package/lib/signer/getAddress.d.ts.map +1 -0
  101. package/lib/signer/getAddress.js +30 -0
  102. package/lib/signer/getAddress.js.map +1 -0
  103. package/lib/signer/index.d.ts +3 -0
  104. package/lib/signer/index.d.ts.map +1 -0
  105. package/lib/signer/index.js +8 -0
  106. package/lib/signer/index.js.map +1 -0
  107. package/lib/test/bot-specs.d.ts +7 -0
  108. package/lib/test/bot-specs.d.ts.map +1 -0
  109. package/lib/test/bot-specs.js +151 -0
  110. package/lib/test/bot-specs.js.map +1 -0
  111. package/lib/test/bridgeDatasetTest.d.ts +4 -0
  112. package/lib/test/bridgeDatasetTest.d.ts.map +1 -0
  113. package/lib/test/bridgeDatasetTest.js +401 -0
  114. package/lib/test/bridgeDatasetTest.js.map +1 -0
  115. package/lib/test/cli.d.ts +19 -0
  116. package/lib/test/cli.d.ts.map +1 -0
  117. package/lib/test/cli.js +59 -0
  118. package/lib/test/cli.js.map +1 -0
  119. package/lib/test/index.d.ts +6 -0
  120. package/lib/test/index.d.ts.map +1 -0
  121. package/lib/test/index.js +26 -0
  122. package/lib/test/index.js.map +1 -0
  123. package/lib/test/speculos-deviceActions.d.ts +5 -0
  124. package/lib/test/speculos-deviceActions.d.ts.map +1 -0
  125. package/lib/test/speculos-deviceActions.js +159 -0
  126. package/lib/test/speculos-deviceActions.js.map +1 -0
  127. package/lib/types/bridge.d.ts +35 -0
  128. package/lib/types/bridge.d.ts.map +1 -0
  129. package/lib/types/bridge.js +3 -0
  130. package/lib/types/bridge.js.map +1 -0
  131. package/lib/types/common.d.ts +96 -0
  132. package/lib/types/common.d.ts.map +1 -0
  133. package/lib/types/common.js +10 -0
  134. package/lib/types/common.js.map +1 -0
  135. package/lib/types/index.d.ts +4 -0
  136. package/lib/types/index.d.ts.map +1 -0
  137. package/lib/types/index.js +20 -0
  138. package/lib/types/index.js.map +1 -0
  139. package/lib/types/signer.d.ts +19 -0
  140. package/lib/types/signer.d.ts.map +1 -0
  141. package/lib/types/signer.js +3 -0
  142. package/lib/types/signer.js.map +1 -0
  143. package/lib-es/api/api.d.ts +9 -0
  144. package/lib-es/api/api.d.ts.map +1 -0
  145. package/lib-es/api/api.js +87 -0
  146. package/lib-es/api/api.js.map +1 -0
  147. package/lib-es/api/index.d.ts +2 -0
  148. package/lib-es/api/index.d.ts.map +1 -0
  149. package/lib-es/api/index.js +2 -0
  150. package/lib-es/api/index.js.map +1 -0
  151. package/lib-es/bridge/broadcast.d.ts +4 -0
  152. package/lib-es/bridge/broadcast.d.ts.map +1 -0
  153. package/lib-es/bridge/broadcast.js +23 -0
  154. package/lib-es/bridge/broadcast.js.map +1 -0
  155. package/lib-es/bridge/buildOptimisticOperation.d.ts +5 -0
  156. package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -0
  157. package/lib-es/bridge/buildOptimisticOperation.js +58 -0
  158. package/lib-es/bridge/buildOptimisticOperation.js.map +1 -0
  159. package/lib-es/bridge/createTransaction.d.ts +4 -0
  160. package/lib-es/bridge/createTransaction.d.ts.map +1 -0
  161. package/lib-es/bridge/createTransaction.js +17 -0
  162. package/lib-es/bridge/createTransaction.js.map +1 -0
  163. package/lib-es/bridge/deviceTransactionConfig.d.ts +33 -0
  164. package/lib-es/bridge/deviceTransactionConfig.d.ts.map +1 -0
  165. package/lib-es/bridge/deviceTransactionConfig.js +69 -0
  166. package/lib-es/bridge/deviceTransactionConfig.js.map +1 -0
  167. package/lib-es/bridge/estimateMaxSpendable.d.ts +4 -0
  168. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -0
  169. package/lib-es/bridge/estimateMaxSpendable.js +93 -0
  170. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -0
  171. package/lib-es/bridge/getTransactionStatus.d.ts +4 -0
  172. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -0
  173. package/lib-es/bridge/getTransactionStatus.js +80 -0
  174. package/lib-es/bridge/getTransactionStatus.js.map +1 -0
  175. package/lib-es/bridge/index.d.ts +8 -0
  176. package/lib-es/bridge/index.d.ts.map +1 -0
  177. package/lib-es/bridge/index.js +47 -0
  178. package/lib-es/bridge/index.js.map +1 -0
  179. package/lib-es/bridge/prepareTransaction.d.ts +4 -0
  180. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -0
  181. package/lib-es/bridge/prepareTransaction.js +68 -0
  182. package/lib-es/bridge/prepareTransaction.js.map +1 -0
  183. package/lib-es/bridge/serializer.d.ts +13 -0
  184. package/lib-es/bridge/serializer.d.ts.map +1 -0
  185. package/lib-es/bridge/serializer.js +58 -0
  186. package/lib-es/bridge/serializer.js.map +1 -0
  187. package/lib-es/bridge/signOperation.d.ts +5 -0
  188. package/lib-es/bridge/signOperation.d.ts.map +1 -0
  189. package/lib-es/bridge/signOperation.js +76 -0
  190. package/lib-es/bridge/signOperation.js.map +1 -0
  191. package/lib-es/bridge/transaction.d.ts +14 -0
  192. package/lib-es/bridge/transaction.d.ts.map +1 -0
  193. package/lib-es/bridge/transaction.js +33 -0
  194. package/lib-es/bridge/transaction.js.map +1 -0
  195. package/lib-es/bridge/utils.d.ts +26 -0
  196. package/lib-es/bridge/utils.d.ts.map +1 -0
  197. package/lib-es/bridge/utils.js +57 -0
  198. package/lib-es/bridge/utils.js.map +1 -0
  199. package/lib-es/bridge/utils.unit.test.d.ts +2 -0
  200. package/lib-es/bridge/utils.unit.test.d.ts.map +1 -0
  201. package/lib-es/bridge/utils.unit.test.js +21 -0
  202. package/lib-es/bridge/utils.unit.test.js.map +1 -0
  203. package/lib-es/common-logic/index.d.ts +2 -0
  204. package/lib-es/common-logic/index.d.ts.map +1 -0
  205. package/lib-es/common-logic/index.js +2 -0
  206. package/lib-es/common-logic/index.js.map +1 -0
  207. package/lib-es/common-logic/utils.d.ts +22 -0
  208. package/lib-es/common-logic/utils.d.ts.map +1 -0
  209. package/lib-es/common-logic/utils.js +175 -0
  210. package/lib-es/common-logic/utils.js.map +1 -0
  211. package/lib-es/erc20/ERC20.json +12 -0
  212. package/lib-es/erc20/tokenAccounts.d.ts +10 -0
  213. package/lib-es/erc20/tokenAccounts.d.ts.map +1 -0
  214. package/lib-es/erc20/tokenAccounts.js +158 -0
  215. package/lib-es/erc20/tokenAccounts.js.map +1 -0
  216. package/lib-es/errors.d.ts +7 -0
  217. package/lib-es/errors.d.ts.map +1 -0
  218. package/lib-es/errors.js +10 -0
  219. package/lib-es/errors.js.map +1 -0
  220. package/lib-es/hw-signMessage.d.ts +12 -0
  221. package/lib-es/hw-signMessage.d.ts.map +1 -0
  222. package/lib-es/hw-signMessage.js +28 -0
  223. package/lib-es/hw-signMessage.js.map +1 -0
  224. package/lib-es/index.d.ts +2 -0
  225. package/lib-es/index.d.ts.map +1 -0
  226. package/lib-es/index.js +2 -0
  227. package/lib-es/index.js.map +1 -0
  228. package/lib-es/network/addresses.d.ts +16 -0
  229. package/lib-es/network/addresses.d.ts.map +1 -0
  230. package/lib-es/network/addresses.js +64 -0
  231. package/lib-es/network/addresses.js.map +1 -0
  232. package/lib-es/network/index.d.ts +2 -0
  233. package/lib-es/network/index.d.ts.map +1 -0
  234. package/lib-es/network/index.js +2 -0
  235. package/lib-es/network/index.js.map +1 -0
  236. package/lib-es/signer/getAddress.d.ts +6 -0
  237. package/lib-es/signer/getAddress.d.ts.map +1 -0
  238. package/lib-es/signer/getAddress.js +28 -0
  239. package/lib-es/signer/getAddress.js.map +1 -0
  240. package/lib-es/signer/index.d.ts +3 -0
  241. package/lib-es/signer/index.d.ts.map +1 -0
  242. package/lib-es/signer/index.js +3 -0
  243. package/lib-es/signer/index.js.map +1 -0
  244. package/lib-es/test/bot-specs.d.ts +7 -0
  245. package/lib-es/test/bot-specs.d.ts.map +1 -0
  246. package/lib-es/test/bot-specs.js +146 -0
  247. package/lib-es/test/bot-specs.js.map +1 -0
  248. package/lib-es/test/bridgeDatasetTest.d.ts +4 -0
  249. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -0
  250. package/lib-es/test/bridgeDatasetTest.js +395 -0
  251. package/lib-es/test/bridgeDatasetTest.js.map +1 -0
  252. package/lib-es/test/cli.d.ts +19 -0
  253. package/lib-es/test/cli.d.ts.map +1 -0
  254. package/lib-es/test/cli.js +53 -0
  255. package/lib-es/test/cli.js.map +1 -0
  256. package/lib-es/test/index.d.ts +6 -0
  257. package/lib-es/test/index.d.ts.map +1 -0
  258. package/lib-es/test/index.js +6 -0
  259. package/lib-es/test/index.js.map +1 -0
  260. package/lib-es/test/speculos-deviceActions.d.ts +5 -0
  261. package/lib-es/test/speculos-deviceActions.d.ts.map +1 -0
  262. package/lib-es/test/speculos-deviceActions.js +152 -0
  263. package/lib-es/test/speculos-deviceActions.js.map +1 -0
  264. package/lib-es/types/bridge.d.ts +35 -0
  265. package/lib-es/types/bridge.d.ts.map +1 -0
  266. package/lib-es/types/bridge.js +2 -0
  267. package/lib-es/types/bridge.js.map +1 -0
  268. package/lib-es/types/common.d.ts +96 -0
  269. package/lib-es/types/common.d.ts.map +1 -0
  270. package/lib-es/types/common.js +7 -0
  271. package/lib-es/types/common.js.map +1 -0
  272. package/lib-es/types/index.d.ts +4 -0
  273. package/lib-es/types/index.d.ts.map +1 -0
  274. package/lib-es/types/index.js +4 -0
  275. package/lib-es/types/index.js.map +1 -0
  276. package/lib-es/types/signer.d.ts +19 -0
  277. package/lib-es/types/signer.d.ts.map +1 -0
  278. package/lib-es/types/signer.js +2 -0
  279. package/lib-es/types/signer.js.map +1 -0
  280. package/package.json +135 -0
  281. package/src/api/api.ts +125 -0
  282. package/src/api/index.ts +1 -0
  283. package/src/bridge/broadcast.ts +20 -0
  284. package/src/bridge/buildOptimisticOperation.ts +58 -0
  285. package/src/bridge/createTransaction.ts +20 -0
  286. package/src/bridge/deviceTransactionConfig.ts +119 -0
  287. package/src/bridge/estimateMaxSpendable.ts +120 -0
  288. package/src/bridge/getTransactionStatus.ts +80 -0
  289. package/src/bridge/index.ts +63 -0
  290. package/src/bridge/prepareTransaction.ts +82 -0
  291. package/src/bridge/serializer.ts +63 -0
  292. package/src/bridge/signOperation.ts +97 -0
  293. package/src/bridge/transaction.ts +69 -0
  294. package/src/bridge/utils.ts +73 -0
  295. package/src/bridge/utils.unit.test.ts +27 -0
  296. package/src/common-logic/index.ts +10 -0
  297. package/src/common-logic/utils.ts +232 -0
  298. package/src/erc20/ERC20.json +12 -0
  299. package/src/erc20/tokenAccounts.ts +183 -0
  300. package/src/errors.ts +13 -0
  301. package/src/hw-signMessage.ts +27 -0
  302. package/src/index.ts +1 -0
  303. package/src/network/addresses.ts +93 -0
  304. package/src/network/index.ts +1 -0
  305. package/src/signer/getAddress.ts +28 -0
  306. package/src/signer/index.ts +3 -0
  307. package/src/test/bot-specs.ts +163 -0
  308. package/src/test/bridgeDatasetTest.ts +403 -0
  309. package/src/test/cli.ts +80 -0
  310. package/src/test/index.ts +6 -0
  311. package/src/test/speculos-deviceActions.ts +166 -0
  312. package/src/types/bridge.ts +42 -0
  313. package/src/types/common.ts +105 -0
  314. package/src/types/index.ts +3 -0
  315. package/src/types/signer.ts +19 -0
  316. package/tsconfig.json +14 -0
@@ -0,0 +1,58 @@
1
+ import { Account, Operation, OperationType } from "@ledgerhq/types-live";
2
+ import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
3
+ import { Transaction } from "../types";
4
+ import { toCBORResponse } from "../bridge/serializer";
5
+ import { calculateEstimatedFees } from "../bridge/utils";
6
+ import { convertAddressEthToFil } from "../network";
7
+ import { getSubAccount } from "../common-logic/utils";
8
+
9
+ export const buildOptimisticOperation = async (
10
+ account: Account,
11
+ transaction: Transaction,
12
+ serializationRes: toCBORResponse,
13
+ operationType: OperationType = "OUT",
14
+ ): Promise<Operation> => {
15
+ const type = operationType;
16
+ const subAccount = getSubAccount(account, transaction);
17
+ // resolved at broadcast time
18
+ const txHash = "";
19
+ const { gasFeeCap, gasLimit } = transaction;
20
+ const { parsedSender, recipientToBroadcast, amountToBroadcast: finalAmount } = serializationRes;
21
+ const fee = calculateEstimatedFees(gasFeeCap, gasLimit);
22
+
23
+ let operation: Operation;
24
+ if (subAccount) {
25
+ const recipientFilAddr = convertAddressEthToFil(transaction.recipient);
26
+ operation = {
27
+ id: encodeOperationId(subAccount.id, txHash, "OUT"),
28
+ hash: txHash,
29
+ type,
30
+ value: finalAmount,
31
+ fee,
32
+ blockHeight: null,
33
+ blockHash: null,
34
+ accountId: subAccount.id,
35
+ senders: [parsedSender],
36
+ recipients: [recipientFilAddr],
37
+ date: new Date(),
38
+ extra: {},
39
+ };
40
+ } else {
41
+ operation = {
42
+ id: encodeOperationId(account.id, txHash, "OUT"),
43
+ hash: txHash,
44
+ type,
45
+ senders: [parsedSender],
46
+ recipients: [recipientToBroadcast],
47
+ accountId: account.id,
48
+ value: finalAmount.plus(fee),
49
+ fee,
50
+ blockHash: null,
51
+ blockHeight: null,
52
+ date: new Date(),
53
+ extra: {},
54
+ };
55
+ }
56
+
57
+ return operation;
58
+ };
@@ -0,0 +1,20 @@
1
+ import { AccountBridge } from "@ledgerhq/types-live";
2
+ import { Transaction } from "../types";
3
+ import BigNumber from "bignumber.js";
4
+
5
+ export const createTransaction: AccountBridge<Transaction>["createTransaction"] = () => {
6
+ // log("debug", "[createTransaction] creating base tx");
7
+
8
+ return {
9
+ family: "filecoin",
10
+ amount: new BigNumber(0),
11
+ method: 0,
12
+ version: 0,
13
+ nonce: 0,
14
+ gasLimit: new BigNumber(0),
15
+ gasFeeCap: new BigNumber(0),
16
+ gasPremium: new BigNumber(0),
17
+ recipient: "",
18
+ useAllAmount: false,
19
+ };
20
+ };
@@ -0,0 +1,119 @@
1
+ import type { CommonDeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
2
+ import type { Account, AccountLike, TokenAccount } from "@ledgerhq/types-live";
3
+ import type { Transaction, TransactionStatus } from "../types";
4
+ import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies/index";
5
+ import {
6
+ AccountType,
7
+ Methods,
8
+ expectedToFieldForTokenTransfer,
9
+ getAccountUnit,
10
+ methodToString,
11
+ } from "./utils";
12
+ import { validateAddress } from "../network";
13
+
14
+ export type ExtraDeviceTransactionField =
15
+ | {
16
+ type: "filecoin.gasFeeCap";
17
+ label: string;
18
+ value: string;
19
+ }
20
+ | {
21
+ type: "filecoin.gasPremium";
22
+ label: string;
23
+ value: string;
24
+ }
25
+ | {
26
+ type: "filecoin.gasLimit";
27
+ label: string;
28
+ value: string;
29
+ }
30
+ | {
31
+ type: "filecoin.method";
32
+ label: string;
33
+ value: string;
34
+ }
35
+ | {
36
+ type: "filecoin.recipient";
37
+ label: string;
38
+ value: string;
39
+ };
40
+
41
+ export type DeviceTransactionField = CommonDeviceTransactionField | ExtraDeviceTransactionField;
42
+
43
+ function getDeviceTransactionConfig(input: {
44
+ account: AccountLike;
45
+ parentAccount: Account | null | undefined;
46
+ transaction: Transaction;
47
+ status: TransactionStatus;
48
+ }): Array<DeviceTransactionField> {
49
+ const tokenTransfer = input.account.type === AccountType.TokenAccount;
50
+ const subAccount = tokenTransfer ? (input.account as TokenAccount) : null;
51
+
52
+ const fields: Array<DeviceTransactionField> = [];
53
+ const unit = input.parentAccount
54
+ ? input.parentAccount.currency.units[0]
55
+ : getAccountUnit(input.account);
56
+ const formatConfig = {
57
+ disableRounding: true,
58
+ alwaysShowSign: false,
59
+ showCode: false,
60
+ };
61
+
62
+ if (subAccount) {
63
+ fields.push({
64
+ type: "filecoin.recipient",
65
+ label: "To",
66
+ value: expectedToFieldForTokenTransfer(input.transaction.recipient),
67
+ });
68
+ } else {
69
+ const recipient = input.transaction.recipient;
70
+ if (recipient.length >= 4 && recipient.substring(0, 4) === "0xff") {
71
+ const validated = validateAddress(recipient);
72
+ if (validated.isValid) {
73
+ const value = validated.parsedAddress.toString();
74
+ fields.push({
75
+ type: "filecoin.recipient",
76
+ label: "To",
77
+ value,
78
+ });
79
+ }
80
+ }
81
+ }
82
+
83
+ fields.push({
84
+ type: "filecoin.gasLimit",
85
+ label: "Gas Limit",
86
+ value: formatCurrencyUnit(unit, input.transaction.gasLimit, formatConfig),
87
+ });
88
+
89
+ if (!subAccount) {
90
+ fields.push({
91
+ type: "filecoin.gasFeeCap",
92
+ label: "Gas Fee Cap",
93
+ value: formatCurrencyUnit(unit, input.transaction.gasFeeCap, formatConfig),
94
+ });
95
+
96
+ fields.push({
97
+ type: "filecoin.gasPremium",
98
+ label: "Gas Premium",
99
+ value: formatCurrencyUnit(unit, input.transaction.gasPremium, formatConfig),
100
+ });
101
+ fields.push({
102
+ type: "filecoin.method",
103
+ label: "Method",
104
+ value: methodToString(input.transaction.method),
105
+ });
106
+ }
107
+
108
+ if (subAccount) {
109
+ fields.push({
110
+ type: "filecoin.method",
111
+ label: "Method",
112
+ value: methodToString(Methods.ERC20Transfer),
113
+ });
114
+ }
115
+
116
+ return fields;
117
+ }
118
+
119
+ export default getDeviceTransactionConfig;
@@ -0,0 +1,120 @@
1
+ import { AccountBridge, TokenAccount } from "@ledgerhq/types-live";
2
+ import { Transaction } from "../types";
3
+ import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
4
+ import { getAddress, getSubAccount } from "../common-logic";
5
+ import { AccountType, Methods, calculateEstimatedFees } from "./utils";
6
+ import {
7
+ InvalidAddress,
8
+ NotEnoughBalanceInParentAccount,
9
+ NotEnoughSpendableBalance,
10
+ } from "@ledgerhq/errors";
11
+ import { isFilEthAddress, validateAddress } from "../network";
12
+ import { fetchBalances, fetchEstimatedFees } from "../api";
13
+ import BigNumber from "bignumber.js";
14
+ import { BroadcastBlockIncl } from "../types";
15
+ import { encodeTxnParams, generateTokenTxnParams } from "../erc20/tokenAccounts";
16
+
17
+ export const estimateMaxSpendable: AccountBridge<Transaction>["estimateMaxSpendable"] = async ({
18
+ account,
19
+ parentAccount,
20
+ transaction,
21
+ }) => {
22
+ // log("debug", "[estimateMaxSpendable] start fn");
23
+ if (transaction && !transaction.subAccountId) {
24
+ transaction.subAccountId = account.type === "Account" ? null : account.id;
25
+ }
26
+
27
+ let tokenAccountTxn: boolean = false;
28
+ let subAccount: TokenAccount | undefined | null;
29
+ const a = getMainAccount(account, parentAccount);
30
+ if (account.type === AccountType.TokenAccount) {
31
+ tokenAccountTxn = true;
32
+ subAccount = account;
33
+ }
34
+ if (transaction && transaction.subAccountId && !subAccount) {
35
+ tokenAccountTxn = true;
36
+ subAccount = getSubAccount(a, transaction) ?? null;
37
+ }
38
+
39
+ let { address: sender } = getAddress(a);
40
+
41
+ let methodNum = Methods.Transfer;
42
+ let recipient = transaction?.recipient;
43
+
44
+ const invalidAddressErr = new InvalidAddress(undefined, {
45
+ currencyName: subAccount ? subAccount.token.name : a.currency.name,
46
+ });
47
+
48
+ const senderValidation = validateAddress(sender);
49
+ if (!senderValidation.isValid) throw invalidAddressErr;
50
+ sender = senderValidation.parsedAddress.toString();
51
+
52
+ if (recipient) {
53
+ const recipientValidation = validateAddress(recipient);
54
+ if (!recipientValidation.isValid) {
55
+ throw invalidAddressErr;
56
+ }
57
+ recipient = recipientValidation.parsedAddress.toString();
58
+
59
+ methodNum =
60
+ isFilEthAddress(recipientValidation.parsedAddress) || tokenAccountTxn
61
+ ? Methods.InvokeEVM
62
+ : Methods.Transfer;
63
+ }
64
+
65
+ let balance = new BigNumber((await fetchBalances(sender)).spendable_balance);
66
+
67
+ if (balance.eq(0)) return balance;
68
+
69
+ const validatedContractAddress = validateAddress(subAccount?.token.contractAddress ?? "");
70
+ if (tokenAccountTxn && !validatedContractAddress.isValid) {
71
+ throw invalidAddressErr;
72
+ }
73
+ const contractAddress =
74
+ tokenAccountTxn && validatedContractAddress.isValid
75
+ ? validatedContractAddress.parsedAddress.toString()
76
+ : "";
77
+ const finalRecipient = tokenAccountTxn ? contractAddress : recipient;
78
+
79
+ // If token transfer, the evm payload is required to estimate fees
80
+ const params =
81
+ tokenAccountTxn && transaction && subAccount
82
+ ? generateTokenTxnParams(
83
+ contractAddress,
84
+ transaction.amount.isZero() ? BigNumber(1) : transaction.amount,
85
+ )
86
+ : undefined;
87
+
88
+ const result = await fetchEstimatedFees({
89
+ to: finalRecipient,
90
+ from: sender,
91
+ methodNum,
92
+ blockIncl: BroadcastBlockIncl,
93
+ ...(params && { params: encodeTxnParams(params) }), // If token transfer, the eth call params are required to estimate fees
94
+ ...(tokenAccountTxn && { value: "0" }), // If token transfer, the value should be 0 (avoid any native token transfer on fee estimation)
95
+ });
96
+
97
+ const gasFeeCap = new BigNumber(result.gas_fee_cap);
98
+ const gasLimit = new BigNumber(result.gas_limit);
99
+ const estimatedFees = calculateEstimatedFees(gasFeeCap, gasLimit);
100
+
101
+ if (balance.lte(estimatedFees)) {
102
+ if (tokenAccountTxn) {
103
+ throw new NotEnoughBalanceInParentAccount(undefined, {
104
+ currencyName: a.currency.name,
105
+ });
106
+ }
107
+
108
+ throw new NotEnoughSpendableBalance(undefined, {
109
+ currencyName: a.currency.name,
110
+ });
111
+ }
112
+ balance = balance.minus(estimatedFees);
113
+
114
+ if (tokenAccountTxn && subAccount) {
115
+ return subAccount.spendableBalance;
116
+ }
117
+ // log("debug", "[estimateMaxSpendable] finish fn");
118
+
119
+ return balance;
120
+ };
@@ -0,0 +1,80 @@
1
+ import {
2
+ AmountRequired,
3
+ FeeNotLoaded,
4
+ InvalidAddress,
5
+ NotEnoughBalance,
6
+ RecipientRequired,
7
+ } from "@ledgerhq/errors";
8
+ import { Account, AccountBridge } from "@ledgerhq/types-live";
9
+ import { Transaction, TransactionStatus } from "../types";
10
+ import { isRecipientValidForTokenTransfer, validateAddress } from "../network";
11
+ import { getAddress, getSubAccount } from "../common-logic";
12
+ import { calculateEstimatedFees } from "./utils";
13
+ import { InvalidRecipientForTokenTransfer } from "../errors";
14
+ import BigNumber from "bignumber.js";
15
+
16
+ export const getTransactionStatus: AccountBridge<Transaction>["getTransactionStatus"] = async (
17
+ account: Account,
18
+ transaction: Transaction,
19
+ ): Promise<TransactionStatus> => {
20
+ // log("debug", "[getTransactionStatus] start fn");
21
+ const errors: TransactionStatus["errors"] = {};
22
+ const warnings: TransactionStatus["warnings"] = {};
23
+ const { balance } = account;
24
+ const { address } = getAddress(account);
25
+ const subAccount = getSubAccount(account, transaction);
26
+ const { recipient, useAllAmount, gasPremium, gasFeeCap, gasLimit } = transaction;
27
+ let { amount } = transaction;
28
+ const invalidAddressErr = new InvalidAddress(undefined, {
29
+ currencyName: account.currency.name,
30
+ });
31
+ if (!recipient) errors.recipient = new RecipientRequired();
32
+ else if (!validateAddress(recipient).isValid) errors.recipient = invalidAddressErr;
33
+ else if (!validateAddress(address).isValid) errors.sender = invalidAddressErr;
34
+ if (gasFeeCap.eq(0) || gasPremium.eq(0) || gasLimit.eq(0)) errors.gas = new FeeNotLoaded();
35
+ // This is the worst case scenario (the tx won't cost more than this value)
36
+ const estimatedFees = calculateEstimatedFees(gasFeeCap, gasLimit);
37
+ let totalSpent: BigNumber;
38
+ if (useAllAmount && !subAccount) {
39
+ totalSpent = account.spendableBalance;
40
+ amount = totalSpent.minus(estimatedFees);
41
+ if (amount.lte(0) || totalSpent.gt(balance)) {
42
+ errors.amount = new NotEnoughBalance();
43
+ }
44
+ }
45
+
46
+ if (subAccount) {
47
+ totalSpent = estimatedFees;
48
+ if (totalSpent.gt(account.spendableBalance)) errors.amount = new NotEnoughBalance();
49
+ } else {
50
+ totalSpent = amount.plus(estimatedFees);
51
+ if (amount.eq(0)) {
52
+ errors.amount = new AmountRequired();
53
+ } else if (totalSpent.gt(account.spendableBalance)) errors.amount = new NotEnoughBalance();
54
+ }
55
+
56
+ if (subAccount) {
57
+ const spendable = subAccount.spendableBalance;
58
+ if (transaction.amount.gt(spendable)) {
59
+ errors.amount = new NotEnoughBalance();
60
+ }
61
+ if (useAllAmount) {
62
+ amount = spendable;
63
+ }
64
+ totalSpent = amount;
65
+
66
+ if (recipient && !isRecipientValidForTokenTransfer(recipient)) {
67
+ errors.recipient = new InvalidRecipientForTokenTransfer();
68
+ }
69
+ }
70
+
71
+ // log("debug", "[getTransactionStatus] finish fn");
72
+
73
+ return {
74
+ errors,
75
+ warnings,
76
+ estimatedFees,
77
+ amount,
78
+ totalSpent,
79
+ };
80
+ };
@@ -0,0 +1,63 @@
1
+ import {
2
+ makeAccountBridgeReceive,
3
+ makeScanAccounts,
4
+ makeSync,
5
+ } from "@ledgerhq/coin-framework/bridge/jsHelpers";
6
+ import resolver from "../signer";
7
+ import getAddressWrapper from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
8
+ import { SignerContext } from "@ledgerhq/coin-framework/signer";
9
+ import type { Account, AccountBridge, CurrencyBridge } from "@ledgerhq/types-live";
10
+ import { defaultUpdateTransaction } from "@ledgerhq/coin-framework/bridge/jsHelpers";
11
+ import type { Transaction, TransactionStatus, FilecoinSigner } from "../types";
12
+ import { getTransactionStatus } from "./getTransactionStatus";
13
+ import { estimateMaxSpendable } from "./estimateMaxSpendable";
14
+ import { prepareTransaction } from "./prepareTransaction";
15
+ import { createTransaction } from "./createTransaction";
16
+ import { getAccountShape } from "../common-logic/utils";
17
+ import { buildSignOperation } from "./signOperation";
18
+ import { broadcast } from "./broadcast";
19
+
20
+ function buildCurrencyBridge(signerContext: SignerContext<FilecoinSigner>): CurrencyBridge {
21
+ const getAddress = resolver(signerContext);
22
+
23
+ const scanAccounts = makeScanAccounts({
24
+ getAccountShape,
25
+ getAddressFn: getAddressWrapper(getAddress),
26
+ });
27
+
28
+ return {
29
+ preload: () => Promise.resolve({}),
30
+ hydrate: () => {},
31
+ scanAccounts,
32
+ };
33
+ }
34
+
35
+ const sync = makeSync({ getAccountShape });
36
+
37
+ function buildAccountBridge(
38
+ signerContext: SignerContext<FilecoinSigner>,
39
+ ): AccountBridge<Transaction, Account, TransactionStatus> {
40
+ const getAddress = resolver(signerContext);
41
+
42
+ const receive = makeAccountBridgeReceive(getAddressWrapper(getAddress));
43
+ const signOperation = buildSignOperation(signerContext);
44
+
45
+ return {
46
+ estimateMaxSpendable,
47
+ createTransaction,
48
+ updateTransaction: defaultUpdateTransaction,
49
+ getTransactionStatus,
50
+ prepareTransaction,
51
+ sync,
52
+ receive,
53
+ signOperation,
54
+ broadcast,
55
+ };
56
+ }
57
+
58
+ export function createBridges(signerContext: SignerContext<FilecoinSigner>) {
59
+ return {
60
+ currencyBridge: buildCurrencyBridge(signerContext),
61
+ accountBridge: buildAccountBridge(signerContext),
62
+ };
63
+ }
@@ -0,0 +1,82 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { AccountBridge } from "@ledgerhq/types-live";
3
+ import { defaultUpdateTransaction } from "@ledgerhq/coin-framework/bridge/jsHelpers";
4
+ import { isEthereumConvertableAddr, isFilEthAddress, validateAddress } from "../network";
5
+ import { BroadcastBlockIncl, Transaction } from "../types";
6
+ import { Methods, calculateEstimatedFees } from "./utils";
7
+ import { fetchEstimatedFees } from "../api/index";
8
+ import { getAddress, getSubAccount } from "../common-logic/utils";
9
+ import { encodeTxnParams, generateTokenTxnParams } from "../erc20/tokenAccounts";
10
+
11
+ export const prepareTransaction: AccountBridge<Transaction>["prepareTransaction"] = async (
12
+ account,
13
+ transaction,
14
+ ) => {
15
+ const { balance } = account;
16
+ const { address } = getAddress(account);
17
+ const { useAllAmount } = transaction;
18
+ const recipient = transaction.recipient.toLowerCase();
19
+
20
+ const subAccount = getSubAccount(account, transaction);
21
+ const tokenAccountTxn = !!subAccount;
22
+
23
+ if (recipient && address) {
24
+ const recipientValidation = validateAddress(recipient);
25
+ const senderValidation = validateAddress(address);
26
+
27
+ if (recipientValidation.isValid && senderValidation.isValid) {
28
+ const patch: Partial<Transaction> = {};
29
+
30
+ const method =
31
+ isFilEthAddress(recipientValidation.parsedAddress) || tokenAccountTxn
32
+ ? Methods.InvokeEVM
33
+ : Methods.Transfer;
34
+
35
+ const validatedContractAddress = validateAddress(subAccount?.token.contractAddress ?? "");
36
+ let finalRecipient = recipientValidation;
37
+ let params: string | undefined = undefined;
38
+ // used as fallback only for estimation of fees
39
+ let fallbackParams: string = "";
40
+ if (tokenAccountTxn && validatedContractAddress.isValid) {
41
+ finalRecipient = validatedContractAddress;
42
+ // If token transfer, the evm payload is required to estimate fees
43
+ if (isEthereumConvertableAddr(recipientValidation.parsedAddress)) {
44
+ params = generateTokenTxnParams(
45
+ recipient,
46
+ transaction.amount.isZero() ? BigNumber(1) : transaction.amount,
47
+ );
48
+ } else {
49
+ fallbackParams = generateTokenTxnParams(subAccount.token.contractAddress, BigNumber(1));
50
+ }
51
+ }
52
+
53
+ const paramsForEstimation = params ? params : fallbackParams;
54
+ const result = await fetchEstimatedFees({
55
+ to: finalRecipient.parsedAddress.toString(),
56
+ from: senderValidation.parsedAddress.toString(),
57
+ methodNum: method,
58
+ blockIncl: BroadcastBlockIncl,
59
+ ...(tokenAccountTxn && { params: encodeTxnParams(paramsForEstimation) }), // If token transfer, the eth call params are required to estimate fees
60
+ ...(tokenAccountTxn && { value: "0" }), // If token transfer, the value should be 0 (avoid any native token transfer on fee estimation)
61
+ });
62
+
63
+ patch.gasFeeCap = new BigNumber(result.gas_fee_cap);
64
+ patch.gasPremium = new BigNumber(result.gas_premium);
65
+ patch.gasLimit = new BigNumber(result.gas_limit);
66
+ patch.nonce = result.nonce;
67
+ patch.method = method;
68
+ patch.params = params;
69
+
70
+ const fee = calculateEstimatedFees(patch.gasFeeCap, patch.gasLimit);
71
+ if (useAllAmount) {
72
+ patch.amount = subAccount ? subAccount.spendableBalance : balance.minus(fee);
73
+ patch.params =
74
+ tokenAccountTxn && params ? generateTokenTxnParams(recipient, patch.amount) : undefined;
75
+ }
76
+
77
+ return defaultUpdateTransaction(transaction, patch);
78
+ }
79
+ }
80
+
81
+ return transaction;
82
+ };
@@ -0,0 +1,63 @@
1
+ import { Account } from "@ledgerhq/types-live";
2
+
3
+ import { Transaction } from "../types";
4
+ import { getAddress, getSubAccount } from "../common-logic/index";
5
+ import { validateAddress } from "../network";
6
+ import { Message } from "iso-filecoin/message";
7
+ import { encodeTxnParams } from "../erc20/tokenAccounts";
8
+ import BigNumber from "bignumber.js";
9
+ import { AccountType } from "./utils";
10
+
11
+ export interface toCBORResponse {
12
+ txPayload: Buffer;
13
+ recipientToBroadcast: string;
14
+ parsedSender: string;
15
+ encodedParams: string;
16
+ amountToBroadcast: BigNumber;
17
+ }
18
+
19
+ export const toCBOR = async (account: Account, tx: Transaction): Promise<toCBORResponse> => {
20
+ const { address: from } = getAddress(account);
21
+ const { method, version, nonce, gasLimit, gasPremium, gasFeeCap, amount, recipient } = tx;
22
+ const recipientValidation = validateAddress(recipient);
23
+ const fromValidation = validateAddress(from);
24
+
25
+ const subAccount = getSubAccount(account, tx);
26
+ const tokenTransfer = subAccount && subAccount.type === AccountType.TokenAccount;
27
+ const params = tokenTransfer ? encodeTxnParams(tx.params ?? "") : undefined;
28
+
29
+ if (!recipientValidation.isValid || !fromValidation.isValid)
30
+ throw new Error("recipient and/or from address are not valid");
31
+
32
+ let finalRecipient: string;
33
+ if (tokenTransfer) {
34
+ const validated = validateAddress(subAccount.token.contractAddress);
35
+ if (!validated.isValid) throw new Error("token contract address is not valid");
36
+ finalRecipient = validated.parsedAddress.toString();
37
+ } else {
38
+ finalRecipient = recipientValidation.parsedAddress.toString();
39
+ }
40
+
41
+ const finalAmount = tokenTransfer ? "0" : amount.toString();
42
+
43
+ const message = new Message({
44
+ to: finalRecipient,
45
+ from: fromValidation.parsedAddress.toString(),
46
+ gasFeeCap: gasFeeCap.toString(),
47
+ gasLimit: gasLimit.toNumber(),
48
+ gasPremium: gasPremium.toString(),
49
+ method,
50
+ nonce,
51
+ params,
52
+ version: version === 0 ? 0 : undefined,
53
+ value: finalAmount,
54
+ });
55
+
56
+ return {
57
+ txPayload: message.serialize(),
58
+ recipientToBroadcast: finalRecipient,
59
+ parsedSender: fromValidation.parsedAddress.toString(),
60
+ encodedParams: params ?? "",
61
+ amountToBroadcast: new BigNumber(finalAmount),
62
+ };
63
+ };