Skip to content

Commit db9bc3a

Browse files
fix(ripple): Add support for non-standard currency code (40 symbols)
1 parent 455e985 commit db9bc3a

File tree

3 files changed

+47
-15
lines changed

3 files changed

+47
-15
lines changed

src/XRP/Transaction.cpp

+22-12
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Data Transaction::serialize() const {
8585
(transaction_type == TransactionType::NFTokenCreateOffer)) {
8686
encodeType(FieldType::amount, 1, data);
8787
append(data,
88-
(currency_amount.currency.size() > 0) ?
88+
(!currency_amount.currency.empty()) ?
8989
serializeCurrencyAmount(currency_amount) :
9090
serializeAmount(amount));
9191
} else if (transaction_type == TransactionType::TrustSet) {
@@ -257,17 +257,7 @@ Data Transaction::serializeCurrencyAmount(const CurrencyAmount& currency_amount)
257257
// https://xrpl.org/serialization.html#amount-fields
258258
auto data = Data();
259259
encode64BE(amount_cast.value, data);
260-
261-
// ISO-4217 currency code
262-
encodeZeros(1, data); // type code (0x00)
263-
encodeZeros(11, data); // reserved
264-
if (currency_amount.currency.size() == 3) {
265-
data.insert(data.end(), currency_amount.currency.begin(), currency_amount.currency.end());
266-
} else {
267-
encodeZeros(3, data); // none
268-
}
269-
270-
encodeZeros(5, data); // reserved
260+
serializeCurrencyCode(data, currency_amount.currency);
271261
data.insert(data.end(), currency_amount.issuer.begin(), currency_amount.issuer.end());
272262
return data;
273263
}
@@ -278,4 +268,24 @@ Data Transaction::serializeAddress(Address address) {
278268
return data;
279269
}
280270

271+
void Transaction::serializeCurrencyCode(Data& out, const std::string& currency_code) {
272+
if (currency_code.size() == 40) {
273+
auto code_bytes = parse_hex(currency_code);
274+
out.insert(out.end(), code_bytes.begin(), code_bytes.end());
275+
return;
276+
}
277+
278+
// Standard ISO-4217 currency code
279+
encodeZeros(1, out); // type code (0x00)
280+
encodeZeros(11, out); // reserved
281+
282+
if (currency_code.size() == 3) {
283+
out.insert(out.end(), currency_code.begin(), currency_code.end());
284+
} else {
285+
encodeZeros(3, out); // none
286+
}
287+
288+
encodeZeros(5, out); // reserved
289+
}
290+
281291
} // namespace TW::Ripple

src/XRP/Transaction.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Transaction {
4747
/// See https://github.com/trezor/trezor-core/tree/master/src/apps/ripple#transactions
4848
public:
4949
struct CurrencyAmount {
50-
Data currency;
50+
std::string currency;
5151
Data value;
5252
Data issuer;
5353
};
@@ -182,10 +182,11 @@ class Transaction {
182182
static Data serializeAmount(int64_t amount);
183183
static Data serializeCurrencyAmount(const CurrencyAmount& currency_amount);
184184
static Data serializeAddress(Address address);
185+
static void serializeCurrencyCode(Data& out, const std::string& currency_code);
185186

186187
private:
187-
void setCurrencyAmount(CurrencyAmount& p_currency_amount, const std::string& currency, const std::string& value, const std::string& issuer) {
188-
p_currency_amount.currency = Data(currency.begin(), currency.end());
188+
void setCurrencyAmount(CurrencyAmount& p_currency_amount, const std::string& p_currency, const std::string& value, const std::string& issuer) {
189+
p_currency_amount.currency = p_currency;
189190
p_currency_amount.value = Data(value.begin(), value.end());
190191
setAccount(issuer, p_currency_amount.issuer);
191192
}

tests/chains/XRP/TWAnySignerTests.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,27 @@ TEST(TWAnySignerRipple, SignTrustSetPayment) {
8080
EXPECT_EQ(hex(output.encoded()), "12001422000000002401ec60b9201b01ec60ce63d4c38d7ea4c6800000000000000000000000000055534400000000004b4e9c06f24296074f7bc48f92a97916c6dc5ea968400000000000000a732103dc4a0dae2d550de7cace9c26c1a331a114e3e7efee5577204b476d27e2dc683a7446304402206ebcc7a689845df373dd2566cd3789862d426d9ad4e6a09c2d2772b57e82696a022066b1f217a0f0d834d167613a313f74097423a9ccd11f1ae7f90ffab0d2fc26b58114308ea8e515b64f2e6616a33b42e1bbb9fa00bbd2");
8181
}
8282

83+
TEST(TWAnySignerRipple, SignTrustSetPaymentNonStandardCurrencyCode) {
84+
// https://livenet.xrpl.org/transactions/31ABD41ECAD459BCD008DBA4377047413AEE7A965517DB240016B66A3F4A97E1
85+
auto key = parse_hex("574e99f7946cfa2a6ca9368ca72fd37e42583cddb9ecc746aa4cb194ef4b2480");
86+
Proto::SigningInput input;
87+
88+
input.mutable_op_trust_set()->mutable_limit_amount()->set_currency("524C555344000000000000000000000000000000");
89+
input.mutable_op_trust_set()->mutable_limit_amount()->set_value("1000000000");
90+
input.mutable_op_trust_set()->mutable_limit_amount()->set_issuer("rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De");
91+
input.set_fee(500);
92+
input.set_sequence(93674950);
93+
input.set_last_ledger_sequence(187349950);
94+
input.set_account("rDgEGKXWkHHr1HYq2ETnNAs9MdV4R8Gyt");
95+
input.set_private_key(key.data(), key.size());
96+
97+
Proto::SigningOutput output;
98+
ANY_SIGN(input, TWCoinTypeXRP);
99+
100+
EXPECT_EQ(hex(output.encoded()), "12001422000000002405955dc6201b0b2abbbe63d6c38d7ea4c68000524c555344000000000000000000000000000000e5e961c6a025c9404aa7b662dd1df975be75d13e6840000000000001f47321039c77e9329017ced5f8673ebafcd29687a1fff181140c030062fa77865688fc5d74473045022100aa5f7ffc2e11008a3fe98173c66360937cd3a72cb0951aa1b46ba32675c36b2d02206bc02de3a609e5c4b9e1510a6431a7d7efc0fba4ab9586d6595b86047e46bac281140265c09d122fab2a261a80ee59f1f4cd8fba8cf8");
101+
}
102+
103+
83104
TEST(TWAnySignerRipple, SignTokenPayment0) {
84105
// https://testnet.xrpl.org/transactions/8F7820892294598B58CFA2E1101D15ED98C179B25A2BA6DAEB4F5B727CB00D4E
85106
auto key = parse_hex("4ba5fd2ebf0f5d7e579b3c354c263ebb39cda4093845125786a280301af14e21");

0 commit comments

Comments
 (0)