edge-currency-plugins 2.4.1 → 2.5.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.
- package/lib/common/plugin/types.js +8 -2
- 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 +295 -68
- package/lib/common/utxobased/engine/makeUtxoEngineState.js +15 -13
- package/lib/common/utxobased/engine/types.js +22 -1
- package/lib/common/utxobased/info/litecoin.js +1 -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 +1 -1
- 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
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
var _cleaners = require('cleaners');
|
|
12
11
|
|
|
13
12
|
|
|
13
|
+
var _cleaners = require('cleaners');
|
|
14
|
+
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
|
|
@@ -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
|
|
|
@@ -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,211 @@ var _utils = require('./utils');
|
|
|
129
140
|
})
|
|
130
141
|
|
|
131
142
|
const engine = {
|
|
143
|
+
async accelerate(edgeTx) {
|
|
144
|
+
const { canReplaceByFee = false } = currencyInfo
|
|
145
|
+
if (!canReplaceByFee) return null
|
|
146
|
+
|
|
147
|
+
// Get the replaced transaction from the processor:
|
|
148
|
+
const replacedTxid = edgeTx.txid
|
|
149
|
+
const [replacedTx] = await processor.fetchTransactions({
|
|
150
|
+
txId: replacedTxid
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
// Transaction checks:
|
|
154
|
+
// The transaction must be found and not confirmed or dropped.
|
|
155
|
+
if (replacedTx == null) return null
|
|
156
|
+
if (replacedTx.blockHeight !== 0) return null
|
|
157
|
+
|
|
158
|
+
// Double the fee used for the RBF transaction:
|
|
159
|
+
const vBytes = _utils.transactionSizeFromHex.call(void 0, replacedTx.hex)
|
|
160
|
+
const newFeeRate = Math.round((parseInt(replacedTx.fees) / vBytes) * 2)
|
|
161
|
+
|
|
162
|
+
const replacedTxInputs = replacedTx.inputs
|
|
163
|
+
// Recreate UTXOs from processor transaction and mark them as unspent:
|
|
164
|
+
const replacedTxUtxos = await Promise.all(
|
|
165
|
+
replacedTxInputs.map(async (_, index) => {
|
|
166
|
+
const utxo = await _utxo.utxoFromProcessorTransactionInput.call(void 0,
|
|
167
|
+
processor,
|
|
168
|
+
replacedTx,
|
|
169
|
+
index
|
|
170
|
+
)
|
|
171
|
+
// Mark as unspent because we're going to reuse replaced tx's UTXOs
|
|
172
|
+
utxo.spent = false
|
|
173
|
+
return utxo
|
|
174
|
+
})
|
|
175
|
+
)
|
|
176
|
+
// Get the largest input from the transaction to re-use:
|
|
177
|
+
const replacedTxMaxUtxo = replacedTxUtxos.reduce((maxUtxo, utxo) => {
|
|
178
|
+
if (utxo.value > maxUtxo.value) return utxo
|
|
179
|
+
return maxUtxo
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
const targets = []
|
|
183
|
+
const newOurReceiveAddresses = []
|
|
184
|
+
let foundChangeAddress
|
|
185
|
+
for (const output of replacedTx.outputs) {
|
|
186
|
+
// Fetch address by output's scriptPubkey to determine output ownership
|
|
187
|
+
const ourAddress = await processor.fetchAddress(output.scriptPubkey)
|
|
188
|
+
|
|
189
|
+
// This isn't our output, so include it as a target
|
|
190
|
+
if (ourAddress == null) {
|
|
191
|
+
targets.push({
|
|
192
|
+
scriptPubkey: output.scriptPubkey,
|
|
193
|
+
value: parseInt(output.amount)
|
|
194
|
+
})
|
|
195
|
+
continue
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Addresses from database should include a path; this is a type assert
|
|
199
|
+
if (ourAddress.path == null)
|
|
200
|
+
throw new Error('Expecting path for address')
|
|
201
|
+
|
|
202
|
+
// The output is ours:
|
|
203
|
+
const purposeType = _utils3.pathToPurposeType.call(void 0,
|
|
204
|
+
ourAddress.path,
|
|
205
|
+
engineInfo.scriptTemplates
|
|
206
|
+
)
|
|
207
|
+
const addressType = _utils3.getAddressTypeFromPurposeType.call(void 0, purposeType)
|
|
208
|
+
const { address } = _keymanager.scriptPubkeyToAddress.call(void 0, {
|
|
209
|
+
scriptPubkey: ourAddress.scriptPubkey,
|
|
210
|
+
addressType,
|
|
211
|
+
coin: coinInfo.name,
|
|
212
|
+
redeemScript: ourAddress.redeemScript
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
newOurReceiveAddresses.push(address)
|
|
216
|
+
|
|
217
|
+
// Detect if it's the change address:
|
|
218
|
+
if (ourAddress.path.changeIndex === 1) {
|
|
219
|
+
foundChangeAddress = address
|
|
220
|
+
} else {
|
|
221
|
+
// This isn't our change address, so include it as a target.
|
|
222
|
+
// The transaction must have been a spend-to-self.
|
|
223
|
+
targets.push({
|
|
224
|
+
scriptPubkey: output.scriptPubkey,
|
|
225
|
+
value: parseInt(output.amount)
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Use the found change address or generate a new one:
|
|
231
|
+
const freshAddress =
|
|
232
|
+
foundChangeAddress == null
|
|
233
|
+
? await engineState.getFreshAddress({ branch: 1 })
|
|
234
|
+
: { publicAddress: foundChangeAddress }
|
|
235
|
+
const freshChangeAddress =
|
|
236
|
+
_nullishCoalesce(freshAddress.segwitAddress, () => ( freshAddress.publicAddress))
|
|
237
|
+
|
|
238
|
+
// Get all current UTXOs:
|
|
239
|
+
const currentUtxos = _filterUndefined.filterUndefined.call(void 0,
|
|
240
|
+
await processor.fetchUtxos({
|
|
241
|
+
utxoIds: []
|
|
242
|
+
})
|
|
243
|
+
)
|
|
244
|
+
// Exclude all UTXOs which are from the replaced tx, because
|
|
245
|
+
// they wont be valid.
|
|
246
|
+
.filter(utxo => utxo.txid !== replacedTxid)
|
|
247
|
+
|
|
248
|
+
// Combine replaced transaction's inputs as UTXOs with the current UTXO set
|
|
249
|
+
const utxos = [...replacedTxUtxos, ...currentUtxos]
|
|
250
|
+
|
|
251
|
+
// New transaction to be the replacement transaction
|
|
252
|
+
const makeTxArgs = {
|
|
253
|
+
utxos,
|
|
254
|
+
forceUseUtxo: [replacedTxMaxUtxo],
|
|
255
|
+
targets,
|
|
256
|
+
memos: edgeTx.memos,
|
|
257
|
+
feeRate: newFeeRate,
|
|
258
|
+
coin: coinInfo.name,
|
|
259
|
+
currencyCode: currencyInfo.currencyCode,
|
|
260
|
+
enableRbf: true,
|
|
261
|
+
freshChangeAddress,
|
|
262
|
+
subtractFee: false,
|
|
263
|
+
log,
|
|
264
|
+
outputSort: 'bip69'
|
|
265
|
+
}
|
|
266
|
+
const newTx = (() => {
|
|
267
|
+
try {
|
|
268
|
+
return _keymanager.makeTx.call(void 0, makeTxArgs)
|
|
269
|
+
} catch (error) {
|
|
270
|
+
const cleanError = _types5.asMaybeInsufficientFundsErrorPlus.call(void 0, error)
|
|
271
|
+
if (_optionalChain([cleanError, 'optionalAccess', _2 => _2.networkFeeShortage]) != null) {
|
|
272
|
+
let feeDelta = parseInt(cleanError.networkFeeShortage)
|
|
273
|
+
// Adjust target values until we diminish the fee delta completely
|
|
274
|
+
for (const target of targets) {
|
|
275
|
+
if (target.value == null) continue
|
|
276
|
+
// The term is how much value to subtract from the target's value.
|
|
277
|
+
// The term's maximum value is the target's value.
|
|
278
|
+
// The term's minimum value is the fee delta.
|
|
279
|
+
const term = Math.min(target.value, feeDelta)
|
|
280
|
+
target.value -= term // Either decrement or zero out
|
|
281
|
+
feeDelta -= term // Ether decrement or zero out
|
|
282
|
+
}
|
|
283
|
+
// Retry making the transaction
|
|
284
|
+
return _keymanager.makeTx.call(void 0, makeTxArgs)
|
|
285
|
+
}
|
|
286
|
+
throw error
|
|
287
|
+
}
|
|
288
|
+
})()
|
|
289
|
+
|
|
290
|
+
if (newTx.changeUsed) {
|
|
291
|
+
newOurReceiveAddresses.push(freshChangeAddress)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Generate new tracking of our scripts:
|
|
295
|
+
const newOurScriptPubkeys = newTx.inputs.map(input =>
|
|
296
|
+
input.scriptPubkey.toString('hex')
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
// Calculate transaction spend amount:
|
|
300
|
+
let nativeAmount = '0'
|
|
301
|
+
for (const output of newTx.outputs) {
|
|
302
|
+
const scriptPubkey = output.scriptPubkey.toString('hex')
|
|
303
|
+
const own = await processor.fetchAddress(scriptPubkey)
|
|
304
|
+
if (own == null) {
|
|
305
|
+
// Not our output
|
|
306
|
+
nativeAmount = bs.sub(nativeAmount, output.value.toString())
|
|
307
|
+
} else {
|
|
308
|
+
// Our output
|
|
309
|
+
newOurScriptPubkeys.push(scriptPubkey)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const networkFee = newTx.fee.toString()
|
|
314
|
+
nativeAmount = bs.sub(nativeAmount, networkFee)
|
|
315
|
+
|
|
316
|
+
const newTxOtherParams = {
|
|
317
|
+
unsignedTx: newTx.hex,
|
|
318
|
+
psbt: {
|
|
319
|
+
base64: newTx.psbtBase64,
|
|
320
|
+
inputs: newTx.inputs,
|
|
321
|
+
outputs: newTx.outputs
|
|
322
|
+
},
|
|
323
|
+
ourScriptPubkeys: newOurScriptPubkeys,
|
|
324
|
+
replacedTxid: replacedTxid
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Return a EdgeTransaction object with the updates
|
|
328
|
+
return {
|
|
329
|
+
...edgeTx,
|
|
330
|
+
blockHeight: 0,
|
|
331
|
+
currencyCode: currencyInfo.currencyCode,
|
|
332
|
+
date: _unixTime.unixTime.call(void 0, ),
|
|
333
|
+
feeRateUsed: {
|
|
334
|
+
satPerVByte: newFeeRate
|
|
335
|
+
},
|
|
336
|
+
isSend: true,
|
|
337
|
+
nativeAmount,
|
|
338
|
+
networkFee,
|
|
339
|
+
otherParams: newTxOtherParams,
|
|
340
|
+
ourReceiveAddresses: newOurReceiveAddresses,
|
|
341
|
+
parentNetworkFee: undefined,
|
|
342
|
+
signedTx: '',
|
|
343
|
+
txid: '',
|
|
344
|
+
walletId: walletInfo.id
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
|
|
132
348
|
async startEngine() {
|
|
133
349
|
emitter.emit(
|
|
134
350
|
_makeEngineEmitter.EngineEvent.WALLET_BALANCE_CHANGED,
|
|
@@ -166,8 +382,8 @@ var _utils = require('./utils');
|
|
|
166
382
|
async broadcastTx(transaction) {
|
|
167
383
|
const { otherParams } = transaction
|
|
168
384
|
if (
|
|
169
|
-
_optionalChain([otherParams, 'optionalAccess',
|
|
170
|
-
_optionalChain([otherParams, 'optionalAccess',
|
|
385
|
+
_optionalChain([otherParams, 'optionalAccess', _3 => _3.paymentProtocolInfo, 'optionalAccess', _4 => _4.payment]) != null &&
|
|
386
|
+
_optionalChain([otherParams, 'optionalAccess', _5 => _5.paymentProtocolInfo, 'optionalAccess', _6 => _6.paymentUrl]) != null
|
|
171
387
|
) {
|
|
172
388
|
const paymentAck = await _paymentRequest.sendPayment.call(void 0,
|
|
173
389
|
io.fetch,
|
|
@@ -193,7 +409,7 @@ var _utils = require('./utils');
|
|
|
193
409
|
},
|
|
194
410
|
|
|
195
411
|
async changeUserSettings(userSettings) {
|
|
196
|
-
await pluginState.updateServers(
|
|
412
|
+
await pluginState.updateServers(_types7.asUtxoUserSettings.call(void 0, userSettings))
|
|
197
413
|
},
|
|
198
414
|
|
|
199
415
|
async disableTokens(_tokens) {
|
|
@@ -236,10 +452,6 @@ var _utils = require('./utils');
|
|
|
236
452
|
.join('\n')
|
|
237
453
|
},
|
|
238
454
|
|
|
239
|
-
async getEnabledTokens() {
|
|
240
|
-
return await Promise.resolve([])
|
|
241
|
-
},
|
|
242
|
-
|
|
243
455
|
async getFreshAddress(
|
|
244
456
|
opts
|
|
245
457
|
) {
|
|
@@ -261,10 +473,6 @@ var _utils = require('./utils');
|
|
|
261
473
|
)
|
|
262
474
|
},
|
|
263
475
|
|
|
264
|
-
getTokenStatus(_token) {
|
|
265
|
-
return false
|
|
266
|
-
},
|
|
267
|
-
|
|
268
476
|
async getTransactions(
|
|
269
477
|
options
|
|
270
478
|
) {
|
|
@@ -295,17 +503,22 @@ var _utils = require('./utils');
|
|
|
295
503
|
async makeSpend(edgeSpendInfo) {
|
|
296
504
|
edgeSpendInfo = _upgradeMemos.upgradeMemos.call(void 0, edgeSpendInfo, currencyInfo)
|
|
297
505
|
const { memos = [], spendTargets } = edgeSpendInfo
|
|
298
|
-
const
|
|
299
|
-
_optionalChain([edgeSpendInfo, 'access', _5 => _5.otherParams, 'optionalAccess', _6 => _6.txOptions])
|
|
300
|
-
const { outputSort = 'bip69', utxoSourceAddress, forceChangeAddress } =
|
|
506
|
+
const spendInfoOtherParams = _types7.asUtxoSpendInfoOtherParams.call(void 0,
|
|
301
507
|
_nullishCoalesce(edgeSpendInfo.otherParams, () => ( {}))
|
|
508
|
+
)
|
|
509
|
+
const txOptions = _nullishCoalesce(spendInfoOtherParams.txOptions, () => ( {}))
|
|
510
|
+
const {
|
|
511
|
+
outputSort,
|
|
512
|
+
utxoSourceAddress,
|
|
513
|
+
forceChangeAddress
|
|
514
|
+
} = spendInfoOtherParams
|
|
302
515
|
|
|
303
516
|
let utxoScriptPubkey
|
|
304
517
|
if (utxoSourceAddress != null) {
|
|
305
518
|
utxoScriptPubkey = walletTools.addressToScriptPubkey(utxoSourceAddress)
|
|
306
519
|
}
|
|
307
520
|
|
|
308
|
-
if (
|
|
521
|
+
if (txOptions.CPFP == null && spendTargets.length < 1) {
|
|
309
522
|
throw new Error('Need to provide Spend Targets')
|
|
310
523
|
}
|
|
311
524
|
// Calculate the total amount to send
|
|
@@ -314,7 +527,7 @@ var _utils = require('./utils');
|
|
|
314
527
|
'0'
|
|
315
528
|
)
|
|
316
529
|
const utxos =
|
|
317
|
-
await _asyncNullishCoalesce(
|
|
530
|
+
await _asyncNullishCoalesce(txOptions.utxos, async () => (
|
|
318
531
|
_filterUndefined.filterUndefined.call(void 0,
|
|
319
532
|
(await processor.fetchUtxos({
|
|
320
533
|
scriptPubkey: utxoScriptPubkey,
|
|
@@ -323,7 +536,7 @@ var _utils = require('./utils');
|
|
|
323
536
|
)))
|
|
324
537
|
|
|
325
538
|
if (
|
|
326
|
-
bs.gt(totalAmountToSend, `${
|
|
539
|
+
bs.gt(totalAmountToSend, `${_utils3.sumUtxos.call(void 0, utxos)}`) ||
|
|
327
540
|
utxos.length === 0
|
|
328
541
|
) {
|
|
329
542
|
throw new (0, _edgecorejs.InsufficientFundsError)(currencyInfo.currencyCode)
|
|
@@ -337,7 +550,7 @@ var _utils = require('./utils');
|
|
|
337
550
|
}
|
|
338
551
|
|
|
339
552
|
// if script exists construct address from script
|
|
340
|
-
if (_optionalChain([target, 'access',
|
|
553
|
+
if (_optionalChain([target, 'access', _7 => _7.otherParams, 'optionalAccess', _8 => _8.script]) != null) {
|
|
341
554
|
const { script } = target.otherParams
|
|
342
555
|
if (script.type === 'replayProtection') {
|
|
343
556
|
// construct a replay protection p2sh address
|
|
@@ -357,7 +570,7 @@ var _utils = require('./utils');
|
|
|
357
570
|
const scriptPubkey = walletTools.addressToScriptPubkey(
|
|
358
571
|
target.publicAddress
|
|
359
572
|
)
|
|
360
|
-
if (processor.fetchAddress(scriptPubkey) != null) {
|
|
573
|
+
if ((await processor.fetchAddress(scriptPubkey)) != null) {
|
|
361
574
|
ourReceiveAddresses.push(target.publicAddress)
|
|
362
575
|
}
|
|
363
576
|
}
|
|
@@ -381,31 +594,12 @@ var _utils = require('./utils');
|
|
|
381
594
|
freshAddress.segwitAddress)), () => (
|
|
382
595
|
freshAddress.publicAddress))
|
|
383
596
|
|
|
384
|
-
const
|
|
385
|
-
|
|
597
|
+
const feeRate = parseInt(await fees.getRate(edgeSpendInfo))
|
|
598
|
+
|
|
386
599
|
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) {
|
|
600
|
+
if (txOptions.CPFP != null) {
|
|
407
601
|
const [childTx] = await processor.fetchTransactions({
|
|
408
|
-
txId:
|
|
602
|
+
txId: txOptions.CPFP
|
|
409
603
|
})
|
|
410
604
|
if (childTx == null) throw new Error('transaction not found')
|
|
411
605
|
const utxos = []
|
|
@@ -417,9 +611,10 @@ var _utils = require('./utils');
|
|
|
417
611
|
// cpfp just sends to change, no target addresses are required
|
|
418
612
|
targets = []
|
|
419
613
|
}
|
|
614
|
+
|
|
420
615
|
log.warn(`spend: Using fee rate ${feeRate} sat/B`)
|
|
421
616
|
const subtractFee =
|
|
422
|
-
|
|
617
|
+
txOptions.subtractFee != null ? txOptions.subtractFee : false
|
|
423
618
|
const tx = _keymanager.makeTx.call(void 0, {
|
|
424
619
|
utxos,
|
|
425
620
|
forceUseUtxo: maxUtxo != null ? [maxUtxo] : [],
|
|
@@ -428,7 +623,10 @@ var _utils = require('./utils');
|
|
|
428
623
|
feeRate,
|
|
429
624
|
coin: coinInfo.name,
|
|
430
625
|
currencyCode: currencyInfo.currencyCode,
|
|
431
|
-
|
|
626
|
+
enableRbf:
|
|
627
|
+
_nullishCoalesce(_nullishCoalesce(spendInfoOtherParams.enableRbf, () => (
|
|
628
|
+
currencyInfo.canReplaceByFee)), () => (
|
|
629
|
+
false)),
|
|
432
630
|
freshChangeAddress,
|
|
433
631
|
subtractFee,
|
|
434
632
|
log,
|
|
@@ -507,6 +705,26 @@ var _utils = require('./utils');
|
|
|
507
705
|
},
|
|
508
706
|
|
|
509
707
|
async saveTx(edgeTx) {
|
|
708
|
+
// If the transaction being saved replaces a transaction, update it.
|
|
709
|
+
const replacedTxid = _optionalChain([edgeTx, 'access', _9 => _9.otherParams, 'optionalAccess', _10 => _10.replacedTxid])
|
|
710
|
+
if (replacedTxid != null) {
|
|
711
|
+
// Get the replaced transaction using the replacedTxid
|
|
712
|
+
const [rbfTx] = await processor.fetchTransactions({
|
|
713
|
+
txId: replacedTxid
|
|
714
|
+
})
|
|
715
|
+
if (rbfTx != null) {
|
|
716
|
+
rbfTx.blockHeight = -1
|
|
717
|
+
await _makeUtxoEngineState.transactionChanged.call(void 0, {
|
|
718
|
+
walletId: walletInfo.id,
|
|
719
|
+
tx: rbfTx,
|
|
720
|
+
pluginInfo,
|
|
721
|
+
emitter,
|
|
722
|
+
walletTools,
|
|
723
|
+
processor
|
|
724
|
+
})
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
510
728
|
const tx = _ProcessorTransaction.fromEdgeTransaction.call(void 0, edgeTx)
|
|
511
729
|
await _makeUtxoEngineState.transactionChanged.call(void 0, {
|
|
512
730
|
walletId: walletInfo.id,
|
|
@@ -518,7 +736,7 @@ var _utils = require('./utils');
|
|
|
518
736
|
})
|
|
519
737
|
await processor.saveTransaction({
|
|
520
738
|
tx,
|
|
521
|
-
scriptPubkeys: _optionalChain([edgeTx, 'access',
|
|
739
|
+
scriptPubkeys: _optionalChain([edgeTx, 'access', _11 => _11.otherParams, 'optionalAccess', _12 => _12.ourScriptPubkeys])
|
|
522
740
|
})
|
|
523
741
|
|
|
524
742
|
/*
|
|
@@ -533,11 +751,11 @@ var _utils = require('./utils');
|
|
|
533
751
|
privateKeys,
|
|
534
752
|
opts
|
|
535
753
|
) {
|
|
536
|
-
const otherParams =
|
|
754
|
+
const otherParams = _types7.asUtxoSignMessageOtherParams.call(void 0, opts.otherParams)
|
|
537
755
|
const { publicAddress } = otherParams
|
|
538
756
|
const scriptPubkey = walletTools.addressToScriptPubkey(publicAddress)
|
|
539
757
|
const processorAddress = await processor.fetchAddress(scriptPubkey)
|
|
540
|
-
if (_optionalChain([processorAddress, 'optionalAccess',
|
|
758
|
+
if (_optionalChain([processorAddress, 'optionalAccess', _13 => _13.path]) == null) {
|
|
541
759
|
throw new Error('Missing address to sign with')
|
|
542
760
|
}
|
|
543
761
|
const privateKey = asMaybeCurrencyPrivateKey(privateKeys)
|
|
@@ -546,14 +764,14 @@ var _utils = require('./utils');
|
|
|
546
764
|
throw new Error('Cannot sign a message for a read-only wallet')
|
|
547
765
|
|
|
548
766
|
// Derive the xprivs on the fly, since we do not persist them
|
|
549
|
-
const xprivKeys = await
|
|
767
|
+
const xprivKeys = await _utils3.fetchOrDeriveXprivFromKeys.call(void 0, {
|
|
550
768
|
privateKey,
|
|
551
769
|
walletLocalEncryptedDisklet,
|
|
552
770
|
coin: coinInfo.name
|
|
553
771
|
})
|
|
554
772
|
|
|
555
773
|
const signature = await walletTools.signMessageBase64({
|
|
556
|
-
path: _optionalChain([processorAddress, 'optionalAccess',
|
|
774
|
+
path: _optionalChain([processorAddress, 'optionalAccess', _14 => _14.path]),
|
|
557
775
|
message,
|
|
558
776
|
xprivKeys
|
|
559
777
|
})
|
|
@@ -568,8 +786,7 @@ var _utils = require('./utils');
|
|
|
568
786
|
if (otherParams == null) throw new Error('Invalid transaction data')
|
|
569
787
|
|
|
570
788
|
const { psbt, edgeSpendInfo } = otherParams
|
|
571
|
-
if (psbt == null
|
|
572
|
-
throw new Error('Invalid transaction data')
|
|
789
|
+
if (psbt == null) throw new Error('Invalid transaction data')
|
|
573
790
|
|
|
574
791
|
const privateKey = asMaybeCurrencyPrivateKey(privateKeys)
|
|
575
792
|
|
|
@@ -577,7 +794,7 @@ var _utils = require('./utils');
|
|
|
577
794
|
throw new Error('Cannot sign a transaction for a read-only wallet')
|
|
578
795
|
|
|
579
796
|
// Derive the xprivs on the fly, since we do not persist them
|
|
580
|
-
const xprivKeys = await
|
|
797
|
+
const xprivKeys = await _utils3.fetchOrDeriveXprivFromKeys.call(void 0, {
|
|
581
798
|
privateKey,
|
|
582
799
|
walletLocalEncryptedDisklet,
|
|
583
800
|
coin: coinInfo.name
|
|
@@ -588,24 +805,34 @@ var _utils = require('./utils');
|
|
|
588
805
|
const privateKeyEncodings = await (async (
|
|
589
806
|
|
|
590
807
|
) => {
|
|
591
|
-
if (edgeSpendInfo.privateKeys != null) {
|
|
808
|
+
if (_optionalChain([edgeSpendInfo, 'optionalAccess', _15 => _15.privateKeys]) != null) {
|
|
592
809
|
return edgeSpendInfo.privateKeys.map(wif =>
|
|
593
810
|
walletTools.getPrivateKeyEncodingFromWif(wif)
|
|
594
811
|
)
|
|
595
812
|
} else {
|
|
596
813
|
return await Promise.all(
|
|
597
|
-
psbt.inputs.map(async ({ hash, index }) => {
|
|
598
|
-
const
|
|
599
|
-
const utxoId = `${txid}_${index}`
|
|
814
|
+
psbt.inputs.map(async ({ hash, index: vout }) => {
|
|
815
|
+
const txId = Buffer.from(hash).reverse().toString('hex')
|
|
600
816
|
|
|
601
|
-
const [
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
const
|
|
817
|
+
const [transaction] = await processor.fetchTransactions({ txId })
|
|
818
|
+
if (transaction == null)
|
|
819
|
+
throw new Error(
|
|
820
|
+
'Unable to find previous transaction data for input'
|
|
821
|
+
)
|
|
822
|
+
const prevout = transaction.outputs.find(
|
|
823
|
+
input => input.n === vout
|
|
824
|
+
)
|
|
825
|
+
if (prevout == null)
|
|
826
|
+
throw new Error('Unable to find prevout in transaction')
|
|
827
|
+
const { scriptPubkey } = prevout
|
|
828
|
+
|
|
829
|
+
// Use the scriptPubkey to find the private key from the address
|
|
830
|
+
// derivation path
|
|
831
|
+
const address = await processor.fetchAddress(scriptPubkey)
|
|
607
832
|
if (address == null) {
|
|
608
|
-
throw new Error(
|
|
833
|
+
throw new Error(
|
|
834
|
+
`Address for scriptPubkey '${scriptPubkey}' not found`
|
|
835
|
+
)
|
|
609
836
|
}
|
|
610
837
|
if (address.path == null)
|
|
611
838
|
throw new Error(
|
|
@@ -634,7 +861,7 @@ var _utils = require('./utils');
|
|
|
634
861
|
transaction.signedTx = signedTx.hex
|
|
635
862
|
|
|
636
863
|
const { paymentProtocolInfo } =
|
|
637
|
-
_nullishCoalesce(_optionalChain([transaction, 'access',
|
|
864
|
+
_nullishCoalesce(_optionalChain([transaction, 'access', _16 => _16.otherParams, 'optionalAccess', _17 => _17.edgeSpendInfo, 'optionalAccess', _18 => _18.otherParams]), () => ( {}))
|
|
638
865
|
if (paymentProtocolInfo != null) {
|
|
639
866
|
const payment = _paymentRequest.createPayment.call(void 0,
|
|
640
867
|
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;
|
|
@@ -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.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",
|