diff --git a/emulator/pom.xml b/emulator/pom.xml
index 98196233..89808b2c 100644
--- a/emulator/pom.xml
+++ b/emulator/pom.xml
@@ -103,6 +103,12 @@
0.4.3
test
+
+ io.github.neodix42
+ cell
+ 0.4.3
+ compile
+
\ No newline at end of file
diff --git a/emulator/src/main/java/org/ton/java/emulator/TvmVerbosityLevel.java b/emulator/src/main/java/org/ton/java/emulator/TvmVerbosityLevel.java
new file mode 100644
index 00000000..390fa96f
--- /dev/null
+++ b/emulator/src/main/java/org/ton/java/emulator/TvmVerbosityLevel.java
@@ -0,0 +1,7 @@
+package org.ton.java.emulator;
+
+import java.io.Serializable;
+
+public enum TvmVerbosityLevel implements Serializable {
+ TRUNCATED, UNLIMITED, WITH_CELL_HASH_AND_OFFSET, WITH_ALL_STACK_VALUES
+}
diff --git a/emulator/src/test/java/org/ton/java/emulator/TestTvmEmulator.java b/emulator/src/test/java/org/ton/java/emulator/TestTvmEmulator.java
index 7fb1940a..156164d6 100644
--- a/emulator/src/test/java/org/ton/java/emulator/TestTvmEmulator.java
+++ b/emulator/src/test/java/org/ton/java/emulator/TestTvmEmulator.java
@@ -17,8 +17,8 @@
import org.ton.java.cell.CellSlice;
import org.ton.java.cell.TonHashMapE;
import org.ton.java.smartcontract.FuncCompiler;
+import org.ton.java.smartcontract.GenericSmartContract;
import org.ton.java.smartcontract.types.WalletV4R2Config;
-import org.ton.java.smartcontract.utils.MsgUtils;
import org.ton.java.smartcontract.wallet.v4.WalletV4R2;
import org.ton.java.tlb.types.*;
import org.ton.java.tonlib.Tonlib;
@@ -32,6 +32,8 @@
import java.util.Collections;
import java.util.concurrent.ExecutionException;
+import static java.util.Objects.isNull;
+import static java.util.Objects.nonNull;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
@@ -66,9 +68,9 @@ public static void setUpBeforeClass() {
.pathToEmulatorSharedLib("G:/libs/emulator.dll")
.codeBoc(code.toBase64())
.dataBoc(data.toBase64())
- .verbosityLevel(3)
+ .verbosityLevel(TvmVerbosityLevel.UNLIMITED)
.build();
-// tvmEmulator.setDebugEnabled(true);
+ tvmEmulator.setDebugEnabled(true);
}
@Test
@@ -77,7 +79,7 @@ public void testInitTvmEmulator() {
long emulator = tvmEmulatorI.tvm_emulator_create(
contract.getStateInit().getCode().toBase64(),
contract.getStateInit().getData().toBase64(),
- 2);
+ TvmVerbosityLevel.UNLIMITED.ordinal());
assertNotEquals(0, emulator);
}
@@ -145,14 +147,8 @@ public void testTvmEmulatorEmulateRunMethod() {
@Test
public void testTvmEmulatorRunGetMethodGetSeqNo() {
String result = tvmEmulator.runGetMethod(
- 85143, // seqno
- VmStack.builder()
- .depth(0)
- .stack(VmStackList.builder()
- .tos(Lists.emptyList())
- .build())
- .build()
- .toCell().toBase64());
+ 85143 // seqno
+ );
log.info("result runGetMethod: {}", result);
GetMethodResult methodResult = gson.fromJson(result, GetMethodResult.class);
@@ -167,7 +163,12 @@ public void testTvmEmulatorRunGetMethodGetSeqNo() {
VmStackList vmStackList = stack.getStack();
log.info("vmStackList: {}", vmStackList.getTos());
BigInteger seqno = VmStackValueTinyInt.deserialize(CellSlice.beginParse(vmStackList.getTos().get(0).toCell())).getValue();
- log.info("seqno value: {}", seqno); // pubkey
+ log.info("seqno value: {}", seqno);
+ }
+
+ @Test
+ public void testTvmEmulatorRunGetMethodGetSeqNoShortVersion() {
+ log.info("seqno value: {}", tvmEmulator.runGetSeqNo());
}
@Test
@@ -198,21 +199,99 @@ public void testTvmEmulatorRunGetMethodGetPubKey() {
log.info("vmStackList value: {}", pubKey.toString(16)); // pubkey
}
+ @Test
+ public void testTvmEmulatorRunGetMethodGetPubKeyShortVersion() {
+ log.info("contract's pubKey: {}", tvmEmulator.runGetPublicKey()); // pubkey
+ }
+
@Test
public void testTvmEmulatorSendExternalMessage() {
+ String address = contract.getAddress().toBounceable();
+ String randSeedHex = Utils.sha256("ABC");
+// Cell configAll = tonlib.getConfigAll(128);
+
+ // optionally set C7
+ assertTrue(tvmEmulator.setC7(address,
+ Instant.now().getEpochSecond(),
+ Utils.toNano(1).longValue(),
+ randSeedHex
+ , null
+// , configAll.toBase64()
+ ));
+
+ WalletV4R2Config config = WalletV4R2Config.builder()
+ .operation(0)
+ .walletId(42)
+ .seqno(0)
+ .destination(Address.of("0:258e549638a6980ae5d3c76382afd3f4f32e34482dafc3751e3358589c8de00d"))
+ .amount(Utils.toNano(0.331))
+ .build();
+
+ assertTrue(tvmEmulator.setLibs(getLibs().toBase64()));
+
+ Message msg = contract.prepareExternalMsg(config);
+ String resultBoc = tvmEmulator.sendExternalMessage(msg.getBody().toBase64());
+
+ SendExternalMessageResult result = gson.fromJson(resultBoc, SendExternalMessageResult.class);
+ log.info("result sendExternalMessage, exitCode: {}", result.getVm_exit_code());
+ log.info("seqno value: {}", tvmEmulator.runGetSeqNo());
+ }
+
+ @Test
+ public void testTvmEmulatorSendExternalMessageCustom() throws IOException, ExecutionException, InterruptedException {
+
+ FuncCompiler smcFunc = FuncCompiler.builder()
+ .contractPath("G:/smartcontracts/new-wallet-v4r2.fc")
+ .build();
+
+ String codeCellHex = smcFunc.compile();
+ Cell codeCell = CellBuilder.beginCell().fromBoc(codeCellHex).endCell();
+
+ byte[] publicKey = Utils.hexToSignedBytes("82A0B2543D06FEC0AAC952E9EC738BE56AB1B6027FC0C1AA817AE14B4D1ED2FB");
+ byte[] secretKey = Utils.hexToSignedBytes("F182111193F30D79D517F2339A1BA7C25FDF6C52142F0F2C1D960A1F1D65E1E4");
+ TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSeed(secretKey);
+
+ Cell dataCell = CellBuilder.beginCell()
+ .storeUint(0, 32) // seqno
+ .storeUint(42, 32) // wallet id
+ .storeBytes(keyPair.getPublicKey())
+ .storeUint(0, 1) //plugins dict empty
+ .endCell();
+
+ log.info("codeCellHex {}", codeCellHex);
+ log.info("dataCellHex {}", dataCell.toHex());
+
+ tvmEmulator = TvmEmulator.builder()
+ .pathToEmulatorSharedLib("G:/libs/emulator.dll")
+ .codeBoc(codeCell.toBase64())
+ .dataBoc(dataCell.toBase64())
+ .verbosityLevel(TvmVerbosityLevel.UNLIMITED)
+ .build();
+
+ tvmEmulator.setDebugEnabled(true);
+
+ // optionally set C7
// String address = contract.getAddress().toBounceable();
// String randSeedHex = Utils.sha256("ABC");
//// Cell configAll = tonlib.getConfigAll(128);
//
// assertTrue(tvmEmulator.setC7(address,
-// Instant.now().getEpochSecond() - 300,
-// Utils.toNano(1).longValue(),
+// Instant.now().getEpochSecond(),
+// Utils.toNano(3).longValue(),
// randSeedHex
// , null
//// , configAll.toBase64()
// ));
+ GenericSmartContract smc = GenericSmartContract.builder()
+ .tonlib(tonlib)
+ .keyPair(keyPair)
+ .code(codeCellHex)
+ .data(dataCell.toHex())
+ .build();
+
+
WalletV4R2Config config = WalletV4R2Config.builder()
.operation(0)
.walletId(42)
@@ -221,11 +300,39 @@ public void testTvmEmulatorSendExternalMessage() {
.amount(Utils.toNano(0.331))
.build();
- Message msg = contract.prepareExternalMsg(config);
- String resultBoc = tvmEmulator.sendExternalMessage(msg.toCell().toBase64());
+ assertTrue(tvmEmulator.setLibs(getLibs().toBase64()));
+ Cell transferBody = createTransferBody(config);
+ Cell signedBody = CellBuilder.beginCell()
+ .storeBytes(Utils.signData(keyPair.getPublicKey(), keyPair.getSecretKey(), transferBody.hash()))
+ .storeCell(transferBody)
+ .endCell();
+ log.info("extMsg {}", signedBody.toHex());
+
+ String resultBoc = tvmEmulator.sendExternalMessage(signedBody.toBase64());
SendExternalMessageResult result = gson.fromJson(resultBoc, SendExternalMessageResult.class);
- log.info("result sendExternalMessage: {}", result);
+ log.info("result sendExternalMessage, exitCode: {}", result.getVm_exit_code());
+
+ config = WalletV4R2Config.builder()
+ .operation(0)
+ .walletId(42)
+ .seqno(1) // second transfer with seqno 0 fails with error code 33 - as expected
+ .destination(Address.of("0:258e549638a6980ae5d3c76382afd3f4f32e34482dafc3751e3358589c8de00d"))
+ .amount(Utils.toNano(0.332))
+ .build();
+
+ assertTrue(tvmEmulator.setLibs(getLibs().toBase64()));
+ transferBody = createTransferBody(config);
+ signedBody = CellBuilder.beginCell()
+ .storeBytes(Utils.signData(keyPair.getPublicKey(), keyPair.getSecretKey(), transferBody.hash()))
+ .storeCell(transferBody)
+ .endCell();
+ log.info("extMsg {}", signedBody.toHex());
+
+ resultBoc = tvmEmulator.sendExternalMessage(signedBody.toBase64());
+
+ result = gson.fromJson(resultBoc, SendExternalMessageResult.class);
+ log.info("result sendExternalMessage, exitCode: {}", result.getVm_exit_code());
}
@Test
@@ -240,10 +347,10 @@ public void testTvmEmulatorSendInternalMessageCustomContract() throws IOExceptio
TweetNaclFast.Signature.KeyPair keyPair = Utils.generateSignatureKeyPair();
Cell dataCell = CellBuilder.beginCell()
- .storeUint(0, 32) // seqno
+ .storeUint(0, 32) // seqno
.storeUint(42, 32) // wallet id
.storeBytes(keyPair.getPublicKey())
- .storeUint(0, 1) //plugins dict empty
+ .storeUint(0, 1) //plugins dict empty
.endCell();
log.info("codeCellHex {}", codeCellHex);
@@ -254,7 +361,7 @@ public void testTvmEmulatorSendInternalMessageCustomContract() throws IOExceptio
.pathToEmulatorSharedLib("G:/libs/emulator.dll")
.codeBoc(codeCell.toBase64())
.dataBoc(dataCell.toBase64())
- .verbosityLevel(1)
+ .verbosityLevel(TvmVerbosityLevel.UNLIMITED)
.build();
String address = contract.getAddress().toBounceable();
@@ -263,6 +370,7 @@ public void testTvmEmulatorSendInternalMessageCustomContract() throws IOExceptio
assertTrue(tvmEmulator.setLibs(getLibs().toBase64()));
+ // optionally set C7
// assertTrue(tvmEmulator.setC7(address,
// Instant.now().getEpochSecond(),
// Utils.toNano(1).longValue(),
@@ -277,14 +385,11 @@ public void testTvmEmulatorSendInternalMessageCustomContract() throws IOExceptio
Cell body = CellBuilder.beginCell()
.storeUint(0x706c7567, 32) // op request funds
.endCell();
- Message msg = MsgUtils.createInternalMessage(
- Address.of("0:258e549638a6980ae5d3c76382afd3f4f32e34482dafc3751e3358589c8de00d")
- , Utils.toNano(0.1), null, body, true);
String resultBoc = tvmEmulator.sendInternalMessage(body.toBase64(), Utils.toNano(0.11).longValue());
log.info("resultBoc {}", resultBoc);
SendExternalMessageResult result = gson.fromJson(resultBoc, SendExternalMessageResult.class);
- log.info("result sendInternalMessage: {}", result);
+ log.info("result sendInternalMessage, exitCode: {}", result.getVm_exit_code());
}
@@ -293,14 +398,14 @@ public void testTvmEmulatorSendInternalMessage() {
Cell body = CellBuilder.beginCell()
.storeUint(0x706c7567, 32) // op request funds
.endCell();
- Message msg = MsgUtils.createInternalMessage(
- Address.of("0:258e549638a6980ae5d3c76382afd3f4f32e34482dafc3751e3358589c8de00d")
- , Utils.toNano(0.1), null, body, true);
- String resultBoc = tvmEmulator.sendInternalMessage(msg.toCell().toBase64(), Utils.toNano(0.11).longValue());
+ assertTrue(tvmEmulator.setLibs(getLibs().toBase64()));
+ tvmEmulator.setDebugEnabled(true);
+
+ String resultBoc = tvmEmulator.sendInternalMessage(body.toBase64(), Utils.toNano(0.11).longValue());
SendExternalMessageResult result = gson.fromJson(resultBoc, SendExternalMessageResult.class);
- log.info("result sendInternalMessage: {}", result);
+ log.info("result sendInternalMessage, exitCode: {}", result.getVm_exit_code());
}
@Test
@@ -312,7 +417,6 @@ public void testTvmEmulatorSetPrevBlockInfo() {
private static Cell getLibs() {
SmcLibraryResult result = tonlib.getLibraries(
Collections.singletonList("wkUmK4wrzl6fzSPKM04dVfqW1M5pqigX3tcXzvy6P3M="));
- log.info("result: {}", result);
TonHashMapE x = new TonHashMapE(256);
@@ -330,4 +434,63 @@ private static Cell getLibs() {
);
return dictLibs;
}
+
+ private Cell createTransferBody(WalletV4R2Config config) {
+
+ CellBuilder message = CellBuilder.beginCell();
+
+ message.storeUint(config.getWalletId(), 32);
+
+ message.storeUint((config.getValidUntil() == 0) ? Instant.now().getEpochSecond() + 60 : config.getValidUntil(), 32);
+
+ message.storeUint(config.getSeqno(), 32);// msg_seqno
+
+ if (config.getOperation() == 0) {
+ Cell order = Message.builder()
+ .info(InternalMessageInfo.builder()
+ .bounce(config.isBounce())
+ .dstAddr(MsgAddressIntStd.builder()
+ .workchainId(config.getDestination().wc)
+ .address(config.getDestination().toBigInteger())
+ .build())
+ .value(CurrencyCollection.builder().coins(config.getAmount()).build())
+ .build())
+ .init(config.getStateInit())
+ .body((isNull(config.getBody()) && nonNull(config.getComment())) ?
+ CellBuilder.beginCell()
+ .storeUint(0, 32)
+ .storeString(config.getComment())
+ .endCell()
+ : config.getBody())
+ .build().toCell();
+
+ message.storeUint(BigInteger.ZERO, 8); // op simple send
+ message.storeUint(config.getMode(), 8);
+ message.storeRef(order);
+ } else if (config.getOperation() == 1) {
+ message.storeUint(1, 8); // deploy and install plugin
+ message.storeUint(BigInteger.valueOf(config.getNewPlugin().getPluginWc()), 8);
+ message.storeCoins(config.getNewPlugin().getAmount()); // plugin balance
+ message.storeRef(config.getNewPlugin().getStateInit());
+ message.storeRef(config.getNewPlugin().getBody());
+ }
+ if (config.getOperation() == 2) {
+ message.storeUint(2, 8); // install plugin
+ message.storeUint(BigInteger.valueOf(config.getDeployedPlugin().getPluginAddress().wc), 8);
+ message.storeBytes(config.getDeployedPlugin().getPluginAddress().hashPart);
+ message.storeCoins(BigInteger.valueOf(config.getDeployedPlugin().getAmount().longValue()));
+ message.storeUint(BigInteger.valueOf(config.getDeployedPlugin().getQueryId()), 64);
+ message.endCell();
+ }
+ if (config.getOperation() == 3) {
+ message.storeUint(3, 8); // remove plugin
+ message.storeUint(BigInteger.valueOf(config.getDeployedPlugin().getPluginAddress().wc), 8);
+ message.storeBytes(config.getDeployedPlugin().getPluginAddress().hashPart);
+ message.storeCoins(BigInteger.valueOf(config.getDeployedPlugin().getAmount().longValue()));
+ message.storeUint(BigInteger.valueOf(config.getDeployedPlugin().getQueryId()), 64);
+ message.endCell();
+ }
+
+ return message.endCell();
+ }
}
diff --git a/emulator/src/main/java/org/ton/java/emulator/TvmEmulator.java b/emulator/src/test/java/org/ton/java/emulator/TvmEmulator.java
similarity index 76%
rename from emulator/src/main/java/org/ton/java/emulator/TvmEmulator.java
rename to emulator/src/test/java/org/ton/java/emulator/TvmEmulator.java
index 9a602d8b..2b689ac5 100644
--- a/emulator/src/main/java/org/ton/java/emulator/TvmEmulator.java
+++ b/emulator/src/test/java/org/ton/java/emulator/TvmEmulator.java
@@ -1,10 +1,23 @@
package org.ton.java.emulator;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.ToNumberPolicy;
import com.sun.jna.Native;
import lombok.Builder;
import lombok.extern.java.Log;
+import org.assertj.core.util.Lists;
+import org.ton.java.cell.Cell;
+import org.ton.java.cell.CellBuilder;
+import org.ton.java.cell.CellSlice;
+import org.ton.java.tlb.types.VmStack;
+import org.ton.java.tlb.types.VmStackList;
+import org.ton.java.tlb.types.VmStackValueInt;
+import org.ton.java.tlb.types.VmStackValueTinyInt;
import org.ton.java.utils.Utils;
+import java.math.BigInteger;
+
import static java.util.Objects.isNull;
@Log
@@ -33,7 +46,7 @@ public class TvmEmulator {
private String codeBoc;
private String dataBoc;
- private Integer verbosityLevel;
+ private TvmVerbosityLevel verbosityLevel;
public static class TvmEmulatorBuilder {
}
@@ -78,7 +91,7 @@ public TvmEmulator build() {
super.tvmEmulatorI = Native.load(super.pathToEmulatorSharedLib, TvmEmulatorI.class);
if (isNull(super.verbosityLevel)) {
- super.verbosityLevel = 3;
+ super.verbosityLevel = TvmVerbosityLevel.WITH_ALL_STACK_VALUES;
}
if (isNull(super.codeBoc)) {
throw new Error("codeBoc is not set");
@@ -86,7 +99,7 @@ public TvmEmulator build() {
if (isNull(super.dataBoc)) {
throw new Error("dataBoc is not set");
}
- super.tvmEmulator = super.tvmEmulatorI.tvm_emulator_create(super.codeBoc, super.dataBoc, super.verbosityLevel);
+ super.tvmEmulator = super.tvmEmulatorI.tvm_emulator_create(super.codeBoc, super.dataBoc, super.verbosityLevel.ordinal());
if (super.tvmEmulator == 0) {
throw new Error("Can't create emulator instance");
@@ -197,12 +210,65 @@ public String runGetMethod(int methodId, String stackBoc) {
return tvmEmulatorI.tvm_emulator_run_get_method(tvmEmulator, methodId, stackBoc);
}
+ /**
+ * Run get method with empty input stack
+ *
+ * @param methodId Integer method id
+ * @return Json object with error:
+ * {
+ * "success": false,
+ * "error": "Error description"
+ * }
+ * Or success:
+ * {
+ * "success": true
+ * "vm_log": "...",
+ * "vm_exit_code": 0,
+ * "stack": "Base64 encoded BoC serialized stack (VmStack)",
+ * "missing_library": null,
+ * "gas_used": 1212
+ * }
+ */
+ public String runGetMethod(int methodId) {
+ return tvmEmulatorI.tvm_emulator_run_get_method(tvmEmulator, methodId,
+ VmStack.builder()
+ .depth(0)
+ .stack(VmStackList.builder()
+ .tos(Lists.emptyList())
+ .build())
+ .build()
+ .toCell().toBase64());
+ }
+
+ public BigInteger runGetSeqNo() {
+ String seqNoResult = runGetMethod(85143);
+ Gson gson = new GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL).create();
+ GetMethodResult methodResult = gson.fromJson(seqNoResult, GetMethodResult.class);
+
+ Cell cellResult = CellBuilder.beginCell().fromBocBase64(methodResult.getStack()).endCell();
+ VmStack stack = VmStack.deserialize(CellSlice.beginParse(cellResult));
+ VmStackList vmStackList = stack.getStack();
+ return VmStackValueTinyInt.deserialize(CellSlice.beginParse(vmStackList.getTos().get(0).toCell())).getValue();
+ }
+
+ public String runGetPublicKey() {
+ String pubKeyResult = runGetMethod(78748);
+ Gson gson = new GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL).create();
+ GetMethodResult methodResult = gson.fromJson(pubKeyResult, GetMethodResult.class);
+
+ Cell cellResult = CellBuilder.beginCell().fromBocBase64(methodResult.getStack()).endCell();
+ VmStack stack = VmStack.deserialize(CellSlice.beginParse(cellResult));
+ int depth = stack.getDepth();
+ VmStackList vmStackList = stack.getStack();
+ BigInteger pubKey = VmStackValueInt.deserialize(CellSlice.beginParse(vmStackList.getTos().get(0).toCell())).getValue();
+ return pubKey.toString(16);
+ }
+
/**
* Optimized version of "run get method" with all passed parameters in a single call
*
* @param len Length of params_boc buffer
* @param paramsBoc BoC serialized parameters, scheme:
- * request$_
* code:^Cell data:^Cell stack:^VmStack params:^[c7:^VmStack libs:^Cell]
* method_id:(## 32)
* @param gasLimit Gas limit
@@ -265,7 +331,6 @@ public String sendExternalMessage(String messageBodyBoc) {
public String sendInternalMessage(String messageBodyBoc, long amount) {
return tvmEmulatorI.tvm_emulator_send_internal_message(tvmEmulator, messageBodyBoc, amount);
}
-
}
diff --git a/smartcontract/src/main/java/org/ton/java/smartcontract/types/WalletV4R2Config.java b/smartcontract/src/main/java/org/ton/java/smartcontract/types/WalletV4R2Config.java
index 72f05252..7fd90aa2 100644
--- a/smartcontract/src/main/java/org/ton/java/smartcontract/types/WalletV4R2Config.java
+++ b/smartcontract/src/main/java/org/ton/java/smartcontract/types/WalletV4R2Config.java
@@ -7,6 +7,7 @@
import org.ton.java.address.Address;
import org.ton.java.cell.Cell;
import org.ton.java.smartcontract.wallet.v4.SubscriptionInfo;
+import org.ton.java.tlb.types.StateInit;
import java.math.BigInteger;
@@ -20,9 +21,12 @@ public class WalletV4R2Config implements WalletConfig {
int mode;
long validUntil;
long createdAt;
+ boolean bounce;
Address destination;
BigInteger amount;
Cell body;
+ StateInit stateInit;
+ String comment;
int operation; // 0 - simple send; 1 - deploy and install plugin; 2 - install plugin; 3 - remove plugin
SubscriptionInfo subscriptionInfo;
NewPlugin newPlugin;
diff --git a/smartcontract/src/main/java/org/ton/java/smartcontract/wallet/v4/WalletV4R2.java b/smartcontract/src/main/java/org/ton/java/smartcontract/wallet/v4/WalletV4R2.java
index a4c0aaca..bf49ff10 100644
--- a/smartcontract/src/main/java/org/ton/java/smartcontract/wallet/v4/WalletV4R2.java
+++ b/smartcontract/src/main/java/org/ton/java/smartcontract/wallet/v4/WalletV4R2.java
@@ -10,9 +10,7 @@
import org.ton.java.smartcontract.types.WalletV4R2Config;
import org.ton.java.smartcontract.utils.MsgUtils;
import org.ton.java.smartcontract.wallet.Contract;
-import org.ton.java.tlb.types.ExternalMessageInfo;
-import org.ton.java.tlb.types.Message;
-import org.ton.java.tlb.types.StateInit;
+import org.ton.java.tlb.types.*;
import org.ton.java.tonlib.Tonlib;
import org.ton.java.tonlib.types.*;
import org.ton.java.utils.Utils;
@@ -25,6 +23,7 @@
import java.util.List;
import static java.util.Objects.isNull;
+import static java.util.Objects.nonNull;
@Builder
@Getter
@@ -106,8 +105,27 @@ public Cell createTransferBody(WalletV4R2Config config) {
message.storeUint(config.getSeqno(), 32);// msg_seqno
if (config.getOperation() == 0) {
+ Cell order = Message.builder()
+ .info(InternalMessageInfo.builder()
+ .bounce(config.isBounce())
+ .dstAddr(MsgAddressIntStd.builder()
+ .workchainId(config.getDestination().wc)
+ .address(config.getDestination().toBigInteger())
+ .build())
+ .value(CurrencyCollection.builder().coins(config.getAmount()).build())
+ .build())
+ .init(config.getStateInit())
+ .body((isNull(config.getBody()) && nonNull(config.getComment())) ?
+ CellBuilder.beginCell()
+ .storeUint(0, 32)
+ .storeString(config.getComment())
+ .endCell()
+ : config.getBody())
+ .build().toCell();
+
message.storeUint(BigInteger.ZERO, 8); // op simple send
- //message.storeRef(body); ??
+ message.storeUint(config.getMode(), 8);
+ message.storeRef(order);
} else if (config.getOperation() == 1) {
message.storeUint(1, 8); // deploy and install plugin
message.storeUint(BigInteger.valueOf(config.getNewPlugin().getPluginWc()), 8);
@@ -139,7 +157,7 @@ public Cell createTransferBody(WalletV4R2Config config) {
* Deploy wallet without any plugins.
* One can also deploy plugin separately and later install into the wallet. See installPlugin().
*/
-
+
public ExtMessageInfo deploy() {
return tonlib.sendRawMessage(prepareDeployMsg().toCell().toBase64());
}
diff --git a/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestNft.java b/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestNft.java
index 834adf54..5d368436 100644
--- a/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestNft.java
+++ b/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestNft.java
@@ -210,7 +210,7 @@ public void testNft() {
//sends from adminWallet to nftItem request for static data, response comes to adminWallet
//https://github.com/ton-blockchain/token-contract/blob/main/nft/nft-item.fc#L131
- getStaticData(adminWallet, Utils.toNano(0.088), nftItem1Address, BigInteger.valueOf(661), adminWallet.getKeyPair());
+ getStaticData(adminWallet, Utils.toNano(0.088), nftItem1Address, BigInteger.valueOf(661));
// transfer nft item to nft sale smart-contract (send amount > full_price+1ton)
transferNftItem(adminWallet, Utils.toNano(1.4), nftItem1Address, BigInteger.ZERO, nftSale1.getAddress(),
@@ -250,8 +250,7 @@ public void testNft() {
"ton://my-nft/collection.json", "ton://my-nft/", 0.16,
Address.of(WALLET2_ADDRESS), adminWallet.getKeyPair());
- changeNftCollectionOwner(adminWallet, Utils.toNano(0.06), nftCollection.getAddress(),
- Address.of(WALLET2_ADDRESS), adminWallet.getKeyPair());
+ changeNftCollectionOwner(adminWallet, Utils.toNano(0.06), nftCollection.getAddress(), Address.of(WALLET2_ADDRESS));
getRoyaltyParams(adminWallet, Utils.toNano(0.0777), nftCollection.getAddress());
}
@@ -275,7 +274,7 @@ private long getNftCollectionInfo(NftCollection nftCollection) {
}
- public void changeNftCollectionOwner(WalletV3R1 wallet, BigInteger msgValue, Address nftCollectionAddress, Address newOwner, TweetNaclFast.Signature.KeyPair keyPair) {
+ public void changeNftCollectionOwner(WalletV3R1 wallet, BigInteger msgValue, Address nftCollectionAddress, Address newOwner) {
WalletV3Config walletV3Config = WalletV3Config.builder()
.walletId(42)
@@ -340,7 +339,7 @@ private void transferNftItem(WalletV3R1 wallet, BigInteger msgValue, Address nft
assertThat(extMessageInfo.getError().getCode()).isZero();
}
- private void getStaticData(WalletV3R1 wallet, BigInteger msgValue, Address nftItemAddress, BigInteger queryId, TweetNaclFast.Signature.KeyPair keyPair) {
+ private void getStaticData(WalletV3R1 wallet, BigInteger msgValue, Address nftItemAddress, BigInteger queryId) {
WalletV3Config config = WalletV3Config.builder()
.walletId(42)
.seqno(wallet.getSeqno())
diff --git a/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestWalletV4R2Plugins.java b/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestWalletV4R2Plugins.java
index 36a876b7..2941df72 100644
--- a/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestWalletV4R2Plugins.java
+++ b/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestWalletV4R2Plugins.java
@@ -223,7 +223,7 @@ public void testSimpleSend() throws InterruptedException {
log.info("pub-key {}", Utils.bytesToHex(contract.getKeyPair().getPublicKey()));
log.info("prv-key {}", Utils.bytesToHex(contract.getKeyPair().getSecretKey()));
- BigInteger balance = TestFaucet.topUpContract(tonlib, Address.of(nonBounceableAddress), Utils.toNano(7));
+ BigInteger balance = TestFaucet.topUpContract(tonlib, Address.of(nonBounceableAddress), Utils.toNano(1));
log.info("new wallet {} balance: {}", contract.getName(), Utils.formatNanoValue(balance));
// deploy wallet-v4
@@ -245,7 +245,10 @@ public void testSimpleSend() throws InterruptedException {
.walletId(contract.getWalletId())
.seqno(contract.getSeqno())
.destination(Address.of(FAUCET_ADDRESS_RAW))
- .amount(Utils.toNano(0.331)).build();
+ .mode(3)
+ .amount(Utils.toNano(0.331))
+ .comment("ton4j-v4r2-simple-send")
+ .build();
contract.send(config);
}