Skip to content

Commit

Permalink
[TON]: Add TONWallet.buildStateInit function for dapps support (#3970)
Browse files Browse the repository at this point in the history
* feat(ton): Add `tw_ton_wallet_create_v4_r2_state_init` in Rust

* feat(ton): Add `TWTONWalletCreateV4R2StateInit` C FFI

* feat(ton): Rename `TWTONWalletCreateV4R2StateInit` to `TWTONWalletBuildV4R2StateInit` for Swift and Kotlin codegen compat

* Add iOS, Android tests
  • Loading branch information
satoshiotomakan authored Aug 7, 2024
1 parent a21d447 commit 6a31911
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

package com.trustwallet.core.app.blockchains.theopennetwork

import com.trustwallet.core.app.utils.toHexByteArray
import org.junit.Assert.assertEquals
import org.junit.Test
import wallet.core.jni.PublicKey
import wallet.core.jni.PublicKeyType
import wallet.core.jni.TONWallet

class TestTheOpenNetworkWallet {
init {
System.loadLibrary("TrustWalletCore")
}

@Test
fun TheOpenNetworkWalletBuildV4R2StateInit() {
val publicKey = PublicKey("f229a9371fa7c2108b3d90ea22c9be705ff5d0cfeaee9cbb9366ff0171579357".toHexByteArray(), PublicKeyType.ED25519)
val baseWorkchain = 0
val defaultWalletId = 0x29a9a317
val stateInit = TONWallet.buildV4R2StateInit(publicKey, baseWorkchain, defaultWalletId)

val expected = "te6cckECFgEAAwQAAgE0AQIBFP8A9KQT9LzyyAsDAFEAAAAAKamjF/IpqTcfp8IQiz2Q6iLJvnBf9dDP6u6cu5Nm/wFxV5NXQAIBIAQFAgFIBgcE+PKDCNcYINMf0x/THwL4I7vyZO1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8ICQoLAubQAdDTAyFxsJJfBOAi10nBIJJfBOAC0x8hghBwbHVnvSKCEGRzdHK9sJJfBeAD+kAwIPpEAcjKB8v/ydDtRNCBAUDXIfQEMFyBAQj0Cm+hMbOSXwfgBdM/yCWCEHBsdWe6kjgw4w0DghBkc3RyupJfBuMNDA0CASAODwBu0gf6ANTUIvkABcjKBxXL/8nQd3SAGMjLBcsCIs8WUAX6AhTLaxLMzMlz+wDIQBSBAQj0UfKnAgBwgQEI1xj6ANM/yFQgR4EBCPRR8qeCEG5vdGVwdIAYyMsFywJQBs8WUAT6AhTLahLLH8s/yXP7AAIAbIEBCNcY+gDTPzBSJIEBCPRZ8qeCEGRzdHJwdIAYyMsFywJQBc8WUAP6AhPLassfEss/yXP7AAAK9ADJ7VQAeAH6APQEMPgnbyIwUAqhIb7y4FCCEHBsdWeDHrFwgBhQBMsFJs8WWPoCGfQAy2kXyx9SYMs/IMmAQPsABgCKUASBAQj0WTDtRNCBAUDXIMgBzxb0AMntVAFysI4jghBkc3Rygx6xcIAYUAXLBVADzxYj+gITy2rLH8s/yYBA+wCSXwPiAgEgEBEAWb0kK29qJoQICga5D6AhhHDUCAhHpJN9KZEM5pA+n/mDeBKAG3gQFImHFZ8xhAIBWBITABG4yX7UTQ1wsfgAPbKd+1E0IEBQNch9AQwAsjKB8v/ydABgQEI9ApvoTGACASAUFQAZrc52omhAIGuQ64X/wAAZrx32omhAEGuQ64WPwEXtMkg="
assertEquals(stateInit, expected)
}
}
26 changes: 26 additions & 0 deletions include/TrustWalletCore/TWTONWallet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

#pragma once

#include "TWBase.h"
#include "TWPublicKey.h"
#include "TWString.h"

TW_EXTERN_C_BEGIN

/// TON wallet operations.
TW_EXPORT_CLASS
struct TWTONWallet;

/// Constructs a TON Wallet V4R2 stateInit encoded as BoC (BagOfCells) for the given `public_key`.
///
/// \param publicKey wallet's public key.
/// \param workchain TON workchain to which the wallet belongs. Usually, base chain is used (0).
/// \param walletId wallet's ID allows to create multiple wallets for the same private key.
/// \return Pointer to a base64 encoded Bag Of Cells (BoC) StateInit. Null if invalid public key provided.
TW_EXPORT_STATIC_METHOD
TWString *_Nullable TWTONWalletBuildV4R2StateInit(struct TWPublicKey *_Nonnull publicKey, int32_t workchain, int32_t walletId);

TW_EXTERN_C_END
1 change: 1 addition & 0 deletions rust/chains/tw_ton/src/modules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
// Copyright © 2017 Trust Wallet.

pub mod address_converter;
pub mod wallet_provider;
29 changes: 29 additions & 0 deletions rust/chains/tw_ton/src/modules/wallet_provider.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

use crate::wallet::wallet_v4::WalletV4;
use crate::wallet::TonWallet;
use tw_keypair::ed25519::sha512::PublicKey;
use tw_ton_sdk::boc::BagOfCells;
use tw_ton_sdk::error::CellResult;

const HAS_CRC32: bool = true;

/// TON Wallet common functionality.
pub struct WalletProvider;

impl WalletProvider {
/// Constructs a TON Wallet V4R2 stateInit encoded as BoC (BagOfCells) for the given `public_key`.
pub fn v4r2_state_init(
public_key: PublicKey,
workchain: i32,
wallet_id: i32,
) -> CellResult<String> {
let state_init =
TonWallet::with_public_key(workchain, WalletV4::r2()?, public_key, wallet_id)?
.state_init()?
.to_cell()?;
BagOfCells::from_root(state_init).to_base64(HAS_CRC32)
}
}
1 change: 1 addition & 0 deletions rust/wallet_core_rs/src/ffi/ton/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
// Copyright © 2017 Trust Wallet.

pub mod address_converter;
pub mod wallet;
33 changes: 33 additions & 0 deletions rust/wallet_core_rs/src/ffi/ton/wallet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

#![allow(clippy::missing_safety_doc)]

use tw_keypair::ffi::pubkey::TWPublicKey;
use tw_memory::ffi::tw_string::TWString;
use tw_memory::ffi::RawPtrTrait;
use tw_misc::try_or_else;
use tw_ton::modules::wallet_provider::WalletProvider;

/// Constructs a TON Wallet V4R2 stateInit encoded as BoC (BagOfCells) for the given `public_key`.
///
/// \param public_key wallet's public key.
/// \param workchain TON workchain to which the wallet belongs. Usually, base chain is used (0).
/// \param wallet_id wallet's ID allows to create multiple wallets for the same private key.
/// \return Pointer to a base64 encoded Bag Of Cells (BoC) StateInit. Null if invalid public key provided.
#[no_mangle]
pub unsafe extern "C" fn tw_ton_wallet_build_v4_r2_state_init(
public_key: *const TWPublicKey,
workchain: i32,
wallet_id: i32,
) -> *mut TWString {
let public_key = try_or_else!(TWPublicKey::from_ptr_as_ref(public_key), std::ptr::null_mut);
let ed_pubkey = try_or_else!(public_key.as_ref().to_ed25519(), std::ptr::null_mut).clone();

let state_init = try_or_else!(
WalletProvider::v4r2_state_init(ed_pubkey, workchain, wallet_id),
std::ptr::null_mut
);
TWString::from(state_init).into_ptr()
}
21 changes: 21 additions & 0 deletions rust/wallet_core_rs/tests/ton_wallet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

use tw_keypair::test_utils::tw_public_key_helper::TWPublicKeyHelper;
use tw_keypair::tw::PublicKeyType;
use tw_memory::test_utils::tw_string_helper::TWStringHelper;
use wallet_core_rs::ffi::ton::wallet::tw_ton_wallet_build_v4_r2_state_init;

#[test]
fn test_ton_wallet_create_state_init() {
let public_key = TWPublicKeyHelper::with_hex(
"f229a9371fa7c2108b3d90ea22c9be705ff5d0cfeaee9cbb9366ff0171579357",
PublicKeyType::Ed25519,
);
assert!(!public_key.is_null());
let state_init_boc = TWStringHelper::wrap(unsafe {
tw_ton_wallet_build_v4_r2_state_init(public_key.ptr(), 0, 0x29a9a317)
});
assert_eq!(state_init_boc.to_string().unwrap(), "te6cckECFgEAAwQAAgE0AQIBFP8A9KQT9LzyyAsDAFEAAAAAKamjF/IpqTcfp8IQiz2Q6iLJvnBf9dDP6u6cu5Nm/wFxV5NXQAIBIAQFAgFIBgcE+PKDCNcYINMf0x/THwL4I7vyZO1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8ICQoLAubQAdDTAyFxsJJfBOAi10nBIJJfBOAC0x8hghBwbHVnvSKCEGRzdHK9sJJfBeAD+kAwIPpEAcjKB8v/ydDtRNCBAUDXIfQEMFyBAQj0Cm+hMbOSXwfgBdM/yCWCEHBsdWe6kjgw4w0DghBkc3RyupJfBuMNDA0CASAODwBu0gf6ANTUIvkABcjKBxXL/8nQd3SAGMjLBcsCIs8WUAX6AhTLaxLMzMlz+wDIQBSBAQj0UfKnAgBwgQEI1xj6ANM/yFQgR4EBCPRR8qeCEG5vdGVwdIAYyMsFywJQBs8WUAT6AhTLahLLH8s/yXP7AAIAbIEBCNcY+gDTPzBSJIEBCPRZ8qeCEGRzdHJwdIAYyMsFywJQBc8WUAP6AhPLassfEss/yXP7AAAK9ADJ7VQAeAH6APQEMPgnbyIwUAqhIb7y4FCCEHBsdWeDHrFwgBhQBMsFJs8WWPoCGfQAy2kXyx9SYMs/IMmAQPsABgCKUASBAQj0WTDtRNCBAUDXIMgBzxb0AMntVAFysI4jghBkc3Rygx6xcIAYUAXLBVADzxYj+gITy2rLH8s/yYBA+wCSXwPiAgEgEBEAWb0kK29qJoQICga5D6AhhHDUCAhHpJN9KZEM5pA+n/mDeBKAG3gQFImHFZ8xhAIBWBITABG4yX7UTQ1wsfgAPbKd+1E0IEBQNch9AQwAsjKB8v/ydABgQEI9ApvoTGACASAUFQAZrc52omhAIGuQ64X/wAAZrx32omhAEGuQ64WPwEXtMkg=");
}
21 changes: 21 additions & 0 deletions src/interface/TWTONWallet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

#include "TrustWalletCore/TWTONWallet.h"
#include "rust/Wrapper.h"
#include "PublicKey.h"

using namespace TW;

TWString *_Nullable TWTONWalletBuildV4R2StateInit(struct TWPublicKey *_Nonnull publicKey, int32_t workchain, int32_t walletId) {
auto keyType = static_cast<uint32_t>(TWPublicKeyKeyType(publicKey));
auto* publicKeyRustRaw = Rust::tw_public_key_create_with_data(publicKey->impl.bytes.data(), publicKey->impl.bytes.size(), keyType);
const auto publicKeyRust = Rust::wrapTWPublicKey(publicKeyRustRaw);

Rust::TWStringWrapper stateInit = Rust::tw_ton_wallet_build_v4_r2_state_init(publicKeyRust.get(), workchain, walletId);
if (!stateInit) {
return nullptr;
}
return TWStringCreateWithUTF8Bytes(stateInit.c_str());
}
7 changes: 7 additions & 0 deletions swift/Tests/Blockchains/TheOpenNetworkTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ class TheOpenNetworkTests: XCTestCase {
let jettonAddress = TONAddressConverter.fromBoc(boc: jettonAddressBocEncoded)
XCTAssertEqual(jettonAddress, "UQAt6fNdWGLjZT5CdU8mBf0FHDMXrd0qI4FpdvDkcYrpXV5H")
}

func testBuildV4R2StateInit() {
let publicKeyData = Data(hexString: "f229a9371fa7c2108b3d90ea22c9be705ff5d0cfeaee9cbb9366ff0171579357")!
let publicKey = PublicKey(data: publicKeyData, type: .ed25519)!
let stateInit = TONWallet.buildV4R2StateInit(publicKey: publicKey, workchain: 0, walletId: 0x29a9a317)!
XCTAssertEqual(stateInit, "te6cckECFgEAAwQAAgE0AQIBFP8A9KQT9LzyyAsDAFEAAAAAKamjF/IpqTcfp8IQiz2Q6iLJvnBf9dDP6u6cu5Nm/wFxV5NXQAIBIAQFAgFIBgcE+PKDCNcYINMf0x/THwL4I7vyZO1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8ICQoLAubQAdDTAyFxsJJfBOAi10nBIJJfBOAC0x8hghBwbHVnvSKCEGRzdHK9sJJfBeAD+kAwIPpEAcjKB8v/ydDtRNCBAUDXIfQEMFyBAQj0Cm+hMbOSXwfgBdM/yCWCEHBsdWe6kjgw4w0DghBkc3RyupJfBuMNDA0CASAODwBu0gf6ANTUIvkABcjKBxXL/8nQd3SAGMjLBcsCIs8WUAX6AhTLaxLMzMlz+wDIQBSBAQj0UfKnAgBwgQEI1xj6ANM/yFQgR4EBCPRR8qeCEG5vdGVwdIAYyMsFywJQBs8WUAT6AhTLahLLH8s/yXP7AAIAbIEBCNcY+gDTPzBSJIEBCPRZ8qeCEGRzdHJwdIAYyMsFywJQBc8WUAP6AhPLassfEss/yXP7AAAK9ADJ7VQAeAH6APQEMPgnbyIwUAqhIb7y4FCCEHBsdWeDHrFwgBhQBMsFJs8WWPoCGfQAy2kXyx9SYMs/IMmAQPsABgCKUASBAQj0WTDtRNCBAUDXIMgBzxb0AMntVAFysI4jghBkc3Rygx6xcIAYUAXLBVADzxYj+gITy2rLH8s/yYBA+wCSXwPiAgEgEBEAWb0kK29qJoQICga5D6AhhHDUCAhHpJN9KZEM5pA+n/mDeBKAG3gQFImHFZ8xhAIBWBITABG4yX7UTQ1wsfgAPbKd+1E0IEBQNch9AQwAsjKB8v/ydABgQEI9ApvoTGACASAUFQAZrc52omhAIGuQ64X/wAAZrx32omhAEGuQ64WPwEXtMkg=")
}

func testSign() {
let privateKeyData = Data(hexString: "c38f49de2fb13223a9e7d37d5d0ffbdd89a5eb7c8b0ee4d1c299f2cefe7dc4a0")!
Expand Down
22 changes: 22 additions & 0 deletions tests/chains/TheOpenNetwork/TWTONWalletTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

#include "TestUtilities.h"

#include "HexCoding.h"
#include "TrustWalletCore/TWTONWallet.h"

namespace TW::TheOpenNetwork::tests {

TEST(TWTONWallet, BuildV4R2StateInit) {
auto publicKeyBytes = DATA("f229a9371fa7c2108b3d90ea22c9be705ff5d0cfeaee9cbb9366ff0171579357");
auto publicKey = WRAP(TWPublicKey, TWPublicKeyCreateWithData(publicKeyBytes.get(), TWPublicKeyTypeED25519));

const int32_t baseWorkchain = 0;
const int32_t defaultWalletId = 0x29a9a317;
const auto stateInit = WRAPS(TWTONWalletBuildV4R2StateInit(publicKey.get(), baseWorkchain, defaultWalletId));
assertStringsEqual(stateInit, "te6cckECFgEAAwQAAgE0AQIBFP8A9KQT9LzyyAsDAFEAAAAAKamjF/IpqTcfp8IQiz2Q6iLJvnBf9dDP6u6cu5Nm/wFxV5NXQAIBIAQFAgFIBgcE+PKDCNcYINMf0x/THwL4I7vyZO1E0NMf0x/T//QE0VFDuvKhUVG68qIF+QFUEGT5EPKj+AAkpMjLH1JAyx9SMMv/UhD0AMntVPgPAdMHIcAAn2xRkyDXSpbTB9QC+wDoMOAhwAHjACHAAuMAAcADkTDjDQOkyMsfEssfy/8ICQoLAubQAdDTAyFxsJJfBOAi10nBIJJfBOAC0x8hghBwbHVnvSKCEGRzdHK9sJJfBeAD+kAwIPpEAcjKB8v/ydDtRNCBAUDXIfQEMFyBAQj0Cm+hMbOSXwfgBdM/yCWCEHBsdWe6kjgw4w0DghBkc3RyupJfBuMNDA0CASAODwBu0gf6ANTUIvkABcjKBxXL/8nQd3SAGMjLBcsCIs8WUAX6AhTLaxLMzMlz+wDIQBSBAQj0UfKnAgBwgQEI1xj6ANM/yFQgR4EBCPRR8qeCEG5vdGVwdIAYyMsFywJQBs8WUAT6AhTLahLLH8s/yXP7AAIAbIEBCNcY+gDTPzBSJIEBCPRZ8qeCEGRzdHJwdIAYyMsFywJQBc8WUAP6AhPLassfEss/yXP7AAAK9ADJ7VQAeAH6APQEMPgnbyIwUAqhIb7y4FCCEHBsdWeDHrFwgBhQBMsFJs8WWPoCGfQAy2kXyx9SYMs/IMmAQPsABgCKUASBAQj0WTDtRNCBAUDXIMgBzxb0AMntVAFysI4jghBkc3Rygx6xcIAYUAXLBVADzxYj+gITy2rLH8s/yYBA+wCSXwPiAgEgEBEAWb0kK29qJoQICga5D6AhhHDUCAhHpJN9KZEM5pA+n/mDeBKAG3gQFImHFZ8xhAIBWBITABG4yX7UTQ1wsfgAPbKd+1E0IEBQNch9AQwAsjKB8v/ydABgQEI9ApvoTGACASAUFQAZrc52omhAIGuQ64X/wAAZrx32omhAEGuQ64WPwEXtMkg=");
}

} // namespace TW::TheOpenNetwork::tests

0 comments on commit 6a31911

Please sign in to comment.