@ton3/liteclient
Version:
TON Blockchain LiteClient
383 lines • 14.8 kB
JavaScript
"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