@ledgerhq/coin-bitcoin 0.28.0 → 0.29.0-nightly.20260116024452

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.
@@ -39,6 +39,9 @@
39
39
  "src/constants/index.ts",
40
40
  "src/supportedFeatures.ts"
41
41
  ],
42
- "ignoreUnresolved": [],
42
+ "ignoreUnresolved": [
43
+ "@jest/expect-utils",
44
+ "@jest/get-type",
45
+ "jest-util"],
43
46
  "ignoreUnused": []
44
47
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @ledgerhq/coin-bitcoin
2
2
 
3
+ ## 0.29.0-nightly.20260116024452
4
+
5
+ ### Minor Changes
6
+
7
+ - [#13396](https://github.com/LedgerHQ/ledger-live/pull/13396) [`b9a3e43`](https://github.com/LedgerHQ/ledger-live/commit/b9a3e431be33943ab4feb4294d6a7f27b966e61b) Thanks [@gre-ledger](https://github.com/gre-ledger)! - Update Jest to v30
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`537a975`](https://github.com/LedgerHQ/ledger-live/commit/537a975536ca3669d3b88371e1e1f651c4cb9a1b), [`cbcae7c`](https://github.com/LedgerHQ/ledger-live/commit/cbcae7c0ba9b54b1167d26e4227bd2b847207cb9), [`8754614`](https://github.com/LedgerHQ/ledger-live/commit/87546149a62b81f8a25bb6222626592ead629f62), [`50bae0f`](https://github.com/LedgerHQ/ledger-live/commit/50bae0f13a95ef166b2c5609ccbcf5ef01ba1579), [`cf08174`](https://github.com/LedgerHQ/ledger-live/commit/cf0817462e9f0210fceff29ec60b0699e4e69b71), [`b9a3e43`](https://github.com/LedgerHQ/ledger-live/commit/b9a3e431be33943ab4feb4294d6a7f27b966e61b), [`3ac5f26`](https://github.com/LedgerHQ/ledger-live/commit/3ac5f26111f8596327fa7e588e514509de3f8a59), [`7f05536`](https://github.com/LedgerHQ/ledger-live/commit/7f0553665e9c8721f263825cc79994bfc6729d9b)]:
12
+ - @ledgerhq/cryptoassets@13.37.0-nightly.20260116024452
13
+ - @ledgerhq/coin-framework@6.13.0-nightly.20260116024452
14
+ - @ledgerhq/types-live@6.93.0-nightly.20260116024452
15
+ - @ledgerhq/live-env@2.25.0-nightly.20260116024452
16
+ - @ledgerhq/types-cryptoassets@7.32.0-nightly.20260116024452
17
+ - @ledgerhq/devices@8.10.0-nightly.20260116024452
18
+ - @ledgerhq/errors@6.29.0-nightly.20260116024452
19
+ - @ledgerhq/logs@6.14.0-nightly.20260116024452
20
+ - @ledgerhq/live-network@2.2.0-nightly.20260116024452
21
+
3
22
  ## 0.28.0
4
23
 
5
24
  ### Minor Changes
package/jest.config.js CHANGED
@@ -1,4 +1,3 @@
1
- /** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
2
1
  module.exports = {
3
2
  passWithNoTests: true,
4
3
  collectCoverageFrom: [
@@ -11,8 +10,17 @@ module.exports = {
11
10
  "!src/wallet-btc/__tests__/**/*.ts",
12
11
  ],
13
12
  coverageReporters: ["json", ["lcov", { file: "lcov.info", projectRoot: "../../../" }], "text"],
14
- preset: "ts-jest",
15
13
  testEnvironment: "node",
14
+ transform: {
15
+ "^.+\\.(ts|tsx)$": [
16
+ "@swc/jest",
17
+ {
18
+ jsc: {
19
+ target: "esnext",
20
+ },
21
+ },
22
+ ],
23
+ },
16
24
  testPathIgnorePatterns: ["lib/", "lib-es/", ".integration.test.ts"],
17
25
  modulePathIgnorePatterns: ["__tests__/fixtures"],
18
26
  reporters: [
@@ -1,8 +1,19 @@
1
- /** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
1
+ /** @type {import('jest').Config} */
2
2
  module.exports = {
3
- preset: "ts-jest",
4
3
  testEnvironment: "node",
5
- testRegex: ".integration.test.ts$",
6
- testPathIgnorePatterns: ["lib/", "lib-es/", "bridge.integration.test.ts"],
4
+ testRegex: ".integ.test.ts$",
5
+ testPathIgnorePatterns: ["lib/", "lib-es/"],
7
6
  testTimeout: 60_000,
7
+ forceExit: true,
8
+ passWithNoTests: true,
9
+ transform: {
10
+ "^.+\\.(t|j)sx?$": [
11
+ "@swc/jest",
12
+ {
13
+ jsc: {
14
+ target: "esnext",
15
+ },
16
+ },
17
+ ],
18
+ },
8
19
  };
@@ -1 +1 @@
1
- {"version":3,"file":"explorer.d.ts","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAI9D,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AA6BF,eAAO,MAAM,mBAAmB,aAAc,cAAc,KAAG,cAI9D,CAAC;AAEF,eAAO,MAAM,iBAAiB,aAAc,cAAc,KAAG,MAG5D,CAAC"}
1
+ {"version":3,"file":"explorer.d.ts","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAI9D,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAqBF,eAAO,MAAM,mBAAmB,aAAc,cAAc,KAAG,cAI9D,CAAC;AAEF,eAAO,MAAM,iBAAiB,aAAc,cAAc,KAAG,MAG5D,CAAC"}
package/lib/explorer.js CHANGED
@@ -7,13 +7,6 @@ exports.blockchainBaseURL = exports.getCurrencyExplorer = void 0;
7
7
  const invariant_1 = __importDefault(require("invariant"));
8
8
  const live_env_1 = require("@ledgerhq/live-env");
9
9
  const findCurrencyExplorer = (currency) => {
10
- if ((0, live_env_1.getEnv)("SATSTACK") && currency.id === "bitcoin") {
11
- return {
12
- endpoint: (0, live_env_1.getEnv)("EXPLORER_SATSTACK"),
13
- id: "btc",
14
- version: "v3",
15
- };
16
- }
17
10
  if (!currency.explorerId) {
18
11
  console.warn("no explorerId for", currency.id);
19
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"explorer.js","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":";;;;;;AACA,0DAAkC;AAClC,iDAA4C;AAQ5C,MAAM,oBAAoB,GAAG,CAAC,QAAwB,EAAqC,EAAE;IAC3F,IAAI,IAAA,iBAAM,EAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO;YACL,QAAQ,EAAE,IAAA,iBAAM,EAAC,mBAAmB,CAAC;YACrC,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,iBAAiB,EAAE,CAAC;QACtC,OAAO;YACL,QAAQ,EAAE,IAAA,iBAAM,EAAC,kBAAkB,CAAC;YACpC,EAAE,EAAE,aAAa;YACjB,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,IAAA,iBAAM,EAAC,UAAU,CAAC;QAC5B,EAAE,EAAE,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,EAAE;QACtC,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,mBAAmB,GAAG,CAAC,QAAwB,EAAkB,EAAE;IAC9E,MAAM,GAAG,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAA,mBAAS,EAAC,GAAG,EAAE,0BAA0B,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAJW,QAAA,mBAAmB,uBAI9B;AAEK,MAAM,iBAAiB,GAAG,CAAC,QAAwB,EAAU,EAAE;IACpE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAA,2BAAmB,EAAC,QAAQ,CAAC,CAAC;IAChE,OAAO,GAAG,QAAQ,eAAe,OAAO,IAAI,EAAE,EAAE,CAAC;AACnD,CAAC,CAAC;AAHW,QAAA,iBAAiB,qBAG5B"}
1
+ {"version":3,"file":"explorer.js","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":";;;;;;AACA,0DAAkC;AAClC,iDAA4C;AAQ5C,MAAM,oBAAoB,GAAG,CAAC,QAAwB,EAAqC,EAAE;IAC3F,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,iBAAiB,EAAE,CAAC;QACtC,OAAO;YACL,QAAQ,EAAE,IAAA,iBAAM,EAAC,kBAAkB,CAAC;YACpC,EAAE,EAAE,aAAa;YACjB,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,IAAA,iBAAM,EAAC,UAAU,CAAC;QAC5B,EAAE,EAAE,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,EAAE;QACtC,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,mBAAmB,GAAG,CAAC,QAAwB,EAAkB,EAAE;IAC9E,MAAM,GAAG,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAA,mBAAS,EAAC,GAAG,EAAE,0BAA0B,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAJW,QAAA,mBAAmB,uBAI9B;AAEK,MAAM,iBAAiB,GAAG,CAAC,QAAwB,EAAU,EAAE;IACpE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAA,2BAAmB,EAAC,QAAQ,CAAC,CAAC;IAChE,OAAO,GAAG,QAAQ,eAAe,OAAO,IAAI,EAAE,EAAE,CAAC;AACnD,CAAC,CAAC;AAHW,QAAA,iBAAiB,qBAG5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"explorer.d.ts","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAI9D,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AA6BF,eAAO,MAAM,mBAAmB,aAAc,cAAc,KAAG,cAI9D,CAAC;AAEF,eAAO,MAAM,iBAAiB,aAAc,cAAc,KAAG,MAG5D,CAAC"}
1
+ {"version":3,"file":"explorer.d.ts","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAI9D,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAqBF,eAAO,MAAM,mBAAmB,aAAc,cAAc,KAAG,cAI9D,CAAC;AAEF,eAAO,MAAM,iBAAiB,aAAc,cAAc,KAAG,MAG5D,CAAC"}
@@ -1,13 +1,6 @@
1
1
  import invariant from "invariant";
2
2
  import { getEnv } from "@ledgerhq/live-env";
3
3
  const findCurrencyExplorer = (currency) => {
4
- if (getEnv("SATSTACK") && currency.id === "bitcoin") {
5
- return {
6
- endpoint: getEnv("EXPLORER_SATSTACK"),
7
- id: "btc",
8
- version: "v3",
9
- };
10
- }
11
4
  if (!currency.explorerId) {
12
5
  console.warn("no explorerId for", currency.id);
13
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"explorer.js","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQ5C,MAAM,oBAAoB,GAAG,CAAC,QAAwB,EAAqC,EAAE;IAC3F,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,mBAAmB,CAAC;YACrC,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,iBAAiB,EAAE,CAAC;QACtC,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,kBAAkB,CAAC;YACpC,EAAE,EAAE,aAAa;YACjB,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC;QAC5B,EAAE,EAAE,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,EAAE;QACtC,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAwB,EAAkB,EAAE;IAC9E,MAAM,GAAG,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC3C,SAAS,CAAC,GAAG,EAAE,0BAA0B,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAwB,EAAU,EAAE;IACpE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAChE,OAAO,GAAG,QAAQ,eAAe,OAAO,IAAI,EAAE,EAAE,CAAC;AACnD,CAAC,CAAC"}
1
+ {"version":3,"file":"explorer.js","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQ5C,MAAM,oBAAoB,GAAG,CAAC,QAAwB,EAAqC,EAAE;IAC3F,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,iBAAiB,EAAE,CAAC;QACtC,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,kBAAkB,CAAC;YACpC,EAAE,EAAE,aAAa;YACjB,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC;QAC5B,EAAE,EAAE,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,EAAE;QACtC,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAwB,EAAkB,EAAE;IAC9E,MAAM,GAAG,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC3C,SAAS,CAAC,GAAG,EAAE,0BAA0B,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAwB,EAAU,EAAE;IACpE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAChE,OAAO,GAAG,QAAQ,eAAe,OAAO,IAAI,EAAE,EAAE,CAAC;AACnD,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/coin-bitcoin",
3
- "version": "0.28.0",
3
+ "version": "0.29.0-nightly.20260116024452",
4
4
  "description": "Ledger Bitcoin Coin integration",
5
5
  "keywords": [
6
6
  "Ledger",
@@ -54,22 +54,22 @@
54
54
  "cashaddrjs": "^0.4.4",
55
55
  "coininfo": "^5.1.0",
56
56
  "create-hmac": "^1.1.7",
57
- "expect": "^27.4.6",
57
+ "expect": "30.2.0",
58
58
  "invariant": "^2.2.2",
59
59
  "lodash": "^4.17.21",
60
60
  "rxjs": "7.8.2",
61
61
  "@noble/curves": "^1.9.7",
62
62
  "utility-types": "^3.10.0",
63
63
  "varuint-bitcoin": "1.1.2",
64
- "@ledgerhq/coin-framework": "^6.12.0",
65
- "@ledgerhq/cryptoassets": "^13.36.0",
66
- "@ledgerhq/devices": "8.9.0",
67
- "@ledgerhq/errors": "^6.28.0",
68
- "@ledgerhq/live-env": "^2.24.0",
69
- "@ledgerhq/live-network": "^2.1.5",
70
- "@ledgerhq/logs": "^6.13.0",
71
- "@ledgerhq/types-cryptoassets": "^7.31.0",
72
- "@ledgerhq/types-live": "^6.92.0"
64
+ "@ledgerhq/coin-framework": "^6.13.0-nightly.20260116024452",
65
+ "@ledgerhq/cryptoassets": "^13.37.0-nightly.20260116024452",
66
+ "@ledgerhq/devices": "8.10.0-nightly.20260116024452",
67
+ "@ledgerhq/errors": "^6.29.0-nightly.20260116024452",
68
+ "@ledgerhq/live-env": "^2.25.0-nightly.20260116024452",
69
+ "@ledgerhq/live-network": "^2.2.0-nightly.20260116024452",
70
+ "@ledgerhq/logs": "^6.14.0-nightly.20260116024452",
71
+ "@ledgerhq/types-cryptoassets": "^7.32.0-nightly.20260116024452",
72
+ "@ledgerhq/types-live": "^6.93.0-nightly.20260116024452"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@types/bchaddrjs": "^0.4.3",
@@ -78,7 +78,7 @@
78
78
  "@types/cashaddrjs": "^0.3.3",
79
79
  "@types/create-hmac": "^1.1.3",
80
80
  "@types/invariant": "^2.2.2",
81
- "@types/jest": "^29.5.10",
81
+ "@types/jest": "30.0.0",
82
82
  "@types/lodash": "^4.14.191",
83
83
  "@types/object-hash": "^2.1.0",
84
84
  "@types/ripemd160": "^2.0.3",
@@ -87,11 +87,12 @@
87
87
  "axios": "1.13.2",
88
88
  "bip32": "^2.0.6",
89
89
  "bip39": "^3.0.4",
90
- "jest": "^29.7.0",
91
- "jest-file-snapshot": "^0.5.0",
90
+ "jest": "30.2.0",
91
+ "jest-file-snapshot": "0.7.0",
92
92
  "object-hash": "^2.2.0",
93
- "ts-jest": "^29.1.1",
94
- "@ledgerhq/disable-network-setup": "^0.1.0"
93
+ "@swc/jest": "0.2.39",
94
+ "@swc/core": "1.15.8",
95
+ "@ledgerhq/disable-network-setup": "^0.2.0-nightly.20260116024452"
95
96
  },
96
97
  "scripts": {
97
98
  "clean": "rimraf lib lib-es",
@@ -10,24 +10,25 @@ let currentExplorer: any = {
10
10
  getNetwork: jest.fn().mockResolvedValue({ relay_fee: "0.00001000" }), // 1 sat/vB
11
11
  };
12
12
 
13
- class DummyStrategy {
14
- constructor(..._args: any[]) {}
15
- }
16
-
17
- jest.mock("../../wallet-btc", () => ({
18
- __esModule: true,
19
- default: {
20
- estimateAccountMaxSpendable: (...args: any[]) => estimateAccountMaxSpendable(...args),
21
- buildAccountTx: (...args: any[]) => buildAccountTx(...args),
22
- },
23
- getWalletAccount: jest.fn((_account: any) => ({
24
- xpub: { explorer: currentExplorer, crypto: {} },
25
- derivationMode: "native_segwit",
26
- })),
27
- CoinSelect: DummyStrategy,
28
- DeepFirst: DummyStrategy,
29
- Merge: DummyStrategy,
30
- }));
13
+ jest.mock("../../wallet-btc", () => {
14
+ class DummyStrategy {
15
+ constructor(..._args: any[]) {}
16
+ }
17
+ return {
18
+ __esModule: true,
19
+ default: {
20
+ estimateAccountMaxSpendable: (...args: any[]) => estimateAccountMaxSpendable(...args),
21
+ buildAccountTx: (...args: any[]) => buildAccountTx(...args),
22
+ },
23
+ getWalletAccount: jest.fn((_account: any) => ({
24
+ xpub: { explorer: currentExplorer, crypto: {} },
25
+ derivationMode: "native_segwit",
26
+ })),
27
+ CoinSelect: DummyStrategy,
28
+ DeepFirst: DummyStrategy,
29
+ Merge: DummyStrategy,
30
+ };
31
+ });
31
32
 
32
33
  import { buildTransaction } from "../../buildTransaction";
33
34
 
package/src/explorer.ts CHANGED
@@ -9,14 +9,6 @@ type LedgerExplorer = {
9
9
  };
10
10
 
11
11
  const findCurrencyExplorer = (currency: CryptoCurrency): LedgerExplorer | null | undefined => {
12
- if (getEnv("SATSTACK") && currency.id === "bitcoin") {
13
- return {
14
- endpoint: getEnv("EXPLORER_SATSTACK"),
15
- id: "btc",
16
- version: "v3",
17
- };
18
- }
19
-
20
12
  if (!currency.explorerId) {
21
13
  console.warn("no explorerId for", currency.id);
22
14
  }
@@ -1,16 +1,35 @@
1
1
  /* eslint @typescript-eslint/consistent-type-assertions: 0 */
2
2
 
3
3
  import { Account } from "@ledgerhq/types-live";
4
- import * as cache from "./cache";
5
4
  import { BitcoinInput, Transaction } from "./types";
6
- import getTransactionStatus, { MAX_BLOCK_HEIGHT_FOR_TAPROOT } from "./getTransactionStatus";
7
5
  import { AddressesSanctionedError } from "@ledgerhq/coin-framework/sanction/errors";
8
6
  import BigNumber from "bignumber.js";
7
+
8
+ // Mock modules before importing the module under test
9
+ jest.mock("./cache", () => {
10
+ const actual = jest.requireActual("./cache");
11
+ return {
12
+ ...actual,
13
+ calculateFees: jest.fn(),
14
+ validateRecipient: jest.fn(),
15
+ };
16
+ });
17
+
18
+ jest.mock("@ledgerhq/coin-framework/sanction/index", () => {
19
+ const actual = jest.requireActual("@ledgerhq/coin-framework/sanction/index");
20
+ return {
21
+ ...actual,
22
+ isAddressSanctioned: jest.fn(),
23
+ };
24
+ });
25
+
26
+ import * as cache from "./cache";
9
27
  import * as sanction from "@ledgerhq/coin-framework/sanction/index";
28
+ import getTransactionStatus, { MAX_BLOCK_HEIGHT_FOR_TAPROOT } from "./getTransactionStatus";
10
29
 
11
- const calculateFeesSpy = jest.spyOn(cache, "calculateFees");
12
- const validateRecipientSpy = jest.spyOn(cache, "validateRecipient");
13
- const isAddressSanctionedSpy = jest.spyOn(sanction, "isAddressSanctioned");
30
+ const calculateFeesSpy = cache.calculateFees as jest.Mock;
31
+ const validateRecipientSpy = cache.validateRecipient as jest.Mock;
32
+ const isAddressSanctionedSpy = sanction.isAddressSanctioned as jest.Mock;
14
33
 
15
34
  describe("getTransactionStatus on Bitcoin", () => {
16
35
  it("should return as sender error only sanctioned utxo addresses", async () => {
@@ -1,19 +0,0 @@
1
- import { Observable } from "rxjs";
2
- import type { Result } from "@ledgerhq/coin-framework/derivation";
3
- import type { Account, DerivationMode } from "@ledgerhq/types-live";
4
- import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
5
- import { SignerContext } from "./signer";
6
- export type AccountDescriptor = {
7
- internal: string;
8
- external: string;
9
- };
10
- export declare function inferDescriptorFromAccount(account: Account): AccountDescriptor | null | undefined;
11
- export declare function inferDescriptorFromDeviceInfo({ derivationMode, currency, index, parentDerivation, accountDerivation, }: {
12
- derivationMode: DerivationMode;
13
- currency: CryptoCurrency;
14
- index: number;
15
- parentDerivation: Result;
16
- accountDerivation: Result;
17
- }): AccountDescriptor | null | undefined;
18
- export declare function scanDescriptors(deviceId: string, currency: CryptoCurrency, signerContext: SignerContext, limit?: number): Observable<AccountDescriptor>;
19
- //# sourceMappingURL=descriptor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"descriptor.d.ts","sourceRoot":"","sources":["../src/descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,MAAM,CAAC;AAInD,OAAO,KAAK,EAGV,MAAM,EACP,MAAM,qCAAqC,CAAC;AAS7C,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AA2CF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAYjG;AAwCD,wBAAgB,6BAA6B,CAAC,EAC5C,cAAc,EACd,QAAQ,EACR,KAAK,EACL,gBAAgB,EAChB,iBAAiB,GAClB,EAAE;IACD,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,iBAAiB,GAAG,IAAI,GAAG,SAAS,CA6BvC;AACD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,aAAa,EAAE,aAAa,EAC5B,KAAK,SAAK,GACT,UAAU,CAAC,iBAAiB,CAAC,CAoC/B"}
package/lib/descriptor.js DELETED
@@ -1,127 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.scanDescriptors = exports.inferDescriptorFromDeviceInfo = exports.inferDescriptorFromAccount = void 0;
7
- const rxjs_1 = require("rxjs");
8
- const operators_1 = require("rxjs/operators");
9
- const invariant_1 = __importDefault(require("invariant"));
10
- const bs58_1 = __importDefault(require("bs58"));
11
- const crypto_util_1 = require("./crypto-util");
12
- const derivation_1 = require("@ledgerhq/coin-framework/derivation");
13
- const hw_getAddress_1 = __importDefault(require("./hw-getAddress"));
14
- const index_1 = require("@ledgerhq/coin-framework/account/index");
15
- const perDerivation = {
16
- "": fragment => `pkh(${fragment})`,
17
- segwit: fragment => `sh(wpkh(${fragment}))`,
18
- native_segwit: fragment => `wpkh(${fragment})`,
19
- taproot: fragment => `tr(${fragment})`,
20
- };
21
- function makeFingerprint(compressedPubKey) {
22
- return (0, crypto_util_1.hash160)(compressedPubKey).slice(0, 4);
23
- }
24
- function makeDescriptor({ currency, index, derivationMode, fingerprint, xpub, }) {
25
- const tmpl = perDerivation[derivationMode];
26
- if (!tmpl || !xpub)
27
- return;
28
- const keyOrigin = fingerprint.toString("hex");
29
- const scheme = (0, derivation_1.getDerivationScheme)({
30
- currency,
31
- derivationMode,
32
- });
33
- const accountPath = (0, derivation_1.runAccountDerivationScheme)(scheme, currency, {
34
- account: index,
35
- });
36
- return {
37
- external: tmpl(`[${keyOrigin}/${accountPath}]${xpub}/0/*`),
38
- internal: tmpl(`[${keyOrigin}/${accountPath}]${xpub}/1/*`),
39
- };
40
- }
41
- function inferDescriptorFromAccount(account) {
42
- if (account.currency.family !== "bitcoin")
43
- return;
44
- const { id, derivationMode, seedIdentifier, currency, index } = account;
45
- const xpub = (0, index_1.decodeAccountId)(id).xpubOrAddress;
46
- const fingerprint = makeFingerprint(compressPublicKeySECP256(Buffer.from(seedIdentifier, "hex")));
47
- return makeDescriptor({
48
- derivationMode,
49
- currency,
50
- fingerprint,
51
- xpub,
52
- index,
53
- });
54
- }
55
- exports.inferDescriptorFromAccount = inferDescriptorFromAccount;
56
- function asBufferUInt32BE(n) {
57
- const buf = Buffer.allocUnsafe(4);
58
- buf.writeUInt32BE(n, 0);
59
- return buf;
60
- }
61
- const compressPublicKeySECP256 = (publicKey) => Buffer.concat([Buffer.from([0x02 + (publicKey[64] & 0x01)]), publicKey.slice(1, 33)]);
62
- function makeXpub({ version, depth, parentFingerprint, index, chainCode, pubKey, }) {
63
- const indexBuffer = asBufferUInt32BE(index);
64
- indexBuffer[0] |= 0x80;
65
- const extendedKeyBytes = Buffer.concat([
66
- asBufferUInt32BE(version),
67
- Buffer.from([depth]),
68
- parentFingerprint,
69
- indexBuffer,
70
- chainCode,
71
- pubKey,
72
- ]);
73
- const checksum = (0, crypto_util_1.hash256)(extendedKeyBytes).slice(0, 4);
74
- return bs58_1.default.encode(Buffer.concat([extendedKeyBytes, checksum]));
75
- }
76
- function inferDescriptorFromDeviceInfo({ derivationMode, currency, index, parentDerivation, accountDerivation, }) {
77
- (0, invariant_1.default)(currency.bitcoinLikeInfo, "bitcoin currency expected");
78
- const { bitcoinLikeInfo } = currency;
79
- const { XPUBVersion } = bitcoinLikeInfo;
80
- (0, invariant_1.default)(XPUBVersion, "unsupported bitcoin fork %s", currency.id);
81
- const { chainCode } = accountDerivation;
82
- (0, invariant_1.default)(chainCode, "chainCode is required");
83
- const fingerprint = makeFingerprint(compressPublicKeySECP256(Buffer.from(parentDerivation.publicKey, "hex")));
84
- const xpub = makeXpub({
85
- version: XPUBVersion,
86
- depth: 3,
87
- parentFingerprint: fingerprint,
88
- index,
89
- chainCode: Buffer.from(chainCode, "hex"),
90
- pubKey: compressPublicKeySECP256(Buffer.from(accountDerivation.publicKey, "hex")),
91
- });
92
- return makeDescriptor({
93
- derivationMode,
94
- currency,
95
- fingerprint,
96
- xpub,
97
- index,
98
- });
99
- }
100
- exports.inferDescriptorFromDeviceInfo = inferDescriptorFromDeviceInfo;
101
- function scanDescriptors(deviceId, currency, signerContext, limit = 10) {
102
- const derivateAddress = (opts) => (0, rxjs_1.from)((0, hw_getAddress_1.default)(signerContext)(deviceId, opts));
103
- function stepAddress({ index, accountDerivation, parentDerivation, derivationMode, }) {
104
- const result = inferDescriptorFromDeviceInfo({
105
- derivationMode,
106
- currency,
107
- index,
108
- parentDerivation,
109
- accountDerivation,
110
- });
111
- return !result
112
- ? rxjs_1.EMPTY
113
- : (0, rxjs_1.of)({
114
- result,
115
- complete: index >= limit,
116
- });
117
- }
118
- return (0, rxjs_1.from)((0, derivation_1.getDerivationModesForCurrency)(currency)).pipe((0, operators_1.concatMap)(derivationMode => (0, derivation_1.walletDerivation)({
119
- currency,
120
- derivationMode,
121
- derivateAddress,
122
- stepAddress,
123
- shouldDerivesOnAccount: true,
124
- })));
125
- }
126
- exports.scanDescriptors = scanDescriptors;
127
- //# sourceMappingURL=descriptor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"descriptor.js","sourceRoot":"","sources":["../src/descriptor.ts"],"names":[],"mappings":"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"}
@@ -1,19 +0,0 @@
1
- import { Observable } from "rxjs";
2
- import type { Result } from "@ledgerhq/coin-framework/derivation";
3
- import type { Account, DerivationMode } from "@ledgerhq/types-live";
4
- import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
5
- import { SignerContext } from "./signer";
6
- export type AccountDescriptor = {
7
- internal: string;
8
- external: string;
9
- };
10
- export declare function inferDescriptorFromAccount(account: Account): AccountDescriptor | null | undefined;
11
- export declare function inferDescriptorFromDeviceInfo({ derivationMode, currency, index, parentDerivation, accountDerivation, }: {
12
- derivationMode: DerivationMode;
13
- currency: CryptoCurrency;
14
- index: number;
15
- parentDerivation: Result;
16
- accountDerivation: Result;
17
- }): AccountDescriptor | null | undefined;
18
- export declare function scanDescriptors(deviceId: string, currency: CryptoCurrency, signerContext: SignerContext, limit?: number): Observable<AccountDescriptor>;
19
- //# sourceMappingURL=descriptor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"descriptor.d.ts","sourceRoot":"","sources":["../src/descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,MAAM,CAAC;AAInD,OAAO,KAAK,EAGV,MAAM,EACP,MAAM,qCAAqC,CAAC;AAS7C,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AA2CF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAYjG;AAwCD,wBAAgB,6BAA6B,CAAC,EAC5C,cAAc,EACd,QAAQ,EACR,KAAK,EACL,gBAAgB,EAChB,iBAAiB,GAClB,EAAE;IACD,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,iBAAiB,GAAG,IAAI,GAAG,SAAS,CA6BvC;AACD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,aAAa,EAAE,aAAa,EAC5B,KAAK,SAAK,GACT,UAAU,CAAC,iBAAiB,CAAC,CAoC/B"}
@@ -1,118 +0,0 @@
1
- import { from, of, EMPTY } from "rxjs";
2
- import { concatMap } from "rxjs/operators";
3
- import invariant from "invariant";
4
- import bs58 from "bs58";
5
- import { hash256, hash160 } from "./crypto-util";
6
- import { walletDerivation, getDerivationModesForCurrency, runAccountDerivationScheme, getDerivationScheme, } from "@ledgerhq/coin-framework/derivation";
7
- import getAddress from "./hw-getAddress";
8
- import { decodeAccountId } from "@ledgerhq/coin-framework/account/index";
9
- const perDerivation = {
10
- "": fragment => `pkh(${fragment})`,
11
- segwit: fragment => `sh(wpkh(${fragment}))`,
12
- native_segwit: fragment => `wpkh(${fragment})`,
13
- taproot: fragment => `tr(${fragment})`,
14
- };
15
- function makeFingerprint(compressedPubKey) {
16
- return hash160(compressedPubKey).slice(0, 4);
17
- }
18
- function makeDescriptor({ currency, index, derivationMode, fingerprint, xpub, }) {
19
- const tmpl = perDerivation[derivationMode];
20
- if (!tmpl || !xpub)
21
- return;
22
- const keyOrigin = fingerprint.toString("hex");
23
- const scheme = getDerivationScheme({
24
- currency,
25
- derivationMode,
26
- });
27
- const accountPath = runAccountDerivationScheme(scheme, currency, {
28
- account: index,
29
- });
30
- return {
31
- external: tmpl(`[${keyOrigin}/${accountPath}]${xpub}/0/*`),
32
- internal: tmpl(`[${keyOrigin}/${accountPath}]${xpub}/1/*`),
33
- };
34
- }
35
- export function inferDescriptorFromAccount(account) {
36
- if (account.currency.family !== "bitcoin")
37
- return;
38
- const { id, derivationMode, seedIdentifier, currency, index } = account;
39
- const xpub = decodeAccountId(id).xpubOrAddress;
40
- const fingerprint = makeFingerprint(compressPublicKeySECP256(Buffer.from(seedIdentifier, "hex")));
41
- return makeDescriptor({
42
- derivationMode,
43
- currency,
44
- fingerprint,
45
- xpub,
46
- index,
47
- });
48
- }
49
- function asBufferUInt32BE(n) {
50
- const buf = Buffer.allocUnsafe(4);
51
- buf.writeUInt32BE(n, 0);
52
- return buf;
53
- }
54
- const compressPublicKeySECP256 = (publicKey) => Buffer.concat([Buffer.from([0x02 + (publicKey[64] & 0x01)]), publicKey.slice(1, 33)]);
55
- function makeXpub({ version, depth, parentFingerprint, index, chainCode, pubKey, }) {
56
- const indexBuffer = asBufferUInt32BE(index);
57
- indexBuffer[0] |= 0x80;
58
- const extendedKeyBytes = Buffer.concat([
59
- asBufferUInt32BE(version),
60
- Buffer.from([depth]),
61
- parentFingerprint,
62
- indexBuffer,
63
- chainCode,
64
- pubKey,
65
- ]);
66
- const checksum = hash256(extendedKeyBytes).slice(0, 4);
67
- return bs58.encode(Buffer.concat([extendedKeyBytes, checksum]));
68
- }
69
- export function inferDescriptorFromDeviceInfo({ derivationMode, currency, index, parentDerivation, accountDerivation, }) {
70
- invariant(currency.bitcoinLikeInfo, "bitcoin currency expected");
71
- const { bitcoinLikeInfo } = currency;
72
- const { XPUBVersion } = bitcoinLikeInfo;
73
- invariant(XPUBVersion, "unsupported bitcoin fork %s", currency.id);
74
- const { chainCode } = accountDerivation;
75
- invariant(chainCode, "chainCode is required");
76
- const fingerprint = makeFingerprint(compressPublicKeySECP256(Buffer.from(parentDerivation.publicKey, "hex")));
77
- const xpub = makeXpub({
78
- version: XPUBVersion,
79
- depth: 3,
80
- parentFingerprint: fingerprint,
81
- index,
82
- chainCode: Buffer.from(chainCode, "hex"),
83
- pubKey: compressPublicKeySECP256(Buffer.from(accountDerivation.publicKey, "hex")),
84
- });
85
- return makeDescriptor({
86
- derivationMode,
87
- currency,
88
- fingerprint,
89
- xpub,
90
- index,
91
- });
92
- }
93
- export function scanDescriptors(deviceId, currency, signerContext, limit = 10) {
94
- const derivateAddress = (opts) => from(getAddress(signerContext)(deviceId, opts));
95
- function stepAddress({ index, accountDerivation, parentDerivation, derivationMode, }) {
96
- const result = inferDescriptorFromDeviceInfo({
97
- derivationMode,
98
- currency,
99
- index,
100
- parentDerivation,
101
- accountDerivation,
102
- });
103
- return !result
104
- ? EMPTY
105
- : of({
106
- result,
107
- complete: index >= limit,
108
- });
109
- }
110
- return from(getDerivationModesForCurrency(currency)).pipe(concatMap(derivationMode => walletDerivation({
111
- currency,
112
- derivationMode,
113
- derivateAddress,
114
- stepAddress,
115
- shouldDerivesOnAccount: true,
116
- })));
117
- }
118
- //# sourceMappingURL=descriptor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"descriptor.js","sourceRoot":"","sources":["../src/descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,IAAI,MAAM,MAAM,CAAC;AAMxB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,6BAA6B,EAC7B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AAGzC,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAOzE,MAAM,aAAa,GAEf;IACF,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,OAAO,QAAQ,GAAG;IAClC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,WAAW,QAAQ,IAAI;IAC3C,aAAa,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,QAAQ,GAAG;IAC9C,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,MAAM,QAAQ,GAAG;CACvC,CAAC;AAEF,SAAS,eAAe,CAAC,gBAAwB;IAC/C,OAAO,OAAO,CAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,cAAc,CAAC,EACtB,QAAQ,EACR,KAAK,EACL,cAAc,EACd,WAAW,EACX,IAAI,GAOL;IACC,MAAM,IAAI,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;IAC3C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO;IAC3B,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,mBAAmB,CAAC;QACjC,QAAQ;QACR,cAAc;KACf,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,0BAA0B,CAAC,MAAM,EAAE,QAAQ,EAAE;QAC/D,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IACH,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,IAAI,SAAS,IAAI,WAAW,IAAI,IAAI,MAAM,CAAC;QAC1D,QAAQ,EAAE,IAAI,CAAC,IAAI,SAAS,IAAI,WAAW,IAAI,IAAI,MAAM,CAAC;KAC3D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,OAAgB;IACzD,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO;IAClD,MAAM,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IACxE,MAAM,IAAI,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC;IAC/C,MAAM,WAAW,GAAG,eAAe,CAAC,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAClG,OAAO,cAAc,CAAC;QACpB,cAAc;QACd,QAAQ;QACR,WAAW;QACX,IAAI;QACJ,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAS;IACjC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAClC,GAAG,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,wBAAwB,GAAG,CAAC,SAAiB,EAAE,EAAE,CACrD,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAExF,SAAS,QAAQ,CAAC,EAChB,OAAO,EACP,KAAK,EACL,iBAAiB,EACjB,KAAK,EACL,SAAS,EACT,MAAM,GAQP;IACC,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC5C,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACvB,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC;QACrC,gBAAgB,CAAC,OAAO,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;QACpB,iBAAiB;QACjB,WAAW;QACX,SAAS;QACT,MAAM;KACP,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,EAC5C,cAAc,EACd,QAAQ,EACR,KAAK,EACL,gBAAgB,EAChB,iBAAiB,GAOlB;IACC,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,2BAA2B,CAAC,CAAC;IACjE,MAAM,EAAE,eAAe,EAAE,GAAG,QAAQ,CAAC;IACrC,MAAM,EAAE,WAAW,EAAE,GAAG,eAIvB,CAAC;IACF,SAAS,CAAC,WAAW,EAAE,6BAA6B,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnE,MAAM,EAAE,SAAS,EAAE,GAAG,iBAAiB,CAAC;IACxC,SAAS,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,eAAe,CACjC,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CACzE,CAAC;IACF,MAAM,IAAI,GAAG,QAAQ,CAAC;QACpB,OAAO,EAAE,WAAW;QACpB,KAAK,EAAE,CAAC;QACR,iBAAiB,EAAE,WAAW;QAC9B,KAAK;QACL,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAmB,EAAE,KAAK,CAAC;QAClD,MAAM,EAAE,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;KAClF,CAAC,CAAC;IACH,OAAO,cAAc,CAAC;QACpB,cAAc;QACd,QAAQ;QACR,WAAW;QACX,IAAI;QACJ,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AACD,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,QAAwB,EACxB,aAA4B,EAC5B,KAAK,GAAG,EAAE;IAEV,MAAM,eAAe,GAAG,CAAC,IAAuB,EAAE,EAAE,CAClD,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;IAElD,SAAS,WAAW,CAAC,EACnB,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,GACG;QACjB,MAAM,MAAM,GAAG,6BAA6B,CAAC;YAC3C,cAAc;YACd,QAAQ;YACR,KAAK;YACL,gBAAgB;YAChB,iBAAiB;SAClB,CAAC,CAAC;QACH,OAAO,CAAC,MAAM;YACZ,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,EAAE,CAAC;gBACD,MAAM;gBACN,QAAQ,EAAE,KAAK,IAAI,KAAK;aACzB,CAAC,CAAC;IACT,CAAC;IAED,OAAO,IAAI,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CACvD,SAAS,CAAC,cAAc,CAAC,EAAE,CACzB,gBAAgB,CAAC;QACf,QAAQ;QACR,cAAc;QACd,eAAe;QACf,WAAW;QACX,sBAAsB,EAAE,IAAI;KAC7B,CAAC,CACH,CACF,CAAC;AACJ,CAAC"}
@@ -1,76 +0,0 @@
1
- import invariant from "invariant";
2
- import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/index";
3
- import { setSupportedCurrencies } from "@ledgerhq/coin-framework/currencies/index";
4
- import { fromAccountRaw } from "@ledgerhq/coin-framework/serialization/index";
5
- import { inferDescriptorFromDeviceInfo, inferDescriptorFromAccount } from "./descriptor";
6
- import bitcoinDatasets from "./datasets/bitcoin";
7
- import { assignFromAccountRaw } from "./serialization";
8
- import type { CryptoAssetsStore } from "@ledgerhq/types-live";
9
- import { setCryptoAssetsStore } from "@ledgerhq/cryptoassets/state";
10
-
11
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12
- setCryptoAssetsStore({
13
- findTokenById: () => Promise.resolve(undefined),
14
- findTokenByAddressInCurrency: () => Promise.resolve(undefined),
15
- getTokensSyncHash: () => Promise.resolve("0"),
16
- } as CryptoAssetsStore);
17
-
18
- setSupportedCurrencies(["bitcoin"]);
19
- describe("inferDescriptorFromAccount", () => {
20
- invariant(bitcoinDatasets.accounts, "bitcoin datasets have accounts");
21
-
22
- let bitcoin1: any, bitcoin2: any;
23
-
24
- beforeAll(async () => {
25
- invariant(bitcoinDatasets.accounts, "bitcoin datasets have accounts in beforeAll");
26
- [bitcoin1, bitcoin2] = await Promise.all(
27
- bitcoinDatasets.accounts.map(a => fromAccountRaw(a.raw, { assignFromAccountRaw })),
28
- );
29
- });
30
-
31
- it("should work on bitcoin account 1", () => {
32
- expect(inferDescriptorFromAccount(bitcoin1)).toEqual({
33
- external:
34
- "pkh([224b6226/44'/0'/0']xpub6BuPWhjLqutPV8SF4RMrrn8c3t7uBZbz4CBbThpbg9GYjqRMncra9mjgSfWSK7uMDz37hhzJ8wvkbDDQQJt6VgwLoszvmPiSBtLA1bPLLSn/0/*)",
35
- internal:
36
- "pkh([224b6226/44'/0'/0']xpub6BuPWhjLqutPV8SF4RMrrn8c3t7uBZbz4CBbThpbg9GYjqRMncra9mjgSfWSK7uMDz37hhzJ8wvkbDDQQJt6VgwLoszvmPiSBtLA1bPLLSn/1/*)",
37
- });
38
- });
39
- it("should work on bitcoin account 2", () => {
40
- expect(inferDescriptorFromAccount(bitcoin2)).toEqual({
41
- external:
42
- "wpkh([d6a9e45e/84'/0'/1']xpub6DEHKg8fgKcb9at2u9Xhjtx4tXGyWqUPQAx2zNCzr41gQRyCqpCn7onSoJU4VS96GXyCtAhhFxErnG2pGVvVexaqF7DEfqGGnGk7Havn7C2/0/*)",
43
- internal:
44
- "wpkh([d6a9e45e/84'/0'/1']xpub6DEHKg8fgKcb9at2u9Xhjtx4tXGyWqUPQAx2zNCzr41gQRyCqpCn7onSoJU4VS96GXyCtAhhFxErnG2pGVvVexaqF7DEfqGGnGk7Havn7C2/1/*)",
45
- });
46
- });
47
- });
48
- describe("inferDescriptorFromDeviceInfo", () => {
49
- it("should work on a first Bitcoin legacy derivation", () => {
50
- const descriptor = inferDescriptorFromDeviceInfo({
51
- derivationMode: "",
52
- currency: getCryptoCurrencyById("bitcoin"),
53
- index: 0,
54
- parentDerivation: {
55
- address: "148LHFgQkoPKHUFeVzFNmUjKT7ZwB47fTR",
56
- path: "44'/0'",
57
- publicKey:
58
- "041caa3a42db5bdd125b2530c47cfbe829539b5a20a5562ec839d241c67d1862f2980d26ebffee25e4f924410c3316b397f34bd572543e72c59a7569ef9032f498",
59
- chainCode: "9f819c7d45eb9eb1e9bd5fa695158cca9e493182f95068b22c8c440ae6eb0720",
60
- },
61
- accountDerivation: {
62
- address: "15o6uBtRzKojbxqBe4Kni66BSvXfKYT2GY",
63
- path: "44'/0'/0'",
64
- publicKey:
65
- "04238878d371ce61cdd04d22ccab50c542e94ffa7a27d02d6bcefaa22e4fcee6db4c2029fd4de0b595e98002c0be01fc1fbd3568671e394c97a6d52c3d4c113fb5",
66
- chainCode: "44728146118df8d18d38c2615154eaffcdd53829957f4e26863344f35653364e",
67
- },
68
- });
69
- expect(descriptor).toEqual({
70
- external:
71
- "pkh([224b6226/44'/0'/0']xpub6BuPWhjLqutPV8SF4RMrrn8c3t7uBZbz4CBbThpbg9GYjqRMncra9mjgSfWSK7uMDz37hhzJ8wvkbDDQQJt6VgwLoszvmPiSBtLA1bPLLSn/0/*)",
72
- internal:
73
- "pkh([224b6226/44'/0'/0']xpub6BuPWhjLqutPV8SF4RMrrn8c3t7uBZbz4CBbThpbg9GYjqRMncra9mjgSfWSK7uMDz37hhzJ8wvkbDDQQJt6VgwLoszvmPiSBtLA1bPLLSn/1/*)",
74
- });
75
- });
76
- });
package/src/descriptor.ts DELETED
@@ -1,204 +0,0 @@
1
- import { Observable, from, of, EMPTY } from "rxjs";
2
- import { concatMap } from "rxjs/operators";
3
- import invariant from "invariant";
4
- import bs58 from "bs58";
5
- import type {
6
- GetAddressOptions,
7
- StepAddressInput,
8
- Result,
9
- } from "@ledgerhq/coin-framework/derivation";
10
- import { hash256, hash160 } from "./crypto-util";
11
- import {
12
- walletDerivation,
13
- getDerivationModesForCurrency,
14
- runAccountDerivationScheme,
15
- getDerivationScheme,
16
- } from "@ledgerhq/coin-framework/derivation";
17
- import getAddress from "./hw-getAddress";
18
- import type { Account, DerivationMode } from "@ledgerhq/types-live";
19
- import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
20
- import { decodeAccountId } from "@ledgerhq/coin-framework/account/index";
21
- import { SignerContext } from "./signer";
22
-
23
- export type AccountDescriptor = {
24
- internal: string;
25
- external: string;
26
- };
27
- const perDerivation: Partial<
28
- Record<DerivationMode, ((arg0: string) => string) | null | undefined>
29
- > = {
30
- "": fragment => `pkh(${fragment})`,
31
- segwit: fragment => `sh(wpkh(${fragment}))`,
32
- native_segwit: fragment => `wpkh(${fragment})`,
33
- taproot: fragment => `tr(${fragment})`,
34
- };
35
-
36
- function makeFingerprint(compressedPubKey: Buffer) {
37
- return hash160(compressedPubKey).slice(0, 4);
38
- }
39
-
40
- function makeDescriptor({
41
- currency,
42
- index,
43
- derivationMode,
44
- fingerprint,
45
- xpub,
46
- }: {
47
- currency: CryptoCurrency;
48
- index: number;
49
- derivationMode: DerivationMode;
50
- fingerprint: Buffer;
51
- xpub: string;
52
- }) {
53
- const tmpl = perDerivation[derivationMode];
54
- if (!tmpl || !xpub) return;
55
- const keyOrigin = fingerprint.toString("hex");
56
- const scheme = getDerivationScheme({
57
- currency,
58
- derivationMode,
59
- });
60
- const accountPath = runAccountDerivationScheme(scheme, currency, {
61
- account: index,
62
- });
63
- return {
64
- external: tmpl(`[${keyOrigin}/${accountPath}]${xpub}/0/*`),
65
- internal: tmpl(`[${keyOrigin}/${accountPath}]${xpub}/1/*`),
66
- };
67
- }
68
-
69
- export function inferDescriptorFromAccount(account: Account): AccountDescriptor | null | undefined {
70
- if (account.currency.family !== "bitcoin") return;
71
- const { id, derivationMode, seedIdentifier, currency, index } = account;
72
- const xpub = decodeAccountId(id).xpubOrAddress;
73
- const fingerprint = makeFingerprint(compressPublicKeySECP256(Buffer.from(seedIdentifier, "hex")));
74
- return makeDescriptor({
75
- derivationMode,
76
- currency,
77
- fingerprint,
78
- xpub,
79
- index,
80
- });
81
- }
82
-
83
- function asBufferUInt32BE(n: number) {
84
- const buf = Buffer.allocUnsafe(4);
85
- buf.writeUInt32BE(n, 0);
86
- return buf;
87
- }
88
-
89
- const compressPublicKeySECP256 = (publicKey: Buffer) =>
90
- Buffer.concat([Buffer.from([0x02 + (publicKey[64] & 0x01)]), publicKey.slice(1, 33)]);
91
-
92
- function makeXpub({
93
- version,
94
- depth,
95
- parentFingerprint,
96
- index,
97
- chainCode,
98
- pubKey,
99
- }: {
100
- version: number;
101
- depth: number;
102
- parentFingerprint: Buffer;
103
- index: number;
104
- chainCode: Buffer;
105
- pubKey: Buffer;
106
- }) {
107
- const indexBuffer = asBufferUInt32BE(index);
108
- indexBuffer[0] |= 0x80;
109
- const extendedKeyBytes = Buffer.concat([
110
- asBufferUInt32BE(version),
111
- Buffer.from([depth]),
112
- parentFingerprint,
113
- indexBuffer,
114
- chainCode,
115
- pubKey,
116
- ]);
117
- const checksum = hash256(extendedKeyBytes).slice(0, 4);
118
- return bs58.encode(Buffer.concat([extendedKeyBytes, checksum]));
119
- }
120
-
121
- export function inferDescriptorFromDeviceInfo({
122
- derivationMode,
123
- currency,
124
- index,
125
- parentDerivation,
126
- accountDerivation,
127
- }: {
128
- derivationMode: DerivationMode;
129
- currency: CryptoCurrency;
130
- index: number;
131
- parentDerivation: Result;
132
- accountDerivation: Result;
133
- }): AccountDescriptor | null | undefined {
134
- invariant(currency.bitcoinLikeInfo, "bitcoin currency expected");
135
- const { bitcoinLikeInfo } = currency;
136
- const { XPUBVersion } = bitcoinLikeInfo as {
137
- P2PKH: number;
138
- P2SH: number;
139
- XPUBVersion?: number;
140
- };
141
- invariant(XPUBVersion, "unsupported bitcoin fork %s", currency.id);
142
- const { chainCode } = accountDerivation;
143
- invariant(chainCode, "chainCode is required");
144
- const fingerprint = makeFingerprint(
145
- compressPublicKeySECP256(Buffer.from(parentDerivation.publicKey, "hex")),
146
- );
147
- const xpub = makeXpub({
148
- version: XPUBVersion,
149
- depth: 3,
150
- parentFingerprint: fingerprint,
151
- index,
152
- chainCode: Buffer.from(chainCode as string, "hex"),
153
- pubKey: compressPublicKeySECP256(Buffer.from(accountDerivation.publicKey, "hex")),
154
- });
155
- return makeDescriptor({
156
- derivationMode,
157
- currency,
158
- fingerprint,
159
- xpub,
160
- index,
161
- });
162
- }
163
- export function scanDescriptors(
164
- deviceId: string,
165
- currency: CryptoCurrency,
166
- signerContext: SignerContext,
167
- limit = 10,
168
- ): Observable<AccountDescriptor> {
169
- const derivateAddress = (opts: GetAddressOptions) =>
170
- from(getAddress(signerContext)(deviceId, opts));
171
-
172
- function stepAddress({
173
- index,
174
- accountDerivation,
175
- parentDerivation,
176
- derivationMode,
177
- }: StepAddressInput) {
178
- const result = inferDescriptorFromDeviceInfo({
179
- derivationMode,
180
- currency,
181
- index,
182
- parentDerivation,
183
- accountDerivation,
184
- });
185
- return !result
186
- ? EMPTY
187
- : of({
188
- result,
189
- complete: index >= limit,
190
- });
191
- }
192
-
193
- return from(getDerivationModesForCurrency(currency)).pipe(
194
- concatMap(derivationMode =>
195
- walletDerivation({
196
- currency,
197
- derivationMode,
198
- derivateAddress,
199
- stepAddress,
200
- shouldDerivesOnAccount: true,
201
- }),
202
- ),
203
- );
204
- }