@ledgerhq/live-common 21.22.0 → 21.24.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 (262) hide show
  1. package/lib/account/formatters.d.ts.map +1 -1
  2. package/lib/account/formatters.js +1 -0
  3. package/lib/account/formatters.js.map +1 -1
  4. package/lib/account/support.d.ts.map +1 -1
  5. package/lib/account/support.js +1 -0
  6. package/lib/account/support.js.map +1 -1
  7. package/lib/data/icons/react/index.d.ts +1 -0
  8. package/lib/data/icons/react/index.d.ts.map +1 -1
  9. package/lib/data/icons/react/index.js +4 -2
  10. package/lib/data/icons/react/index.js.map +1 -1
  11. package/lib/data/icons/react/sol.js +4 -2
  12. package/lib/data/icons/react/sol.js.map +1 -1
  13. package/lib/data/icons/react/ssv.d.ts +8 -0
  14. package/lib/data/icons/react/ssv.d.ts.map +1 -0
  15. package/lib/data/icons/react/ssv.js +31 -0
  16. package/lib/data/icons/react/ssv.js.map +1 -0
  17. package/lib/data/icons/reactNative/index.d.ts +1 -0
  18. package/lib/data/icons/reactNative/index.d.ts.map +1 -1
  19. package/lib/data/icons/reactNative/index.js +4 -2
  20. package/lib/data/icons/reactNative/index.js.map +1 -1
  21. package/lib/data/icons/reactNative/sol.js +4 -2
  22. package/lib/data/icons/reactNative/sol.js.map +1 -1
  23. package/lib/data/icons/reactNative/ssv.d.ts +8 -0
  24. package/lib/data/icons/reactNative/ssv.d.ts.map +1 -0
  25. package/lib/data/icons/reactNative/ssv.js +32 -0
  26. package/lib/data/icons/reactNative/ssv.js.map +1 -0
  27. package/lib/derivation.d.ts.map +1 -1
  28. package/lib/derivation.js +0 -3
  29. package/lib/derivation.js.map +1 -1
  30. package/lib/env.d.ts +10 -10
  31. package/lib/env.d.ts.map +1 -1
  32. package/lib/env.js +5 -5
  33. package/lib/env.js.map +1 -1
  34. package/lib/env.react.d.ts +1 -1
  35. package/lib/env.react.d.ts.map +1 -1
  36. package/lib/families/algorand/account.d.ts.map +1 -1
  37. package/lib/families/algorand/account.js +0 -4
  38. package/lib/families/algorand/account.js.map +1 -1
  39. package/lib/families/algorand/api/algodv2.d.ts +5 -0
  40. package/lib/families/algorand/api/algodv2.d.ts.map +1 -0
  41. package/lib/families/algorand/api/algodv2.js +118 -0
  42. package/lib/families/algorand/api/algodv2.js.map +1 -0
  43. package/lib/families/algorand/api/algodv2.types.d.ts +24 -0
  44. package/lib/families/algorand/api/algodv2.types.d.ts.map +1 -0
  45. package/lib/families/algorand/api/algodv2.types.js +3 -0
  46. package/lib/families/algorand/api/algodv2.types.js.map +1 -0
  47. package/lib/families/algorand/api/index.d.ts +5 -0
  48. package/lib/families/algorand/api/index.d.ts.map +1 -0
  49. package/lib/families/algorand/api/index.js +17 -0
  50. package/lib/families/algorand/api/index.js.map +1 -0
  51. package/lib/families/algorand/api/indexer.d.ts +3 -0
  52. package/lib/families/algorand/api/indexer.d.ts.map +1 -0
  53. package/lib/families/algorand/api/indexer.js +134 -0
  54. package/lib/families/algorand/api/indexer.js.map +1 -0
  55. package/lib/families/algorand/api/indexer.types.d.ts +35 -0
  56. package/lib/families/algorand/api/indexer.types.d.ts.map +1 -0
  57. package/lib/families/algorand/api/indexer.types.js +10 -0
  58. package/lib/families/algorand/api/indexer.types.js.map +1 -0
  59. package/lib/families/algorand/bridge/js.d.ts +8 -0
  60. package/lib/families/algorand/bridge/js.d.ts.map +1 -0
  61. package/lib/families/algorand/bridge/js.js +85 -0
  62. package/lib/families/algorand/bridge/js.js.map +1 -0
  63. package/lib/families/algorand/bridge/libcore.d.ts +3 -3
  64. package/lib/families/algorand/bridge/libcore.d.ts.map +1 -1
  65. package/lib/families/algorand/bridge/libcore.js.map +1 -1
  66. package/lib/families/algorand/bridge/mock.d.ts +2 -2
  67. package/lib/families/algorand/bridge/mock.d.ts.map +1 -1
  68. package/lib/families/algorand/bridge/mock.js.map +1 -1
  69. package/lib/families/algorand/buildTransaction.d.ts +8 -0
  70. package/lib/families/algorand/buildTransaction.d.ts.map +1 -0
  71. package/lib/families/algorand/buildTransaction.js +101 -0
  72. package/lib/families/algorand/buildTransaction.js.map +1 -0
  73. package/lib/families/algorand/cli-transaction.js +1 -1
  74. package/lib/families/algorand/cli-transaction.js.map +1 -1
  75. package/lib/families/algorand/deviceTransactionConfig.d.ts +2 -2
  76. package/lib/families/algorand/deviceTransactionConfig.d.ts.map +1 -1
  77. package/lib/families/algorand/deviceTransactionConfig.js +0 -13
  78. package/lib/families/algorand/deviceTransactionConfig.js.map +1 -1
  79. package/lib/families/algorand/hw-getAddress.d.ts.map +1 -1
  80. package/lib/families/algorand/hw-getAddress.js +2 -24
  81. package/lib/families/algorand/hw-getAddress.js.map +1 -1
  82. package/lib/families/algorand/js-broadcast.d.ts +9 -0
  83. package/lib/families/algorand/js-broadcast.d.ts.map +1 -0
  84. package/lib/families/algorand/js-broadcast.js +63 -0
  85. package/lib/families/algorand/js-broadcast.js.map +1 -0
  86. package/lib/families/algorand/js-estimateMaxSpendable.d.ts +9 -0
  87. package/lib/families/algorand/js-estimateMaxSpendable.d.ts.map +1 -0
  88. package/lib/families/algorand/js-estimateMaxSpendable.js +89 -0
  89. package/lib/families/algorand/js-estimateMaxSpendable.js.map +1 -0
  90. package/lib/families/algorand/js-getFeesForTransaction.d.ts +5 -0
  91. package/lib/families/algorand/js-getFeesForTransaction.d.ts.map +1 -0
  92. package/lib/families/algorand/js-getFeesForTransaction.js +69 -0
  93. package/lib/families/algorand/js-getFeesForTransaction.js.map +1 -0
  94. package/lib/families/algorand/js-getTransactionStatus.d.ts +11 -0
  95. package/lib/families/algorand/js-getTransactionStatus.d.ts.map +1 -0
  96. package/lib/families/algorand/js-getTransactionStatus.js +201 -0
  97. package/lib/families/algorand/js-getTransactionStatus.js.map +1 -0
  98. package/lib/families/algorand/js-prepareTransaction.d.ts +5 -0
  99. package/lib/families/algorand/js-prepareTransaction.d.ts.map +1 -0
  100. package/lib/families/algorand/js-prepareTransaction.js +101 -0
  101. package/lib/families/algorand/js-prepareTransaction.js.map +1 -0
  102. package/lib/families/algorand/js-signOperation.d.ts +10 -0
  103. package/lib/families/algorand/js-signOperation.d.ts.map +1 -0
  104. package/lib/families/algorand/js-signOperation.js +164 -0
  105. package/lib/families/algorand/js-signOperation.js.map +1 -0
  106. package/lib/families/algorand/js-synchronization.d.ts +10 -0
  107. package/lib/families/algorand/js-synchronization.d.ts.map +1 -0
  108. package/lib/families/algorand/js-synchronization.js +411 -0
  109. package/lib/families/algorand/js-synchronization.js.map +1 -0
  110. package/lib/families/algorand/libcore-buildTransaction.d.ts +2 -2
  111. package/lib/families/algorand/libcore-buildTransaction.d.ts.map +1 -1
  112. package/lib/families/algorand/libcore-getFeesForTransaction.d.ts +4 -4
  113. package/lib/families/algorand/libcore-getFeesForTransaction.d.ts.map +1 -1
  114. package/lib/families/algorand/libcore-getFeesForTransaction.js +2 -2
  115. package/lib/families/algorand/libcore-getFeesForTransaction.js.map +1 -1
  116. package/lib/families/algorand/libcore-postBuildAccount.d.ts.map +1 -1
  117. package/lib/families/algorand/libcore-postBuildAccount.js +5 -11
  118. package/lib/families/algorand/libcore-postBuildAccount.js.map +1 -1
  119. package/lib/families/algorand/libcore-signOperation.d.ts +2 -2
  120. package/lib/families/algorand/libcore-signOperation.d.ts.map +1 -1
  121. package/lib/families/algorand/libcore-signOperation.js.map +1 -1
  122. package/lib/families/algorand/logic.d.ts +10 -0
  123. package/lib/families/algorand/logic.d.ts.map +1 -1
  124. package/lib/families/algorand/logic.js +79 -1
  125. package/lib/families/algorand/logic.js.map +1 -1
  126. package/lib/families/algorand/mock.d.ts.map +1 -1
  127. package/lib/families/algorand/mock.js +4 -11
  128. package/lib/families/algorand/mock.js.map +1 -1
  129. package/lib/families/algorand/serialization.js +4 -4
  130. package/lib/families/algorand/serialization.js.map +1 -1
  131. package/lib/families/algorand/specs.d.ts +2 -2
  132. package/lib/families/algorand/specs.d.ts.map +1 -1
  133. package/lib/families/algorand/specs.js +8 -16
  134. package/lib/families/algorand/specs.js.map +1 -1
  135. package/lib/families/algorand/speculos-deviceActions.d.ts +2 -2
  136. package/lib/families/algorand/speculos-deviceActions.d.ts.map +1 -1
  137. package/lib/families/algorand/speculos-deviceActions.js +4 -0
  138. package/lib/families/algorand/speculos-deviceActions.js.map +1 -1
  139. package/lib/families/algorand/test-dataset.d.ts +2 -2
  140. package/lib/families/algorand/test-dataset.d.ts.map +1 -1
  141. package/lib/families/algorand/test-dataset.js +1 -2
  142. package/lib/families/algorand/test-dataset.js.map +1 -1
  143. package/lib/families/algorand/tokens.d.ts.map +1 -1
  144. package/lib/families/algorand/tokens.js.map +1 -1
  145. package/lib/families/algorand/transaction.d.ts +5 -5
  146. package/lib/families/algorand/transaction.d.ts.map +1 -1
  147. package/lib/families/algorand/transaction.js.map +1 -1
  148. package/lib/families/algorand/types.d.ts +7 -5
  149. package/lib/families/algorand/types.d.ts.map +1 -1
  150. package/lib/families/algorand/types.js.map +1 -1
  151. package/lib/families/bitcoin/js-prepareTransaction.d.ts.map +1 -1
  152. package/lib/families/bitcoin/js-prepareTransaction.js +3 -2
  153. package/lib/families/bitcoin/js-prepareTransaction.js.map +1 -1
  154. package/lib/families/bitcoin/js-synchronisation.d.ts.map +1 -1
  155. package/lib/families/bitcoin/js-synchronisation.js +13 -14
  156. package/lib/families/bitcoin/js-synchronisation.js.map +1 -1
  157. package/lib/families/bitcoin/wallet-btc/crypto/base.d.ts.map +1 -1
  158. package/lib/families/bitcoin/wallet-btc/crypto/base.js +30 -22
  159. package/lib/families/bitcoin/wallet-btc/crypto/base.js.map +1 -1
  160. package/lib/families/bitcoin/wallet-btc/crypto/bip32.d.ts +11 -0
  161. package/lib/families/bitcoin/wallet-btc/crypto/bip32.d.ts.map +1 -0
  162. package/lib/families/bitcoin/wallet-btc/crypto/bip32.js +32 -0
  163. package/lib/families/bitcoin/wallet-btc/crypto/bip32.js.map +1 -0
  164. package/lib/families/bitcoin/wallet-btc/crypto/decred.d.ts.map +1 -1
  165. package/lib/families/bitcoin/wallet-btc/crypto/decred.js +3 -115
  166. package/lib/families/bitcoin/wallet-btc/crypto/decred.js.map +1 -1
  167. package/lib/families/bitcoin/wallet-btc/storage/index.d.ts +24 -8
  168. package/lib/families/bitcoin/wallet-btc/storage/index.d.ts.map +1 -1
  169. package/lib/families/bitcoin/wallet-btc/storage/index.js +114 -128
  170. package/lib/families/bitcoin/wallet-btc/storage/index.js.map +1 -1
  171. package/lib/families/bitcoin/wallet-btc/storage/types.d.ts +8 -7
  172. package/lib/families/bitcoin/wallet-btc/storage/types.d.ts.map +1 -1
  173. package/lib/families/bitcoin/wallet-btc/xpub.d.ts.map +1 -1
  174. package/lib/families/bitcoin/wallet-btc/xpub.js +42 -63
  175. package/lib/families/bitcoin/wallet-btc/xpub.js.map +1 -1
  176. package/lib/families/tezos/bridge/js.d.ts.map +1 -1
  177. package/lib/families/tezos/bridge/js.js +38 -17
  178. package/lib/families/tezos/bridge/js.js.map +1 -1
  179. package/lib/families/tezos/signOperation.d.ts.map +1 -1
  180. package/lib/families/tezos/signOperation.js +9 -0
  181. package/lib/families/tezos/signOperation.js.map +1 -1
  182. package/lib/families/tezos/synchronisation.js +1 -1
  183. package/lib/families/tezos/synchronisation.js.map +1 -1
  184. package/lib/generated/bridge/js.d.ts +4 -0
  185. package/lib/generated/bridge/js.d.ts.map +1 -1
  186. package/lib/generated/bridge/js.js +26 -24
  187. package/lib/generated/bridge/js.js.map +1 -1
  188. package/lib/generated/bridge/libcore.d.ts +1 -1
  189. package/lib/generated/bridge/mock.d.ts +1 -1
  190. package/lib/generated/specs.d.ts +1 -1
  191. package/lib/generated/speculos-deviceActions.d.ts +1 -1
  192. package/lib/generated/test-dataset.d.ts +1 -1
  193. package/lib/generated/transaction.d.ts +3 -3
  194. package/lib/libcore/buildAccount/index.d.ts.map +1 -1
  195. package/lib/libcore/buildAccount/index.js +0 -1
  196. package/lib/libcore/buildAccount/index.js.map +1 -1
  197. package/lib/mock/account.js +21 -21
  198. package/lib/mock/account.js.map +1 -1
  199. package/lib/types/operation.d.ts +1 -1
  200. package/lib/types/operation.d.ts.map +1 -1
  201. package/package.json +4 -3
  202. package/src/__tests__/__snapshots__/all.libcore.ts.snap +7 -114
  203. package/src/account/formatters.ts +1 -0
  204. package/src/account/support.ts +1 -0
  205. package/src/data/icons/react/index.tsx +1 -0
  206. package/src/data/icons/react/sol.tsx +1 -1
  207. package/src/data/icons/react/ssv.tsx +12 -0
  208. package/src/data/icons/reactNative/index.tsx +1 -0
  209. package/src/data/icons/reactNative/sol.tsx +1 -1
  210. package/src/data/icons/reactNative/ssv.tsx +13 -0
  211. package/src/data/icons/svg/SOL.svg +1 -3
  212. package/src/data/icons/svg/SSV.svg +4 -0
  213. package/src/derivation.ts +0 -2
  214. package/src/env.ts +5 -5
  215. package/src/families/algorand/account.ts +0 -9
  216. package/src/families/algorand/api/algodv2.ts +68 -0
  217. package/src/families/algorand/api/algodv2.types.ts +27 -0
  218. package/src/families/algorand/api/index.ts +4 -0
  219. package/src/families/algorand/api/indexer.ts +99 -0
  220. package/src/families/algorand/api/indexer.types.ts +41 -0
  221. package/src/families/algorand/bridge/js.ts +46 -0
  222. package/src/families/algorand/bridge/libcore.ts +4 -4
  223. package/src/families/algorand/bridge/mock.ts +3 -3
  224. package/src/families/algorand/buildTransaction.ts +100 -0
  225. package/src/families/algorand/cli-transaction.ts +1 -1
  226. package/src/families/algorand/deviceTransactionConfig.ts +2 -16
  227. package/src/families/algorand/hw-getAddress.ts +1 -10
  228. package/src/families/algorand/js-broadcast.ts +17 -0
  229. package/src/families/algorand/js-estimateMaxSpendable.ts +51 -0
  230. package/src/families/algorand/js-getFeesForTransaction.ts +25 -0
  231. package/src/families/algorand/js-getTransactionStatus.ts +178 -0
  232. package/src/families/algorand/js-prepareTransaction.ts +42 -0
  233. package/src/families/algorand/js-signOperation.ts +145 -0
  234. package/src/families/algorand/js-synchronization.ts +433 -0
  235. package/src/families/algorand/libcore-buildTransaction.ts +2 -2
  236. package/src/families/algorand/libcore-getFeesForTransaction.ts +4 -4
  237. package/src/families/algorand/libcore-postBuildAccount.ts +2 -7
  238. package/src/families/algorand/libcore-signOperation.ts +2 -2
  239. package/src/families/algorand/logic.ts +47 -0
  240. package/src/families/algorand/mock.ts +2 -12
  241. package/src/families/algorand/serialization.ts +4 -4
  242. package/src/families/algorand/specs.ts +16 -22
  243. package/src/families/algorand/speculos-deviceActions.ts +87 -82
  244. package/src/families/algorand/test-dataset.ts +5 -6
  245. package/src/families/algorand/tokens.ts +1 -0
  246. package/src/families/algorand/transaction.ts +13 -4
  247. package/src/families/algorand/types.ts +10 -5
  248. package/src/families/bitcoin/js-prepareTransaction.ts +3 -2
  249. package/src/families/bitcoin/js-synchronisation.ts +17 -15
  250. package/src/families/bitcoin/wallet-btc/crypto/base.ts +33 -21
  251. package/src/families/bitcoin/wallet-btc/crypto/bip32.ts +36 -0
  252. package/src/families/bitcoin/wallet-btc/crypto/decred.ts +3 -155
  253. package/src/families/bitcoin/wallet-btc/storage/index.ts +23 -11
  254. package/src/families/bitcoin/wallet-btc/storage/types.ts +8 -10
  255. package/src/families/bitcoin/wallet-btc/xpub.ts +14 -10
  256. package/src/families/tezos/bridge/js.ts +43 -18
  257. package/src/families/tezos/signOperation.ts +12 -0
  258. package/src/families/tezos/synchronisation.ts +1 -1
  259. package/src/generated/bridge/js.ts +3 -0
  260. package/src/libcore/buildAccount/index.ts +1 -2
  261. package/src/mock/account.ts +27 -27
  262. package/src/types/operation.ts +9 -4
@@ -1,13 +1,15 @@
1
1
  // from https://github.com/LedgerHQ/xpub-scan/blob/master/src/actions/deriveAddresses.ts
2
2
 
3
3
  import * as bjs from "bitcoinjs-lib";
4
- import * as bip32 from "bip32";
5
4
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6
5
  // @ts-ignore
7
6
  import { toOutputScript } from "bitcoinjs-lib/src/address";
8
7
  import bs58check from "bs58check";
9
8
  import { DerivationModes } from "../types";
10
9
  import { ICrypto } from "./types";
10
+ import bs58 from "bs58";
11
+ import bech32 from "bech32";
12
+ import BIP32 from "./bip32";
11
13
 
12
14
  export function fallbackValidateAddress(address: string): boolean {
13
15
  try {
@@ -41,7 +43,18 @@ class Base implements ICrypto {
41
43
 
42
44
  protected getPubkeyAt(xpub: string, account: number, index: number): Buffer {
43
45
  if (!Base.bech32Cache[xpub]) {
44
- Base.bech32Cache[xpub] = bip32.fromBase58(xpub, this.network);
46
+ const buffer: Buffer = bs58.decode(xpub);
47
+ const depth: number = buffer[4];
48
+ const i: number = buffer.readUInt32BE(9);
49
+ const chainCode: Buffer = buffer.slice(13, 45);
50
+ const publicKey: Buffer = buffer.slice(45, 78);
51
+ Base.bech32Cache[xpub] = new BIP32(
52
+ publicKey,
53
+ chainCode,
54
+ this.network,
55
+ depth,
56
+ i
57
+ );
45
58
  }
46
59
  if (Base.publickeyCache[`${xpub}-${account}-${index}`]) {
47
60
  return Base.publickeyCache[`${xpub}-${account}-${index}`];
@@ -62,33 +75,32 @@ class Base implements ICrypto {
62
75
 
63
76
  // derive legacy address at account and index positions
64
77
  getLegacyAddress(xpub: string, account: number, index: number): string {
65
- const { address } = bjs.payments.p2pkh({
66
- pubkey: this.getPubkeyAt(xpub, account, index),
67
- network: this.network,
68
- });
69
-
70
- return String(address);
78
+ const publicKeyBuffer: Buffer = this.getPubkeyAt(xpub, account, index);
79
+ const publicKeyHash160: Buffer = bjs.crypto.hash160(publicKeyBuffer);
80
+ return bjs.address.toBase58Check(publicKeyHash160, this.network.pubKeyHash);
71
81
  }
72
82
 
73
83
  // derive native SegWit at account and index positions
74
84
  getNativeSegWitAddress(xpub: string, account: number, index: number): string {
75
- const { address } = bjs.payments.p2wpkh({
76
- pubkey: this.getPubkeyAt(xpub, account, index),
77
- network: this.network,
78
- });
79
-
80
- return String(address);
85
+ const publicKeyBuffer: Buffer = this.getPubkeyAt(xpub, account, index);
86
+ const publicKeyHash160: Buffer = bjs.crypto.hash160(publicKeyBuffer);
87
+ const words: number[] = bech32.toWords(publicKeyHash160);
88
+ words.unshift(0x00);
89
+ return bech32.encode(this.network.bech32, words);
81
90
  }
82
91
 
83
92
  // derive SegWit at account and index positions
84
93
  getSegWitAddress(xpub: string, account: number, index: number): string {
85
- const { address } = bjs.payments.p2sh({
86
- redeem: bjs.payments.p2wpkh({
87
- pubkey: this.getPubkeyAt(xpub, account, index),
88
- network: this.network,
89
- }),
90
- });
91
- return String(address);
94
+ const publicKeyBuffer: Buffer = this.getPubkeyAt(xpub, account, index);
95
+ const redeemOutput: Buffer = bjs.script.compile([
96
+ 0,
97
+ bjs.crypto.hash160(publicKeyBuffer),
98
+ ]);
99
+ const publicKeyHash160: Buffer = bjs.crypto.hash160(redeemOutput);
100
+ const payload: Buffer = Buffer.allocUnsafe(21);
101
+ payload.writeUInt8(this.network.scriptHash, 0);
102
+ publicKeyHash160.copy(payload, 1);
103
+ return bs58check.encode(payload);
92
104
  }
93
105
 
94
106
  // get address given an address type
@@ -0,0 +1,36 @@
1
+ import ecc from "tiny-secp256k1";
2
+ import createHmac from "create-hmac";
3
+
4
+ // the BIP32 class is inspired from https://github.com/bitcoinjs/bip32/blob/master/src/bip32.js
5
+ class BIP32 {
6
+ publicKey: any;
7
+ chainCode: any;
8
+ network: any;
9
+ depth: number;
10
+ index: number;
11
+ constructor(
12
+ publicKey: any,
13
+ chainCode: any,
14
+ network: any,
15
+ depth = 0,
16
+ index = 0
17
+ ) {
18
+ this.publicKey = publicKey;
19
+ this.chainCode = chainCode;
20
+ this.network = network;
21
+ this.depth = depth;
22
+ this.index = index;
23
+ }
24
+ derive(index: number) {
25
+ const data = Buffer.allocUnsafe(37);
26
+ this.publicKey.copy(data, 0);
27
+ data.writeUInt32BE(index, 33);
28
+ const I = createHmac("sha512", this.chainCode).update(data).digest();
29
+ const IL = I.slice(0, 32);
30
+ const IR = I.slice(32);
31
+ const Ki = ecc.pointAddScalar(this.publicKey, IL, true);
32
+ return new BIP32(Ki, IR, this.network, this.depth + 1, index);
33
+ }
34
+ }
35
+
36
+ export default BIP32;
@@ -6,150 +6,7 @@ import bs58check from "bs58check";
6
6
  import createBlakeHash from "blake-hash";
7
7
  import RIPEMD160 from "ripemd160";
8
8
  import bs58 from "bs58";
9
- import ecc from "tiny-secp256k1";
10
- import createHash from "create-hash";
11
- import createHmac from "create-hmac";
12
-
13
- // the BIP32 class is inspired from https://github.com/bitcoinjs/bip32/blob/master/src/bip32.js
14
- class BIP32 {
15
- privateKey: any;
16
- publicKey: any;
17
- chainCode: any;
18
- network: any;
19
- depth: number;
20
- index: number;
21
- ParentFingerprint: number;
22
- lowR: boolean;
23
- constructor(
24
- privateKey,
25
- publicKey,
26
- chainCode,
27
- network,
28
- depth = 0,
29
- index = 0,
30
- ParentFingerprint = 0x00000000
31
- ) {
32
- this.privateKey = privateKey;
33
- this.publicKey = publicKey;
34
- this.chainCode = chainCode;
35
- this.network = network;
36
- this.depth = depth;
37
- this.index = index;
38
- this.ParentFingerprint = ParentFingerprint;
39
- this.lowR = false;
40
- }
41
- pk() {
42
- if (this.publicKey === undefined)
43
- this.publicKey = ecc.pointFromScalar(this.privateKey, true);
44
- return this.publicKey;
45
- }
46
- isNeutered() {
47
- return this.privateKey === undefined;
48
- }
49
- neutered() {
50
- return new BIP32(
51
- undefined,
52
- this.pk(),
53
- this.chainCode,
54
- this.network,
55
- this.depth,
56
- this.index,
57
- this.ParentFingerprint
58
- );
59
- }
60
- hmacSHA512(key, data) {
61
- return createHmac("sha512", key).update(data).digest();
62
- }
63
- hash160(buffer) {
64
- const sha256Hash = createHash("sha256").update(buffer).digest();
65
- return createHash("rmd160").update(sha256Hash).digest();
66
- }
67
- fingerprint() {
68
- return this.hash160(this.pk()).slice(0, 4);
69
- }
70
-
71
- toBase58() {
72
- const network = this.network;
73
- const version = !this.isNeutered()
74
- ? network.bip32.private
75
- : network.bip32.public;
76
- const buffer = Buffer.allocUnsafe(78);
77
- // 4 bytes: version bytes
78
- buffer.writeUInt32BE(version, 0);
79
- // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ....
80
- buffer.writeUInt8(this.depth, 4);
81
- // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
82
- buffer.writeUInt32BE(this.ParentFingerprint, 5);
83
- // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
84
- // This is encoded in big endian. (0x00000000 if master key)
85
- buffer.writeUInt32BE(this.index, 9);
86
- // 32 bytes: the chain code
87
- this.chainCode.copy(buffer, 13);
88
- // 33 bytes: the public key or private key data
89
- if (!this.isNeutered()) {
90
- // 0x00 + k for private keys
91
- buffer.writeUInt8(0, 45);
92
- this.privateKey.copy(buffer, 46);
93
- // 33 bytes: the public key
94
- } else {
95
- // X9.62 encoding for public keys
96
- this.pk().copy(buffer, 45);
97
- }
98
- return bs58check.encode(buffer);
99
- }
100
- // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions
101
- derive(index) {
102
- const isHardened = index >= 0x80000000;
103
- const data = Buffer.allocUnsafe(37);
104
- // Hardened child
105
- if (isHardened) {
106
- data[0] = 0x00;
107
- this.privateKey.copy(data, 1);
108
- data.writeUInt32BE(index, 33);
109
- } else {
110
- this.pk().copy(data, 0);
111
- data.writeUInt32BE(index, 33);
112
- }
113
- const I = this.hmacSHA512(this.chainCode, data);
114
- const IL = I.slice(0, 32);
115
- const IR = I.slice(32);
116
- // if parse256(IL) >= n, proceed with the next value for i
117
- if (!ecc.isPrivate(IL)) return this.derive(index + 1);
118
- // Private parent key -> private child key
119
- let hd;
120
- if (!this.isNeutered()) {
121
- // ki = parse256(IL) + kpar (mod n)
122
- const ki = ecc.privateAdd(this.privateKey, IL);
123
- // In case ki == 0, proceed with the next value for i
124
- if (ki == null) return this.derive(index + 1);
125
- hd = new BIP32(
126
- ki,
127
- undefined,
128
- IR,
129
- this.network,
130
- this.depth + 1,
131
- index,
132
- this.fingerprint().readUInt32BE(0)
133
- );
134
- } else {
135
- // Ki = point(parse256(IL)) + Kpar
136
- // = G*IL + Kpar
137
- const Ki = ecc.pointAddScalar(this.pk(), IL, true);
138
- // In case Ki is the point at infinity, proceed with the next value for i
139
- if (Ki === null) return this.derive(index + 1);
140
- hd = new BIP32(
141
- undefined,
142
- Ki,
143
- IR,
144
- this.network,
145
- this.depth + 1,
146
- index,
147
- this.fingerprint().readUInt32BE(0)
148
- );
149
- }
150
- return hd;
151
- }
152
- }
9
+ import BIP32 from "./bip32";
153
10
 
154
11
  class Decred extends Base {
155
12
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -227,20 +84,11 @@ class Decred extends Base {
227
84
  buffer = bs58check.decode(xpub);
228
85
  }
229
86
  const depth = buffer[4];
230
- const parentFingerprint = buffer.readUInt32BE(5);
231
87
  const i = buffer.readUInt32BE(9);
232
88
  const chainCode = buffer.slice(13, 45);
233
89
  const X = buffer.slice(45, 78);
234
- const hd = new BIP32(
235
- undefined,
236
- X,
237
- chainCode,
238
- this.network,
239
- depth,
240
- i,
241
- parentFingerprint
242
- );
243
- const publicKey = hd.derive(account).derive(index).pk();
90
+ const hd = new BIP32(X, chainCode, this.network, depth, i);
91
+ const publicKey = hd.derive(account).derive(index).publicKey;
244
92
  const address = Decred.getAddressFromPk(publicKey);
245
93
  Base.addressCache[`${derivationMode}-${xpub}-${account}-${index}`] =
246
94
  address;
@@ -1,4 +1,5 @@
1
1
  import { findLast, filter, uniqBy, findIndex, has } from "lodash";
2
+ import Base from "../crypto/base";
2
3
  import { Input, IStorage, Output, TX, Address } from "./types";
3
4
 
4
5
  // a mock storage class that just use js objects
@@ -12,12 +13,14 @@ class BitcoinLikeStorage implements IStorage {
12
13
  // accounting
13
14
  unspentUtxos: { [key: string]: Output[] } = {};
14
15
 
16
+ addressCache: { [key: string]: string } = {};
17
+
15
18
  // only needed to handle the case when the input
16
19
  // is seen before the output (typically explorer
17
20
  // returning unordered tx within the same block)
18
21
  spentUtxos: { [key: string]: Input[] } = {};
19
22
 
20
- async getLastTx(txFilter: {
23
+ getLastTx(txFilter: {
21
24
  account?: number;
22
25
  index?: number;
23
26
  address?: string;
@@ -38,18 +41,18 @@ class BitcoinLikeStorage implements IStorage {
38
41
  return tx;
39
42
  }
40
43
 
41
- async getTx(address: string, hash: string) {
44
+ getTx(address: string, hash: string) {
42
45
  const index = `${address}-${hash}`;
43
46
  return this.txs[this.primaryIndex[index]];
44
47
  }
45
48
 
46
49
  // TODO: only expose unspentUtxos
47
- async getAddressUnspentUtxos(address: Address) {
50
+ getAddressUnspentUtxos(address: Address) {
48
51
  const indexAddress = address.address;
49
52
  return this.unspentUtxos[indexAddress];
50
53
  }
51
54
 
52
- async appendTxs(txs: TX[]) {
55
+ appendTxs(txs: TX[]) {
53
56
  const lastLength = this.txs.length;
54
57
 
55
58
  txs.forEach((tx) => {
@@ -97,10 +100,7 @@ class BitcoinLikeStorage implements IStorage {
97
100
  return this.txs.length - lastLength;
98
101
  }
99
102
 
100
- async getUniquesAddresses(addressesFilter: {
101
- account?: number;
102
- index?: number;
103
- }) {
103
+ getUniquesAddresses(addressesFilter: { account?: number; index?: number }) {
104
104
  // TODO: to speed up, create more useful indexes in appendTxs
105
105
  return uniqBy(
106
106
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -114,7 +114,7 @@ class BitcoinLikeStorage implements IStorage {
114
114
  );
115
115
  }
116
116
 
117
- async removeTxs(txsFilter: { account: number; index: number }) {
117
+ removeTxs(txsFilter: { account: number; index: number }) {
118
118
  const newTxs: TX[] = [];
119
119
  this.primaryIndex = {};
120
120
 
@@ -137,7 +137,7 @@ class BitcoinLikeStorage implements IStorage {
137
137
 
138
138
  // We are a bit ugly because we can't rely undo unspentUTXO
139
139
  // So we clean the address and rebuild without the pendings
140
- async removePendingTxs(txsFilter: { account: number; index: number }) {
140
+ removePendingTxs(txsFilter: { account: number; index: number }) {
141
141
  const newTxs: TX[] = [];
142
142
  const txsToReAdd: TX[] = [];
143
143
  this.primaryIndex = {};
@@ -161,7 +161,14 @@ class BitcoinLikeStorage implements IStorage {
161
161
  });
162
162
 
163
163
  this.txs = newTxs;
164
- await this.appendTxs(txsToReAdd);
164
+ this.appendTxs(txsToReAdd);
165
+ }
166
+
167
+ addAddress(key: string, address: string): void {
168
+ if (!this.addressCache) {
169
+ this.addressCache = {};
170
+ }
171
+ this.addressCache[key] = address;
165
172
  }
166
173
 
167
174
  exportSync() {
@@ -169,6 +176,7 @@ class BitcoinLikeStorage implements IStorage {
169
176
  txs: this.txs,
170
177
  primaryIndex: this.primaryIndex,
171
178
  unspentUtxos: this.unspentUtxos,
179
+ addressCache: this.addressCache,
172
180
  };
173
181
  }
174
182
 
@@ -176,10 +184,13 @@ class BitcoinLikeStorage implements IStorage {
176
184
  txs: TX[];
177
185
  primaryIndex: { [key: string]: number };
178
186
  unspentUtxos: { [key: string]: Output[] };
187
+ addressCache: { [key: string]: string };
179
188
  }) {
180
189
  this.txs = data.txs;
181
190
  this.primaryIndex = data.primaryIndex;
182
191
  this.unspentUtxos = data.unspentUtxos;
192
+ this.addressCache = data.addressCache;
193
+ Base.addressCache = { ...Base.addressCache, ...this.addressCache };
183
194
  }
184
195
 
185
196
  async export() {
@@ -190,6 +201,7 @@ class BitcoinLikeStorage implements IStorage {
190
201
  txs: TX[];
191
202
  primaryIndex: { [key: string]: number };
192
203
  unspentUtxos: { [key: string]: Output[] };
204
+ addressCache: { [key: string]: string };
193
205
  }) {
194
206
  return this.loadSync(data);
195
207
  }
@@ -43,24 +43,22 @@ export interface Address {
43
43
  }
44
44
 
45
45
  export interface IStorage {
46
- appendTxs(txs: TX[]): Promise<number>;
47
- getAddressUnspentUtxos(address: Address): Promise<Output[]>;
46
+ appendTxs(txs: TX[]): number;
47
+ getAddressUnspentUtxos(address: Address): Output[];
48
48
  getLastTx(txFilter: {
49
49
  account?: number;
50
50
  index?: number;
51
51
  address?: string;
52
52
  confirmed?: boolean;
53
- }): Promise<TX | undefined>;
54
- getTx(address: string, hash: string): Promise<TX | undefined>;
53
+ }): TX | undefined;
54
+ getTx(address: string, hash: string): TX | undefined;
55
55
  getUniquesAddresses(addressesFilter: {
56
56
  account?: number;
57
57
  index?: number;
58
- }): Promise<Address[]>;
59
- removeTxs(txsFilter: { account: number; index: number }): Promise<void>;
60
- removePendingTxs(txsFilter: {
61
- account: number;
62
- index: number;
63
- }): Promise<void>;
58
+ }): Address[];
59
+ removeTxs(txsFilter: { account: number; index: number }): void;
60
+ removePendingTxs(txsFilter: { account: number; index: number }): void;
61
+ addAddress(key: string, address: string): void;
64
62
  export(): Promise<unknown>;
65
63
  load(data: unknown): Promise<void>;
66
64
  exportSync(): unknown;
@@ -66,6 +66,10 @@ class Xpub extends EventEmitter {
66
66
  index
67
67
  );
68
68
 
69
+ this.storage.addAddress(
70
+ `${this.derivationMode}-${this.xpub}-${account}-${index}`,
71
+ address
72
+ );
69
73
  await this.whenSynced("address", address);
70
74
 
71
75
  const data = {
@@ -87,13 +91,13 @@ class Xpub extends EventEmitter {
87
91
 
88
92
  // in case pendings have changed we clean them out
89
93
  // TODO perf : bad : looping in the tx array
90
- const hasPendings = !!(await this.storage.getLastTx({
94
+ const hasPendings = !!this.storage.getLastTx({
91
95
  confirmed: false,
92
96
  account,
93
97
  index,
94
- }));
98
+ });
95
99
  if (hasPendings) {
96
- await this.storage.removePendingTxs({ account, index });
100
+ this.storage.removePendingTxs({ account, index });
97
101
  }
98
102
  total = await this.fetchHydrateAndStoreNewTxs(address, account, index);
99
103
  } catch (e) {
@@ -103,7 +107,7 @@ class Xpub extends EventEmitter {
103
107
 
104
108
  this.emitSynced({ ...data, total });
105
109
 
106
- const lastTx = await this.storage.getLastTx({
110
+ const lastTx = this.storage.getLastTx({
107
111
  account,
108
112
  index,
109
113
  });
@@ -200,7 +204,7 @@ class Xpub extends EventEmitter {
200
204
  async getAddressBalance(address: Address) {
201
205
  await this.whenSynced("address", address.address);
202
206
 
203
- const unspentUtxos = await this.storage.getAddressUnspentUtxos(address);
207
+ const unspentUtxos = this.storage.getAddressUnspentUtxos(address);
204
208
 
205
209
  return unspentUtxos.reduce(
206
210
  (total, { value }) => total.plus(value),
@@ -419,7 +423,7 @@ class Xpub extends EventEmitter {
419
423
  let txs: TX[] = [];
420
424
  let inserted = 0;
421
425
  do {
422
- const lastTx = await this.storage.getLastTx({
426
+ const lastTx = this.storage.getLastTx({
423
427
  account,
424
428
  index,
425
429
  confirmed: true,
@@ -433,14 +437,14 @@ class Xpub extends EventEmitter {
433
437
  if (pendingTxs.length === 0) {
434
438
  pendingTxs = txs.filter((tx) => !tx.block);
435
439
  }
436
- inserted += await this.storage.appendTxs(txs.filter((tx) => tx.block)); // only insert not pending tx
440
+ inserted += this.storage.appendTxs(txs.filter((tx) => tx.block)); // only insert not pending tx
437
441
  } while (txs.length - pendingTxs.length >= this.txsSyncArraySize); // check whether page is full, if not, it is the last page
438
- inserted += await this.storage.appendTxs(pendingTxs);
442
+ inserted += this.storage.appendTxs(pendingTxs);
439
443
  return inserted;
440
444
  }
441
445
 
442
446
  async checkAddressReorg(account: number, index: number) {
443
- const lastTx = await this.storage.getLastTx({
447
+ const lastTx = this.storage.getLastTx({
444
448
  account,
445
449
  index,
446
450
  confirmed: true,
@@ -462,7 +466,7 @@ class Xpub extends EventEmitter {
462
466
  // TODO: delete only everything for this (address, block)
463
467
  // but need to think if its possible with current storage implem
464
468
 
465
- await this.storage.removeTxs({
469
+ this.storage.removeTxs({
466
470
  account,
467
471
  index,
468
472
  });
@@ -109,7 +109,11 @@ const getTransactionStatus = async (
109
109
  .lt(thresholdWarning)
110
110
  ) {
111
111
  if (isAccountDelegating(account)) {
112
- warnings.amount = new RecommendUndelegation();
112
+ if (t.useAllAmount) {
113
+ errors.amount = new RecommendUndelegation();
114
+ } else {
115
+ warnings.amount = new RecommendUndelegation();
116
+ }
113
117
  }
114
118
  }
115
119
  }
@@ -178,11 +182,14 @@ const prepareTransaction = async (
178
182
  },
179
183
  });
180
184
 
185
+ const t: Transaction = { ...transaction, taquitoError: null };
186
+
187
+ let amount = transaction.amount;
181
188
  if (transaction.useAllAmount) {
182
189
  // taquito does not accept 0, so we do 1
183
190
  // only failing case is when the account precisely has fees + 1. which is
184
191
  // unlikely
185
- transaction.amount = new BigNumber(1);
192
+ amount = new BigNumber(1);
186
193
  }
187
194
 
188
195
  try {
@@ -192,7 +199,7 @@ const prepareTransaction = async (
192
199
  out = await tezos.estimate.transfer({
193
200
  mutez: true,
194
201
  to: transaction.recipient,
195
- amount: transaction.amount.toNumber(),
202
+ amount: amount.toNumber(),
196
203
  });
197
204
  break;
198
205
  case "delegate":
@@ -210,7 +217,7 @@ const prepareTransaction = async (
210
217
  throw new Error("unsupported mode=" + transaction.mode);
211
218
  }
212
219
 
213
- if (transaction.useAllAmount) {
220
+ if (t.useAllAmount) {
214
221
  const totalFees = out.suggestedFeeMutez + out.burnFeeMutez;
215
222
  const maxAmount = account.balance
216
223
  .minus(totalFees + (tezosResources.revealed ? 0 : DEFAULT_FEE.REVEAL))
@@ -224,41 +231,59 @@ const prepareTransaction = async (
224
231
  return gasBuffer * MINIMAL_FEE_PER_GAS_MUTEZ + opSize;
225
232
  };
226
233
  const incr = increasedFee(gasBuffer, Number(out.opSize));
227
- transaction.fees = new BigNumber(out.suggestedFeeMutez + incr);
228
- transaction.gasLimit = new BigNumber(out.gasLimit + gasBuffer);
229
- transaction.amount = new BigNumber(maxAmount - incr);
234
+ t.fees = new BigNumber(out.suggestedFeeMutez + incr);
235
+ t.gasLimit = new BigNumber(out.gasLimit + gasBuffer);
236
+ t.amount = new BigNumber(maxAmount - incr);
230
237
  } else {
231
- transaction.fees = new BigNumber(out.suggestedFeeMutez);
232
- transaction.gasLimit = new BigNumber(out.gasLimit);
233
- transaction.storageLimit = new BigNumber(out.storageLimit);
238
+ t.fees = new BigNumber(out.suggestedFeeMutez);
239
+ t.gasLimit = new BigNumber(out.gasLimit);
240
+ t.storageLimit = new BigNumber(out.storageLimit);
234
241
  }
235
242
 
236
- transaction.storageLimit = new BigNumber(out.storageLimit);
237
- transaction.estimatedFees = transaction.fees;
243
+ t.storageLimit = new BigNumber(out.storageLimit);
244
+ t.estimatedFees = t.fees;
238
245
  if (!tezosResources.revealed) {
239
- transaction.estimatedFees = transaction.estimatedFees.plus(
240
- DEFAULT_FEE.REVEAL
241
- );
246
+ t.estimatedFees = t.estimatedFees.plus(DEFAULT_FEE.REVEAL);
242
247
  }
243
248
  } catch (e) {
244
249
  if (typeof e !== "object" || !e) throw e;
245
250
  if ("id" in e) {
246
- transaction.taquitoError = (e as { id: string }).id;
251
+ t.taquitoError = (e as { id: string }).id;
247
252
  } else if ("status" in e) {
248
253
  // in case of http 400, log & ignore (more case to handle)
249
254
  log(
250
255
  "taquito-network-error",
251
256
  String((e as { message: string }).message || ""),
252
- { transaction }
257
+ { transaction: t }
253
258
  );
254
259
  } else {
255
260
  throw e;
256
261
  }
257
262
  }
258
263
 
259
- return transaction;
264
+ // nothing changed
265
+ if (
266
+ bnEq(t.fees, transaction.fees) &&
267
+ bnEq(t.fees, transaction.fees) &&
268
+ bnEq(t.gasLimit, transaction.gasLimit) &&
269
+ bnEq(t.amount, transaction.amount) &&
270
+ bnEq(t.storageLimit, transaction.storageLimit) &&
271
+ bnEq(t.estimatedFees, transaction.estimatedFees) &&
272
+ t.taquitoError === transaction.taquitoError
273
+ ) {
274
+ return transaction;
275
+ }
276
+
277
+ return t;
260
278
  };
261
279
 
280
+ function bnEq(
281
+ a: BigNumber | null | undefined,
282
+ b: BigNumber | null | undefined
283
+ ): boolean {
284
+ return !a && !b ? true : !a || !b ? false : a.eq(b);
285
+ }
286
+
262
287
  const estimateMaxSpendable = async ({
263
288
  account,
264
289
  parentAccount,
@@ -8,6 +8,8 @@ import type { Account, SignOperationEvent } from "../../types";
8
8
  import { withDevice } from "../../hw/deviceAccess";
9
9
  import { getEnv } from "../../env";
10
10
  import { FeeNotLoaded } from "@ledgerhq/errors";
11
+ import { upperModulo } from "../../modulo";
12
+ import BigNumber from "bignumber.js";
11
13
 
12
14
  export const signOperation = ({
13
15
  account,
@@ -53,6 +55,16 @@ export const signOperation = ({
53
55
  storageLimit: transaction.storageLimit?.toNumber() || 0,
54
56
  gasLimit: transaction.gasLimit?.toNumber() || 0,
55
57
  };
58
+
59
+ if (["delegate", "undelegate"].includes(transaction.mode)) {
60
+ // https://ledgerhq.atlassian.net/browse/LL-8821
61
+ params.gasLimit = upperModulo(
62
+ transaction.gasLimit || new BigNumber(0),
63
+ new BigNumber(136),
64
+ new BigNumber(1000)
65
+ ).toNumber();
66
+ }
67
+
56
68
  switch (transaction.mode) {
57
69
  case "send":
58
70
  res = await tezos.contract.transfer({
@@ -226,7 +226,7 @@ const txToOp =
226
226
  }
227
227
 
228
228
  return {
229
- id: encodeOperationId(accountId, hash, type),
229
+ id: encodeOperationId(accountId, hash + String(tx.id), type),
230
230
  hash,
231
231
  type,
232
232
  value,