Skip to content

Commit 26aa428

Browse files
10gicMilerius
andauthored
[TON]: Support TON mintless jettons (#4041)
* Support TON mintless jettons * Only adjust comments * Adjust TheOpenNetwork.proto --------- Co-authored-by: Sztergbaum Roman <rmscastle@gmail.com>
1 parent b4221b4 commit 26aa428

File tree

9 files changed

+123
-87
lines changed

9 files changed

+123
-87
lines changed

android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/theopennetwork/TestTheOpenNetworkSigner.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,14 @@ class TestTheOpenNetworkSigner {
9797
// "This transaction deploys Doge Chatbot contract"
9898
val commentPayload = "te6cckEBAQEANAAAZAAAAABUaGlzIHRyYW5zYWN0aW9uIGRlcGxveXMgRG9nZSBDaGF0Ym90IGNvbnRyYWN0v84vSg=="
9999

100-
val customPayload = TheOpenNetwork.CustomPayload.newBuilder()
101-
.setStateInit(dogeChatbotStateInit)
102-
.setPayload(commentPayload)
103-
.build()
104-
105100
val transfer = TheOpenNetwork.Transfer.newBuilder()
106101
.setDest(dogeChatbotDeployingAddress)
107102
// 0.069 TON
108103
.setAmount(69_000_000)
109104
.setMode(TheOpenNetwork.SendMode.PAY_FEES_SEPARATELY_VALUE or TheOpenNetwork.SendMode.IGNORE_ACTION_PHASE_ERRORS_VALUE)
110105
.setBounceable(false)
111-
.setCustomPayload(customPayload)
106+
.setStateInit(dogeChatbotStateInit)
107+
.setCustomPayload(commentPayload)
112108

113109
val input = TheOpenNetwork.SigningInput.newBuilder()
114110
.setPrivateKey(ByteString.copyFrom(privateKey.data()))

rust/chains/tw_ton/src/message/payload/jetton_transfer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ pub struct JettonTransferPayload {
2323
/// Address where to send a response with confirmation of a successful transfer and the rest of the incoming message Toncoins.
2424
response_destination: TonAddress,
2525
/// Optional custom data (which is used by either sender or receiver jetton wallet for inner logic).
26-
/// At WalletCore, we do not use `custom_payload` at the moment.
27-
#[allow(dead_code)]
2826
custom_payload: Option<CellArc>,
2927
/// Amount of nanotons to be sent to the destination address.
3028
forward_ton_amount: U256,
@@ -65,6 +63,11 @@ impl JettonTransferPayload {
6563
self
6664
}
6765

66+
pub fn with_custom_payload(&mut self, custom_payload: Option<CellArc>) -> &mut Self {
67+
self.custom_payload = custom_payload;
68+
self
69+
}
70+
6871
pub fn with_forward_ton_amount(&mut self, forward_ton_amount: U256) -> &mut Self {
6972
self.forward_ton_amount = forward_ton_amount;
7073
self

rust/chains/tw_ton/src/signing_request/builder.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use crate::address::TonAddress;
66
use crate::signing_request::{
7-
JettonTransferRequest, SigningRequest, TransferCustomRequest, TransferPayload, TransferRequest,
7+
JettonTransferRequest, SigningRequest, TransferPayload, TransferRequest,
88
};
99
use crate::wallet::{wallet_v4, wallet_v5, VersionedTonWallet};
1010
use std::str::FromStr;
@@ -98,6 +98,12 @@ impl SigningRequestBuilder {
9898
Some(input.comment.to_string())
9999
};
100100

101+
let state_init = if input.state_init.is_empty() {
102+
None
103+
} else {
104+
Some(input.state_init.to_string())
105+
};
106+
101107
let mode = u8::try_from(input.mode)
102108
.tw_err(|_| SigningErrorType::Error_invalid_params)
103109
.context("'mode' must fit uint8")?;
@@ -115,6 +121,7 @@ impl SigningRequestBuilder {
115121
ton_amount: U256::from(input.amount),
116122
mode,
117123
comment,
124+
state_init,
118125
payload,
119126
})
120127
}
@@ -128,33 +135,25 @@ impl SigningRequestBuilder {
128135
.into_tw()
129136
.context("Invalid 'response_address' address")?;
130137

138+
let custom_payload = if input.custom_payload.is_empty() {
139+
None
140+
} else {
141+
Some(input.custom_payload.to_string())
142+
};
143+
131144
let jetton_payload = JettonTransferRequest {
132145
query_id: input.query_id,
133146
jetton_amount: U256::from(input.jetton_amount),
134147
dest,
135148
response_address,
149+
custom_payload,
136150
forward_ton_amount: U256::from(input.forward_amount),
137151
};
138152

139153
Ok(TransferPayload::JettonTransfer(jetton_payload))
140154
}
141155

142-
fn custom_request(input: &Proto::CustomPayload) -> SigningResult<TransferPayload> {
143-
let state_init = if input.state_init.is_empty() {
144-
None
145-
} else {
146-
Some(input.state_init.to_string())
147-
};
148-
149-
let payload = if input.payload.is_empty() {
150-
None
151-
} else {
152-
Some(input.payload.to_string())
153-
};
154-
155-
Ok(TransferPayload::Custom(TransferCustomRequest {
156-
state_init,
157-
payload,
158-
}))
156+
fn custom_request(input: &str) -> SigningResult<TransferPayload> {
157+
Ok(TransferPayload::Custom(input.to_string()))
159158
}
160159
}

rust/chains/tw_ton/src/signing_request/cell_creator.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::message::payload::comment::CommentPayload;
88
use crate::message::payload::empty::EmptyPayload;
99
use crate::message::payload::jetton_transfer::JettonTransferPayload;
1010
use crate::signing_request::{
11-
JettonTransferRequest, SigningRequest, TransferCustomRequest, TransferPayload, TransferRequest,
11+
JettonTransferRequest, SigningRequest, TransferPayload, TransferRequest,
1212
};
1313
use std::sync::Arc;
1414
use tw_coin_entry::error::prelude::ResultContext;
@@ -71,10 +71,23 @@ impl InternalMessageCreator {
7171
jetton: &JettonTransferRequest,
7272
comment: Option<String>,
7373
) -> CellResult<CellArc> {
74+
let custom_payload_cell = if let Some(ref custom_payload) = jetton.custom_payload {
75+
Some(
76+
BagOfCells::parse_base64(custom_payload)
77+
.context("Error parsing JettonTransfer custom_payload")?
78+
.single_root()
79+
.map(Arc::clone)
80+
.context("custom_payload must contain only one single root")?,
81+
)
82+
} else {
83+
None
84+
};
85+
7486
let mut payload = JettonTransferPayload::new(jetton.dest.clone(), jetton.jetton_amount);
7587
payload
7688
.with_query_id(jetton.query_id)
7789
.with_response_destination(jetton.response_address.clone())
90+
.with_custom_payload(custom_payload_cell)
7891
.with_forward_ton_amount(jetton.forward_ton_amount);
7992

8093
if let Some(comment) = comment {
@@ -87,27 +100,16 @@ impl InternalMessageCreator {
87100
.context("Error generating Jetton Transfer payload")
88101
}
89102

90-
fn custom_payload(custom: &TransferCustomRequest) -> CellResult<CellArc> {
91-
match custom.payload {
92-
Some(ref payload) => BagOfCells::parse_base64(payload)
93-
.context("Error parsing custom Transfer payload")?
94-
.single_root()
95-
.map(Arc::clone)
96-
.context("Custom Transfer payload must contain only one single root"),
97-
// Create an empty Cell payload.
98-
None => EmptyPayload
99-
.build()
100-
.map(Cell::into_arc)
101-
.context("Error generating Transfer's empty payload"),
102-
}
103+
fn custom_payload(payload: &str) -> CellResult<CellArc> {
104+
BagOfCells::parse_base64(payload)
105+
.context("Error parsing custom Transfer payload")?
106+
.single_root()
107+
.map(Arc::clone)
108+
.context("Custom Transfer payload must contain only one single root")
103109
}
104110

105111
fn maybe_custom_state_init(request: &TransferRequest) -> CellResult<Option<CellArc>> {
106-
let Some(TransferPayload::Custom(ref custom)) = request.payload else {
107-
return Ok(None);
108-
};
109-
110-
let Some(ref state_init) = custom.state_init else {
112+
let Some(ref state_init) = request.state_init else {
111113
return Ok(None);
112114
};
113115

rust/chains/tw_ton/src/signing_request/mod.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub enum TransferPayload {
1313
/// Jetton Transfer message payload.
1414
JettonTransfer(JettonTransferRequest),
1515
/// Custom Transfer message payload.
16-
Custom(TransferCustomRequest),
16+
Custom(String),
1717
}
1818

1919
pub struct TransferRequest {
@@ -27,6 +27,8 @@ pub struct TransferRequest {
2727
pub mode: u8,
2828
/// Transfer comment message.
2929
pub comment: Option<String>,
30+
/// Raw one-cell BoC encoded in Base64. Can be used to deploy a smart contract.
31+
pub state_init: Option<String>,
3032
/// Transfer payload.
3133
pub payload: Option<TransferPayload>,
3234
}
@@ -42,18 +44,12 @@ pub struct JettonTransferRequest {
4244
/// Address where to send a response with confirmation of a successful transfer and the rest of the incoming message Toncoins.
4345
/// Usually the sender should get back their toncoins.
4446
pub response_address: TonAddress,
47+
/// Optional custom payload. Can be used for mintless jetton transfers.
48+
pub custom_payload: Option<String>,
4549
/// Amount in nanotons to forward to recipient. Basically minimum amount - 1 nanoton should be used.
4650
pub forward_ton_amount: U256,
4751
}
4852

49-
pub struct TransferCustomRequest {
50-
/// (string base64, optional): raw one-cell BoC encoded in Base64.
51-
/// Can be used to deploy a smart contract.
52-
pub state_init: Option<String>,
53-
/// (string base64, optional): raw one-cell BoC encoded in Base64.
54-
pub payload: Option<String>,
55-
}
56-
5753
pub struct SigningRequest {
5854
/// Wallet initialized with the user's key-pair or public key.
5955
pub wallet: VersionedTonWallet,

rust/tw_tests/tests/chains/ton/ton_sign.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ fn test_ton_sign_transfer_jettons() {
303303
// Send unused toncoins back to sender.
304304
response_address: "EQBaKIMq5Am2p_rfR1IFTwsNWHxBkOpLTmwUain5Fj4llTXk".into(),
305305
forward_amount: 1,
306+
..Proto::JettonTransfer::default()
306307
};
307308

308309
let transfer = Proto::Transfer {
@@ -348,6 +349,7 @@ fn test_ton_sign_transfer_jettons_with_comment() {
348349
// Send unused toncoins back to sender.
349350
response_address: "EQBaKIMq5Am2p_rfR1IFTwsNWHxBkOpLTmwUain5Fj4llTXk".into(),
350351
forward_amount: 1,
352+
..Proto::JettonTransfer::default()
351353
};
352354

353355
let transfer = Proto::Transfer {
@@ -394,10 +396,7 @@ fn test_ton_sign_transfer_custom_payload() {
394396
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
395397
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
396398
bounceable: true,
397-
payload: PayloadType::custom_payload(Proto::CustomPayload {
398-
state_init: "".into(),
399-
payload: comment_cell("Hi there sir").into(),
400-
}),
399+
payload: PayloadType::custom_payload(comment_cell("Hi there sir").into()),
401400
..Proto::Transfer::default()
402401
};
403402

@@ -448,10 +447,10 @@ fn test_ton_sign_transfer_custom_payload_with_state_init() {
448447
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
449448
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
450449
bounceable: false,
451-
payload: PayloadType::custom_payload(Proto::CustomPayload {
452-
state_init: doge_state_init.into(),
453-
payload: comment_cell("This transaction deploys Doge Chatbot contract").into(),
454-
}),
450+
state_init: doge_state_init.into(),
451+
payload: PayloadType::custom_payload(
452+
comment_cell("This transaction deploys Doge Chatbot contract").into(),
453+
),
455454
..Proto::Transfer::default()
456455
};
457456

rust/tw_tests/tests/chains/ton/ton_sign_wallet_v5r1.rs

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ fn test_ton_sign_wallet_v5r1_transfer_jettons() {
232232
// Send unused toncoins back to sender.
233233
response_address: "UQCh41gQP1A4I0lnAn6yAfitDAIYpXG6UFIXqeSz1TVxNOJ_".into(),
234234
forward_amount: 1,
235+
..Default::default()
235236
};
236237

237238
let transfer = Proto::Transfer {
@@ -277,6 +278,7 @@ fn test_ton_sign_wallet_v5r1_transfer_jettons_with_comment() {
277278
// Send unused toncoins back to sender.
278279
response_address: "UQCh41gQP1A4I0lnAn6yAfitDAIYpXG6UFIXqeSz1TVxNOJ_".into(),
279280
forward_amount: 1,
281+
..Default::default()
280282
};
281283

282284
let transfer = Proto::Transfer {
@@ -323,10 +325,7 @@ fn test_ton_sign_wallet_v5r1_transfer_custom_payload() {
323325
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
324326
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
325327
bounceable: true,
326-
payload: PayloadType::custom_payload(Proto::CustomPayload {
327-
state_init: "".into(),
328-
payload: comment_cell("Hi there sir").into(),
329-
}),
328+
payload: PayloadType::custom_payload(comment_cell("Hi there sir").into()),
330329
..Proto::Transfer::default()
331330
};
332331

@@ -377,10 +376,10 @@ fn test_ton_sign_wallet_v5r1_transfer_custom_payload_with_state_init() {
377376
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
378377
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
379378
bounceable: false,
380-
payload: PayloadType::custom_payload(Proto::CustomPayload {
381-
state_init: doge_state_init.into(),
382-
payload: comment_cell("This transaction deploys Doge Chatbot contract").into(),
383-
}),
379+
state_init: doge_state_init.into(),
380+
payload: PayloadType::custom_payload(
381+
comment_cell("This transaction deploys Doge Chatbot contract").into(),
382+
),
384383
..Proto::Transfer::default()
385384
};
386385

@@ -432,3 +431,50 @@ fn test_ton_sign_wallet_v5r1_missing_required_send_mode() {
432431

433432
assert_eq!(output.error, SigningError::Error_internal);
434433
}
434+
435+
#[test]
436+
fn test_ton_sign_wallet_v5r1_mintless_jetton() {
437+
let private_key = "502d60b0f3327382e7d0585b789f1db9aa04907fe5cddc5c28818ec163ebf4ba";
438+
439+
let jetton_transfer = Proto::JettonTransfer {
440+
query_id: 1,
441+
// Transfer 0 mintless jetton to self.
442+
jetton_amount: 0,
443+
to_owner: "UQCh41gQP1A4I0lnAn6yAfitDAIYpXG6UFIXqeSz1TVxNOJ_".into(),
444+
// Send unused toncoins back to sender.
445+
response_address: "UQCh41gQP1A4I0lnAn6yAfitDAIYpXG6UFIXqeSz1TVxNOJ_".into(),
446+
forward_amount: 1,
447+
custom_payload: "te6ccgECNQEABJMAAQgN9gLWAQlGA6+1FWXC4ss/wvDOFwMk2bVM97AUEWqaUhh63uWfQ26nAB4CIgWBcAIDBChIAQEZG2ZqtEYGAq27TvzHdGuGrhhKoICBU+Zg9Xq/qRMHGAAdIgEgBQYiASAHCChIAQEV0tdPcZG01smq0thhsmqf9ZzE0QqpP3c+ERvuHF1JDgAbKEgBAf3dO8qdKoPys7AWvavs1wMNWCOq5XashXaRopmksx/LABsiASAJCiIBIAsMKEgBAWP0xUs9JBrfQRl1FkF2tIfIDYpwLdf3fXqMi6BqxNtmABoiASANDihIAQFOErI5E7ld/nTAgHXdGI74UH8kxIaFyAkH42P54tEC9QAYIgEgDxAoSAEBrF16Czdlg18FB467CrR6Ucwxb8H+Z1e4qDeFWbkz1WEAFyIBIBESKEgBAXeWzg9xTFO6z0FP+axi8Njuxxp0zPrAUs4vnmt/dE3xABYoSAEBEZ7KazNpaWJoInmqO4II/AfncyhMNWxh6BE2qFU7/9wAFCIBIBMUKEgBAZleZTNXbgCF+8G08kiQeDPanQtNCVakzEU3g9GKB+K2ABQiASAVFihIAQFeCM83J7sm36g24qFeEDvStahHWn6SsEk+Wii49rzBiAASIgEgFxgoSAEBfV9jrgSeiAKVqeeLliXdoLrxFWe2HK0f4SG5h4kfb8YAESIBIBkaIgEgGxwoSAEBImHhXIbOHuOnOgE5f0KLqoXDB7/ZLQQGiHysuulUq2IAECIBIB0eKEgBAXT+qb5w1+qtvbJ1Fbn8y6IhO85YfxKIgKBga6ROO/yQAA8iASAfIChIAQGoJHXWXWRQGZdP9xIUrMowhvgnf+CwKTIIOBxlDiKgcAANKEgBAZ6tCuDr89HFRz3WwwK+wW4XmkE+O7Hf+NgUDI+uqnAJAAwiASAhIihIAQHtasTLBAw7MZHpRTsKyC47E1PZ/LAtF3n2Y2b5ThX0VgALIgEgIyQiASAlJihIAQGumGRf7UXrpK12Cuvj06565IC0Kbd4i2XoG6dnqC+uQAAJKEgBAXM19HUUkz6ns7o/2x45kQ2iLj8gl3zYhrAhISEUg0O1AAgiASAnKCIBICkqKEgBAa7kNA+lev+Z5T/xqKBbO648BvnLL6/hAp1auOiZTWRhAAcoSAEBxn19AKZGAUPYWs8pTpNQrCB4Ap0KfzyjOgB1Mc9PbIUABSIBICssKEgBAWarrCPqSS6+lq6NRcrWZ2/v6bN4b6Zd3GWAtN6j8a6BAAQiASAtLiIBIC8wKEgBAXYYqhLZ1tHg+HdKd8vLmTBsojkj61ZiafXB7pOt+hEFAAMiASAxMihIAQHt8p6qBiXtz+kKcgo13Udyh7Uo8irrdKlSSY2dOdALogAAIgFIMzQoSAEByacrlqsAKiFOlv4Rp4V1gNg2i4aVPkcHJq8Vug/89k4AAABduZA/UDgjSWcCfrIB+K0MAhilcbpQUhep5LPVNXE0Q7msoAAABm4N2AAABm9VrQgoSAEByIAktH0CNxT//QZ8Vgj68CApZON9XBKDfE0D2rY8Fx4AAA==".into()
448+
};
449+
450+
let transfer = Proto::Transfer {
451+
dest: "UQCn2lssMz09Gn60mBnv544DgiqIX3mK5cqGEPEPKxCNbE0E".into(), // jetton wallet address
452+
amount: 90 * 1000 * 1000, // 0.09 TON as fee
453+
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
454+
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
455+
bounceable: true,
456+
state_init: "te6ccgEBAwEAjwACATQBAghCAg7xnhv0Dyukkvyqw4buylm/aCejhQcI2fzZrbaDq8M2AMoAgBQ8awIH6gcEaSzgT9ZAPxWhgEMUrjdKCkL1PJZ6pq4mkAPpn0MdzkzH7w8jwjgGMZfR3Y2FqlpEArXYKCy3B42gyr7UVZcLiyz/C8M4XAyTZtUz3sBQRappSGHre5Z9DbqcAg==".into(),
457+
payload: PayloadType::jetton_transfer(jetton_transfer),
458+
..Proto::Transfer::default()
459+
};
460+
461+
let input = Proto::SigningInput {
462+
private_key: private_key.decode_hex().unwrap().into(),
463+
messages: vec![transfer],
464+
sequence_number: 7,
465+
expire_at: 1727346541,
466+
wallet_version: Proto::WalletVersion::WALLET_V5_R1,
467+
..Proto::SigningInput::default()
468+
};
469+
470+
let mut signer = AnySignerHelper::<Proto::SigningOutput>::default();
471+
let output = signer.sign(CoinType::TON, input);
472+
473+
assert_eq!(output.error, SigningError::OK, "{}", output.error_message);
474+
// Successfully broadcasted: https://tonviewer.com/transaction/70f347338b3e0d33feb285a0cc7300d216b6011462ed7e76c6395bcca7abc649
475+
assert_eq_boc(&output.encoded, "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");
476+
assert_eq!(
477+
output.hash.to_hex(),
478+
"70f347338b3e0d33feb285a0cc7300d216b6011462ed7e76c6395bcca7abc649"
479+
);
480+
}

src/proto/TheOpenNetwork.proto

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,16 @@ message Transfer {
4343
// If the address is bounceable
4444
bool bounceable = 5;
4545

46+
// Optional raw one-cell BoC encoded in Base64.
47+
// Can be used to deploy a smart contract.
48+
string state_init = 6;
49+
4650
// One of the Transfer message payloads (optional).
4751
oneof payload {
4852
// Jetton transfer payload.
49-
JettonTransfer jetton_transfer = 6;
50-
// TON transfer with custom stateInit and payload (contract call).
51-
CustomPayload custom_payload = 7;
53+
JettonTransfer jetton_transfer = 7;
54+
// TON transfer with custom payload (contract call). Raw one-cell BoC encoded in Base64.
55+
string custom_payload = 8;
5256
}
5357
}
5458

@@ -67,15 +71,10 @@ message JettonTransfer {
6771

6872
// Amount in nanotons to forward to recipient. Basically minimum amount - 1 nanoton should be used
6973
uint64 forward_amount = 5;
70-
}
71-
72-
message CustomPayload {
73-
// (string base64, optional): raw one-cell BoC encoded in Base64.
74-
// Can be used to deploy a smart contract.
75-
string state_init = 1;
7674

77-
// (string base64, optional): raw one-cell BoC encoded in Base64.
78-
string payload = 2;
75+
// Optional raw one-cell BoC encoded in Base64.
76+
// Can be used in the case of mintless jetton transfers.
77+
string custom_payload = 6;
7978
}
8079

8180
message SigningInput {

0 commit comments

Comments
 (0)