@ledgerhq/live-common 22.3.0-universal.0 → 23.0.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/lib/__tests__/test-helpers/setup.js +2 -0
  2. package/lib/__tests__/test-helpers/setup.js.map +1 -1
  3. package/lib/account/pending.d.ts +2 -1
  4. package/lib/account/pending.d.ts.map +1 -1
  5. package/lib/account/serialization.d.ts +3 -1
  6. package/lib/account/serialization.d.ts.map +1 -1
  7. package/lib/account/serialization.js +12 -3
  8. package/lib/account/serialization.js.map +1 -1
  9. package/lib/cross.d.ts.map +1 -1
  10. package/lib/cross.js +2 -1
  11. package/lib/cross.js.map +1 -1
  12. package/lib/derivation.d.ts +10 -1
  13. package/lib/derivation.d.ts.map +1 -1
  14. package/lib/derivation.js +28 -5
  15. package/lib/derivation.js.map +1 -1
  16. package/lib/env.d.ts +20 -5
  17. package/lib/env.d.ts.map +1 -1
  18. package/lib/env.js +16 -1
  19. package/lib/env.js.map +1 -1
  20. package/lib/env.react.d.ts +1 -1
  21. package/lib/env.react.d.ts.map +1 -1
  22. package/lib/errors.d.ts +1 -0
  23. package/lib/errors.d.ts.map +1 -1
  24. package/lib/errors.js +1 -0
  25. package/lib/errors.js.map +1 -1
  26. package/lib/families/algorand/js-synchronization.d.ts +2 -2
  27. package/lib/families/bitcoin/exchange.d.ts +1 -1
  28. package/lib/families/bitcoin/js-synchronisation.d.ts +2 -2
  29. package/lib/families/cardano/api/api-types.d.ts +38 -0
  30. package/lib/families/cardano/api/api-types.d.ts.map +1 -0
  31. package/lib/families/cardano/api/api-types.js +3 -0
  32. package/lib/families/cardano/api/api-types.js.map +1 -0
  33. package/lib/families/cardano/api/getNetworkInfo.d.ts +4 -0
  34. package/lib/families/cardano/api/getNetworkInfo.d.ts.map +1 -0
  35. package/lib/families/cardano/api/getNetworkInfo.js +83 -0
  36. package/lib/families/cardano/api/getNetworkInfo.js.map +1 -0
  37. package/lib/families/cardano/api/getTransactions.d.ts +10 -0
  38. package/lib/families/cardano/api/getTransactions.d.ts.map +1 -0
  39. package/lib/families/cardano/api/getTransactions.js +257 -0
  40. package/lib/families/cardano/api/getTransactions.js.map +1 -0
  41. package/lib/families/cardano/api/submitTransaction.d.ts +7 -0
  42. package/lib/families/cardano/api/submitTransaction.d.ts.map +1 -0
  43. package/lib/families/cardano/api/submitTransaction.js +69 -0
  44. package/lib/families/cardano/api/submitTransaction.js.map +1 -0
  45. package/lib/families/cardano/bridge/js.d.ts +8 -0
  46. package/lib/families/cardano/bridge/js.d.ts.map +1 -0
  47. package/lib/families/cardano/bridge/js.js +69 -0
  48. package/lib/families/cardano/bridge/js.js.map +1 -0
  49. package/lib/families/cardano/bridge.test.d.ts +2 -0
  50. package/lib/families/cardano/bridge.test.d.ts.map +1 -0
  51. package/lib/families/cardano/bridge.test.js +11 -0
  52. package/lib/families/cardano/bridge.test.js.map +1 -0
  53. package/lib/families/cardano/buildSubAccounts.d.ts +25 -0
  54. package/lib/families/cardano/buildSubAccounts.d.ts.map +1 -0
  55. package/lib/families/cardano/buildSubAccounts.js +176 -0
  56. package/lib/families/cardano/buildSubAccounts.js.map +1 -0
  57. package/lib/families/cardano/cli-transaction.d.ts +19 -0
  58. package/lib/families/cardano/cli-transaction.d.ts.map +1 -0
  59. package/lib/families/cardano/cli-transaction.js +70 -0
  60. package/lib/families/cardano/cli-transaction.js.map +1 -0
  61. package/lib/families/cardano/constants.d.ts +8 -0
  62. package/lib/families/cardano/constants.d.ts.map +1 -0
  63. package/lib/families/cardano/constants.js +12 -0
  64. package/lib/families/cardano/constants.js.map +1 -0
  65. package/lib/families/cardano/datasets/rawAccount.1.d.ts +3 -0
  66. package/lib/families/cardano/datasets/rawAccount.1.d.ts.map +1 -0
  67. package/lib/families/cardano/datasets/rawAccount.1.js +27 -0
  68. package/lib/families/cardano/datasets/rawAccount.1.js.map +1 -0
  69. package/lib/families/cardano/datasets/scanAccounts.d.ts +5 -0
  70. package/lib/families/cardano/datasets/scanAccounts.d.ts.map +1 -0
  71. package/lib/families/cardano/datasets/scanAccounts.js +10 -0
  72. package/lib/families/cardano/datasets/scanAccounts.js.map +1 -0
  73. package/lib/families/cardano/errors.d.ts +7 -0
  74. package/lib/families/cardano/errors.d.ts.map +1 -0
  75. package/lib/families/cardano/errors.js +9 -0
  76. package/lib/families/cardano/errors.js.map +1 -0
  77. package/lib/families/cardano/hw-getAddress.d.ts +4 -0
  78. package/lib/families/cardano/hw-getAddress.d.ts.map +1 -0
  79. package/lib/families/cardano/hw-getAddress.js +126 -0
  80. package/lib/families/cardano/hw-getAddress.js.map +1 -0
  81. package/lib/families/cardano/js-broadcast.d.ts +8 -0
  82. package/lib/families/cardano/js-broadcast.d.ts.map +1 -0
  83. package/lib/families/cardano/js-broadcast.js +65 -0
  84. package/lib/families/cardano/js-broadcast.js.map +1 -0
  85. package/lib/families/cardano/js-buildTransaction.d.ts +12 -0
  86. package/lib/families/cardano/js-buildTransaction.d.ts.map +1 -0
  87. package/lib/families/cardano/js-buildTransaction.js +253 -0
  88. package/lib/families/cardano/js-buildTransaction.js.map +1 -0
  89. package/lib/families/cardano/js-estimateMaxSpendable.d.ts +15 -0
  90. package/lib/families/cardano/js-estimateMaxSpendable.d.ts.map +1 -0
  91. package/lib/families/cardano/js-estimateMaxSpendable.js +99 -0
  92. package/lib/families/cardano/js-estimateMaxSpendable.js.map +1 -0
  93. package/lib/families/cardano/js-getFeesForTransaction.d.ts +15 -0
  94. package/lib/families/cardano/js-getFeesForTransaction.d.ts.map +1 -0
  95. package/lib/families/cardano/js-getFeesForTransaction.js +61 -0
  96. package/lib/families/cardano/js-getFeesForTransaction.js.map +1 -0
  97. package/lib/families/cardano/js-getTransactionStatus.d.ts +5 -0
  98. package/lib/families/cardano/js-getTransactionStatus.d.ts.map +1 -0
  99. package/lib/families/cardano/js-getTransactionStatus.js +156 -0
  100. package/lib/families/cardano/js-getTransactionStatus.js.map +1 -0
  101. package/lib/families/cardano/js-signOperation.d.ts +13 -0
  102. package/lib/families/cardano/js-signOperation.d.ts.map +1 -0
  103. package/lib/families/cardano/js-signOperation.js +274 -0
  104. package/lib/families/cardano/js-signOperation.js.map +1 -0
  105. package/lib/families/cardano/js-synchronisation.d.ts +11 -0
  106. package/lib/families/cardano/js-synchronisation.d.ts.map +1 -0
  107. package/lib/families/cardano/js-synchronisation.js +247 -0
  108. package/lib/families/cardano/js-synchronisation.js.map +1 -0
  109. package/lib/families/cardano/js-transaction.d.ts +23 -0
  110. package/lib/families/cardano/js-transaction.d.ts.map +1 -0
  111. package/lib/families/cardano/js-transaction.js +112 -0
  112. package/lib/families/cardano/js-transaction.js.map +1 -0
  113. package/lib/families/cardano/logic.d.ts +92 -0
  114. package/lib/families/cardano/logic.d.ts.map +1 -0
  115. package/lib/families/cardano/logic.js +378 -0
  116. package/lib/families/cardano/logic.js.map +1 -0
  117. package/lib/families/cardano/networks.d.ts +3 -0
  118. package/lib/families/cardano/networks.d.ts.map +1 -0
  119. package/lib/families/cardano/networks.js +34 -0
  120. package/lib/families/cardano/networks.js.map +1 -0
  121. package/lib/families/cardano/postSyncPatch.d.ts +7 -0
  122. package/lib/families/cardano/postSyncPatch.d.ts.map +1 -0
  123. package/lib/families/cardano/postSyncPatch.js +37 -0
  124. package/lib/families/cardano/postSyncPatch.js.map +1 -0
  125. package/lib/families/cardano/serialization.d.ts +4 -0
  126. package/lib/families/cardano/serialization.d.ts.map +1 -0
  127. package/lib/families/cardano/serialization.js +121 -0
  128. package/lib/families/cardano/serialization.js.map +1 -0
  129. package/lib/families/cardano/specs.d.ts +7 -0
  130. package/lib/families/cardano/specs.d.ts.map +1 -0
  131. package/lib/families/cardano/specs.js +83 -0
  132. package/lib/families/cardano/specs.js.map +1 -0
  133. package/lib/families/cardano/speculos-deviceActions.d.ts +7 -0
  134. package/lib/families/cardano/speculos-deviceActions.d.ts.map +1 -0
  135. package/lib/families/cardano/speculos-deviceActions.js +69 -0
  136. package/lib/families/cardano/speculos-deviceActions.js.map +1 -0
  137. package/lib/families/cardano/test-dataset.d.ts +5 -0
  138. package/lib/families/cardano/test-dataset.d.ts.map +1 -0
  139. package/lib/families/cardano/test-dataset.js +42 -0
  140. package/lib/families/cardano/test-dataset.js.map +1 -0
  141. package/lib/families/cardano/transaction.d.ts +12 -0
  142. package/lib/families/cardano/transaction.d.ts.map +1 -0
  143. package/lib/families/cardano/transaction.js +47 -0
  144. package/lib/families/cardano/transaction.js.map +1 -0
  145. package/lib/families/cardano/types.d.ts +152 -0
  146. package/lib/families/cardano/types.d.ts.map +1 -0
  147. package/lib/families/cardano/types.js +18 -0
  148. package/lib/families/cardano/types.js.map +1 -0
  149. package/lib/families/celo/js-synchronisation.d.ts +2 -2
  150. package/lib/families/cosmos/js-synchronisation.d.ts +2 -2
  151. package/lib/families/crypto_org/js-synchronisation.d.ts +2 -2
  152. package/lib/families/elrond/js-synchronisation.d.ts +2 -2
  153. package/lib/families/ethereum/hw-signMessage.d.ts.map +1 -1
  154. package/lib/families/ethereum/hw-signMessage.js +10 -4
  155. package/lib/families/ethereum/hw-signMessage.js.map +1 -1
  156. package/lib/families/filecoin/bridge/account.js +18 -14
  157. package/lib/families/filecoin/bridge/account.js.map +1 -1
  158. package/lib/families/filecoin/bridge/utils/types.d.ts +1 -1
  159. package/lib/families/filecoin/bridge/utils/types.d.ts.map +1 -1
  160. package/lib/families/filecoin/bridge/utils/utils.d.ts +1 -1
  161. package/lib/families/filecoin/bridge/utils/utils.d.ts.map +1 -1
  162. package/lib/families/filecoin/bridge/utils/utils.js +9 -8
  163. package/lib/families/filecoin/bridge/utils/utils.js.map +1 -1
  164. package/lib/families/filecoin/bridge.test.d.ts +2 -0
  165. package/lib/families/filecoin/bridge.test.d.ts.map +1 -0
  166. package/lib/families/filecoin/bridge.test.js +92 -0
  167. package/lib/families/filecoin/bridge.test.js.map +1 -0
  168. package/lib/families/filecoin/specs.d.ts.map +1 -1
  169. package/lib/families/filecoin/specs.js +1 -2
  170. package/lib/families/filecoin/specs.js.map +1 -1
  171. package/lib/families/filecoin/test-dataset.d.ts.map +1 -1
  172. package/lib/families/filecoin/test-dataset.js +8 -9
  173. package/lib/families/filecoin/test-dataset.js.map +1 -1
  174. package/lib/families/hedera/js-synchronisation.d.ts +2 -2
  175. package/lib/families/polkadot/js-synchronisation.d.ts +2 -2
  176. package/lib/families/ripple/js-synchronization.d.ts +2 -2
  177. package/lib/families/stellar/js-synchronization.d.ts +2 -2
  178. package/lib/generated/bridge/js.d.ts +4 -0
  179. package/lib/generated/bridge/js.d.ts.map +1 -1
  180. package/lib/generated/bridge/js.js +30 -28
  181. package/lib/generated/bridge/js.js.map +1 -1
  182. package/lib/generated/cli-transaction.d.ts +15 -0
  183. package/lib/generated/cli-transaction.d.ts.map +1 -1
  184. package/lib/generated/cli-transaction.js +28 -26
  185. package/lib/generated/cli-transaction.js.map +1 -1
  186. package/lib/generated/exchange.d.ts +1 -1
  187. package/lib/generated/hw-getAddress.d.ts +1 -0
  188. package/lib/generated/hw-getAddress.d.ts.map +1 -1
  189. package/lib/generated/hw-getAddress.js +30 -28
  190. package/lib/generated/hw-getAddress.js.map +1 -1
  191. package/lib/generated/specs.d.ts +3 -0
  192. package/lib/generated/specs.d.ts.map +1 -1
  193. package/lib/generated/specs.js +28 -26
  194. package/lib/generated/specs.js.map +1 -1
  195. package/lib/generated/speculos-deviceActions.d.ts +3 -0
  196. package/lib/generated/speculos-deviceActions.d.ts.map +1 -1
  197. package/lib/generated/speculos-deviceActions.js +28 -26
  198. package/lib/generated/speculos-deviceActions.js.map +1 -1
  199. package/lib/generated/test-dataset.d.ts +1 -0
  200. package/lib/generated/test-dataset.d.ts.map +1 -1
  201. package/lib/generated/test-dataset.js +26 -24
  202. package/lib/generated/test-dataset.js.map +1 -1
  203. package/lib/generated/transaction.d.ts +5 -0
  204. package/lib/generated/transaction.d.ts.map +1 -1
  205. package/lib/generated/transaction.js +30 -28
  206. package/lib/generated/transaction.js.map +1 -1
  207. package/lib/generated/types.d.ts +4 -2
  208. package/lib/generated/types.d.ts.map +1 -1
  209. package/lib/reconciliation.d.ts.map +1 -1
  210. package/lib/reconciliation.js +6 -0
  211. package/lib/reconciliation.js.map +1 -1
  212. package/lib/types/account.d.ts +3 -0
  213. package/lib/types/account.d.ts.map +1 -1
  214. package/package.json +5 -3
  215. package/src/__tests__/test-helpers/setup.ts +2 -0
  216. package/src/account/serialization.ts +15 -0
  217. package/src/cross.ts +2 -1
  218. package/src/derivation.ts +19 -2
  219. package/src/env.ts +16 -1
  220. package/src/errors.ts +1 -0
  221. package/src/families/cardano/__snapshots__/bridge.test.ts.snap +1667 -0
  222. package/src/families/cardano/api/api-types.ts +33 -0
  223. package/src/families/cardano/api/getNetworkInfo.ts +38 -0
  224. package/src/families/cardano/api/getTransactions.ts +240 -0
  225. package/src/families/cardano/api/submitTransaction.ts +27 -0
  226. package/src/families/cardano/bridge/js.ts +35 -0
  227. package/src/families/cardano/bridge.test.ts +6 -0
  228. package/src/families/cardano/buildSubAccounts.ts +182 -0
  229. package/src/families/cardano/cli-transaction.ts +78 -0
  230. package/src/families/cardano/constants.ts +12 -0
  231. package/src/families/cardano/datasets/rawAccount.1.ts +28 -0
  232. package/src/families/cardano/datasets/scanAccounts.ts +23 -0
  233. package/src/families/cardano/errors.ts +8 -0
  234. package/src/families/cardano/hw-getAddress.ts +61 -0
  235. package/src/families/cardano/js-broadcast.ts +25 -0
  236. package/src/families/cardano/js-buildTransaction.ts +293 -0
  237. package/src/families/cardano/js-estimateMaxSpendable.ts +60 -0
  238. package/src/families/cardano/js-getFeesForTransaction.ts +25 -0
  239. package/src/families/cardano/js-getTransactionStatus.ts +123 -0
  240. package/src/families/cardano/js-signOperation.ts +265 -0
  241. package/src/families/cardano/js-synchronisation.ts +255 -0
  242. package/src/families/cardano/js-transaction.ts +69 -0
  243. package/src/families/cardano/logic.ts +454 -0
  244. package/src/families/cardano/networks.ts +33 -0
  245. package/src/families/cardano/postSyncPatch.ts +45 -0
  246. package/src/families/cardano/serialization.ts +179 -0
  247. package/src/families/cardano/specs.ts +96 -0
  248. package/src/families/cardano/speculos-deviceActions.ts +66 -0
  249. package/src/families/cardano/test-dataset.ts +41 -0
  250. package/src/families/cardano/transaction.ts +55 -0
  251. package/src/families/cardano/types.ts +178 -0
  252. package/src/families/ethereum/hw-signMessage.ts +9 -5
  253. package/src/families/filecoin/__snapshots__/bridge.test.ts.snap +87 -0
  254. package/src/families/filecoin/bridge/account.ts +20 -20
  255. package/src/families/filecoin/bridge/utils/types.ts +1 -1
  256. package/src/families/filecoin/bridge/utils/utils.ts +8 -7
  257. package/src/families/filecoin/bridge.test.ts +39 -0
  258. package/src/families/filecoin/specs.ts +1 -2
  259. package/src/families/filecoin/test-dataset.ts +19 -15
  260. package/src/generated/bridge/js.ts +3 -0
  261. package/src/generated/cli-transaction.ts +3 -0
  262. package/src/generated/hw-getAddress.ts +3 -0
  263. package/src/generated/specs.ts +3 -0
  264. package/src/generated/speculos-deviceActions.ts +3 -0
  265. package/src/generated/test-dataset.ts +3 -0
  266. package/src/generated/transaction.ts +3 -0
  267. package/src/generated/types.ts +4 -0
  268. package/src/reconciliation.ts +10 -0
  269. package/src/types/account.ts +6 -0
@@ -0,0 +1,265 @@
1
+ import { BigNumber } from "bignumber.js";
2
+ import { Observable } from "rxjs";
3
+ import { FeeNotLoaded } from "@ledgerhq/errors";
4
+
5
+ import type { CardanoResources, Transaction } from "./types";
6
+ import type {
7
+ Account,
8
+ Operation,
9
+ SignedOperation,
10
+ SignOperationEvent,
11
+ } from "../../types";
12
+
13
+ import { withDevice } from "../../hw/deviceAccess";
14
+ import { encodeOperationId } from "../../operation";
15
+
16
+ import { buildTransaction } from "./js-buildTransaction";
17
+
18
+ import Ada, {
19
+ Networks,
20
+ SignTransactionRequest,
21
+ TransactionSigningMode,
22
+ TxAuxiliaryDataType,
23
+ Witness,
24
+ } from "@cardano-foundation/ledgerjs-hw-app-cardano";
25
+ import {
26
+ types as TyphonTypes,
27
+ Transaction as TyphonTransaction,
28
+ } from "@stricahq/typhonjs";
29
+ import { Bip32PublicKey } from "@stricahq/bip32ed25519";
30
+ import {
31
+ getExtendedPublicKeyFromHex,
32
+ getOperationType,
33
+ prepareLedgerInput,
34
+ prepareLedgerOutput,
35
+ } from "./logic";
36
+ import ShelleyTypeAddress from "@stricahq/typhonjs/dist/address/ShelleyTypeAddress";
37
+ import { getNetworkParameters } from "./networks";
38
+ import { MEMO_LABEL } from "./constants";
39
+
40
+ const buildOptimisticOperation = (
41
+ account: Account,
42
+ transaction: TyphonTransaction,
43
+ t: Transaction
44
+ ): Operation => {
45
+ const cardanoResources = account.cardanoResources as CardanoResources;
46
+ const accountCreds = new Set(
47
+ [
48
+ ...cardanoResources.externalCredentials,
49
+ ...cardanoResources.internalCredentials,
50
+ ].map((cred) => cred.key)
51
+ );
52
+
53
+ const accountInput = transaction
54
+ .getInputs()
55
+ .reduce(
56
+ (total, i) =>
57
+ accountCreds.has(i.address.paymentCredential.hash)
58
+ ? total.plus(i.amount)
59
+ : total.plus(0),
60
+ new BigNumber(0)
61
+ );
62
+
63
+ const accountOutput = transaction
64
+ .getOutputs()
65
+ .reduce(
66
+ (total, o) =>
67
+ o.address instanceof ShelleyTypeAddress &&
68
+ accountCreds.has(o.address.paymentCredential.hash)
69
+ ? total.plus(o.amount)
70
+ : total.plus(0),
71
+ new BigNumber(0)
72
+ );
73
+
74
+ const accountChange = accountOutput.minus(accountInput);
75
+ const opType = getOperationType({
76
+ valueChange: accountChange,
77
+ fees: transaction.getFee(),
78
+ });
79
+ const transactionHash = transaction.getTransactionHash().toString("hex");
80
+ const auxiliaryData = transaction.getAuxiliaryData();
81
+ let memo;
82
+ if (auxiliaryData) {
83
+ const memoMetadata = auxiliaryData.metadata.find(
84
+ (m) => m.label === MEMO_LABEL
85
+ );
86
+ if (memoMetadata && Array.isArray(memoMetadata.data)) {
87
+ memo = memoMetadata.data.join(", ");
88
+ }
89
+ }
90
+
91
+ const op: Operation = {
92
+ id: encodeOperationId(account.id, transactionHash, opType),
93
+ hash: transactionHash,
94
+ type: opType,
95
+ value: accountChange.absoluteValue(),
96
+ fee: transaction.getFee(),
97
+ blockHash: undefined,
98
+ blockHeight: null,
99
+ senders: transaction.getInputs().map((i) => i.address.getBech32()),
100
+ recipients: transaction.getOutputs().map((o) => o.address.getBech32()),
101
+ accountId: account.id,
102
+ date: new Date(),
103
+ extra: {
104
+ memo,
105
+ },
106
+ };
107
+
108
+ const tokenAccount = t.subAccountId
109
+ ? account.subAccounts?.find((ta) => ta.id === t.subAccountId)
110
+ : null;
111
+
112
+ if (tokenAccount && opType === "OUT") {
113
+ op.subOperations = [
114
+ {
115
+ id: encodeOperationId(tokenAccount.id, transactionHash, opType),
116
+ hash: transactionHash,
117
+ type: opType,
118
+ value: t.useAllAmount ? tokenAccount.balance : t.amount,
119
+ fee: t.fees as BigNumber,
120
+ blockHash: undefined,
121
+ blockHeight: null,
122
+ senders: transaction.getInputs().map((i) => i.address.getBech32()),
123
+ recipients: transaction.getOutputs().map((o) => o.address.getBech32()),
124
+ accountId: tokenAccount.id,
125
+ date: new Date(),
126
+ extra: {},
127
+ },
128
+ ];
129
+ }
130
+
131
+ return op;
132
+ };
133
+
134
+ /**
135
+ * Adds signatures to unsigned transaction
136
+ */
137
+ const signTx = (
138
+ unsignedTransaction: TyphonTransaction,
139
+ accountKey: Bip32PublicKey,
140
+ witnesses: Array<Witness>
141
+ ) => {
142
+ witnesses.forEach((witness) => {
143
+ const [, , , chainType, index] = witness.path;
144
+ const publicKey = accountKey
145
+ .derive(chainType)
146
+ .derive(index)
147
+ .toPublicKey()
148
+ .toBytes();
149
+ const vKeyWitness: TyphonTypes.VKeyWitness = {
150
+ signature: Buffer.from(witness.witnessSignatureHex, "hex"),
151
+ publicKey: Buffer.from(publicKey),
152
+ };
153
+ unsignedTransaction.addWitness(vKeyWitness);
154
+ });
155
+
156
+ return unsignedTransaction.buildTransaction();
157
+ };
158
+
159
+ /**
160
+ * Sign Transaction with Ledger hardware
161
+ */
162
+ const signOperation = ({
163
+ account,
164
+ deviceId,
165
+ transaction,
166
+ }: {
167
+ account: Account;
168
+ deviceId: string;
169
+ transaction: Transaction;
170
+ }): Observable<SignOperationEvent> =>
171
+ withDevice(deviceId)(
172
+ (transport) =>
173
+ new Observable((o) => {
174
+ async function main() {
175
+ o.next({ type: "device-signature-requested" });
176
+
177
+ if (!transaction.fees) {
178
+ throw new FeeNotLoaded();
179
+ }
180
+
181
+ const unsignedTransaction = await buildTransaction(
182
+ account,
183
+ transaction
184
+ );
185
+
186
+ const accountPubKey = getExtendedPublicKeyFromHex(
187
+ account.xpub as string
188
+ );
189
+
190
+ const rawInputs = unsignedTransaction.getInputs();
191
+ const ledgerAppInputs = rawInputs.map((i) =>
192
+ prepareLedgerInput(i, account.index)
193
+ );
194
+
195
+ const rawOutptus = unsignedTransaction.getOutputs();
196
+ const ledgerAppOutputs = rawOutptus.map((o) =>
197
+ prepareLedgerOutput(o, account.index)
198
+ );
199
+
200
+ const auxiliaryDataHashHex =
201
+ unsignedTransaction.getAuxiliaryDataHashHex();
202
+
203
+ const networkParams = getNetworkParameters(account.currency.id);
204
+ const network =
205
+ networkParams.networkId === Networks.Mainnet.networkId
206
+ ? Networks.Mainnet
207
+ : Networks.Testnet;
208
+
209
+ const trxOptions: SignTransactionRequest = {
210
+ signingMode: TransactionSigningMode.ORDINARY_TRANSACTION,
211
+ tx: {
212
+ network,
213
+ inputs: ledgerAppInputs,
214
+ outputs: ledgerAppOutputs,
215
+ certificates: [],
216
+ withdrawals: [],
217
+ fee: unsignedTransaction.getFee().toString(),
218
+ ttl: unsignedTransaction.getTTL()?.toString(),
219
+ validityIntervalStart: null,
220
+ auxiliaryData: auxiliaryDataHashHex
221
+ ? {
222
+ type: TxAuxiliaryDataType.ARBITRARY_HASH,
223
+ params: {
224
+ hashHex: auxiliaryDataHashHex,
225
+ },
226
+ }
227
+ : null,
228
+ },
229
+ additionalWitnessPaths: [],
230
+ };
231
+
232
+ // Sign by device
233
+ const appAda = new Ada(transport);
234
+ const r = await appAda.signTransaction(trxOptions);
235
+ const signed = signTx(
236
+ unsignedTransaction,
237
+ accountPubKey,
238
+ r.witnesses
239
+ );
240
+
241
+ o.next({ type: "device-signature-granted" });
242
+
243
+ const operation = buildOptimisticOperation(
244
+ account,
245
+ unsignedTransaction,
246
+ transaction
247
+ );
248
+
249
+ o.next({
250
+ type: "signed",
251
+ signedOperation: {
252
+ operation,
253
+ signature: signed.payload,
254
+ expirationDate: null,
255
+ } as SignedOperation,
256
+ });
257
+ }
258
+ main().then(
259
+ () => o.complete(),
260
+ (e) => o.error(e)
261
+ );
262
+ })
263
+ );
264
+
265
+ export default signOperation;
@@ -0,0 +1,255 @@
1
+ import type { Operation, TokenAccount } from "../../types";
2
+ import {
3
+ GetAccountShape,
4
+ makeScanAccounts,
5
+ mergeOps,
6
+ } from "../../bridge/jsHelpers";
7
+ import { makeSync } from "../../bridge/jsHelpers";
8
+ import { encodeAccountId, inferSubOperations } from "../../account";
9
+
10
+ import BigNumber from "bignumber.js";
11
+ import Ada from "@cardano-foundation/ledgerjs-hw-app-cardano";
12
+ import { str_to_path } from "@cardano-foundation/ledgerjs-hw-app-cardano/dist/utils";
13
+ import { utils as TyphonUtils } from "@stricahq/typhonjs";
14
+ import { APITransaction } from "./api/api-types";
15
+ import { CardanoOutput, PaymentCredential } from "./types";
16
+ import {
17
+ getAccountChange,
18
+ getAccountStakeCredential,
19
+ getBaseAddress,
20
+ getBipPathString,
21
+ getMemoFromTx,
22
+ getOperationType,
23
+ isHexString,
24
+ } from "./logic";
25
+ import { encodeOperationId } from "../../operation";
26
+ import { getNetworkParameters } from "./networks";
27
+ import { getNetworkInfo } from "./api/getNetworkInfo";
28
+ import uniqBy from "lodash/uniqBy";
29
+ import postSyncPatch from "./postSyncPatch";
30
+ import { getTransactions } from "./api/getTransactions";
31
+
32
+ function mapTxToAccountOperation(
33
+ tx: APITransaction,
34
+ accountId: string,
35
+ accountCredentialsMap: Record<string, PaymentCredential>,
36
+ subAccounts: Array<TokenAccount>
37
+ ): Operation {
38
+ const accountChange = getAccountChange(tx, accountCredentialsMap);
39
+ const mainOperationType = getOperationType({
40
+ valueChange: accountChange.ada,
41
+ fees: new BigNumber(tx.fees),
42
+ });
43
+
44
+ const subOperations = inferSubOperations(tx.hash, subAccounts);
45
+ const memo = getMemoFromTx(tx);
46
+
47
+ return {
48
+ accountId,
49
+ id: encodeOperationId(accountId, tx.hash, mainOperationType),
50
+ hash: tx.hash,
51
+ type: mainOperationType,
52
+ fee: new BigNumber(tx.fees),
53
+ value: accountChange.ada.absoluteValue(),
54
+ senders: tx.inputs.map((i) =>
55
+ isHexString(i.address)
56
+ ? TyphonUtils.getAddressFromHex(i.address).getBech32()
57
+ : i.address
58
+ ),
59
+ recipients: tx.outputs.map((o) =>
60
+ isHexString(o.address)
61
+ ? TyphonUtils.getAddressFromHex(o.address).getBech32()
62
+ : o.address
63
+ ),
64
+ subOperations,
65
+ blockHeight: tx.blockHeight,
66
+ date: new Date(tx.timestamp),
67
+ extra: {
68
+ memo,
69
+ },
70
+ blockHash: undefined,
71
+ };
72
+ }
73
+
74
+ function syncUtxos(
75
+ newTransactions: Array<APITransaction>,
76
+ stableUtxos: Array<CardanoOutput>,
77
+ accountCredentialsMap: Record<string, PaymentCredential>
78
+ ): Array<CardanoOutput> {
79
+ const newUtxos: Array<CardanoOutput> = [];
80
+ // spentUtxoKey = txId#index
81
+ const spentUtxoKeys: Set<string> = new Set();
82
+
83
+ newTransactions.forEach((t) => {
84
+ t.inputs.forEach((i) => {
85
+ const cred = accountCredentialsMap[i.paymentKey];
86
+ if (cred) spentUtxoKeys.add(`${i.txId}#${i.index}`);
87
+ });
88
+
89
+ t.outputs.forEach((o, outputIndex) => {
90
+ const cred = accountCredentialsMap[o.paymentKey];
91
+ if (cred) {
92
+ newUtxos.push({
93
+ hash: t.hash,
94
+ index: outputIndex,
95
+ address: o.address,
96
+ amount: new BigNumber(o.value),
97
+ tokens: o.tokens.map((token) => ({
98
+ assetName: token.assetName,
99
+ policyId: token.policyId,
100
+ amount: new BigNumber(token.value),
101
+ })),
102
+ paymentCredential: {
103
+ key: o.paymentKey,
104
+ path: cred.path,
105
+ },
106
+ });
107
+ }
108
+ });
109
+ });
110
+
111
+ const utxos = uniqBy(
112
+ [...stableUtxos, ...newUtxos],
113
+ (u) => `${u.hash}#${u.index}`
114
+ ).filter((u) => !spentUtxoKeys.has(`${u.hash}#${u.index}`));
115
+
116
+ return utxos;
117
+ }
118
+
119
+ export const getAccountShape: GetAccountShape = async (info) => {
120
+ const {
121
+ transport,
122
+ currency,
123
+ index: accountIndex,
124
+ derivationPath,
125
+ derivationMode,
126
+ initialAccount,
127
+ } = info;
128
+ // In case we get a full derivation path
129
+ const rootPath = derivationPath.split("/", 2).join("/");
130
+ const accountPath = `${rootPath}/${accountIndex}'`;
131
+
132
+ const paramXpub = initialAccount?.xpub;
133
+ let extendedPubKeyRes;
134
+ if (!paramXpub) {
135
+ if (!transport) {
136
+ // hwapp not provided
137
+ throw new Error("hwapp required to generate the xpub");
138
+ }
139
+ const ada = new Ada(transport);
140
+ extendedPubKeyRes = await ada.getExtendedPublicKey({
141
+ path: str_to_path(accountPath),
142
+ });
143
+ }
144
+ const xpub =
145
+ paramXpub ||
146
+ `${extendedPubKeyRes.publicKeyHex}${extendedPubKeyRes.chainCodeHex}`;
147
+ const accountId = encodeAccountId({
148
+ type: "js",
149
+ version: "2",
150
+ currencyId: currency.id,
151
+ xpubOrAddress: xpub,
152
+ derivationMode,
153
+ });
154
+
155
+ const requiredConfirmations = 90;
156
+ const syncFromBlockHeight =
157
+ initialAccount?.blockHeight &&
158
+ initialAccount.blockHeight > requiredConfirmations
159
+ ? initialAccount.blockHeight - requiredConfirmations
160
+ : 0;
161
+
162
+ const {
163
+ transactions: newTransactions,
164
+ blockHeight,
165
+ externalCredentials,
166
+ internalCredentials,
167
+ } = await getTransactions(
168
+ xpub,
169
+ accountIndex,
170
+ initialAccount,
171
+ syncFromBlockHeight,
172
+ currency
173
+ );
174
+
175
+ const accountCredentialsMap = [
176
+ ...externalCredentials,
177
+ ...internalCredentials,
178
+ ].reduce((finalMap, cred) => {
179
+ finalMap[cred.key] = cred;
180
+ return finalMap;
181
+ }, {} as Record<string, PaymentCredential>);
182
+
183
+ const stableOperationsByIds: Record<string, Operation> = {};
184
+ (initialAccount?.operations || []).forEach((o) => {
185
+ if ((o.blockHeight as number) < syncFromBlockHeight) {
186
+ stableOperationsByIds[o.hash] = o;
187
+ }
188
+ });
189
+
190
+ const stableUtxos = (initialAccount?.cardanoResources?.utxos || []).filter(
191
+ (u) => stableOperationsByIds[u.hash]
192
+ );
193
+
194
+ const utxos = syncUtxos(newTransactions, stableUtxos, accountCredentialsMap);
195
+ const accountBalance = utxos.reduce(
196
+ (total, u) => total.plus(u.amount),
197
+ new BigNumber(0)
198
+ );
199
+ // const tokenBalance = mergeTokens(utxos.map((u) => u.tokens).flat());
200
+ // const subAccounts = buildSubAccounts({
201
+ // initialAccount,
202
+ // parentAccountId: accountId,
203
+ // parentCurrency: currency,
204
+ // newTransactions,
205
+ // tokens: tokenBalance,
206
+ // accountCredentialsMap,
207
+ // });
208
+ const subAccounts = [];
209
+
210
+ const newOperations = newTransactions.map((t) =>
211
+ mapTxToAccountOperation(t, accountId, accountCredentialsMap, subAccounts)
212
+ );
213
+
214
+ const operations = mergeOps(
215
+ Object.values(stableOperationsByIds),
216
+ newOperations
217
+ );
218
+
219
+ const stakeCredential = getAccountStakeCredential(xpub, accountIndex);
220
+ const networkParams = getNetworkParameters(currency.id);
221
+ const freshAddresses = externalCredentials
222
+ .filter((c) => !c.isUsed)
223
+ .map((c) => ({
224
+ derivationPath: getBipPathString(c.path),
225
+ address: getBaseAddress({
226
+ networkId: networkParams.networkId,
227
+ paymentCred: c,
228
+ stakeCred: stakeCredential,
229
+ }).getBech32(),
230
+ }));
231
+ const cardanoNetworkInfo = await getNetworkInfo(initialAccount, currency);
232
+
233
+ return {
234
+ id: accountId,
235
+ xpub,
236
+ balance: accountBalance,
237
+ spendableBalance: accountBalance,
238
+ operations: operations,
239
+ subAccounts,
240
+ freshAddresses,
241
+ freshAddress: freshAddresses[0].address,
242
+ freshAddressPath: freshAddresses[0].derivationPath,
243
+ blockHeight,
244
+ cardanoResources: {
245
+ utxos,
246
+ externalCredentials,
247
+ internalCredentials,
248
+ protocolParams: cardanoNetworkInfo.protocolParams,
249
+ },
250
+ };
251
+ };
252
+
253
+ export const scanAccounts = makeScanAccounts({ getAccountShape });
254
+
255
+ export const sync = makeSync({ getAccountShape, postSync: postSyncPatch });
@@ -0,0 +1,69 @@
1
+ import { BigNumber } from "bignumber.js";
2
+ import type { Account } from "../../types";
3
+ import { Transaction } from "./types";
4
+ import {
5
+ types as TyphonTypes,
6
+ address as TyphonAddress,
7
+ } from "@stricahq/typhonjs";
8
+
9
+ import { buildTransaction } from "./js-buildTransaction";
10
+
11
+ /**
12
+ * Create an empty transaction
13
+ *
14
+ * @returns {Transaction}
15
+ */
16
+ export const createTransaction = (): Transaction => ({
17
+ family: "cardano",
18
+ mode: "send",
19
+ amount: new BigNumber(0),
20
+ recipient: "",
21
+ useAllAmount: false,
22
+ fees: new BigNumber(0),
23
+ });
24
+
25
+ /**
26
+ * Apply patch to transaction
27
+ *
28
+ * @param {*} t
29
+ * @param {*} patch
30
+ */
31
+ export const updateTransaction = (
32
+ t: Transaction,
33
+ patch: Partial<Transaction>
34
+ ): Transaction => ({ ...t, ...patch });
35
+
36
+ /**
37
+ * Prepare transaction before checking status
38
+ *
39
+ * @param {Account} a
40
+ * @param {Transaction} t
41
+ */
42
+ export const prepareTransaction = async (
43
+ a: Account,
44
+ t: Transaction
45
+ ): Promise<Transaction> => {
46
+ let transaction;
47
+ try {
48
+ transaction = await buildTransaction(a, t);
49
+ } catch (error) {
50
+ return { ...t, fees: new BigNumber(0), amount: new BigNumber(0) };
51
+ }
52
+
53
+ const transactionFees = transaction.getFee();
54
+ const transactionAmount = t.subAccountId
55
+ ? t.amount
56
+ : transaction
57
+ .getOutputs()
58
+ .filter(
59
+ (o) =>
60
+ !(o.address instanceof TyphonAddress.BaseAddress) ||
61
+ !(
62
+ o.address.paymentCredential.type === TyphonTypes.HashType.ADDRESS
63
+ ) ||
64
+ o.address.paymentCredential.bipPath === undefined
65
+ )
66
+ .reduce((total, o) => total.plus(o.amount), new BigNumber(0));
67
+
68
+ return { ...t, fees: transactionFees, amount: transactionAmount };
69
+ };