UNPKG

@ton3/liteclient

Version:
383 lines 14.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BlockchainClient = void 0; const core_1 = require("@tonkite/core"); const ton3_core_1 = require("ton3-core"); const stack_1 = require("../../utils/stack"); const types_1 = require("@tonkite/types"); const cursor_1 = require("./cursor"); class BlockchainClient { constructor(api) { this.api = api; } async getMasterchainInfo(wait) { const masterchainInfo = await this.api.getMasterchainInfo(wait); return { workchain: masterchainInfo.last.workchain, shard: masterchainInfo.last.shard, seqno: masterchainInfo.last.seqno, rootHash: masterchainInfo.last.root_hash, fileHash: masterchainInfo.last.file_hash, }; } async getAllShardsInfo(blockId, wait) { const allShards = await this.api.getAllShardsInfo({ workchain: blockId.workchain, shard: blockId.shard, seqno: blockId.seqno, root_hash: blockId.rootHash, file_hash: blockId.fileHash, }, wait); const [cell] = ton3_core_1.BOC.from(allShards.data); const shardHashes = (0, types_1.loadShardHashes)(cell.slice()); return shardHashes .map((workchain) => workchain.shards.map((shard) => ({ workchain: workchain.workchain, shard: shard.id, seqno: shard.description.seq_no, rootHash: shard.description.root_hash, fileHash: shard.description.file_hash, }))) .flat(); } async lookupBlock(blockId, wait) { const result = await this.api.lookupBlock({ id: { workchain: blockId.workchain, shard: blockId.shard, seqno: blockId.seqno, }, }, wait); return { workchain: result.id.workchain, shard: result.id.shard, seqno: result.id.seqno, rootHash: result.id.root_hash, fileHash: result.id.file_hash, }; } async getAccountState(data, wait) { const accountStateRaw = await this.api.getAccountState({ blockId: { workchain: data.blockId.workchain, shard: data.blockId.shard, seqno: data.blockId.seqno, root_hash: data.blockId.rootHash, file_hash: data.blockId.fileHash, }, account: { workchain: data.account.workchain, id: data.account.hash, } }, wait); if (!accountStateRaw.state.length) { return new core_1.Account({ workchain: accountStateRaw.id.workchain, shard: accountStateRaw.id.shard, seqno: accountStateRaw.id.seqno, rootHash: accountStateRaw.id.root_hash, fileHash: accountStateRaw.id.file_hash, }, data.account, ton3_core_1.Coins.fromNano(0), { lt: 0n, hash: new Uint8Array(32), }, core_1.AccountStatus.UNINITIALIZED, null, null, null, { lastPaid: null, duePayment: null, usage: { bits: 0, cells: 0, publicCells: 0, }, }); } const [_, proof] = ton3_core_1.BOC.from(accountStateRaw.proof); const loadShardIdent = (slice) => { if (slice.loadUint(2) !== 0b00) { throw new Error('Incorrect ShardIdent'); } const shardPrefixBits = slice.loadBigUint(6); const workchainId = slice.loadInt(32); const shardPrefix = slice.loadBigUint(64); return { shardPrefixBits, workchainId, shardPrefix, }; }; const loadDepthBalanceInfo = (slice) => { const splitDepth = slice.loadUint(5); const balance = (0, types_1.loadCurrencyCollection)(slice); return { splitDepth, balance, }; }; const loadShardAccounts = (slice) => { return [ ...ton3_core_1.Hashmap.parse(256, ton3_core_1.Slice.parse(slice.refs[0]), { deserializers: { key: ton3_core_1.Utils.Helpers.bitsToBytes, value: (cell) => { const cs = ton3_core_1.Slice.parse(cell); const depthBalanceInfo = loadDepthBalanceInfo(cs); const shardAccount = (0, types_1.loadShardAccount)(cs); return { shardAccount, depthBalanceInfo, }; }, }, }), ]; }; const loadShardStateUnsplit = (slice) => { if (slice.loadUint(32) !== 0x9023afe2) { throw new Error('Incorrect ShardStateUnsplit'); } const global_id = slice.loadInt(32); const shard_id = loadShardIdent(slice); const seq_no = slice.loadUint(32); const vert_seq_no = slice.loadUint(32); const gen_utime = slice.loadUint(32); const gen_lt = slice.loadBigUint(64); const min_ref_mc_seqno = slice.loadUint(32); const out_msg_queue_info = slice.loadRef(); const before_split = slice.loadBit(); const shardAccounts = loadShardAccounts(ton3_core_1.Slice.parse(slice.loadRef())); const next = ton3_core_1.Slice.parse(slice.loadRef()); const overload_history = next.loadBigUint(64); const underload_history = next.loadBigUint(64); return { global_id, shard_id, seq_no, vert_seq_no, gen_utime, gen_lt, min_ref_mc_seqno, out_msg_queue_info, before_split, shardAccounts, overload_history, underload_history, }; }; const [cell] = ton3_core_1.BOC.from(accountStateRaw.state); const shardState = loadShardStateUnsplit(proof.refs[0].slice()); const accountState = (0, types_1.loadAccount)(cell.slice()); const shardAccount = shardState.shardAccounts .filter(([accountHash]) => { return Buffer.from(accountHash).equals(Buffer.from(data.account.hash, 0)); }) .map(([_, { shardAccount }]) => shardAccount)[0]; return new core_1.Account({ workchain: accountStateRaw.id.workchain, shard: accountStateRaw.id.shard, seqno: accountStateRaw.id.seqno, rootHash: accountStateRaw.id.root_hash, fileHash: accountStateRaw.id.file_hash, }, data.account, accountState.storage.balance.coins, { lt: shardAccount.lastTransactionId.lt, hash: shardAccount.lastTransactionId.hash, }, accountState.storage.state.type, accountState.storage.state.type === 'frozen' ? accountState.storage.state.stateHash : null, accountState.storage.state.type === 'active' ? accountState.storage.state.code : null, accountState.storage.state.type === 'active' ? accountState.storage.state.data : null, { lastPaid: new Date(accountState.storageStat.lastPaid * 1000), duePayment: accountState.storageStat.duePayment, usage: { bits: accountState.storageStat.used.bits, cells: accountState.storageStat.used.cells, publicCells: accountState.storageStat.used.publicCells, }, }); } shardIdent(slice) { slice.skipBits(2); const shard_pfx_bits = slice.loadBits(Math.ceil(Math.log2(60 + 1))); const workchain_id = slice.loadInt(32); const shard_prefix = slice.loadBigUint(64); return { shard_pfx_bits, workchain_id, shard_prefix }; } globalVersion(slice) { slice.skipBits(8); const version = slice.loadUint(32); const capabilities = slice.loadBigUint(64); return { version, capabilities }; } extBlkRef(slice) { const end_lt = slice.loadBigUint(64); const seq_no = slice.loadUint(32); const root_hash = slice.loadBytes(256); const file_hash = slice.loadBytes(256); return { end_lt, seq_no, root_hash, file_hash }; } blkMasterInfo(slice) { const master = this.extBlkRef(slice); return { master }; } blkPrevInfo(slice, arg) { if (arg === 0) { return this.extBlkRef(slice); } return [ this.extBlkRef(slice.loadRef().slice()), this.extBlkRef(slice.loadRef().slice()) ]; } blkInfo(slice) { slice.skipBits(32); const version = slice.loadUint(32); const not_master = slice.loadBit(); const after_merge = slice.loadBit(); const before_split = slice.loadBit(); const after_split = slice.loadBit(); const want_split = Boolean(slice.loadBit()); const want_merge = Boolean(slice.loadBit()); const key_block = Boolean(slice.loadBit()); const vert_seqno_incr = slice.loadBit(); const flags = slice.loadUint(8); const seq_no = slice.loadUint(32); const vert_seq_no = slice.loadUint(32); const shard = this.shardIdent(slice); const gen_utime = slice.loadUint(32); const start_lt = slice.loadBigUint(64); const end_lt = slice.loadBigUint(64); const gen_validator_list_hash_short = slice.loadUint(32); const gen_catchain_seqno = slice.loadUint(32); const min_ref_mc_seqno = slice.loadUint(32); const prev_key_block_seqno = slice.loadUint(32); const gen_software = (flags & (1 << 0)) ? this.globalVersion(slice) : null; const master_ref = Boolean(not_master) ? this.blkMasterInfo(slice.loadRef().slice()) : null; const prev_ref = this.blkPrevInfo(slice.loadRef().slice(), after_merge); const prev_vert_ref = Boolean(vert_seqno_incr) ? this.blkPrevInfo(slice.loadRef().slice(), 0) : null; return { version, not_master, after_merge, before_split, after_split, want_split, want_merge, key_block, vert_seqno_incr, flags, seq_no, vert_seq_no, shard, gen_utime, start_lt, end_lt, gen_validator_list_hash_short, gen_catchain_seqno, min_ref_mc_seqno, prev_key_block_seqno, gen_software, master_ref, prev_ref, prev_vert_ref }; } async getBlock(blockId, wait) { const { data } = await this.api.getBlock({ workchain: blockId.workchain, shard: blockId.shard, seqno: blockId.seqno, root_hash: blockId.rootHash, file_hash: blockId.fileHash }, wait); const slice = ton3_core_1.BOC.from(data).root[0].slice(); slice.skipBits(32); const global_id = slice.loadInt(32); const info = this.blkInfo(slice.loadRef().slice()); const value_flow = slice.loadRef(); const state_update = slice.loadRef(); const extra = slice.loadRef(); return { global_id, info, value_flow, state_update, extra }; } async getBlockTransactions(data, wait) { const result = await this.api.listBlockTransactions({ blockId: { workchain: data.blockId.workchain, shard: data.blockId.shard, seqno: data.blockId.seqno, root_hash: data.blockId.rootHash, file_hash: data.blockId.fileHash, }, count: 40, after: data.after ? { account: data.after.account.hash, lt: data.after.lt } : null }, wait); return result.ids.map((id) => ({ account: new ton3_core_1.Address(`${result.id.workchain}:${ton3_core_1.Utils.Helpers.bytesToHex(id.account)}`), lt: id.lt, hash: id.hash, })); } async getOneTransaction(data, wait) { return await this.api.getOneTransaction({ blockId: { workchain: data.blockId.workchain, shard: data.blockId.shard, seqno: data.blockId.seqno, root_hash: data.blockId.rootHash, file_hash: data.blockId.fileHash }, accountId: data.account, lt: data.lt }, wait); } getTransactions(data) { const { account, after, take = Infinity } = data; return new cursor_1.TransactionCursor(this.api, account, after, take); } async invokeGetMethod(data, wait) { const { account, method, stack = [] } = data; const methodName = typeof method !== 'number' ? ton3_core_1.Utils.Helpers.stringToBytes(method) : null; const methodId = BigInt(typeof method !== 'number' ? (ton3_core_1.Utils.Checksum.crc16(methodName) & 0xffff) | 0x10000 : method); const blockId = { workchain: account.blockId.workchain, shard: account.blockId.shard, seqno: account.blockId.seqno, root_hash: account.blockId.rootHash, file_hash: account.blockId.fileHash }; const accountId = { workchain: account.address.workchain, id: account.address.hash }; const params = new ton3_core_1.BOC([stack_1.Stack.serialize(stack)]).toBytes(); const response = await this.api.runSmcMethod({ blockId, accountId, methodId, params }, wait); const result = { ...response, result: response.result ? stack_1.Stack.deserialize(ton3_core_1.BOC.from(response.result).root[0]) : null }; return result; } async getTime(wait) { return await this.api.getTime(wait); } } exports.BlockchainClient = BlockchainClient; //# sourceMappingURL=index.js.map