mainnet-js 3.0.0-next.0 → 3.0.0-next.2
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/dist/index.html +1 -1
- package/dist/{mainnet-3.0.0-next.0.js → mainnet-3.0.0-next.2.js} +21 -41
- package/dist/module/cache/walletCache.d.ts +10 -4
- package/dist/module/cache/walletCache.d.ts.map +1 -1
- package/dist/module/cache/walletCache.js +12 -13
- package/dist/module/cache/walletCache.js.map +1 -1
- package/dist/module/chain.d.ts +1 -1
- package/dist/module/chain.js +1 -1
- package/dist/module/chain.js.map +1 -1
- package/dist/module/constant.d.ts +1 -1
- package/dist/module/constant.d.ts.map +1 -1
- package/dist/module/constant.js +1 -1
- package/dist/module/constant.js.map +1 -1
- package/dist/module/enum.d.ts +1 -7
- package/dist/module/enum.d.ts.map +1 -1
- package/dist/module/enum.js +0 -6
- package/dist/module/enum.js.map +1 -1
- package/dist/module/history/getHistory.d.ts.map +1 -1
- package/dist/module/history/getHistory.js +17 -47
- package/dist/module/history/getHistory.js.map +1 -1
- package/dist/module/history/interface.d.ts +1 -1
- package/dist/module/history/interface.d.ts.map +1 -1
- package/dist/module/interface.d.ts +6 -5
- package/dist/module/interface.d.ts.map +1 -1
- package/dist/module/interface.js.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.js +2 -4
- package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
- package/dist/module/network/getRelayFeeCache.js +2 -2
- package/dist/module/network/getRelayFeeCache.js.map +1 -1
- package/dist/module/network/interface.d.ts +2 -2
- package/dist/module/network/interface.d.ts.map +1 -1
- package/dist/module/rate/ExchangeRate.d.ts +2 -1
- package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
- package/dist/module/rate/ExchangeRate.js +4 -1
- package/dist/module/rate/ExchangeRate.js.map +1 -1
- package/dist/module/transaction/Wif.d.ts +9 -9
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +35 -35
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/transaction/allocateFee.d.ts +3 -3
- package/dist/module/transaction/allocateFee.d.ts.map +1 -1
- package/dist/module/transaction/allocateFee.js +5 -6
- package/dist/module/transaction/allocateFee.js.map +1 -1
- package/dist/module/util/amountInSatoshi.d.ts +1 -1
- package/dist/module/util/amountInSatoshi.d.ts.map +1 -1
- package/dist/module/util/amountInSatoshi.js +3 -9
- package/dist/module/util/amountInSatoshi.js.map +1 -1
- package/dist/module/util/asSendRequestObject.d.ts.map +1 -1
- package/dist/module/util/asSendRequestObject.js +10 -7
- package/dist/module/util/asSendRequestObject.js.map +1 -1
- package/dist/module/util/convert.d.ts +3 -0
- package/dist/module/util/convert.d.ts.map +1 -1
- package/dist/module/util/convert.js +12 -0
- package/dist/module/util/convert.js.map +1 -1
- package/dist/module/util/index.d.ts +2 -3
- package/dist/module/util/index.d.ts.map +1 -1
- package/dist/module/util/index.js +2 -3
- package/dist/module/util/index.js.map +1 -1
- package/dist/module/util/satoshiToAmount.d.ts +1 -1
- package/dist/module/util/satoshiToAmount.d.ts.map +1 -1
- package/dist/module/util/satoshiToAmount.js +3 -9
- package/dist/module/util/satoshiToAmount.js.map +1 -1
- package/dist/module/util/sumSendRequestAmounts.d.ts.map +1 -1
- package/dist/module/util/sumSendRequestAmounts.js +3 -4
- package/dist/module/util/sumSendRequestAmounts.js.map +1 -1
- package/dist/module/util/sumUtxoValue.d.ts +1 -1
- package/dist/module/util/sumUtxoValue.js +3 -3
- package/dist/module/util/sumUtxoValue.js.map +1 -1
- package/dist/module/wallet/Base.d.ts +28 -30
- package/dist/module/wallet/Base.d.ts.map +1 -1
- package/dist/module/wallet/Base.js +82 -119
- package/dist/module/wallet/Base.js.map +1 -1
- package/dist/module/wallet/HDWallet.d.ts +1 -1
- package/dist/module/wallet/Util.js +1 -1
- package/dist/module/wallet/Util.js.map +1 -1
- package/dist/module/wallet/Wif.d.ts +1 -1
- package/dist/module/wallet/interface.d.ts +2 -3
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/wallet/model.d.ts +53 -41
- package/dist/module/wallet/model.d.ts.map +1 -1
- package/dist/module/wallet/model.js +14 -22
- package/dist/module/wallet/model.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/cache/walletCache.ts +23 -36
- package/src/chain.ts +1 -1
- package/src/constant.ts +1 -1
- package/src/enum.ts +0 -6
- package/src/history/getHistory.test.ts +20 -34
- package/src/history/getHistory.ts +17 -49
- package/src/history/interface.ts +1 -1
- package/src/interface.ts +6 -5
- package/src/network/Connection.test.ts +3 -3
- package/src/network/ElectrumNetworkProvider.ts +2 -4
- package/src/network/Rpc.test.ts +2 -3
- package/src/network/getRelayFeeCache.ts +2 -2
- package/src/network/interface.ts +2 -2
- package/src/rate/ExchangeRate.test.ts +2 -44
- package/src/rate/ExchangeRate.ts +5 -2
- package/src/transaction/Wif.ts +50 -45
- package/src/transaction/allocateFee.test.ts +110 -131
- package/src/transaction/allocateFee.ts +14 -15
- package/src/util/amountInSatoshi.test.ts +1 -9
- package/src/util/amountInSatoshi.ts +6 -10
- package/src/util/asSendRequestObject.ts +12 -7
- package/src/util/convert.ts +18 -0
- package/src/util/index.ts +2 -7
- package/src/util/satoshiToAmount.test.ts +1 -1
- package/src/util/satoshiToAmount.ts +4 -10
- package/src/util/sumSendRequestAmounts.ts +3 -4
- package/src/util/sumUtxoValue.ts +4 -4
- package/src/wallet/Base.ts +95 -164
- package/src/wallet/Cashtokens.test.headless.js +228 -173
- package/src/wallet/Cashtokens.test.ts +506 -406
- package/src/wallet/HDWallet.test.ts +223 -68
- package/src/wallet/Util.ts +1 -1
- package/src/wallet/Wif.test.ts +108 -133
- package/src/wallet/interface.ts +2 -3
- package/src/wallet/model.test.ts +2 -5
- package/src/wallet/model.ts +64 -71
- package/dist/module/util/balanceObjectFromSatoshi.d.ts +0 -8
- package/dist/module/util/balanceObjectFromSatoshi.d.ts.map +0 -1
- package/dist/module/util/balanceObjectFromSatoshi.js +0 -35
- package/dist/module/util/balanceObjectFromSatoshi.js.map +0 -1
- package/src/util/balanceObjectFromSatoshi.test.ts +0 -58
- package/src/util/balanceObjectFromSatoshi.ts +0 -52
package/src/transaction/Wif.ts
CHANGED
|
@@ -26,11 +26,10 @@ import {
|
|
|
26
26
|
SourceOutput,
|
|
27
27
|
TokenSendRequest,
|
|
28
28
|
} from "../wallet/model.js";
|
|
29
|
-
import { amountInSatoshi } from "../util/amountInSatoshi.js";
|
|
30
29
|
import { sumSendRequestAmounts } from "../util/sumSendRequestAmounts.js";
|
|
31
30
|
import { sumUtxoValue } from "../util/sumUtxoValue.js";
|
|
32
31
|
import { FeePaidByEnum } from "../wallet/enum.js";
|
|
33
|
-
import {
|
|
32
|
+
import { WalletCache } from "../cache/walletCache.js";
|
|
34
33
|
|
|
35
34
|
export const placeholderPrivateKey =
|
|
36
35
|
"0000000000000000000000000000000000000000000000000000000000000001";
|
|
@@ -41,7 +40,7 @@ export async function buildP2pkhNonHdTransaction({
|
|
|
41
40
|
inputs,
|
|
42
41
|
outputs,
|
|
43
42
|
signingKey,
|
|
44
|
-
fee =
|
|
43
|
+
fee = 0n,
|
|
45
44
|
discardChange = false,
|
|
46
45
|
feePaidBy = FeePaidByEnum.change,
|
|
47
46
|
changeAddress = "",
|
|
@@ -50,11 +49,11 @@ export async function buildP2pkhNonHdTransaction({
|
|
|
50
49
|
inputs: Utxo[];
|
|
51
50
|
outputs: Array<SendRequest | TokenSendRequest | OpReturnData>;
|
|
52
51
|
signingKey?: Uint8Array;
|
|
53
|
-
fee?:
|
|
52
|
+
fee?: bigint;
|
|
54
53
|
discardChange?: boolean;
|
|
55
54
|
feePaidBy?: FeePaidByEnum;
|
|
56
55
|
changeAddress?: string;
|
|
57
|
-
walletCache?:
|
|
56
|
+
walletCache?: WalletCache;
|
|
58
57
|
}) {
|
|
59
58
|
if (!signingKey) {
|
|
60
59
|
throw new Error("Missing signing key when building transaction");
|
|
@@ -135,7 +134,7 @@ export function prepareInputs({
|
|
|
135
134
|
AuthenticationProgramStateCommon
|
|
136
135
|
>;
|
|
137
136
|
signingKey: Uint8Array;
|
|
138
|
-
walletCache?:
|
|
137
|
+
walletCache?: WalletCache;
|
|
139
138
|
}) {
|
|
140
139
|
const preparedInputs: any[] = [];
|
|
141
140
|
const sourceOutputs: any[] = [];
|
|
@@ -154,19 +153,20 @@ export function prepareInputs({
|
|
|
154
153
|
|
|
155
154
|
const libAuthToken = i.token && {
|
|
156
155
|
amount: BigInt(i.token.amount),
|
|
157
|
-
category: hexToBin(i.token.
|
|
156
|
+
category: hexToBin(i.token.category),
|
|
158
157
|
nft:
|
|
159
|
-
i.token.capability !== undefined ||
|
|
158
|
+
i.token.nft?.capability !== undefined ||
|
|
159
|
+
i.token.nft?.commitment !== undefined
|
|
160
160
|
? {
|
|
161
|
-
capability: i.token.capability,
|
|
161
|
+
capability: i.token.nft?.capability,
|
|
162
162
|
commitment:
|
|
163
|
-
i.token.commitment !== undefined &&
|
|
164
|
-
hexToBin(i.token.commitment!),
|
|
163
|
+
i.token.nft?.commitment !== undefined &&
|
|
164
|
+
hexToBin(i.token.nft?.commitment!),
|
|
165
165
|
}
|
|
166
166
|
: undefined,
|
|
167
167
|
};
|
|
168
168
|
const key =
|
|
169
|
-
walletCache?.
|
|
169
|
+
walletCache?.get(i.address)?.privateKey ??
|
|
170
170
|
(signingKey?.length ? signingKey : Uint8Array.from(Array(32)));
|
|
171
171
|
const newInput = {
|
|
172
172
|
outpointIndex: utxoIndex,
|
|
@@ -231,7 +231,7 @@ export async function prepareOutputs(
|
|
|
231
231
|
if (typeof outputLockingBytecode === "string")
|
|
232
232
|
throw new Error(outputLockingBytecode);
|
|
233
233
|
|
|
234
|
-
const sendAmount =
|
|
234
|
+
const sendAmount = Number(output.value);
|
|
235
235
|
if (sendAmount % 1 !== 0) {
|
|
236
236
|
throw Error(
|
|
237
237
|
`Cannot send ${sendAmount} satoshis, (fractional sats do not exist, yet), please use an integer number.`
|
|
@@ -271,13 +271,14 @@ export function prepareTokenOutputs(request: TokenSendRequest): Output {
|
|
|
271
271
|
|
|
272
272
|
const libAuthToken = {
|
|
273
273
|
amount: BigInt(token.amount),
|
|
274
|
-
category: hexToBin(token.
|
|
274
|
+
category: hexToBin(token.category),
|
|
275
275
|
nft:
|
|
276
|
-
token.capability !== undefined || token.commitment !== undefined
|
|
276
|
+
token.nft?.capability !== undefined || token.nft?.commitment !== undefined
|
|
277
277
|
? {
|
|
278
|
-
capability: token.capability,
|
|
278
|
+
capability: token.nft?.capability,
|
|
279
279
|
commitment:
|
|
280
|
-
token.commitment !== undefined &&
|
|
280
|
+
token.nft?.commitment !== undefined &&
|
|
281
|
+
hexToBin(token.nft?.commitment!),
|
|
281
282
|
}
|
|
282
283
|
: undefined,
|
|
283
284
|
};
|
|
@@ -320,13 +321,13 @@ export async function getSuitableUtxos(
|
|
|
320
321
|
if (tokenOperation === "send") {
|
|
321
322
|
for (const request of tokenRequests) {
|
|
322
323
|
const tokenInputs = availableInputs.filter(
|
|
323
|
-
(val) => val.token?.
|
|
324
|
+
(val) => val.token?.category === request.category
|
|
324
325
|
);
|
|
325
326
|
const sameCommitmentTokens = [...suitableUtxos, ...tokenInputs]
|
|
326
327
|
.filter(
|
|
327
328
|
(val) =>
|
|
328
|
-
val.token?.capability === request.capability &&
|
|
329
|
-
val.token?.commitment === request.commitment
|
|
329
|
+
val.token?.nft?.capability === request.nft?.capability &&
|
|
330
|
+
val.token?.nft?.commitment === request.nft?.commitment
|
|
330
331
|
)
|
|
331
332
|
.filter(
|
|
332
333
|
(val) =>
|
|
@@ -349,13 +350,15 @@ export async function getSuitableUtxos(
|
|
|
349
350
|
}
|
|
350
351
|
|
|
351
352
|
if (
|
|
352
|
-
request.capability === NFTCapability.minting ||
|
|
353
|
-
request.capability === NFTCapability.mutable
|
|
353
|
+
request.nft?.capability === NFTCapability.minting ||
|
|
354
|
+
request.nft?.capability === NFTCapability.mutable
|
|
354
355
|
) {
|
|
355
356
|
const changeCommitmentTokens = [
|
|
356
357
|
...suitableUtxos,
|
|
357
358
|
...tokenInputs,
|
|
358
|
-
].filter(
|
|
359
|
+
].filter(
|
|
360
|
+
(val) => val.token?.nft?.capability === request.nft?.capability
|
|
361
|
+
);
|
|
359
362
|
if (changeCommitmentTokens.length) {
|
|
360
363
|
const input = changeCommitmentTokens[0];
|
|
361
364
|
const index = availableInputs.indexOf(input);
|
|
@@ -370,17 +373,17 @@ export async function getSuitableUtxos(
|
|
|
370
373
|
|
|
371
374
|
// handle splitting the hybrid (FT+NFT) token into its parts
|
|
372
375
|
if (
|
|
373
|
-
request.capability === undefined &&
|
|
374
|
-
request.commitment === undefined &&
|
|
376
|
+
request.nft?.capability === undefined &&
|
|
377
|
+
request.nft?.commitment === undefined &&
|
|
375
378
|
[...suitableUtxos, ...tokenInputs]
|
|
376
|
-
.map((val) => val.token?.
|
|
377
|
-
.includes(request.
|
|
379
|
+
.map((val) => val.token?.category)
|
|
380
|
+
.includes(request.category)
|
|
378
381
|
) {
|
|
379
382
|
continue;
|
|
380
383
|
}
|
|
381
384
|
|
|
382
385
|
throw Error(
|
|
383
|
-
`No suitable token utxos available to send token with id "${request.
|
|
386
|
+
`No suitable token utxos available to send token with id "${request.category}", capability "${request.nft?.capability}", commitment "${request.nft?.commitment}"`
|
|
384
387
|
);
|
|
385
388
|
}
|
|
386
389
|
}
|
|
@@ -451,7 +454,7 @@ export async function getFeeAmountSimple({
|
|
|
451
454
|
relayFeePerByteInSatoshi: number;
|
|
452
455
|
feePaidBy: FeePaidByEnum;
|
|
453
456
|
discardChange?: boolean;
|
|
454
|
-
}) {
|
|
457
|
+
}): Promise<bigint> {
|
|
455
458
|
const inputSizeP2pkh = 148;
|
|
456
459
|
const outputSizeP2pkh = 34;
|
|
457
460
|
|
|
@@ -462,37 +465,37 @@ export async function getFeeAmountSimple({
|
|
|
462
465
|
? inputSizeP2pkh +
|
|
463
466
|
1 +
|
|
464
467
|
34 +
|
|
465
|
-
Math.round(1 + (curr.token.commitment?.length ?? 0) / 2) +
|
|
468
|
+
Math.round(1 + (curr.token.nft?.commitment?.length ?? 0) / 2) +
|
|
466
469
|
(curr.token.amount ? 9 : 0)
|
|
467
470
|
: inputSizeP2pkh),
|
|
468
471
|
0
|
|
469
472
|
);
|
|
470
473
|
|
|
471
|
-
const outputSize = (sendRequest) => {
|
|
472
|
-
if (sendRequest.hasOwnProperty("
|
|
473
|
-
return outputSizeP2pkh;
|
|
474
|
-
} else if (sendRequest.hasOwnProperty("tokenId")) {
|
|
474
|
+
const outputSize = (sendRequest: SendRequestType) => {
|
|
475
|
+
if (sendRequest.hasOwnProperty("category")) {
|
|
475
476
|
const tokenRequest = sendRequest as TokenSendRequest;
|
|
476
477
|
return (
|
|
477
478
|
outputSizeP2pkh +
|
|
478
479
|
1 +
|
|
479
480
|
34 +
|
|
480
|
-
Math.round(1 + (tokenRequest.commitment?.length ?? 0) / 2) +
|
|
481
|
+
Math.round(1 + (tokenRequest.nft?.commitment?.length ?? 0) / 2) +
|
|
481
482
|
(tokenRequest.amount ? 9 : 0)
|
|
482
483
|
);
|
|
483
484
|
} else if (sendRequest.hasOwnProperty("buffer")) {
|
|
484
485
|
return 9 + (sendRequest as OpReturnData).buffer.length;
|
|
486
|
+
} else {
|
|
487
|
+
return outputSizeP2pkh;
|
|
485
488
|
}
|
|
486
|
-
|
|
487
|
-
return 0;
|
|
488
489
|
};
|
|
489
490
|
|
|
490
491
|
const outputTotalSize =
|
|
491
492
|
sendRequests.reduce((prev, curr) => prev + outputSize(curr), 0) +
|
|
492
493
|
(discardChange ? 0 : outputSizeP2pkh);
|
|
493
494
|
|
|
494
|
-
return
|
|
495
|
-
(
|
|
495
|
+
return BigInt(
|
|
496
|
+
Math.ceil(
|
|
497
|
+
(inputTotalSize + outputTotalSize + 16) * relayFeePerByteInSatoshi
|
|
498
|
+
)
|
|
496
499
|
);
|
|
497
500
|
}
|
|
498
501
|
|
|
@@ -512,7 +515,7 @@ export async function getFeeAmount({
|
|
|
512
515
|
relayFeePerByteInSatoshi: number;
|
|
513
516
|
feePaidBy: FeePaidByEnum;
|
|
514
517
|
discardChange?: boolean;
|
|
515
|
-
walletCache?:
|
|
518
|
+
walletCache?: WalletCache;
|
|
516
519
|
}) {
|
|
517
520
|
// build transaction
|
|
518
521
|
if (utxos) {
|
|
@@ -522,14 +525,16 @@ export async function getFeeAmount({
|
|
|
522
525
|
inputs: utxos,
|
|
523
526
|
outputs: sendRequests,
|
|
524
527
|
signingKey: placeholderPrivateKeyBin,
|
|
525
|
-
fee:
|
|
528
|
+
fee: 0n, //DUST_UTXO_THRESHOLD
|
|
526
529
|
discardChange: discardChange ?? false,
|
|
527
530
|
feePaidBy,
|
|
528
531
|
changeAddress: "",
|
|
529
532
|
walletCache,
|
|
530
533
|
});
|
|
531
534
|
|
|
532
|
-
return
|
|
535
|
+
return BigInt(
|
|
536
|
+
Math.ceil(draftTransaction.length * relayFeePerByteInSatoshi + 1)
|
|
537
|
+
);
|
|
533
538
|
} else {
|
|
534
539
|
throw Error(
|
|
535
540
|
"The available inputs in the wallet cannot satisfy this send request"
|
|
@@ -542,7 +547,7 @@ export async function buildEncodedTransaction({
|
|
|
542
547
|
inputs,
|
|
543
548
|
outputs,
|
|
544
549
|
signingKey,
|
|
545
|
-
fee =
|
|
550
|
+
fee = 0n,
|
|
546
551
|
discardChange = false,
|
|
547
552
|
feePaidBy = FeePaidByEnum.change,
|
|
548
553
|
changeAddress = "",
|
|
@@ -552,12 +557,12 @@ export async function buildEncodedTransaction({
|
|
|
552
557
|
inputs: Utxo[];
|
|
553
558
|
outputs: Array<SendRequest | TokenSendRequest | OpReturnData>;
|
|
554
559
|
signingKey: Uint8Array;
|
|
555
|
-
fee?:
|
|
560
|
+
fee?: bigint;
|
|
556
561
|
discardChange?: boolean;
|
|
557
562
|
feePaidBy?: FeePaidByEnum;
|
|
558
563
|
changeAddress?: string;
|
|
559
564
|
buildUnsigned?: boolean;
|
|
560
|
-
walletCache?:
|
|
565
|
+
walletCache?: WalletCache;
|
|
561
566
|
}) {
|
|
562
567
|
const { transaction, sourceOutputs } = await buildP2pkhNonHdTransaction({
|
|
563
568
|
inputs,
|
|
@@ -29,66 +29,61 @@ describe("Fee tests", () => {
|
|
|
29
29
|
await funder.send([
|
|
30
30
|
{
|
|
31
31
|
cashaddr: alice.cashaddr!,
|
|
32
|
-
value:
|
|
33
|
-
unit: "satoshis",
|
|
32
|
+
value: 4500n,
|
|
34
33
|
},
|
|
35
34
|
]);
|
|
36
35
|
await alice.send(
|
|
37
36
|
[
|
|
38
37
|
{
|
|
39
38
|
cashaddr: bob.cashaddr!,
|
|
40
|
-
|
|
41
|
-
value: 549,
|
|
39
|
+
value: 549n,
|
|
42
40
|
},
|
|
43
41
|
{
|
|
44
42
|
cashaddr: charlie.cashaddr!,
|
|
45
|
-
|
|
46
|
-
value: 550,
|
|
43
|
+
value: 550n,
|
|
47
44
|
},
|
|
48
45
|
{
|
|
49
46
|
cashaddr: dave.cashaddr!,
|
|
50
|
-
|
|
51
|
-
value: 551,
|
|
47
|
+
value: 551n,
|
|
52
48
|
},
|
|
53
49
|
{
|
|
54
50
|
cashaddr: edward.cashaddr!,
|
|
55
|
-
|
|
56
|
-
value: 2552,
|
|
51
|
+
value: 2552n,
|
|
57
52
|
},
|
|
58
53
|
],
|
|
59
54
|
{ feePaidBy: FeePaidByEnum.changeThenAny }
|
|
60
55
|
);
|
|
61
|
-
expect(await alice.getBalance(
|
|
62
|
-
expect(await bob.getBalance(
|
|
63
|
-
expect(await charlie.getBalance(
|
|
64
|
-
expect(await dave.getBalance(
|
|
65
|
-
expect(await edward.getBalance(
|
|
56
|
+
expect(await alice.getBalance()).toBe(0n);
|
|
57
|
+
expect(await bob.getBalance()).toBe(0n);
|
|
58
|
+
expect(await charlie.getBalance()).toBe(550n);
|
|
59
|
+
expect(await dave.getBalance()).toBe(551n);
|
|
60
|
+
expect(await edward.getBalance()).toBe(2552n);
|
|
66
61
|
}
|
|
67
62
|
});
|
|
68
63
|
|
|
69
64
|
test("Expect first in to subtract fee from first", async () => {
|
|
70
65
|
let to = [
|
|
71
|
-
["alice",
|
|
72
|
-
["bob",
|
|
66
|
+
["alice", 2000n],
|
|
67
|
+
["bob", 2000n],
|
|
73
68
|
];
|
|
74
|
-
let fee =
|
|
69
|
+
let fee = 1n;
|
|
75
70
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
76
|
-
let allocatedInputs =
|
|
71
|
+
let allocatedInputs = allocateFee(
|
|
77
72
|
requests,
|
|
78
73
|
fee,
|
|
79
74
|
FeePaidByEnum.first,
|
|
80
75
|
BigInt(0)
|
|
81
76
|
);
|
|
82
|
-
expect(allocatedInputs[0].value).toBeLessThan(
|
|
83
|
-
expect(allocatedInputs[1].value).toBe(
|
|
77
|
+
expect(allocatedInputs[0].value).toBeLessThan(2000n);
|
|
78
|
+
expect(allocatedInputs[1].value).toBe(2000n);
|
|
84
79
|
});
|
|
85
80
|
|
|
86
81
|
test("Expect last to subtract fee from last", async () => {
|
|
87
82
|
let to = [
|
|
88
|
-
["alice",
|
|
89
|
-
["bob",
|
|
83
|
+
["alice", 2000n],
|
|
84
|
+
["bob", 2000n],
|
|
90
85
|
];
|
|
91
|
-
let fee =
|
|
86
|
+
let fee = 1n;
|
|
92
87
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
93
88
|
let allocatedInputs = allocateFee(
|
|
94
89
|
requests,
|
|
@@ -97,17 +92,17 @@ describe("Fee tests", () => {
|
|
|
97
92
|
BigInt(0)
|
|
98
93
|
);
|
|
99
94
|
|
|
100
|
-
expect(allocatedInputs[0].value).toBe(
|
|
101
|
-
expect(allocatedInputs[1].value).toBeLessThan(
|
|
95
|
+
expect(allocatedInputs[0].value).toBe(2000n);
|
|
96
|
+
expect(allocatedInputs[1].value).toBeLessThan(2000n);
|
|
102
97
|
});
|
|
103
98
|
|
|
104
99
|
test("Expect all to allocate fees equally", async () => {
|
|
105
100
|
let to = [
|
|
106
|
-
["alice",
|
|
107
|
-
["bob",
|
|
108
|
-
["charlie",
|
|
101
|
+
["alice", 2000n],
|
|
102
|
+
["bob", 2000n],
|
|
103
|
+
["charlie", 2000n],
|
|
109
104
|
];
|
|
110
|
-
let fee =
|
|
105
|
+
let fee = 3n;
|
|
111
106
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
112
107
|
|
|
113
108
|
let allocatedInputs = allocateFee(
|
|
@@ -117,18 +112,18 @@ describe("Fee tests", () => {
|
|
|
117
112
|
BigInt(0)
|
|
118
113
|
);
|
|
119
114
|
|
|
120
|
-
expect(allocatedInputs[0].value).toBe(
|
|
121
|
-
expect(allocatedInputs[1].value).toBe(
|
|
122
|
-
expect(allocatedInputs[2].value).toBe(
|
|
115
|
+
expect(allocatedInputs[0].value).toBe(1999n);
|
|
116
|
+
expect(allocatedInputs[1].value).toBe(1999n);
|
|
117
|
+
expect(allocatedInputs[2].value).toBe(1999n);
|
|
123
118
|
});
|
|
124
119
|
|
|
125
120
|
test("Expect all to allocate fees equally, taking dust result", async () => {
|
|
126
121
|
let to = [
|
|
127
|
-
["alice",
|
|
128
|
-
["bob",
|
|
129
|
-
["charlie",
|
|
122
|
+
["alice", 2000n],
|
|
123
|
+
["bob", 547n],
|
|
124
|
+
["charlie", 2000n],
|
|
130
125
|
];
|
|
131
|
-
let fee =
|
|
126
|
+
let fee = 300n;
|
|
132
127
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
133
128
|
|
|
134
129
|
let allocatedInputs = allocateFee(
|
|
@@ -138,18 +133,18 @@ describe("Fee tests", () => {
|
|
|
138
133
|
BigInt(0)
|
|
139
134
|
);
|
|
140
135
|
|
|
141
|
-
expect(allocatedInputs[0].value).toBe(
|
|
142
|
-
expect(allocatedInputs[1].value).toBe(
|
|
136
|
+
expect(allocatedInputs[0].value).toBe(2000n);
|
|
137
|
+
expect(allocatedInputs[1].value).toBe(2000n);
|
|
143
138
|
expect(allocatedInputs.length).toBe(2);
|
|
144
139
|
});
|
|
145
140
|
|
|
146
141
|
test("Expect all to allocate fees equally, taking dust result output, dividing remainder", async () => {
|
|
147
142
|
let to = [
|
|
148
|
-
["alice",
|
|
149
|
-
["bob",
|
|
150
|
-
["charlie",
|
|
143
|
+
["alice", 2000n],
|
|
144
|
+
["bob", 547n],
|
|
145
|
+
["charlie", 2000n],
|
|
151
146
|
];
|
|
152
|
-
let fee =
|
|
147
|
+
let fee = 647n;
|
|
153
148
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
154
149
|
|
|
155
150
|
let allocatedInputs = allocateFee(
|
|
@@ -159,18 +154,18 @@ describe("Fee tests", () => {
|
|
|
159
154
|
BigInt(0)
|
|
160
155
|
);
|
|
161
156
|
|
|
162
|
-
expect(allocatedInputs[0].value).toBe(
|
|
163
|
-
expect(allocatedInputs[1].value).toBe(
|
|
157
|
+
expect(allocatedInputs[0].value).toBe(1950n);
|
|
158
|
+
expect(allocatedInputs[1].value).toBe(1950n);
|
|
164
159
|
expect(allocatedInputs.length).toBe(2);
|
|
165
160
|
});
|
|
166
161
|
|
|
167
162
|
test("Expect an odd fee to be applied to have remainder applied to first receipt", async () => {
|
|
168
163
|
let to = [
|
|
169
|
-
["alice",
|
|
170
|
-
["bob",
|
|
171
|
-
["charlie",
|
|
164
|
+
["alice", 2000n],
|
|
165
|
+
["bob", 2000n],
|
|
166
|
+
["charlie", 2000n],
|
|
172
167
|
];
|
|
173
|
-
let fee =
|
|
168
|
+
let fee = 301n;
|
|
174
169
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
175
170
|
|
|
176
171
|
let allocatedInputs = allocateFee(
|
|
@@ -180,88 +175,72 @@ describe("Fee tests", () => {
|
|
|
180
175
|
BigInt(0)
|
|
181
176
|
);
|
|
182
177
|
|
|
183
|
-
expect(allocatedInputs[0].value).toBe(
|
|
184
|
-
expect(allocatedInputs[1].value).toBe(
|
|
185
|
-
expect(allocatedInputs[2].value).toBe(
|
|
178
|
+
expect(allocatedInputs[0].value).toBe(1899n);
|
|
179
|
+
expect(allocatedInputs[1].value).toBe(1900n);
|
|
180
|
+
expect(allocatedInputs[2].value).toBe(1900n);
|
|
186
181
|
});
|
|
187
182
|
|
|
188
183
|
test("Expect insufficient funds to error", async () => {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
requests,
|
|
200
|
-
fee,
|
|
201
|
-
FeePaidByEnum.changeThenAny,
|
|
202
|
-
BigInt(999)
|
|
203
|
-
);
|
|
204
|
-
} catch (e: any) {
|
|
205
|
-
expect(e.message).toBe("Insufficient funds for transaction given fee");
|
|
206
|
-
}
|
|
184
|
+
let to = [
|
|
185
|
+
["alice", 2000n],
|
|
186
|
+
["bob", 2000n],
|
|
187
|
+
["charlie", 2000n],
|
|
188
|
+
];
|
|
189
|
+
let fee = 7000n;
|
|
190
|
+
let requests = asSendRequestObject(to) as SendRequest[];
|
|
191
|
+
expect(() =>
|
|
192
|
+
allocateFee(requests, fee, FeePaidByEnum.changeThenAny, BigInt(999))
|
|
193
|
+
).toThrow("Insufficient funds for transaction given fee");
|
|
207
194
|
});
|
|
208
195
|
|
|
209
196
|
test("Expect dust amounts to error", async () => {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
requests,
|
|
221
|
-
fee,
|
|
222
|
-
FeePaidByEnum.first,
|
|
223
|
-
BigInt(0)
|
|
224
|
-
);
|
|
225
|
-
} catch (e: any) {
|
|
226
|
-
expect(e.message).toBe("Fee strategy would result in dust output");
|
|
227
|
-
}
|
|
197
|
+
let to = [
|
|
198
|
+
["alice", 2000n],
|
|
199
|
+
["bob", 2000n],
|
|
200
|
+
["charlie", 2000n],
|
|
201
|
+
];
|
|
202
|
+
let fee = 1500n;
|
|
203
|
+
let requests = asSendRequestObject(to) as SendRequest[];
|
|
204
|
+
expect(() =>
|
|
205
|
+
allocateFee(requests, fee, FeePaidByEnum.first, BigInt(0))
|
|
206
|
+
).toThrow("Fee strategy would result in dust output");
|
|
228
207
|
});
|
|
229
208
|
|
|
230
209
|
test("Expect near-dust amounts not to error", async () => {
|
|
231
210
|
let to = [
|
|
232
|
-
["alice",
|
|
233
|
-
["bob",
|
|
234
|
-
["charlie",
|
|
211
|
+
["alice", 1000n],
|
|
212
|
+
["bob", 1000n],
|
|
213
|
+
["charlie", 1000n],
|
|
235
214
|
];
|
|
236
|
-
let fee =
|
|
215
|
+
let fee = 1362n;
|
|
237
216
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
238
217
|
let result = allocateFee(requests, fee, FeePaidByEnum.any, BigInt(0));
|
|
239
|
-
expect(result[0].value).toBe(
|
|
240
|
-
expect(result[1].value).toBe(
|
|
241
|
-
expect(result[2].value).toBe(
|
|
218
|
+
expect(result[0].value).toBe(546n);
|
|
219
|
+
expect(result[1].value).toBe(546n);
|
|
220
|
+
expect(result[2].value).toBe(546n);
|
|
242
221
|
});
|
|
243
222
|
|
|
244
223
|
test("Expect `any` to not consume change", async () => {
|
|
245
224
|
let to = [
|
|
246
|
-
["alice",
|
|
247
|
-
["bob",
|
|
248
|
-
["charlie",
|
|
225
|
+
["alice", 1000n],
|
|
226
|
+
["bob", 1000n],
|
|
227
|
+
["charlie", 1000n],
|
|
249
228
|
];
|
|
250
|
-
let fee =
|
|
229
|
+
let fee = 1362n;
|
|
251
230
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
252
231
|
let result = allocateFee(requests, fee, FeePaidByEnum.any, BigInt(1362));
|
|
253
|
-
expect(result[0].value).toBe(
|
|
254
|
-
expect(result[1].value).toBe(
|
|
255
|
-
expect(result[2].value).toBe(
|
|
232
|
+
expect(result[0].value).toBe(546n);
|
|
233
|
+
expect(result[1].value).toBe(546n);
|
|
234
|
+
expect(result[2].value).toBe(546n);
|
|
256
235
|
});
|
|
257
236
|
|
|
258
237
|
test("Expect `change,any` to consume only change", async () => {
|
|
259
238
|
let to = [
|
|
260
|
-
["alice",
|
|
261
|
-
["bob",
|
|
262
|
-
["charlie",
|
|
239
|
+
["alice", 1000n],
|
|
240
|
+
["bob", 1000n],
|
|
241
|
+
["charlie", 1000n],
|
|
263
242
|
];
|
|
264
|
-
let fee =
|
|
243
|
+
let fee = 1362n;
|
|
265
244
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
266
245
|
let result = allocateFee(
|
|
267
246
|
requests,
|
|
@@ -269,18 +248,18 @@ describe("Fee tests", () => {
|
|
|
269
248
|
FeePaidByEnum.changeThenAny,
|
|
270
249
|
BigInt(1362)
|
|
271
250
|
);
|
|
272
|
-
expect(result[0].value).toBe(
|
|
273
|
-
expect(result[1].value).toBe(
|
|
274
|
-
expect(result[2].value).toBe(
|
|
251
|
+
expect(result[0].value).toBe(1000n);
|
|
252
|
+
expect(result[1].value).toBe(1000n);
|
|
253
|
+
expect(result[2].value).toBe(1000n);
|
|
275
254
|
});
|
|
276
255
|
|
|
277
256
|
test("Expect `change,any` to use both", async () => {
|
|
278
257
|
let to = [
|
|
279
|
-
["alice",
|
|
280
|
-
["bob",
|
|
281
|
-
["charlie",
|
|
258
|
+
["alice", 1000n],
|
|
259
|
+
["bob", 1000n],
|
|
260
|
+
["charlie", 1000n],
|
|
282
261
|
];
|
|
283
|
-
let fee =
|
|
262
|
+
let fee = 1362n * 2n;
|
|
284
263
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
285
264
|
let result = allocateFee(
|
|
286
265
|
requests,
|
|
@@ -288,32 +267,32 @@ describe("Fee tests", () => {
|
|
|
288
267
|
FeePaidByEnum.changeThenAny,
|
|
289
268
|
BigInt(1362)
|
|
290
269
|
);
|
|
291
|
-
expect(result[0].value).toBe(
|
|
292
|
-
expect(result[1].value).toBe(
|
|
293
|
-
expect(result[2].value).toBe(
|
|
270
|
+
expect(result[0].value).toBe(546n);
|
|
271
|
+
expect(result[1].value).toBe(546n);
|
|
272
|
+
expect(result[2].value).toBe(546n);
|
|
294
273
|
});
|
|
295
274
|
|
|
296
275
|
test("Expect sortSendRequests to sort by lowest value first", async () => {
|
|
297
276
|
let to = [
|
|
298
|
-
["alice",
|
|
299
|
-
["bob",
|
|
300
|
-
["charlie",
|
|
301
|
-
["dave",
|
|
302
|
-
["edward",
|
|
303
|
-
["fred",
|
|
304
|
-
["greg",
|
|
305
|
-
["harry",
|
|
277
|
+
["alice", 2000n],
|
|
278
|
+
["bob", 547n],
|
|
279
|
+
["charlie", 1n],
|
|
280
|
+
["dave", 4n],
|
|
281
|
+
["edward", 6n],
|
|
282
|
+
["fred", 2000n],
|
|
283
|
+
["greg", 2000n],
|
|
284
|
+
["harry", 2000n],
|
|
306
285
|
];
|
|
307
|
-
let fee =
|
|
286
|
+
let fee = 1n;
|
|
308
287
|
let requests = asSendRequestObject(to) as SendRequest[];
|
|
309
288
|
|
|
310
289
|
let result = sortSendRequests(requests);
|
|
311
|
-
expect(result[0].value).toBe(
|
|
312
|
-
expect(result[1].value).toBe(
|
|
313
|
-
expect(result[2].value).toBe(
|
|
314
|
-
expect(result[3].value).toBe(
|
|
315
|
-
expect(result[4].value).toBe(
|
|
316
|
-
expect(result[5].value).toBe(
|
|
290
|
+
expect(result[0].value).toBe(1n);
|
|
291
|
+
expect(result[1].value).toBe(4n);
|
|
292
|
+
expect(result[2].value).toBe(6n);
|
|
293
|
+
expect(result[3].value).toBe(547n);
|
|
294
|
+
expect(result[4].value).toBe(2000n);
|
|
295
|
+
expect(result[5].value).toBe(2000n);
|
|
317
296
|
expect(result.length).toBe(8);
|
|
318
297
|
});
|
|
319
298
|
});
|