edge-currency-plugins 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,6 @@ var _bnjs = require('bn.js'); var _bnjs2 = _interopRequireDefault(_bnjs);
5
5
 
6
6
 
7
7
 
8
- var _keymanager = require('../../keymanager/keymanager');
9
8
 
10
9
 
11
10
 
@@ -63,35 +62,16 @@ var _keymanager = require('../../keymanager/keymanager');
63
62
  args
64
63
  ) => {
65
64
  const { tx, processor, walletTools, pluginInfo, walletId } = args
66
- const { engineInfo, currencyInfo } = pluginInfo
65
+ const { currencyInfo } = pluginInfo
67
66
  const ourReceiveAddresses = []
68
67
  for (const out of tx.ourOuts) {
69
68
  const { scriptPubkey } = tx.outputs[parseInt(out)]
70
69
  const address = await processor.fetchAddress(scriptPubkey)
71
70
 
72
- /*
73
- Hack to set replay protection tx to the correct script type through the
74
- address format.
75
-
76
- We use a function which can determine whether the derivationLevelScriptHash
77
- was used for the path's change index in order to detect whether an address
78
- is used for replay protection. We need to detect this because we must treat
79
- the address format as bip49 because the script is P2SH even though the
80
- address is on the bip44 derivation chain.
81
- */
82
- const scriptTemplate = _optionalChain([engineInfo, 'access', _ => _.scriptTemplates, 'optionalAccess', _2 => _2.replayProtection])
83
- if (
84
- scriptTemplate != null &&
85
- _optionalChain([address, 'optionalAccess', _3 => _3.path]) != null &&
86
- _keymanager.isPathUsingDerivationLevelScriptHash.call(void 0, scriptTemplate, address.path)
87
- ) {
88
- address.path.format = 'bip49'
89
- }
90
-
91
- if (_optionalChain([address, 'optionalAccess', _4 => _4.path]) != null) {
71
+ if (_optionalChain([address, 'optionalAccess', _ => _.path]) != null) {
92
72
  const { address: addrStr } = walletTools.scriptPubkeyToAddress({
93
- scriptPubkey,
94
- format: address.path.format
73
+ changePath: address.path,
74
+ scriptPubkey
95
75
  })
96
76
  ourReceiveAddresses.push(addrStr)
97
77
  }
@@ -93,8 +93,8 @@ var _utils = require('./utils');
93
93
  }
94
94
 
95
95
  const walletTools = _makeUtxoWalletTools.makeUtxoWalletTools.call(void 0, {
96
- publicKey,
97
- coin: coinInfo.name
96
+ pluginInfo,
97
+ publicKey
98
98
  })
99
99
 
100
100
  const fees = await _makeFees.makeFees.call(void 0, {
@@ -648,8 +648,8 @@ var _utils = require('./utils');
648
648
  const tmpMetadata = await _makeMetadata.makeMetadata.call(void 0, tmpConfig)
649
649
  const tmpProcessor = await _makeProcessor.makeProcessor.call(void 0, tmpConfig)
650
650
  const tmpWalletTools = _makeUtxoWalletTools.makeUtxoWalletTools.call(void 0, {
651
- publicKey: tmpWalletInfo.keys.publicKey,
652
- coin: coinInfo.name
651
+ pluginInfo,
652
+ publicKey: tmpWalletInfo.keys.publicKey
653
653
  })
654
654
 
655
655
  // Max spend after imported wallet finishes sync
@@ -54,6 +54,8 @@ var _makeServerStates = require('./makeServerStates');
54
54
 
55
55
 
56
56
 
57
+
58
+
57
59
  var _utils3 = require('./utils');
58
60
 
59
61
 
@@ -243,8 +245,7 @@ var _utils3 = require('./utils');
243
245
  addToAddressTransactionCache(
244
246
  commonArgs,
245
247
  response.address,
246
- path.format,
247
- path.changeIndex,
248
+ path,
248
249
  0,
249
250
  taskCache.addressTransactionCache
250
251
  ).catch(() => {
@@ -267,13 +268,16 @@ var _utils3 = require('./utils');
267
268
  = []
268
269
 
269
270
  for (const format of walletFormats) {
270
- const branches = _utils3.getFormatSupportedBranches.call(void 0, format)
271
+ const branches = _utils3.getFormatSupportedBranches.call(void 0, pluginInfo.engineInfo, format)
271
272
  for (const branch of branches) {
272
273
  const addressesToSubscribe = new Set()
273
- const branchAddressCount = processor.numAddressesByFormatPath({
274
+ const changePath = {
274
275
  format,
275
276
  changeIndex: branch
276
- })
277
+ }
278
+ const branchAddressCount = processor.numAddressesByFormatPath(
279
+ changePath
280
+ )
277
281
  // If the processor has not processed any addresses then the loop
278
282
  // condition will only iterate once when branchAddressCount is 0 for the
279
283
  // first address in the derivation path.
@@ -293,8 +297,8 @@ var _utils3 = require('./utils');
293
297
  )
294
298
  }
295
299
  const { address } = walletTools.scriptPubkeyToAddress({
296
- scriptPubkey: processorAddress.scriptPubkey,
297
- format
300
+ changePath,
301
+ scriptPubkey: processorAddress.scriptPubkey
298
302
  })
299
303
  addressesToSubscribe.add(address)
300
304
  addressBalanceChanges.push({
@@ -467,8 +471,8 @@ var _utils3 = require('./utils');
467
471
  redeemScript
468
472
  } = walletTools.getScriptPubkeyFromWif(wif, format)
469
473
  const { address } = walletTools.scriptPubkeyToAddress({
470
- scriptPubkey,
471
- format: path.format
474
+ changePath: path,
475
+ scriptPubkey
472
476
  })
473
477
 
474
478
  // Make a new IAddress and save it
@@ -585,6 +589,7 @@ var _utils3 = require('./utils');
585
589
 
586
590
 
587
591
 
592
+
588
593
 
589
594
 
590
595
  const setLookAhead = async (common) => {
@@ -602,7 +607,7 @@ const setLookAhead = async (common) => {
602
607
 
603
608
  try {
604
609
  for (const format of walletFormats) {
605
- const branches = _utils3.getFormatSupportedBranches.call(void 0, format)
610
+ const branches = _utils3.getFormatSupportedBranches.call(void 0, engineInfo, format)
606
611
  for (const branch of branches) {
607
612
  await deriveKeys({ format, changeIndex: branch })
608
613
  }
@@ -627,8 +632,8 @@ const setLookAhead = async (common) => {
627
632
 
628
633
  const { scriptPubkey, redeemScript } = walletTools.getScriptPubkey(path)
629
634
  const { address } = walletTools.scriptPubkeyToAddress({
630
- scriptPubkey,
631
- format: path.format
635
+ changePath: path,
636
+ scriptPubkey
632
637
  })
633
638
 
634
639
  // Make a new IAddress and save it
@@ -668,14 +673,13 @@ const addToAddressSubscribeCache = (
668
673
  }
669
674
 
670
675
  const addToAddressTransactionCache = async (
671
- args,
676
+ common,
672
677
  address,
673
- format,
674
- branch,
678
+ changePath,
675
679
  blockHeight,
676
680
  addressTransactionCache
677
681
  ) => {
678
- const { walletTools, processor } = args
682
+ const { walletTools, processor } = common
679
683
  // Fetch the blockHeight for the address from the database
680
684
  const scriptPubkey = walletTools.addressToScriptPubkey(address)
681
685
 
@@ -687,10 +691,7 @@ const addToAddressTransactionCache = async (
687
691
 
688
692
  addressTransactionCache[address] = {
689
693
  processing: false,
690
- path: {
691
- format,
692
- changeIndex: branch
693
- },
694
+ path: changePath,
694
695
  page: 1, // Page starts on 1
695
696
  blockHeight
696
697
  }
@@ -774,21 +775,25 @@ const addToAddressTransactionCache = async (
774
775
  }
775
776
 
776
777
  // Loop unparsed utxos, some require a network call to get the full tx data
777
- for (const [utxoString, state] of Object.entries(rawUtxoCache)) {
778
- const utxo = JSON.parse(utxoString)
778
+ for (const [utxoId, state] of Object.entries(rawUtxoCache)) {
779
+ const utxo = state.blockbookUtxo
779
780
  if (utxo == null) continue
780
781
  if (!state.processing) {
781
782
  // check if we need to fetch additional network content for legacy purpose type
782
- const purposeType = _utils3.currencyFormatToPurposeType.call(void 0, state.path.format)
783
+ const purposeType = _utils3.pathToPurposeType.call(void 0,
784
+ state.path,
785
+ pluginInfo.engineInfo.scriptTemplates
786
+ )
783
787
  if (
784
788
  purposeType === _keymanager.BIP43PurposeTypeEnum.Airbitz ||
785
- purposeType === _keymanager.BIP43PurposeTypeEnum.Legacy
789
+ purposeType === _keymanager.BIP43PurposeTypeEnum.Legacy ||
790
+ purposeType === _keymanager.BIP43PurposeTypeEnum.ReplayProtection
786
791
  ) {
787
792
  // if we do need to make a network call, check with the serverState
788
793
  if (!serverStates.serverCanGetTx(uri, utxo.txid)) return
789
794
  }
790
795
  state.processing = true
791
- _utils.removeItem.call(void 0, rawUtxoCache, utxoString)
796
+ _utils.removeItem.call(void 0, rawUtxoCache, utxoId)
792
797
  const wsTask = await processRawUtxo({
793
798
  ...args,
794
799
  ...state,
@@ -829,30 +834,38 @@ const addToAddressTransactionCache = async (
829
834
 
830
835
  // Check if there are any addresses pending to be subscribed
831
836
  if (Object.keys(addressSubscribeCache).length > 0) {
832
- // These are addresse to which the server has not subscribed
833
- const newAddress = []
837
+ // These are addresses to which the server has not subscribed
838
+ const newAddresses = []
834
839
  const blockHeight = serverStates.getBlockHeight(uri)
835
840
 
836
841
  // Loop each address in the cache
837
842
  for (const [address, state] of Object.entries(addressSubscribeCache)) {
843
+ const isAddressNewlySubscribed = !serverStates.serverIsAwareOfAddress(
844
+ uri,
845
+ address
846
+ )
847
+
838
848
  // Add address in the cache to the set of addresses to watch
839
- if (!serverStates.serverIsAwareOfAddress(uri, address)) {
840
- newAddress.push(address)
849
+ if (isAddressNewlySubscribed) {
850
+ newAddresses.push(address)
841
851
  }
842
852
 
843
853
  // Add to the addressTransactionCache if they're not yet added:
844
854
  // Only process newly watched addresses
845
855
  if (state.processing) continue
856
+
846
857
  // Add the newly watched addresses to the UTXO cache
847
- addressUtxoCache[address] = {
848
- processing: false,
849
- path: state.path
858
+ if (isAddressNewlySubscribed) {
859
+ addressUtxoCache[address] = {
860
+ processing: false,
861
+ path: state.path
862
+ }
850
863
  }
864
+
851
865
  await addToAddressTransactionCache(
852
866
  args,
853
867
  address,
854
- state.path.format,
855
- state.path.changeIndex,
868
+ state.path,
856
869
  blockHeight,
857
870
  addressTransactionCache
858
871
  )
@@ -860,8 +873,8 @@ const addToAddressTransactionCache = async (
860
873
  }
861
874
 
862
875
  // Subscribe to any new addresses
863
- if (newAddress.length > 0) {
864
- serverStates.watchAddresses(uri, newAddress)
876
+ if (newAddresses.length > 0) {
877
+ serverStates.watchAddresses(uri, newAddresses)
865
878
  return true
866
879
  }
867
880
  }
@@ -1188,8 +1201,8 @@ const internalGetFreshAddress = async (
1188
1201
  throw new Error('Unknown address path')
1189
1202
  }
1190
1203
  const address = walletTools.scriptPubkeyToAddress({
1191
- scriptPubkey,
1192
- format
1204
+ changePath: path,
1205
+ scriptPubkey
1193
1206
  })
1194
1207
 
1195
1208
  return {
@@ -1415,7 +1428,9 @@ const processAddressUtxos = async (
1415
1428
  }
1416
1429
 
1417
1430
  for (const utxo of utxos) {
1418
- rawUtxoCache[JSON.stringify(utxo)] = {
1431
+ const utxoId = `${utxo.txid}_${utxo.vout}`
1432
+ rawUtxoCache[utxoId] = {
1433
+ blockbookUtxo: utxo,
1419
1434
  processing: false,
1420
1435
  requiredCount: utxos.length,
1421
1436
  path,
@@ -1557,6 +1572,7 @@ const processRawUtxo = async (
1557
1572
  utxo,
1558
1573
  id,
1559
1574
  address,
1575
+ pluginInfo,
1560
1576
  processor,
1561
1577
  path,
1562
1578
  taskCache,
@@ -1566,7 +1582,11 @@ const processRawUtxo = async (
1566
1582
  log
1567
1583
  } = args
1568
1584
  const { rawUtxoCache, processorUtxoCache } = taskCache
1569
- let scriptType
1585
+ const purposeType = _utils3.pathToPurposeType.call(void 0,
1586
+ path,
1587
+ pluginInfo.engineInfo.scriptTemplates
1588
+ )
1589
+ const scriptType = _utils3.getScriptTypeFromPurposeType.call(void 0, purposeType)
1570
1590
  let script
1571
1591
  let redeemScript
1572
1592
 
@@ -1591,19 +1611,18 @@ const processRawUtxo = async (
1591
1611
  }
1592
1612
  )
1593
1613
 
1594
- switch (_utils3.currencyFormatToPurposeType.call(void 0, path.format)) {
1614
+ switch (purposeType) {
1595
1615
  case _keymanager.BIP43PurposeTypeEnum.Airbitz:
1596
1616
  case _keymanager.BIP43PurposeTypeEnum.Legacy:
1597
- scriptType = _keymanager.ScriptTypeEnum.p2pkh
1598
- if (address.redeemScript != null) {
1599
- scriptType = _keymanager.ScriptTypeEnum.p2sh
1600
- redeemScript = address.redeemScript
1601
- }
1617
+ case _keymanager.BIP43PurposeTypeEnum.ReplayProtection:
1618
+ redeemScript = address.redeemScript
1602
1619
 
1603
1620
  // Legacy UTXOs need the previous transaction hex as the script
1604
1621
  // If we do not currently have it, add it to the queue to fetch it
1605
1622
  {
1606
- const [tx] = await processor.fetchTransactions({ txId: utxo.txid })
1623
+ const [tx] = await processor.fetchTransactions({
1624
+ txId: utxo.txid
1625
+ })
1607
1626
  if (tx == null) {
1608
1627
  const queryTime = Date.now()
1609
1628
  const deferred = new _Deferred2.default()
@@ -1621,7 +1640,9 @@ const processRawUtxo = async (
1621
1640
  .catch(err => {
1622
1641
  // If something went wrong, add the UTXO back to the queue
1623
1642
  log('error in processRawUtxo:', err)
1624
- rawUtxoCache[JSON.stringify(utxo)] = {
1643
+ const utxoId = `${utxo.txid}_${utxo.vout}`
1644
+ rawUtxoCache[utxoId] = {
1645
+ blockbookUtxo: utxo,
1625
1646
  processing: false,
1626
1647
  path,
1627
1648
  address,
@@ -1639,7 +1660,6 @@ const processRawUtxo = async (
1639
1660
 
1640
1661
  break
1641
1662
  case _keymanager.BIP43PurposeTypeEnum.WrappedSegwit:
1642
- scriptType = _keymanager.ScriptTypeEnum.p2wpkhp2sh
1643
1663
  script = address.scriptPubkey
1644
1664
  if (address.redeemScript == null) {
1645
1665
  throw new Error(
@@ -1650,7 +1670,6 @@ const processRawUtxo = async (
1650
1670
 
1651
1671
  break
1652
1672
  case _keymanager.BIP43PurposeTypeEnum.Segwit:
1653
- scriptType = _keymanager.ScriptTypeEnum.p2wpkh
1654
1673
  script = address.scriptPubkey
1655
1674
 
1656
1675
  break
@@ -13,12 +13,18 @@
13
13
 
14
14
 
15
15
 
16
+
17
+
18
+
19
+
20
+
16
21
  var _keymanager = require('../keymanager/keymanager');
17
22
 
18
23
 
19
24
 
20
25
 
21
26
 
27
+
22
28
  var _utils = require('./utils');
23
29
 
24
30
 
@@ -91,7 +97,9 @@ var _utils = require('./utils');
91
97
  function makeUtxoWalletTools(
92
98
  config
93
99
  ) {
94
- const { coin, publicKey } = config
100
+ const { pluginInfo, publicKey } = config
101
+ const { engineInfo } = pluginInfo
102
+ const { name: coin } = pluginInfo.coinInfo
95
103
 
96
104
  const xpubKeys = publicKey.publicKeys
97
105
 
@@ -112,10 +120,11 @@ var _utils = require('./utils');
112
120
  },
113
121
 
114
122
  getScriptPubkey(args) {
115
- const purposeType = _utils.currencyFormatToPurposeType.call(void 0, args.format)
123
+ const purposeType = _utils.pathToPurposeType.call(void 0, args, engineInfo.scriptTemplates)
116
124
  const scriptType = _utils.getScriptTypeFromPurposeType.call(void 0, purposeType)
117
125
  return _keymanager.pubkeyToScriptPubkey.call(void 0, {
118
126
  pubkey: fns.getPubkey(args),
127
+ scriptTemplates: engineInfo.scriptTemplates,
119
128
  scriptType
120
129
  })
121
130
  },
@@ -147,12 +156,16 @@ var _utils = require('./utils');
147
156
  const pubkey = _keymanager.privateKeyEncodingToPubkey.call(void 0, privateKeyEncoding)
148
157
  return _keymanager.pubkeyToScriptPubkey.call(void 0, {
149
158
  pubkey: pubkey,
159
+ scriptTemplates: engineInfo.scriptTemplates,
150
160
  scriptType
151
161
  })
152
162
  },
153
163
 
154
164
  getAddress(args) {
155
- const purposeType = _utils.currencyFormatToPurposeType.call(void 0, args.format)
165
+ const purposeType = _utils.pathToPurposeType.call(void 0,
166
+ args,
167
+ pluginInfo.engineInfo.scriptTemplates
168
+ )
156
169
  const { scriptPubkey } = fns.getScriptPubkey(args)
157
170
  const addressType = _utils.getAddressTypeFromPurposeType.call(void 0, purposeType)
158
171
  return _keymanager.scriptPubkeyToAddress.call(void 0, {
@@ -167,8 +180,13 @@ var _utils = require('./utils');
167
180
  },
168
181
 
169
182
  scriptPubkeyToAddress(args) {
170
- const purposeType = _utils.currencyFormatToPurposeType.call(void 0, args.format)
183
+ const { changePath } = args
184
+ const purposeType = _utils.pathToPurposeType.call(void 0,
185
+ changePath,
186
+ pluginInfo.engineInfo.scriptTemplates
187
+ )
171
188
  const addressType = _utils.getAddressTypeFromPurposeType.call(void 0, purposeType)
189
+
172
190
  return _keymanager.scriptPubkeyToAddress.call(void 0, {
173
191
  scriptPubkey: args.scriptPubkey,
174
192
  addressType,
@@ -2,9 +2,6 @@
2
2
 
3
3
 
4
4
  var _keymanager = require('../../keymanager/keymanager');
5
-
6
-
7
-
8
5
  var _utils = require('../utils');
9
6
 
10
7
  const getOwnUtxosFromTx = async (
@@ -43,18 +40,15 @@ var _utils = require('../utils');
43
40
  const path = address.path
44
41
  if (path != null) {
45
42
  const redeemScript = address.redeemScript
46
- const purposeType = _utils.currencyFormatToPurposeType.call(void 0, path.format)
43
+ const purposeType = _utils.pathToPurposeType.call(void 0, path, engineInfo.scriptTemplates)
47
44
 
48
45
  const isAirbitzOrLegacy = [
49
46
  _keymanager.BIP43PurposeTypeEnum.Airbitz,
50
- _keymanager.BIP43PurposeTypeEnum.Legacy
47
+ _keymanager.BIP43PurposeTypeEnum.Legacy,
48
+ _keymanager.BIP43PurposeTypeEnum.ReplayProtection
51
49
  ].includes(purposeType)
52
50
 
53
- const scriptType = _utils.getScriptTypeFromPurposeType.call(void 0,
54
- purposeType,
55
- redeemScript,
56
- engineInfo.scriptTemplates
57
- )
51
+ const scriptType = _utils.getScriptTypeFromPurposeType.call(void 0, purposeType)
58
52
  const script = isAirbitzOrLegacy ? tx.hex : address.scriptPubkey
59
53
  const utxo = {
60
54
  id,
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _biggystring = require('biggystring'); var bs = _interopRequireWildcard(_biggystring);
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }var _biggystring = require('biggystring'); var bs = _interopRequireWildcard(_biggystring);
2
2
 
3
3
 
4
4
 
@@ -18,6 +18,8 @@ var _cleaners = require('../keymanager/cleaners');
18
18
 
19
19
 
20
20
 
21
+
22
+
21
23
  var _keymanager = require('../keymanager/keymanager');
22
24
 
23
25
  const getCurrencyFormatFromPurposeType = (
@@ -32,6 +34,8 @@ var _keymanager = require('../keymanager/keymanager');
32
34
  return 'bip49'
33
35
  case _keymanager.BIP43PurposeTypeEnum.Segwit:
34
36
  return 'bip84'
37
+ case _keymanager.BIP43PurposeTypeEnum.ReplayProtection:
38
+ return 'bip44' // Only bip44 formatted wallets contain this purpose type (BCH)
35
39
  }
36
40
  }; exports.getCurrencyFormatFromPurposeType = getCurrencyFormatFromPurposeType
37
41
 
@@ -69,27 +73,18 @@ var _keymanager = require('../keymanager/keymanager');
69
73
 
70
74
  case _keymanager.BIP43PurposeTypeEnum.Segwit:
71
75
  return _keymanager.AddressTypeEnum.p2wpkh
76
+
77
+ case _keymanager.BIP43PurposeTypeEnum.ReplayProtection:
78
+ return _keymanager.AddressTypeEnum.p2sh
72
79
  }
73
80
  }; exports.getAddressTypeFromPurposeType = getAddressTypeFromPurposeType
74
81
 
75
82
  const getScriptTypeFromPurposeType = (
76
- purpose,
77
- redeemScript,
78
- scriptTemplates
83
+ purpose
79
84
  ) => {
80
85
  switch (purpose) {
81
86
  case _keymanager.BIP43PurposeTypeEnum.Airbitz:
82
87
  case _keymanager.BIP43PurposeTypeEnum.Legacy:
83
- if (redeemScript != null) {
84
- if (_optionalChain([scriptTemplates, 'optionalAccess', _ => _.replayProtection]) != null) {
85
- const replayProtectionPartialScript = scriptTemplates
86
- .replayProtection('')
87
- .slice(0, -4)
88
- if (redeemScript.indexOf(replayProtectionPartialScript) === 0) {
89
- return _keymanager.ScriptTypeEnum.replayProtection
90
- }
91
- }
92
- }
93
88
  return _keymanager.ScriptTypeEnum.p2pkh
94
89
 
95
90
  case _keymanager.BIP43PurposeTypeEnum.WrappedSegwit:
@@ -97,6 +92,9 @@ var _keymanager = require('../keymanager/keymanager');
97
92
 
98
93
  case _keymanager.BIP43PurposeTypeEnum.Segwit:
99
94
  return _keymanager.ScriptTypeEnum.p2wpkh
95
+
96
+ case _keymanager.BIP43PurposeTypeEnum.ReplayProtection:
97
+ return _keymanager.ScriptTypeEnum.replayProtection
100
98
  }
101
99
  }; exports.getScriptTypeFromPurposeType = getScriptTypeFromPurposeType
102
100
 
@@ -109,15 +107,63 @@ var _keymanager = require('../keymanager/keymanager');
109
107
  }); exports.validScriptPubkeyFromAddress = validScriptPubkeyFromAddress
110
108
 
111
109
  const getFormatSupportedBranches = (
110
+ engineInfo,
112
111
  format
113
112
  ) => {
114
113
  const branches = [0]
115
114
  if (exports.currencyFormatToPurposeType.call(void 0, format) !== _keymanager.BIP43PurposeTypeEnum.Airbitz) {
116
115
  branches.push(1)
117
116
  }
117
+ if (engineInfo.scriptTemplates != null) {
118
+ if (engineInfo.scriptTemplates.replayProtection != null) {
119
+ branches.push(
120
+ _keymanager.derivationLevelScriptHash.call(void 0, engineInfo.scriptTemplates.replayProtection)
121
+ )
122
+ }
123
+ }
118
124
  return branches
119
125
  }; exports.getFormatSupportedBranches = getFormatSupportedBranches
120
126
 
127
+ /**
128
+ * The reason for this function is to consider the address path for
129
+ * determining the purpose-type for the address. This is because some parts
130
+ * of the address such as the changeIndex have special meaning for the
131
+ * purpose-type. Specifically for scriptTemplates, the hash of the template
132
+ * is used to deterministically identify the changeIndex used constantly for
133
+ * the addresses spending to those scriptTemplates.
134
+ *
135
+ * In the future, we will want to strictly use only the format of the path
136
+ * in order to determine the purpose-type per the BIP43 spec. This will require
137
+ * a significant lift to reconsider the type for the path's format (currently
138
+ * CurrencyFormat). The scriptTemplates could define a format index and this
139
+ * could be used in address paths instead of a CurrencyType.
140
+ */
141
+ const pathToPurposeType = (
142
+ path,
143
+ scriptTemplates
144
+ ) => {
145
+ // Script Template Purpose Types
146
+ if (scriptTemplates != null) {
147
+ // TODO: Change ScriptTemplates map type to couple the key to the ScriptTypeEnum; make this algorithm generic and move it to key-manager
148
+ // Handle each hard-coded case for the supported script templates
149
+ if (
150
+ scriptTemplates.replayProtection != null &&
151
+ _keymanager.isPathUsingDerivationLevelScriptHash.call(void 0,
152
+ scriptTemplates.replayProtection,
153
+ path
154
+ )
155
+ ) {
156
+ return _keymanager.BIP43PurposeTypeEnum.ReplayProtection
157
+ }
158
+ }
159
+ return exports.currencyFormatToPurposeType.call(void 0, path.format)
160
+ }; exports.pathToPurposeType = pathToPurposeType
161
+
162
+ /**
163
+ * Only use this function when needing to infer the purpose-type for a wallet
164
+ * format (CurrencyFormat). To get the purpose-type for an address use
165
+ * pathToPurposeType passing the address path.
166
+ */
121
167
  const currencyFormatToPurposeType = (
122
168
  format
123
169
  ) =>
@@ -52,7 +52,7 @@ const currencyInfo = {
52
52
 
53
53
  const engineInfo = {
54
54
  formats: ['bip44', 'bip32'],
55
- // forks: ['bitcoinsv'],
55
+ forks: ['bitcoinsv'],
56
56
  gapLimit: 10,
57
57
  defaultFee: 10000,
58
58
  feeUpdateInterval: 60000,
@@ -28,6 +28,7 @@ var BIP43PurposeTypeEnum; (function (BIP43PurposeTypeEnum) {
28
28
  const Legacy = 'legacy'; BIP43PurposeTypeEnum["Legacy"] = Legacy; // xpub/xprv tpub/tprv etc.
29
29
  const Segwit = 'segwit'; BIP43PurposeTypeEnum["Segwit"] = Segwit; // zpub/zprv vpub/vprv etc.
30
30
  const WrappedSegwit = 'wrappedSegwit'; BIP43PurposeTypeEnum["WrappedSegwit"] = WrappedSegwit; // ypub/yprv upub/uprv etc.
31
+ const ReplayProtection = 'replayProtection'; BIP43PurposeTypeEnum["ReplayProtection"] = ReplayProtection;
31
32
  })(BIP43PurposeTypeEnum || (exports.BIP43PurposeTypeEnum = BIP43PurposeTypeEnum = {}));
32
33
 
33
34
  // supported address types.
@@ -239,6 +240,7 @@ var VerifyAddressEnum; (function (VerifyAddressEnum) {
239
240
 
240
241
 
241
242
 
243
+
242
244
 
243
245
 
244
246
  function bip43PurposeNumberToTypeEnum(
@@ -510,12 +512,18 @@ const addressToScriptPubkeyInternal = (
510
512
  default:
511
513
  throw new Error('invalid address type in address to script pubkey')
512
514
  }
513
- const scriptPubkey = payment({
514
- address: args.address,
515
- network: network,
516
- bs58DecodeFunc: coin.bs58DecodeFunc,
517
- bs58EncodeFunc: coin.bs58EncodeFunc
518
- }).output
515
+ let scriptPubkey
516
+ try {
517
+ scriptPubkey = payment({
518
+ address: args.address,
519
+ network: network,
520
+ bs58DecodeFunc: coin.bs58DecodeFunc,
521
+ bs58EncodeFunc: coin.bs58EncodeFunc
522
+ }).output
523
+ } catch (error) {
524
+ console.trace(error)
525
+ throw error
526
+ }
519
527
  if (scriptPubkey == null) {
520
528
  throw new Error('failed converting address to scriptPubkey')
521
529
  }
@@ -621,23 +629,28 @@ const addressToScriptPubkeyInternal = (
621
629
  default:
622
630
  throw new Error('invalid address type in address to script pubkey')
623
631
  }
624
- address =
625
- _nullishCoalesce(address, () => (
626
- payment({
627
- output: Buffer.from(args.scriptPubkey, 'hex'),
628
- network: network,
629
- bs58DecodeFunc: coinClass.bs58DecodeFunc,
630
- bs58EncodeFunc: coinClass.bs58EncodeFunc
631
- }).address))
632
-
633
- legacyAddress =
634
- _nullishCoalesce(legacyAddress, () => (
635
- payment({
636
- output: Buffer.from(args.scriptPubkey, 'hex'),
637
- network: legacyNetwork,
638
- bs58DecodeFunc: coinClass.bs58DecodeFunc,
639
- bs58EncodeFunc: coinClass.bs58EncodeFunc
640
- }).address))
632
+ try {
633
+ address =
634
+ _nullishCoalesce(address, () => (
635
+ payment({
636
+ output: Buffer.from(args.scriptPubkey, 'hex'),
637
+ network: network,
638
+ bs58DecodeFunc: coinClass.bs58DecodeFunc,
639
+ bs58EncodeFunc: coinClass.bs58EncodeFunc
640
+ }).address))
641
+
642
+ legacyAddress =
643
+ _nullishCoalesce(legacyAddress, () => (
644
+ payment({
645
+ output: Buffer.from(args.scriptPubkey, 'hex'),
646
+ network: legacyNetwork,
647
+ bs58DecodeFunc: coinClass.bs58DecodeFunc,
648
+ bs58EncodeFunc: coinClass.bs58EncodeFunc
649
+ }).address))
650
+ } catch (error) {
651
+ console.trace(error)
652
+ throw error
653
+ }
641
654
 
642
655
  if (address == null || legacyAddress == null) {
643
656
  throw new Error('failed converting scriptPubkey to address')
@@ -666,10 +679,16 @@ const addressToScriptPubkeyInternal = (
666
679
  default:
667
680
  throw new Error('invalid address type in address to script pubkey')
668
681
  }
669
- const scriptHash = payment({
670
- output: Buffer.from(args.scriptPubkey, 'hex'),
671
- network: network
672
- }).hash
682
+ let scriptHash
683
+ try {
684
+ scriptHash = payment({
685
+ output: Buffer.from(args.scriptPubkey, 'hex'),
686
+ network: network
687
+ }).hash
688
+ } catch (error) {
689
+ console.trace(error)
690
+ throw error
691
+ }
673
692
  if (scriptHash == null) {
674
693
  throw new Error('failed converting scriptPubkey to address')
675
694
  }
@@ -693,13 +712,34 @@ const addressToScriptPubkeyInternal = (
693
712
  output: Buffer.from(scriptPubkey, 'hex')
694
713
  }
695
714
  })
696
- if (p2sh.output == null || _optionalChain([p2sh, 'access', _ => _.redeem, 'optionalAccess', _2 => _2.output]) == null) {
715
+ const scriptPubkeyFromLib = _optionalChain([p2sh, 'access', _ => _.output, 'optionalAccess', _2 => _2.toString, 'call', _3 => _3('hex')])
716
+ const redeemScript = _optionalChain([p2sh, 'access', _4 => _4.redeem, 'optionalAccess', _5 => _5.output, 'optionalAccess', _6 => _6.toString, 'call', _7 => _7('hex')])
717
+ const scriptHash = _optionalChain([p2sh, 'access', _8 => _8.hash, 'optionalAccess', _9 => _9.toString, 'call', _10 => _10('hex')])
718
+
719
+ if (scriptPubkeyFromLib == null || redeemScript == null) {
697
720
  throw new Error('unable to convert script to p2sh')
698
721
  }
722
+
723
+ let address = p2sh.address
724
+
725
+ // Special cashaddr handling
726
+ if (coin != null && scriptHash != null) {
727
+ const coinClass = _coinmapper.getCoinFromString.call(void 0, coin)
728
+ const coinPrefixes = coinClass.prefixes
729
+ const standardPrefixes = selectedCoinPrefixes(coinPrefixes, 0)
730
+ if (standardPrefixes.cashaddr != null) {
731
+ address = _cashAddress.hashToCashAddress.call(void 0,
732
+ scriptHash,
733
+ _cashAddress.CashaddrTypeEnum.scripthash,
734
+ standardPrefixes.cashaddr
735
+ )
736
+ }
737
+ }
738
+
699
739
  return {
700
- scriptPubkey: p2sh.output.toString('hex'),
701
- redeemScript: p2sh.redeem.output.toString('hex'),
702
- address: p2sh.address
740
+ scriptPubkey: scriptPubkeyFromLib,
741
+ redeemScript: redeemScript,
742
+ address
703
743
  }
704
744
  } exports.scriptPubkeyToP2SH = scriptPubkeyToP2SH;
705
745
 
@@ -731,6 +771,14 @@ const addressToScriptPubkeyInternal = (
731
771
  throw new Error('failed converting pubkey to script pubkey')
732
772
  }
733
773
  return { scriptPubkey: payment.output.toString('hex') }
774
+ case ScriptTypeEnum.replayProtection: {
775
+ if (args.scriptTemplates == null)
776
+ throw new Error('Missing replayProtection script template')
777
+ const redeemScript = args.scriptTemplates.replayProtection(args.pubkey)
778
+ return scriptPubkeyToP2SH({
779
+ scriptPubkey: redeemScript
780
+ })
781
+ }
734
782
  default:
735
783
  throw new Error('invalid address type in pubkey to script pubkey')
736
784
  }
@@ -761,9 +809,9 @@ const xprivToPrivateKeyInternal = (
761
809
  const bip32FromBase58Func = _nullishCoalesce(coin.bip32FromBase58Func, () => ( bip32.fromBase58))
762
810
  const node = bip32FromBase58Func(args.xpriv, network)
763
811
  return _optionalChain([node
764
- , 'access', _3 => _3.derive, 'call', _4 => _4(args.bip44ChangeIndex)
765
- , 'access', _5 => _5.derive, 'call', _6 => _6(args.bip44AddressIndex)
766
- , 'access', _7 => _7.privateKey, 'optionalAccess', _8 => _8.toString, 'call', _9 => _9('hex')])
812
+ , 'access', _11 => _11.derive, 'call', _12 => _12(args.bip44ChangeIndex)
813
+ , 'access', _13 => _13.derive, 'call', _14 => _14(args.bip44AddressIndex)
814
+ , 'access', _15 => _15.privateKey, 'optionalAccess', _16 => _16.toString, 'call', _17 => _17('hex')])
767
815
  }
768
816
 
769
817
  const xprivToPrivateKey = (args) => {
@@ -992,7 +1040,7 @@ const wifToPrivateKeyEncodingInternal = (
992
1040
  psbt.addInputs(sortedInputs)
993
1041
  psbt.addOutputs(sortedOutputs)
994
1042
  } catch (error) {
995
- _optionalChain([log, 'optionalAccess', _10 => _10.error, 'call', _11 => _11(`Failed makeTx: ${String(error)}`)])
1043
+ _optionalChain([log, 'optionalAccess', _18 => _18.error, 'call', _19 => _19(`Failed makeTx: ${String(error)}`)])
996
1044
  throw error
997
1045
  }
998
1046
 
@@ -1002,7 +1050,7 @@ const wifToPrivateKeyEncodingInternal = (
1002
1050
  changeUsed: result.changeUsed,
1003
1051
  fee: result.fee,
1004
1052
  psbtBase64: psbt.toBase64(),
1005
- hex: _optionalChain([psbt, 'access', _12 => _12.data, 'optionalAccess', _13 => _13.globalMap, 'optionalAccess', _14 => _14.unsignedTx, 'optionalAccess', _15 => _15.toBuffer, 'call', _16 => _16(), 'optionalAccess', _17 => _17.toString, 'call', _18 => _18('hex')])
1053
+ hex: _optionalChain([psbt, 'access', _20 => _20.data, 'optionalAccess', _21 => _21.globalMap, 'optionalAccess', _22 => _22.unsignedTx, 'optionalAccess', _23 => _23.toBuffer, 'call', _24 => _24(), 'optionalAccess', _25 => _25.toString, 'call', _26 => _26('hex')])
1006
1054
  }
1007
1055
  } exports.makeTx = makeTx;
1008
1056
 
@@ -1126,6 +1174,8 @@ const bip43PurposeTypeEnumToNumber = (
1126
1174
  return 49
1127
1175
  case BIP43PurposeTypeEnum.Segwit:
1128
1176
  return 84
1177
+ case BIP43PurposeTypeEnum.ReplayProtection:
1178
+ return 44 // Only bip44 formatted wallets contain this purpose type (BCH)
1129
1179
  }
1130
1180
  }
1131
1181
 
@@ -1256,10 +1306,16 @@ const scriptHashToScriptPubkey = (
1256
1306
  default:
1257
1307
  throw new Error('invalid address type in address to script pubkey')
1258
1308
  }
1259
- const scriptPubkey = payment({
1260
- hash: Buffer.from(args.scriptHash, 'hex'),
1261
- network: network
1262
- }).output
1309
+ let scriptPubkey
1310
+ try {
1311
+ scriptPubkey = payment({
1312
+ hash: Buffer.from(args.scriptHash, 'hex'),
1313
+ network: network
1314
+ }).output
1315
+ } catch (error) {
1316
+ console.trace(error)
1317
+ throw error
1318
+ }
1263
1319
  if (scriptPubkey == null) {
1264
1320
  throw new Error('failed converting scriptPubkey to address')
1265
1321
  }
@@ -5,6 +5,7 @@ import { ChangePath, CurrencyFormat, EngineConfig, PluginInfo } from '../../plug
5
5
  import { Processor } from '../db/makeProcessor';
6
6
  import { IAddress, IProcessorTransaction, IUTXO } from '../db/types';
7
7
  import { NumbWalletInfo } from '../keymanager/cleaners';
8
+ import { BlockbookAccountUtxo } from '../network/BlockBookAPI';
8
9
  import { WsTask } from '../network/Socket';
9
10
  import AwaitLock from './await-lock';
10
11
  import { ServerStates } from './makeServerStates';
@@ -89,6 +90,7 @@ interface ProcessorUtxoCache {
89
90
  }
90
91
  interface RawUtxoCache {
91
92
  [key: string]: {
93
+ blockbookUtxo: BlockbookAccountUtxo;
92
94
  processing: boolean;
93
95
  path: ChangePath;
94
96
  address: IAddress;
@@ -1,11 +1,11 @@
1
- import { AddressPath, CurrencyFormat } from '../../plugin/types';
1
+ import { AddressPath, ChangePath, CurrencyFormat, PluginInfo } from '../../plugin/types';
2
2
  import { ScriptTemplate } from '../info/scriptTemplates/types';
3
3
  import { PublicKey } from '../keymanager/cleaners';
4
4
  import { PrivateKeyEncoding } from '../keymanager/keymanager';
5
5
  import { CurrencyFormatKeys } from './utils';
6
6
  export interface WalletToolsConfig {
7
+ pluginInfo: PluginInfo;
7
8
  publicKey: PublicKey;
8
- coin: string;
9
9
  }
10
10
  export interface UTXOPluginWalletTools {
11
11
  getPubkey: (args: AddressPath) => string;
@@ -24,8 +24,8 @@ interface ScriptPubkeyReturn {
24
24
  redeemScript?: string;
25
25
  }
26
26
  interface ScriptPubkeyToAddressArgs {
27
+ changePath: ChangePath;
27
28
  scriptPubkey: string;
28
- format: CurrencyFormat;
29
29
  }
30
30
  interface GetPrivateKeyArgs {
31
31
  path: AddressPath;
@@ -1,6 +1,6 @@
1
1
  import { Disklet } from 'disklet';
2
2
  import { EdgeMemoRules, EdgeParsedUri } from 'edge-core-js/types';
3
- import { CurrencyFormat } from '../../plugin/types';
3
+ import { ChangePath, CurrencyFormat, EngineInfo } from '../../plugin/types';
4
4
  import { IUTXO } from '../db/types';
5
5
  import { ScriptTemplates } from '../info/scriptTemplates/types';
6
6
  import { PrivateKey } from '../keymanager/cleaners';
@@ -9,12 +9,32 @@ export declare const getCurrencyFormatFromPurposeType: (purpose: BIP43PurposeTyp
9
9
  export declare const validateMemo: (memo: string) => EdgeMemoRules;
10
10
  export declare const getAddressTypeFromKeys: (privateKey: PrivateKey) => AddressTypeEnum;
11
11
  export declare const getAddressTypeFromPurposeType: (purpose: BIP43PurposeTypeEnum) => AddressTypeEnum;
12
- export declare const getScriptTypeFromPurposeType: (purpose: BIP43PurposeTypeEnum, redeemScript?: string | undefined, scriptTemplates?: ScriptTemplates | undefined) => ScriptTypeEnum;
12
+ export declare const getScriptTypeFromPurposeType: (purpose: BIP43PurposeTypeEnum) => ScriptTypeEnum;
13
13
  export declare const validScriptPubkeyFromAddress: (args: {
14
14
  address: string;
15
15
  coin: string;
16
16
  }) => string;
17
- export declare const getFormatSupportedBranches: (format: CurrencyFormat) => number[];
17
+ export declare const getFormatSupportedBranches: (engineInfo: EngineInfo, format: CurrencyFormat) => number[];
18
+ /**
19
+ * The reason for this function is to consider the address path for
20
+ * determining the purpose-type for the address. This is because some parts
21
+ * of the address such as the changeIndex have special meaning for the
22
+ * purpose-type. Specifically for scriptTemplates, the hash of the template
23
+ * is used to deterministically identify the changeIndex used constantly for
24
+ * the addresses spending to those scriptTemplates.
25
+ *
26
+ * In the future, we will want to strictly use only the format of the path
27
+ * in order to determine the purpose-type per the BIP43 spec. This will require
28
+ * a significant lift to reconsider the type for the path's format (currently
29
+ * CurrencyFormat). The scriptTemplates could define a format index and this
30
+ * could be used in address paths instead of a CurrencyType.
31
+ */
32
+ export declare const pathToPurposeType: (path: ChangePath, scriptTemplates?: ScriptTemplates | undefined) => BIP43PurposeTypeEnum;
33
+ /**
34
+ * Only use this function when needing to infer the purpose-type for a wallet
35
+ * format (CurrencyFormat). To get the purpose-type for an address use
36
+ * pathToPurposeType passing the address path.
37
+ */
18
38
  export declare const currencyFormatToPurposeType: (format: CurrencyFormat) => BIP43PurposeTypeEnum;
19
39
  export declare type CurrencyFormatKeys = {
20
40
  [format in CurrencyFormat]?: string;
@@ -1,13 +1,14 @@
1
1
  import { EdgeLog } from 'edge-core-js/types';
2
- import { AddressPath } from '../../plugin/types';
2
+ import { ChangePath } from '../../plugin/types';
3
3
  import { IUTXO } from '../db/types';
4
- import { ScriptTemplate } from '../info/scriptTemplates/types';
4
+ import { ScriptTemplate, ScriptTemplates } from '../info/scriptTemplates/types';
5
5
  import * as utxopicker from './utxopicker';
6
6
  export declare enum BIP43PurposeTypeEnum {
7
7
  Airbitz = "airbitz",
8
8
  Legacy = "legacy",
9
9
  Segwit = "segwit",
10
- WrappedSegwit = "wrappedSegwit"
10
+ WrappedSegwit = "wrappedSegwit",
11
+ ReplayProtection = "replayProtection"
11
12
  }
12
13
  export declare enum AddressTypeEnum {
13
14
  p2pkh = "p2pkh",
@@ -71,6 +72,7 @@ export interface AddressToScriptPubkeyArgs {
71
72
  }
72
73
  export interface PubkeyToScriptPubkeyArgs {
73
74
  pubkey: string;
75
+ scriptTemplates?: ScriptTemplates;
74
76
  scriptType: ScriptTypeEnum;
75
77
  }
76
78
  export interface PubkeyToScriptPubkeyReturn {
@@ -189,7 +191,7 @@ export declare const getAddressTypeFromAddress: (address: string, coinName: stri
189
191
  export declare function seedOrMnemonicToXPriv(args: SeedOrMnemonicToXPrivArgs): string;
190
192
  export declare const xprivToXPub: (args: XPrivToXPubArgs) => string;
191
193
  export declare function derivationLevelScriptHash(scriptTemplate: ScriptTemplate): number;
192
- export declare const isPathUsingDerivationLevelScriptHash: (scriptTemplate: ScriptTemplate, path: AddressPath) => boolean;
194
+ export declare const isPathUsingDerivationLevelScriptHash: (scriptTemplate: ScriptTemplate, path: ChangePath) => boolean;
193
195
  export declare const xpubToPubkey: (args: XPubToPubkeyArgs) => string;
194
196
  export declare const addressToScriptPubkey: (args: AddressToScriptPubkeyArgs) => string;
195
197
  export declare function scriptPubkeyToAddress(args: ScriptPubkeyToAddressArgs): ScriptPubkeyToAddressReturn;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edge-currency-plugins",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Edge currency plugins to fetch and process wallet accounts, balances and transactions.",
5
5
  "repository": "https://github.com/EdgeApp/edge-currency-plugins",
6
6
  "license": "MIT",