From 21172cdb35c43b1f1fd8dc9f1cf4b1e0b4829523 Mon Sep 17 00:00:00 2001 From: neodiX Date: Mon, 10 Jun 2024 20:42:03 +0200 Subject: [PATCH] tested sendInternalMessage and sendExternalMessage; next to test emulateRunMethod - WIP --- emulator/pom.xml | 6 + .../ton/java/emulator/TvmVerbosityLevel.java | 7 + .../ton/java/emulator/TestTvmEmulator.java | 225 +++++++++++++++--- .../org/ton/java/emulator/TvmEmulator.java | 75 +++++- .../smartcontract/types/WalletV4R2Config.java | 4 + .../smartcontract/wallet/v4/WalletV4R2.java | 28 ++- .../integrationtests/TestNft.java | 9 +- .../TestWalletV4R2Plugins.java | 7 +- 8 files changed, 313 insertions(+), 48 deletions(-) create mode 100644 emulator/src/main/java/org/ton/java/emulator/TvmVerbosityLevel.java rename emulator/src/{main => test}/java/org/ton/java/emulator/TvmEmulator.java (76%) 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); }