Skip to content

Commit 3f77d9c

Browse files
Tolsihewigovens
authored andcommitted
Waves tx json serialization (#526)
* added waves tx json serialization * review fixes * json dump test
1 parent a718618 commit 3f77d9c

File tree

8 files changed

+92
-23
lines changed

8 files changed

+92
-23
lines changed

android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/waves/TestWavesSigner.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,12 @@ class TestWavesTransactionSigner {
2121
val signingInput = Waves.SigningInput.newBuilder()
2222
signingInput.apply {
2323
amount = 100_000_000
24-
amountAsset = "DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq"
24+
asset = "DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq"
2525
fee = 100_000
2626
feeAsset = "DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq"
2727
to = "3PPCZQkvdMJpmx7Zrz1cnYsPe9Bt1XT2Ckx"
2828
attachment = ByteString.copyFrom("68656c6c6f".toHexByteArray())
2929
timestamp = 1559146613
30-
publicKey = ByteString.copyFrom("794e8429ddf58353eacab99b4c2b3b71c8c1b5927980db2d6f8db52744dd103d".toHexByteArray())
3130
privateKey = ByteString.copyFrom("68b7a9adb4a655b205f43dac413803785921e22cd7c4d05857b203a62621075f".toHexByteArray())
3231
}
3332

js/tests/blockchain/waves/WavesSigner.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ describe('WavesSigner', () => {
1111
it('test Waves transaction signing', () => {
1212
const signingInput = TW.Waves.Proto.SigningInput.create({
1313
amount: Long.fromString('100000000'),
14-
amountAsset: 'DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq',
14+
asset: 'DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq',
1515
attachment: fromHexString('68656c6c6f'),
1616
fee: Long.fromString('100000'),
1717
feeAsset: 'DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq',
1818
privateKey: fromHexString('68b7a9adb4a655b205f43dac413803785921e22cd7c4d05857b203a62621075f'),
19-
publicKey: fromHexString('794e8429ddf58353eacab99b4c2b3b71c8c1b5927980db2d6f8db52744dd103d'),
2019
timestamp: Long.fromString('1559146613'),
2120
to: '3PPCZQkvdMJpmx7Zrz1cnYsPe9Bt1XT2Ckx',
2221
});

src/Waves/Transaction.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
using namespace TW;
1414
using namespace TW::Waves;
1515

16+
using json = nlohmann::json;
17+
1618
const std::string Transaction::WAVES = "WAVES";
1719

1820
Data Transaction::serializeToSign() const {
@@ -28,11 +30,11 @@ Data Transaction::serializeToSign() const {
2830
data[1] = static_cast<byte>(TransactionVersion::V2);
2931
append(data, pub_key);
3032

31-
if (amount_asset == WAVES) {
33+
if (asset == WAVES) {
3234
data.push_back(static_cast<uint8_t>(0));
3335
} else {
3436
data.push_back(static_cast<uint8_t>(1));
35-
append(data, Base58::bitcoin.decode(amount_asset));
37+
append(data, Base58::bitcoin.decode(asset));
3638
}
3739

3840
if (fee_asset == WAVES) {
@@ -48,4 +50,26 @@ Data Transaction::serializeToSign() const {
4850
append(data, Data(std::begin(to.bytes), std::end(to.bytes)));
4951
encodeDynamicLengthBytes(attachment, data);
5052
return data;
53+
}
54+
55+
json Transaction::buildJson(Data signature) const {
56+
json jsonTx;
57+
58+
jsonTx["type"] = TransactionType::transfer;
59+
jsonTx["version"] = TransactionVersion::V2;
60+
jsonTx["fee"] = fee;
61+
jsonTx["senderPublicKey"] = Base58::bitcoin.encode(pub_key);
62+
jsonTx["timestamp"] = timestamp;
63+
jsonTx["proofs"] = json::array({Base58::bitcoin.encode(signature)}).dump();
64+
jsonTx["recipient"] = Address(to).string();
65+
if (asset != WAVES) {
66+
jsonTx["assetId"] = asset;
67+
}
68+
if (fee_asset != WAVES) {
69+
jsonTx["feeAssetId"] = fee_asset;
70+
}
71+
jsonTx["amount"] = amount;
72+
jsonTx["attachment"] = Base58::bitcoin.encode(attachment);
73+
74+
return jsonTx;
5175
}

src/Waves/Transaction.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "Address.h"
1010
#include "../Data.h"
1111
#include "../proto/Waves.pb.h"
12+
#include <nlohmann/json.hpp>
1213

1314
namespace TW::Waves {
1415

@@ -23,26 +24,26 @@ class Transaction {
2324
static const std::string WAVES;
2425

2526
int64_t amount;
26-
std::string amount_asset;
27+
std::string asset;
2728
int64_t fee;
2829
std::string fee_asset;
2930
Address to;
3031
Data attachment;
3132
int64_t timestamp;
3233
Data pub_key;
3334

34-
Transaction(int64_t amount, std::string amount_asset, int64_t fee, std::string fee_asset,
35+
Transaction(int64_t amount, std::string asset, int64_t fee, std::string fee_asset,
3536
Address to, Data attachment, int64_t timestamp, Data pub_key)
3637
: amount(std::move(amount))
3738
, fee(std::move(fee))
3839
, to(std::move(to))
3940
, attachment(std::move(attachment))
4041
, timestamp(std::move(timestamp))
4142
, pub_key(std::move(pub_key)) {
42-
if (amount_asset.empty()) {
43-
amount_asset = WAVES;
43+
if (asset.empty()) {
44+
asset = WAVES;
4445
}
45-
this->amount_asset = amount_asset;
46+
this->asset = asset;
4647
if (fee_asset.empty()) {
4748
fee_asset = WAVES;
4849
}
@@ -51,6 +52,7 @@ class Transaction {
5152

5253
public:
5354
Data serializeToSign() const;
55+
nlohmann::json buildJson(Data signature) const;
5456
};
5557

5658
} // namespace TW::Waves

src/interface/TWWavesSigner.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <TrustWalletCore/TWWavesSigner.h>
88

9+
#include "../Base58.h"
910
#include "../Waves/Signer.h"
1011
#include "../proto/Waves.pb.h"
1112

@@ -16,21 +17,23 @@ TW_Waves_Proto_SigningOutput TWWavesSignerSign(TW_Waves_Proto_SigningInput data)
1617
Proto::SigningInput input;
1718
input.ParseFromArray(TWDataBytes(data), static_cast<int>(TWDataSize(data)));
1819

19-
auto key = PrivateKey(Data(input.private_key().begin(), input.private_key().end()));
20+
auto privateKey = PrivateKey(Data(input.private_key().begin(), input.private_key().end()));
21+
auto publicKey = privateKey.getPublicKey(TWPublicKeyTypeCURVE25519);
2022
auto transaction = Transaction(
2123
/* amount */ input.amount(),
22-
/* amount_asset */ input.amount_asset(),
24+
/* asset */ input.asset(),
2325
/* fee */ input.fee(),
2426
/* fee_asset */ input.fee_asset(),
2527
/* to */ Address(input.to()),
2628
/* attachment */ Data(input.attachment().begin(), input.attachment().end()),
2729
/* timestamp */ input.timestamp(),
28-
/* pub_key */ Data(input.public_key().begin(), input.public_key().end()));
30+
/* pub_key */ publicKey.bytes);
2931

30-
Data signature = Signer::sign(key, transaction);
32+
Data signature = Signer::sign(privateKey, transaction);
3133

3234
Proto::SigningOutput protoOutput = Proto::SigningOutput();
3335
protoOutput.set_signature(reinterpret_cast<const char *>(signature.data()), signature.size());
36+
protoOutput.set_json(transaction.buildJson(signature).dump());
3437
std::string serialized = protoOutput.SerializeAsString();
3538
return TWDataCreateWithBytes(reinterpret_cast<const uint8_t *>(serialized.data()),
3639
serialized.size());

src/proto/Waves.proto

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ option java_package = "wallet.core.jni.proto";
77
message SigningInput {
88
int64 amount = 1;
99

10-
string amount_asset = 2;
10+
string asset = 2;
1111

12+
// minimum 0.001 Waves (100000 Wavelets) for now
1213
int64 fee = 3;
1314

1415
string fee_asset = 4;
@@ -18,14 +19,14 @@ message SigningInput {
1819
// any 140 bytes payload, will be displayed to the client as utf-8 string
1920
bytes attachment = 6;
2021

22+
// in millis
2123
int64 timestamp = 7;
2224

23-
bytes public_key = 8;
24-
25-
bytes private_key = 9;
25+
bytes private_key = 8;
2626
}
2727

2828
// Transaction signing output.
2929
message SigningOutput {
3030
bytes signature = 1;
31+
string json = 2;
3132
}

tests/Waves/TransactionTests.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
#include "Waves/Address.h"
1111
#include "Waves/Transaction.h"
1212

13+
#include <Waves/Signer.h>
1314
#include <gtest/gtest.h>
1415

16+
using json = nlohmann::json;
17+
1518
using namespace std;
1619
using namespace TW;
1720
using namespace TW::Waves;
@@ -67,4 +70,43 @@ TEST(WavesTransaction, failedSerialize) {
6770
/* pub_key */
6871
parse_hex("d528aabec35ca100d87c7b7a128632faf19cd44531819457445113a32a21ef22"));
6972
EXPECT_THROW(tx1.serializeToSign(), invalid_argument);
73+
}
74+
75+
TEST(WavesTransaction, jsonSerialize) {
76+
const auto privateKey =
77+
PrivateKey(parse_hex("9864a747e1b97f131fabb6b447296c9b6f0201e79fb3c5356e6c77e89b6a806a"));
78+
const auto publicKeyCurve25519 = privateKey.getPublicKey(TWPublicKeyTypeCURVE25519);
79+
ASSERT_EQ(hex(Data(publicKeyCurve25519.bytes.begin(), publicKeyCurve25519.bytes.end())),
80+
"559a50cb45a9a8e8d4f83295c354725990164d10bb505275d1a3086c08fb935d");
81+
// 3P2uzAzX9XTu1t32GkWw68YFFLwtapWvDds
82+
const auto address = Address(publicKeyCurve25519);
83+
84+
auto tx1 = Transaction(
85+
/* amount */ 10000000,
86+
/* amount asset */ "DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq",
87+
/* fee */ 100000000,
88+
/* fee asset*/ "DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD82zq",
89+
/* to */ address,
90+
/* attachment */ parse_hex("66616c6166656c"),
91+
/* timestamp */ 1526641218066,
92+
/* pub_key */
93+
parse_hex("559a50cb45a9a8e8d4f83295c354725990164d10bb505275d1a3086c08fb935d"));
94+
95+
auto signature = Signer::sign(privateKey, tx1);
96+
97+
auto json = tx1.buildJson(signature);
98+
99+
ASSERT_EQ(json["type"], TransactionType::transfer);
100+
ASSERT_EQ(json["version"], TransactionVersion::V2);
101+
ASSERT_EQ(json["fee"], 100000000);
102+
ASSERT_EQ(json["senderPublicKey"], "6mA8eQjie53kd4jbZrwL3ZhMBqCX6nzit1k55tR2X7zU");
103+
ASSERT_EQ(json["timestamp"], 1526641218066);
104+
ASSERT_EQ(json["proofs"], "[\"5ynN2NUiFHkQzw9bK8R7dZcNfTWMAtcWRJsrMvFFM6dUT3fSnPCCX7CTajNU8bJCB"
105+
"H69vU1mnwfx4zpDtF1SkzKg\"]");
106+
ASSERT_EQ(json["recipient"], "3P2uzAzX9XTu1t32GkWw68YFFLwtapWvDds");
107+
ASSERT_EQ(json["assetId"], "DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq");
108+
ASSERT_EQ(json["feeAssetId"], "DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD82zq");
109+
ASSERT_EQ(json["amount"], 10000000);
110+
ASSERT_EQ(json["attachment"], "4t2Xazb2SX");
111+
ASSERT_EQ(json.dump(), "{\"amount\":10000000,\"assetId\":\"DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq\",\"attachment\":\"4t2Xazb2SX\",\"fee\":100000000,\"feeAssetId\":\"DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD82zq\",\"proofs\":\"[\\\"5ynN2NUiFHkQzw9bK8R7dZcNfTWMAtcWRJsrMvFFM6dUT3fSnPCCX7CTajNU8bJCBH69vU1mnwfx4zpDtF1SkzKg\\\"]\",\"recipient\":\"3P2uzAzX9XTu1t32GkWw68YFFLwtapWvDds\",\"senderPublicKey\":\"6mA8eQjie53kd4jbZrwL3ZhMBqCX6nzit1k55tR2X7zU\",\"timestamp\":1526641218066,\"type\":4,\"version\":2}");
70112
}

tests/interface/TWWavesSignerTests.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,13 @@ TEST(TWWavesSigner, Sign) {
2727
const auto publicKeyCurve25519 = privateKey.getPublicKey(TWPublicKeyTypeCURVE25519);
2828

2929
input.set_amount(int64_t(100000000));
30-
input.set_amount_asset("DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq");
30+
input.set_asset("DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq");
3131
input.set_fee(int64_t(100000));
3232
input.set_fee_asset("DacnEpaUVFRCYk8Fcd1F3cqUZuT4XG7qW9mRyoZD81zq");
3333
input.set_to("3PPCZQkvdMJpmx7Zrz1cnYsPe9Bt1XT2Ckx");
3434
input.set_attachment("hello");
3535
input.set_timestamp(int64_t(1559146613));
3636
input.set_private_key(privateKey.bytes.data(), privateKey.bytes.size());
37-
input.set_public_key(publicKeyCurve25519.bytes.data(), publicKeyCurve25519.bytes.size());
3837

3938
auto inputData = input.SerializeAsString();
4039
auto inputTWData = TWDataCreateWithBytes((const byte *)inputData.data(), inputData.size());
@@ -48,13 +47,13 @@ TEST(TWWavesSigner, Sign) {
4847

4948
auto transaction = Waves::Transaction(
5049
/* amount */ input.amount(),
51-
/* amount_asset */ input.amount_asset(),
50+
/* asset */ input.asset(),
5251
/* fee */ input.fee(),
5352
/* fee_asset */ input.fee_asset(),
5453
/* to */ Waves::Address(input.to()),
5554
/* attachment */ Data(input.attachment().begin(), input.attachment().end()),
5655
/* timestamp */ input.timestamp(),
57-
/* pub_key */ Data(input.public_key().begin(), input.public_key().end()));
56+
/* pub_key */ publicKeyCurve25519.bytes);
5857

5958
ASSERT_TRUE(publicKeyCurve25519.verify(
6059
Data(output.signature().begin(), output.signature().end()), transaction.serializeToSign()));

0 commit comments

Comments
 (0)