Skip to content

Commit

Permalink
extended Tonlib's methods with supporting block height (BlockIdExt) a…
Browse files Browse the repository at this point in the history
…s a parameter:

runMethod()
getAccountState()
getRawAccountState()
loadContract()
getAccountStatus()
  • Loading branch information
mercedesbenz00 committed Jun 21, 2024
1 parent f6abd0b commit e8195b5
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 11 deletions.
159 changes: 154 additions & 5 deletions tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,40 @@ public RawAccountState getRawAccountState(Address address) {
}
}

public RawAccountState getRawAccountState(Address address, BlockIdExt blockId) {
synchronized (gson) {

if (StringUtils.isEmpty(blockId.getRoot_hash())) { // retrieve hashes
blockId = lookupBlock(blockId.getSeqno(), blockId.getWorkchain(), blockId.getShard(),0 );
if (StringUtils.isEmpty(blockId.getRoot_hash())) {
throw new Error("Cannot lookup block for hashes by seqno. Probably block not in db. Try to specify block's root and file hashes manually in base64 format.");
}
System.out.println("got hashes "+blockId);
}

AccountAddressOnly accountAddressOnly = AccountAddressOnly.builder()
.account_address(address.toString(false))
.build();

GetRawAccountStateQueryOnly getAccountStateQuery = GetRawAccountStateQueryOnly.builder()
.account_address(accountAddressOnly)
.build();

RawGetAccountStateOnlyWithBlockQuery rawGetAccountStateOnlyWithBlockQuery = RawGetAccountStateOnlyWithBlockQuery.builder()
.id(blockId)
.function(getAccountStateQuery)
.build();

String result = syncAndRead(gson.toJson(rawGetAccountStateOnlyWithBlockQuery));

if ((isNull(result)) || (result.contains("@type") && result.contains("error"))) {
throw new Error ("Cannot getRawAccountState, error" + result);
}

return gson.fromJson(result, RawAccountState.class);
}
}

/**
* Returns status of an address
*
Expand Down Expand Up @@ -734,6 +768,43 @@ public FullAccountState getAccountState(Address address) {
}
}

public FullAccountState getAccountState(Address address, BlockIdExt blockId) {
synchronized (gson) {

synchronized (gson) {

if (StringUtils.isEmpty(blockId.getRoot_hash())) { // retrieve hashes
blockId = lookupBlock(blockId.getSeqno(), blockId.getWorkchain(), blockId.getShard(),0 );
if (StringUtils.isEmpty(blockId.getRoot_hash())) {
throw new Error("Cannot lookup block for hashes by seqno. Probably block not in db. Try to specify block's root and file hashes manually in base64 format.");
}
System.out.println("got hashes "+blockId);
}

AccountAddressOnly accountAddressOnly = AccountAddressOnly.builder()
.account_address(address.toString(false))
.build();

GetAccountStateQueryOnly getAccountStateQuery = GetAccountStateQueryOnly.builder()
.account_address(accountAddressOnly)
.build();

GetAccountStateOnlyWithBlockQuery getAccountStateOnlyWithBlockQuery = GetAccountStateOnlyWithBlockQuery.builder()
.id(blockId)
.function(getAccountStateQuery)
.build();

String result = syncAndRead(gson.toJson(getAccountStateOnlyWithBlockQuery));

if ((isNull(result)) || (result.contains("@type") && result.contains("error"))) {
throw new Error ("Cannot getAccountState, error" + result);
}

return gson.fromJson(result, FullAccountState.class);
}
}
}

/**
* Returns account status by address.
*
Expand All @@ -753,6 +824,25 @@ public String getAccountStatus(Address address) {
}
}

/**
* Returns account status by address and blockId.
*
* @param address Address
* @return String - uninitialized, frozen or active.
*/
public String getAccountStatus(Address address, BlockIdExt blockId) {
RawAccountState state = getRawAccountState(address, blockId);
if (nonNull(state) && StringUtils.isEmpty(state.getCode())) {
if (StringUtils.isEmpty(state.getFrozen_hash())) {
return "uninitialized";
} else {
return "frozen";
}
} else {
return "active";
}
}


public Cell getConfigAll(int mode) {
synchronized (gson) {
Expand All @@ -762,7 +852,6 @@ public Cell getConfigAll(int mode) {

String result = syncAndRead(gson.toJson(configParamQuery));
ConfigInfo ci = gson.fromJson(result, ConfigInfo.class);
System.out.println(Utils.bytesToHex(Utils.base64ToBytes(ci.getConfig().getBytes())));
return CellBuilder.beginCell().fromBoc(Utils.base64ToBytes(ci.getConfig().getBytes())).endCell();
}
}
Expand All @@ -775,13 +864,11 @@ public Cell getConfigParam(BlockIdExt id, long param) {
.build();

String result = syncAndRead(gson.toJson(configParamQuery));
System.out.println(result);
ConfigInfo ci = gson.fromJson(result, ConfigInfo.class);
return CellBuilder.beginCell().fromBoc(Utils.base64ToBytes(ci.getConfig().getBytes())).endCell();
}
}


public long loadContract(AccountAddressOnly address) {
synchronized (gson) {
LoadContractQuery loadContractQuery = LoadContractQuery.builder()
Expand All @@ -793,6 +880,10 @@ public long loadContract(AccountAddressOnly address) {
return gson.fromJson(result, LoadContract.class).getId();
}
}

/**
* loads contract by seqno within master chain and shard -9223372036854775808
*/
public long loadContract(AccountAddressOnly address, long seqno) {
synchronized (gson) {
BlockIdExt fullBlock;
Expand All @@ -807,12 +898,40 @@ public long loadContract(AccountAddressOnly address, long seqno) {
.account_address(address)
.build();

WithBlockQuery withBlockQuery = WithBlockQuery.builder()
LoadContractWithBlockQuery loadContractWithBlockQuery = LoadContractWithBlockQuery.builder()
.id(fullBlock)
.function(loadContractQuery)
.build();

String result = syncAndRead(gson.toJson(withBlockQuery));
String result = syncAndRead(gson.toJson(loadContractWithBlockQuery));

return gson.fromJson(result, LoadContract.class).getId();
}
}

/**
* load contract by blockId
* @param address contract's address
* @param blockId BlockIdExt
* @return contract's id
*/
public long loadContract(AccountAddressOnly address, BlockIdExt blockId) {
synchronized (gson) {

if (StringUtils.isEmpty(blockId.getRoot_hash())) {
blockId = lookupBlock(blockId.getSeqno(),blockId.getWorkchain(),blockId.getShard(),0 );
}

LoadContractQuery loadContractQuery = LoadContractQuery.builder()
.account_address(address)
.build();

LoadContractWithBlockQuery loadContractWithBlockQuery = LoadContractWithBlockQuery.builder()
.id(blockId)
.function(loadContractQuery)
.build();

String result = syncAndRead(gson.toJson(loadContractWithBlockQuery));

return gson.fromJson(result, LoadContract.class).getId();
}
Expand All @@ -828,6 +947,36 @@ public RunResult runMethod(Address contractAddress, String methodName) {
}
}

/**
* executes runMethod at specified blockId
*/
public RunResult runMethod(Address contractAddress, String methodName, BlockIdExt blockId) {
long contractId = loadContract(AccountAddressOnly.builder()
.account_address(contractAddress.toString(false)).build(),
blockId);
if (contractId == -1) {
System.err.println("cannot load contract " + AccountAddressOnly.builder().account_address(contractAddress.toString(false)));
return null;
} else {
return runMethod(contractId, methodName, null);
}
}

/**
* executes runMethod by seqno within master chain and shard -9223372036854775808
*/
public RunResult runMethod(Address contractAddress, String methodName, long seqno) {
long contractId = loadContract(AccountAddressOnly.builder()
.account_address(contractAddress.toString(false)).build(),
seqno);
if (contractId == -1) {
System.err.println("cannot load contract " + AccountAddressOnly.builder().account_address(contractAddress.toString(false)));
return null;
} else {
return runMethod(contractId, methodName, null);
}
}

public RunResult runMethod(Address contractAddress, String methodName, Deque<String> stackData) {
synchronized (gson) {
long contractId = loadContract(AccountAddressOnly.builder().account_address(contractAddress.toString(false)).build());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.ton.java.tonlib.queries;

import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.ton.java.tonlib.types.BlockIdExt;

@Builder
@Setter
@Getter
@ToString
public class GetAccountStateOnlyWithBlockQuery extends ExtraQuery {
@SerializedName(value = "@type")
final String type = "withBlock";
BlockIdExt id;
GetAccountStateQueryOnly function;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.ton.java.tonlib.queries;

import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.ton.java.tonlib.types.BlockIdExt;

@Builder
@Setter
@Getter
@ToString
public class GetAccountStateWithBlockQuery extends ExtraQuery {
@SerializedName(value = "@type")
final String type = "withBlock";
BlockIdExt id;
GetAccountStateQuery function;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
@Setter
@Getter
@ToString
public class WithBlockQuery extends ExtraQuery {
public class LoadContractWithBlockQuery extends ExtraQuery {
@SerializedName(value = "@type")
final String type = "withBlock";
BlockIdExt id;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.ton.java.tonlib.queries;

import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.ton.java.tonlib.types.BlockIdExt;

@Builder
@Setter
@Getter
@ToString
public class RawGetAccountStateOnlyWithBlockQuery extends ExtraQuery {
@SerializedName(value = "@type")
final String type = "withBlock";
BlockIdExt id;
GetRawAccountStateQueryOnly function;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.ton.java.tonlib.queries;

import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.ton.java.tonlib.types.BlockIdExt;

@Builder
@Setter
@Getter
@ToString
public class RawGetAccountStateWithBlockQuery extends ExtraQuery {
@SerializedName(value = "@type")
final String type = "withBlock";
BlockIdExt id;
GetRawAccountStateQuery function;
}
26 changes: 21 additions & 5 deletions tonlib/src/test/java/org/ton/java/tonlib/TestTonlibJson.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public class TestTonlibJson {

@BeforeClass
public static void setUpBeforeClass() throws Exception {
tonlib = Tonlib.builder().build();
tonlib = Tonlib.builder().ignoreCache(false).build();
}

@Test
Expand Down Expand Up @@ -524,7 +524,7 @@ public void testTonlibLoadContractSeqno() {
@Test
public void testTonlibRunMethodComputeReturnedStake() {
Address elector = Address.of(ELECTOR_ADDRESSS);
RunResult result = tonlib.runMethod(elector, "compute_returned_stake", null);
RunResult result = tonlib.runMethod(elector, "compute_returned_stake", new ArrayDeque<>());
log.info("result: {}", result);
assertThat(result.getExit_code()).isEqualTo(2); // error since compute_returned_stake requires an argument

Expand Down Expand Up @@ -600,12 +600,28 @@ public void testTonlibTryLocateTxByOutcomingMessage() {

@Test
public void testTonlibStateAndStatus() {
int i = 0;

FullAccountState accountState1 = tonlib.getAccountState(Address.of("EQCtPHFrtkIw3UC2rNfSgVWYT1MiMLDUtgMy2M7j1P_eNMDq"));
log.info("{} with balance {} and code [{}]: {}", "EQCtPHFrtkIw3UC2rNfSgVWYT1MiMLDUtgMy2M7j1P_eNMDq", i, accountState1.getBalance(), accountState1);
log.info("FullAccountState {}", accountState1);

RawAccountState accountState2 = tonlib.getRawAccountState(Address.of("EQCtPHFrtkIw3UC2rNfSgVWYT1MiMLDUtgMy2M7j1P_eNMDq"));
log.info("{} with balance {} and code [{}]: {}", "EQCtPHFrtkIw3UC2rNfSgVWYT1MiMLDUtgMy2M7j1P_eNMDq", i, accountState2.getBalance(), accountState2);
log.info("RawAccountState {}", accountState2);

BlockIdExt blockId = BlockIdExt.builder()
.workchain(-1)
.shard(-9223372036854775808L)
.seqno(27894542)
.root_hash("akLZC86Ve0IPDW2HGhSCKKz7RkJk1yAgl34qMpo1RlE=")
.file_hash("KjJvOENNPc39inKO2cOce0s/fUX9Nv8/qdS1VFj2yw0=")
.build();

log.info("input blockId {}", blockId);

FullAccountState accountState1AtBlock = tonlib.getAccountState(Address.of("EQCtPHFrtkIw3UC2rNfSgVWYT1MiMLDUtgMy2M7j1P_eNMDq"), blockId);
log.info("accountState1AtBlock {}", accountState1AtBlock);

RawAccountState accountState2AtBlock = tonlib.getRawAccountState(Address.of("EQCtPHFrtkIw3UC2rNfSgVWYT1MiMLDUtgMy2M7j1P_eNMDq"), blockId);
log.info("RawAccountStateAtBlock {}", accountState2AtBlock);

String accountState1Status = tonlib.getRawAccountStatus(Address.of("EQCtPHFrtkIw3UC2rNfSgVWYT1MiMLDUtgMy2M7j1P_eNMDq"));
log.info("==========================================");
Expand Down

0 comments on commit e8195b5

Please sign in to comment.