@factorial-finance/blueprint-node
Version:
blueprint-node-plugin
168 lines (167 loc) • 6.64 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlockchainService = void 0;
const sandbox_1 = require("@ton/sandbox");
const ton_1 = require("@ton/ton");
const core_1 = require("@ton/core");
const library_cell_1 = require("../constants/library-cell");
const test_wallets_1 = require("../constants/test-wallets");
const networks_1 = require("../constants/networks");
const utils_1 = require("../utils");
const defaults_1 = require("../constants/defaults");
class BlockchainService {
constructor(fork) {
this.blockchain = null;
this.txs = new Map();
if (fork) {
const networkConfig = networks_1.NETWORK_CONFIGS[fork];
this.fork = fork;
this.endpoint = networkConfig.endpoint;
}
}
async initialize() {
if (process.env.NODE_ENV !== 'test') {
console.clear();
}
utils_1.Logger.info('🔄 Initializing TON Sandbox Blockchain...');
try {
this.blockchain = await this.createBlockchain();
await this.initializeTestWallets();
this.setupLibraries();
}
catch (error) {
throw new utils_1.ValidationError(`Failed to initialize blockchain: ${error instanceof Error ? error.message : String(error)}`);
}
}
async createBlockchain() {
const params = this.endpoint
? {
storage: new sandbox_1.RemoteBlockchainStorage((0, sandbox_1.wrapTonClient4ForRemote)(new ton_1.TonClient4({ endpoint: this.endpoint })))
}
: undefined;
return await sandbox_1.Blockchain.create(params);
}
async initializeTestWallets() {
const walletInitPromises = test_wallets_1.testWallets.subWallets.map(async (wallet) => {
await this.setBalance(core_1.Address.parse(wallet.address), defaults_1.DEFAULTS.INITIAL_TON_AMOUNT);
});
await Promise.all(walletInitPromises);
}
setupLibraries() {
if (this.fork === "mainnet" || this.fork === "testnet") {
this.blockchain.libs = core_1.Cell.fromBase64(library_cell_1.MAINNET_LIBRARY_CELL);
}
}
ensureBlockchainInitialized() {
if (!this.blockchain) {
throw new utils_1.ValidationError('Blockchain service not initialized. Call initialize() first.');
}
}
async setBalance(address, balance) {
this.ensureBlockchainInitialized();
const contract = await this.blockchain.getContract(address);
contract.balance = balance;
}
async increaseBalance(address, amount) {
this.ensureBlockchainInitialized();
const contract = await this.blockchain.getContract(address);
contract.balance += amount;
}
async setAccountCode(address, code) {
this.ensureBlockchainInitialized();
const contract = await this.blockchain.getContract(address);
if (contract.accountState?.type !== "active" || !contract.accountState.state.code) {
throw new utils_1.ContractError("Account is not active");
}
const newShardAccount = (0, sandbox_1.createShardAccount)({
address: address,
code: code,
data: contract.accountState.state.data,
balance: contract.balance,
});
this.blockchain.setShardAccount(address, newShardAccount);
}
async setAccountData(address, data) {
this.ensureBlockchainInitialized();
const contract = await this.blockchain.getContract(address);
if (contract.accountState?.type !== "active" || !contract.accountState.state.data) {
throw new utils_1.ContractError("Account is not active");
}
const newShardAccount = (0, sandbox_1.createShardAccount)({
address: address,
code: contract.accountState.state.code,
data: data,
balance: contract.balance,
});
this.blockchain.setShardAccount(address, newShardAccount);
}
async addLibrary(library) {
this.ensureBlockchainInitialized();
const libs = this.getCurrentLibraries();
libs.set(BigInt("0x" + library.hash().toString('hex')), library);
this.setLibraries((0, core_1.beginCell)().storeDictDirect(libs).endCell());
}
getCurrentLibraries() {
this.ensureBlockchainInitialized();
if (this.blockchain.libs) {
try {
return this.blockchain.libs
.beginParse()
.loadDictDirect(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.Cell());
}
catch (error) { }
}
return core_1.Dictionary.empty(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.Cell());
}
async setLibraries(libraries) {
this.ensureBlockchainInitialized();
this.blockchain.libs = libraries;
}
async getLibraries() {
this.ensureBlockchainInitialized();
return this.getCurrentLibraries();
}
async sendBoc(boc) {
this.ensureBlockchainInitialized();
const cell = core_1.Cell.fromBase64(boc);
const result = await this.blockchain.sendMessage(cell);
this.addTransactions(result.transactions);
return result.transactions;
}
async getContract(address) {
this.ensureBlockchainInitialized();
const contract = await this.blockchain.getContract(address);
return contract;
}
async runGetMethod(address, method, stack) {
this.ensureBlockchainInitialized();
const result = await this.blockchain.runGetMethod(address, method, stack);
return result;
}
getBlockchain() {
this.ensureBlockchainInitialized();
return this.blockchain;
}
addTransactions(transactions) {
for (const tx of transactions) {
const existingTxs = this.txs.get(tx.address) || [];
existingTxs.push(tx);
this.txs.set(tx.address, existingTxs);
}
}
getTransactions(address) {
return this.txs.get((0, utils_1.addrToBigInt)(address)) || [];
}
getCurrentTime() {
return this.blockchain?.now || Math.floor(Date.now() / 1000);
}
async getCodeHash(address) {
this.ensureBlockchainInitialized();
const contract = await this.getContract(address);
if (contract.accountState?.type === 'active' && contract.accountState.state.code) {
return contract.accountState.state.code.hash().toString('hex');
}
return null;
}
}
exports.BlockchainService = BlockchainService;