bitbadgesjs-sdk 0.31.0 → 0.31.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/cjs/api-indexer/BitBadgesCollection.d.ts +1 -0
- package/dist/cjs/api-indexer/BitBadgesCollection.d.ts.map +1 -1
- package/dist/cjs/api-indexer/BitBadgesCollection.js +4 -1
- package/dist/cjs/api-indexer/BitBadgesCollection.js.map +1 -1
- package/dist/cjs/core/approval-utils.spec.d.ts +2 -0
- package/dist/cjs/core/approval-utils.spec.d.ts.map +1 -0
- package/dist/cjs/core/approval-utils.spec.js +240 -0
- package/dist/cjs/core/approval-utils.spec.js.map +1 -0
- package/dist/cjs/core/approvals.spec.js +96 -0
- package/dist/cjs/core/approvals.spec.js.map +1 -1
- package/dist/cjs/core/bids.spec.d.ts +2 -0
- package/dist/cjs/core/bids.spec.d.ts.map +1 -0
- package/dist/cjs/core/bids.spec.js +201 -0
- package/dist/cjs/core/bids.spec.js.map +1 -0
- package/dist/cjs/core/blockin.spec.d.ts +2 -0
- package/dist/cjs/core/blockin.spec.d.ts.map +1 -0
- package/dist/cjs/core/blockin.spec.js +163 -0
- package/dist/cjs/core/blockin.spec.js.map +1 -0
- package/dist/cjs/core/coin.spec.d.ts +2 -0
- package/dist/cjs/core/coin.spec.d.ts.map +1 -0
- package/dist/cjs/core/coin.spec.js +80 -0
- package/dist/cjs/core/coin.spec.js.map +1 -0
- package/dist/cjs/core/cosmos-wrappers.spec.d.ts +2 -0
- package/dist/cjs/core/cosmos-wrappers.spec.d.ts.map +1 -0
- package/dist/cjs/core/cosmos-wrappers.spec.js +623 -0
- package/dist/cjs/core/cosmos-wrappers.spec.js.map +1 -0
- package/dist/cjs/core/managersplitter.spec.d.ts +2 -0
- package/dist/cjs/core/managersplitter.spec.d.ts.map +1 -0
- package/dist/cjs/core/managersplitter.spec.js +170 -0
- package/dist/cjs/core/managersplitter.spec.js.map +1 -0
- package/dist/cjs/core/overlaps.spec.js +201 -0
- package/dist/cjs/core/overlaps.spec.js.map +1 -1
- package/dist/cjs/core/permission-utils.spec.d.ts +2 -0
- package/dist/cjs/core/permission-utils.spec.d.ts.map +1 -0
- package/dist/cjs/core/permission-utils.spec.js +192 -0
- package/dist/cjs/core/permission-utils.spec.js.map +1 -0
- package/dist/cjs/core/permissions.js +4 -4
- package/dist/cjs/core/permissions.js.map +1 -1
- package/dist/cjs/core/permissions.spec.d.ts +2 -0
- package/dist/cjs/core/permissions.spec.d.ts.map +1 -0
- package/dist/cjs/core/permissions.spec.js +2051 -0
- package/dist/cjs/core/permissions.spec.js.map +1 -0
- package/dist/cjs/core/transfers.d.ts.map +1 -1
- package/dist/cjs/core/transfers.js +11 -7
- package/dist/cjs/core/transfers.js.map +1 -1
- package/dist/cjs/core/transfers.spec.js +647 -0
- package/dist/cjs/core/transfers.spec.js.map +1 -1
- package/dist/cjs/core/userBalances.spec.d.ts +2 -0
- package/dist/cjs/core/userBalances.spec.d.ts.map +1 -0
- package/dist/cjs/core/userBalances.spec.js +184 -0
- package/dist/cjs/core/userBalances.spec.js.map +1 -0
- package/dist/cjs/core/validate-utils.spec.d.ts +2 -0
- package/dist/cjs/core/validate-utils.spec.d.ts.map +1 -0
- package/dist/cjs/core/validate-utils.spec.js +202 -0
- package/dist/cjs/core/validate-utils.spec.js.map +1 -0
- package/dist/cjs/tsconfig.build.tsbuildinfo +1 -1
- package/dist/esm/api-indexer/BitBadgesCollection.d.ts +1 -0
- package/dist/esm/api-indexer/BitBadgesCollection.d.ts.map +1 -1
- package/dist/esm/api-indexer/BitBadgesCollection.js +4 -1
- package/dist/esm/api-indexer/BitBadgesCollection.js.map +1 -1
- package/dist/esm/core/approval-utils.spec.d.ts +2 -0
- package/dist/esm/core/approval-utils.spec.d.ts.map +1 -0
- package/dist/esm/core/approval-utils.spec.js +238 -0
- package/dist/esm/core/approval-utils.spec.js.map +1 -0
- package/dist/esm/core/approvals.spec.js +97 -1
- package/dist/esm/core/approvals.spec.js.map +1 -1
- package/dist/esm/core/bids.spec.d.ts +2 -0
- package/dist/esm/core/bids.spec.d.ts.map +1 -0
- package/dist/esm/core/bids.spec.js +199 -0
- package/dist/esm/core/bids.spec.js.map +1 -0
- package/dist/esm/core/blockin.spec.d.ts +2 -0
- package/dist/esm/core/blockin.spec.d.ts.map +1 -0
- package/dist/esm/core/blockin.spec.js +161 -0
- package/dist/esm/core/blockin.spec.js.map +1 -0
- package/dist/esm/core/coin.spec.d.ts +2 -0
- package/dist/esm/core/coin.spec.d.ts.map +1 -0
- package/dist/esm/core/coin.spec.js +78 -0
- package/dist/esm/core/coin.spec.js.map +1 -0
- package/dist/esm/core/cosmos-wrappers.spec.d.ts +2 -0
- package/dist/esm/core/cosmos-wrappers.spec.d.ts.map +1 -0
- package/dist/esm/core/cosmos-wrappers.spec.js +621 -0
- package/dist/esm/core/cosmos-wrappers.spec.js.map +1 -0
- package/dist/esm/core/managersplitter.spec.d.ts +2 -0
- package/dist/esm/core/managersplitter.spec.d.ts.map +1 -0
- package/dist/esm/core/managersplitter.spec.js +168 -0
- package/dist/esm/core/managersplitter.spec.js.map +1 -0
- package/dist/esm/core/overlaps.spec.js +202 -1
- package/dist/esm/core/overlaps.spec.js.map +1 -1
- package/dist/esm/core/permission-utils.spec.d.ts +2 -0
- package/dist/esm/core/permission-utils.spec.d.ts.map +1 -0
- package/dist/esm/core/permission-utils.spec.js +190 -0
- package/dist/esm/core/permission-utils.spec.js.map +1 -0
- package/dist/esm/core/permissions.js +4 -4
- package/dist/esm/core/permissions.js.map +1 -1
- package/dist/esm/core/permissions.spec.d.ts +2 -0
- package/dist/esm/core/permissions.spec.d.ts.map +1 -0
- package/dist/esm/core/permissions.spec.js +2049 -0
- package/dist/esm/core/permissions.spec.js.map +1 -0
- package/dist/esm/core/transfers.d.ts.map +1 -1
- package/dist/esm/core/transfers.js +11 -7
- package/dist/esm/core/transfers.js.map +1 -1
- package/dist/esm/core/transfers.spec.js +648 -1
- package/dist/esm/core/transfers.spec.js.map +1 -1
- package/dist/esm/core/userBalances.spec.d.ts +2 -0
- package/dist/esm/core/userBalances.spec.d.ts.map +1 -0
- package/dist/esm/core/userBalances.spec.js +182 -0
- package/dist/esm/core/userBalances.spec.js.map +1 -0
- package/dist/esm/core/validate-utils.spec.d.ts +2 -0
- package/dist/esm/core/validate-utils.spec.d.ts.map +1 -0
- package/dist/esm/core/validate-utils.spec.js +200 -0
- package/dist/esm/core/validate-utils.spec.js.map +1 -0
- package/dist/esm/tsconfig-esm.build.tsbuildinfo +1 -1
- package/package.json +4 -5
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { genTestAddress } from './addressLists.spec.js';
|
|
2
|
-
import { createBalanceMapForOffChainBalances, getAllTokenIdsToBeTransferred, getAllBalancesToBeTransferred, getBalancesAfterTransfers } from './transfers.js';
|
|
2
|
+
import { createBalanceMapForOffChainBalances, convertOffChainBalancesMap, getAllTokenIdsToBeTransferred, getAllBalancesToBeTransferred, getBalancesAfterTransfers, getBalanceAfterTransfer, getTransfersFromTransfersWithIncrements, Transfer, TransferWithIncrements } from './transfers.js';
|
|
3
3
|
import { UintRangeArray } from './uintRanges.js';
|
|
4
|
+
import { BigIntify, Stringify } from '../common/string-numbers.js';
|
|
5
|
+
import { ApprovalIdentifierDetails, MerkleProof, ETHSignatureProof } from './misc.js';
|
|
4
6
|
BigInt.prototype.toJSON = function () {
|
|
5
7
|
return this.toString();
|
|
6
8
|
};
|
|
@@ -383,6 +385,651 @@ describe('Transfers', () => {
|
|
|
383
385
|
const allBalances = getAllBalancesToBeTransferred(transfersWithIncrements, currentTime);
|
|
384
386
|
expect(allBalances.length).toBeGreaterThan(0);
|
|
385
387
|
});
|
|
388
|
+
it('should compute end time as blockTime + duration - 1 (matching on-chain behavior) via slow path', () => {
|
|
389
|
+
const blockTime = 1000000n;
|
|
390
|
+
const duration = 50000n;
|
|
391
|
+
const expectedEnd = blockTime + duration - 1n;
|
|
392
|
+
const startingBalances = [
|
|
393
|
+
{
|
|
394
|
+
amount: 1n,
|
|
395
|
+
tokenIds: [{ start: 1n, end: 10n }],
|
|
396
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
397
|
+
}
|
|
398
|
+
];
|
|
399
|
+
const transfersWithIncrements = [
|
|
400
|
+
{
|
|
401
|
+
from: 'Mint',
|
|
402
|
+
balances: [
|
|
403
|
+
{
|
|
404
|
+
amount: 1n,
|
|
405
|
+
tokenIds: [{ start: 1n, end: 2n }],
|
|
406
|
+
ownershipTimes: [{ start: blockTime, end: expectedEnd }]
|
|
407
|
+
}
|
|
408
|
+
],
|
|
409
|
+
toAddresses: [genTestAddress(), genTestAddress(), genTestAddress()],
|
|
410
|
+
incrementTokenIdsBy: 3n,
|
|
411
|
+
incrementOwnershipTimesBy: 0n,
|
|
412
|
+
durationFromTimestamp: duration
|
|
413
|
+
}
|
|
414
|
+
];
|
|
415
|
+
const balancesAfterTransfers = getBalancesAfterTransfers(startingBalances, transfersWithIncrements, blockTime);
|
|
416
|
+
const remaining = balancesAfterTransfers.filterZeroBalances();
|
|
417
|
+
expect(remaining.length).toBeGreaterThan(0);
|
|
418
|
+
});
|
|
419
|
+
it('should compute end time as blockTime + duration - 1 via fast path', () => {
|
|
420
|
+
const blockTime = 1000000n;
|
|
421
|
+
const duration = 50000n;
|
|
422
|
+
const expectedEnd = blockTime + duration - 1n;
|
|
423
|
+
const startingBalances = [
|
|
424
|
+
{
|
|
425
|
+
amount: 1n,
|
|
426
|
+
tokenIds: [{ start: 1n, end: 100n }],
|
|
427
|
+
ownershipTimes: [{ start: blockTime, end: expectedEnd }]
|
|
428
|
+
}
|
|
429
|
+
];
|
|
430
|
+
const transfersWithIncrements = [
|
|
431
|
+
{
|
|
432
|
+
from: 'Mint',
|
|
433
|
+
balances: [
|
|
434
|
+
{
|
|
435
|
+
amount: 1n,
|
|
436
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
437
|
+
ownershipTimes: [{ start: 0n, end: 100000n }]
|
|
438
|
+
}
|
|
439
|
+
],
|
|
440
|
+
toAddresses: [],
|
|
441
|
+
toAddressesLength: 100n,
|
|
442
|
+
incrementTokenIdsBy: 1n,
|
|
443
|
+
incrementOwnershipTimesBy: 0n,
|
|
444
|
+
durationFromTimestamp: duration
|
|
445
|
+
}
|
|
446
|
+
];
|
|
447
|
+
const allBalances = getAllBalancesToBeTransferred(transfersWithIncrements, blockTime);
|
|
448
|
+
expect(allBalances.length).toBeGreaterThan(0);
|
|
449
|
+
for (const balance of allBalances) {
|
|
450
|
+
for (const ownershipTime of balance.ownershipTimes) {
|
|
451
|
+
expect(ownershipTime.start).toBe(blockTime);
|
|
452
|
+
expect(ownershipTime.end).toBe(expectedEnd);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
const balancesAfterTransfers = getBalancesAfterTransfers(startingBalances, transfersWithIncrements, blockTime);
|
|
456
|
+
expect(balancesAfterTransfers.filterZeroBalances().length).toBe(0);
|
|
457
|
+
});
|
|
458
|
+
it('should NOT match if end time were blockTime + duration (without -1)', () => {
|
|
459
|
+
const blockTime = 1000000n;
|
|
460
|
+
const duration = 50000n;
|
|
461
|
+
const wrongEnd = blockTime + duration;
|
|
462
|
+
const allBalances = getAllBalancesToBeTransferred([
|
|
463
|
+
{
|
|
464
|
+
from: 'Mint',
|
|
465
|
+
balances: [
|
|
466
|
+
{
|
|
467
|
+
amount: 1n,
|
|
468
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
469
|
+
ownershipTimes: [{ start: 0n, end: 100000n }]
|
|
470
|
+
}
|
|
471
|
+
],
|
|
472
|
+
toAddresses: [genTestAddress()],
|
|
473
|
+
incrementTokenIdsBy: 0n,
|
|
474
|
+
incrementOwnershipTimesBy: 0n,
|
|
475
|
+
durationFromTimestamp: duration
|
|
476
|
+
}
|
|
477
|
+
], blockTime);
|
|
478
|
+
for (const balance of allBalances) {
|
|
479
|
+
for (const ownershipTime of balance.ownershipTimes) {
|
|
480
|
+
expect(ownershipTime.end).not.toBe(wrongEnd);
|
|
481
|
+
expect(ownershipTime.end).toBe(wrongEnd - 1n);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
it('should give all recipients the same duration-based ownership times', () => {
|
|
486
|
+
const blockTime = 1000000n;
|
|
487
|
+
const duration = 86400000n;
|
|
488
|
+
const recipients = [genTestAddress(), genTestAddress(), genTestAddress()];
|
|
489
|
+
const transfers = getTransfersFromTransfersWithIncrements([
|
|
490
|
+
{
|
|
491
|
+
from: 'Mint',
|
|
492
|
+
toAddresses: recipients,
|
|
493
|
+
balances: [
|
|
494
|
+
{
|
|
495
|
+
amount: 1n,
|
|
496
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
497
|
+
ownershipTimes: [{ start: 0n, end: 100000n }]
|
|
498
|
+
}
|
|
499
|
+
],
|
|
500
|
+
durationFromTimestamp: duration
|
|
501
|
+
}
|
|
502
|
+
], blockTime);
|
|
503
|
+
expect(transfers.length).toBe(3);
|
|
504
|
+
const expectedStart = blockTime;
|
|
505
|
+
const expectedEnd = blockTime + duration - 1n;
|
|
506
|
+
for (let i = 0; i < transfers.length; i++) {
|
|
507
|
+
expect(transfers[i].balances[0].ownershipTimes[0].start).toBe(expectedStart);
|
|
508
|
+
expect(transfers[i].balances[0].ownershipTimes[0].end).toBe(expectedEnd);
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
});
|
|
512
|
+
describe('Transfer class', () => {
|
|
513
|
+
it('should construct a Transfer with required fields', () => {
|
|
514
|
+
const addr1 = genTestAddress();
|
|
515
|
+
const addr2 = genTestAddress();
|
|
516
|
+
const transfer = new Transfer({
|
|
517
|
+
from: addr1,
|
|
518
|
+
toAddresses: [addr2],
|
|
519
|
+
balances: [
|
|
520
|
+
{
|
|
521
|
+
amount: 10n,
|
|
522
|
+
tokenIds: [{ start: 1n, end: 5n }],
|
|
523
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
524
|
+
}
|
|
525
|
+
]
|
|
526
|
+
});
|
|
527
|
+
expect(transfer.from).toBe(addr1);
|
|
528
|
+
expect(transfer.toAddresses).toEqual([addr2]);
|
|
529
|
+
expect(transfer.balances.length).toBe(1);
|
|
530
|
+
expect(transfer.balances[0].amount).toBe(10n);
|
|
531
|
+
});
|
|
532
|
+
it('should construct with optional memo', () => {
|
|
533
|
+
const transfer = new Transfer({
|
|
534
|
+
from: genTestAddress(),
|
|
535
|
+
toAddresses: [genTestAddress()],
|
|
536
|
+
balances: [],
|
|
537
|
+
memo: 'test memo'
|
|
538
|
+
});
|
|
539
|
+
expect(transfer.memo).toBe('test memo');
|
|
540
|
+
});
|
|
541
|
+
it('should return empty number field names', () => {
|
|
542
|
+
const transfer = new Transfer({
|
|
543
|
+
from: genTestAddress(),
|
|
544
|
+
toAddresses: [],
|
|
545
|
+
balances: []
|
|
546
|
+
});
|
|
547
|
+
expect(transfer.getNumberFieldNames()).toEqual([]);
|
|
548
|
+
});
|
|
549
|
+
it('should convert between number types', () => {
|
|
550
|
+
const transfer = new Transfer({
|
|
551
|
+
from: genTestAddress(),
|
|
552
|
+
toAddresses: [genTestAddress()],
|
|
553
|
+
balances: [
|
|
554
|
+
{
|
|
555
|
+
amount: 100n,
|
|
556
|
+
tokenIds: [{ start: 1n, end: 10n }],
|
|
557
|
+
ownershipTimes: [{ start: 1n, end: 1000n }]
|
|
558
|
+
}
|
|
559
|
+
]
|
|
560
|
+
});
|
|
561
|
+
const stringified = transfer.convert(Stringify);
|
|
562
|
+
expect(stringified.balances[0].amount).toBe('100');
|
|
563
|
+
expect(stringified.balances[0].tokenIds[0].start).toBe('1');
|
|
564
|
+
expect(stringified.balances[0].tokenIds[0].end).toBe('10');
|
|
565
|
+
});
|
|
566
|
+
it('should handle optional fields being undefined', () => {
|
|
567
|
+
const transfer = new Transfer({
|
|
568
|
+
from: genTestAddress(),
|
|
569
|
+
toAddresses: [],
|
|
570
|
+
balances: []
|
|
571
|
+
});
|
|
572
|
+
expect(transfer.precalculateBalancesFromApproval).toBeUndefined();
|
|
573
|
+
expect(transfer.merkleProofs).toBeUndefined();
|
|
574
|
+
expect(transfer.ethSignatureProofs).toBeUndefined();
|
|
575
|
+
expect(transfer.memo).toBeUndefined();
|
|
576
|
+
expect(transfer.prioritizedApprovals).toBeUndefined();
|
|
577
|
+
expect(transfer.onlyCheckPrioritizedCollectionApprovals).toBeUndefined();
|
|
578
|
+
expect(transfer.onlyCheckPrioritizedIncomingApprovals).toBeUndefined();
|
|
579
|
+
expect(transfer.onlyCheckPrioritizedOutgoingApprovals).toBeUndefined();
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
describe('TransferWithIncrements class', () => {
|
|
583
|
+
it('should construct with increment fields', () => {
|
|
584
|
+
const twi = new TransferWithIncrements({
|
|
585
|
+
from: genTestAddress(),
|
|
586
|
+
toAddresses: [genTestAddress()],
|
|
587
|
+
balances: [
|
|
588
|
+
{
|
|
589
|
+
amount: 1n,
|
|
590
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
591
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
592
|
+
}
|
|
593
|
+
],
|
|
594
|
+
incrementTokenIdsBy: 1n,
|
|
595
|
+
incrementOwnershipTimesBy: 0n,
|
|
596
|
+
toAddressesLength: 100n,
|
|
597
|
+
durationFromTimestamp: 0n
|
|
598
|
+
});
|
|
599
|
+
expect(twi.incrementTokenIdsBy).toBe(1n);
|
|
600
|
+
expect(twi.incrementOwnershipTimesBy).toBe(0n);
|
|
601
|
+
expect(twi.toAddressesLength).toBe(100n);
|
|
602
|
+
expect(twi.durationFromTimestamp).toBe(0n);
|
|
603
|
+
});
|
|
604
|
+
it('should return correct number field names', () => {
|
|
605
|
+
const twi = new TransferWithIncrements({
|
|
606
|
+
from: genTestAddress(),
|
|
607
|
+
toAddresses: [],
|
|
608
|
+
balances: []
|
|
609
|
+
});
|
|
610
|
+
expect(twi.getNumberFieldNames()).toEqual([
|
|
611
|
+
'toAddressesLength',
|
|
612
|
+
'incrementTokenIdsBy',
|
|
613
|
+
'incrementOwnershipTimesBy',
|
|
614
|
+
'durationFromTimestamp'
|
|
615
|
+
]);
|
|
616
|
+
});
|
|
617
|
+
it('should convert between number types', () => {
|
|
618
|
+
const twi = new TransferWithIncrements({
|
|
619
|
+
from: genTestAddress(),
|
|
620
|
+
toAddresses: [],
|
|
621
|
+
balances: [
|
|
622
|
+
{
|
|
623
|
+
amount: 50n,
|
|
624
|
+
tokenIds: [{ start: 1n, end: 10n }],
|
|
625
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
626
|
+
}
|
|
627
|
+
],
|
|
628
|
+
incrementTokenIdsBy: 5n,
|
|
629
|
+
toAddressesLength: 20n
|
|
630
|
+
});
|
|
631
|
+
const stringified = twi.convert(Stringify);
|
|
632
|
+
expect(stringified.incrementTokenIdsBy).toBe('5');
|
|
633
|
+
expect(stringified.toAddressesLength).toBe('20');
|
|
634
|
+
expect(stringified.balances[0].amount).toBe('50');
|
|
635
|
+
});
|
|
636
|
+
it('should handle undefined optional increment fields', () => {
|
|
637
|
+
const twi = new TransferWithIncrements({
|
|
638
|
+
from: genTestAddress(),
|
|
639
|
+
toAddresses: [],
|
|
640
|
+
balances: []
|
|
641
|
+
});
|
|
642
|
+
expect(twi.incrementTokenIdsBy).toBeUndefined();
|
|
643
|
+
expect(twi.incrementOwnershipTimesBy).toBeUndefined();
|
|
644
|
+
expect(twi.toAddressesLength).toBeUndefined();
|
|
645
|
+
expect(twi.durationFromTimestamp).toBeUndefined();
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
describe('getBalanceAfterTransfer (single)', () => {
|
|
649
|
+
it('should subtract a single transfer from balance', () => {
|
|
650
|
+
const startBalance = [
|
|
651
|
+
{
|
|
652
|
+
amount: 100n,
|
|
653
|
+
tokenIds: [{ start: 1n, end: 10n }],
|
|
654
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
655
|
+
}
|
|
656
|
+
];
|
|
657
|
+
const result = getBalanceAfterTransfer(startBalance, 1n, 10n, 1n, 18446744073709551615n, 10n, 1n);
|
|
658
|
+
expect(result[0].amount).toBe(90n);
|
|
659
|
+
});
|
|
660
|
+
it('should multiply amount by numRecipients', () => {
|
|
661
|
+
const startBalance = [
|
|
662
|
+
{
|
|
663
|
+
amount: 100n,
|
|
664
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
665
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
666
|
+
}
|
|
667
|
+
];
|
|
668
|
+
const result = getBalanceAfterTransfer(startBalance, 1n, 1n, 1n, 18446744073709551615n, 10n, 5n);
|
|
669
|
+
expect(result[0].amount).toBe(50n);
|
|
670
|
+
});
|
|
671
|
+
it('should throw on underflow without allowUnderflow', () => {
|
|
672
|
+
const startBalance = [
|
|
673
|
+
{
|
|
674
|
+
amount: 10n,
|
|
675
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
676
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
677
|
+
}
|
|
678
|
+
];
|
|
679
|
+
expect(() => getBalanceAfterTransfer(startBalance, 1n, 1n, 1n, 18446744073709551615n, 20n, 1n, false)).toThrow();
|
|
680
|
+
});
|
|
681
|
+
it('should allow underflow when flag is set', () => {
|
|
682
|
+
const startBalance = [
|
|
683
|
+
{
|
|
684
|
+
amount: 10n,
|
|
685
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
686
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
687
|
+
}
|
|
688
|
+
];
|
|
689
|
+
const result = getBalanceAfterTransfer(startBalance, 1n, 1n, 1n, 18446744073709551615n, 20n, 1n, true);
|
|
690
|
+
expect(result[0].amount).toBe(-10n);
|
|
691
|
+
});
|
|
692
|
+
it('should return empty array when balance is fully depleted', () => {
|
|
693
|
+
const startBalance = [
|
|
694
|
+
{
|
|
695
|
+
amount: 50n,
|
|
696
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
697
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
698
|
+
}
|
|
699
|
+
];
|
|
700
|
+
const result = getBalanceAfterTransfer(startBalance, 1n, 1n, 1n, 18446744073709551615n, 50n, 1n);
|
|
701
|
+
const filtered = result.filter((b) => b.amount > 0n);
|
|
702
|
+
expect(filtered.length).toBe(0);
|
|
703
|
+
});
|
|
704
|
+
it('should only subtract from matching token ID range', () => {
|
|
705
|
+
const startBalance = [
|
|
706
|
+
{
|
|
707
|
+
amount: 100n,
|
|
708
|
+
tokenIds: [{ start: 1n, end: 10n }],
|
|
709
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
710
|
+
}
|
|
711
|
+
];
|
|
712
|
+
const result = getBalanceAfterTransfer(startBalance, 5n, 5n, 1n, 18446744073709551615n, 50n, 1n);
|
|
713
|
+
const totalNonZero = result.filter((b) => b.amount > 0n);
|
|
714
|
+
expect(totalNonZero.length).toBeGreaterThan(0);
|
|
715
|
+
});
|
|
716
|
+
});
|
|
717
|
+
describe('convertOffChainBalancesMap', () => {
|
|
718
|
+
it('should convert balances map between number types', () => {
|
|
719
|
+
const bigintMap = {
|
|
720
|
+
[genTestAddress()]: [
|
|
721
|
+
{
|
|
722
|
+
amount: 100n,
|
|
723
|
+
tokenIds: [{ start: 1n, end: 10n }],
|
|
724
|
+
ownershipTimes: [{ start: 1n, end: 1000n }]
|
|
725
|
+
}
|
|
726
|
+
]
|
|
727
|
+
};
|
|
728
|
+
const stringMap = convertOffChainBalancesMap(bigintMap, Stringify);
|
|
729
|
+
const keys = Object.keys(stringMap);
|
|
730
|
+
expect(keys.length).toBe(1);
|
|
731
|
+
expect(stringMap[keys[0]][0].amount).toBe('100');
|
|
732
|
+
expect(stringMap[keys[0]][0].tokenIds[0].start).toBe('1');
|
|
733
|
+
});
|
|
734
|
+
it('should handle empty map', () => {
|
|
735
|
+
const result = convertOffChainBalancesMap({}, Stringify);
|
|
736
|
+
expect(Object.keys(result).length).toBe(0);
|
|
737
|
+
});
|
|
738
|
+
it('should handle map with multiple addresses', () => {
|
|
739
|
+
const addr1 = genTestAddress();
|
|
740
|
+
const addr2 = genTestAddress();
|
|
741
|
+
const bigintMap = {
|
|
742
|
+
[addr1]: [
|
|
743
|
+
{
|
|
744
|
+
amount: 50n,
|
|
745
|
+
tokenIds: [{ start: 1n, end: 5n }],
|
|
746
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
747
|
+
}
|
|
748
|
+
],
|
|
749
|
+
[addr2]: [
|
|
750
|
+
{
|
|
751
|
+
amount: 200n,
|
|
752
|
+
tokenIds: [{ start: 10n, end: 20n }],
|
|
753
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
754
|
+
}
|
|
755
|
+
]
|
|
756
|
+
};
|
|
757
|
+
const stringMap = convertOffChainBalancesMap(bigintMap, Stringify);
|
|
758
|
+
expect(stringMap[addr1][0].amount).toBe('50');
|
|
759
|
+
expect(stringMap[addr2][0].amount).toBe('200');
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
describe('createBalanceMapForOffChainBalances - error paths', () => {
|
|
763
|
+
it('should throw when durationFromTimestamp is used', () => {
|
|
764
|
+
const transfers = [
|
|
765
|
+
{
|
|
766
|
+
from: 'Mint',
|
|
767
|
+
balances: [
|
|
768
|
+
{
|
|
769
|
+
amount: 1n,
|
|
770
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
771
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
772
|
+
}
|
|
773
|
+
],
|
|
774
|
+
toAddresses: [genTestAddress()],
|
|
775
|
+
durationFromTimestamp: 86400000n
|
|
776
|
+
}
|
|
777
|
+
];
|
|
778
|
+
expect(() => createBalanceMapForOffChainBalances(transfers)).toThrow('durationFromTimestamp is not supported in createBalanceMapForOffChainBalances');
|
|
779
|
+
});
|
|
780
|
+
});
|
|
781
|
+
describe('getTransfersFromTransfersWithIncrements', () => {
|
|
782
|
+
it('should return single transfer when no increments', () => {
|
|
783
|
+
const addr1 = genTestAddress();
|
|
784
|
+
const addr2 = genTestAddress();
|
|
785
|
+
const transfers = getTransfersFromTransfersWithIncrements([
|
|
786
|
+
{
|
|
787
|
+
from: addr1,
|
|
788
|
+
toAddresses: [addr2],
|
|
789
|
+
balances: [
|
|
790
|
+
{
|
|
791
|
+
amount: 10n,
|
|
792
|
+
tokenIds: [{ start: 1n, end: 10n }],
|
|
793
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
794
|
+
}
|
|
795
|
+
]
|
|
796
|
+
}
|
|
797
|
+
], 0n);
|
|
798
|
+
expect(transfers.length).toBe(1);
|
|
799
|
+
expect(transfers[0].toAddresses).toEqual([addr2]);
|
|
800
|
+
});
|
|
801
|
+
it('should create N transfers when incrementTokenIdsBy is set', () => {
|
|
802
|
+
const recipients = [genTestAddress(), genTestAddress(), genTestAddress()];
|
|
803
|
+
const transfers = getTransfersFromTransfersWithIncrements([
|
|
804
|
+
{
|
|
805
|
+
from: 'Mint',
|
|
806
|
+
toAddresses: recipients,
|
|
807
|
+
balances: [
|
|
808
|
+
{
|
|
809
|
+
amount: 1n,
|
|
810
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
811
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
812
|
+
}
|
|
813
|
+
],
|
|
814
|
+
incrementTokenIdsBy: 1n
|
|
815
|
+
}
|
|
816
|
+
], 0n);
|
|
817
|
+
expect(transfers.length).toBe(3);
|
|
818
|
+
expect(transfers[0].balances[0].tokenIds[0].start).toBe(1n);
|
|
819
|
+
expect(transfers[0].balances[0].tokenIds[0].end).toBe(1n);
|
|
820
|
+
expect(transfers[1].balances[0].tokenIds[0].start).toBe(2n);
|
|
821
|
+
expect(transfers[2].balances[0].tokenIds[0].start).toBe(3n);
|
|
822
|
+
});
|
|
823
|
+
it('should create N transfers when incrementOwnershipTimesBy is set', () => {
|
|
824
|
+
const recipients = [genTestAddress(), genTestAddress()];
|
|
825
|
+
const transfers = getTransfersFromTransfersWithIncrements([
|
|
826
|
+
{
|
|
827
|
+
from: 'Mint',
|
|
828
|
+
toAddresses: recipients,
|
|
829
|
+
balances: [
|
|
830
|
+
{
|
|
831
|
+
amount: 1n,
|
|
832
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
833
|
+
ownershipTimes: [{ start: 1000n, end: 2000n }]
|
|
834
|
+
}
|
|
835
|
+
],
|
|
836
|
+
incrementOwnershipTimesBy: 5000n
|
|
837
|
+
}
|
|
838
|
+
], 0n);
|
|
839
|
+
expect(transfers.length).toBe(2);
|
|
840
|
+
expect(transfers[0].balances[0].ownershipTimes[0].start).toBe(1000n);
|
|
841
|
+
expect(transfers[0].balances[0].ownershipTimes[0].end).toBe(2000n);
|
|
842
|
+
expect(transfers[1].balances[0].ownershipTimes[0].start).toBe(6000n);
|
|
843
|
+
expect(transfers[1].balances[0].ownershipTimes[0].end).toBe(7000n);
|
|
844
|
+
});
|
|
845
|
+
it('should handle empty transfers array', () => {
|
|
846
|
+
const transfers = getTransfersFromTransfersWithIncrements([], 0n);
|
|
847
|
+
expect(transfers.length).toBe(0);
|
|
848
|
+
});
|
|
849
|
+
it('should use toAddressesLength over toAddresses.length when both are set', () => {
|
|
850
|
+
const addr = genTestAddress();
|
|
851
|
+
const transfers = getTransfersFromTransfersWithIncrements([
|
|
852
|
+
{
|
|
853
|
+
from: 'Mint',
|
|
854
|
+
toAddresses: [addr],
|
|
855
|
+
balances: [
|
|
856
|
+
{
|
|
857
|
+
amount: 1n,
|
|
858
|
+
tokenIds: [{ start: 1n, end: 1n }],
|
|
859
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
860
|
+
}
|
|
861
|
+
]
|
|
862
|
+
}
|
|
863
|
+
], 0n);
|
|
864
|
+
expect(transfers.length).toBe(1);
|
|
865
|
+
});
|
|
866
|
+
});
|
|
867
|
+
describe('Transfer class - proto/JSON serialization', () => {
|
|
868
|
+
it('should convert to proto and back via fromProto', () => {
|
|
869
|
+
const addr1 = genTestAddress();
|
|
870
|
+
const addr2 = genTestAddress();
|
|
871
|
+
const original = new Transfer({
|
|
872
|
+
from: addr1,
|
|
873
|
+
toAddresses: [addr2],
|
|
874
|
+
balances: [
|
|
875
|
+
{
|
|
876
|
+
amount: 42n,
|
|
877
|
+
tokenIds: [{ start: 1n, end: 10n }],
|
|
878
|
+
ownershipTimes: [{ start: 1n, end: 1000n }]
|
|
879
|
+
}
|
|
880
|
+
]
|
|
881
|
+
});
|
|
882
|
+
const proto = original.toProto();
|
|
883
|
+
expect(proto).toBeTruthy();
|
|
884
|
+
const restored = Transfer.fromProto(proto, BigIntify);
|
|
885
|
+
expect(restored.from).toBe(addr1);
|
|
886
|
+
expect(restored.toAddresses).toEqual([addr2]);
|
|
887
|
+
expect(restored.balances[0].amount).toBe(42n);
|
|
888
|
+
expect(restored.balances[0].tokenIds[0].start).toBe(1n);
|
|
889
|
+
expect(restored.balances[0].tokenIds[0].end).toBe(10n);
|
|
890
|
+
});
|
|
891
|
+
it('should round-trip through fromJson', () => {
|
|
892
|
+
const addr1 = genTestAddress();
|
|
893
|
+
const addr2 = genTestAddress();
|
|
894
|
+
const original = new Transfer({
|
|
895
|
+
from: addr1,
|
|
896
|
+
toAddresses: [addr2],
|
|
897
|
+
balances: [
|
|
898
|
+
{
|
|
899
|
+
amount: 10n,
|
|
900
|
+
tokenIds: [{ start: 5n, end: 5n }],
|
|
901
|
+
ownershipTimes: [{ start: 1n, end: 100n }]
|
|
902
|
+
}
|
|
903
|
+
],
|
|
904
|
+
memo: 'hello'
|
|
905
|
+
});
|
|
906
|
+
const proto = original.toProto();
|
|
907
|
+
const jsonVal = proto.toJson();
|
|
908
|
+
const restored = Transfer.fromJson(jsonVal, BigIntify);
|
|
909
|
+
expect(restored.from).toBe(addr1);
|
|
910
|
+
expect(restored.balances[0].amount).toBe(10n);
|
|
911
|
+
expect(restored.memo).toBe('hello');
|
|
912
|
+
});
|
|
913
|
+
it('should round-trip through fromJsonString', () => {
|
|
914
|
+
const addr1 = genTestAddress();
|
|
915
|
+
const original = new Transfer({
|
|
916
|
+
from: addr1,
|
|
917
|
+
toAddresses: [],
|
|
918
|
+
balances: [
|
|
919
|
+
{
|
|
920
|
+
amount: 7n,
|
|
921
|
+
tokenIds: [{ start: 3n, end: 3n }],
|
|
922
|
+
ownershipTimes: UintRangeArray.FullRanges()
|
|
923
|
+
}
|
|
924
|
+
]
|
|
925
|
+
});
|
|
926
|
+
const jsonStr = original.toProto().toJsonString();
|
|
927
|
+
const restored = Transfer.fromJsonString(jsonStr, BigIntify);
|
|
928
|
+
expect(restored.from).toBe(addr1);
|
|
929
|
+
expect(restored.balances[0].amount).toBe(7n);
|
|
930
|
+
});
|
|
931
|
+
it('should construct Transfer with prioritizedApprovals', () => {
|
|
932
|
+
const addr1 = genTestAddress();
|
|
933
|
+
const transfer = new Transfer({
|
|
934
|
+
from: addr1,
|
|
935
|
+
toAddresses: [],
|
|
936
|
+
balances: [],
|
|
937
|
+
prioritizedApprovals: [
|
|
938
|
+
new ApprovalIdentifierDetails({
|
|
939
|
+
approvalId: 'approval-1',
|
|
940
|
+
approvalLevel: 'collection',
|
|
941
|
+
approverAddress: '',
|
|
942
|
+
version: 0n
|
|
943
|
+
})
|
|
944
|
+
],
|
|
945
|
+
onlyCheckPrioritizedCollectionApprovals: true,
|
|
946
|
+
onlyCheckPrioritizedIncomingApprovals: false,
|
|
947
|
+
onlyCheckPrioritizedOutgoingApprovals: true
|
|
948
|
+
});
|
|
949
|
+
expect(transfer.prioritizedApprovals).toBeDefined();
|
|
950
|
+
expect(transfer.prioritizedApprovals.length).toBe(1);
|
|
951
|
+
expect(transfer.prioritizedApprovals[0].approvalId).toBe('approval-1');
|
|
952
|
+
expect(transfer.onlyCheckPrioritizedCollectionApprovals).toBe(true);
|
|
953
|
+
expect(transfer.onlyCheckPrioritizedOutgoingApprovals).toBe(true);
|
|
954
|
+
});
|
|
955
|
+
it('should convert Transfer with prioritizedApprovals to proto and back', () => {
|
|
956
|
+
const addr1 = genTestAddress();
|
|
957
|
+
const transfer = new Transfer({
|
|
958
|
+
from: addr1,
|
|
959
|
+
toAddresses: [],
|
|
960
|
+
balances: [],
|
|
961
|
+
prioritizedApprovals: [
|
|
962
|
+
new ApprovalIdentifierDetails({
|
|
963
|
+
approvalId: 'approval-x',
|
|
964
|
+
approvalLevel: 'outgoing',
|
|
965
|
+
approverAddress: addr1,
|
|
966
|
+
version: 0n
|
|
967
|
+
})
|
|
968
|
+
]
|
|
969
|
+
});
|
|
970
|
+
const proto = transfer.toProto();
|
|
971
|
+
const restored = Transfer.fromProto(proto, BigIntify);
|
|
972
|
+
expect(restored.prioritizedApprovals).toBeDefined();
|
|
973
|
+
expect(restored.prioritizedApprovals[0].approvalId).toBe('approval-x');
|
|
974
|
+
});
|
|
975
|
+
it('should toBech32Addresses convert address formats', () => {
|
|
976
|
+
const addr = genTestAddress();
|
|
977
|
+
const transfer = new Transfer({
|
|
978
|
+
from: addr,
|
|
979
|
+
toAddresses: [addr],
|
|
980
|
+
balances: []
|
|
981
|
+
});
|
|
982
|
+
const converted = transfer.toBech32Addresses('bb');
|
|
983
|
+
expect(converted.from).toBeTruthy();
|
|
984
|
+
expect(converted.toAddresses.length).toBe(1);
|
|
985
|
+
});
|
|
986
|
+
it('should toBech32Addresses with prioritizedApprovals (covers line 107)', () => {
|
|
987
|
+
const addr = genTestAddress();
|
|
988
|
+
const transfer = new Transfer({
|
|
989
|
+
from: addr,
|
|
990
|
+
toAddresses: [],
|
|
991
|
+
balances: [],
|
|
992
|
+
prioritizedApprovals: [
|
|
993
|
+
new ApprovalIdentifierDetails({
|
|
994
|
+
approvalId: 'test',
|
|
995
|
+
approvalLevel: 'collection',
|
|
996
|
+
approverAddress: '',
|
|
997
|
+
version: 0n
|
|
998
|
+
})
|
|
999
|
+
]
|
|
1000
|
+
});
|
|
1001
|
+
const converted = transfer.toBech32Addresses('bb');
|
|
1002
|
+
expect(converted.prioritizedApprovals).toBeDefined();
|
|
1003
|
+
expect(converted.prioritizedApprovals.length).toBe(1);
|
|
1004
|
+
});
|
|
1005
|
+
it('should round-trip Transfer with merkleProofs through proto (covers lines 88-89)', () => {
|
|
1006
|
+
const addr = genTestAddress();
|
|
1007
|
+
const transfer = new Transfer({
|
|
1008
|
+
from: addr,
|
|
1009
|
+
toAddresses: [],
|
|
1010
|
+
balances: [],
|
|
1011
|
+
merkleProofs: [
|
|
1012
|
+
new MerkleProof({
|
|
1013
|
+
aunts: [],
|
|
1014
|
+
leaf: 'leaf-value',
|
|
1015
|
+
leafSignature: 'sig'
|
|
1016
|
+
})
|
|
1017
|
+
],
|
|
1018
|
+
ethSignatureProofs: [
|
|
1019
|
+
new ETHSignatureProof({
|
|
1020
|
+
nonce: 'nonce-123',
|
|
1021
|
+
signature: '0x1234'
|
|
1022
|
+
})
|
|
1023
|
+
]
|
|
1024
|
+
});
|
|
1025
|
+
const proto = transfer.toProto();
|
|
1026
|
+
const restored = Transfer.fromProto(proto, BigIntify);
|
|
1027
|
+
expect(restored.merkleProofs).toBeDefined();
|
|
1028
|
+
expect(restored.merkleProofs.length).toBe(1);
|
|
1029
|
+
expect(restored.merkleProofs[0].leaf).toBe('leaf-value');
|
|
1030
|
+
expect(restored.ethSignatureProofs).toBeDefined();
|
|
1031
|
+
expect(restored.ethSignatureProofs[0].nonce).toBe('nonce-123');
|
|
1032
|
+
});
|
|
386
1033
|
});
|
|
387
1034
|
});
|
|
388
1035
|
//# sourceMappingURL=transfers.spec.js.map
|