Skip to content

Commit

Permalink
[TON]: Support TON mintless jettons (#4041)
Browse files Browse the repository at this point in the history
* Support TON mintless jettons

* Only adjust comments

* Adjust TheOpenNetwork.proto

---------

Co-authored-by: Sztergbaum Roman <[email protected]>
  • Loading branch information
10gic and Milerius authored Oct 4, 2024
1 parent b4221b4 commit 26aa428
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,14 @@ class TestTheOpenNetworkSigner {
// "This transaction deploys Doge Chatbot contract"
val commentPayload = "te6cckEBAQEANAAAZAAAAABUaGlzIHRyYW5zYWN0aW9uIGRlcGxveXMgRG9nZSBDaGF0Ym90IGNvbnRyYWN0v84vSg=="

val customPayload = TheOpenNetwork.CustomPayload.newBuilder()
.setStateInit(dogeChatbotStateInit)
.setPayload(commentPayload)
.build()

val transfer = TheOpenNetwork.Transfer.newBuilder()
.setDest(dogeChatbotDeployingAddress)
// 0.069 TON
.setAmount(69_000_000)
.setMode(TheOpenNetwork.SendMode.PAY_FEES_SEPARATELY_VALUE or TheOpenNetwork.SendMode.IGNORE_ACTION_PHASE_ERRORS_VALUE)
.setBounceable(false)
.setCustomPayload(customPayload)
.setStateInit(dogeChatbotStateInit)
.setCustomPayload(commentPayload)

val input = TheOpenNetwork.SigningInput.newBuilder()
.setPrivateKey(ByteString.copyFrom(privateKey.data()))
Expand Down
7 changes: 5 additions & 2 deletions rust/chains/tw_ton/src/message/payload/jetton_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ pub struct JettonTransferPayload {
/// Address where to send a response with confirmation of a successful transfer and the rest of the incoming message Toncoins.
response_destination: TonAddress,
/// Optional custom data (which is used by either sender or receiver jetton wallet for inner logic).
/// At WalletCore, we do not use `custom_payload` at the moment.
#[allow(dead_code)]
custom_payload: Option<CellArc>,
/// Amount of nanotons to be sent to the destination address.
forward_ton_amount: U256,
Expand Down Expand Up @@ -65,6 +63,11 @@ impl JettonTransferPayload {
self
}

pub fn with_custom_payload(&mut self, custom_payload: Option<CellArc>) -> &mut Self {
self.custom_payload = custom_payload;
self
}

pub fn with_forward_ton_amount(&mut self, forward_ton_amount: U256) -> &mut Self {
self.forward_ton_amount = forward_ton_amount;
self
Expand Down
35 changes: 17 additions & 18 deletions rust/chains/tw_ton/src/signing_request/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use crate::address::TonAddress;
use crate::signing_request::{
JettonTransferRequest, SigningRequest, TransferCustomRequest, TransferPayload, TransferRequest,
JettonTransferRequest, SigningRequest, TransferPayload, TransferRequest,
};
use crate::wallet::{wallet_v4, wallet_v5, VersionedTonWallet};
use std::str::FromStr;
Expand Down Expand Up @@ -98,6 +98,12 @@ impl SigningRequestBuilder {
Some(input.comment.to_string())
};

let state_init = if input.state_init.is_empty() {
None
} else {
Some(input.state_init.to_string())
};

let mode = u8::try_from(input.mode)
.tw_err(|_| SigningErrorType::Error_invalid_params)
.context("'mode' must fit uint8")?;
Expand All @@ -115,6 +121,7 @@ impl SigningRequestBuilder {
ton_amount: U256::from(input.amount),
mode,
comment,
state_init,
payload,
})
}
Expand All @@ -128,33 +135,25 @@ impl SigningRequestBuilder {
.into_tw()
.context("Invalid 'response_address' address")?;

let custom_payload = if input.custom_payload.is_empty() {
None
} else {
Some(input.custom_payload.to_string())
};

let jetton_payload = JettonTransferRequest {
query_id: input.query_id,
jetton_amount: U256::from(input.jetton_amount),
dest,
response_address,
custom_payload,
forward_ton_amount: U256::from(input.forward_amount),
};

Ok(TransferPayload::JettonTransfer(jetton_payload))
}

fn custom_request(input: &Proto::CustomPayload) -> SigningResult<TransferPayload> {
let state_init = if input.state_init.is_empty() {
None
} else {
Some(input.state_init.to_string())
};

let payload = if input.payload.is_empty() {
None
} else {
Some(input.payload.to_string())
};

Ok(TransferPayload::Custom(TransferCustomRequest {
state_init,
payload,
}))
fn custom_request(input: &str) -> SigningResult<TransferPayload> {
Ok(TransferPayload::Custom(input.to_string()))
}
}
40 changes: 21 additions & 19 deletions rust/chains/tw_ton/src/signing_request/cell_creator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::message::payload::comment::CommentPayload;
use crate::message::payload::empty::EmptyPayload;
use crate::message::payload::jetton_transfer::JettonTransferPayload;
use crate::signing_request::{
JettonTransferRequest, SigningRequest, TransferCustomRequest, TransferPayload, TransferRequest,
JettonTransferRequest, SigningRequest, TransferPayload, TransferRequest,
};
use std::sync::Arc;
use tw_coin_entry::error::prelude::ResultContext;
Expand Down Expand Up @@ -71,10 +71,23 @@ impl InternalMessageCreator {
jetton: &JettonTransferRequest,
comment: Option<String>,
) -> CellResult<CellArc> {
let custom_payload_cell = if let Some(ref custom_payload) = jetton.custom_payload {
Some(
BagOfCells::parse_base64(custom_payload)
.context("Error parsing JettonTransfer custom_payload")?
.single_root()
.map(Arc::clone)
.context("custom_payload must contain only one single root")?,
)
} else {
None
};

let mut payload = JettonTransferPayload::new(jetton.dest.clone(), jetton.jetton_amount);
payload
.with_query_id(jetton.query_id)
.with_response_destination(jetton.response_address.clone())
.with_custom_payload(custom_payload_cell)
.with_forward_ton_amount(jetton.forward_ton_amount);

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

fn custom_payload(custom: &TransferCustomRequest) -> CellResult<CellArc> {
match custom.payload {
Some(ref payload) => BagOfCells::parse_base64(payload)
.context("Error parsing custom Transfer payload")?
.single_root()
.map(Arc::clone)
.context("Custom Transfer payload must contain only one single root"),
// Create an empty Cell payload.
None => EmptyPayload
.build()
.map(Cell::into_arc)
.context("Error generating Transfer's empty payload"),
}
fn custom_payload(payload: &str) -> CellResult<CellArc> {
BagOfCells::parse_base64(payload)
.context("Error parsing custom Transfer payload")?
.single_root()
.map(Arc::clone)
.context("Custom Transfer payload must contain only one single root")
}

fn maybe_custom_state_init(request: &TransferRequest) -> CellResult<Option<CellArc>> {
let Some(TransferPayload::Custom(ref custom)) = request.payload else {
return Ok(None);
};

let Some(ref state_init) = custom.state_init else {
let Some(ref state_init) = request.state_init else {
return Ok(None);
};

Expand Down
14 changes: 5 additions & 9 deletions rust/chains/tw_ton/src/signing_request/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub enum TransferPayload {
/// Jetton Transfer message payload.
JettonTransfer(JettonTransferRequest),
/// Custom Transfer message payload.
Custom(TransferCustomRequest),
Custom(String),
}

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

pub struct TransferCustomRequest {
/// (string base64, optional): raw one-cell BoC encoded in Base64.
/// Can be used to deploy a smart contract.
pub state_init: Option<String>,
/// (string base64, optional): raw one-cell BoC encoded in Base64.
pub payload: Option<String>,
}

pub struct SigningRequest {
/// Wallet initialized with the user's key-pair or public key.
pub wallet: VersionedTonWallet,
Expand Down
15 changes: 7 additions & 8 deletions rust/tw_tests/tests/chains/ton/ton_sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ fn test_ton_sign_transfer_jettons() {
// Send unused toncoins back to sender.
response_address: "EQBaKIMq5Am2p_rfR1IFTwsNWHxBkOpLTmwUain5Fj4llTXk".into(),
forward_amount: 1,
..Proto::JettonTransfer::default()
};

let transfer = Proto::Transfer {
Expand Down Expand Up @@ -348,6 +349,7 @@ fn test_ton_sign_transfer_jettons_with_comment() {
// Send unused toncoins back to sender.
response_address: "EQBaKIMq5Am2p_rfR1IFTwsNWHxBkOpLTmwUain5Fj4llTXk".into(),
forward_amount: 1,
..Proto::JettonTransfer::default()
};

let transfer = Proto::Transfer {
Expand Down Expand Up @@ -394,10 +396,7 @@ fn test_ton_sign_transfer_custom_payload() {
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
bounceable: true,
payload: PayloadType::custom_payload(Proto::CustomPayload {
state_init: "".into(),
payload: comment_cell("Hi there sir").into(),
}),
payload: PayloadType::custom_payload(comment_cell("Hi there sir").into()),
..Proto::Transfer::default()
};

Expand Down Expand Up @@ -448,10 +447,10 @@ fn test_ton_sign_transfer_custom_payload_with_state_init() {
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
bounceable: false,
payload: PayloadType::custom_payload(Proto::CustomPayload {
state_init: doge_state_init.into(),
payload: comment_cell("This transaction deploys Doge Chatbot contract").into(),
}),
state_init: doge_state_init.into(),
payload: PayloadType::custom_payload(
comment_cell("This transaction deploys Doge Chatbot contract").into(),
),
..Proto::Transfer::default()
};

Expand Down
62 changes: 54 additions & 8 deletions rust/tw_tests/tests/chains/ton/ton_sign_wallet_v5r1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ fn test_ton_sign_wallet_v5r1_transfer_jettons() {
// Send unused toncoins back to sender.
response_address: "UQCh41gQP1A4I0lnAn6yAfitDAIYpXG6UFIXqeSz1TVxNOJ_".into(),
forward_amount: 1,
..Default::default()
};

let transfer = Proto::Transfer {
Expand Down Expand Up @@ -277,6 +278,7 @@ fn test_ton_sign_wallet_v5r1_transfer_jettons_with_comment() {
// Send unused toncoins back to sender.
response_address: "UQCh41gQP1A4I0lnAn6yAfitDAIYpXG6UFIXqeSz1TVxNOJ_".into(),
forward_amount: 1,
..Default::default()
};

let transfer = Proto::Transfer {
Expand Down Expand Up @@ -323,10 +325,7 @@ fn test_ton_sign_wallet_v5r1_transfer_custom_payload() {
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
bounceable: true,
payload: PayloadType::custom_payload(Proto::CustomPayload {
state_init: "".into(),
payload: comment_cell("Hi there sir").into(),
}),
payload: PayloadType::custom_payload(comment_cell("Hi there sir").into()),
..Proto::Transfer::default()
};

Expand Down Expand Up @@ -377,10 +376,10 @@ fn test_ton_sign_wallet_v5r1_transfer_custom_payload_with_state_init() {
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
bounceable: false,
payload: PayloadType::custom_payload(Proto::CustomPayload {
state_init: doge_state_init.into(),
payload: comment_cell("This transaction deploys Doge Chatbot contract").into(),
}),
state_init: doge_state_init.into(),
payload: PayloadType::custom_payload(
comment_cell("This transaction deploys Doge Chatbot contract").into(),
),
..Proto::Transfer::default()
};

Expand Down Expand Up @@ -432,3 +431,50 @@ fn test_ton_sign_wallet_v5r1_missing_required_send_mode() {

assert_eq!(output.error, SigningError::Error_internal);
}

#[test]
fn test_ton_sign_wallet_v5r1_mintless_jetton() {
let private_key = "502d60b0f3327382e7d0585b789f1db9aa04907fe5cddc5c28818ec163ebf4ba";

let jetton_transfer = Proto::JettonTransfer {
query_id: 1,
// Transfer 0 mintless jetton to self.
jetton_amount: 0,
to_owner: "UQCh41gQP1A4I0lnAn6yAfitDAIYpXG6UFIXqeSz1TVxNOJ_".into(),
// Send unused toncoins back to sender.
response_address: "UQCh41gQP1A4I0lnAn6yAfitDAIYpXG6UFIXqeSz1TVxNOJ_".into(),
forward_amount: 1,
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()
};

let transfer = Proto::Transfer {
dest: "UQCn2lssMz09Gn60mBnv544DgiqIX3mK5cqGEPEPKxCNbE0E".into(), // jetton wallet address
amount: 90 * 1000 * 1000, // 0.09 TON as fee
mode: Proto::SendMode::PAY_FEES_SEPARATELY as u32
| Proto::SendMode::IGNORE_ACTION_PHASE_ERRORS as u32,
bounceable: true,
state_init: "te6ccgEBAwEAjwACATQBAghCAg7xnhv0Dyukkvyqw4buylm/aCejhQcI2fzZrbaDq8M2AMoAgBQ8awIH6gcEaSzgT9ZAPxWhgEMUrjdKCkL1PJZ6pq4mkAPpn0MdzkzH7w8jwjgGMZfR3Y2FqlpEArXYKCy3B42gyr7UVZcLiyz/C8M4XAyTZtUz3sBQRappSGHre5Z9DbqcAg==".into(),
payload: PayloadType::jetton_transfer(jetton_transfer),
..Proto::Transfer::default()
};

let input = Proto::SigningInput {
private_key: private_key.decode_hex().unwrap().into(),
messages: vec![transfer],
sequence_number: 7,
expire_at: 1727346541,
wallet_version: Proto::WalletVersion::WALLET_V5_R1,
..Proto::SigningInput::default()
};

let mut signer = AnySignerHelper::<Proto::SigningOutput>::default();
let output = signer.sign(CoinType::TON, input);

assert_eq!(output.error, SigningError::OK, "{}", output.error_message);
// Successfully broadcasted: https://tonviewer.com/transaction/70f347338b3e0d33feb285a0cc7300d216b6011462ed7e76c6395bcca7abc649
assert_eq_boc(&output.encoded, "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");
assert_eq!(
output.hash.to_hex(),
"70f347338b3e0d33feb285a0cc7300d216b6011462ed7e76c6395bcca7abc649"
);
}
21 changes: 10 additions & 11 deletions src/proto/TheOpenNetwork.proto
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ message Transfer {
// If the address is bounceable
bool bounceable = 5;

// Optional raw one-cell BoC encoded in Base64.
// Can be used to deploy a smart contract.
string state_init = 6;

// One of the Transfer message payloads (optional).
oneof payload {
// Jetton transfer payload.
JettonTransfer jetton_transfer = 6;
// TON transfer with custom stateInit and payload (contract call).
CustomPayload custom_payload = 7;
JettonTransfer jetton_transfer = 7;
// TON transfer with custom payload (contract call). Raw one-cell BoC encoded in Base64.
string custom_payload = 8;
}
}

Expand All @@ -67,15 +71,10 @@ message JettonTransfer {

// Amount in nanotons to forward to recipient. Basically minimum amount - 1 nanoton should be used
uint64 forward_amount = 5;
}

message CustomPayload {
// (string base64, optional): raw one-cell BoC encoded in Base64.
// Can be used to deploy a smart contract.
string state_init = 1;

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

message SigningInput {
Expand Down
Loading

0 comments on commit 26aa428

Please sign in to comment.