@ledgerhq/live-common 21.4.1-btcjs.4 → 21.5.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 (169) hide show
  1. package/lib/account/addAccounts.d.ts.map +1 -1
  2. package/lib/account/addAccounts.js +1 -2
  3. package/lib/account/addAccounts.js.map +1 -1
  4. package/lib/account/support.d.ts.map +1 -1
  5. package/lib/account/support.js +1 -24
  6. package/lib/account/support.js.map +1 -1
  7. package/lib/api/explorerConfig/index.js +15 -15
  8. package/lib/apps/polyfill.d.ts.map +1 -1
  9. package/lib/apps/polyfill.js +5 -0
  10. package/lib/apps/polyfill.js.map +1 -1
  11. package/lib/bridge/jsHelpers.d.ts +1 -6
  12. package/lib/bridge/jsHelpers.d.ts.map +1 -1
  13. package/lib/bridge/jsHelpers.js +3 -11
  14. package/lib/bridge/jsHelpers.js.map +1 -1
  15. package/lib/env.js +2 -2
  16. package/lib/families/bitcoin/account.d.ts.map +1 -1
  17. package/lib/families/bitcoin/account.js +2 -3
  18. package/lib/families/bitcoin/account.js.map +1 -1
  19. package/lib/families/bitcoin/datasets/bitcoin.js +6 -6
  20. package/lib/families/bitcoin/datasets/bitcoin.js.map +1 -1
  21. package/lib/families/bitcoin/datasets/litecoin.js +3 -3
  22. package/lib/families/bitcoin/datasets/litecoin.js.map +1 -1
  23. package/lib/families/bitcoin/serialization.d.ts +2 -2
  24. package/lib/families/bitcoin/serialization.d.ts.map +1 -1
  25. package/lib/families/bitcoin/serialization.js +4 -8
  26. package/lib/families/bitcoin/serialization.js.map +1 -1
  27. package/lib/families/bitcoin/specs.d.ts.map +1 -1
  28. package/lib/families/bitcoin/specs.js +5 -8
  29. package/lib/families/bitcoin/specs.js.map +1 -1
  30. package/lib/families/bitcoin/speculos-deviceActions.js +2 -2
  31. package/lib/families/bitcoin/speculos-deviceActions.js.map +1 -1
  32. package/lib/families/bitcoin/test-dataset.js +1 -1
  33. package/lib/families/bitcoin/test-dataset.js.map +1 -1
  34. package/lib/families/bitcoin/transaction.d.ts +3 -3
  35. package/lib/families/bitcoin/transaction.d.ts.map +1 -1
  36. package/lib/families/bitcoin/transaction.js +61 -64
  37. package/lib/families/bitcoin/transaction.js.map +1 -1
  38. package/lib/families/bitcoin/types.d.ts +36 -66
  39. package/lib/families/bitcoin/types.d.ts.map +1 -1
  40. package/lib/families/bitcoin/types.js +1 -16
  41. package/lib/families/bitcoin/types.js.map +1 -1
  42. package/lib/families/crypto_org/logic.d.ts +1 -1
  43. package/lib/families/crypto_org/logic.js +7 -7
  44. package/lib/families/elrond/js-getTransactionStatus.d.ts.map +1 -1
  45. package/lib/families/elrond/js-getTransactionStatus.js +3 -0
  46. package/lib/families/elrond/js-getTransactionStatus.js.map +1 -1
  47. package/lib/families/elrond/js-signOperation.d.ts.map +1 -1
  48. package/lib/families/elrond/js-signOperation.js +10 -7
  49. package/lib/families/elrond/js-signOperation.js.map +1 -1
  50. package/lib/generated/bridge/js.d.ts +0 -4
  51. package/lib/generated/bridge/js.d.ts.map +1 -1
  52. package/lib/generated/bridge/js.js +18 -20
  53. package/lib/generated/bridge/js.js.map +1 -1
  54. package/lib/hw/actions/initSwap.js +2 -2
  55. package/lib/hw/actions/initSwap.js.map +1 -1
  56. package/lib/migrations/accounts-dataset.d.ts.map +1 -1
  57. package/lib/migrations/accounts-dataset.js +2 -4
  58. package/lib/migrations/accounts-dataset.js.map +1 -1
  59. package/lib/migrations/accounts.d.ts.map +1 -1
  60. package/lib/migrations/accounts.js +0 -17
  61. package/lib/migrations/accounts.js.map +1 -1
  62. package/lib/mock/account.d.ts.map +1 -1
  63. package/lib/mock/account.js +1 -2
  64. package/lib/mock/account.js.map +1 -1
  65. package/package.json +22 -22
  66. package/src/__tests__/__snapshots__/all.libcore.ts.snap +43 -6
  67. package/src/account/addAccounts.ts +1 -2
  68. package/src/account/support.ts +1 -24
  69. package/src/api/explorerConfig/index.ts +15 -15
  70. package/src/apps/polyfill.ts +5 -0
  71. package/src/bridge/jsHelpers.ts +2 -22
  72. package/src/env.ts +2 -2
  73. package/src/families/bitcoin/account.ts +1 -2
  74. package/src/families/bitcoin/datasets/bitcoin.ts +6 -6
  75. package/src/families/bitcoin/datasets/litecoin.ts +6 -6
  76. package/src/families/bitcoin/serialization.ts +0 -6
  77. package/src/families/bitcoin/specs.ts +2 -5
  78. package/src/families/bitcoin/speculos-deviceActions.ts +1 -1
  79. package/src/families/bitcoin/test-dataset.ts +1 -1
  80. package/src/families/bitcoin/transaction.ts +93 -98
  81. package/src/families/bitcoin/types.ts +37 -95
  82. package/src/families/crypto_org/logic.ts +6 -6
  83. package/src/families/elrond/js-getTransactionStatus.ts +5 -0
  84. package/src/families/elrond/js-signOperation.ts +1 -0
  85. package/src/generated/bridge/js.ts +0 -3
  86. package/src/hw/actions/initSwap.ts +2 -2
  87. package/src/migrations/accounts-dataset.ts +0 -3
  88. package/src/migrations/accounts.ts +0 -18
  89. package/src/mock/account.ts +0 -2
  90. package/lib/families/bitcoin/bridge/js.d.ts +0 -8
  91. package/lib/families/bitcoin/bridge/js.d.ts.map +0 -1
  92. package/lib/families/bitcoin/bridge/js.js +0 -149
  93. package/lib/families/bitcoin/bridge/js.js.map +0 -1
  94. package/lib/families/bitcoin/cache.d.ts +0 -28
  95. package/lib/families/bitcoin/cache.d.ts.map +0 -1
  96. package/lib/families/bitcoin/cache.js +0 -109
  97. package/lib/families/bitcoin/cache.js.map +0 -1
  98. package/lib/families/bitcoin/getAccountNetworkInfo.d.ts +0 -6
  99. package/lib/families/bitcoin/getAccountNetworkInfo.d.ts.map +0 -1
  100. package/lib/families/bitcoin/getAccountNetworkInfo.js +0 -124
  101. package/lib/families/bitcoin/getAccountNetworkInfo.js.map +0 -1
  102. package/lib/families/bitcoin/getAccountNetworkInfo.test.d.ts +0 -2
  103. package/lib/families/bitcoin/getAccountNetworkInfo.test.d.ts.map +0 -1
  104. package/lib/families/bitcoin/getAccountNetworkInfo.test.js +0 -71
  105. package/lib/families/bitcoin/getAccountNetworkInfo.test.js.map +0 -1
  106. package/lib/families/bitcoin/js-broadcast.d.ts +0 -11
  107. package/lib/families/bitcoin/js-broadcast.d.ts.map +0 -1
  108. package/lib/families/bitcoin/js-broadcast.js +0 -80
  109. package/lib/families/bitcoin/js-broadcast.js.map +0 -1
  110. package/lib/families/bitcoin/js-buildTransaction.d.ts +0 -5
  111. package/lib/families/bitcoin/js-buildTransaction.d.ts.map +0 -1
  112. package/lib/families/bitcoin/js-buildTransaction.js +0 -106
  113. package/lib/families/bitcoin/js-buildTransaction.js.map +0 -1
  114. package/lib/families/bitcoin/js-createTransaction.d.ts +0 -9
  115. package/lib/families/bitcoin/js-createTransaction.d.ts.map +0 -1
  116. package/lib/families/bitcoin/js-createTransaction.js +0 -27
  117. package/lib/families/bitcoin/js-createTransaction.js.map +0 -1
  118. package/lib/families/bitcoin/js-estimateMaxSpendable.d.ts +0 -15
  119. package/lib/families/bitcoin/js-estimateMaxSpendable.d.ts.map +0 -1
  120. package/lib/families/bitcoin/js-estimateMaxSpendable.js +0 -95
  121. package/lib/families/bitcoin/js-estimateMaxSpendable.js.map +0 -1
  122. package/lib/families/bitcoin/js-getFeesForTransaction.d.ts +0 -26
  123. package/lib/families/bitcoin/js-getFeesForTransaction.d.ts.map +0 -1
  124. package/lib/families/bitcoin/js-getFeesForTransaction.js +0 -100
  125. package/lib/families/bitcoin/js-getFeesForTransaction.js.map +0 -1
  126. package/lib/families/bitcoin/js-getTransactionStatus.d.ts +0 -5
  127. package/lib/families/bitcoin/js-getTransactionStatus.d.ts.map +0 -1
  128. package/lib/families/bitcoin/js-getTransactionStatus.js +0 -131
  129. package/lib/families/bitcoin/js-getTransactionStatus.js.map +0 -1
  130. package/lib/families/bitcoin/js-prepareTransaction.d.ts +0 -5
  131. package/lib/families/bitcoin/js-prepareTransaction.d.ts.map +0 -1
  132. package/lib/families/bitcoin/js-prepareTransaction.js +0 -80
  133. package/lib/families/bitcoin/js-prepareTransaction.js.map +0 -1
  134. package/lib/families/bitcoin/js-signOperation.d.ts +0 -10
  135. package/lib/families/bitcoin/js-signOperation.d.ts.map +0 -1
  136. package/lib/families/bitcoin/js-signOperation.js +0 -212
  137. package/lib/families/bitcoin/js-signOperation.js.map +0 -1
  138. package/lib/families/bitcoin/js-synchronisation.d.ts +0 -10
  139. package/lib/families/bitcoin/js-synchronisation.d.ts.map +0 -1
  140. package/lib/families/bitcoin/js-synchronisation.js +0 -411
  141. package/lib/families/bitcoin/js-synchronisation.js.map +0 -1
  142. package/lib/families/bitcoin/logic.d.ts +0 -34
  143. package/lib/families/bitcoin/logic.d.ts.map +0 -1
  144. package/lib/families/bitcoin/logic.js +0 -283
  145. package/lib/families/bitcoin/logic.js.map +0 -1
  146. package/lib/families/bitcoin/networks.d.ts +0 -3
  147. package/lib/families/bitcoin/networks.d.ts.map +0 -1
  148. package/lib/families/bitcoin/networks.js +0 -379
  149. package/lib/families/bitcoin/networks.js.map +0 -1
  150. package/lib/families/bitcoin/wallet.d.ts +0 -6
  151. package/lib/families/bitcoin/wallet.d.ts.map +0 -1
  152. package/lib/families/bitcoin/wallet.js +0 -66
  153. package/lib/families/bitcoin/wallet.js.map +0 -1
  154. package/src/families/bitcoin/bridge/js.ts +0 -76
  155. package/src/families/bitcoin/cache.ts +0 -76
  156. package/src/families/bitcoin/getAccountNetworkInfo.test.ts +0 -27
  157. package/src/families/bitcoin/getAccountNetworkInfo.ts +0 -61
  158. package/src/families/bitcoin/js-broadcast.ts +0 -30
  159. package/src/families/bitcoin/js-buildTransaction.ts +0 -57
  160. package/src/families/bitcoin/js-createTransaction.ts +0 -27
  161. package/src/families/bitcoin/js-estimateMaxSpendable.ts +0 -36
  162. package/src/families/bitcoin/js-getFeesForTransaction.ts +0 -59
  163. package/src/families/bitcoin/js-getTransactionStatus.ts +0 -118
  164. package/src/families/bitcoin/js-prepareTransaction.ts +0 -35
  165. package/src/families/bitcoin/js-signOperation.ts +0 -164
  166. package/src/families/bitcoin/js-synchronisation.ts +0 -362
  167. package/src/families/bitcoin/logic.ts +0 -243
  168. package/src/families/bitcoin/networks.ts +0 -360
  169. package/src/families/bitcoin/wallet.ts +0 -21
@@ -1,36 +0,0 @@
1
- import { BigNumber } from "bignumber.js";
2
- import type { AccountLike, Account } from "../../types";
3
- import type { Transaction } from "./types";
4
- import { getMainAccount } from "../../account";
5
- import wallet, { getWalletAccount } from "./wallet";
6
- import { getAccountNetworkInfo } from "./getAccountNetworkInfo";
7
-
8
- /**
9
- * Returns the maximum possible amount for transaction
10
- *
11
- * @param {Object} param - the account, parentAccount and transaction
12
- */
13
- const estimateMaxSpendable = async ({
14
- account,
15
- parentAccount,
16
- transaction,
17
- }: {
18
- account: AccountLike;
19
- parentAccount: Account | null | undefined;
20
- transaction: Transaction | null | undefined;
21
- }): Promise<BigNumber> => {
22
- const mainAccount = getMainAccount(account, parentAccount);
23
- const walletAccount = await getWalletAccount(mainAccount);
24
- let feePerByte = transaction?.feePerByte;
25
- if (!feePerByte) {
26
- const networkInfo = await getAccountNetworkInfo(mainAccount);
27
- feePerByte = networkInfo.feeItems.defaultFeePerByte;
28
- }
29
- const maxSpendable = await wallet.estimateAccountMaxSpendable(
30
- walletAccount,
31
- feePerByte.toNumber() //!\ wallet-btc handles fees as JS number
32
- );
33
- return maxSpendable.lt(0) ? new BigNumber(0) : maxSpendable;
34
- };
35
-
36
- export default estimateMaxSpendable;
@@ -1,59 +0,0 @@
1
- import { BigNumber } from "bignumber.js";
2
- import type { Account } from "./../../types";
3
- import type { Transaction } from "./types";
4
- import { buildTransaction } from "./js-buildTransaction";
5
- import { perCoinLogic } from "./logic";
6
-
7
- const getFeesForTransaction = async ({
8
- account,
9
- transaction,
10
- }: {
11
- account: Account;
12
- transaction: Transaction;
13
- }) => {
14
- const walletTx = await buildTransaction(account, transaction);
15
- const fees = new BigNumber(walletTx.fee).integerValue();
16
- let txInputs = walletTx.inputs.map((i) => {
17
- return {
18
- address: i.address,
19
- value: new BigNumber(i.value),
20
- previousTxHash: i.output_hash,
21
- previousOutputIndex: i.output_index,
22
- };
23
- });
24
- let txOutputs = walletTx.outputs.map((o) => {
25
- return {
26
- outputIndex: walletTx.outputs.indexOf(o),
27
- address: o.address,
28
- isChange: o.isChange,
29
- value: new BigNumber(o.value),
30
- hash: undefined,
31
- blockHeight: undefined,
32
- rbf: transaction.rbf,
33
- };
34
- });
35
- const perCoin = perCoinLogic[account.currency.id];
36
-
37
- if (perCoin) {
38
- const { syncReplaceAddress } = perCoin;
39
-
40
- if (syncReplaceAddress) {
41
- txInputs = txInputs.map((i) => ({
42
- ...i,
43
- address: i.address && syncReplaceAddress(i.address),
44
- }));
45
- txOutputs = txOutputs.map((o) => ({
46
- ...o,
47
- address: o.address && syncReplaceAddress(o.address),
48
- }));
49
- }
50
- }
51
-
52
- return {
53
- fees,
54
- txInputs,
55
- txOutputs,
56
- };
57
- };
58
-
59
- export default getFeesForTransaction;
@@ -1,118 +0,0 @@
1
- import { BigNumber } from "bignumber.js";
2
- import { log } from "@ledgerhq/logs";
3
- import {
4
- AmountRequired,
5
- NotEnoughBalance,
6
- FeeNotLoaded,
7
- FeeTooHigh,
8
- FeeRequired,
9
- } from "@ledgerhq/errors";
10
- import { LowerThanMinimumRelayFee } from "./../../errors";
11
- import type { Account, TransactionStatus } from "./../../types";
12
- import type { Transaction } from "./types";
13
- import { calculateFees, validateRecipient } from "./cache";
14
- import { getMinRelayFee } from "./logic";
15
-
16
- const getTransactionStatus = async (
17
- a: Account,
18
- t: Transaction
19
- ): Promise<TransactionStatus> => {
20
- const errors: any = {};
21
- const warnings: any = {};
22
- const useAllAmount = !!t.useAllAmount;
23
- const { recipientError, recipientWarning } = await validateRecipient(
24
- a.currency,
25
- t.recipient
26
- );
27
-
28
- if (recipientError) {
29
- errors.recipient = recipientError;
30
- }
31
-
32
- if (recipientWarning) {
33
- warnings.recipient = recipientWarning;
34
- }
35
-
36
- let txInputs;
37
- let txOutputs;
38
- let estimatedFees = new BigNumber(0);
39
-
40
- if (!t.feePerByte) {
41
- errors.feePerByte = new FeeNotLoaded();
42
- } else if (t.feePerByte.eq(0)) {
43
- errors.feePerByte = new FeeRequired();
44
- } else if (t.recipient && !errors.recipient) {
45
- await calculateFees({
46
- account: a,
47
- transaction: t,
48
- }).then(
49
- (res) => {
50
- txInputs = res.txInputs;
51
- txOutputs = res.txOutputs;
52
- estimatedFees = res.fees;
53
- },
54
- (error) => {
55
- if (error.name === "NotEnoughBalance") {
56
- errors.amount = error;
57
- } else {
58
- throw error;
59
- }
60
- }
61
- );
62
- }
63
-
64
- const sumOfInputs = (txInputs || []).reduce(
65
- (sum, input) => sum.plus(input.value),
66
- new BigNumber(0)
67
- );
68
- const sumOfChanges = (txOutputs || [])
69
- .filter((o) => o.isChange)
70
- .reduce((sum, output) => sum.plus(output.value), new BigNumber(0));
71
-
72
- if (txInputs) {
73
- log("bitcoin", `${txInputs.length} inputs, sum: ${sumOfInputs.toString()}`);
74
- }
75
-
76
- if (txOutputs) {
77
- log(
78
- "bitcoin",
79
- `${txOutputs.length} outputs, sum of changes: ${sumOfChanges.toString()}`
80
- );
81
- }
82
-
83
- const totalSpent = sumOfInputs.minus(sumOfChanges);
84
- const amount = useAllAmount ? totalSpent.minus(estimatedFees) : t.amount;
85
- log(
86
- "bitcoin",
87
- `totalSpent ${totalSpent.toString()} amount ${amount.toString()}`
88
- );
89
-
90
- if (!errors.amount && !amount.gt(0)) {
91
- errors.amount = useAllAmount
92
- ? new NotEnoughBalance()
93
- : new AmountRequired();
94
- }
95
-
96
- if (
97
- process.env.EXPERIMENTAL_MIN_RELAY_FEE &&
98
- estimatedFees &&
99
- estimatedFees.gt(0) &&
100
- estimatedFees.lt(getMinRelayFee(a.currency))
101
- ) {
102
- warnings.feePerByte = new LowerThanMinimumRelayFee();
103
- } else if (amount.gt(0) && estimatedFees.times(10).gt(amount)) {
104
- warnings.feeTooHigh = new FeeTooHigh();
105
- }
106
-
107
- return Promise.resolve({
108
- errors,
109
- warnings,
110
- estimatedFees,
111
- amount,
112
- totalSpent,
113
- txInputs,
114
- txOutputs,
115
- });
116
- };
117
-
118
- export default getTransactionStatus;
@@ -1,35 +0,0 @@
1
- import invariant from "invariant";
2
- import type { Account } from "../../types";
3
- import type { Transaction } from "./types";
4
- import { getAccountNetworkInfo } from "./getAccountNetworkInfo";
5
- import { inferFeePerByte } from "./logic";
6
-
7
- const prepareTransaction = async (
8
- a: Account,
9
- t: Transaction
10
- ): Promise<Transaction> => {
11
- let networkInfo = t.networkInfo;
12
-
13
- if (!networkInfo) {
14
- networkInfo = await getAccountNetworkInfo(a);
15
- invariant(networkInfo.family === "bitcoin", "bitcoin networkInfo expected");
16
- }
17
-
18
- const feePerByte = inferFeePerByte(t, networkInfo);
19
-
20
- if (
21
- t.networkInfo === networkInfo &&
22
- (feePerByte === t.feePerByte || feePerByte.eq(t.feePerByte || 0))
23
- ) {
24
- // nothing changed
25
- return t;
26
- }
27
-
28
- return {
29
- ...t,
30
- networkInfo,
31
- feePerByte,
32
- };
33
- };
34
-
35
- export default prepareTransaction;
@@ -1,164 +0,0 @@
1
- import { BigNumber } from "bignumber.js";
2
- import { Observable } from "rxjs";
3
- import Btc from "@ledgerhq/hw-app-btc";
4
- import { log } from "@ledgerhq/logs";
5
- import type { Account, Operation, SignOperationEvent } from "./../../types";
6
- import { isSegwitDerivationMode } from "./../../derivation";
7
- import { encodeOperationId } from "./../../operation";
8
- import { open, close } from "./../../hw";
9
- import type { Transaction } from "./types";
10
- import { getNetworkParameters } from "./networks";
11
- import { buildTransaction } from "./js-buildTransaction";
12
- import { calculateFees } from "./cache";
13
- import wallet, { getWalletAccount } from "./wallet";
14
- import { perCoinLogic } from "./logic";
15
-
16
- const signOperation = ({
17
- account,
18
- deviceId,
19
- transaction,
20
- }: {
21
- account: Account;
22
- deviceId: any;
23
- transaction: Transaction;
24
- }): Observable<SignOperationEvent> =>
25
- Observable.create((o) => {
26
- async function main() {
27
- const { currency } = account;
28
- const transport = await open(deviceId);
29
- const hwApp = new Btc(transport);
30
- const walletAccount = await getWalletAccount(account);
31
-
32
- try {
33
- log("hw", `signTransaction ${currency.id} for account ${account.id}`);
34
- const txInfo = await buildTransaction(account, transaction);
35
- let senders: string[] = [];
36
- let recipients: string[] = [];
37
- let fee = new BigNumber(0);
38
- // Maybe better not re-calculate these fields here, instead include them
39
- // in Transaction type and set them in prepareTransaction?
40
- await calculateFees({
41
- account,
42
- transaction,
43
- }).then((res) => {
44
- senders = res.txInputs
45
- .map((i) => i.address)
46
- .filter(Boolean) as string[];
47
- recipients = res.txOutputs
48
- .map((o) => o.address)
49
- .filter(Boolean) as string[];
50
- fee = res.fees;
51
- });
52
-
53
- // FIXME (legacy)
54
- // should be `transaction.getLockTime()` as soon as lock time is
55
- // handled by libcore (actually: it always returns a default value
56
- // and that caused issue with zcash (see #904))
57
- // cf. https://github.com/LedgerHQ/lib-ledger-core/blob/fc9d762b83fc2b269d072b662065747a64ab2816/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.cpp#L156-L159
58
- let lockTime;
59
-
60
- // (legacy) Set lockTime for Komodo to enable reward claiming on UTXOs created by
61
- // Ledger Live. We should only set this if the currency is Komodo and
62
- // lockTime isn't already defined.
63
- if (currency.id === "komodo" && lockTime === undefined) {
64
- const unixtime = Math.floor(Date.now() / 1000);
65
- lockTime = unixtime - 777;
66
- }
67
-
68
- const networkParams = getNetworkParameters(currency.id);
69
- const sigHashType = networkParams.sigHash;
70
- if (isNaN(sigHashType)) {
71
- throw new Error("sigHashType should not be NaN");
72
- }
73
-
74
- const segwit = isSegwitDerivationMode(account.derivationMode);
75
-
76
- // FIXME Call to explorer needed to set timestamp
77
- // cf. https://github.com/LedgerHQ/lib-ledger-core/blob/fc9d762b83fc2b269d072b662065747a64ab2816/core/src/wallet/bitcoin/transaction_builders/BitcoinLikeUtxoPicker.cpp#L150-L154
78
- /*
79
- const hasTimestamp = networkParams.usesTimestampedTransaction;
80
- const initialTimestamp = hasTimestamp
81
- ? transaction.timestamp
82
- : undefined;
83
- */
84
-
85
- const perCoin = perCoinLogic[currency.id];
86
- let additionals = [currency.id];
87
-
88
- if (account.derivationMode === "native_segwit") {
89
- additionals.push("bech32");
90
- }
91
-
92
- if (perCoin?.getAdditionals) {
93
- additionals = additionals.concat(
94
- perCoin.getAdditionals({
95
- transaction,
96
- })
97
- );
98
- }
99
-
100
- const expiryHeight = perCoin?.hasExpiryHeight
101
- ? Buffer.from([0x00, 0x00, 0x00, 0x00])
102
- : undefined;
103
-
104
- const signature = await wallet.signAccountTx({
105
- btc: hwApp,
106
- fromAccount: walletAccount,
107
- txInfo,
108
- lockTime,
109
- sigHashType,
110
- segwit,
111
- //initialTimestamp,
112
- additionals,
113
- expiryHeight,
114
- onDeviceSignatureGranted: () =>
115
- o.next({
116
- type: "device-signature-granted",
117
- }),
118
- onDeviceSignatureRequested: () =>
119
- o.next({
120
- type: "device-signature-requested",
121
- }),
122
- onDeviceStreaming: ({ progress, index, total }) =>
123
- o.next({
124
- type: "device-streaming",
125
- progress,
126
- index,
127
- total,
128
- }),
129
- });
130
- // Build the optimistic operation
131
- const operation: Operation = {
132
- id: encodeOperationId(account.id, "", "OUT"),
133
- hash: "", // Will be resolved in broadcast()
134
- type: "OUT",
135
- value: new BigNumber(transaction.amount).plus(fee),
136
- fee,
137
- blockHash: null,
138
- blockHeight: null,
139
- senders,
140
- recipients,
141
- accountId: account.id,
142
- date: new Date(),
143
- extra: {},
144
- };
145
- o.next({
146
- type: "signed",
147
- signedOperation: {
148
- operation,
149
- signature,
150
- expirationDate: null,
151
- },
152
- });
153
- } finally {
154
- close(transport, deviceId);
155
- }
156
- }
157
-
158
- main().then(
159
- () => o.complete(),
160
- (e) => o.error(e)
161
- );
162
- });
163
-
164
- export default signOperation;
@@ -1,362 +0,0 @@
1
- import { $Shape } from "utility-types";
2
- import type {
3
- TX,
4
- Currency,
5
- Input as WalletInput,
6
- Output as WalletOutput,
7
- } from "@ledgerhq/wallet-btc";
8
- import { DerivationModes as WalletDerivationModes } from "@ledgerhq/wallet-btc";
9
- import { BigNumber } from "bignumber.js";
10
- import Btc from "@ledgerhq/hw-app-btc";
11
- import { log } from "@ledgerhq/logs";
12
- import type {
13
- Account,
14
- Operation,
15
- OperationType,
16
- DerivationMode,
17
- } from "../../types";
18
- import type { GetAccountShape } from "../../bridge/jsHelpers";
19
- import { makeSync, makeScanAccounts, mergeOps } from "../../bridge/jsHelpers";
20
- import { findCurrencyExplorer } from "../../api/Ledger";
21
- import { encodeOperationId } from "../../operation";
22
- import { BitcoinOutput } from "./types";
23
- import { perCoinLogic } from "./logic";
24
- import wallet from "./wallet";
25
-
26
- // Map LL's DerivationMode to wallet-btc's
27
- const toWalletDerivationMode = (
28
- mode: DerivationMode
29
- ): WalletDerivationModes => {
30
- switch (mode) {
31
- case "segwit":
32
- case "segwit_on_legacy":
33
- case "segwit_unsplit":
34
- case "bch_on_bitcoin_segwit":
35
- case "vertcoin_128_segwit":
36
- return WalletDerivationModes.SEGWIT;
37
-
38
- case "native_segwit":
39
- return WalletDerivationModes.NATIVE_SEGWIT;
40
-
41
- default:
42
- return WalletDerivationModes.LEGACY;
43
- }
44
- };
45
-
46
- // Map LL's currency ID to wallet-btc's Account.params.network
47
- const toWalletNetwork = (currencyId: string): "testnet" | "mainnet" => {
48
- return ["bitcoin_testnet"].includes(currencyId) ? "testnet" : "mainnet";
49
- };
50
-
51
- // Map wallet-btc's Output to LL's BitcoinOutput
52
- const fromWalletUtxo = (utxo: WalletOutput): BitcoinOutput => {
53
- return {
54
- hash: utxo.output_hash,
55
- outputIndex: utxo.output_index,
56
- blockHeight: utxo.block_height,
57
- address: utxo.address,
58
- value: new BigNumber(utxo.value),
59
- rbf: utxo.rbf,
60
- isChange: false, // wallet-btc limitation: doesn't provide it
61
- path: "",
62
- };
63
- };
64
-
65
- // wallet-btc limitation: returns all transactions twice (for each side of the tx)
66
- // so we need to deduplicate them...
67
- const deduplicateOperations = (
68
- operations: (Operation | undefined)[]
69
- ): Operation[] => {
70
- const seen = {};
71
- const out: Operation[] = [];
72
- let j = 0;
73
-
74
- for (const operation of operations) {
75
- if (operation) {
76
- if (seen[operation.id] !== 1) {
77
- seen[operation.id] = 1;
78
- out[j++] = operation;
79
- }
80
- }
81
- }
82
-
83
- return out;
84
- };
85
-
86
- const mapTxToOperations = (
87
- tx: TX,
88
- currencyId: string,
89
- accountId: string,
90
- accountAddresses: string[],
91
- changeAddresses: string[]
92
- ): $Shape<Operation[]> => {
93
- const operations: Operation[] = [];
94
- const hash = tx.hash;
95
- const fee = new BigNumber(tx.fees);
96
- const blockHeight = tx.block?.height;
97
- const blockHash = tx.block?.hash;
98
- const date = new Date(tx.block?.time || tx.received_at);
99
- const senders: string[] = [];
100
- const recipients: string[] = [];
101
- let type: OperationType = "OUT";
102
- let value = new BigNumber(0);
103
- const hasFailed = false;
104
- const accountInputs: WalletInput[] = [];
105
- const accountOutputs: WalletOutput[] = [];
106
- const syncReplaceAddress = perCoinLogic[currencyId]?.syncReplaceAddress;
107
-
108
- for (const input of tx.inputs) {
109
- if (input.address) {
110
- senders.push(
111
- syncReplaceAddress ? syncReplaceAddress(input.address) : input.address
112
- );
113
-
114
- if (input.value) {
115
- if (accountAddresses.includes(input.address)) {
116
- // This address is part of the account
117
- value = value.plus(input.value);
118
- accountInputs.push(input);
119
- }
120
- }
121
- }
122
- }
123
-
124
- // All inputs of a same transaction have the same sequence
125
- const transactionSequenceNumber =
126
- (accountInputs.length > 0 && accountInputs[0].sequence) || undefined;
127
- const hasSpentNothing = value.eq(0);
128
-
129
- for (const output of tx.outputs) {
130
- if (output.address) {
131
- if (accountAddresses.includes(output.address)) {
132
- accountOutputs.push(output);
133
-
134
- if (changeAddresses.includes(output.address)) {
135
- if (
136
- (recipients.length === 0 &&
137
- output.output_hash ===
138
- tx.outputs[tx.outputs.length - 1].output_hash) || // Is that condition safe?
139
- hasSpentNothing
140
- ) {
141
- recipients.push(
142
- syncReplaceAddress
143
- ? syncReplaceAddress(output.address)
144
- : output.address
145
- );
146
- }
147
- } else {
148
- recipients.push(
149
- syncReplaceAddress
150
- ? syncReplaceAddress(output.address)
151
- : output.address
152
- );
153
- }
154
- } else {
155
- recipients.push(
156
- syncReplaceAddress
157
- ? syncReplaceAddress(output.address)
158
- : output.address
159
- );
160
- }
161
- }
162
- }
163
-
164
- if (accountInputs.length > 0) {
165
- // It's a SEND operation
166
- for (const output of accountOutputs) {
167
- if (changeAddresses.includes(output.address)) {
168
- value = value.minus(output.value);
169
- }
170
- }
171
-
172
- type = "OUT";
173
- operations.push({
174
- id: encodeOperationId(accountId, hash, type),
175
- hash,
176
- type,
177
- value,
178
- fee,
179
- senders,
180
- recipients,
181
- blockHeight,
182
- blockHash,
183
- transactionSequenceNumber,
184
- accountId,
185
- date,
186
- hasFailed,
187
- extra: {},
188
- });
189
- }
190
-
191
- if (accountOutputs.length > 0) {
192
- // It's a RECEIVE operation
193
- const filterChangeAddresses = !!accountInputs.length;
194
- let accountOutputCount = 0;
195
- let finalAmount = new BigNumber(0);
196
-
197
- for (const output of accountOutputs) {
198
- if (!filterChangeAddresses || !changeAddresses.includes(output.address)) {
199
- finalAmount = finalAmount.plus(output.value);
200
- accountOutputCount += 1;
201
- }
202
- }
203
-
204
- if (accountOutputCount > 0) {
205
- value = finalAmount;
206
- type = "IN";
207
- operations.push({
208
- id: encodeOperationId(accountId, hash, type),
209
- hash,
210
- type,
211
- value,
212
- fee,
213
- senders,
214
- recipients,
215
- blockHeight,
216
- blockHash,
217
- transactionSequenceNumber,
218
- accountId,
219
- date,
220
- hasFailed,
221
- extra: {},
222
- });
223
- }
224
- }
225
-
226
- return operations;
227
- };
228
-
229
- const getAccountShape: GetAccountShape = async (info) => {
230
- const {
231
- transport,
232
- currency,
233
- id: accountId,
234
- index,
235
- derivationPath,
236
- derivationMode,
237
- initialAccount,
238
- } = info;
239
- const paramXpub = initialAccount?.xpub;
240
-
241
- // In case we get a full derivation path, extract the seed identification part
242
- // 44'/0'/0'/0/0 --> 44'/0'
243
- // FIXME Only the CLI provides a full derivationPath: why?
244
- const rootPath = derivationPath.split("/", 2).join("/");
245
-
246
- const walletNetwork = toWalletNetwork(currency.id);
247
- const walletDerivationMode = toWalletDerivationMode(derivationMode);
248
- const explorer = findCurrencyExplorer(currency);
249
- if (!explorer) {
250
- throw new Error(`No explorer found for currency ${currency.name}`);
251
- }
252
- if (explorer.version !== "v2" && explorer.version !== "v3") {
253
- throw new Error(`Unsupported explorer version ${explorer.version}`);
254
- }
255
-
256
- const walletAccount = initialAccount?.bitcoinResources?.serializedData
257
- ? await wallet.importFromSerializedAccount(
258
- initialAccount.bitcoinResources.serializedData
259
- )
260
- : await wallet.generateAccount({
261
- btc: (!paramXpub && transport && new Btc(transport)) || undefined,
262
- xpub: paramXpub,
263
- path: rootPath,
264
- index,
265
- currency: <Currency>currency.id,
266
- network: walletNetwork,
267
- derivationMode: walletDerivationMode,
268
- explorer: explorer && `ledger${explorer.version}`,
269
- explorerURI: `${explorer.endpoint}/blockchain/${explorer.version}/${explorer.id}`,
270
- storage: "mock",
271
- storageParams: [],
272
- });
273
- const xpub = paramXpub || walletAccount.xpub.xpub;
274
- const oldOperations = initialAccount?.operations || [];
275
- await wallet.syncAccount(walletAccount);
276
- const balance = await wallet.getAccountBalance(walletAccount);
277
- const currentBlock = await walletAccount.xpub.explorer.getCurrentBlock();
278
- const blockHeight = currentBlock?.height;
279
-
280
- // @ts-expect-error return from wallet-btc should be typed
281
- const { txs: transactions } = await wallet.getAccountTransactions(
282
- walletAccount
283
- );
284
- const accountAddressesWithInfo = await walletAccount.xpub.getXpubAddresses();
285
- const accountAddresses = accountAddressesWithInfo
286
- ? accountAddressesWithInfo.map((a) => a.address)
287
- : [];
288
- const changeAddressesWithInfo =
289
- await walletAccount.xpub.storage.getUniquesAddresses({
290
- account: 1,
291
- });
292
- const changeAddresses = changeAddressesWithInfo
293
- ? changeAddressesWithInfo.map((a) => a.address)
294
- : [];
295
- const newOperations = transactions
296
- ?.map((tx) =>
297
- mapTxToOperations(
298
- tx,
299
- currency.id,
300
- accountId,
301
- accountAddresses,
302
- changeAddresses
303
- )
304
- )
305
- .flat();
306
- const newUniqueOperations = deduplicateOperations(newOperations);
307
- const operations = mergeOps(oldOperations, newUniqueOperations);
308
- const rawUtxos = await wallet.getAccountUnspentUtxos(walletAccount);
309
- const utxos = rawUtxos.map(fromWalletUtxo);
310
- const serializedData = await wallet.exportToSerializedAccount(walletAccount);
311
- return {
312
- id: accountId,
313
- xpub,
314
- balance,
315
- spendableBalance: balance,
316
- operations,
317
- operationsCount: operations.length,
318
- blockHeight,
319
- bitcoinResources: {
320
- utxos,
321
- serializedData,
322
- },
323
- };
324
- };
325
-
326
- const postSync = (initial: Account, synced: Account) => {
327
- log("bitcoin/postSync", "bitcoinResources");
328
- const perCoin = perCoinLogic[synced.currency.id];
329
-
330
- if (perCoin) {
331
- const { postBuildBitcoinResources, syncReplaceAddress } = perCoin;
332
-
333
- if (postBuildBitcoinResources) {
334
- synced.bitcoinResources = postBuildBitcoinResources(
335
- synced,
336
- synced.bitcoinResources
337
- );
338
- }
339
-
340
- if (syncReplaceAddress) {
341
- synced.freshAddress = syncReplaceAddress(synced.freshAddress);
342
- synced.freshAddresses = synced.freshAddresses.map((a) => ({
343
- ...a,
344
- address: syncReplaceAddress(a.address),
345
- }));
346
- if (synced.bitcoinResources) {
347
- synced.bitcoinResources.utxos = synced.bitcoinResources?.utxos.map(
348
- (u) => ({
349
- ...u,
350
- address: u.address && syncReplaceAddress(u.address),
351
- })
352
- );
353
- }
354
- }
355
- }
356
-
357
- log("bitcoin/postSync", "bitcoinResources DONE");
358
- return synced;
359
- };
360
-
361
- export const scanAccounts = makeScanAccounts(getAccountShape);
362
- export const sync = makeSync(getAccountShape, postSync);