Skip to content

Commit 8feaa21

Browse files
committed
feature(USDT transfer): simplify USDT transfer
1 parent 62cd24c commit 8feaa21

File tree

6 files changed

+159
-31
lines changed

6 files changed

+159
-31
lines changed

src/main/java/org/tron/common/enums/NetType.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,17 @@ public enum NetType {
1919
728126428L,
2020
"TFFAMQLZybALaLb4uxHA9RBE7pxhUAjF3U",
2121
"https://open.gasfree.io",
22-
"/tron")
22+
"/tron"),
23+
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
2324
),
2425
NILE("https://nile.trongrid.io",
2526
new Grpc(FULLNODE_NILE, FULLNODE_NILE_SOLIDITY),
2627
new GasFree(
2728
3448148188L,
2829
"THQGuFzL87ZqhxkgqYEryRAd7gqFqL5rdc",
2930
"https://open-test.gasfree.io",
30-
"/nile")
31+
"/nile"),
32+
"TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"
3133
),
3234
SHASTA(
3335
"https://api.shasta.trongrid.io",
@@ -36,18 +38,21 @@ public enum NetType {
3638
2494104990L,
3739
"TSwCtDum13k1PodgNgTWx5be7k1c6eWaNP",
3840
"https://open-test.gasfree.io",
39-
"/shasta")
41+
"/shasta"),
42+
"TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs"
4043
),
41-
CUSTOM(null, null, null);
44+
CUSTOM(null, null, null, null);
4245

4346
private final String http;
4447
private final Grpc grpc;
4548
private final GasFree gasFree;
49+
private final String usdtAddress;
4650

47-
NetType(String http, Grpc grpc, GasFree gasFree) {
51+
NetType(String http, Grpc grpc, GasFree gasFree, String usdtAddress) {
4852
this.http = http;
4953
this.grpc = grpc;
5054
this.gasFree = gasFree;
55+
this.usdtAddress = usdtAddress;
5156
}
5257

5358
@Setter

src/main/java/org/tron/common/utils/Utils.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import org.tron.api.GrpcAPI.TransactionSignWeight;
7272
import org.tron.common.crypto.Hash;
7373
import org.tron.common.crypto.Sha256Sm3Hash;
74+
import org.tron.common.enums.NetType;
7475
import org.tron.core.dao.Tx;
7576
import org.tron.keystore.StringUtils;
7677
import org.tron.keystore.WalletFile;
@@ -610,7 +611,11 @@ public static Tx getTx(Chain.Transaction transaction) {
610611
tx.setType(contract.getType().name());
611612
tx.setFrom(encode58Check(triggerSmartContract.getOwnerAddress().toByteArray()));
612613
tx.setTo(encode58Check(triggerSmartContract.getContractAddress().toByteArray()));
613-
// setTransferParams(tx, triggerSmartContract);
614+
NetType netType = WalletApi.getCurrentNetwork();
615+
if (netType.getUsdtAddress().equals(encode58Check(triggerSmartContract.getContractAddress().toByteArray()))) {
616+
setTransferParams(tx, triggerSmartContract);
617+
tx.setType(contract.getType().name() + "(transferUSDT)");
618+
}
614619
break;
615620
case UpdateSettingContract:
616621
UpdateSettingContract updateSettingContract =

src/main/java/org/tron/core/manager/TxHistoryManager.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,20 @@ public class TxHistoryManager {
5151
}
5252
}
5353

54+
public TxHistoryManager() {
55+
this.currentUserAddress = null;
56+
}
57+
5458
public TxHistoryManager(String currentUserAddress) {
5559
this.currentUserAddress = Objects.requireNonNull(currentUserAddress);
5660
ensureBaseDirectoryExists();
5761
}
5862

59-
private Path getNetworkFilePath(NetType network) {
63+
public Path getNetworkFilePath(NetType network) {
6064
return Paths.get(BASE_DIR, network.name(), HISTORY_FILE);
6165
}
6266

63-
private void ensureNetworkDirectoryExists(NetType network) {
67+
public void ensureNetworkDirectoryExists(NetType network) {
6468
try {
6569
Files.createDirectories(Paths.get(BASE_DIR, network.name()));
6670
} catch (IOException e) {
@@ -240,7 +244,7 @@ private String txToLine(Tx tx) {
240244
);
241245
}
242246

243-
private Optional<Tx> lineToTx(String line) {
247+
public Optional<Tx> lineToTx(String line) {
244248
try {
245249
String[] parts = line.split(",");
246250
if (parts.length != 8) return Optional.empty();

src/main/java/org/tron/core/viewer/TxHistoryViewer.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,18 @@ private LocalDateTime getLocalDateTime(String s) {
142142
private void printTransactionPage(List<Tx> transactions, int currentPage, int totalPages) {
143143
// Print table header
144144
System.out.printf("\n=== TRANSACTIONS (Page %d of %d) ===\n", currentPage, totalPages);
145-
System.out.println("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
146-
System.out.printf("%-78s %-45s %-48s %-48s %-33s %-30s " +
145+
System.out.println("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
146+
System.out.printf("%-78s %-48s %-48s %-48s %-33s %-30s " +
147147
// "%-100s" +
148148
"\n",
149149
greenBoldHighlight("ID"), greenBoldHighlight("TYPE"), greenBoldHighlight("OWNER ADDRESS"), greenBoldHighlight("ACTIVE/TO/CONTRACT ADDRESS"), greenBoldHighlight("AMOUNT"), greenBoldHighlight("TIME")
150150
// , greenBoldHighlight("NOTE")
151151
);
152-
System.out.println("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
152+
System.out.println("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
153153

154154
// Print all transaction fields
155155
for (Tx tx : transactions) {
156-
System.out.printf("%-65s %-32s %-35s %-35s %-20s %-17s" +
156+
System.out.printf("%-65s %-35s %-35s %-35s %-20s %-17s" +
157157
// " %-100s" +
158158
"\n",
159159
tx.getId(),

src/main/java/org/tron/walletcli/Client.java

Lines changed: 114 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import static org.apache.commons.lang3.StringUtils.EMPTY;
44
import static org.tron.common.enums.NetType.CUSTOM;
5+
import static org.tron.common.enums.NetType.MAIN;
6+
import static org.tron.common.enums.NetType.NILE;
7+
import static org.tron.common.enums.NetType.SHASTA;
58
import static org.tron.common.utils.CommandHelpUtil.getCommandHelp;
69
import static org.tron.common.utils.Utils.EMPTY_STR;
710
import static org.tron.common.utils.Utils.MAX_LENGTH;
@@ -22,13 +25,17 @@
2225
import static org.tron.ledger.console.ConsoleColor.ANSI_RED;
2326
import static org.tron.ledger.console.ConsoleColor.ANSI_RESET;
2427

28+
import com.alibaba.fastjson.JSON;
29+
import com.alibaba.fastjson.JSONObject;
2530
import com.beust.jcommander.JCommander;
2631
import com.beust.jcommander.Parameter;
2732
import com.google.common.primitives.Longs;
2833
import com.google.protobuf.InvalidProtocolBufferException;
2934
import java.io.File;
3035
import java.io.IOException;
3136
import java.math.BigInteger;
37+
import java.nio.file.Files;
38+
import java.nio.file.Path;
3239
import java.nio.file.Paths;
3340
import java.security.InvalidKeyException;
3441
import java.security.NoSuchAlgorithmException;
@@ -43,8 +50,11 @@
4350
import java.util.HashMap;
4451
import java.util.Iterator;
4552
import java.util.List;
53+
import java.util.Optional;
4654
import java.util.regex.Matcher;
4755
import java.util.regex.Pattern;
56+
import java.util.stream.Collectors;
57+
import java.util.stream.Stream;
4858
import org.apache.commons.lang3.ArrayUtils;
4959
import org.apache.commons.lang3.tuple.Pair;
5060
import org.bouncycastle.util.encoders.Hex;
@@ -66,8 +76,10 @@
6676
import org.tron.common.utils.ByteUtil;
6777
import org.tron.common.utils.PathUtil;
6878
import org.tron.common.utils.Utils;
79+
import org.tron.core.dao.Tx;
6980
import org.tron.core.exception.CancelException;
7081
import org.tron.core.exception.CipherException;
82+
import org.tron.core.manager.TxHistoryManager;
7183
import org.tron.core.manager.UpdateAccountPermissionInteractive;
7284
import org.tron.keystore.StringUtils;
7385
import org.tron.ledger.TronLedgerGetAddress;
@@ -167,6 +179,7 @@ public class Client {
167179
"GetTransactionInfoByBlockNum",
168180
"GetTransactionInfoById",
169181
"GetTransactionSignWeight",
182+
"GetUsdtBalance",
170183
"Help",
171184
"ImportWallet",
172185
"ImportWalletByMnemonic",
@@ -3598,10 +3611,18 @@ private void run() {
35983611
sendCoin(parameters);
35993612
break;
36003613
}
3601-
case "transferUSDT": {
3614+
case "transferusdt": {
36023615
transferUSDT(parameters);
36033616
break;
36043617
}
3618+
case "getusdttransferbyid": {
3619+
getUsdtTransferById(parameters);
3620+
break;
3621+
}
3622+
case "getusdtbalance": {
3623+
getUsdtBalance(parameters);
3624+
break;
3625+
}
36053626
case "transferasset": {
36063627
transferAsset(parameters);
36073628
break;
@@ -3976,9 +3997,87 @@ private void run() {
39763997
}
39773998
}
39783999

3979-
private void transferUSDT(String[] parameters) {
4000+
private void getUsdtTransferById(String[] parameters) throws IOException {
4001+
NetType netType = WalletApi.getCurrentNetwork();
4002+
if (netType != MAIN && netType != NILE && netType != SHASTA) {
4003+
System.out.println("This command does not support the current network.");
4004+
return;
4005+
}
4006+
if (parameters == null || parameters.length != 1) {
4007+
System.out.println("GetUsdtTransferById needs 1 parameter like the following: ");
4008+
System.out.println("GetUsdtTransferById txId ");
4009+
return;
4010+
}
4011+
String txId = parameters[0];
4012+
TxHistoryManager txHistoryManager = new TxHistoryManager();
4013+
Path filePath = txHistoryManager.getNetworkFilePath(netType);
4014+
txHistoryManager.ensureNetworkDirectoryExists(netType);
4015+
List<Tx> txs = new ArrayList<>();
4016+
try (Stream<String> lines = Files.lines(filePath)) {
4017+
txs = Files.exists(filePath) ? lines
4018+
.filter(line -> !line.trim().isEmpty()).map(txHistoryManager::lineToTx)
4019+
.filter(Optional::isPresent)
4020+
.map(Optional::get).collect(Collectors.toList()) : new ArrayList<>();
4021+
} catch (IOException e) {
4022+
System.err.println("Failed to count transactions: " + e.getMessage());
4023+
}
4024+
Optional<Tx> foundTx = txs.stream()
4025+
.filter(tx -> tx.getId().equals(txId))
4026+
.findFirst();
4027+
4028+
if (foundTx.isPresent()) {
4029+
Tx tx = foundTx.get();
4030+
JSONObject json = new JSONObject(true);
4031+
json.put("id", tx.getId());
4032+
json.put("type", tx.getType());
4033+
json.put("from", tx.getFrom());
4034+
json.put("to", tx.getTo());
4035+
json.put("amount", Long.parseLong(tx.getAmount()));
4036+
String prefix = netType == MAIN ? EMPTY : (netType.name().toLowerCase() + ".");
4037+
json.put("tronscanQueryUrl", String.format("https://%stronscan.org/#/transaction/%s", prefix, txId));
4038+
System.out.println(JSON.toJSONString(json, true));
4039+
} else {
4040+
System.out.println("The USDT transfer you inquired about does not exist.");
4041+
}
4042+
}
4043+
4044+
private void getUsdtBalance(String[] parameters) throws Exception {
4045+
NetType netType = WalletApi.getCurrentNetwork();
4046+
if (netType != MAIN && netType != NILE && netType != SHASTA) {
4047+
System.out.println("This command does not support the current network.");
4048+
return;
4049+
}
4050+
byte[] ownerAddress;
4051+
if (ArrayUtils.isEmpty(parameters)) {
4052+
ownerAddress = null;
4053+
} else if (parameters.length == 1) {
4054+
ownerAddress = WalletApi.decodeFromBase58Check(parameters[0]);
4055+
if (ownerAddress == null) {
4056+
System.out.println("The address you entered is invalid.");
4057+
return;
4058+
}
4059+
} else {
4060+
System.out.println("GetUsdtBalance needs no parameter or 1 parameter like the following: ");
4061+
System.out.println("GetUsdtBalance Address ");
4062+
return;
4063+
}
4064+
Pair<Boolean, Long> pair = walletApiWrapper.getUsdtBalance(ownerAddress);
4065+
if (Boolean.TRUE.equals(pair.getLeft())) {
4066+
long balance = pair.getRight();
4067+
System.out.println("USDT balance = " + balance);
4068+
} else {
4069+
System.out.println("GetUsdtBalance " + failedHighlight() + " !!!!");
4070+
}
4071+
}
4072+
4073+
private void transferUSDT(String[] parameters) throws Exception {
4074+
NetType netType = WalletApi.getCurrentNetwork();
4075+
if (netType != MAIN && netType != NILE && netType != SHASTA) {
4076+
System.out.println("This command does not support the current network.");
4077+
return;
4078+
}
39804079
if (parameters == null || (parameters.length != 2 && parameters.length != 3)) {
3981-
System.out.println("TransferUSDT needs 2 parameters like following: ");
4080+
System.out.println("TransferUSDT needs at least 2 parameters like following: ");
39824081
System.out.println("TransferUSDT [OwnerAddress] ToAddress Amount");
39834082
return;
39844083
}
@@ -3992,23 +4091,20 @@ private void transferUSDT(String[] parameters) {
39924091
return;
39934092
}
39944093
}
3995-
39964094
String base58ToAddress = parameters[index++];
3997-
byte[] toAddress = WalletApi.decodeFromBase58Check(base58ToAddress);
3998-
if (toAddress == null) {
3999-
System.out.println("Invalid toAddress.");
4000-
return;
4095+
String amountStr = parameters[index];
4096+
String inputStr = String.format("\"%s\",%s", base58ToAddress, amountStr);
4097+
final String methodStr = "transfer(address,uint256)";
4098+
byte[] input = Hex.decode(AbiUtil.parseMethod(methodStr, inputStr, false));
4099+
byte[] contractAddress = WalletApi.decodeFromBase58Check(netType.getUsdtAddress());
4100+
boolean result = walletApiWrapper.callContract(
4101+
ownerAddress, contractAddress, 0, input, 1000000000, 0, "", false);
4102+
if (result) {
4103+
System.out.println("Transfer " + amountStr + " to " + base58ToAddress + " " + successfulHighlight() + ".\n"
4104+
+ "Please check the given transaction id to get the result on blockchain using getTransactionInfoById command");
4105+
} else {
4106+
System.out.println("Transfer " + amountStr + " to " + base58ToAddress + " " + failedHighlight() + ".");
40014107
}
4002-
4003-
String amountStr = parameters[index++];
4004-
long amount = Long.parseLong(amountStr);
4005-
4006-
// boolean result = walletApiWrapper.transferUSDT(ownerAddress, toAddress, amount);
4007-
// if (result) {
4008-
// System.out.println("Transfer " + amount + " to " + base58ToAddress + " " + successfulHighlight() + " !!");
4009-
// } else {
4010-
// System.out.println("Transfer " + amount + " to " + base58ToAddress + " " + failedHighlight() + " !!");
4011-
// }
40124108
}
40134109

40144110
private void viewBackupRecords(String[] parameters) {

src/main/java/org/tron/walletcli/WalletApiWrapper.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,24 @@ public boolean callContract(byte[] ownerAddress, byte[] contractAddress, long ca
13331333
isConstant, false).getLeft();
13341334
}
13351335

1336+
public Pair<Boolean, Long> getUsdtBalance(byte[] ownerAddress)
1337+
throws Exception {
1338+
if (wallet == null || !wallet.isLoginState()) {
1339+
// Reference Gasfree balance, login is required to query, as historical methods are reused
1340+
System.out.println("Warning: getUsdtBalance " + failedHighlight() + ", Please login first !!");
1341+
return Pair.of(false, 0L);
1342+
}
1343+
if (ArrayUtils.isEmpty(ownerAddress)) {
1344+
ownerAddress = wallet.getAddress();
1345+
}
1346+
byte[] d = Hex.decode(AbiUtil.parseMethod("balanceOf(address)",
1347+
"\"" + encode58Check(ownerAddress) + "\"", false));
1348+
NetType netType = WalletApi.getCurrentNetwork();
1349+
byte[] contractAddress = WalletApi.decodeFromBase58Check(netType.getUsdtAddress());
1350+
return wallet.triggerContract(ownerAddress, contractAddress,
1351+
0, d, 0, 0, EMPTY, true, false);
1352+
}
1353+
13361354
public boolean estimateEnergy(byte[] ownerAddress, byte[] contractAddress, long callValue,
13371355
byte[] data, long tokenValue, String tokenId)
13381356
throws CipherException, IOException, CancelException {

0 commit comments

Comments
 (0)