diff --git a/smartcontract/src/test/java/org/ton/java/smartcontract/TestTonSdkTestCasesSmartContracts.java b/smartcontract/src/test/java/org/ton/java/smartcontract/TestTonSdkTestCasesSmartContracts.java index cdb5c5ae..86eeeac7 100644 --- a/smartcontract/src/test/java/org/ton/java/smartcontract/TestTonSdkTestCasesSmartContracts.java +++ b/smartcontract/src/test/java/org/ton/java/smartcontract/TestTonSdkTestCasesSmartContracts.java @@ -11,16 +11,22 @@ import org.junit.runners.JUnit4; import org.ton.java.address.Address; import org.ton.java.cell.CellBuilder; +import org.ton.java.smartcontract.token.ft.JettonMinterStableCoin; +import org.ton.java.smartcontract.token.ft.JettonWalletStableCoin; import org.ton.java.smartcontract.types.WalletCodes; import org.ton.java.smartcontract.types.WalletV3Config; import org.ton.java.smartcontract.types.WalletV4R2Config; +import org.ton.java.smartcontract.utils.MsgUtils; import org.ton.java.smartcontract.wallet.v3.WalletV3R2; import org.ton.java.smartcontract.wallet.v4.WalletV4R2; import org.ton.java.tlb.types.Message; +import org.ton.java.tonlib.Tonlib; +import org.ton.java.tonlib.types.ExtMessageInfo; import org.ton.java.utils.Utils; import java.io.IOException; import java.math.BigDecimal; +import java.math.BigInteger; import java.net.URL; import java.nio.charset.Charset; @@ -547,4 +553,225 @@ public void testSmartContracts13() { Message sendMsg = contract.prepareExternalMsg(config); assertThat(sendMsg.toCell().toHex(true).toUpperCase()).isEqualTo(expectedBocAsHex); } + + @Test + public void testSmartContracts14() { + + String testId = "smartcontracts-14"; + TonSdkTestCases.TestCase testCase = tonSdkTestCases.getTestCases().get(testId); + + String description = testCase.getDescription(); + + log.info("testId: {}", testId); + log.info("description: {}", description); + + String usdtMasterContractAddress = testCase.getInput().get("usdtMasterContractAddress").toString(); + BigDecimal amountToncoinsToJettonWallet = new BigDecimal(testCase.getInput().get("amountToncoinsToJettonWallet").toString()); + BigInteger amountNanoUsdt = new BigInteger(testCase.getInput().get("amountNanoUsdt").toString()); + BigInteger forwardAmountNanocoins = new BigInteger(testCase.getInput().get("forwardAmountNanocoins").toString()); + String forwardComment = testCase.getInput().get("forwardComment").toString(); + + // careful - mainnet + Tonlib tonlib = Tonlib.builder() + .testnet(false) + .ignoreCache(false) + .build(); + + Address usdtMasterAddress = Address.of(usdtMasterContractAddress); + + //64 bytes private key of your wallet, top it up before using + byte[] secretKey = Utils.hexToSignedBytes("add"); + + //use when you have 64 bytes private key + TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSecretKey(secretKey); + + //use when you have 32 bytes private key + //TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSeed(secretKey); + + // create random wallet + WalletV3R2 randomDestinationWallet = WalletV3R2.builder() + .keyPair(Utils.generateSignatureKeyPair()) + .walletId(42) + .build(); + + // use your wallet + WalletV3R2 myWallet = WalletV3R2.builder() + .tonlib(tonlib) + .keyPair(keyPair) + .walletId(42) + .build(); + + String nonBounceableAddress = myWallet.getAddress().toNonBounceable(); + String bounceableAddress = myWallet.getAddress().toBounceable(); + String rawAddress = myWallet.getAddress().toRaw(); + + log.info("non-bounceable address: {}", nonBounceableAddress); + log.info(" bounceable address: {}", bounceableAddress); + log.info(" raw address: {}", rawAddress); + log.info("pub-key {}", Utils.bytesToHex(myWallet.getKeyPair().getPublicKey())); + log.info("prv-key {}", Utils.bytesToHex(myWallet.getKeyPair().getSecretKey())); + + String status = tonlib.getAccountStatus(Address.of(bounceableAddress)); + log.info("account status {}", status); + + String balance = tonlib.getAccountBalance(Address.of(bounceableAddress)); + log.info("account balance {}", Utils.formatNanoValue(balance)); + + // myWallet.deploy(); + // myWallet.waitForDeployment(30); + + // get usdt jetton master (minter) address + JettonMinterStableCoin usdtMasterWallet = JettonMinterStableCoin.builder() + .tonlib(tonlib) + .customAddress(usdtMasterAddress) + .build(); + + log.info("usdt total supply: {}", Utils.formatJettonValue(usdtMasterWallet.getTotalSupply(), 6, 2)); + + // get my JettonWallet the one that holds my jettons (USDT) tokens + JettonWalletStableCoin myJettonWallet = usdtMasterWallet.getJettonWallet(myWallet.getAddress()); + log.info("my jettonWallet balance: {}", Utils.formatJettonValue(myJettonWallet.getBalance(), 6, 2)); + + // send my jettons to external address + WalletV3Config walletV3Config = WalletV3Config.builder() + .walletId(42) + .seqno(myWallet.getSeqno()) + .destination(myJettonWallet.getAddress()) + .amount(Utils.toNano(amountToncoinsToJettonWallet)) + .body(JettonWalletStableCoin.createTransferBody( + 0, + amountNanoUsdt, // jettons to send + randomDestinationWallet.getAddress(), // recipient + null, // response address + forwardAmountNanocoins, // forward amount + MsgUtils.createTextMessageBody(forwardComment)) + ).build(); + ExtMessageInfo extMessageInfo = myWallet.send(walletV3Config); + assertThat(extMessageInfo.getError().getCode()).isZero(); + + Utils.sleep(90, "transferring 0.02 USDT jettons to wallet " + randomDestinationWallet.getAddress()); + + BigInteger expectedBalanceOfNanocoinsAtRandomAddress = new BigInteger(testCase.getExpectedOutput().get("balanceOfNanocoinsAtRandomAddress").toString()); + BigInteger expectedBalanceOfJettonsAtRandomAddress = new BigInteger(testCase.getExpectedOutput().get("balanceOfJettonsAtRandomAddress").toString()); + + BigInteger balanceOfDestinationWallet = new BigInteger(tonlib.getAccountBalance(randomDestinationWallet.getAddress())); + log.info("balanceOfDestinationWallet in toncoins: {}", balanceOfDestinationWallet); + + JettonWalletStableCoin randomJettonWallet = usdtMasterWallet.getJettonWallet(randomDestinationWallet.getAddress()); + BigInteger balanceOfJettonWallet = randomJettonWallet.getBalance(); + log.info("balanceOfJettonWallet in jettons: {}", Utils.formatJettonValue(balanceOfJettonWallet, 6, 2)); + + assertThat(balanceOfDestinationWallet).isEqualTo(expectedBalanceOfNanocoinsAtRandomAddress); + assertThat(balanceOfJettonWallet).isEqualTo(expectedBalanceOfJettonsAtRandomAddress); + } + + @Test + public void testSmartContracts15() { + + String testId = "smartcontracts-15"; + TonSdkTestCases.TestCase testCase = tonSdkTestCases.getTestCases().get(testId); + + String description = testCase.getDescription(); + + log.info("testId: {}", testId); + log.info("description: {}", description); + + String usdtMasterContractAddress = testCase.getInput().get("usdtMasterContractAddress").toString(); + BigDecimal amountToncoinsToJettonWallet = new BigDecimal(testCase.getInput().get("amountToncoinsToJettonWallet").toString()); + BigInteger amountNanoUsdt = new BigInteger(testCase.getInput().get("amountNanoUsdt").toString()); + BigInteger forwardAmountNanocoins = new BigInteger(testCase.getInput().get("forwardAmountNanocoins").toString()); + + // careful - mainnet + Tonlib tonlib = Tonlib.builder() + .testnet(false) + .ignoreCache(false) + .build(); + + Address usdtMasterAddress = Address.of(usdtMasterContractAddress); + + //64 bytes private key of your wallet, top it up before using + byte[] secretKey = Utils.hexToSignedBytes("add"); + + //use when you have 64 bytes private key + TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSecretKey(secretKey); + + //use when you have 32 bytes private key + //TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSeed(secretKey); + + // create random wallet + WalletV4R2 randomDestinationWallet = WalletV4R2.builder() + .keyPair(Utils.generateSignatureKeyPair()) + .walletId(42) + .build(); + + // use your wallet + WalletV4R2 myWallet = WalletV4R2.builder() + .tonlib(tonlib) + .keyPair(keyPair) + .walletId(42) + .build(); + + String nonBounceableAddress = myWallet.getAddress().toNonBounceable(); + String bounceableAddress = myWallet.getAddress().toBounceable(); + String rawAddress = myWallet.getAddress().toRaw(); + + log.info("non-bounceable address: {}", nonBounceableAddress); + log.info(" bounceable address: {}", bounceableAddress); + log.info(" raw address: {}", rawAddress); + log.info("pub-key {}", Utils.bytesToHex(myWallet.getKeyPair().getPublicKey())); + log.info("prv-key {}", Utils.bytesToHex(myWallet.getKeyPair().getSecretKey())); + + String status = tonlib.getAccountStatus(Address.of(bounceableAddress)); + log.info("account status {}", status); + + String balance = tonlib.getAccountBalance(Address.of(bounceableAddress)); + log.info("account balance {}", Utils.formatNanoValue(balance)); + + // myWallet.deploy(); + // myWallet.waitForDeployment(30); + + // get usdt jetton master (minter) address + JettonMinterStableCoin usdtMasterWallet = JettonMinterStableCoin.builder() + .tonlib(tonlib) + .customAddress(usdtMasterAddress) + .build(); + + log.info("usdt total supply: {}", Utils.formatJettonValue(usdtMasterWallet.getTotalSupply(), 6, 2)); + + // get my JettonWallet the one that holds my jettons (USDT) tokens + JettonWalletStableCoin myJettonWallet = usdtMasterWallet.getJettonWallet(myWallet.getAddress()); + log.info("my jettonWallet balance: {}", Utils.formatJettonValue(myJettonWallet.getBalance(), 6, 2)); + + // send my jettons to external address + WalletV4R2Config walletV4Config = WalletV4R2Config.builder() + .walletId(42) + .seqno(myWallet.getSeqno()) + .destination(myJettonWallet.getAddress()) + .amount(Utils.toNano(amountToncoinsToJettonWallet)) + .body(JettonWalletStableCoin.createTransferBody( + 0, + amountNanoUsdt, // jettons to send + randomDestinationWallet.getAddress(), // recipient + null, // response address + forwardAmountNanocoins, // forward amount + null) // forward payload + ).build(); + ExtMessageInfo extMessageInfo = myWallet.send(walletV4Config); + assertThat(extMessageInfo.getError().getCode()).isZero(); + + Utils.sleep(90, "transferring 0.02 USDT jettons to wallet " + randomDestinationWallet.getAddress()); + + BigInteger expectedBalanceOfNanocoinsAtRandomAddress = new BigInteger(testCase.getExpectedOutput().get("balanceOfNanocoinsAtRandomAddress").toString()); + BigInteger expectedBalanceOfJettonsAtRandomAddress = new BigInteger(testCase.getExpectedOutput().get("balanceOfJettonsAtRandomAddress").toString()); + + BigInteger balanceOfDestinationWallet = new BigInteger(tonlib.getAccountBalance(randomDestinationWallet.getAddress())); + log.info("balanceOfDestinationWallet in toncoins: {}", balanceOfDestinationWallet); + + JettonWalletStableCoin randomJettonWallet = usdtMasterWallet.getJettonWallet(randomDestinationWallet.getAddress()); + BigInteger balanceOfJettonWallet = randomJettonWallet.getBalance(); + log.info("balanceOfJettonWallet in jettons: {}", Utils.formatJettonValue(balanceOfJettonWallet, 6, 2)); + + assertThat(balanceOfDestinationWallet).isEqualTo(expectedBalanceOfNanocoinsAtRandomAddress); + assertThat(balanceOfJettonWallet).isEqualTo(expectedBalanceOfJettonsAtRandomAddress); + } } diff --git a/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestJettonStableCoinMainnet.java b/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestJettonStableCoinMainnet.java index 67981d7c..fff31d4b 100644 --- a/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestJettonStableCoinMainnet.java +++ b/smartcontract/src/test/java/org/ton/java/smartcontract/integrationtests/TestJettonStableCoinMainnet.java @@ -9,8 +9,10 @@ import org.ton.java.smartcontract.token.ft.JettonMinterStableCoin; import org.ton.java.smartcontract.token.ft.JettonWalletStableCoin; import org.ton.java.smartcontract.types.WalletV3Config; +import org.ton.java.smartcontract.types.WalletV4R2Config; import org.ton.java.smartcontract.utils.MsgUtils; import org.ton.java.smartcontract.wallet.v3.WalletV3R2; +import org.ton.java.smartcontract.wallet.v4.WalletV4R2; import org.ton.java.tonlib.Tonlib; import org.ton.java.tonlib.types.ExtMessageInfo; import org.ton.java.utils.Utils; @@ -33,13 +35,12 @@ public void testJettonStableCoin() { tonlib = Tonlib.builder() .testnet(false) .ignoreCache(false) -// .verbosityLevel(VerbosityLevel.DEBUG) .build(); Address usdtMasterAddress = Address.of(USDT_MASTER_WALLET); //64 bytes private key of your wallet - byte[] secretKey = Utils.hexToSignedBytes(""); + byte[] secretKey = Utils.hexToSignedBytes("add"); //use when you have 64 bytes private key TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSecretKey(secretKey); @@ -53,6 +54,11 @@ public void testJettonStableCoin() { TweetNaclFast.Signature.KeyPair keyPair = Utils.generateSignatureKeyPair(); */ + WalletV3R2 randomDestinationWallet = WalletV3R2.builder() + .keyPair(Utils.generateSignatureKeyPair()) + .walletId(42) + .build(); + // use your wallet WalletV3R2 myWallet = WalletV3R2.builder() .tonlib(tonlib) @@ -99,15 +105,121 @@ public void testJettonStableCoin() { .amount(Utils.toNano(0.02)) .body(JettonWalletStableCoin.createTransferBody( 0, - BigInteger.valueOf(20000), // 2 cents - Address.of("EQDaVo6hnW_zf99qxX0fJGH4kOJbAVdXaJnJs4x37bNGJyTZ"), // recipient - null, // response address - BigInteger.ONE, // forward amount + BigInteger.valueOf(20000), // 2 cents + randomDestinationWallet.getAddress(), // recipient + null, // response address + BigInteger.ONE, // forward amount MsgUtils.createTextMessageBody("gift")) // forward payload ).build(); ExtMessageInfo extMessageInfo = myWallet.send(walletV3Config); assertThat(extMessageInfo.getError().getCode()).isZero(); - Utils.sleep(30, "transferring 0.02 USDT jettons to wallet EQDaVo6hnW_zf99qxX0fJGH4kOJbAVdXaJnJs4x37bNGJyTZ"); + Utils.sleep(90, "transferring 0.02 USDT jettons to wallet " + randomDestinationWallet.getAddress()); + + BigInteger balanceOfDestinationWallet = new BigInteger(tonlib.getAccountBalance(randomDestinationWallet.getAddress())); + log.info("balanceOfDestinationWallet in toncoins: {}", balanceOfDestinationWallet); + assertThat(balanceOfDestinationWallet).isEqualTo(BigInteger.ONE); + + JettonWalletStableCoin randomJettonWallet = usdtMasterWallet.getJettonWallet(randomDestinationWallet.getAddress()); + BigInteger randomJettonWalletBalance = randomJettonWallet.getBalance(); + log.info("randomJettonWallet balance in jettons: {}", Utils.formatJettonValue(randomJettonWalletBalance, 6, 2)); + assertThat(randomJettonWalletBalance).isEqualTo(BigInteger.valueOf(20000)); + } + + @Test + public void testJettonStableCoinV4R2() { + // careful - mainnet + tonlib = Tonlib.builder() + .testnet(false) + .ignoreCache(false) + .build(); + + Address usdtMasterAddress = Address.of(USDT_MASTER_WALLET); + + //64 bytes private key of your wallet + byte[] secretKey = Utils.hexToSignedBytes("add"); + + //use when you have 64 bytes private key + TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSecretKey(secretKey); + + //use when you have 32 bytes private key + //TweetNaclFast.Signature.KeyPair keyPair = TweetNaclFast.Signature.keyPair_fromSeed(secretKey); + + + // generate private key and get wallet address, that you top up later + // TweetNaclFast.Signature.KeyPair keyPair = Utils.generateSignatureKeyPair(); + + + WalletV4R2 randomDestinationWallet = WalletV4R2.builder() + .keyPair(Utils.generateSignatureKeyPair()) + .walletId(42) + .build(); + + // use your wallet + WalletV4R2 myWallet = WalletV4R2.builder() + .tonlib(tonlib) + .keyPair(keyPair) + .walletId(42) + .build(); + + String nonBounceableAddress = myWallet.getAddress().toNonBounceable(); + String bounceableAddress = myWallet.getAddress().toBounceable(); + String rawAddress = myWallet.getAddress().toRaw(); + + log.info("non-bounceable address: {}", nonBounceableAddress); + log.info(" bounceable address: {}", bounceableAddress); + log.info(" raw address: {}", rawAddress); + log.info("pub-key {}", Utils.bytesToHex(myWallet.getKeyPair().getPublicKey())); + log.info("prv-key {}", Utils.bytesToHex(myWallet.getKeyPair().getSecretKey())); + + String status = tonlib.getAccountStatus(Address.of(bounceableAddress)); + log.info("account status {}", status); + + String balance = tonlib.getAccountBalance(Address.of(bounceableAddress)); + log.info("account balance {}", Utils.formatNanoValue(balance)); + +// myWallet.deploy(); +// myWallet.waitForDeployment(90); + + // get usdt jetton master (minter) address + JettonMinterStableCoin usdtMasterWallet = JettonMinterStableCoin.builder() + .tonlib(tonlib) + .customAddress(usdtMasterAddress) + .build(); + + log.info("usdt total supply: {}", Utils.formatJettonValue(usdtMasterWallet.getTotalSupply(), 6, 2)); + + // get my JettonWallet the one that holds my jettons (USDT) tokens + JettonWalletStableCoin myJettonWallet = usdtMasterWallet.getJettonWallet(myWallet.getAddress()); + log.info("my jettonWallet balance: {}", Utils.formatJettonValue(myJettonWallet.getBalance(), 6, 2)); + + // send my jettons to external address + WalletV4R2Config walletV4Config = WalletV4R2Config.builder() + .walletId(42) + .seqno(myWallet.getSeqno()) + .destination(myJettonWallet.getAddress()) + .amount(Utils.toNano(0.02)) + .body(JettonWalletStableCoin.createTransferBody( + 0, + BigInteger.valueOf(20000), // 2 cents + randomDestinationWallet.getAddress(), // recipient + null, // response address + BigInteger.ZERO, // forward amount + null) // forward payload + ).build(); + ExtMessageInfo extMessageInfo = myWallet.send(walletV4Config); + assertThat(extMessageInfo.getError().getCode()).isZero(); + + Utils.sleep(120, "transferring 0.02 USDT jettons to wallet " + randomDestinationWallet.getAddress()); + + BigInteger balanceOfDestinationWallet = new BigInteger(tonlib.getAccountBalance(randomDestinationWallet.getAddress())); + log.info("balanceOfDestinationWallet in toncoins: {}", balanceOfDestinationWallet); + + JettonWalletStableCoin randomJettonWallet = usdtMasterWallet.getJettonWallet(randomDestinationWallet.getAddress()); + BigInteger randomJettonWalletBalance = randomJettonWallet.getBalance(); + log.info("randomJettonWallet balance in jettons: {}", Utils.formatJettonValue(randomJettonWalletBalance, 6, 2)); + + assertThat(balanceOfDestinationWallet).isEqualTo(BigInteger.ZERO); + assertThat(randomJettonWalletBalance).isEqualTo(BigInteger.valueOf(20000)); } } diff --git a/tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java b/tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java index 2ca84e01..d3f95667 100644 --- a/tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java +++ b/tonlib/src/main/java/org/ton/java/tonlib/Tonlib.java @@ -831,7 +831,11 @@ public String getAccountStatus(Address address) { * @return String - uninitialized, frozen or active. */ public String getAccountBalance(Address address) { - return getRawAccountState(address).getBalance(); + String balance = getRawAccountState(address).getBalance(); + if (balance.equals("-1")) { + return "0"; + } + return balance; } /**