edge-currency-plugins 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/fees/makeFees.js +2 -2
- package/lib/common/plugin/types.js +29 -16
- package/lib/common/utxobased/db/Models/ProcessorTransaction.js +6 -9
- package/lib/common/utxobased/db/types.js +15 -1
- package/lib/common/utxobased/db/util/utxo.js +70 -0
- package/lib/common/utxobased/engine/makeUtxoEngine.js +292 -68
- package/lib/common/utxobased/engine/makeUtxoEngineState.js +15 -13
- package/lib/common/utxobased/engine/types.js +22 -1
- package/lib/common/utxobased/keymanager/keymanager.js +43 -14
- package/lib/common/utxobased/keymanager/types.js +33 -0
- package/lib/common/utxobased/keymanager/utxopicker/accumulative.js +2 -1
- package/lib/common/utxobased/keymanager/utxopicker/forceUseUtxo.js +2 -1
- package/lib/common/utxobased/keymanager/utxopicker/types.js +1 -0
- package/lib/common/utxobased/keymanager/utxopicker/utils.js +8 -1
- package/lib/common/utxobased/network/BlockBookAPI.js +1 -1
- package/lib/src/common/plugin/types.d.ts +2 -2
- package/lib/src/common/utxobased/db/types.d.ts +1 -0
- package/lib/src/common/utxobased/db/util/utxo.d.ts +3 -0
- package/lib/src/common/utxobased/engine/types.d.ts +9 -0
- package/lib/src/common/utxobased/keymanager/keymanager.d.ts +4 -2
- package/lib/src/common/utxobased/keymanager/types.d.ts +13 -0
- package/lib/src/common/utxobased/keymanager/utxopicker/types.d.ts +1 -1
- package/lib/src/common/utxobased/keymanager/utxopicker/utils.d.ts +1 -0
- package/package.json +1 -1
|
@@ -65,7 +65,7 @@ var _processMempoolSpaceFees = require('./processMempoolSpaceFees');
|
|
|
65
65
|
const edgeFees = await fetchFees({
|
|
66
66
|
...common,
|
|
67
67
|
uri: `${_constants.INFO_SERVER_URI}/v1/networkFees/${currencyInfo.pluginId}`,
|
|
68
|
-
cleaner: _cleaners.asMaybe.call(void 0, _types3.asFeeInfo, null)
|
|
68
|
+
cleaner: _cleaners.asMaybe.call(void 0, _types3.asFeeInfo.call(void 0, feeInfo), null)
|
|
69
69
|
})
|
|
70
70
|
Object.assign(feeInfo, edgeFees)
|
|
71
71
|
await updateVendorFees()
|
|
@@ -122,7 +122,7 @@ const fetchCachedFees = async (
|
|
|
122
122
|
fallback
|
|
123
123
|
) => {
|
|
124
124
|
const data = await memlet.getJson(_constants.FEES_PATH).catch(() => undefined)
|
|
125
|
-
const feeSettings = _cleaners.asMaybe.call(void 0, _types3.asFeeInfo, fallback)(data)
|
|
125
|
+
const feeSettings = _cleaners.asMaybe.call(void 0, _types3.asFeeInfo.call(void 0, fallback), fallback)(data)
|
|
126
126
|
return feeSettings
|
|
127
127
|
}
|
|
128
128
|
|
|
@@ -1,4 +1,5 @@
|
|
|
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; } }
|
|
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; }
|
|
2
|
+
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
|
|
@@ -8,8 +9,8 @@
|
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
var _cleaners = require('cleaners');
|
|
12
12
|
|
|
13
|
+
var _cleaners = require('cleaners');
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
|
|
@@ -21,6 +22,7 @@ var _cleaners = require('cleaners');
|
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
var _types3 = require('../utxobased/db/types');
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
|
|
@@ -46,7 +48,11 @@ var _cleaners = require('cleaners');
|
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
const asTxOptions = _cleaners.asObject({
|
|
52
|
+
utxos: _cleaners.asOptional.call(void 0, _cleaners.asArray.call(void 0, _types3.asIUTXO)),
|
|
53
|
+
subtractFee: _cleaners.asOptional.call(void 0, _cleaners.asBoolean),
|
|
54
|
+
CPFP: _cleaners.asOptional.call(void 0, _cleaners.asString)
|
|
55
|
+
}); exports.asTxOptions = asTxOptions
|
|
50
56
|
|
|
51
57
|
|
|
52
58
|
|
|
@@ -161,21 +167,28 @@ var _cleaners = require('cleaners');
|
|
|
161
167
|
|
|
162
168
|
|
|
163
169
|
|
|
164
|
-
const asFeeInfo =
|
|
165
|
-
|
|
170
|
+
const asFeeInfo = (fallback) =>
|
|
171
|
+
_cleaners.asObject({
|
|
172
|
+
...exports.asFeeRates.shape,
|
|
166
173
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
174
|
+
lowFeeFudgeFactor: _cleaners.asMaybe.call(void 0, _cleaners.asString, _optionalChain([fallback, 'optionalAccess', _ => _.lowFeeFudgeFactor])),
|
|
175
|
+
standardFeeLowFudgeFactor: _cleaners.asMaybe.call(void 0,
|
|
176
|
+
_cleaners.asString,
|
|
177
|
+
_optionalChain([fallback, 'optionalAccess', _2 => _2.standardFeeLowFudgeFactor])
|
|
178
|
+
),
|
|
179
|
+
standardFeeHighFudgeFactor: _cleaners.asMaybe.call(void 0,
|
|
180
|
+
_cleaners.asString,
|
|
181
|
+
_optionalChain([fallback, 'optionalAccess', _3 => _3.standardFeeHighFudgeFactor])
|
|
182
|
+
),
|
|
183
|
+
highFeeFudgeFactor: _cleaners.asMaybe.call(void 0, _cleaners.asString, _optionalChain([fallback, 'optionalAccess', _4 => _4.highFeeFudgeFactor])),
|
|
171
184
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}); exports.asFeeInfo = asFeeInfo
|
|
185
|
+
// The amount of satoshis which will be charged the standardFeeLow
|
|
186
|
+
standardFeeLowAmount: _cleaners.asString,
|
|
187
|
+
// The amount of satoshis which will be charged the standardFeeHigh
|
|
188
|
+
standardFeeHighAmount: _cleaners.asString,
|
|
189
|
+
// A safe-guard for any potential software bugs:
|
|
190
|
+
maximumFeeRate: _cleaners.asOptional.call(void 0, _cleaners.asString, _optionalChain([fallback, 'optionalAccess', _5 => _5.maximumFeeRate]))
|
|
191
|
+
}).withRest; exports.asFeeInfo = asFeeInfo
|
|
179
192
|
|
|
180
193
|
|
|
181
194
|
|
|
@@ -78,8 +78,7 @@ var _bnjs = require('bn.js'); var _bnjs2 = _interopRequireDefault(_bnjs);
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
let feeRateUsed
|
|
83
82
|
try {
|
|
84
83
|
const altcoinTx = _altcoinjs.Transaction.fromHex(tx.hex)
|
|
85
84
|
const vBytes = altcoinTx.virtualSize()
|
|
@@ -87,12 +86,10 @@ var _bnjs = require('bn.js'); var _bnjs2 = _interopRequireDefault(_bnjs);
|
|
|
87
86
|
const feeRate = new (0, _bnjs2.default)(tx.fees, 10)
|
|
88
87
|
.div(new (0, _bnjs2.default)(vBytes, 10))
|
|
89
88
|
.toNumber()
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
})
|
|
89
|
+
feeRateUsed = {
|
|
90
|
+
// GUI repo uses satPerVByte rather than satPerByte defined in customFeeTemplate
|
|
91
|
+
satPerVByte: feeRate
|
|
92
|
+
}
|
|
96
93
|
} catch (e) {}
|
|
97
94
|
|
|
98
95
|
return {
|
|
@@ -108,6 +105,6 @@ var _bnjs = require('bn.js'); var _bnjs2 = _interopRequireDefault(_bnjs);
|
|
|
108
105
|
signedTx: tx.hex,
|
|
109
106
|
txid: tx.txid,
|
|
110
107
|
walletId,
|
|
111
|
-
|
|
108
|
+
feeRateUsed
|
|
112
109
|
}
|
|
113
110
|
}; exports.toEdgeTransaction = toEdgeTransaction
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _cleaners = require('cleaners');
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
var _keymanager = require('../keymanager/keymanager');
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
|
|
@@ -40,6 +42,18 @@
|
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
|
|
45
|
+
const asIUTXO = _cleaners.asObject({
|
|
46
|
+
id: _cleaners.asString,
|
|
47
|
+
txid: _cleaners.asString,
|
|
48
|
+
vout: _cleaners.asNumber,
|
|
49
|
+
value: _cleaners.asString,
|
|
50
|
+
scriptPubkey: _cleaners.asString,
|
|
51
|
+
script: _cleaners.asString,
|
|
52
|
+
redeemScript: _cleaners.asOptional.call(void 0, _cleaners.asString),
|
|
53
|
+
scriptType: _keymanager.asScriptTypeEnum,
|
|
54
|
+
blockHeight: _cleaners.asNumber,
|
|
55
|
+
spent: _cleaners.asBoolean
|
|
56
|
+
}); exports.asIUTXO = asIUTXO
|
|
43
57
|
|
|
44
58
|
|
|
45
59
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _utils = require('../../engine/utils');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _keymanager = require('../../keymanager/keymanager');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const utxoFromProcessorTransactionInput = async (
|
|
10
|
+
processor,
|
|
11
|
+
processorTransaction,
|
|
12
|
+
inputIndex
|
|
13
|
+
) => {
|
|
14
|
+
const input = processorTransaction.inputs[inputIndex]
|
|
15
|
+
const { scriptPubkey } = input
|
|
16
|
+
const address = await processor.fetchAddress(scriptPubkey)
|
|
17
|
+
|
|
18
|
+
if (address == null)
|
|
19
|
+
throw new Error(`Cannot find address for ${scriptPubkey}`)
|
|
20
|
+
if (address.path == null)
|
|
21
|
+
throw new Error(`Address has no derivation path information`)
|
|
22
|
+
|
|
23
|
+
// Optional redeemScript for "our addresses"
|
|
24
|
+
const redeemScript = address.redeemScript
|
|
25
|
+
|
|
26
|
+
const purposeType = _utils.currencyFormatToPurposeType.call(void 0, address.path.format)
|
|
27
|
+
const getScripts = async (
|
|
28
|
+
scriptPubkey
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
) => {
|
|
33
|
+
switch (purposeType) {
|
|
34
|
+
case _keymanager.BIP43PurposeTypeEnum.Airbitz:
|
|
35
|
+
case _keymanager.BIP43PurposeTypeEnum.Legacy: {
|
|
36
|
+
return {
|
|
37
|
+
script: processorTransaction.hex,
|
|
38
|
+
scriptType:
|
|
39
|
+
redeemScript != null ? _keymanager.ScriptTypeEnum.p2sh : _keymanager.ScriptTypeEnum.p2pkh
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
case _keymanager.BIP43PurposeTypeEnum.WrappedSegwit:
|
|
43
|
+
return {
|
|
44
|
+
script: scriptPubkey,
|
|
45
|
+
scriptType: _keymanager.ScriptTypeEnum.p2wpkhp2sh
|
|
46
|
+
}
|
|
47
|
+
case _keymanager.BIP43PurposeTypeEnum.Segwit:
|
|
48
|
+
return {
|
|
49
|
+
script: scriptPubkey,
|
|
50
|
+
scriptType: _keymanager.ScriptTypeEnum.p2wpkh
|
|
51
|
+
}
|
|
52
|
+
default:
|
|
53
|
+
throw new Error(`Unknown purpose type ${purposeType}`)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const { script, scriptType } = await getScripts(scriptPubkey)
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
id: `${input.txId}_${input.outputIndex}`,
|
|
60
|
+
txid: input.txId,
|
|
61
|
+
vout: input.outputIndex,
|
|
62
|
+
value: input.amount,
|
|
63
|
+
scriptPubkey,
|
|
64
|
+
script,
|
|
65
|
+
redeemScript,
|
|
66
|
+
scriptType,
|
|
67
|
+
blockHeight: processorTransaction.blockHeight,
|
|
68
|
+
spent: true
|
|
69
|
+
}
|
|
70
|
+
}; exports.utxoFromProcessorTransactionInput = utxoFromProcessorTransactionInput
|
|
@@ -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 _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } 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; }
|
|
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 _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } 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);
|
|
2
2
|
var _cleaners = require('cleaners');
|
|
3
3
|
var _disklet = require('disklet');
|
|
4
4
|
|
|
@@ -31,6 +31,7 @@ var _makeProcessor = require('../db/makeProcessor');
|
|
|
31
31
|
|
|
32
32
|
var _ProcessorTransaction = require('../db/Models/ProcessorTransaction');
|
|
33
33
|
|
|
34
|
+
var _utxo = require('../db/util/utxo');
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
|
|
@@ -41,7 +42,11 @@ var _cleaners3 = require('../keymanager/cleaners');
|
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
|
|
45
|
+
|
|
46
|
+
|
|
44
47
|
var _keymanager = require('../keymanager/keymanager');
|
|
48
|
+
var _types5 = require('../keymanager/types');
|
|
49
|
+
var _utils = require('../keymanager/utxopicker/utils');
|
|
45
50
|
var _makeUtxoEngineState = require('./makeUtxoEngineState');
|
|
46
51
|
var _makeUtxoWalletTools = require('./makeUtxoWalletTools');
|
|
47
52
|
var _paymentRequest = require('./paymentRequest');
|
|
@@ -49,9 +54,15 @@ var _paymentRequest = require('./paymentRequest');
|
|
|
49
54
|
|
|
50
55
|
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
|
|
58
|
+
var _types7 = require('./types');
|
|
53
59
|
var _getOwnUtxosFromTx = require('./util/getOwnUtxosFromTx');
|
|
54
|
-
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
var _utils3 = require('./utils');
|
|
55
66
|
|
|
56
67
|
async function makeUtxoEngine(
|
|
57
68
|
config
|
|
@@ -71,7 +82,7 @@ var _utils = require('./utils');
|
|
|
71
82
|
log
|
|
72
83
|
} = options
|
|
73
84
|
const { currencyInfo, engineInfo, coinInfo } = pluginInfo
|
|
74
|
-
const userSettings =
|
|
85
|
+
const userSettings = _types7.asUtxoUserSettings.call(void 0, options.userSettings)
|
|
75
86
|
|
|
76
87
|
// We should move the active server list to the engine state,
|
|
77
88
|
// since multiple accounts can be logged in at once,
|
|
@@ -129,6 +140,208 @@ var _utils = require('./utils');
|
|
|
129
140
|
})
|
|
130
141
|
|
|
131
142
|
const engine = {
|
|
143
|
+
async accelerate(edgeTx) {
|
|
144
|
+
// Get the replaced transaction from the processor:
|
|
145
|
+
const replacedTxid = edgeTx.txid
|
|
146
|
+
const [replacedTx] = await processor.fetchTransactions({
|
|
147
|
+
txId: replacedTxid
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// Transaction checks:
|
|
151
|
+
// The transaction must be found and not confirmed or dropped.
|
|
152
|
+
if (replacedTx == null) return null
|
|
153
|
+
if (replacedTx.blockHeight !== 0) return null
|
|
154
|
+
|
|
155
|
+
// Double the fee used for the RBF transaction:
|
|
156
|
+
const vBytes = _utils.transactionSizeFromHex.call(void 0, replacedTx.hex)
|
|
157
|
+
const newFeeRate = Math.round((parseInt(replacedTx.fees) / vBytes) * 2)
|
|
158
|
+
|
|
159
|
+
const replacedTxInputs = replacedTx.inputs
|
|
160
|
+
// Recreate UTXOs from processor transaction and mark them as unspent:
|
|
161
|
+
const replacedTxUtxos = await Promise.all(
|
|
162
|
+
replacedTxInputs.map(async (_, index) => {
|
|
163
|
+
const utxo = await _utxo.utxoFromProcessorTransactionInput.call(void 0,
|
|
164
|
+
processor,
|
|
165
|
+
replacedTx,
|
|
166
|
+
index
|
|
167
|
+
)
|
|
168
|
+
// Mark as unspent because we're going to reuse replaced tx's UTXOs
|
|
169
|
+
utxo.spent = false
|
|
170
|
+
return utxo
|
|
171
|
+
})
|
|
172
|
+
)
|
|
173
|
+
// Get the largest input from the transaction to re-use:
|
|
174
|
+
const replacedTxMaxUtxo = replacedTxUtxos.reduce((maxUtxo, utxo) => {
|
|
175
|
+
if (utxo.value > maxUtxo.value) return utxo
|
|
176
|
+
return maxUtxo
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const targets = []
|
|
180
|
+
const newOurReceiveAddresses = []
|
|
181
|
+
let foundChangeAddress
|
|
182
|
+
for (const output of replacedTx.outputs) {
|
|
183
|
+
// Fetch address by output's scriptPubkey to determine output ownership
|
|
184
|
+
const ourAddress = await processor.fetchAddress(output.scriptPubkey)
|
|
185
|
+
|
|
186
|
+
// This isn't our output, so include it as a target
|
|
187
|
+
if (ourAddress == null) {
|
|
188
|
+
targets.push({
|
|
189
|
+
scriptPubkey: output.scriptPubkey,
|
|
190
|
+
value: parseInt(output.amount)
|
|
191
|
+
})
|
|
192
|
+
continue
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Addresses from database should include a path; this is a type assert
|
|
196
|
+
if (ourAddress.path == null)
|
|
197
|
+
throw new Error('Expecting path for address')
|
|
198
|
+
|
|
199
|
+
// The output is ours:
|
|
200
|
+
const purposeType = _utils3.pathToPurposeType.call(void 0,
|
|
201
|
+
ourAddress.path,
|
|
202
|
+
engineInfo.scriptTemplates
|
|
203
|
+
)
|
|
204
|
+
const addressType = _utils3.getAddressTypeFromPurposeType.call(void 0, purposeType)
|
|
205
|
+
const { address } = _keymanager.scriptPubkeyToAddress.call(void 0, {
|
|
206
|
+
scriptPubkey: ourAddress.scriptPubkey,
|
|
207
|
+
addressType,
|
|
208
|
+
coin: coinInfo.name,
|
|
209
|
+
redeemScript: ourAddress.redeemScript
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
newOurReceiveAddresses.push(address)
|
|
213
|
+
|
|
214
|
+
// Detect if it's the change address:
|
|
215
|
+
if (ourAddress.path.changeIndex === 1) {
|
|
216
|
+
foundChangeAddress = address
|
|
217
|
+
} else {
|
|
218
|
+
// This isn't our change address, so include it as a target.
|
|
219
|
+
// The transaction must have been a spend-to-self.
|
|
220
|
+
targets.push({
|
|
221
|
+
scriptPubkey: output.scriptPubkey,
|
|
222
|
+
value: parseInt(output.amount)
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Use the found change address or generate a new one:
|
|
228
|
+
const freshAddress =
|
|
229
|
+
foundChangeAddress == null
|
|
230
|
+
? await engineState.getFreshAddress({ branch: 1 })
|
|
231
|
+
: { publicAddress: foundChangeAddress }
|
|
232
|
+
const freshChangeAddress =
|
|
233
|
+
_nullishCoalesce(freshAddress.segwitAddress, () => ( freshAddress.publicAddress))
|
|
234
|
+
|
|
235
|
+
// Get all current UTXOs:
|
|
236
|
+
const currentUtxos = _filterUndefined.filterUndefined.call(void 0,
|
|
237
|
+
await processor.fetchUtxos({
|
|
238
|
+
utxoIds: []
|
|
239
|
+
})
|
|
240
|
+
)
|
|
241
|
+
// Exclude all UTXOs which are from the replaced tx, because
|
|
242
|
+
// they wont be valid.
|
|
243
|
+
.filter(utxo => utxo.txid !== replacedTxid)
|
|
244
|
+
|
|
245
|
+
// Combine replaced transaction's inputs as UTXOs with the current UTXO set
|
|
246
|
+
const utxos = [...replacedTxUtxos, ...currentUtxos]
|
|
247
|
+
|
|
248
|
+
// New transaction to be the replacement transaction
|
|
249
|
+
const makeTxArgs = {
|
|
250
|
+
utxos,
|
|
251
|
+
forceUseUtxo: [replacedTxMaxUtxo],
|
|
252
|
+
targets,
|
|
253
|
+
memos: edgeTx.memos,
|
|
254
|
+
feeRate: newFeeRate,
|
|
255
|
+
coin: coinInfo.name,
|
|
256
|
+
currencyCode: currencyInfo.currencyCode,
|
|
257
|
+
enableRbf: true,
|
|
258
|
+
freshChangeAddress,
|
|
259
|
+
subtractFee: false,
|
|
260
|
+
log,
|
|
261
|
+
outputSort: 'bip69'
|
|
262
|
+
}
|
|
263
|
+
const newTx = (() => {
|
|
264
|
+
try {
|
|
265
|
+
return _keymanager.makeTx.call(void 0, makeTxArgs)
|
|
266
|
+
} catch (error) {
|
|
267
|
+
const cleanError = _types5.asMaybeInsufficientFundsErrorPlus.call(void 0, error)
|
|
268
|
+
if (_optionalChain([cleanError, 'optionalAccess', _2 => _2.networkFeeShortage]) != null) {
|
|
269
|
+
let feeDelta = parseInt(cleanError.networkFeeShortage)
|
|
270
|
+
// Adjust target values until we diminish the fee delta completely
|
|
271
|
+
for (const target of targets) {
|
|
272
|
+
if (target.value == null) continue
|
|
273
|
+
// The term is how much value to subtract from the target's value.
|
|
274
|
+
// The term's maximum value is the target's value.
|
|
275
|
+
// The term's minimum value is the fee delta.
|
|
276
|
+
const term = Math.min(target.value, feeDelta)
|
|
277
|
+
target.value -= term // Either decrement or zero out
|
|
278
|
+
feeDelta -= term // Ether decrement or zero out
|
|
279
|
+
}
|
|
280
|
+
// Retry making the transaction
|
|
281
|
+
return _keymanager.makeTx.call(void 0, makeTxArgs)
|
|
282
|
+
}
|
|
283
|
+
throw error
|
|
284
|
+
}
|
|
285
|
+
})()
|
|
286
|
+
|
|
287
|
+
if (newTx.changeUsed) {
|
|
288
|
+
newOurReceiveAddresses.push(freshChangeAddress)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Generate new tracking of our scripts:
|
|
292
|
+
const newOurScriptPubkeys = newTx.inputs.map(input =>
|
|
293
|
+
input.scriptPubkey.toString('hex')
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
// Calculate transaction spend amount:
|
|
297
|
+
let nativeAmount = '0'
|
|
298
|
+
for (const output of newTx.outputs) {
|
|
299
|
+
const scriptPubkey = output.scriptPubkey.toString('hex')
|
|
300
|
+
const own = await processor.fetchAddress(scriptPubkey)
|
|
301
|
+
if (own == null) {
|
|
302
|
+
// Not our output
|
|
303
|
+
nativeAmount = bs.sub(nativeAmount, output.value.toString())
|
|
304
|
+
} else {
|
|
305
|
+
// Our output
|
|
306
|
+
newOurScriptPubkeys.push(scriptPubkey)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const networkFee = newTx.fee.toString()
|
|
311
|
+
nativeAmount = bs.sub(nativeAmount, networkFee)
|
|
312
|
+
|
|
313
|
+
const newTxOtherParams = {
|
|
314
|
+
unsignedTx: newTx.hex,
|
|
315
|
+
psbt: {
|
|
316
|
+
base64: newTx.psbtBase64,
|
|
317
|
+
inputs: newTx.inputs,
|
|
318
|
+
outputs: newTx.outputs
|
|
319
|
+
},
|
|
320
|
+
ourScriptPubkeys: newOurScriptPubkeys,
|
|
321
|
+
replacedTxid: replacedTxid
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Return a EdgeTransaction object with the updates
|
|
325
|
+
return {
|
|
326
|
+
...edgeTx,
|
|
327
|
+
blockHeight: 0,
|
|
328
|
+
currencyCode: currencyInfo.currencyCode,
|
|
329
|
+
date: _unixTime.unixTime.call(void 0, ),
|
|
330
|
+
feeRateUsed: {
|
|
331
|
+
satPerVByte: newFeeRate
|
|
332
|
+
},
|
|
333
|
+
isSend: true,
|
|
334
|
+
nativeAmount,
|
|
335
|
+
networkFee,
|
|
336
|
+
otherParams: newTxOtherParams,
|
|
337
|
+
ourReceiveAddresses: newOurReceiveAddresses,
|
|
338
|
+
parentNetworkFee: undefined,
|
|
339
|
+
signedTx: '',
|
|
340
|
+
txid: '',
|
|
341
|
+
walletId: walletInfo.id
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
|
|
132
345
|
async startEngine() {
|
|
133
346
|
emitter.emit(
|
|
134
347
|
_makeEngineEmitter.EngineEvent.WALLET_BALANCE_CHANGED,
|
|
@@ -166,8 +379,8 @@ var _utils = require('./utils');
|
|
|
166
379
|
async broadcastTx(transaction) {
|
|
167
380
|
const { otherParams } = transaction
|
|
168
381
|
if (
|
|
169
|
-
_optionalChain([otherParams, 'optionalAccess',
|
|
170
|
-
_optionalChain([otherParams, 'optionalAccess',
|
|
382
|
+
_optionalChain([otherParams, 'optionalAccess', _3 => _3.paymentProtocolInfo, 'optionalAccess', _4 => _4.payment]) != null &&
|
|
383
|
+
_optionalChain([otherParams, 'optionalAccess', _5 => _5.paymentProtocolInfo, 'optionalAccess', _6 => _6.paymentUrl]) != null
|
|
171
384
|
) {
|
|
172
385
|
const paymentAck = await _paymentRequest.sendPayment.call(void 0,
|
|
173
386
|
io.fetch,
|
|
@@ -193,7 +406,7 @@ var _utils = require('./utils');
|
|
|
193
406
|
},
|
|
194
407
|
|
|
195
408
|
async changeUserSettings(userSettings) {
|
|
196
|
-
await pluginState.updateServers(
|
|
409
|
+
await pluginState.updateServers(_types7.asUtxoUserSettings.call(void 0, userSettings))
|
|
197
410
|
},
|
|
198
411
|
|
|
199
412
|
async disableTokens(_tokens) {
|
|
@@ -236,10 +449,6 @@ var _utils = require('./utils');
|
|
|
236
449
|
.join('\n')
|
|
237
450
|
},
|
|
238
451
|
|
|
239
|
-
async getEnabledTokens() {
|
|
240
|
-
return await Promise.resolve([])
|
|
241
|
-
},
|
|
242
|
-
|
|
243
452
|
async getFreshAddress(
|
|
244
453
|
opts
|
|
245
454
|
) {
|
|
@@ -261,10 +470,6 @@ var _utils = require('./utils');
|
|
|
261
470
|
)
|
|
262
471
|
},
|
|
263
472
|
|
|
264
|
-
getTokenStatus(_token) {
|
|
265
|
-
return false
|
|
266
|
-
},
|
|
267
|
-
|
|
268
473
|
async getTransactions(
|
|
269
474
|
options
|
|
270
475
|
) {
|
|
@@ -295,17 +500,22 @@ var _utils = require('./utils');
|
|
|
295
500
|
async makeSpend(edgeSpendInfo) {
|
|
296
501
|
edgeSpendInfo = _upgradeMemos.upgradeMemos.call(void 0, edgeSpendInfo, currencyInfo)
|
|
297
502
|
const { memos = [], spendTargets } = edgeSpendInfo
|
|
298
|
-
const
|
|
299
|
-
_optionalChain([edgeSpendInfo, 'access', _5 => _5.otherParams, 'optionalAccess', _6 => _6.txOptions])
|
|
300
|
-
const { outputSort = 'bip69', utxoSourceAddress, forceChangeAddress } =
|
|
503
|
+
const spendInfoOtherParams = _types7.asUtxoSpendInfoOtherParams.call(void 0,
|
|
301
504
|
_nullishCoalesce(edgeSpendInfo.otherParams, () => ( {}))
|
|
505
|
+
)
|
|
506
|
+
const txOptions = _nullishCoalesce(spendInfoOtherParams.txOptions, () => ( {}))
|
|
507
|
+
const {
|
|
508
|
+
outputSort,
|
|
509
|
+
utxoSourceAddress,
|
|
510
|
+
forceChangeAddress
|
|
511
|
+
} = spendInfoOtherParams
|
|
302
512
|
|
|
303
513
|
let utxoScriptPubkey
|
|
304
514
|
if (utxoSourceAddress != null) {
|
|
305
515
|
utxoScriptPubkey = walletTools.addressToScriptPubkey(utxoSourceAddress)
|
|
306
516
|
}
|
|
307
517
|
|
|
308
|
-
if (
|
|
518
|
+
if (txOptions.CPFP == null && spendTargets.length < 1) {
|
|
309
519
|
throw new Error('Need to provide Spend Targets')
|
|
310
520
|
}
|
|
311
521
|
// Calculate the total amount to send
|
|
@@ -314,7 +524,7 @@ var _utils = require('./utils');
|
|
|
314
524
|
'0'
|
|
315
525
|
)
|
|
316
526
|
const utxos =
|
|
317
|
-
await _asyncNullishCoalesce(
|
|
527
|
+
await _asyncNullishCoalesce(txOptions.utxos, async () => (
|
|
318
528
|
_filterUndefined.filterUndefined.call(void 0,
|
|
319
529
|
(await processor.fetchUtxos({
|
|
320
530
|
scriptPubkey: utxoScriptPubkey,
|
|
@@ -323,7 +533,7 @@ var _utils = require('./utils');
|
|
|
323
533
|
)))
|
|
324
534
|
|
|
325
535
|
if (
|
|
326
|
-
bs.gt(totalAmountToSend, `${
|
|
536
|
+
bs.gt(totalAmountToSend, `${_utils3.sumUtxos.call(void 0, utxos)}`) ||
|
|
327
537
|
utxos.length === 0
|
|
328
538
|
) {
|
|
329
539
|
throw new (0, _edgecorejs.InsufficientFundsError)(currencyInfo.currencyCode)
|
|
@@ -337,7 +547,7 @@ var _utils = require('./utils');
|
|
|
337
547
|
}
|
|
338
548
|
|
|
339
549
|
// if script exists construct address from script
|
|
340
|
-
if (_optionalChain([target, 'access',
|
|
550
|
+
if (_optionalChain([target, 'access', _7 => _7.otherParams, 'optionalAccess', _8 => _8.script]) != null) {
|
|
341
551
|
const { script } = target.otherParams
|
|
342
552
|
if (script.type === 'replayProtection') {
|
|
343
553
|
// construct a replay protection p2sh address
|
|
@@ -357,7 +567,7 @@ var _utils = require('./utils');
|
|
|
357
567
|
const scriptPubkey = walletTools.addressToScriptPubkey(
|
|
358
568
|
target.publicAddress
|
|
359
569
|
)
|
|
360
|
-
if (processor.fetchAddress(scriptPubkey) != null) {
|
|
570
|
+
if ((await processor.fetchAddress(scriptPubkey)) != null) {
|
|
361
571
|
ourReceiveAddresses.push(target.publicAddress)
|
|
362
572
|
}
|
|
363
573
|
}
|
|
@@ -381,31 +591,12 @@ var _utils = require('./utils');
|
|
|
381
591
|
freshAddress.segwitAddress)), () => (
|
|
382
592
|
freshAddress.publicAddress))
|
|
383
593
|
|
|
384
|
-
const
|
|
385
|
-
|
|
594
|
+
const feeRate = parseInt(await fees.getRate(edgeSpendInfo))
|
|
595
|
+
|
|
386
596
|
let maxUtxo
|
|
387
|
-
|
|
388
|
-
if (rbfTxid != null) {
|
|
389
|
-
const [rbfTx] = await processor.fetchTransactions({ txId: rbfTxid })
|
|
390
|
-
if (rbfTx == null) throw new Error('transaction not found')
|
|
391
|
-
// double the fee used for the RBF transaction
|
|
392
|
-
feeRate *= 2
|
|
393
|
-
const rbfInputs = rbfTx.inputs
|
|
394
|
-
const maxInput = rbfInputs.reduce((a, b) =>
|
|
395
|
-
bs.gt(a.amount, b.amount) ? a : b
|
|
396
|
-
)
|
|
397
|
-
const maxId = `${maxInput.txId}_${maxInput.outputIndex}`
|
|
398
|
-
maxUtxo = (await processor.fetchUtxos({ utxoIds: [maxId] }))[0]
|
|
399
|
-
if (maxUtxo == null) {
|
|
400
|
-
log.error('transaction to be replaced found, but not its input utxos')
|
|
401
|
-
throw new Error(
|
|
402
|
-
'transaction to be replaced found, but not its input utxos'
|
|
403
|
-
)
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
if (_optionalChain([txOptions, 'optionalAccess', _12 => _12.CPFP]) != null) {
|
|
597
|
+
if (txOptions.CPFP != null) {
|
|
407
598
|
const [childTx] = await processor.fetchTransactions({
|
|
408
|
-
txId:
|
|
599
|
+
txId: txOptions.CPFP
|
|
409
600
|
})
|
|
410
601
|
if (childTx == null) throw new Error('transaction not found')
|
|
411
602
|
const utxos = []
|
|
@@ -417,9 +608,10 @@ var _utils = require('./utils');
|
|
|
417
608
|
// cpfp just sends to change, no target addresses are required
|
|
418
609
|
targets = []
|
|
419
610
|
}
|
|
611
|
+
|
|
420
612
|
log.warn(`spend: Using fee rate ${feeRate} sat/B`)
|
|
421
613
|
const subtractFee =
|
|
422
|
-
|
|
614
|
+
txOptions.subtractFee != null ? txOptions.subtractFee : false
|
|
423
615
|
const tx = _keymanager.makeTx.call(void 0, {
|
|
424
616
|
utxos,
|
|
425
617
|
forceUseUtxo: maxUtxo != null ? [maxUtxo] : [],
|
|
@@ -428,7 +620,10 @@ var _utils = require('./utils');
|
|
|
428
620
|
feeRate,
|
|
429
621
|
coin: coinInfo.name,
|
|
430
622
|
currencyCode: currencyInfo.currencyCode,
|
|
431
|
-
|
|
623
|
+
enableRbf:
|
|
624
|
+
_nullishCoalesce(_nullishCoalesce(spendInfoOtherParams.enableRbf, () => (
|
|
625
|
+
currencyInfo.canReplaceByFee)), () => (
|
|
626
|
+
false)),
|
|
432
627
|
freshChangeAddress,
|
|
433
628
|
subtractFee,
|
|
434
629
|
log,
|
|
@@ -507,6 +702,26 @@ var _utils = require('./utils');
|
|
|
507
702
|
},
|
|
508
703
|
|
|
509
704
|
async saveTx(edgeTx) {
|
|
705
|
+
// If the transaction being saved replaces a transaction, update it.
|
|
706
|
+
const replacedTxid = _optionalChain([edgeTx, 'access', _9 => _9.otherParams, 'optionalAccess', _10 => _10.replacedTxid])
|
|
707
|
+
if (replacedTxid != null) {
|
|
708
|
+
// Get the replaced transaction using the replacedTxid
|
|
709
|
+
const [rbfTx] = await processor.fetchTransactions({
|
|
710
|
+
txId: replacedTxid
|
|
711
|
+
})
|
|
712
|
+
if (rbfTx != null) {
|
|
713
|
+
rbfTx.blockHeight = -1
|
|
714
|
+
await _makeUtxoEngineState.transactionChanged.call(void 0, {
|
|
715
|
+
walletId: walletInfo.id,
|
|
716
|
+
tx: rbfTx,
|
|
717
|
+
pluginInfo,
|
|
718
|
+
emitter,
|
|
719
|
+
walletTools,
|
|
720
|
+
processor
|
|
721
|
+
})
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
510
725
|
const tx = _ProcessorTransaction.fromEdgeTransaction.call(void 0, edgeTx)
|
|
511
726
|
await _makeUtxoEngineState.transactionChanged.call(void 0, {
|
|
512
727
|
walletId: walletInfo.id,
|
|
@@ -518,7 +733,7 @@ var _utils = require('./utils');
|
|
|
518
733
|
})
|
|
519
734
|
await processor.saveTransaction({
|
|
520
735
|
tx,
|
|
521
|
-
scriptPubkeys: _optionalChain([edgeTx, 'access',
|
|
736
|
+
scriptPubkeys: _optionalChain([edgeTx, 'access', _11 => _11.otherParams, 'optionalAccess', _12 => _12.ourScriptPubkeys])
|
|
522
737
|
})
|
|
523
738
|
|
|
524
739
|
/*
|
|
@@ -533,11 +748,11 @@ var _utils = require('./utils');
|
|
|
533
748
|
privateKeys,
|
|
534
749
|
opts
|
|
535
750
|
) {
|
|
536
|
-
const otherParams =
|
|
751
|
+
const otherParams = _types7.asUtxoSignMessageOtherParams.call(void 0, opts.otherParams)
|
|
537
752
|
const { publicAddress } = otherParams
|
|
538
753
|
const scriptPubkey = walletTools.addressToScriptPubkey(publicAddress)
|
|
539
754
|
const processorAddress = await processor.fetchAddress(scriptPubkey)
|
|
540
|
-
if (_optionalChain([processorAddress, 'optionalAccess',
|
|
755
|
+
if (_optionalChain([processorAddress, 'optionalAccess', _13 => _13.path]) == null) {
|
|
541
756
|
throw new Error('Missing address to sign with')
|
|
542
757
|
}
|
|
543
758
|
const privateKey = asMaybeCurrencyPrivateKey(privateKeys)
|
|
@@ -546,14 +761,14 @@ var _utils = require('./utils');
|
|
|
546
761
|
throw new Error('Cannot sign a message for a read-only wallet')
|
|
547
762
|
|
|
548
763
|
// Derive the xprivs on the fly, since we do not persist them
|
|
549
|
-
const xprivKeys = await
|
|
764
|
+
const xprivKeys = await _utils3.fetchOrDeriveXprivFromKeys.call(void 0, {
|
|
550
765
|
privateKey,
|
|
551
766
|
walletLocalEncryptedDisklet,
|
|
552
767
|
coin: coinInfo.name
|
|
553
768
|
})
|
|
554
769
|
|
|
555
770
|
const signature = await walletTools.signMessageBase64({
|
|
556
|
-
path: _optionalChain([processorAddress, 'optionalAccess',
|
|
771
|
+
path: _optionalChain([processorAddress, 'optionalAccess', _14 => _14.path]),
|
|
557
772
|
message,
|
|
558
773
|
xprivKeys
|
|
559
774
|
})
|
|
@@ -568,8 +783,7 @@ var _utils = require('./utils');
|
|
|
568
783
|
if (otherParams == null) throw new Error('Invalid transaction data')
|
|
569
784
|
|
|
570
785
|
const { psbt, edgeSpendInfo } = otherParams
|
|
571
|
-
if (psbt == null
|
|
572
|
-
throw new Error('Invalid transaction data')
|
|
786
|
+
if (psbt == null) throw new Error('Invalid transaction data')
|
|
573
787
|
|
|
574
788
|
const privateKey = asMaybeCurrencyPrivateKey(privateKeys)
|
|
575
789
|
|
|
@@ -577,7 +791,7 @@ var _utils = require('./utils');
|
|
|
577
791
|
throw new Error('Cannot sign a transaction for a read-only wallet')
|
|
578
792
|
|
|
579
793
|
// Derive the xprivs on the fly, since we do not persist them
|
|
580
|
-
const xprivKeys = await
|
|
794
|
+
const xprivKeys = await _utils3.fetchOrDeriveXprivFromKeys.call(void 0, {
|
|
581
795
|
privateKey,
|
|
582
796
|
walletLocalEncryptedDisklet,
|
|
583
797
|
coin: coinInfo.name
|
|
@@ -588,24 +802,34 @@ var _utils = require('./utils');
|
|
|
588
802
|
const privateKeyEncodings = await (async (
|
|
589
803
|
|
|
590
804
|
) => {
|
|
591
|
-
if (edgeSpendInfo.privateKeys != null) {
|
|
805
|
+
if (_optionalChain([edgeSpendInfo, 'optionalAccess', _15 => _15.privateKeys]) != null) {
|
|
592
806
|
return edgeSpendInfo.privateKeys.map(wif =>
|
|
593
807
|
walletTools.getPrivateKeyEncodingFromWif(wif)
|
|
594
808
|
)
|
|
595
809
|
} else {
|
|
596
810
|
return await Promise.all(
|
|
597
|
-
psbt.inputs.map(async ({ hash, index }) => {
|
|
598
|
-
const
|
|
599
|
-
const utxoId = `${txid}_${index}`
|
|
811
|
+
psbt.inputs.map(async ({ hash, index: vout }) => {
|
|
812
|
+
const txId = Buffer.from(hash).reverse().toString('hex')
|
|
600
813
|
|
|
601
|
-
const [
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
const
|
|
814
|
+
const [transaction] = await processor.fetchTransactions({ txId })
|
|
815
|
+
if (transaction == null)
|
|
816
|
+
throw new Error(
|
|
817
|
+
'Unable to find previous transaction data for input'
|
|
818
|
+
)
|
|
819
|
+
const prevout = transaction.outputs.find(
|
|
820
|
+
input => input.n === vout
|
|
821
|
+
)
|
|
822
|
+
if (prevout == null)
|
|
823
|
+
throw new Error('Unable to find prevout in transaction')
|
|
824
|
+
const { scriptPubkey } = prevout
|
|
825
|
+
|
|
826
|
+
// Use the scriptPubkey to find the private key from the address
|
|
827
|
+
// derivation path
|
|
828
|
+
const address = await processor.fetchAddress(scriptPubkey)
|
|
607
829
|
if (address == null) {
|
|
608
|
-
throw new Error(
|
|
830
|
+
throw new Error(
|
|
831
|
+
`Address for scriptPubkey '${scriptPubkey}' not found`
|
|
832
|
+
)
|
|
609
833
|
}
|
|
610
834
|
if (address.path == null)
|
|
611
835
|
throw new Error(
|
|
@@ -634,7 +858,7 @@ var _utils = require('./utils');
|
|
|
634
858
|
transaction.signedTx = signedTx.hex
|
|
635
859
|
|
|
636
860
|
const { paymentProtocolInfo } =
|
|
637
|
-
_nullishCoalesce(_optionalChain([transaction, 'access',
|
|
861
|
+
_nullishCoalesce(_optionalChain([transaction, 'access', _16 => _16.otherParams, 'optionalAccess', _17 => _17.edgeSpendInfo, 'optionalAccess', _18 => _18.otherParams]), () => ( {}))
|
|
638
862
|
if (paymentProtocolInfo != null) {
|
|
639
863
|
const payment = _paymentRequest.createPayment.call(void 0,
|
|
640
864
|
transaction.signedTx,
|
|
@@ -1569,25 +1569,27 @@ const processRawUtxo = async (
|
|
|
1569
1569
|
let redeemScript
|
|
1570
1570
|
|
|
1571
1571
|
// Function to call once we are finished
|
|
1572
|
-
const done = () =>
|
|
1572
|
+
const done = () => {
|
|
1573
|
+
const processorUtxo = {
|
|
1574
|
+
id,
|
|
1575
|
+
txid: utxo.txid,
|
|
1576
|
+
vout: utxo.vout,
|
|
1577
|
+
value: utxo.value,
|
|
1578
|
+
scriptPubkey: address.scriptPubkey,
|
|
1579
|
+
script,
|
|
1580
|
+
redeemScript,
|
|
1581
|
+
scriptType,
|
|
1582
|
+
blockHeight: _nullishCoalesce(utxo.height, () => ( -1)),
|
|
1583
|
+
spent: false
|
|
1584
|
+
}
|
|
1573
1585
|
addToProcessorUtxoCache(
|
|
1574
1586
|
processorUtxoCache,
|
|
1575
1587
|
path,
|
|
1576
1588
|
address.scriptPubkey,
|
|
1577
1589
|
requiredCount,
|
|
1578
|
-
|
|
1579
|
-
id,
|
|
1580
|
-
txid: utxo.txid,
|
|
1581
|
-
vout: utxo.vout,
|
|
1582
|
-
value: utxo.value,
|
|
1583
|
-
scriptPubkey: address.scriptPubkey,
|
|
1584
|
-
script,
|
|
1585
|
-
redeemScript,
|
|
1586
|
-
scriptType,
|
|
1587
|
-
blockHeight: _nullishCoalesce(utxo.height, () => ( -1)),
|
|
1588
|
-
spent: false
|
|
1589
|
-
}
|
|
1590
|
+
processorUtxo
|
|
1590
1591
|
)
|
|
1592
|
+
}
|
|
1591
1593
|
|
|
1592
1594
|
switch (purposeType) {
|
|
1593
1595
|
case _keymanager.BIP43PurposeTypeEnum.Airbitz:
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
var _cleaners = require('cleaners');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
var _types3 = require('../../plugin/types');
|
|
13
|
+
|
|
14
|
+
|
|
6
15
|
const asUtxoUserSettings = _cleaners.asObject.call(void 0, {
|
|
7
16
|
blockbookServers: _cleaners.asMaybe.call(void 0, _cleaners.asArray.call(void 0, _cleaners.asString), []),
|
|
8
17
|
enableCustomServers: _cleaners.asMaybe.call(void 0, _cleaners.asBoolean, false)
|
|
@@ -23,6 +32,18 @@
|
|
|
23
32
|
|
|
24
33
|
|
|
25
34
|
|
|
35
|
+
|
|
26
36
|
const asUtxoSignMessageOtherParams = _cleaners.asObject.call(void 0, {
|
|
27
37
|
publicAddress: _cleaners.asString
|
|
28
38
|
}); exports.asUtxoSignMessageOtherParams = asUtxoSignMessageOtherParams
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const asUtxoSpendInfoOtherParams = _cleaners.asObject.call(void 0, {
|
|
44
|
+
enableRbf: _cleaners.asOptional.call(void 0, _cleaners.asBoolean),
|
|
45
|
+
forceChangeAddress: _cleaners.asOptional.call(void 0, _cleaners.asString),
|
|
46
|
+
outputSort: _cleaners.asOptional.call(void 0, _cleaners.asValue.call(void 0, 'bip69', 'targets'), 'bip69'),
|
|
47
|
+
txOptions: _cleaners.asOptional.call(void 0, _types3.asTxOptions),
|
|
48
|
+
utxoSourceAddress: _cleaners.asOptional.call(void 0, _cleaners.asString)
|
|
49
|
+
}); exports.asUtxoSpendInfoOtherParams = asUtxoSpendInfoOtherParams
|
|
@@ -12,8 +12,9 @@ var _biggystring = require('biggystring');
|
|
|
12
12
|
var _bip32 = require('bip32'); var bip32 = _interopRequireWildcard(_bip32);
|
|
13
13
|
var _bip39 = require('bip39'); var bip39 = _interopRequireWildcard(_bip39);
|
|
14
14
|
var _bitcoinjsmessage = require('bitcoinjs-message'); var _bitcoinjsmessage2 = _interopRequireDefault(_bitcoinjsmessage);
|
|
15
|
+
var _cleaners = require('cleaners');
|
|
15
16
|
var _ecpair = require('ecpair');
|
|
16
|
-
|
|
17
|
+
|
|
17
18
|
|
|
18
19
|
var _indexAtProtected = require('../../../util/indexAtProtected');
|
|
19
20
|
var _undefinedIfEmptyString = require('../../../util/undefinedIfEmptyString');
|
|
@@ -27,7 +28,9 @@ var _bip69 = require('./bip69');
|
|
|
27
28
|
|
|
28
29
|
var _cashAddress = require('./bitcoincashUtils/cashAddress');
|
|
29
30
|
var _coinmapper = require('./coinmapper');
|
|
31
|
+
var _types9 = require('./types');
|
|
30
32
|
var _utxopicker = require('./utxopicker'); var utxopicker = _interopRequireWildcard(_utxopicker);
|
|
33
|
+
var _utils = require('./utxopicker/utils'); var pickerUtils = _interopRequireWildcard(_utils);
|
|
31
34
|
|
|
32
35
|
let ECPair
|
|
33
36
|
|
|
@@ -73,6 +76,17 @@ var ScriptTypeEnum; (function (ScriptTypeEnum) {
|
|
|
73
76
|
const replayProtection = 'replayprotection'; ScriptTypeEnum["replayProtection"] = replayProtection;
|
|
74
77
|
const replayProtectionP2SH = 'replayprotectionp2sh'; ScriptTypeEnum["replayProtectionP2SH"] = replayProtectionP2SH;
|
|
75
78
|
})(ScriptTypeEnum || (exports.ScriptTypeEnum = ScriptTypeEnum = {}));
|
|
79
|
+
const asScriptTypeEnum = _cleaners.asValue.call(void 0,
|
|
80
|
+
'p2wpkh' ,
|
|
81
|
+
'p2wpkhp2sh' ,
|
|
82
|
+
'p2wsh' ,
|
|
83
|
+
'p2pk' ,
|
|
84
|
+
'p2pkh' ,
|
|
85
|
+
'p2sh' ,
|
|
86
|
+
'p2tr' ,
|
|
87
|
+
'replayprotection' ,
|
|
88
|
+
'replayprotectionp2sh'
|
|
89
|
+
); exports.asScriptTypeEnum = asScriptTypeEnum
|
|
76
90
|
|
|
77
91
|
// A transaction input is either legacy or segwit. This is used for transaction creation and passed per input
|
|
78
92
|
var TransactionInputTypeEnum; (function (TransactionInputTypeEnum) {
|
|
@@ -257,6 +271,7 @@ var VerifyAddressEnum; (function (VerifyAddressEnum) {
|
|
|
257
271
|
|
|
258
272
|
|
|
259
273
|
|
|
274
|
+
|
|
260
275
|
|
|
261
276
|
|
|
262
277
|
function bip43PurposeNumberToTypeEnum(
|
|
@@ -928,7 +943,7 @@ const wifToPrivateKeyEncodingInternal = (
|
|
|
928
943
|
function makeTx(args) {
|
|
929
944
|
const { log, outputSort, memos } = args
|
|
930
945
|
let sequence = 0xffffffff
|
|
931
|
-
if (args.
|
|
946
|
+
if (args.enableRbf) {
|
|
932
947
|
sequence -= 2
|
|
933
948
|
}
|
|
934
949
|
|
|
@@ -1006,16 +1021,22 @@ const wifToPrivateKeyEncodingInternal = (
|
|
|
1006
1021
|
|
|
1007
1022
|
const targets = []
|
|
1008
1023
|
for (const target of args.targets) {
|
|
1009
|
-
if (target.
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1024
|
+
if (target.value == null) continue
|
|
1025
|
+
|
|
1026
|
+
const scriptPubkey =
|
|
1027
|
+
target.address == null
|
|
1028
|
+
? target.scriptPubkey
|
|
1029
|
+
: exports.addressToScriptPubkey.call(void 0, {
|
|
1030
|
+
address: target.address,
|
|
1031
|
+
coin: coin.name
|
|
1032
|
+
})
|
|
1033
|
+
|
|
1034
|
+
if (scriptPubkey == null) continue
|
|
1035
|
+
|
|
1036
|
+
targets.push({
|
|
1037
|
+
script: scriptPubkey,
|
|
1038
|
+
value: target.value
|
|
1039
|
+
})
|
|
1019
1040
|
}
|
|
1020
1041
|
for (const memo of memos) {
|
|
1021
1042
|
const memoData =
|
|
@@ -1051,8 +1072,16 @@ const wifToPrivateKeyEncodingInternal = (
|
|
|
1051
1072
|
feeRate: args.feeRate,
|
|
1052
1073
|
changeScript
|
|
1053
1074
|
})
|
|
1054
|
-
if (result.
|
|
1055
|
-
|
|
1075
|
+
if (result.outputs == null) {
|
|
1076
|
+
const targetsValue = pickerUtils.sumOrNaN(targets)
|
|
1077
|
+
const inputsValue = pickerUtils.sumOrNaN(result.inputs)
|
|
1078
|
+
// This is how much fee is needed to validate the spend
|
|
1079
|
+
const feeDelta = result.fee - (inputsValue - targetsValue)
|
|
1080
|
+
throw new (0, _types9.InsufficientFundsErrorPlus)({
|
|
1081
|
+
currencyCode: args.currencyCode,
|
|
1082
|
+
networkFee: result.fee.toString(),
|
|
1083
|
+
networkFeeShortage: feeDelta.toString()
|
|
1084
|
+
})
|
|
1056
1085
|
}
|
|
1057
1086
|
|
|
1058
1087
|
const sortedInputs = _bip69.sortInputs.call(void 0, result.inputs)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
var _types = require('edge-core-js/types');
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class InsufficientFundsErrorPlus extends _types.InsufficientFundsError {
|
|
12
|
+
|
|
13
|
+
constructor(opts = {}) {
|
|
14
|
+
super(opts)
|
|
15
|
+
const { networkFeeShortage } = opts
|
|
16
|
+
this.networkFeeShortage = networkFeeShortage
|
|
17
|
+
}
|
|
18
|
+
} exports.InsufficientFundsErrorPlus = InsufficientFundsErrorPlus;
|
|
19
|
+
|
|
20
|
+
function asMaybeError(name) {
|
|
21
|
+
return function asError(raw) {
|
|
22
|
+
if (raw instanceof Error && raw.name === name) {
|
|
23
|
+
const typeHack = raw
|
|
24
|
+
return typeHack
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const asMaybeInsufficientFundsErrorPlus = asMaybeError(
|
|
30
|
+
// Share the same name because this error type is a subtype of
|
|
31
|
+
// InsufficientFundsError and therefore backwards compatible
|
|
32
|
+
'InsufficientFundsError'
|
|
33
|
+
); exports.asMaybeInsufficientFundsErrorPlus = asMaybeInsufficientFundsErrorPlus
|
|
@@ -47,6 +47,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
47
47
|
|
|
48
48
|
return {
|
|
49
49
|
changeUsed: false,
|
|
50
|
-
fee: Math.ceil(feeRate * utils.transactionBytes(inputs, outputs))
|
|
50
|
+
fee: Math.ceil(feeRate * utils.transactionBytes(inputs, outputs)),
|
|
51
|
+
inputs
|
|
51
52
|
}
|
|
52
53
|
} exports.accumulative = accumulative;
|
|
@@ -54,6 +54,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
54
54
|
|
|
55
55
|
return {
|
|
56
56
|
changeUsed: false,
|
|
57
|
-
fee: Math.ceil(feeRate * utils.transactionBytes(inputs, outputs))
|
|
57
|
+
fee: Math.ceil(feeRate * utils.transactionBytes(inputs, outputs)),
|
|
58
|
+
inputs
|
|
58
59
|
}
|
|
59
60
|
} exports.forceUseUtxo = forceUseUtxo;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var
|
|
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 _altcoinjs = require('altcoin-js'); var bitcoin = _interopRequireWildcard(_altcoinjs);
|
|
2
|
+
|
|
3
|
+
var _keymanager = require('../keymanager');
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
/*
|
|
@@ -108,6 +110,11 @@ function witnessCount(inputs) {
|
|
|
108
110
|
return overhead + inputsSize + outputsSize
|
|
109
111
|
} exports.transactionBytes = transactionBytes;
|
|
110
112
|
|
|
113
|
+
const transactionSizeFromHex = (hex) => {
|
|
114
|
+
const transaction = bitcoin.Transaction.fromHex(hex)
|
|
115
|
+
return transaction.virtualSize()
|
|
116
|
+
}; exports.transactionSizeFromHex = transactionSizeFromHex
|
|
117
|
+
|
|
111
118
|
function uintOrNaN(v) {
|
|
112
119
|
if (!isFinite(v)) return NaN
|
|
113
120
|
if (Math.floor(v) !== v) return NaN
|
|
@@ -90,7 +90,7 @@ var _cleaners = require('cleaners');
|
|
|
90
90
|
txid: _cleaners.asString,
|
|
91
91
|
sequence: _cleaners.asOptional.call(void 0, _cleaners.asNumber),
|
|
92
92
|
n: _cleaners.asNumber,
|
|
93
|
-
vout: _cleaners.asOptional.call(void 0, _cleaners.asNumber,
|
|
93
|
+
vout: _cleaners.asOptional.call(void 0, _cleaners.asNumber, 0), // If Blockbook doesn't provide vout, assume 0 (empirically observed)
|
|
94
94
|
addresses: _cleaners.asArray.call(void 0, asAddress),
|
|
95
95
|
isAddress: _cleaners.asBoolean,
|
|
96
96
|
value: _cleaners.asString,
|
|
@@ -24,9 +24,9 @@ export interface AddressPath {
|
|
|
24
24
|
export interface TxOptions {
|
|
25
25
|
utxos?: IUTXO[];
|
|
26
26
|
subtractFee?: boolean;
|
|
27
|
-
setRBF?: boolean;
|
|
28
27
|
CPFP?: string;
|
|
29
28
|
}
|
|
29
|
+
export declare const asTxOptions: import("cleaners").ObjectCleaner<TxOptions>;
|
|
30
30
|
export interface PluginInfo {
|
|
31
31
|
currencyInfo: EdgeCurrencyInfo;
|
|
32
32
|
engineInfo: EngineInfo;
|
|
@@ -117,7 +117,7 @@ export declare type FeeInfo = FeeRates & {
|
|
|
117
117
|
standardFeeHighAmount: string;
|
|
118
118
|
maximumFeeRate?: string;
|
|
119
119
|
};
|
|
120
|
-
export declare const asFeeInfo:
|
|
120
|
+
export declare const asFeeInfo: (fallback?: FeeInfo | undefined) => Cleaner<FeeInfo>;
|
|
121
121
|
export interface EngineConfig {
|
|
122
122
|
walletInfo: EdgeWalletInfo;
|
|
123
123
|
pluginInfo: PluginInfo;
|
|
@@ -14,8 +14,17 @@ export interface UtxoTxOtherParams {
|
|
|
14
14
|
};
|
|
15
15
|
edgeSpendInfo?: EdgeSpendInfo;
|
|
16
16
|
ourScriptPubkeys: string[];
|
|
17
|
+
replacedTxid?: string;
|
|
17
18
|
}
|
|
18
19
|
export declare type UtxoSignMessageOtherParams = ReturnType<typeof asUtxoSignMessageOtherParams>;
|
|
19
20
|
export declare const asUtxoSignMessageOtherParams: import("cleaners").ObjectCleaner<{
|
|
20
21
|
publicAddress: string;
|
|
21
22
|
}>;
|
|
23
|
+
export declare type UtxoSpendInfoOtherParams = ReturnType<typeof asUtxoSpendInfoOtherParams>;
|
|
24
|
+
export declare const asUtxoSpendInfoOtherParams: import("cleaners").ObjectCleaner<{
|
|
25
|
+
enableRbf: boolean | undefined;
|
|
26
|
+
forceChangeAddress: string | undefined;
|
|
27
|
+
outputSort: "targets" | "bip69";
|
|
28
|
+
txOptions: import("../../plugin/types").TxOptions | undefined;
|
|
29
|
+
utxoSourceAddress: string | undefined;
|
|
30
|
+
}>;
|
|
@@ -28,6 +28,7 @@ export declare enum ScriptTypeEnum {
|
|
|
28
28
|
replayProtection = "replayprotection",
|
|
29
29
|
replayProtectionP2SH = "replayprotectionp2sh"
|
|
30
30
|
}
|
|
31
|
+
export declare const asScriptTypeEnum: import("cleaners").Cleaner<ScriptTypeEnum>;
|
|
31
32
|
export declare enum TransactionInputTypeEnum {
|
|
32
33
|
Legacy = "legacy",
|
|
33
34
|
Segwit = "segwit"
|
|
@@ -136,7 +137,7 @@ export interface MakeTxArgs {
|
|
|
136
137
|
targets: MakeTxTarget[];
|
|
137
138
|
memos: EdgeMemo[];
|
|
138
139
|
feeRate: number;
|
|
139
|
-
|
|
140
|
+
enableRbf: boolean;
|
|
140
141
|
coin: string;
|
|
141
142
|
currencyCode: string;
|
|
142
143
|
freshChangeAddress: string;
|
|
@@ -146,9 +147,10 @@ export interface MakeTxArgs {
|
|
|
146
147
|
}
|
|
147
148
|
export interface MakeTxTarget {
|
|
148
149
|
address?: string;
|
|
150
|
+
scriptPubkey?: string;
|
|
149
151
|
value?: number;
|
|
150
152
|
}
|
|
151
|
-
interface MakeTxReturn extends Required<utxopicker.UtxoPickerResult> {
|
|
153
|
+
export interface MakeTxReturn extends Required<utxopicker.UtxoPickerResult> {
|
|
152
154
|
hex: string;
|
|
153
155
|
psbtBase64: string;
|
|
154
156
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Cleaner } from 'cleaners';
|
|
2
|
+
import { InsufficientFundsError } from 'edge-core-js/types';
|
|
3
|
+
interface InsufficientFundsErrorOptsPlus {
|
|
4
|
+
currencyCode?: string;
|
|
5
|
+
networkFee?: string;
|
|
6
|
+
networkFeeShortage?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class InsufficientFundsErrorPlus extends InsufficientFundsError {
|
|
9
|
+
networkFeeShortage?: string;
|
|
10
|
+
constructor(opts?: InsufficientFundsErrorOptsPlus);
|
|
11
|
+
}
|
|
12
|
+
export declare const asMaybeInsufficientFundsErrorPlus: Cleaner<InsufficientFundsErrorPlus | undefined>;
|
|
13
|
+
export {};
|
|
@@ -5,6 +5,7 @@ export declare function inputBytes(input: UTXO): number;
|
|
|
5
5
|
export declare function outputBytes(output: Output): number;
|
|
6
6
|
export declare function dustThreshold(output: Output, feeRate: number): number;
|
|
7
7
|
export declare function transactionBytes(inputs: UTXO[], outputs: Output[]): number;
|
|
8
|
+
export declare const transactionSizeFromHex: (hex: string) => number;
|
|
8
9
|
export declare function uintOrNaN(v: number): number;
|
|
9
10
|
export declare function sumForgiving(range: Array<{
|
|
10
11
|
value: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "edge-currency-plugins",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
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",
|