edge-currency-plugins 3.12.0 → 3.14.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/android/src/main/assets/edge-currency-plugins/edge-currency-plugins.js +48 -48
- package/lib/common/constants.js +4 -1
- package/lib/common/fees/calcMinerFeePerByte.js +19 -5
- package/lib/common/fees/calcReplacementFeeRate.js +25 -0
- package/lib/common/fees/processMempoolSpaceFees.js +12 -16
- package/lib/common/plugin/types.js +6 -0
- package/lib/common/utxobased/engine/ServerStates.js +196 -95
- package/lib/common/utxobased/engine/UtxoEngine.js +16 -3
- package/lib/common/utxobased/info/bitcoin.js +4 -4
- package/lib/common/utxobased/info/bitcoincash.js +1 -1
- package/lib/common/utxobased/info/bitcointestnet.js +1 -1
- package/lib/common/utxobased/info/bitcointestnet4.js +1 -1
- package/lib/common/utxobased/info/dash.js +1 -1
- package/lib/common/utxobased/info/digibyte.js +1 -1
- package/lib/common/utxobased/info/dogecoin.js +1 -1
- package/lib/common/utxobased/info/ecash.js +4 -1
- package/lib/common/utxobased/info/litecoin.js +3 -3
- package/lib/common/utxobased/info/pivx.js +5 -5
- package/lib/common/utxobased/info/qtum.js +1 -1
- package/lib/common/utxobased/info/vertcoin.js +1 -1
- package/lib/common/utxobased/info/zcoin.js +1 -1
- package/lib/common/utxobased/keymanager/utxopicker/accumulative.js +4 -4
- package/lib/common/utxobased/keymanager/utxopicker/forceUseUtxo.js +5 -5
- package/lib/common/utxobased/keymanager/utxopicker/subtractFee.js +1 -1
- package/lib/common/utxobased/keymanager/utxopicker/utils.js +27 -3
- package/lib/common/utxobased/network/Blockbook.js +10 -2
- package/lib/src/common/constants.d.ts +1 -1
- package/lib/src/common/fees/calcReplacementFeeRate.d.ts +15 -0
- package/lib/src/common/plugin/types.d.ts +7 -1
- package/lib/src/common/utxobased/engine/ServerStates.d.ts +21 -0
- package/lib/src/common/utxobased/keymanager/utxopicker/utils.d.ts +12 -0
- package/lib/test/common/fees/calcReplacementFeeRate.spec.d.ts +1 -0
- package/lib/test/common/fees/processMempoolSpaceFees.spec.d.ts +1 -0
- package/lib/test/common/utxobased/engine/ServerStates.spec.d.ts +1 -0
- package/lib/test/common/utxobased/keymanager/utxopicker/decimalFeeRate.spec.d.ts +1 -0
- package/lib/test/common/utxobased/keymanager/utxopicker/utils.spec.d.ts +1 -0
- package/package.json +1 -1
|
@@ -18,9 +18,9 @@ const currencyInfo = {
|
|
|
18
18
|
walletType: 'wallet:pivx',
|
|
19
19
|
|
|
20
20
|
// Explorers:
|
|
21
|
-
addressExplorer: 'https://
|
|
22
|
-
blockExplorer: 'https://
|
|
23
|
-
transactionExplorer: 'https://
|
|
21
|
+
addressExplorer: 'https://explorer.duddino.com/address/%s',
|
|
22
|
+
blockExplorer: 'https://explorer.duddino.com/block/%s',
|
|
23
|
+
transactionExplorer: 'https://explorer.duddino.com/tx/%s',
|
|
24
24
|
|
|
25
25
|
denominations: [
|
|
26
26
|
{
|
|
@@ -34,7 +34,7 @@ const currencyInfo = {
|
|
|
34
34
|
..._commonInfo.legacyMemoInfo,
|
|
35
35
|
defaultSettings: {
|
|
36
36
|
customFeeSettings: ['satPerByte'],
|
|
37
|
-
blockbookServers: ['wss://pivx-eusa1.edge.app'
|
|
37
|
+
blockbookServers: ['wss://pivx-eusa1.edge.app'],
|
|
38
38
|
enableCustomServers: false
|
|
39
39
|
},
|
|
40
40
|
displayName: 'PIVX',
|
|
@@ -44,7 +44,7 @@ const currencyInfo = {
|
|
|
44
44
|
const engineInfo = {
|
|
45
45
|
serverConfigs: [
|
|
46
46
|
{
|
|
47
|
-
type: 'blockbook
|
|
47
|
+
type: 'blockbook',
|
|
48
48
|
uris: ['https://pivx-wusa1.edge.app']
|
|
49
49
|
},
|
|
50
50
|
{
|
|
@@ -6,7 +6,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
6
6
|
function accumulative(args) {
|
|
7
7
|
const { utxos, targets, feeRate, changeScript } = args
|
|
8
8
|
|
|
9
|
-
if (!isFinite(utils.
|
|
9
|
+
if (!isFinite(utils.feeRateOrNaN(feeRate))) {
|
|
10
10
|
throw new Error('No rate provided')
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -24,7 +24,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
24
24
|
const utxo = utxos[i]
|
|
25
25
|
|
|
26
26
|
// skip detrimental input
|
|
27
|
-
const utxoFee = feeRate
|
|
27
|
+
const utxoFee = utils.feeForBytes(feeRate, utils.inputBytes(utxo))
|
|
28
28
|
if (utxoFee > utxo.value) {
|
|
29
29
|
if (i === utxos.length - 1) {
|
|
30
30
|
break
|
|
@@ -37,7 +37,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
37
37
|
inValue += utxo.value
|
|
38
38
|
|
|
39
39
|
const bytes = utils.transactionBytes(inputs, outputs)
|
|
40
|
-
const fee = bytes
|
|
40
|
+
const fee = utils.feeForBytes(feeRate, bytes)
|
|
41
41
|
|
|
42
42
|
// go again?
|
|
43
43
|
if (inValue < targetValue + fee) continue
|
|
@@ -47,7 +47,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
47
47
|
|
|
48
48
|
return {
|
|
49
49
|
changeUsed: false,
|
|
50
|
-
fee:
|
|
50
|
+
fee: utils.feeForBytes(feeRate, utils.transactionBytes(inputs, outputs)),
|
|
51
51
|
inputs
|
|
52
52
|
}
|
|
53
53
|
} exports.accumulative = accumulative;
|
|
@@ -7,7 +7,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
7
7
|
function forceUseUtxo(args) {
|
|
8
8
|
const { utxos, useUtxos, targets, feeRate, changeScript } = args
|
|
9
9
|
|
|
10
|
-
if (!isFinite(utils.
|
|
10
|
+
if (!isFinite(utils.feeRateOrNaN(feeRate))) {
|
|
11
11
|
throw new Error('No rate provided')
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -21,7 +21,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
21
21
|
let inValue = inputs.reduce((n, { value }) => n + value, 0)
|
|
22
22
|
const targetValue = utils.sumOrNaN(targets)
|
|
23
23
|
const bytes = utils.transactionBytes(inputs, outputs)
|
|
24
|
-
const fee = bytes
|
|
24
|
+
const fee = utils.feeForBytes(feeRate, bytes)
|
|
25
25
|
// if the new feeRate is already covered by lowering the change amount, return
|
|
26
26
|
if (inValue >= targetValue + fee) {
|
|
27
27
|
return utils.finalize(inputs, outputs, feeRate, changeScript)
|
|
@@ -31,7 +31,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
31
31
|
const utxo = utxos[i]
|
|
32
32
|
|
|
33
33
|
// skip detrimental input
|
|
34
|
-
const utxoFee = feeRate
|
|
34
|
+
const utxoFee = utils.feeForBytes(feeRate, utils.inputBytes(utxo))
|
|
35
35
|
if (utxoFee > utxo.value) {
|
|
36
36
|
if (i === utxos.length - 1) {
|
|
37
37
|
break
|
|
@@ -44,7 +44,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
44
44
|
inValue += utxo.value
|
|
45
45
|
|
|
46
46
|
const bytes = utils.transactionBytes(inputs, outputs)
|
|
47
|
-
const fee = bytes
|
|
47
|
+
const fee = utils.feeForBytes(feeRate, bytes)
|
|
48
48
|
|
|
49
49
|
// go again?
|
|
50
50
|
if (inValue < targetValue + fee) continue
|
|
@@ -54,7 +54,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
54
54
|
|
|
55
55
|
return {
|
|
56
56
|
changeUsed: false,
|
|
57
|
-
fee:
|
|
57
|
+
fee: utils.feeForBytes(feeRate, utils.transactionBytes(inputs, outputs)),
|
|
58
58
|
inputs
|
|
59
59
|
}
|
|
60
60
|
} exports.forceUseUtxo = forceUseUtxo;
|
|
@@ -10,7 +10,7 @@ var _utils = require('./utils'); var utils = _interopRequireWildcard(_utils);
|
|
|
10
10
|
scriptPubkey: Buffer.from(target.script, 'hex')
|
|
11
11
|
}))
|
|
12
12
|
|
|
13
|
-
const fee =
|
|
13
|
+
const fee = utils.feeForBytes(feeRate, utils.transactionBytes(utxos, outputs))
|
|
14
14
|
targets[0].value -= fee
|
|
15
15
|
outputs[0].value -= fee
|
|
16
16
|
|
|
@@ -73,7 +73,7 @@ const scriptSizeMap = (() => {
|
|
|
73
73
|
} exports.outputBytes = outputBytes;
|
|
74
74
|
|
|
75
75
|
function dustThreshold(output, feeRate) {
|
|
76
|
-
return outputBytes(output)
|
|
76
|
+
return feeForBytes(feeRate, outputBytes(output))
|
|
77
77
|
} exports.dustThreshold = dustThreshold;
|
|
78
78
|
|
|
79
79
|
function witnessCount(inputs) {
|
|
@@ -122,6 +122,30 @@ function witnessCount(inputs) {
|
|
|
122
122
|
return v
|
|
123
123
|
} exports.uintOrNaN = uintOrNaN;
|
|
124
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Validates a fee rate in satoshis per byte. Fee rates may be fractional,
|
|
127
|
+
* unlike the satoshi values they produce: a rate is always multiplied by a
|
|
128
|
+
* byte count and rounded up before it becomes a satoshi amount.
|
|
129
|
+
*/
|
|
130
|
+
function feeRateOrNaN(v) {
|
|
131
|
+
if (!isFinite(v)) return NaN
|
|
132
|
+
if (v < 0) return NaN
|
|
133
|
+
return v
|
|
134
|
+
} exports.feeRateOrNaN = feeRateOrNaN;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Returns the whole number of satoshis required to pay for `bytes` at
|
|
138
|
+
* `feeRate` satoshis per byte. Always rounds up, so a fractional rate can
|
|
139
|
+
* never produce a fractional satoshi amount and can never underpay.
|
|
140
|
+
*/
|
|
141
|
+
function feeForBytes(feeRate, bytes) {
|
|
142
|
+
// Multiplying a fractional rate carries floating point noise: `1.1 * 10` is
|
|
143
|
+
// 11.000000000000002, which would round an exact satoshi amount up to the
|
|
144
|
+
// next satoshi. Snap the product back to 12 significant digits first, which
|
|
145
|
+
// is far more precision than any real fee needs, but well short of the noise.
|
|
146
|
+
return Math.ceil(parseFloat((feeRate * bytes).toPrecision(12)))
|
|
147
|
+
} exports.feeForBytes = feeForBytes;
|
|
148
|
+
|
|
125
149
|
function sumForgiving(range) {
|
|
126
150
|
return range.reduce((a, x) => a + (isFinite(x.value) ? x.value : 0), 0)
|
|
127
151
|
} exports.sumForgiving = sumForgiving;
|
|
@@ -139,7 +163,7 @@ function witnessCount(inputs) {
|
|
|
139
163
|
const inValue = sumOrNaN(inputs)
|
|
140
164
|
const outValue = sumOrNaN(outputs)
|
|
141
165
|
let txSize = transactionBytes(inputs, outputs)
|
|
142
|
-
let fee =
|
|
166
|
+
let fee = feeForBytes(feeRate, txSize)
|
|
143
167
|
|
|
144
168
|
const changeValue = inValue - (outValue + fee)
|
|
145
169
|
const changeOutput = {
|
|
@@ -149,7 +173,7 @@ function witnessCount(inputs) {
|
|
|
149
173
|
}
|
|
150
174
|
const changeOutputSize = outputBytes(changeOutput)
|
|
151
175
|
txSize += changeOutputSize
|
|
152
|
-
const changeFee = feeRate
|
|
176
|
+
const changeFee = feeForBytes(feeRate, changeOutputSize)
|
|
153
177
|
changeOutput.value -= changeFee
|
|
154
178
|
let changeUsed = false
|
|
155
179
|
if (changeOutput.value > dustThreshold(changeOutput, feeRate)) {
|
|
@@ -177,8 +177,16 @@ var _Socket = require('./Socket');
|
|
|
177
177
|
|
|
178
178
|
|
|
179
179
|
{
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
try {
|
|
181
|
+
const value = yield { ...message }
|
|
182
|
+
deferred.resolve(value)
|
|
183
|
+
} catch (error) {
|
|
184
|
+
// The socket reports a failed request (an error response, the
|
|
185
|
+
// request timeout, the socket closing) by throwing into this
|
|
186
|
+
// generator. Without this catch the deferred stays pending forever
|
|
187
|
+
// and the caller hangs instead of seeing the failure.
|
|
188
|
+
deferred.reject(error)
|
|
189
|
+
}
|
|
182
190
|
return false
|
|
183
191
|
}
|
|
184
192
|
const generator = taskGeneratorFn()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const INFO_SERVER_URI = "https://info1.edge.app";
|
|
2
2
|
export declare const FEES_PATH = "fees.json";
|
|
3
3
|
export declare const MAX_FEE = 999999999;
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const FEE_RATE_DECIMALS = 3;
|
|
5
5
|
export declare const MAX_HIGH_DELAY = 200;
|
|
6
6
|
export declare const MAX_STANDARD_DELAY = 6;
|
|
7
7
|
export declare const MIN_STANDARD_DELAY = 2;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate the sat/vB fee rate for a transaction that replaces another by fee:
|
|
3
|
+
* double the rate the replaced transaction paid.
|
|
4
|
+
*
|
|
5
|
+
* The rate rounds up to FEE_RATE_DECIMALS places. Rounding up means the
|
|
6
|
+
* replacement never pays less than double, and a positive rate never rounds
|
|
7
|
+
* down to zero, which the UTXO picker would accept as a valid rate. Rounding
|
|
8
|
+
* to a fixed number of places keeps the rate readable where it is reported as
|
|
9
|
+
* `feeRateUsed`.
|
|
10
|
+
*
|
|
11
|
+
* @param replacedFee The fee the replaced transaction paid, in satoshis
|
|
12
|
+
* @param replacedVBytes The replaced transaction's virtual size
|
|
13
|
+
* @returns {number}
|
|
14
|
+
*/
|
|
15
|
+
export declare const calcReplacementFeeRate: (replacedFee: number, replacedVBytes: number) => number;
|
|
@@ -116,7 +116,13 @@ export interface EngineInfo {
|
|
|
116
116
|
txSpecificHandling?: (tx: TransactionData, specialTx: unknown) => TransactionData;
|
|
117
117
|
}
|
|
118
118
|
export interface ServerConfig {
|
|
119
|
-
|
|
119
|
+
/**
|
|
120
|
+
* - `blockbook`: a public Blockbook HTTP server. No credentials are sent.
|
|
121
|
+
* - `blockbook-nownode`: a NOWNodes Blockbook HTTP server. Requests carry
|
|
122
|
+
* the `nowNodesApiKey` init option as the `api-key` header, and the
|
|
123
|
+
* server is skipped when no key is configured.
|
|
124
|
+
*/
|
|
125
|
+
type: 'blockbook' | 'blockbook-nownode';
|
|
120
126
|
uris: string[];
|
|
121
127
|
}
|
|
122
128
|
/**
|
|
@@ -23,6 +23,11 @@ interface ServerStateConfig {
|
|
|
23
23
|
pluginInfo: PluginInfo;
|
|
24
24
|
pluginState: PluginState;
|
|
25
25
|
walletInfo: SafeWalletInfo;
|
|
26
|
+
/**
|
|
27
|
+
* Upper bound on any single broadcast attempt. Defaults to the same 30
|
|
28
|
+
* seconds the socket layer uses for a request. Exposed for tests.
|
|
29
|
+
*/
|
|
30
|
+
broadcastTimeoutMs?: number;
|
|
26
31
|
}
|
|
27
32
|
export interface ServerStates {
|
|
28
33
|
setPickNextTaskCB: (callback: (uri: string) => AsyncGenerator<WsTask<unknown> | boolean>) => void;
|
|
@@ -46,5 +51,21 @@ export interface ServerStates {
|
|
|
46
51
|
transactionSpecialQueryTask: (serverUri: string, txId: string) => WsTaskGenerator<unknown>;
|
|
47
52
|
utxoListQueryTask: (serverUri: string, address: string) => WsTaskGenerator<AddressUtxosResponse>;
|
|
48
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* How long broadcastTx gives the first wave (our sockets and Edge's own HTTP
|
|
56
|
+
* servers) before it also sends the transaction to the NOWNodes HTTP servers.
|
|
57
|
+
* NOWNodes is a third party, so it should only see a transaction when our own
|
|
58
|
+
* infrastructure has not already carried it. A first wave that fails outright
|
|
59
|
+
* does not wait this long; the second wave fires as soon as it has all failed.
|
|
60
|
+
*/
|
|
61
|
+
export declare const NOWNODES_BROADCAST_DELAY_MS = 2000;
|
|
62
|
+
/**
|
|
63
|
+
* Every broadcast attempt is counted toward "all attempts failed", so every
|
|
64
|
+
* attempt must settle. Sockets already expire a request after 30 seconds
|
|
65
|
+
* (Socket.ts); HTTP has no such bound of its own, and a server that accepts
|
|
66
|
+
* the connection and never answers would otherwise hold the whole broadcast
|
|
67
|
+
* open. This mirrors the socket figure.
|
|
68
|
+
*/
|
|
69
|
+
export declare const BROADCAST_ATTEMPT_TIMEOUT_MS = 30000;
|
|
49
70
|
export declare function makeServerStates(config: ServerStateConfig): ServerStates;
|
|
50
71
|
export {};
|
|
@@ -7,6 +7,18 @@ export declare function dustThreshold(output: Output, feeRate: number): number;
|
|
|
7
7
|
export declare function transactionBytes(inputs: UTXO[], outputs: Output[]): number;
|
|
8
8
|
export declare const transactionSizeFromHex: (hex: string) => number;
|
|
9
9
|
export declare function uintOrNaN(v: number): number;
|
|
10
|
+
/**
|
|
11
|
+
* Validates a fee rate in satoshis per byte. Fee rates may be fractional,
|
|
12
|
+
* unlike the satoshi values they produce: a rate is always multiplied by a
|
|
13
|
+
* byte count and rounded up before it becomes a satoshi amount.
|
|
14
|
+
*/
|
|
15
|
+
export declare function feeRateOrNaN(v: number): number;
|
|
16
|
+
/**
|
|
17
|
+
* Returns the whole number of satoshis required to pay for `bytes` at
|
|
18
|
+
* `feeRate` satoshis per byte. Always rounds up, so a fractional rate can
|
|
19
|
+
* never produce a fractional satoshi amount and can never underpay.
|
|
20
|
+
*/
|
|
21
|
+
export declare function feeForBytes(feeRate: number, bytes: number): number;
|
|
10
22
|
export declare function sumForgiving(range: Array<{
|
|
11
23
|
value: number;
|
|
12
24
|
}>): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "edge-currency-plugins",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.14.0",
|
|
4
4
|
"description": "Edge currency plugins to fetch and process wallet accounts, balances and transactions.",
|
|
5
5
|
"homepage": "https://edge.app/",
|
|
6
6
|
"repository": "https://github.com/EdgeApp/edge-currency-plugins",
|