@ledgerhq/coin-kaspa 1.4.1 → 1.4.2-nightly.20251126023856
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/.unimportedrc.json +2 -1
- package/CHANGELOG.md +13 -0
- package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib/bridge/getTransactionStatus.js +11 -1
- package/lib/bridge/getTransactionStatus.js.map +1 -1
- package/lib/logic/constants.d.ts +7 -0
- package/lib/logic/constants.d.ts.map +1 -0
- package/lib/logic/constants.js +10 -0
- package/lib/logic/constants.js.map +1 -0
- package/lib/logic/scanAddresses.d.ts.map +1 -1
- package/lib/logic/scanAddresses.js +2 -10
- package/lib/logic/scanAddresses.js.map +1 -1
- package/lib/logic/utxos/lib.d.ts +1 -0
- package/lib/logic/utxos/lib.d.ts.map +1 -1
- package/lib/logic/utxos/lib.js +16 -6
- package/lib/logic/utxos/lib.js.map +1 -1
- package/lib/logic/utxos/selection.d.ts.map +1 -1
- package/lib/logic/utxos/selection.js +11 -26
- package/lib/logic/utxos/selection.js.map +1 -1
- package/lib/types/errors.d.ts +6 -0
- package/lib/types/errors.d.ts.map +1 -1
- package/lib/types/errors.js +3 -1
- package/lib/types/errors.js.map +1 -1
- package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib-es/bridge/getTransactionStatus.js +11 -1
- package/lib-es/bridge/getTransactionStatus.js.map +1 -1
- package/lib-es/logic/constants.d.ts +7 -0
- package/lib-es/logic/constants.d.ts.map +1 -0
- package/lib-es/logic/constants.js +7 -0
- package/lib-es/logic/constants.js.map +1 -0
- package/lib-es/logic/scanAddresses.d.ts.map +1 -1
- package/lib-es/logic/scanAddresses.js +2 -10
- package/lib-es/logic/scanAddresses.js.map +1 -1
- package/lib-es/logic/utxos/lib.d.ts +1 -0
- package/lib-es/logic/utxos/lib.d.ts.map +1 -1
- package/lib-es/logic/utxos/lib.js +14 -5
- package/lib-es/logic/utxos/lib.js.map +1 -1
- package/lib-es/logic/utxos/selection.d.ts.map +1 -1
- package/lib-es/logic/utxos/selection.js +8 -23
- package/lib-es/logic/utxos/selection.js.map +1 -1
- package/lib-es/types/errors.d.ts +6 -0
- package/lib-es/types/errors.d.ts.map +1 -1
- package/lib-es/types/errors.js +2 -0
- package/lib-es/types/errors.js.map +1 -1
- package/package.json +7 -8
- package/src/bridge/getTransactionStatus.ts +10 -1
- package/src/logic/constants.ts +8 -0
- package/src/logic/scanAddresses.ts +2 -12
- package/src/logic/tests/utxoSelection.test.ts +30 -3
- package/src/logic/utxos/lib.ts +17 -12
- package/src/logic/utxos/selection.ts +14 -27
- package/src/types/errors.ts +2 -2
package/.unimportedrc.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @ledgerhq/coin-framework
|
|
2
2
|
|
|
3
|
+
## 1.4.2-nightly.20251126023856
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#12725](https://github.com/LedgerHQ/ledger-live/pull/12725) [`8d79026`](https://github.com/LedgerHQ/ledger-live/commit/8d79026c930df5e846388b45c8dc6e06418b08fc) Thanks [@semeano](https://github.com/semeano)! - Slice set of UTXO if the count is greater than 88
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`50aeea1`](https://github.com/LedgerHQ/ledger-live/commit/50aeea1233056e9abff9568eb928927f39e76cff), [`fe81926`](https://github.com/LedgerHQ/ledger-live/commit/fe81926afeb2df8e917e6bd1e4cbab13f09647fd), [`67137eb`](https://github.com/LedgerHQ/ledger-live/commit/67137eb5d7f04dd5f3610fdaa4e463d292654105), [`49ef24c`](https://github.com/LedgerHQ/ledger-live/commit/49ef24cbd1948bfd146af0b20f2128951b2dc170), [`b4a4e16`](https://github.com/LedgerHQ/ledger-live/commit/b4a4e160aae6fd64f944ab25633f6931dc4358d3), [`927ae64`](https://github.com/LedgerHQ/ledger-live/commit/927ae64db0bb04af54e25623655a001a68e0f2d3), [`903ea9c`](https://github.com/LedgerHQ/ledger-live/commit/903ea9cdacf704a0119de2803a4f409b775391a5), [`9251b77`](https://github.com/LedgerHQ/ledger-live/commit/9251b77fcb01709723842f19220a2a41a6fc8f3b), [`02ef98f`](https://github.com/LedgerHQ/ledger-live/commit/02ef98faeb13c182ef255e06a43c39abeb55ecc7), [`6d0c6b2`](https://github.com/LedgerHQ/ledger-live/commit/6d0c6b2eda60049d8eebda5de2c54e8f0be7d009), [`0d33751`](https://github.com/LedgerHQ/ledger-live/commit/0d33751bb2ae599d0d26ce6a8efdbe01757f12fb), [`aadcec6`](https://github.com/LedgerHQ/ledger-live/commit/aadcec66847b800f79452ba1df09149e0a1cb9e8), [`b113920`](https://github.com/LedgerHQ/ledger-live/commit/b11392056bc334fc1813c473569ad3ae7be08045), [`ed8532b`](https://github.com/LedgerHQ/ledger-live/commit/ed8532bad754ca2b5f1788c6e92f4646b775ec79), [`88a5018`](https://github.com/LedgerHQ/ledger-live/commit/88a501871d58c980f18495b5b32012a3eaa9ab2c), [`9659a34`](https://github.com/LedgerHQ/ledger-live/commit/9659a34d9998d5c4dff8618bf6cef7d16403680d)]:
|
|
10
|
+
- @ledgerhq/cryptoassets@13.34.0-nightly.20251126023856
|
|
11
|
+
- @ledgerhq/types-live@6.90.0-nightly.20251126023856
|
|
12
|
+
- @ledgerhq/coin-framework@6.10.0-nightly.20251126023856
|
|
13
|
+
- @ledgerhq/live-env@2.21.1-nightly.20251126023856
|
|
14
|
+
- @ledgerhq/live-network@2.1.2-nightly.20251126023856
|
|
15
|
+
|
|
3
16
|
## 1.4.1
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTransactionStatus.d.ts","sourceRoot":"","sources":["../../src/bridge/getTransactionStatus.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getTransactionStatus.d.ts","sourceRoot":"","sources":["../../src/bridge/getTransactionStatus.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAiBxE,QAAA,MAAM,oBAAoB,YACf,YAAY,eACR,WAAW,KACvB,QAAQ,iBAAiB,CAkF3B,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const errors_1 = require("@ledgerhq/errors");
|
|
4
|
+
const errors_2 = require("../types/errors");
|
|
4
5
|
const bignumber_js_1 = require("bignumber.js");
|
|
5
6
|
const logic_1 = require("../logic");
|
|
6
7
|
const cache_1 = require("@ledgerhq/live-network/cache");
|
|
8
|
+
const constants_1 = require("../logic/constants");
|
|
7
9
|
const getCachedUtxos = (0, cache_1.makeLRUCache)(async (account) => {
|
|
8
10
|
const { compressedPublicKey, chainCode } = (0, logic_1.parseExtendedPublicKey)(Buffer.from(account.xpub, "hex"));
|
|
9
11
|
return await (0, logic_1.scanUtxos)(compressedPublicKey, chainCode);
|
|
@@ -44,9 +46,17 @@ const getTransactionStatus = async (account, transaction) => {
|
|
|
44
46
|
if (transaction.amount.lt(20000000)) {
|
|
45
47
|
errors.dustLimit = new errors_1.DustLimit("");
|
|
46
48
|
}
|
|
49
|
+
if (utxos.length > constants_1.MAX_UTXOS_PER_TX) {
|
|
50
|
+
warnings.amount = new errors_2.ReducedAmountUtxoWarning();
|
|
51
|
+
}
|
|
47
52
|
}
|
|
48
53
|
if (transaction.amount.gt(maxSpendableAmount) || maxSpendableAmount.eq(0)) {
|
|
49
|
-
|
|
54
|
+
if (utxos.length > constants_1.MAX_UTXOS_PER_TX && account.balance.gt(transaction.amount)) {
|
|
55
|
+
errors.amount = new errors_2.UtxoLimitReachedError();
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
errors.amount = new errors_1.NotEnoughBalance();
|
|
59
|
+
}
|
|
50
60
|
}
|
|
51
61
|
if (Object.keys(errors).length === 0) {
|
|
52
62
|
const result = (0, logic_1.selectUtxos)(utxos, transaction.recipient.length > 67, transaction.amount, (0, logic_1.getFeeRate)(transaction).toNumber() || 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTransactionStatus.js","sourceRoot":"","sources":["../../src/bridge/getTransactionStatus.ts"],"names":[],"mappings":";;AAAA,6CAS0B;AAC1B,+CAAyC;AACzC,oCAOkB;AAElB,wDAAqE;
|
|
1
|
+
{"version":3,"file":"getTransactionStatus.js","sourceRoot":"","sources":["../../src/bridge/getTransactionStatus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const MAX_UTXOS_PER_TX: number;
|
|
2
|
+
export declare const DEFAULT_MASS_1_OUTPUT: number;
|
|
3
|
+
export declare const MASS_PER_INPUT: number;
|
|
4
|
+
export declare const MASS_PER_OUTPUT: number;
|
|
5
|
+
export declare const MASS_LIMIT_PER_TX = 100000;
|
|
6
|
+
export declare const MAX_DISCARD: number;
|
|
7
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/logic/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,EAAE,MAAW,CAAC;AAC3C,eAAO,MAAM,qBAAqB,EAAE,MAAY,CAAC;AAEjD,eAAO,MAAM,cAAc,EAAE,MAAa,CAAC;AAC3C,eAAO,MAAM,eAAe,EAAE,MAAY,CAAC;AAE3C,eAAO,MAAM,iBAAiB,SAAU,CAAC;AACzC,eAAO,MAAM,WAAW,EAAE,MAAkB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_DISCARD = exports.MASS_LIMIT_PER_TX = exports.MASS_PER_OUTPUT = exports.MASS_PER_INPUT = exports.DEFAULT_MASS_1_OUTPUT = exports.MAX_UTXOS_PER_TX = void 0;
|
|
4
|
+
exports.MAX_UTXOS_PER_TX = 88;
|
|
5
|
+
exports.DEFAULT_MASS_1_OUTPUT = 506;
|
|
6
|
+
exports.MASS_PER_INPUT = 1118; // Per selected utxo as input, mass increases by this value.
|
|
7
|
+
exports.MASS_PER_OUTPUT = 412; // Per selected utxo as input, mass increases by this value.
|
|
8
|
+
exports.MASS_LIMIT_PER_TX = 100_000; // TX mass must not exceed 100k gram.
|
|
9
|
+
exports.MAX_DISCARD = 2000_0000; // Throw error, if discarded value is higher than this.
|
|
10
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/logic/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,gBAAgB,GAAW,EAAE,CAAC;AAC9B,QAAA,qBAAqB,GAAW,GAAG,CAAC;AAEpC,QAAA,cAAc,GAAW,IAAI,CAAC,CAAC,4DAA4D;AAC3F,QAAA,eAAe,GAAW,GAAG,CAAC,CAAC,4DAA4D;AAE3F,QAAA,iBAAiB,GAAG,OAAO,CAAC,CAAC,qCAAqC;AAClE,QAAA,WAAW,GAAW,SAAS,CAAC,CAAC,uDAAuD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanAddresses.d.ts","sourceRoot":"","sources":["../../src/logic/scanAddresses.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"scanAddresses.d.ts","sourceRoot":"","sources":["../../src/logic/scanAddresses.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAW5D;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,mBAAmB,EAAE,MAAM,EAC3B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAmE3B"}
|
|
@@ -13,7 +13,6 @@ const CHANGE_ADDRESS_TYPE = 1;
|
|
|
13
13
|
const INITIAL_BALANCE = (0, bignumber_js_1.BigNumber)(0);
|
|
14
14
|
const GAP_LIMIT = 20;
|
|
15
15
|
const SCAN_BATCH_SIZE = 200;
|
|
16
|
-
const MAX_TX_INPUTS = 88; // floor (( 100_000 - 918 (def_size with 2 outputs) ) / 1_118 (per_input))
|
|
17
16
|
/**
|
|
18
17
|
* Scans the addresses for an account and retrieves information such as used addresses and the total balance.
|
|
19
18
|
*
|
|
@@ -76,15 +75,8 @@ async function scanAddresses(compressedPublicKey, chainCode, startIndex) {
|
|
|
76
75
|
updateAddressesData(addresses, accountAddresses, type, keepScanning);
|
|
77
76
|
}
|
|
78
77
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
...accountAddresses.usedReceiveAddresses,
|
|
82
|
-
]
|
|
83
|
-
.sort((a, b) => b.balance.minus(a.balance).toNumber())
|
|
84
|
-
.slice(0, MAX_TX_INPUTS)
|
|
85
|
-
.map(utxo => utxo.balance)
|
|
86
|
-
.reduce((acc, v) => acc.plus(v), (0, bignumber_js_1.BigNumber)(0));
|
|
87
|
-
accountAddresses.spendableBalance = spendableBalance;
|
|
78
|
+
// Assume all the balance could be sent, there are not "locked" coins.
|
|
79
|
+
accountAddresses.spendableBalance = accountAddresses.totalBalance;
|
|
88
80
|
return accountAddresses;
|
|
89
81
|
}
|
|
90
82
|
exports.scanAddresses = scanAddresses;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanAddresses.js","sourceRoot":"","sources":["../../src/logic/scanAddresses.ts"],"names":[],"mappings":";;;;;;AAAA,+CAAyC;AAEzC,oDAAiC;AACjC,wCAAyE;AAEzE,+BAA+B;AAC/B,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,eAAe,GAAG,IAAA,wBAAS,EAAC,CAAC,CAAC,CAAC;AACrC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B
|
|
1
|
+
{"version":3,"file":"scanAddresses.js","sourceRoot":"","sources":["../../src/logic/scanAddresses.ts"],"names":[],"mappings":"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"}
|
package/lib/logic/utxos/lib.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ import { KaspaUtxo } from "../../types";
|
|
|
3
3
|
export declare const calcMaxSpendableAmount: (utxos: KaspaUtxo[], isEcdsaRecipient: boolean, feerate?: number) => BigNumber;
|
|
4
4
|
export declare const sumBigNumber: (values: BigNumber[]) => BigNumber;
|
|
5
5
|
export declare const sumUtxoAmounts: (utxos: KaspaUtxo[]) => BigNumber;
|
|
6
|
+
export declare const sortUtxos: (utxos: KaspaUtxo[]) => void;
|
|
6
7
|
//# sourceMappingURL=lib.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../../src/logic/utxos/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../../src/logic/utxos/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,eAAO,MAAM,sBAAsB,UAC1B,SAAS,EAAE,oBACA,OAAO,YAChB,MAAM,KACd,SAgBF,CAAC;AAEF,eAAO,MAAM,YAAY,WAAY,SAAS,EAAE,KAAG,SAElD,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,SAAS,EAAE,KAAG,SAEnD,CAAC;AAEF,eAAO,MAAM,SAAS,UAAW,SAAS,EAAE,SAU3C,CAAC"}
|
package/lib/logic/utxos/lib.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.sumUtxoAmounts = exports.sumBigNumber = exports.calcMaxSpendableAmount = void 0;
|
|
3
|
+
exports.sortUtxos = exports.sumUtxoAmounts = exports.sumBigNumber = exports.calcMaxSpendableAmount = void 0;
|
|
4
4
|
const bignumber_js_1 = require("bignumber.js");
|
|
5
|
-
const
|
|
6
|
-
const DEFAULT_MASS_1_OUTPUT = 506;
|
|
7
|
-
const MAX_UTXOS_PER_TX = 88;
|
|
5
|
+
const constants_1 = require("../constants");
|
|
8
6
|
const calcMaxSpendableAmount = (utxos, isEcdsaRecipient, feerate = 1) => {
|
|
9
|
-
|
|
7
|
+
(0, exports.sortUtxos)(utxos);
|
|
8
|
+
const utxoSubset = utxos.slice(0, constants_1.MAX_UTXOS_PER_TX);
|
|
9
|
+
const maxInputAmount = (0, exports.sumUtxoAmounts)(utxoSubset);
|
|
10
10
|
// storage mass can be neglected here
|
|
11
11
|
// max compute mass for one output and 88 inputs is 98901
|
|
12
|
-
let maxSpendableAmount = maxInputAmount.minus((0, bignumber_js_1.BigNumber)(DEFAULT_MASS_1_OUTPUT +
|
|
12
|
+
let maxSpendableAmount = maxInputAmount.minus((0, bignumber_js_1.BigNumber)(constants_1.DEFAULT_MASS_1_OUTPUT + utxoSubset.length * constants_1.MASS_PER_INPUT).times(feerate));
|
|
13
13
|
if (isEcdsaRecipient) {
|
|
14
14
|
maxSpendableAmount = maxSpendableAmount.minus((0, bignumber_js_1.BigNumber)(11));
|
|
15
15
|
}
|
|
@@ -24,4 +24,14 @@ const sumUtxoAmounts = (utxos) => {
|
|
|
24
24
|
return utxos.reduce((acc, v) => acc.plus(v.utxoEntry.amount), (0, bignumber_js_1.BigNumber)(0));
|
|
25
25
|
};
|
|
26
26
|
exports.sumUtxoAmounts = sumUtxoAmounts;
|
|
27
|
+
const sortUtxos = (utxos) => {
|
|
28
|
+
utxos.sort((a, b) => {
|
|
29
|
+
const transactionComparison = a.utxoEntry.blockDaaScore.localeCompare(b.utxoEntry.blockDaaScore);
|
|
30
|
+
if (transactionComparison !== 0) {
|
|
31
|
+
return transactionComparison;
|
|
32
|
+
}
|
|
33
|
+
return a.utxoEntry.amount.minus(b.utxoEntry.amount).toNumber();
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
exports.sortUtxos = sortUtxos;
|
|
27
37
|
//# sourceMappingURL=lib.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../../src/logic/utxos/lib.ts"],"names":[],"mappings":";;;AAAA,+CAAyC;
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../../src/logic/utxos/lib.ts"],"names":[],"mappings":";;;AAAA,+CAAyC;AAEzC,4CAAuF;AAEhF,MAAM,sBAAsB,GAAG,CACpC,KAAkB,EAClB,gBAAyB,EACzB,UAAkB,CAAC,EACR,EAAE;IACb,IAAA,iBAAS,EAAC,KAAK,CAAC,CAAC;IACjB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,4BAAgB,CAAC,CAAC;IACpD,MAAM,cAAc,GAAG,IAAA,sBAAc,EAAC,UAAU,CAAC,CAAC;IAElD,qCAAqC;IACrC,yDAAyD;IACzD,IAAI,kBAAkB,GAAG,cAAc,CAAC,KAAK,CAC3C,IAAA,wBAAS,EAAC,iCAAqB,GAAG,UAAU,CAAC,MAAM,GAAG,0BAAc,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CACrF,CAAC;IAEF,IAAI,gBAAgB,EAAE,CAAC;QACrB,kBAAkB,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAA,wBAAS,EAAC,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAA,wBAAS,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC;AACtE,CAAC,CAAC;AApBW,QAAA,sBAAsB,0BAoBjC;AAEK,MAAM,YAAY,GAAG,CAAC,MAAmB,EAAa,EAAE;IAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAA,wBAAS,EAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC;AAFW,QAAA,YAAY,gBAEvB;AAEK,MAAM,cAAc,GAAG,CAAC,KAAkB,EAAa,EAAE;IAC9D,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAA,wBAAS,EAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC,CAAC;AAFW,QAAA,cAAc,kBAEzB;AAEK,MAAM,SAAS,GAAG,CAAC,KAAkB,EAAE,EAAE;IAC9C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAClB,MAAM,qBAAqB,GAAG,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,aAAa,CACnE,CAAC,CAAC,SAAS,CAAC,aAAa,CAC1B,CAAC;QACF,IAAI,qBAAqB,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QACD,OAAO,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAVW,QAAA,SAAS,aAUpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/logic/utxos/selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/logic/utxos/selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAWxC,eAAO,MAAM,WAAW,UACf,SAAS,EAAE,oBACA,OAAO,UACjB,SAAS,YACR,MAAM;kBACE,SAAS;SAAO,SAAS;WAAS,SAAS,EAAE;CAqE/D,CAAC"}
|
|
@@ -4,25 +4,19 @@ exports.selectUtxos = void 0;
|
|
|
4
4
|
const bignumber_js_1 = require("bignumber.js");
|
|
5
5
|
const massCalcluation_1 = require("../massCalcluation");
|
|
6
6
|
const lib_1 = require("./lib");
|
|
7
|
-
const
|
|
8
|
-
const MASS_PER_INPUT = 1118; // Per selected utxo as input, mass increases by this value.
|
|
9
|
-
const MASS_PER_OUTPUT = 412; // Per selected utxo as input, mass increases by this value.
|
|
10
|
-
const MAX_UTXOS_PER_TX = 88; // 88 is the maximum of utxo inputs in one TX.
|
|
11
|
-
const MAX_DISCARD = 2000_0000; // Throw error, if discarded value is higher than this.
|
|
7
|
+
const constants_1 = require("../constants");
|
|
12
8
|
const selectUtxos = (utxos, isEcdsaRecipient, amount, feerate = 1) => {
|
|
13
9
|
// always sort utxos
|
|
14
|
-
sortUtxos(utxos);
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// First check in general, if there is enough amount in the UTXOs.
|
|
20
|
-
if ((0, lib_1.calcMaxSpendableAmount)(utxos, isEcdsaRecipient, feerate).isLessThan(amount)) {
|
|
10
|
+
(0, lib_1.sortUtxos)(utxos);
|
|
11
|
+
// UTXOs are already sorted (FIFO), but need to be sliced, as 88 is the maximum for a transaction.
|
|
12
|
+
const utxoSubset = utxos.slice(0, constants_1.MAX_UTXOS_PER_TX);
|
|
13
|
+
// Now check in general, if there is enough amount in the UTXOs.
|
|
14
|
+
if ((0, lib_1.calcMaxSpendableAmount)(utxoSubset, isEcdsaRecipient, feerate).isLessThan(amount)) {
|
|
21
15
|
throw new Error(`UTXO total amount is not sufficient for sending amount ${amount}`);
|
|
22
16
|
}
|
|
23
17
|
// Find a sufficient slice.
|
|
24
|
-
for (let i = 0; i <
|
|
25
|
-
const selectedUtxos =
|
|
18
|
+
for (let i = 0; i < utxoSubset.length; i++) {
|
|
19
|
+
const selectedUtxos = utxoSubset.slice(0, i + 1);
|
|
26
20
|
const selectedUtxoAmount = (0, lib_1.sumUtxoAmounts)(selectedUtxos);
|
|
27
21
|
// calculate absolute min fee for regular TX with 1 outputs and the given feerate.
|
|
28
22
|
const minMass = (0, massCalcluation_1.calcComputeMass)(i + 1, false, isEcdsaRecipient);
|
|
@@ -42,17 +36,17 @@ const selectUtxos = (utxos, isEcdsaRecipient, amount, feerate = 1) => {
|
|
|
42
36
|
: 0;
|
|
43
37
|
// If storage mass exceeds the limit or the change amount is negative ( 2 outputs not possible )
|
|
44
38
|
// Need to pick another UTXO or discard the change.
|
|
45
|
-
if (changeAmount.isLessThan(0) || storageMass > MASS_LIMIT_PER_TX) {
|
|
39
|
+
if (changeAmount.isLessThan(0) || storageMass > constants_1.MASS_LIMIT_PER_TX) {
|
|
46
40
|
// Picking a further UTXO means a higher mass (one input and output) and thus a higher fee.
|
|
47
41
|
// Check if the fee is not higher, than just discarding the change.
|
|
48
|
-
const isWorthPickingAnotherUtxo = changeAmount.isGreaterThan((0, bignumber_js_1.BigNumber)((MASS_PER_INPUT + MASS_PER_OUTPUT) * feerate));
|
|
42
|
+
const isWorthPickingAnotherUtxo = changeAmount.isGreaterThan((0, bignumber_js_1.BigNumber)((constants_1.MASS_PER_INPUT + constants_1.MASS_PER_OUTPUT) * feerate));
|
|
49
43
|
if (i + 1 < utxos.length && isWorthPickingAnotherUtxo) {
|
|
50
44
|
// There is one more UTXO and it is cheaper to pick than discard the change.
|
|
51
45
|
continue;
|
|
52
46
|
}
|
|
53
47
|
else {
|
|
54
48
|
// Change needs to be discarded as fee to keep mass low enough.
|
|
55
|
-
if (changeAmount.isGreaterThan(MAX_DISCARD)) {
|
|
49
|
+
if (changeAmount.isGreaterThan(constants_1.MAX_DISCARD)) {
|
|
56
50
|
throw new Error(`Unable to select UTXOs. Change ${changeAmount} Sompis is too high to be discarded.`);
|
|
57
51
|
}
|
|
58
52
|
changeAmount = (0, bignumber_js_1.BigNumber)(0);
|
|
@@ -68,13 +62,4 @@ const selectUtxos = (utxos, isEcdsaRecipient, amount, feerate = 1) => {
|
|
|
68
62
|
throw new Error("UTXOs can't be determined to fulfill the specified amount");
|
|
69
63
|
};
|
|
70
64
|
exports.selectUtxos = selectUtxos;
|
|
71
|
-
const sortUtxos = (utxos) => {
|
|
72
|
-
utxos.sort((a, b) => {
|
|
73
|
-
const transactionComparison = a.utxoEntry.blockDaaScore.localeCompare(b.utxoEntry.blockDaaScore);
|
|
74
|
-
if (transactionComparison !== 0) {
|
|
75
|
-
return transactionComparison;
|
|
76
|
-
}
|
|
77
|
-
return a.utxoEntry.amount.minus(b.utxoEntry.amount).toNumber();
|
|
78
|
-
});
|
|
79
|
-
};
|
|
80
65
|
//# sourceMappingURL=selection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.js","sourceRoot":"","sources":["../../../src/logic/utxos/selection.ts"],"names":[],"mappings":";;;AAAA,+CAAyC;AAEzC,wDAAsE;AACtE,+
|
|
1
|
+
{"version":3,"file":"selection.js","sourceRoot":"","sources":["../../../src/logic/utxos/selection.ts"],"names":[],"mappings":"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"}
|
package/lib/types/errors.d.ts
CHANGED
|
@@ -7,4 +7,10 @@ export declare const TransactionMassExceededError: import("@ledgerhq/errors/lib/
|
|
|
7
7
|
export declare const EmptyRecipientError: import("@ledgerhq/errors/lib/helpers").LedgerErrorConstructor<{
|
|
8
8
|
[key: string]: unknown;
|
|
9
9
|
}>;
|
|
10
|
+
export declare const ReducedAmountUtxoWarning: import("@ledgerhq/errors/lib/helpers").LedgerErrorConstructor<{
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const UtxoLimitReachedError: import("@ledgerhq/errors/lib/helpers").LedgerErrorConstructor<{
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}>;
|
|
10
16
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB;;EAA8C,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB;;EAA8C,CAAC;AAC7E,eAAO,MAAM,4BAA4B;;EAAyD,CAAC;AACnG,eAAO,MAAM,mBAAmB;;EAAgD,CAAC;AACjF,eAAO,MAAM,wBAAwB;;EAAqD,CAAC;AAC3F,eAAO,MAAM,qBAAqB;;EAAkD,CAAC"}
|
package/lib/types/errors.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EmptyRecipientError = exports.TransactionMassExceededError = exports.NotEnoughFeeError = void 0;
|
|
3
|
+
exports.UtxoLimitReachedError = exports.ReducedAmountUtxoWarning = exports.EmptyRecipientError = exports.TransactionMassExceededError = exports.NotEnoughFeeError = void 0;
|
|
4
4
|
const errors_1 = require("@ledgerhq/errors");
|
|
5
5
|
exports.NotEnoughFeeError = (0, errors_1.createCustomErrorClass)("NotEnoughFeeError");
|
|
6
6
|
exports.TransactionMassExceededError = (0, errors_1.createCustomErrorClass)("TransactionMassExceededError");
|
|
7
7
|
exports.EmptyRecipientError = (0, errors_1.createCustomErrorClass)("EmptyRecipientError");
|
|
8
|
+
exports.ReducedAmountUtxoWarning = (0, errors_1.createCustomErrorClass)("ReducedAmountUtxoWarning");
|
|
9
|
+
exports.UtxoLimitReachedError = (0, errors_1.createCustomErrorClass)("UtxoLimitReachedError");
|
|
8
10
|
//# sourceMappingURL=errors.js.map
|
package/lib/types/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":";;;AAAA,6CAA0D;AAE7C,QAAA,iBAAiB,GAAG,IAAA,+BAAsB,EAAC,mBAAmB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":";;;AAAA,6CAA0D;AAE7C,QAAA,iBAAiB,GAAG,IAAA,+BAAsB,EAAC,mBAAmB,CAAC,CAAC;AAChE,QAAA,4BAA4B,GAAG,IAAA,+BAAsB,EAAC,8BAA8B,CAAC,CAAC;AACtF,QAAA,mBAAmB,GAAG,IAAA,+BAAsB,EAAC,qBAAqB,CAAC,CAAC;AACpE,QAAA,wBAAwB,GAAG,IAAA,+BAAsB,EAAC,0BAA0B,CAAC,CAAC;AAC9E,QAAA,qBAAqB,GAAG,IAAA,+BAAsB,EAAC,uBAAuB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTransactionStatus.d.ts","sourceRoot":"","sources":["../../src/bridge/getTransactionStatus.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getTransactionStatus.d.ts","sourceRoot":"","sources":["../../src/bridge/getTransactionStatus.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAiBxE,QAAA,MAAM,oBAAoB,YACf,YAAY,eACR,WAAW,KACvB,QAAQ,iBAAiB,CAkF3B,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { AmountRequired, DustLimit, FeeNotLoaded, FeeRequired, FeeTooHigh, InvalidAddress, NotEnoughBalance, RecipientRequired, } from "@ledgerhq/errors";
|
|
2
|
+
import { ReducedAmountUtxoWarning, UtxoLimitReachedError } from "../types/errors";
|
|
2
3
|
import { BigNumber } from "bignumber.js";
|
|
3
4
|
import { calcMaxSpendableAmount, getFeeRate, isValidKaspaAddress, parseExtendedPublicKey, scanUtxos, selectUtxos, } from "../logic";
|
|
4
5
|
import { makeLRUCache, minutes } from "@ledgerhq/live-network/cache";
|
|
6
|
+
import { MAX_UTXOS_PER_TX } from "../logic/constants";
|
|
5
7
|
const getCachedUtxos = makeLRUCache(async (account) => {
|
|
6
8
|
const { compressedPublicKey, chainCode } = parseExtendedPublicKey(Buffer.from(account.xpub, "hex"));
|
|
7
9
|
return await scanUtxos(compressedPublicKey, chainCode);
|
|
@@ -42,9 +44,17 @@ const getTransactionStatus = async (account, transaction) => {
|
|
|
42
44
|
if (transaction.amount.lt(20000000)) {
|
|
43
45
|
errors.dustLimit = new DustLimit("");
|
|
44
46
|
}
|
|
47
|
+
if (utxos.length > MAX_UTXOS_PER_TX) {
|
|
48
|
+
warnings.amount = new ReducedAmountUtxoWarning();
|
|
49
|
+
}
|
|
45
50
|
}
|
|
46
51
|
if (transaction.amount.gt(maxSpendableAmount) || maxSpendableAmount.eq(0)) {
|
|
47
|
-
|
|
52
|
+
if (utxos.length > MAX_UTXOS_PER_TX && account.balance.gt(transaction.amount)) {
|
|
53
|
+
errors.amount = new UtxoLimitReachedError();
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
errors.amount = new NotEnoughBalance();
|
|
57
|
+
}
|
|
48
58
|
}
|
|
49
59
|
if (Object.keys(errors).length === 0) {
|
|
50
60
|
const result = selectUtxos(utxos, transaction.recipient.length > 67, transaction.amount, getFeeRate(transaction).toNumber() || 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTransactionStatus.js","sourceRoot":"","sources":["../../src/bridge/getTransactionStatus.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,SAAS,EACT,YAAY,EACZ,WAAW,EACX,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EACL,sBAAsB,EACtB,UAAU,EACV,mBAAmB,EACnB,sBAAsB,EACtB,SAAS,EACT,WAAW,GACZ,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"getTransactionStatus.js","sourceRoot":"","sources":["../../src/bridge/getTransactionStatus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const MAX_UTXOS_PER_TX: number;
|
|
2
|
+
export declare const DEFAULT_MASS_1_OUTPUT: number;
|
|
3
|
+
export declare const MASS_PER_INPUT: number;
|
|
4
|
+
export declare const MASS_PER_OUTPUT: number;
|
|
5
|
+
export declare const MASS_LIMIT_PER_TX = 100000;
|
|
6
|
+
export declare const MAX_DISCARD: number;
|
|
7
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/logic/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,EAAE,MAAW,CAAC;AAC3C,eAAO,MAAM,qBAAqB,EAAE,MAAY,CAAC;AAEjD,eAAO,MAAM,cAAc,EAAE,MAAa,CAAC;AAC3C,eAAO,MAAM,eAAe,EAAE,MAAY,CAAC;AAE3C,eAAO,MAAM,iBAAiB,SAAU,CAAC;AACzC,eAAO,MAAM,WAAW,EAAE,MAAkB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const MAX_UTXOS_PER_TX = 88;
|
|
2
|
+
export const DEFAULT_MASS_1_OUTPUT = 506;
|
|
3
|
+
export const MASS_PER_INPUT = 1118; // Per selected utxo as input, mass increases by this value.
|
|
4
|
+
export const MASS_PER_OUTPUT = 412; // Per selected utxo as input, mass increases by this value.
|
|
5
|
+
export const MASS_LIMIT_PER_TX = 100_000; // TX mass must not exceed 100k gram.
|
|
6
|
+
export const MAX_DISCARD = 2000_0000; // Throw error, if discarded value is higher than this.
|
|
7
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/logic/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAW,EAAE,CAAC;AAC3C,MAAM,CAAC,MAAM,qBAAqB,GAAW,GAAG,CAAC;AAEjD,MAAM,CAAC,MAAM,cAAc,GAAW,IAAI,CAAC,CAAC,4DAA4D;AACxG,MAAM,CAAC,MAAM,eAAe,GAAW,GAAG,CAAC,CAAC,4DAA4D;AAExG,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,qCAAqC;AAC/E,MAAM,CAAC,MAAM,WAAW,GAAW,SAAS,CAAC,CAAC,uDAAuD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanAddresses.d.ts","sourceRoot":"","sources":["../../src/logic/scanAddresses.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"scanAddresses.d.ts","sourceRoot":"","sources":["../../src/logic/scanAddresses.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAW5D;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,mBAAmB,EAAE,MAAM,EAC3B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAmE3B"}
|
|
@@ -7,7 +7,6 @@ const CHANGE_ADDRESS_TYPE = 1;
|
|
|
7
7
|
const INITIAL_BALANCE = BigNumber(0);
|
|
8
8
|
const GAP_LIMIT = 20;
|
|
9
9
|
const SCAN_BATCH_SIZE = 200;
|
|
10
|
-
const MAX_TX_INPUTS = 88; // floor (( 100_000 - 918 (def_size with 2 outputs) ) / 1_118 (per_input))
|
|
11
10
|
/**
|
|
12
11
|
* Scans the addresses for an account and retrieves information such as used addresses and the total balance.
|
|
13
12
|
*
|
|
@@ -70,15 +69,8 @@ export async function scanAddresses(compressedPublicKey, chainCode, startIndex)
|
|
|
70
69
|
updateAddressesData(addresses, accountAddresses, type, keepScanning);
|
|
71
70
|
}
|
|
72
71
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
...accountAddresses.usedReceiveAddresses,
|
|
76
|
-
]
|
|
77
|
-
.sort((a, b) => b.balance.minus(a.balance).toNumber())
|
|
78
|
-
.slice(0, MAX_TX_INPUTS)
|
|
79
|
-
.map(utxo => utxo.balance)
|
|
80
|
-
.reduce((acc, v) => acc.plus(v), BigNumber(0));
|
|
81
|
-
accountAddresses.spendableBalance = spendableBalance;
|
|
72
|
+
// Assume all the balance could be sent, there are not "locked" coins.
|
|
73
|
+
accountAddresses.spendableBalance = accountAddresses.totalBalance;
|
|
82
74
|
return accountAddresses;
|
|
83
75
|
}
|
|
84
76
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanAddresses.js","sourceRoot":"","sources":["../../src/logic/scanAddresses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,UAAU,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEzE,+BAA+B;AAC/B,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,eAAe,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AACrC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B
|
|
1
|
+
{"version":3,"file":"scanAddresses.js","sourceRoot":"","sources":["../../src/logic/scanAddresses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,UAAU,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEzE,+BAA+B;AAC/B,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,eAAe,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AACrC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,mBAA2B,EAC3B,SAAiB,EACjB,UAAkB;IAElB,MAAM,UAAU,GAAe,IAAI,UAAU,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC;IAE9E,MAAM,gBAAgB,GAAqB;QACzC,oBAAoB,EAAE,EAAE;QACxB,mBAAmB,EAAE,EAAE;QACvB,iBAAiB,EAAE;YACjB,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,CAAC;YACR,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,KAAK;YACb,SAAS,EAAE,IAAI;SAChB;QACD,kBAAkB,EAAE;YAClB,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,CAAC;YACR,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,KAAK;YACb,SAAS,EAAE,IAAI;SAChB;QACD,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1B,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC;KAC/B,CAAC;IAEF,qEAAqE;IAErE,gDAAgD;IAChD,KAAK,MAAM,IAAI,IAAI,CAAC,oBAAoB,EAAE,mBAAmB,CAAC,EAAE,CAAC;QAC/D,IAAI,YAAY,GAAY,IAAI,CAAC;QAEjC,OAAO,YAAY,EAAE,CAAC;YACpB,MAAM,SAAS,GAAqB,EAAE,CAAC;YACvC,KAAK,IAAI,KAAK,GAAG,UAAU,EAAE,KAAK,GAAG,UAAU,GAAG,eAAe,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC3E,MAAM,cAAc,GAAW,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAClE,SAAS,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,IAAI;oBACV,KAAK;oBACL,OAAO,EAAE,cAAc;oBACvB,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;oBACrB,MAAM,EAAE,KAAK;iBACI,CAAC,CAAC;YACvB,CAAC;YAED,sDAAsD;YACtD,MAAM,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAEvC,iBAAiB;YACjB,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,gBAAgB,CAAC,YAAY,GAAG,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnF,CAAC;YAED,uEAAuE;YACvE,MAAM,oBAAoB,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC;YAEzD,YAAY,GAAG,CAAC,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjE,IAAI,YAAY;gBAAE,UAAU,IAAI,eAAe,CAAC;YAEhD,mBAAmB,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,gBAAgB,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,YAAY,CAAC;IAElE,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,mBAAmB,CAC1B,SAA2B,EAC3B,gBAAkC,EAClC,IAAY,EACZ,YAAqB;IAErB,IAAI,IAAI,KAAK,oBAAoB,EAAE,CAAC;QAClC,gBAAgB,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAErF,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,wBAAwB;YACxB,uDAAuD;YACvD,gBAAgB,CAAC,kBAAkB;gBACjC,SAAS,CACP,SAAS,CAAC,OAAO,CAAiB,gBAAgB,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CACpF,CAAC;QACN,CAAC;IACH,CAAC;IACD,iBAAiB;IACjB,IAAI,IAAI,KAAK,mBAAmB,EAAE,CAAC;QACjC,gBAAgB,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAEpF,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,wBAAwB;YACxB,uDAAuD;YACvD,gBAAgB,CAAC,iBAAiB;gBAChC,SAAS,CACP,SAAS,CAAC,OAAO,CAAiB,gBAAgB,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CACnF,CAAC;QACN,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,qBAAqB,CAAC,SAA2B;IAC9D,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACpF,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAEtF,KAAK,MAAM,cAAc,IAAI,QAAQ,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,cAAc,CAAC,OAAO,CAAC,CAAC;QAC1F,IAAI,cAAc,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;YAC/B,SAAS,CAAC,YAAY,CAAC,CAAC,OAAO,GAAG,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YACpE,SAAS,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;QACxC,CAAC;IACH,CAAC;IAED,KAAK,MAAM,aAAa,IAAI,eAAe,EAAE,CAAC;QAC5C,MAAM,YAAY,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,aAAa,CAAC,OAAO,CAAC,CAAC;QACzF,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;YACzB,SAAS,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;YACtC,SAAS,CAAC,YAAY,CAAC,CAAC,SAAS,GAAG,aAAa,CAAC,eAAe,CAAC;QACpE,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -3,4 +3,5 @@ import { KaspaUtxo } from "../../types";
|
|
|
3
3
|
export declare const calcMaxSpendableAmount: (utxos: KaspaUtxo[], isEcdsaRecipient: boolean, feerate?: number) => BigNumber;
|
|
4
4
|
export declare const sumBigNumber: (values: BigNumber[]) => BigNumber;
|
|
5
5
|
export declare const sumUtxoAmounts: (utxos: KaspaUtxo[]) => BigNumber;
|
|
6
|
+
export declare const sortUtxos: (utxos: KaspaUtxo[]) => void;
|
|
6
7
|
//# sourceMappingURL=lib.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../../src/logic/utxos/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../../../src/logic/utxos/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,eAAO,MAAM,sBAAsB,UAC1B,SAAS,EAAE,oBACA,OAAO,YAChB,MAAM,KACd,SAgBF,CAAC;AAEF,eAAO,MAAM,YAAY,WAAY,SAAS,EAAE,KAAG,SAElD,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,SAAS,EAAE,KAAG,SAEnD,CAAC;AAEF,eAAO,MAAM,SAAS,UAAW,SAAS,EAAE,SAU3C,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { BigNumber } from "bignumber.js";
|
|
2
|
-
|
|
3
|
-
const DEFAULT_MASS_1_OUTPUT = 506;
|
|
4
|
-
const MAX_UTXOS_PER_TX = 88;
|
|
2
|
+
import { MASS_PER_INPUT, DEFAULT_MASS_1_OUTPUT, MAX_UTXOS_PER_TX } from "../constants";
|
|
5
3
|
export const calcMaxSpendableAmount = (utxos, isEcdsaRecipient, feerate = 1) => {
|
|
6
|
-
|
|
4
|
+
sortUtxos(utxos);
|
|
5
|
+
const utxoSubset = utxos.slice(0, MAX_UTXOS_PER_TX);
|
|
6
|
+
const maxInputAmount = sumUtxoAmounts(utxoSubset);
|
|
7
7
|
// storage mass can be neglected here
|
|
8
8
|
// max compute mass for one output and 88 inputs is 98901
|
|
9
|
-
let maxSpendableAmount = maxInputAmount.minus(BigNumber(DEFAULT_MASS_1_OUTPUT +
|
|
9
|
+
let maxSpendableAmount = maxInputAmount.minus(BigNumber(DEFAULT_MASS_1_OUTPUT + utxoSubset.length * MASS_PER_INPUT).times(feerate));
|
|
10
10
|
if (isEcdsaRecipient) {
|
|
11
11
|
maxSpendableAmount = maxSpendableAmount.minus(BigNumber(11));
|
|
12
12
|
}
|
|
@@ -18,4 +18,13 @@ export const sumBigNumber = (values) => {
|
|
|
18
18
|
export const sumUtxoAmounts = (utxos) => {
|
|
19
19
|
return utxos.reduce((acc, v) => acc.plus(v.utxoEntry.amount), BigNumber(0));
|
|
20
20
|
};
|
|
21
|
+
export const sortUtxos = (utxos) => {
|
|
22
|
+
utxos.sort((a, b) => {
|
|
23
|
+
const transactionComparison = a.utxoEntry.blockDaaScore.localeCompare(b.utxoEntry.blockDaaScore);
|
|
24
|
+
if (transactionComparison !== 0) {
|
|
25
|
+
return transactionComparison;
|
|
26
|
+
}
|
|
27
|
+
return a.utxoEntry.amount.minus(b.utxoEntry.amount).toNumber();
|
|
28
|
+
});
|
|
29
|
+
};
|
|
21
30
|
//# sourceMappingURL=lib.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../../src/logic/utxos/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../../src/logic/utxos/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEvF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,KAAkB,EAClB,gBAAyB,EACzB,UAAkB,CAAC,EACR,EAAE;IACb,SAAS,CAAC,KAAK,CAAC,CAAC;IACjB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACpD,MAAM,cAAc,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAElD,qCAAqC;IACrC,yDAAyD;IACzD,IAAI,kBAAkB,GAAG,cAAc,CAAC,KAAK,CAC3C,SAAS,CAAC,qBAAqB,GAAG,UAAU,CAAC,MAAM,GAAG,cAAc,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CACrF,CAAC;IAEF,IAAI,gBAAgB,EAAE,CAAC;QACrB,kBAAkB,GAAG,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC;AACtE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAmB,EAAa,EAAE;IAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAkB,EAAa,EAAE;IAC9D,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAkB,EAAE,EAAE;IAC9C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAClB,MAAM,qBAAqB,GAAG,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,aAAa,CACnE,CAAC,CAAC,SAAS,CAAC,aAAa,CAC1B,CAAC;QACF,IAAI,qBAAqB,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QACD,OAAO,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/logic/utxos/selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/logic/utxos/selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAWxC,eAAO,MAAM,WAAW,UACf,SAAS,EAAE,oBACA,OAAO,UACjB,SAAS,YACR,MAAM;kBACE,SAAS;SAAO,SAAS;WAAS,SAAS,EAAE;CAqE/D,CAAC"}
|
|
@@ -1,25 +1,19 @@
|
|
|
1
1
|
import { BigNumber } from "bignumber.js";
|
|
2
2
|
import { calcComputeMass, calcStorageMass } from "../massCalcluation";
|
|
3
|
-
import { calcMaxSpendableAmount, sumUtxoAmounts } from "./lib";
|
|
4
|
-
|
|
5
|
-
const MASS_PER_INPUT = 1118; // Per selected utxo as input, mass increases by this value.
|
|
6
|
-
const MASS_PER_OUTPUT = 412; // Per selected utxo as input, mass increases by this value.
|
|
7
|
-
const MAX_UTXOS_PER_TX = 88; // 88 is the maximum of utxo inputs in one TX.
|
|
8
|
-
const MAX_DISCARD = 2000_0000; // Throw error, if discarded value is higher than this.
|
|
3
|
+
import { calcMaxSpendableAmount, sortUtxos, sumUtxoAmounts } from "./lib";
|
|
4
|
+
import { MASS_LIMIT_PER_TX, MASS_PER_INPUT, MASS_PER_OUTPUT, MAX_DISCARD, MAX_UTXOS_PER_TX, } from "../constants";
|
|
9
5
|
export const selectUtxos = (utxos, isEcdsaRecipient, amount, feerate = 1) => {
|
|
10
6
|
// always sort utxos
|
|
11
7
|
sortUtxos(utxos);
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// First check in general, if there is enough amount in the UTXOs.
|
|
17
|
-
if (calcMaxSpendableAmount(utxos, isEcdsaRecipient, feerate).isLessThan(amount)) {
|
|
8
|
+
// UTXOs are already sorted (FIFO), but need to be sliced, as 88 is the maximum for a transaction.
|
|
9
|
+
const utxoSubset = utxos.slice(0, MAX_UTXOS_PER_TX);
|
|
10
|
+
// Now check in general, if there is enough amount in the UTXOs.
|
|
11
|
+
if (calcMaxSpendableAmount(utxoSubset, isEcdsaRecipient, feerate).isLessThan(amount)) {
|
|
18
12
|
throw new Error(`UTXO total amount is not sufficient for sending amount ${amount}`);
|
|
19
13
|
}
|
|
20
14
|
// Find a sufficient slice.
|
|
21
|
-
for (let i = 0; i <
|
|
22
|
-
const selectedUtxos =
|
|
15
|
+
for (let i = 0; i < utxoSubset.length; i++) {
|
|
16
|
+
const selectedUtxos = utxoSubset.slice(0, i + 1);
|
|
23
17
|
const selectedUtxoAmount = sumUtxoAmounts(selectedUtxos);
|
|
24
18
|
// calculate absolute min fee for regular TX with 1 outputs and the given feerate.
|
|
25
19
|
const minMass = calcComputeMass(i + 1, false, isEcdsaRecipient);
|
|
@@ -64,13 +58,4 @@ export const selectUtxos = (utxos, isEcdsaRecipient, amount, feerate = 1) => {
|
|
|
64
58
|
// Throw an error, if UTXOs can't be determined to fulfill the requirement.
|
|
65
59
|
throw new Error("UTXOs can't be determined to fulfill the specified amount");
|
|
66
60
|
};
|
|
67
|
-
const sortUtxos = (utxos) => {
|
|
68
|
-
utxos.sort((a, b) => {
|
|
69
|
-
const transactionComparison = a.utxoEntry.blockDaaScore.localeCompare(b.utxoEntry.blockDaaScore);
|
|
70
|
-
if (transactionComparison !== 0) {
|
|
71
|
-
return transactionComparison;
|
|
72
|
-
}
|
|
73
|
-
return a.utxoEntry.amount.minus(b.utxoEntry.amount).toNumber();
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
61
|
//# sourceMappingURL=selection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.js","sourceRoot":"","sources":["../../../src/logic/utxos/selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"selection.js","sourceRoot":"","sources":["../../../src/logic/utxos/selection.ts"],"names":[],"mappings":"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"}
|
package/lib-es/types/errors.d.ts
CHANGED
|
@@ -7,4 +7,10 @@ export declare const TransactionMassExceededError: import("@ledgerhq/errors/lib/
|
|
|
7
7
|
export declare const EmptyRecipientError: import("@ledgerhq/errors/lib/helpers").LedgerErrorConstructor<{
|
|
8
8
|
[key: string]: unknown;
|
|
9
9
|
}>;
|
|
10
|
+
export declare const ReducedAmountUtxoWarning: import("@ledgerhq/errors/lib/helpers").LedgerErrorConstructor<{
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const UtxoLimitReachedError: import("@ledgerhq/errors/lib/helpers").LedgerErrorConstructor<{
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}>;
|
|
10
16
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB;;EAA8C,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB;;EAA8C,CAAC;AAC7E,eAAO,MAAM,4BAA4B;;EAAyD,CAAC;AACnG,eAAO,MAAM,mBAAmB;;EAAgD,CAAC;AACjF,eAAO,MAAM,wBAAwB;;EAAqD,CAAC;AAC3F,eAAO,MAAM,qBAAqB;;EAAkD,CAAC"}
|
package/lib-es/types/errors.js
CHANGED
|
@@ -2,4 +2,6 @@ import { createCustomErrorClass } from "@ledgerhq/errors";
|
|
|
2
2
|
export const NotEnoughFeeError = createCustomErrorClass("NotEnoughFeeError");
|
|
3
3
|
export const TransactionMassExceededError = createCustomErrorClass("TransactionMassExceededError");
|
|
4
4
|
export const EmptyRecipientError = createCustomErrorClass("EmptyRecipientError");
|
|
5
|
+
export const ReducedAmountUtxoWarning = createCustomErrorClass("ReducedAmountUtxoWarning");
|
|
6
|
+
export const UtxoLimitReachedError = createCustomErrorClass("UtxoLimitReachedError");
|
|
5
7
|
//# sourceMappingURL=errors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAC;AAC7E,MAAM,CAAC,MAAM,4BAA4B,GAAG,sBAAsB,CAAC,8BAA8B,CAAC,CAAC;AACnG,MAAM,CAAC,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,qBAAqB,CAAC,CAAC;AACjF,MAAM,CAAC,MAAM,wBAAwB,GAAG,sBAAsB,CAAC,0BAA0B,CAAC,CAAC;AAC3F,MAAM,CAAC,MAAM,qBAAqB,GAAG,sBAAsB,CAAC,uBAAuB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/coin-kaspa",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2-nightly.20251126023856",
|
|
4
4
|
"description": "Ledger framework for Kaspa integration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -97,15 +97,15 @@
|
|
|
97
97
|
"lru-cache": "^7.14.1",
|
|
98
98
|
"prando": "^6.0.1",
|
|
99
99
|
"rxjs": "^7.8.1",
|
|
100
|
-
"@ledgerhq/coin-framework": "^6.
|
|
101
|
-
"@ledgerhq/cryptoassets": "^13.
|
|
100
|
+
"@ledgerhq/coin-framework": "^6.10.0-nightly.20251126023856",
|
|
101
|
+
"@ledgerhq/cryptoassets": "^13.34.0-nightly.20251126023856",
|
|
102
102
|
"@ledgerhq/devices": "8.7.0",
|
|
103
103
|
"@ledgerhq/errors": "^6.27.0",
|
|
104
|
-
"@ledgerhq/live-env": "^2.21.
|
|
105
|
-
"@ledgerhq/live-network": "^2.1.
|
|
104
|
+
"@ledgerhq/live-env": "^2.21.1-nightly.20251126023856",
|
|
105
|
+
"@ledgerhq/live-network": "^2.1.2-nightly.20251126023856",
|
|
106
106
|
"@ledgerhq/logs": "^6.13.0",
|
|
107
107
|
"@ledgerhq/types-cryptoassets": "^7.30.0",
|
|
108
|
-
"@ledgerhq/types-live": "^6.
|
|
108
|
+
"@ledgerhq/types-live": "^6.90.0-nightly.20251126023856"
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
111
|
"@types/invariant": "^2.2.2",
|
|
@@ -118,8 +118,7 @@
|
|
|
118
118
|
"timemachine": "^0.3.2",
|
|
119
119
|
"ts-jest": "^29.1.1",
|
|
120
120
|
"@ledgerhq/disable-network-setup": "^0.1.0",
|
|
121
|
-
"@ledgerhq/hw-transport-node-speculos": "^6.29.13"
|
|
122
|
-
"@ledgerhq/hw-transport-node-speculos-http": "^6.31.0"
|
|
121
|
+
"@ledgerhq/hw-transport-node-speculos": "^6.29.13"
|
|
123
122
|
},
|
|
124
123
|
"scripts": {
|
|
125
124
|
"clean": "rimraf lib lib-es",
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
NotEnoughBalance,
|
|
9
9
|
RecipientRequired,
|
|
10
10
|
} from "@ledgerhq/errors";
|
|
11
|
+
import { ReducedAmountUtxoWarning, UtxoLimitReachedError } from "../types/errors";
|
|
11
12
|
import { BigNumber } from "bignumber.js";
|
|
12
13
|
import {
|
|
13
14
|
calcMaxSpendableAmount,
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
} from "../logic";
|
|
20
21
|
import { KaspaAccount, Transaction, TransactionStatus } from "../types";
|
|
21
22
|
import { makeLRUCache, minutes } from "@ledgerhq/live-network/cache";
|
|
23
|
+
import { MAX_UTXOS_PER_TX } from "../logic/constants";
|
|
22
24
|
|
|
23
25
|
const getCachedUtxos = makeLRUCache(
|
|
24
26
|
async (account: KaspaAccount) => {
|
|
@@ -83,10 +85,17 @@ const getTransactionStatus = async (
|
|
|
83
85
|
if (transaction.amount.lt(20000000)) {
|
|
84
86
|
errors.dustLimit = new DustLimit("");
|
|
85
87
|
}
|
|
88
|
+
if (utxos.length > MAX_UTXOS_PER_TX) {
|
|
89
|
+
warnings.amount = new ReducedAmountUtxoWarning();
|
|
90
|
+
}
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
if (transaction.amount.gt(maxSpendableAmount) || maxSpendableAmount.eq(0)) {
|
|
89
|
-
|
|
94
|
+
if (utxos.length > MAX_UTXOS_PER_TX && account.balance.gt(transaction.amount)) {
|
|
95
|
+
errors.amount = new UtxoLimitReachedError();
|
|
96
|
+
} else {
|
|
97
|
+
errors.amount = new NotEnoughBalance();
|
|
98
|
+
}
|
|
90
99
|
}
|
|
91
100
|
|
|
92
101
|
if (Object.keys(errors).length === 0) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const MAX_UTXOS_PER_TX: number = 88;
|
|
2
|
+
export const DEFAULT_MASS_1_OUTPUT: number = 506;
|
|
3
|
+
|
|
4
|
+
export const MASS_PER_INPUT: number = 1118; // Per selected utxo as input, mass increases by this value.
|
|
5
|
+
export const MASS_PER_OUTPUT: number = 412; // Per selected utxo as input, mass increases by this value.
|
|
6
|
+
|
|
7
|
+
export const MASS_LIMIT_PER_TX = 100_000; // TX mass must not exceed 100k gram.
|
|
8
|
+
export const MAX_DISCARD: number = 2000_0000; // Throw error, if discarded value is higher than this.
|
|
@@ -10,8 +10,6 @@ const INITIAL_BALANCE = BigNumber(0);
|
|
|
10
10
|
const GAP_LIMIT = 20;
|
|
11
11
|
const SCAN_BATCH_SIZE = 200;
|
|
12
12
|
|
|
13
|
-
const MAX_TX_INPUTS = 88; // floor (( 100_000 - 918 (def_size with 2 outputs) ) / 1_118 (per_input))
|
|
14
|
-
|
|
15
13
|
/**
|
|
16
14
|
* Scans the addresses for an account and retrieves information such as used addresses and the total balance.
|
|
17
15
|
*
|
|
@@ -87,16 +85,8 @@ export async function scanAddresses(
|
|
|
87
85
|
}
|
|
88
86
|
}
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
...accountAddresses.usedReceiveAddresses,
|
|
93
|
-
]
|
|
94
|
-
.sort((a, b) => b.balance.minus(a.balance).toNumber())
|
|
95
|
-
.slice(0, MAX_TX_INPUTS)
|
|
96
|
-
.map(utxo => utxo.balance)
|
|
97
|
-
.reduce((acc, v) => acc.plus(v), BigNumber(0));
|
|
98
|
-
|
|
99
|
-
accountAddresses.spendableBalance = spendableBalance;
|
|
88
|
+
// Assume all the balance could be sent, there are not "locked" coins.
|
|
89
|
+
accountAddresses.spendableBalance = accountAddresses.totalBalance;
|
|
100
90
|
|
|
101
91
|
return accountAddresses;
|
|
102
92
|
}
|
|
@@ -244,14 +244,26 @@ describe("1 output without discard", () => {
|
|
|
244
244
|
expect(selectedUtxos.changeAmount.toNumber()).toBe(0);
|
|
245
245
|
});
|
|
246
246
|
|
|
247
|
-
test("should throw an error if
|
|
247
|
+
test("should throw an error if balance is higher than the sum of 88 UTXO", () => {
|
|
248
248
|
const utxos = KaspaUtxoGenerator.generateUtxoSet(100, BigNumber(1_0000_0000), "0");
|
|
249
249
|
const feeRate = 1;
|
|
250
250
|
const isEcdsaRecipient = false;
|
|
251
251
|
|
|
252
252
|
expect(() => {
|
|
253
|
-
selectUtxos(utxos, isEcdsaRecipient, BigNumber(
|
|
254
|
-
}).toThrow("UTXO
|
|
253
|
+
selectUtxos(utxos, isEcdsaRecipient, BigNumber(99_0000_0000), feeRate);
|
|
254
|
+
}).toThrow("UTXO total amount is not sufficient for sending amount 9900000000");
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test("should be fine, if less than 88 UTXOs needed for a set of 100 UTXO", () => {
|
|
258
|
+
const utxos = KaspaUtxoGenerator.generateUtxoSet(100, BigNumber(1_0000_0000), "0");
|
|
259
|
+
const feeRate = 1;
|
|
260
|
+
const isEcdsaRecipient = false;
|
|
261
|
+
|
|
262
|
+
const selectedUtxos = selectUtxos(utxos, isEcdsaRecipient, BigNumber(80_0000_0000), feeRate);
|
|
263
|
+
|
|
264
|
+
expect(selectedUtxos.utxos.length).toBe(81);
|
|
265
|
+
expect(selectedUtxos.fee.toNumber()).toBe(81 * 1118 + 918);
|
|
266
|
+
expect(selectedUtxos.changeAmount.toNumber()).toBe(1_0000_0000 - (81 * 1118 + 918));
|
|
255
267
|
});
|
|
256
268
|
|
|
257
269
|
test("should throw an error if discarded change exceeds maximum allowable discard value", () => {
|
|
@@ -264,6 +276,21 @@ describe("1 output without discard", () => {
|
|
|
264
276
|
}).toThrow(/Change \d+ Sompis is too high to be discarded./);
|
|
265
277
|
});
|
|
266
278
|
|
|
279
|
+
test("Send maximum amount for 88/100 UTXOs", () => {
|
|
280
|
+
const utxos = KaspaUtxoGenerator.generateUtxoSet(100, BigNumber(1_0000_0000), "0");
|
|
281
|
+
const feeRate = 1;
|
|
282
|
+
const isEcdsaRecipient = false;
|
|
283
|
+
|
|
284
|
+
const expectedFee = 88 * 1118 + 506;
|
|
285
|
+
|
|
286
|
+
const maxAmount = BigNumber(88_0000_0000).minus(expectedFee);
|
|
287
|
+
const selectedUtxos = selectUtxos(utxos, isEcdsaRecipient, maxAmount, feeRate);
|
|
288
|
+
|
|
289
|
+
expect(selectedUtxos.utxos.length).toBe(88);
|
|
290
|
+
expect(selectedUtxos.fee.toNumber()).toBe(expectedFee);
|
|
291
|
+
expect(selectedUtxos.changeAmount.toNumber()).toBe(0);
|
|
292
|
+
});
|
|
293
|
+
|
|
267
294
|
test("should throw - UTXOs can't be determined to fulfill the specified amount", () => {
|
|
268
295
|
jest.spyOn(lib, "calcMaxSpendableAmount").mockReturnValue(BigNumber(1_2345_0000));
|
|
269
296
|
const feeRate = 1;
|
package/src/logic/utxos/lib.ts
CHANGED
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
import { BigNumber } from "bignumber.js";
|
|
2
2
|
import { KaspaUtxo } from "../../types";
|
|
3
|
-
|
|
4
|
-
const ADDITIONAL_MASS_PER_INPUT = 1118;
|
|
5
|
-
|
|
6
|
-
const DEFAULT_MASS_1_OUTPUT: number = 506;
|
|
7
|
-
const MAX_UTXOS_PER_TX: number = 88;
|
|
3
|
+
import { MASS_PER_INPUT, DEFAULT_MASS_1_OUTPUT, MAX_UTXOS_PER_TX } from "../constants";
|
|
8
4
|
|
|
9
5
|
export const calcMaxSpendableAmount = (
|
|
10
6
|
utxos: KaspaUtxo[],
|
|
11
7
|
isEcdsaRecipient: boolean,
|
|
12
8
|
feerate: number = 1,
|
|
13
9
|
): BigNumber => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
);
|
|
10
|
+
sortUtxos(utxos);
|
|
11
|
+
const utxoSubset = utxos.slice(0, MAX_UTXOS_PER_TX);
|
|
12
|
+
const maxInputAmount = sumUtxoAmounts(utxoSubset);
|
|
18
13
|
|
|
19
14
|
// storage mass can be neglected here
|
|
20
15
|
// max compute mass for one output and 88 inputs is 98901
|
|
21
16
|
let maxSpendableAmount = maxInputAmount.minus(
|
|
22
|
-
BigNumber(
|
|
23
|
-
DEFAULT_MASS_1_OUTPUT + Math.min(MAX_UTXOS_PER_TX, utxos.length) * ADDITIONAL_MASS_PER_INPUT,
|
|
24
|
-
).times(feerate),
|
|
17
|
+
BigNumber(DEFAULT_MASS_1_OUTPUT + utxoSubset.length * MASS_PER_INPUT).times(feerate),
|
|
25
18
|
);
|
|
26
19
|
|
|
27
20
|
if (isEcdsaRecipient) {
|
|
@@ -38,3 +31,15 @@ export const sumBigNumber = (values: BigNumber[]): BigNumber => {
|
|
|
38
31
|
export const sumUtxoAmounts = (utxos: KaspaUtxo[]): BigNumber => {
|
|
39
32
|
return utxos.reduce((acc, v) => acc.plus(v.utxoEntry.amount), BigNumber(0));
|
|
40
33
|
};
|
|
34
|
+
|
|
35
|
+
export const sortUtxos = (utxos: KaspaUtxo[]) => {
|
|
36
|
+
utxos.sort((a, b) => {
|
|
37
|
+
const transactionComparison = a.utxoEntry.blockDaaScore.localeCompare(
|
|
38
|
+
b.utxoEntry.blockDaaScore,
|
|
39
|
+
);
|
|
40
|
+
if (transactionComparison !== 0) {
|
|
41
|
+
return transactionComparison;
|
|
42
|
+
}
|
|
43
|
+
return a.utxoEntry.amount.minus(b.utxoEntry.amount).toNumber();
|
|
44
|
+
});
|
|
45
|
+
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { BigNumber } from "bignumber.js";
|
|
2
2
|
import { KaspaUtxo } from "../../types";
|
|
3
3
|
import { calcComputeMass, calcStorageMass } from "../massCalcluation";
|
|
4
|
-
import { calcMaxSpendableAmount, sumUtxoAmounts } from "./lib";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
import { calcMaxSpendableAmount, sortUtxos, sumUtxoAmounts } from "./lib";
|
|
5
|
+
import {
|
|
6
|
+
MASS_LIMIT_PER_TX,
|
|
7
|
+
MASS_PER_INPUT,
|
|
8
|
+
MASS_PER_OUTPUT,
|
|
9
|
+
MAX_DISCARD,
|
|
10
|
+
MAX_UTXOS_PER_TX,
|
|
11
|
+
} from "../constants";
|
|
11
12
|
|
|
12
13
|
export const selectUtxos = (
|
|
13
14
|
utxos: KaspaUtxo[],
|
|
@@ -17,19 +18,17 @@ export const selectUtxos = (
|
|
|
17
18
|
): { changeAmount: BigNumber; fee: BigNumber; utxos: KaspaUtxo[] } => {
|
|
18
19
|
// always sort utxos
|
|
19
20
|
sortUtxos(utxos);
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
throw new Error(`UTXO count exceeds the limit of ${MAX_UTXOS_PER_TX} for a TX.`);
|
|
23
|
-
}
|
|
21
|
+
// UTXOs are already sorted (FIFO), but need to be sliced, as 88 is the maximum for a transaction.
|
|
22
|
+
const utxoSubset = utxos.slice(0, MAX_UTXOS_PER_TX);
|
|
24
23
|
|
|
25
|
-
//
|
|
26
|
-
if (calcMaxSpendableAmount(
|
|
24
|
+
// Now check in general, if there is enough amount in the UTXOs.
|
|
25
|
+
if (calcMaxSpendableAmount(utxoSubset, isEcdsaRecipient, feerate).isLessThan(amount)) {
|
|
27
26
|
throw new Error(`UTXO total amount is not sufficient for sending amount ${amount}`);
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
// Find a sufficient slice.
|
|
31
|
-
for (let i = 0; i <
|
|
32
|
-
const selectedUtxos =
|
|
30
|
+
for (let i = 0; i < utxoSubset.length; i++) {
|
|
31
|
+
const selectedUtxos = utxoSubset.slice(0, i + 1);
|
|
33
32
|
const selectedUtxoAmount = sumUtxoAmounts(selectedUtxos);
|
|
34
33
|
// calculate absolute min fee for regular TX with 1 outputs and the given feerate.
|
|
35
34
|
const minMass = calcComputeMass(i + 1, false, isEcdsaRecipient);
|
|
@@ -86,15 +85,3 @@ export const selectUtxos = (
|
|
|
86
85
|
// Throw an error, if UTXOs can't be determined to fulfill the requirement.
|
|
87
86
|
throw new Error("UTXOs can't be determined to fulfill the specified amount");
|
|
88
87
|
};
|
|
89
|
-
|
|
90
|
-
const sortUtxos = (utxos: KaspaUtxo[]) => {
|
|
91
|
-
utxos.sort((a, b) => {
|
|
92
|
-
const transactionComparison = a.utxoEntry.blockDaaScore.localeCompare(
|
|
93
|
-
b.utxoEntry.blockDaaScore,
|
|
94
|
-
);
|
|
95
|
-
if (transactionComparison !== 0) {
|
|
96
|
-
return transactionComparison;
|
|
97
|
-
}
|
|
98
|
-
return a.utxoEntry.amount.minus(b.utxoEntry.amount).toNumber();
|
|
99
|
-
});
|
|
100
|
-
};
|
package/src/types/errors.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createCustomErrorClass } from "@ledgerhq/errors";
|
|
2
2
|
|
|
3
3
|
export const NotEnoughFeeError = createCustomErrorClass("NotEnoughFeeError");
|
|
4
|
-
|
|
5
4
|
export const TransactionMassExceededError = createCustomErrorClass("TransactionMassExceededError");
|
|
6
|
-
|
|
7
5
|
export const EmptyRecipientError = createCustomErrorClass("EmptyRecipientError");
|
|
6
|
+
export const ReducedAmountUtxoWarning = createCustomErrorClass("ReducedAmountUtxoWarning");
|
|
7
|
+
export const UtxoLimitReachedError = createCustomErrorClass("UtxoLimitReachedError");
|