Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b9c1e44
Rename to blockchain utilities
sebastijankuzner Apr 28, 2026
594cdb9
Use BigInt in utilities
sebastijankuzner Apr 28, 2026
74ef25b
Fix round iterator
sebastijankuzner Apr 28, 2026
49dd68f
Fix block processor
sebastijankuzner Apr 28, 2026
ea457b1
Remove other uses
sebastijankuzner Apr 28, 2026
5026383
Fix api sync
sebastijankuzner Apr 28, 2026
1233cd8
Remove from keywords
sebastijankuzner Apr 28, 2026
fad1f82
Block processor
sebastijankuzner Apr 28, 2026
0ae4847
Serializer
sebastijankuzner Apr 28, 2026
fc3ad70
Transaction pool service
sebastijankuzner Apr 28, 2026
b256cd8
Configuration generator
sebastijankuzner Apr 28, 2026
ea9d0c3
Deployer
sebastijankuzner Apr 28, 2026
96c45cc
Evm consensus
sebastijankuzner Apr 28, 2026
ba4d20a
Importer
sebastijankuzner Apr 28, 2026
7b4cc5b
ApiSync
sebastijankuzner Apr 28, 2026
1b81f96
Validator
sebastijankuzner Apr 28, 2026
29defbe
Fix state tests
sebastijankuzner Apr 28, 2026
ec8ba3a
Test blockchain-utils
sebastijankuzner Apr 28, 2026
b5705ac
Test crypto-validation
sebastijankuzner Apr 28, 2026
422c60f
Webhooks
sebastijankuzner Apr 28, 2026
5ca408a
Fix test factories
sebastijankuzner Apr 28, 2026
ffda2ab
Fix test-transaction-builders
sebastijankuzner Apr 28, 2026
89a80e0
Fix functional tests
sebastijankuzner Apr 29, 2026
4cc3502
Remove BigNumber
sebastijankuzner Apr 29, 2026
f503d6f
style: resolve style guide violations [ci-lint-fix]
sebastijankuzner Apr 29, 2026
ec370a2
Fix deps
sebastijankuzner Apr 29, 2026
7b56140
style: resolve style guide violations [ci-lint-fix]
sebastijankuzner Apr 29, 2026
bf0671c
Support BigInt to JSON
sebastijankuzner Apr 29, 2026
87fe57c
Fix unit tests
sebastijankuzner Apr 29, 2026
48ba636
Ignore
sebastijankuzner Apr 29, 2026
09b0c0c
Fix integration tests
sebastijankuzner Apr 29, 2026
060827b
Deps
sebastijankuzner Apr 29, 2026
15741f9
Fix sender state
sebastijankuzner Apr 30, 2026
ece90d2
Add BigNumber conversion
sebastijankuzner May 4, 2026
4169165
Merge branch 'develop' into refactor/remove-big-number
sebastijankuzner May 4, 2026
d7ae209
Use +=
sebastijankuzner May 4, 2026
34c6821
Test
sebastijankuzner May 4, 2026
2419051
Use to string
sebastijankuzner May 4, 2026
e69dafb
Support database table log
sebastijankuzner May 4, 2026
eb5cb87
Validator fee to string
sebastijankuzner May 4, 2026
542daae
Remove import
sebastijankuzner May 4, 2026
de11ee3
Fee to string
sebastijankuzner May 4, 2026
0f785a4
Remove BigInt.toJSON
sebastijankuzner May 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class WalletFilter {
walletAttributeRepository.set("publicKey", Contracts.State.AttributeType.String);
walletAttributeRepository.set("username", Contracts.State.AttributeType.String);
walletAttributeRepository.set("validatorPublicKey", Contracts.State.AttributeType.String);
walletAttributeRepository.set("validatorRank", Contracts.State.AttributeType.Number);
walletAttributeRepository.set("validatorRank", Contracts.State.AttributeType.Number);
walletAttributeRepository.set("validatorVoteBalance", Contracts.State.AttributeType.BigNumber);
walletAttributeRepository.set("validatorLastBlock", Contracts.State.AttributeType.Object);
walletAttributeRepository.set("validatorForgedFees", Contracts.State.AttributeType.BigNumber);
Expand Down
2 changes: 1 addition & 1 deletion packages/api-development/source/controllers/round.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class RoundController extends Controller {
...this.roundCalculator.calculateRound(blockNumber),
// Map the round validator set (static, vote-weighted, etc.) to actual proposal order
validators: orderedValidators.map((validator) => ({
voteBalance: validator.voteBalance.toFixed(),
voteBalance: validator.voteBalance.toString(),

wallet: validator,
})),
Expand Down
4 changes: 2 additions & 2 deletions packages/api-http/source/controllers/commits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Types } from "@mainsail/api-common";
import Boom from "@hapi/boom";
import { Contracts as ApiDatabaseContracts, Identifiers as ApiDatabaseIdentifiers } from "@mainsail/api-database";
import { inject, injectable } from "@mainsail/container";
import { BigNumber, validatorSetUnpack } from "@mainsail/utils";
import { validatorSetUnpack } from "@mainsail/utils";

import { Controller } from "./controller.js";

Expand Down Expand Up @@ -35,7 +35,7 @@ export class CommitsController extends Controller {

if (round) {
// map bitmask -> indexes -> round.validators
const packed = BigNumber.make(block.validatorSet).toBigInt();
const packed = BigInt(block.validatorSet);
const unpacked = validatorSetUnpack(packed, round.validators.length);
validators = unpacked.filter(Boolean).map((_, index) => round.validators[index]);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/api-http/source/resources/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { Contracts } from "@mainsail/contracts";

import { Models } from "@mainsail/api-database";
import { injectable } from "@mainsail/container";
import { BigNumber } from "@mainsail/utils";

export interface EnrichedBlock extends Models.Block {
state: Models.State;
Expand Down Expand Up @@ -32,7 +31,7 @@ export class BlockResource implements Contracts.Api.Resource {
round: resource.round,
signature: resource.signature,
timestamp: resource.timestamp,
total: BigNumber.make(resource.reward).plus(resource.fee).toFixed(),
total: (BigInt(resource.reward) + BigInt(resource.fee)).toString(),
transactionsCount: resource.transactionsCount,
transactionsRoot: resource.transactionsRoot,
username: resource.generator.attributes?.["username"] ?? undefined,
Expand Down
60 changes: 30 additions & 30 deletions packages/api-sync/source/restore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Identifiers } from "@mainsail/constants";
import { inject, injectable, optional, tagged } from "@mainsail/container";
import { Deployer, Identifiers as EvmConsensusIdentifiers } from "@mainsail/evm-consensus";
import { parseTransactionError } from "@mainsail/evm-contracts";
import { assert, BigNumber, chunk, formatEcdsaSignature, validatorSetPack } from "@mainsail/utils";
import { assert, chunk, formatEcdsaSignature, validatorSetPack } from "@mainsail/utils";
import { performance } from "perf_hooks";

import { TokenParser } from "./contracts.js";
Expand Down Expand Up @@ -42,7 +42,7 @@ interface RestoreContext extends RepositoryContext {
mostRecentCommit: Contracts.Crypto.Commit;

lastBlockNumber: number;
totalSupply: BigNumber;
totalSupply: bigint;

validatorAttributes: Record<string, ValidatorAttributes>;
userAttributes: Record<string, UserAttributes>;
Expand All @@ -52,12 +52,12 @@ interface RestoreContext extends RepositoryContext {

interface ValidatorAttributes {
lastBlock?: Contracts.Crypto.BlockHeader;
totalForgedFees: BigNumber;
totalForgedRewards: BigNumber;
totalForgedFees: bigint;
totalForgedRewards: bigint;
producedBlocks: number;

voteBalance: BigNumber;
fee: BigNumber;
voteBalance: bigint;
fee: bigint;
votersCount: number;
blsPublicKey: string;
isResigned: boolean;
Expand Down Expand Up @@ -203,7 +203,7 @@ export class Restore {
tokenHolderRepository: this.tokenHolderRepositoryFactory(entityManager),
tokenRepository: this.tokenRepositoryFactory(entityManager),

totalSupply: BigNumber.ZERO,
totalSupply: 0n,
transactionRepository: this.transactionRepositoryFactory(entityManager),
userAttributes: {},
validatorAttributes: {},
Expand Down Expand Up @@ -414,8 +414,8 @@ export class Restore {
}
} else {
validatorAttributes.producedBlocks += 1;
validatorAttributes.totalForgedFees = validatorAttributes.totalForgedFees.plus(block.fee);
validatorAttributes.totalForgedRewards = validatorAttributes.totalForgedRewards.plus(block.reward);
validatorAttributes.totalForgedFees += block.fee;
validatorAttributes.totalForgedRewards += block.reward;
validatorAttributes.lastBlock = block;
}

Expand Down Expand Up @@ -571,8 +571,8 @@ export class Restore {
fee: validator.fee,
isResigned: validator.isResigned,
producedBlocks: 0,
totalForgedFees: BigNumber.ZERO,
totalForgedRewards: BigNumber.ZERO,
totalForgedFees: 0n,
totalForgedRewards: 0n,
voteBalance: validator.voteBalance,
votersCount: validator.votersCount,
};
Expand Down Expand Up @@ -648,25 +648,25 @@ export class Restore {
attributes: {
...(validatorAttributes
? {
validatorFee: validatorAttributes.fee,
validatorFee: validatorAttributes.fee.toString(),
validatorPublicKey: validatorAttributes.blsPublicKey,
validatorResigned: validatorAttributes.isResigned,
validatorVoteBalance: validatorAttributes.voteBalance,
validatorVoteBalance: validatorAttributes.voteBalance.toString(),
validatorVotersCount: validatorAttributes.votersCount,

...(validatorAttributes.totalForgedFees.isGreaterThan(0)
? { validatorForgedFees: validatorAttributes.totalForgedFees.toFixed() }
...(validatorAttributes.totalForgedFees > 0n
? { validatorForgedFees: validatorAttributes.totalForgedFees.toString() }
: {}),
...(validatorAttributes.totalForgedRewards.isGreaterThan(0)
? { validatorForgedRewards: validatorAttributes.totalForgedRewards.toFixed() }
...(validatorAttributes.totalForgedRewards > 0n
? { validatorForgedRewards: validatorAttributes.totalForgedRewards.toString() }
: {}),
...(validatorAttributes.totalForgedFees
.plus(validatorAttributes.totalForgedRewards)
.isGreaterThan(0)
...(validatorAttributes.totalForgedFees + validatorAttributes.totalForgedRewards >
0n
? {
validatorForgedTotal: validatorAttributes.totalForgedFees
.plus(validatorAttributes.totalForgedRewards)
.toFixed(),
validatorForgedTotal: (
validatorAttributes.totalForgedFees +
validatorAttributes.totalForgedRewards
).toString(),
}
: {}),
...(validatorAttributes.producedBlocks > 0
Expand Down Expand Up @@ -720,8 +720,8 @@ export class Restore {
}
: {}),
} as string, // is converted into JSONB column
balance: BigNumber.make(account.balance).toFixed(),
nonce: BigNumber.make(account.nonce).toFixed(),
balance: account.balance.toString(),
nonce: account.nonce.toString(),
publicKey: context.addressToPublicKey[account.address] ?? null,
updated_at: "0",
});
Expand All @@ -737,7 +737,7 @@ export class Restore {
offset = result.nextOffset;
} while (offset);

context.totalSupply = context.totalSupply.plus(totalAccountBalance);
context.totalSupply += totalAccountBalance;

const t1 = performance.now();
this.logger.info(`Restored ${totalAccounts.toLocaleString()} wallets in ${t1 - t0}ms`);
Expand All @@ -761,7 +761,7 @@ export class Restore {
for (const wallet of result.wallets) {
legacyColdWallets.push({
address: wallet.address,
balance: BigNumber.make(wallet.balance).toFixed(),
balance: wallet.balance.toString(),
...(Object.keys(wallet.legacyAttributes).length > 0
? {
attributes: {
Expand Down Expand Up @@ -804,7 +804,7 @@ export class Restore {
offset = result.nextOffset;
} while (offset);

context.totalSupply = context.totalSupply.plus(totalLegacyAccountBalance);
context.totalSupply += totalLegacyAccountBalance;

const t1 = performance.now();
this.logger.info(`Restored ${totalLegacyAccounts.toLocaleString()} legacy cold wallets in ${t1 - t0}ms`);
Expand Down Expand Up @@ -855,7 +855,7 @@ export class Restore {

const proposer = validators[proposerIndex];
validatorAddresses[index] = proposer.address;
votes[index] = proposer.voteBalance.toFixed();
votes[index] = proposer.voteBalance.toString();
}

validatorRoundsToIngest.push({
Expand Down Expand Up @@ -899,7 +899,7 @@ export class Restore {
.values({
blockNumber: context.lastBlockNumber.toFixed(),
id: 1,
supply: context.totalSupply.toFixed(),
supply: context.totalSupply.toString(),
})
.execute();
}
Expand Down
14 changes: 7 additions & 7 deletions packages/api-sync/source/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Identifiers } from "@mainsail/constants";
import { inject, injectable, tagged } from "@mainsail/container";
import { Identifiers as EvmConsensusIdentifiers } from "@mainsail/evm-consensus";
import { parseTransactionError } from "@mainsail/evm-contracts";
import { assert, BigNumber, chunk, formatEcdsaSignature, sleep, validatorSetPack } from "@mainsail/utils";
import { assert, chunk, formatEcdsaSignature, sleep, validatorSetPack } from "@mainsail/utils";
import { performance } from "perf_hooks";

import { Listeners, TokenParser } from "./contracts.js";
Expand Down Expand Up @@ -263,10 +263,10 @@ export class Sync implements Contracts.ApiSync.Service {
return {
...(dirtyValidator
? {
validatorFee: dirtyValidator.fee,
validatorFee: dirtyValidator.fee.toString(),
validatorPublicKey: dirtyValidator.blsPublicKey,
validatorResigned: dirtyValidator.isResigned,
validatorVoteBalance: dirtyValidator.voteBalance,
validatorVoteBalance: dirtyValidator.voteBalance.toString(),
validatorVotersCount: dirtyValidator.votersCount,
// updated at end of db transaction
// - validatorRank
Expand Down Expand Up @@ -313,8 +313,8 @@ export class Sync implements Contracts.ApiSync.Service {
return [
account.address,
addressToPublicKey[account.address] ?? null,
BigNumber.make(account.balance).toFixed(),
BigNumber.make(account.nonce).toFixed(),
account.balance.toString(),
account.nonce.toString(),
attributes,
header.number.toFixed(),
];
Expand Down Expand Up @@ -400,7 +400,7 @@ export class Sync implements Contracts.ApiSync.Service {
return {
...this.roundCalculator.calculateRound(number),
validators: validatorWallets.map((v) => v.address),
votes: validatorWallets.map((v) => v.voteBalance.toFixed()),
votes: validatorWallets.map((v) => v.voteBalance.toString()),
};
}

Expand Down Expand Up @@ -470,7 +470,7 @@ export class Sync implements Contracts.ApiSync.Service {
})
.where("id = :id", { id: 1 })
.andWhere("blockNumber = :previousBlockNumber", {
previousBlockNumber: BigNumber.make(deferred.block.number).minus(1).toFixed(),
previousBlockNumber: (BigInt(deferred.block.number) - 1n).toString(),
})
.execute();

Expand Down
4 changes: 2 additions & 2 deletions packages/blockchain-utils/source/fee-calculator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ describe("FeeCalculator", ({ assert, it }) => {
it("should calculate gas consumed", async () => {
const feeCalculator = new FeeCalculator();

assert.equal(feeCalculator.calculateConsumed(5 * 1e9, 21_000).toBigInt(), 105_000_000_000_000n);
assert.equal(feeCalculator.calculateConsumed(5 * 1e9, 21_000n), 105_000_000_000_000n);

assert.equal(
feeCalculator.calculate({ gasLimit: 21_000, gasPrice: 5 * 1e9 } as Contracts.Crypto.Transaction).toBigInt(),
feeCalculator.calculate({ gasLimit: 21_000, gasPrice: 5 * 1e9 } as Contracts.Crypto.Transaction),
105_000_000_000_000n,
);
});
Expand Down
9 changes: 4 additions & 5 deletions packages/blockchain-utils/source/fee-calculator.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import type { Contracts } from "@mainsail/contracts";

import { injectable } from "@mainsail/container";
import { BigNumber } from "@mainsail/utils";

@injectable()
export class FeeCalculator implements Contracts.BlockchainUtils.FeeCalculator {
public calculate(transaction: Contracts.Crypto.Transaction): BigNumber {
return BigNumber.make(transaction.gasPrice).times(transaction.gasLimit);
public calculate(transaction: Contracts.Crypto.Transaction): bigint {
return BigInt(transaction.gasPrice) * BigInt(transaction.gasLimit);
}

public calculateConsumed(gasPrice: number, gasUsed: number): BigNumber {
return BigNumber.make(gasPrice).times(gasUsed);
public calculateConsumed(gasPrice: number, gasUsed: bigint): bigint {
return BigInt(gasPrice) * gasUsed;
}
}
9 changes: 4 additions & 5 deletions packages/blockchain-utils/source/format.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Identifiers } from "@mainsail/constants";
import { BigNumber } from "@mainsail/utils";
import { ServiceProvider as ValidationServiceProvider } from "@mainsail/validation";
import { ServiceProvider as CryptoConfigServiceProvider } from "@mainsail/crypto-config";
import crypto from "../../core/bin/config/devnet/core/crypto.json";
Expand All @@ -23,9 +22,9 @@ describe<{
});

it("should format currency", ({ configuration }) => {
assert.equal(formatCurrency(configuration, BigNumber.ONE), "0.000000000000000001 TѦ");
assert.equal(formatCurrency(configuration, BigNumber.ZERO), "0 TѦ");
assert.equal(formatCurrency(configuration, BigNumber.make(1e18)), "1 TѦ");
assert.equal(formatCurrency(configuration, BigNumber.make(1e18).times(100)), "100 TѦ");
assert.equal(formatCurrency(configuration, 1n), "0.000000000000000001 TѦ");
assert.equal(formatCurrency(configuration, 0n), "0 TѦ");
assert.equal(formatCurrency(configuration, BigInt(1e18)), "1 TѦ");
assert.equal(formatCurrency(configuration, BigInt(1e18) * 100n), "100 TѦ");
});
});
15 changes: 12 additions & 3 deletions packages/blockchain-utils/source/format.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import type { Contracts } from "@mainsail/contracts";
import type { BigNumber } from "@mainsail/utils";

export const formatCurrency = (configuration: Contracts.Crypto.Configuration, amount: BigNumber): string => {
type FractionDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20;

function isFractionDigit(n: number): n is FractionDigit {
return n >= 0 && n <= 20 && Number.isInteger(n);
}

export const formatCurrency = (configuration: Contracts.Crypto.Configuration, amount: bigint): string => {
const { decimals, denomination } = configuration.getMilestone().satoshi;

const localeString = (+amount / denomination).toLocaleString("en", {
if (!isFractionDigit(decimals)) {
throw new Error("Invalid decimals");
}

const localeString = (Number(amount) / denomination).toLocaleString("en", {
maximumFractionDigits: decimals,
minimumFractionDigits: 0,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Application } from "@mainsail/kernel";
import { BigNumber } from "@mainsail/utils";
import envPaths from "env-paths";
import fs from "fs-extra/esm";
import { join } from "path";
Expand Down Expand Up @@ -53,10 +52,10 @@ describe<{
payloadHash: match.string,
payloadLength: match.number,
previousBlock: "0000000000000000000000000000000000000000000000000000000000000000",
reward: BigNumber.ZERO,
reward: 0n,
timestamp: match.number,
totalAmount: BigNumber.make("12500000000000000"),
totalFee: BigNumber.ZERO,
totalAmount: 12500000000000000n,
totalFee: 0n,
transactions: match.array,
version: 1,
},
Expand Down Expand Up @@ -189,10 +188,10 @@ describe<{
payloadHash: match.string,
payloadLength: match.number,
previousBlock: "0000000000000000000000000000000000000000000000000000000000000000",
reward: BigNumber.ZERO,
reward: 0n,
timestamp: match.number,
totalAmount: BigNumber.make("12499999999999969"),
totalFee: BigNumber.ZERO,
totalAmount: 12499999999999969n,
totalFee: 0n,
transactions: match.array,
version: 1,
},
Expand Down
Loading
Loading