Наступает эпоха Web3. Скоро во многих сервисах рядом с Mastercard/Visa появятся такие пункты, как USDT, USDC, BUSD и т. д. Как вы возможно уже догадались, речь пойдет о криптовалютах. Все эти койны являются эквивалентны американскому доллару. Главное, что нужно знать о них, это то, что они не управляются одной компанией, а все кошельки и транзакции распределены сетью серверов. Из плюсов-невозможность заблокировать средства на счету и доступ по всему земному шару, где есть интернет.
Для начала обоснуем выбор сети и какую именно валюту мы хотим внедрить. Мой выбор пал на TRON USDT по нескольким причинам:
Он популярен и у вас не возникнет вопросов, как превратить его в реальные деньги.
Низкие комиссии на блокчейне (~0.2$) и при выводе с криптобирж
Первое: нужно скачать Defi кошелек, например, TrustWallet. Он поможет сгенерировать секретную seed фразу, которая используется для получения секретных ключей для любого блокчейна. После регистрации и сохранения seed фразы нужно найти адрес вашего Tron кошелька в таком формате TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t.
Комиссии платятся токеном TRX. Покупаем с карты минимальное количество USDT и TRX. Самый быстрый способ это сделать-через bestchange.ru.
Поехали кодить. Tron Usdt существует в виде смарт контракта, который называется TRC20. Контрактом называют программный код на языке solidity, который говорит, как будет происходить перевод от одного кошелька к другому и определяет интерфейс для перевода. По контракту TRC20 работает не только USDT, а также другие монеты. Так что автоматом вы можете принимать много других монет, которые работают на TRC20.
Последовательность наших действий:
Последовательность наших действий:
Сгенерировать публичный и приватный ключ из seed фразы
Сгенерировать адрес кошелька из приватного ключа
Создать транзакцию
Подписать транзакцию
Отправить подписанную транзакцию в сеть
Всё будем Всё будем делать на Java. Я буду использовать Android, чтобы у меня был отдельный девайс, который выполнял бы все транзакции, и я не светил приватные ключи на чужом хостинге.
Генерируем публичный приватный ключ с помощью bitcoinj и фразы, которую мы сгенерировали в кошельке.
dependencies {
implementation 'org.bitcoinj:bitcoinj-core:0.15.9'
}
SDeterministicKey generateKeys(String mnemonic) {
byte[] seed = MnemonicCode.toSeed(Arrays.asList(mnemonic.split(" ")), "");
DeterministicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed);
DeterministicHierarchy dh = new DeterministicHierarchy(masterPrivateKey);
String TRON_DERIVATION_PATH = "M/44H/195H/0H/0";
List<ChildNumber> path = HDUtils.parsePath(TRON_DERIVATION_PATH);
int depth = path.size() - 1;
DeterministicKey startWallet = dh.deriveChild(path.subList(0, depth), false, true, path.get(depth));
DeterministicKey firstWallet = HDKeyDerivation.deriveChildKey(startWallet, new ChildNumber(0));
return firstWallet;
}
String mnemonic = "quote enemy figure clog project logic dismiss train wing shoe cement tribe";
DeterministicKey wallet = generateKeys(mnemonic);
String privKeyStr = wallet.getPrivateKeyAsHex();
// 8296345bd446198a4a3f10a91b0ebbfe6a327e52ca14bcdb3ce2ff6e2e37a6f5
String publicKey = wallet.getPublicKeyAsHex();
// 03f0d4462517b3c6512d3b0f5f83e698cd9eb512f364cebc3cc51e6fc988ddf974
Далее из публичного ключа генерируем адрес.
public static byte[] sha256(byte[] input) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(input);
return digest.digest();
} catch (NoSuchAlgorithmException var1) {
throw new RuntimeException(var1);
}
}
public static byte[] sha3(byte[] input) {
Keccak.DigestKeccak kecc = new Keccak.Digest256();
kecc.update(input);
return kecc.digest();
}
private static String public2Address(byte[] publicKey) {
byte[] hash = sha3(copyOfRange(publicKey, 1, publicKey.length));
byte[] address = copyOfRange(hash, 11, hash.length);
address[0] = 65; // T symbol
byte[] salt = sha256(sha256(address));
byte[] inputCheck = new byte[address.length + 4];
System.arraycopy(address, 0, inputCheck, 0, address.length);
System.arraycopy(salt, 0, inputCheck, address.length, 4);
return Base58.encode(inputCheck);
}
String address = public2Address(wallet.getPubKeyPoint().getEncoded(false));
// TYTuGuNJsyb2YEvvQPuG53eqJogArdYCUt
Сверяем адрес публичный и приватный ключи на сайте https://iancoleman.io/bip39/
Создаем транзакцию по документации.
Для этого нам нужно создать параметры в формате Abi.
String prepareParameter(String address, double amountUsdt) {
byte[] addressBytes = Base58.decode(address);
addressBytes = Arrays.copyOfRange(addressBytes, 1, 21);
byte[] amountBytes = BigDecimal.valueOf(amountUsdt)
.multiply(BigDecimal.valueOf(1000000)).toBigInteger().toByteArray();
return dataToAbi(addressBytes) + dataToAbi(amountBytes);
}
String dataToAbi(byte[] bytes) {
byte[] result = new byte[32];
System.arraycopy(bytes, 0, result, 32 - bytes.length, bytes.length);
return hex(result);
}
String parameter = prepareParameter(address, 0.01);
// 000000000000000000000000F6C0085430DBA6465BA81FC0E4317EC8EDD02EF10000000000000000000000000000000000000000000000000000000000002710
Делаем запрос.
POST https://api.trongrid.io/wallet/triggersmartcontract
{
"owner_address": "[YOUR_ADDRESS]",
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", //адрес USDT контракта
"function_selector": "transfer(address,uint256)",
"call_value": 0,
"visible": true,
"parameter": "[YOUR_ABI_PARAMETER]",
"fee_limit": 100000000
}
Подписываем идентификатор транзакции(txID) с помощью Tronj
String signTransaction(String txId, String privateKeyStr) {
Bytes32 private32 = Bytes32.fromHexString(privateKeyStr);
SECP256K1.PrivateKey privateKey = SECP256K1.PrivateKey.create(private32);
SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.create(privateKey);
Bytes32 trId32 = Bytes32.wrap(Hex.decode(txId.getBytes()));
SECP256K1.Signature sig = SECP256K1.sign(trId32, keyPair);
return hex(sig.encodedBytes().toArray());
}
String signature = signTransaction("[YOUR_TXID]", privKeyStr);
// 475F30E3BC3CAD690ABCD55480D81FA7423001D2A1ED9463D81BF65BE4A2F8563217026ADA12AE8F5225B9D3763CCDBCDD0D1352EB658831E174F8ADF5DA127B00
Отсылаем транзакцию в сеть по документации.
POST https://api.trongrid.io/wallet/broadcasttransaction
{
// Полностью копируем транзакцию из предыдущего ответа
"signature":["[YOUR_SIGNATURE]"] // и добавляем сигнатуру
}
Проверяем транзакцию через https://tronscan.org/
P.S. Так как я очень не люблю использовать зависимости в проекте, я постараюсь выделить подпись транзакции в маленький понятный код без использования Tronj.
Комментарии (3)
dmitryvolochaev
11.10.2022 18:37+2С технической стороны очень интересно. Разобрали отправку транзакции. Хотелось бы еще узнать, как проверять, пришел ли платеж вам.
Но вот по политико-экономической части есть замечания.
рядом с Mastercard/Visa появятся такие пункты, как USDT, USDC, BUSD
Вы новости читаете? ЦБ собирается запретить крипту, а в Европе запретят крипту для нас. Переводы между некастодиальными кошельками останутся, да.
не управляются одной компанией
USDT и BUSD управляются разными компаниями. Но и Tether, и Binance могут как банить отдельные кошельки, так и полностью останавливать блокчейн на время рыночного хаоса.
Самый быстрый способ это сделать-через bestchange.ru.
То, что быстрый, не спорю. А вы курс видели? Может, стоит рассмотреть p2p-обмен?
Делаем запрос
Запрос к какому-то сайту, от которого и зависит, попадет ли транзакция в блокчейн. Секретный ключ мы этому сайту не доверяем. Это уже хорошо. Но полноценный web3 - это когда у тебя на компе свой узел p2p-сети, который синхронизирует блокчейн и отправляет транзакции в сеть.
mapcuk
11.10.2022 22:01Не уверен, что Tether остановит, например Ethereum. А Binance прям недавно смогла
Биржа Binance попросила валидаторов остановить производство блоков в сети Binance Smart Chain, после того как хакеры воспользовались уязвимостью в межсетевом мосте BSC Token Hub и вывели активов на $586 млн.
beatleboy
Для безопасности советую не вводить свои сид фразы, приватники на сторонние веб-сервисы.
Все это может утечь и попасть к злоумышленникам в руки. Как итог лишитесь денег.