mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated tonlib
This commit is contained in:
parent
3002321eb7
commit
11bd640ee0
12 changed files with 455 additions and 22 deletions
|
@ -207,6 +207,7 @@ set(SMC_ENVELOPE_SOURCE
|
|||
smc-envelope/TestGiver.cpp
|
||||
smc-envelope/TestWallet.cpp
|
||||
smc-envelope/Wallet.cpp
|
||||
smc-envelope/WalletV3.cpp
|
||||
|
||||
smc-envelope/GenericAccount.h
|
||||
smc-envelope/MultisigWallet.h
|
||||
|
@ -215,6 +216,7 @@ set(SMC_ENVELOPE_SOURCE
|
|||
smc-envelope/TestGiver.h
|
||||
smc-envelope/TestWallet.h
|
||||
smc-envelope/Wallet.h
|
||||
smc-envelope/WalletV3.h
|
||||
)
|
||||
|
||||
set(ED25519_TEST_SOURCE
|
||||
|
|
50
crypto/smartcont/wallet-v3.fif
Normal file
50
crypto/smartcont/wallet-v3.fif
Normal file
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <dest-addr> <subwallet_id> <seqno> <amount> [-B <body-boc>] [<savefile>]" cr
|
||||
."Creates a request to advanced wallet created by new-wallet-v3.fif, with private key loaded from file <filename-base>.pk "
|
||||
."and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)" cr 1 halt
|
||||
} : usage
|
||||
def? $7 { @' $6 "-B" $= { @' $7 =: body-boc-file [forget] $7 def? $8 { @' $8 =: $6 [forget] $8 } { [forget] $6 } cond
|
||||
@' $# 2- =: $# } if } if
|
||||
$# dup 5 < swap 6 > or ' usage if
|
||||
|
||||
true constant bounce
|
||||
|
||||
$1 =: file-base
|
||||
$2 bounce parse-load-address =: bounce 2=: dest_addr
|
||||
$3 parse-int =: subwallet_id
|
||||
$4 parse-int =: seqno
|
||||
$5 $>GR =: amount
|
||||
def? $6 { @' $6 } { "wallet-query" } cond constant savefile
|
||||
3 constant send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors
|
||||
60 constant timeout // external message expires in 60 seconds
|
||||
|
||||
file-base +".addr" load-address
|
||||
2dup 2constant wallet_addr
|
||||
."Source wallet address = " 2dup .addr cr 6 .Addr cr
|
||||
file-base +".pk" load-keypair nip constant wallet_pk
|
||||
|
||||
def? body-boc-file { @' body-boc-file file>B B>boc } { <b 0 32 u, "TESTv3" $, b> } cond
|
||||
constant body-cell
|
||||
|
||||
."Transferring " amount .GR ."to account "
|
||||
dest_addr 2dup bounce 7 + .Addr ." = " .addr
|
||||
."subwallet_id=0x" subwallet_id x.
|
||||
."seqno=0x" seqno x. ."bounce=" bounce . cr
|
||||
."Body of transfer message is " body-cell <s csr. cr
|
||||
|
||||
// create a message
|
||||
<b b{01} s, bounce 1 i, b{000100} s, dest_addr addr, amount Gram, 0 9 64 32 + + 1+ u,
|
||||
body-cell <s 2dup s-fits? not rot over 1 i, -rot { drop body-cell ref, } { s, } cond
|
||||
b>
|
||||
<b subwallet_id 32 u, now timeout + 32 u, seqno 32 u, send-mode 8 u, swap ref, b>
|
||||
dup ."signing message: " <s csr. cr
|
||||
dup hashu wallet_pk ed25519_sign_uint
|
||||
<b b{1000100} s, wallet_addr addr, 0 Gram, b{00} s,
|
||||
swap B, swap <s s, b>
|
||||
dup ."resulting external message: " <s csr. cr
|
||||
2 boc+>B dup Bx. cr
|
||||
savefile +".boc" tuck B>file
|
||||
."Query expires in " timeout . ."seconds" cr
|
||||
."(Saved to file " type .")" cr
|
130
crypto/smc-envelope/WalletV3.cpp
Normal file
130
crypto/smc-envelope/WalletV3.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#include "WalletV3.h"
|
||||
#include "GenericAccount.h"
|
||||
|
||||
#include "vm/boc.h"
|
||||
#include "vm/cells/CellString.h"
|
||||
#include "td/utils/base64.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace ton {
|
||||
td::Ref<vm::Cell> WalletV3::get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept {
|
||||
auto code = get_init_code();
|
||||
auto data = get_init_data(public_key, wallet_id);
|
||||
return GenericAccount::get_init_state(std::move(code), std::move(data));
|
||||
}
|
||||
|
||||
td::Ref<vm::Cell> WalletV3::get_init_message(const td::Ed25519::PrivateKey& private_key,
|
||||
td::uint32 wallet_id) noexcept {
|
||||
td::uint32 seqno = 0;
|
||||
td::uint32 valid_until = std::numeric_limits<td::uint32>::max();
|
||||
auto signature = private_key
|
||||
.sign(vm::CellBuilder()
|
||||
.store_long(wallet_id, 32)
|
||||
.store_long(valid_until, 32)
|
||||
.store_long(seqno, 32)
|
||||
.finalize()
|
||||
->get_hash()
|
||||
.as_slice())
|
||||
.move_as_ok();
|
||||
return vm::CellBuilder()
|
||||
.store_bytes(signature)
|
||||
.store_long(wallet_id, 32)
|
||||
.store_long(valid_until, 32)
|
||||
.store_long(seqno, 32)
|
||||
.finalize();
|
||||
}
|
||||
|
||||
td::Ref<vm::Cell> WalletV3::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id,
|
||||
td::uint32 seqno, td::uint32 valid_until, td::int64 gramms,
|
||||
td::Slice message, const block::StdAddress& dest_address) noexcept {
|
||||
td::int32 send_mode = 3;
|
||||
if (gramms == -1) {
|
||||
gramms = 0;
|
||||
send_mode += 128;
|
||||
}
|
||||
vm::CellBuilder cb;
|
||||
GenericAccount::store_int_message(cb, dest_address, gramms);
|
||||
cb.store_bytes("\0\0\0\0", 4);
|
||||
vm::CellString::store(cb, message, 35 * 8).ensure();
|
||||
auto message_inner = cb.finalize();
|
||||
|
||||
auto message_outer = vm::CellBuilder()
|
||||
.store_long(wallet_id, 32)
|
||||
.store_long(valid_until, 32)
|
||||
.store_long(seqno, 32)
|
||||
.store_long(send_mode, 8)
|
||||
.store_ref(message_inner)
|
||||
.finalize();
|
||||
auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok();
|
||||
return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize();
|
||||
}
|
||||
|
||||
td::Ref<vm::Cell> WalletV3::get_init_code() noexcept {
|
||||
static auto res = [] {
|
||||
auto serialized_code = td::base64_decode(
|
||||
"te6ccgEBAQEAYgAAwP8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x/TH/gjE7vyY+1E0NMf0x/T/"
|
||||
"9FRMrryoVFEuvKiBPkBVBBV+RDyo/gAkyDXSpbTB9QC+wDo0QGkyMsfyx/L/8ntVA==")
|
||||
.move_as_ok();
|
||||
return vm::std_boc_deserialize(serialized_code).move_as_ok();
|
||||
}();
|
||||
return res;
|
||||
}
|
||||
|
||||
vm::CellHash WalletV3::get_init_code_hash() noexcept {
|
||||
return get_init_code()->get_hash();
|
||||
}
|
||||
|
||||
td::Ref<vm::Cell> WalletV3::get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept {
|
||||
return vm::CellBuilder()
|
||||
.store_long(0, 32)
|
||||
.store_long(wallet_id, 32)
|
||||
.store_bytes(public_key.as_octet_string())
|
||||
.finalize();
|
||||
}
|
||||
|
||||
td::Result<td::uint32> WalletV3::get_seqno() const {
|
||||
return TRY_VM(get_seqno_or_throw());
|
||||
}
|
||||
|
||||
td::Result<td::uint32> WalletV3::get_seqno_or_throw() const {
|
||||
if (state_.data.is_null()) {
|
||||
return 0;
|
||||
}
|
||||
//FIXME use get method
|
||||
return static_cast<td::uint32>(vm::load_cell_slice(state_.data).fetch_ulong(32));
|
||||
}
|
||||
|
||||
td::Result<td::uint32> WalletV3::get_wallet_id() const {
|
||||
return TRY_VM(get_wallet_id_or_throw());
|
||||
}
|
||||
|
||||
td::Result<td::uint32> WalletV3::get_wallet_id_or_throw() const {
|
||||
if (state_.data.is_null()) {
|
||||
return 0;
|
||||
}
|
||||
//FIXME use get method
|
||||
auto cs = vm::load_cell_slice(state_.data);
|
||||
cs.skip_first(32);
|
||||
return static_cast<td::uint32>(cs.fetch_ulong(32));
|
||||
}
|
||||
|
||||
} // namespace ton
|
50
crypto/smc-envelope/WalletV3.h
Normal file
50
crypto/smc-envelope/WalletV3.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "smc-envelope/SmartContract.h"
|
||||
#include "vm/cells.h"
|
||||
#include "Ed25519.h"
|
||||
#include "block/block.h"
|
||||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class WalletV3 : ton::SmartContract {
|
||||
public:
|
||||
explicit WalletV3(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
static constexpr unsigned max_message_size = vm::CellString::max_bytes;
|
||||
static td::Ref<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept;
|
||||
static td::Ref<vm::Cell> get_init_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id) noexcept;
|
||||
static td::Ref<vm::Cell> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id,
|
||||
td::uint32 seqno, td::uint32 valid_until, td::int64 gramms,
|
||||
td::Slice message, const block::StdAddress& dest_address) noexcept;
|
||||
|
||||
static td::Ref<vm::Cell> get_init_code() noexcept;
|
||||
static vm::CellHash get_init_code_hash() noexcept;
|
||||
static td::Ref<vm::Cell> get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept;
|
||||
|
||||
td::Result<td::uint32> get_seqno() const;
|
||||
td::Result<td::uint32> get_wallet_id() const;
|
||||
|
||||
private:
|
||||
td::Result<td::uint32> get_seqno_or_throw() const;
|
||||
td::Result<td::uint32> get_wallet_id_or_throw() const;
|
||||
};
|
||||
} // namespace ton
|
|
@ -34,6 +34,7 @@
|
|||
#include "smc-envelope/TestGiver.h"
|
||||
#include "smc-envelope/TestWallet.h"
|
||||
#include "smc-envelope/Wallet.h"
|
||||
#include "smc-envelope/WalletV3.h"
|
||||
|
||||
#include "td/utils/base64.h"
|
||||
#include "td/utils/crypto.h"
|
||||
|
@ -114,6 +115,33 @@ SETCP0 DUP IFNOTRET // return if recv_internal
|
|||
)ABCD";
|
||||
return fift::compile_asm(code).move_as_ok();
|
||||
}
|
||||
td::Ref<vm::Cell> get_wallet_v3_source() {
|
||||
std::string code = R"ABCD(
|
||||
SETCP0 DUP IFNOTRET // return if recv_internal
|
||||
DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method
|
||||
DROP c4 PUSHCTR CTOS 32 PLDU // cnt
|
||||
}>
|
||||
INC 32 THROWIF // fail unless recv_external
|
||||
9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs
|
||||
NOW s1 s3 XCHG LEQ 35 THROWIF // signature in_msg subwallet_id cs msg_seqno
|
||||
c4 PUSH CTOS 32 LDU 32 LDU 256 LDU ENDS // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key
|
||||
s3 s2 XCPU EQUAL 33 THROWIFNOT // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet
|
||||
s4 s4 XCPU EQUAL 34 THROWIFNOT // signature in_msg stored_subwallet cs public_key stored_seqno
|
||||
s0 s4 XCHG HASHSU // signature stored_seqno stored_subwallet cs public_key msg_hash
|
||||
s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs msg_hash signature public_key
|
||||
CHKSIGNU 35 THROWIFNOT // public_key stored_seqno stored_subwallet cs
|
||||
ACCEPT
|
||||
WHILE:<{
|
||||
DUP SREFS // public_key stored_seqno stored_subwallet cs _51
|
||||
}>DO<{ // public_key stored_seqno stored_subwallet cs
|
||||
8 LDU LDREF s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode
|
||||
SENDRAWMSG
|
||||
}> // public_key stored_seqno stored_subwallet cs
|
||||
ENDS SWAP INC // public_key stored_subwallet seqno'
|
||||
NEWC 32 STU 32 STU 256 STU ENDC c4 POP
|
||||
)ABCD";
|
||||
return fift::compile_asm(code).move_as_ok();
|
||||
}
|
||||
|
||||
TEST(Tonlib, TestWallet) {
|
||||
LOG(ERROR) << td::base64_encode(std_boc_serialize(get_test_wallet_source()).move_as_ok());
|
||||
|
@ -209,6 +237,55 @@ TEST(Tonlib, Wallet) {
|
|||
CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash());
|
||||
}
|
||||
|
||||
TEST(Tonlib, WalletV3) {
|
||||
LOG(ERROR) << td::base64_encode(std_boc_serialize(get_wallet_v3_source()).move_as_ok());
|
||||
CHECK(get_wallet_v3_source()->get_hash() == ton::WalletV3::get_init_code()->get_hash());
|
||||
|
||||
auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet-v3.fif"), {"aba", "0", "239"}).move_as_ok();
|
||||
|
||||
auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data;
|
||||
auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet-query.boc").move_as_ok().data;
|
||||
auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet.addr").move_as_ok().data;
|
||||
|
||||
td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}};
|
||||
auto pub_key = priv_key.get_public_key().move_as_ok();
|
||||
auto init_state = ton::WalletV3::get_init_state(pub_key, 239);
|
||||
auto init_message = ton::WalletV3::get_init_message(priv_key, 239);
|
||||
auto address = ton::GenericAccount::get_address(0, init_state);
|
||||
|
||||
CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32));
|
||||
|
||||
td::Ref<vm::Cell> res = ton::GenericAccount::create_ext_message(address, init_state, init_message);
|
||||
|
||||
LOG(ERROR) << "-------";
|
||||
vm::load_cell_slice(res).print_rec(std::cerr);
|
||||
LOG(ERROR) << "-------";
|
||||
vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr);
|
||||
CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash());
|
||||
|
||||
fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet-v3.fif")).ensure();
|
||||
class ZeroOsTime : public fift::OsTime {
|
||||
public:
|
||||
td::uint32 now() override {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
fift_output.source_lookup.set_os_time(std::make_unique<ZeroOsTime>());
|
||||
auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok();
|
||||
fift_output =
|
||||
fift::mem_run_fift(std::move(fift_output.source_lookup),
|
||||
{"aba", "new-wallet", "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "239", "123", "321"})
|
||||
.move_as_ok();
|
||||
auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data;
|
||||
auto gift_message = ton::GenericAccount::create_ext_message(
|
||||
address, {}, ton::WalletV3::make_a_gift_message(priv_key, 239, 123, 60, 321000000000ll, "TESTv3", dest));
|
||||
LOG(ERROR) << "-------";
|
||||
vm::load_cell_slice(gift_message).print_rec(std::cerr);
|
||||
LOG(ERROR) << "-------";
|
||||
vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr);
|
||||
CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash());
|
||||
}
|
||||
|
||||
TEST(Tonlib, TestGiver) {
|
||||
auto address =
|
||||
block::StdAddress::parse("-1:60c04141c6a7b96d68615e7a91d265ad0f3a9a922e9ae9c901d4fa83f5d3c0d0").move_as_ok();
|
||||
|
|
|
@ -22,6 +22,7 @@ keyStoreTypeInMemory = KeyStoreType;
|
|||
config config:string blockchain_name:string use_callbacks_for_network:Bool ignore_cache:Bool = Config;
|
||||
|
||||
options config:config keystore_type:KeyStoreType = Options;
|
||||
options.configInfo default_wallet_id:int53 = options.ConfigInfo;
|
||||
|
||||
key public_key:string secret:secureBytes = Key;
|
||||
inputKeyRegular key:key local_password:secureBytes = InputKey;
|
||||
|
@ -50,6 +51,9 @@ testWallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.t
|
|||
wallet.initialAccountState public_key:string = wallet.InitialAccountState;
|
||||
wallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53 = wallet.AccountState;
|
||||
|
||||
wallet.v3.initialAccountState public_key:string wallet_id:int53 = wallet.v3.InitialAccountState;
|
||||
wallet.v3.accountState balance:int64 wallet_id:int53 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53 = wallet.v3.AccountState;
|
||||
|
||||
testGiver.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53= testGiver.AccountState;
|
||||
|
||||
uninited.accountState balance:int64 last_transaction_id:internal.transactionId frozen_hash:bytes sync_utime:int53 = uninited.AccountState;
|
||||
|
@ -61,6 +65,7 @@ uninited.accountState balance:int64 last_transaction_id:internal.transactionId f
|
|||
generic.accountStateRaw account_state:raw.accountState = generic.AccountState;
|
||||
generic.accountStateTestWallet account_state:testWallet.accountState = generic.AccountState;
|
||||
generic.accountStateWallet account_state:wallet.accountState = generic.AccountState;
|
||||
generic.accountStateWalletV3 account_state:wallet.v3.accountState = generic.AccountState;
|
||||
generic.accountStateTestGiver account_state:testGiver.accountState = generic.AccountState;
|
||||
generic.accountStateUninited account_state:uninited.accountState = generic.AccountState;
|
||||
|
||||
|
@ -120,7 +125,7 @@ init options:options = Ok;
|
|||
close = Ok;
|
||||
|
||||
options.setConfig config:config = Ok;
|
||||
options.validateConfig config:config = Ok;
|
||||
options.validateConfig config:config = options.ConfigInfo;
|
||||
|
||||
createNewKey local_password:secureBytes mnemonic_password:secureBytes random_extra_seed:secureBytes = Key;
|
||||
deleteKey key:key = Ok;
|
||||
|
@ -159,6 +164,8 @@ wallet.getAccountAddress initital_account_state:wallet.initialAccountState = Acc
|
|||
wallet.getAccountState account_address:accountAddress = wallet.AccountState;
|
||||
wallet.sendGrams private_key:InputKey destination:accountAddress seqno:int32 valid_until:int53 amount:int64 message:bytes = SendGramsResult;
|
||||
|
||||
wallet.v3.getAccountAddress initital_account_state:wallet.v3.initialAccountState = AccountAddress;
|
||||
|
||||
testGiver.getAccountState = testGiver.AccountState;
|
||||
testGiver.getAccountAddress = AccountAddress;
|
||||
testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 message:bytes = SendGramsResult;
|
||||
|
|
Binary file not shown.
|
@ -133,9 +133,11 @@ void sync(Client& client) {
|
|||
sync_send(client, make_object<tonlib_api::sync>()).ensure();
|
||||
}
|
||||
|
||||
static td::uint32 default_wallet_id{0};
|
||||
std::string wallet_address(Client& client, const Key& key) {
|
||||
return sync_send(client, make_object<tonlib_api::wallet_getAccountAddress>(
|
||||
make_object<tonlib_api::wallet_initialAccountState>(key.public_key)))
|
||||
return sync_send(client,
|
||||
make_object<tonlib_api::wallet_v3_getAccountAddress>(
|
||||
make_object<tonlib_api::wallet_v3_initialAccountState>(key.public_key, default_wallet_id)))
|
||||
.move_as_ok()
|
||||
->account_address_;
|
||||
}
|
||||
|
@ -171,6 +173,7 @@ AccountState get_account_state(Client& client, std::string address) {
|
|||
case tonlib_api::generic_accountStateUninited::ID:
|
||||
res.type = AccountState::Empty;
|
||||
break;
|
||||
case tonlib_api::generic_accountStateWalletV3::ID:
|
||||
case tonlib_api::generic_accountStateWallet::ID:
|
||||
res.type = AccountState::Wallet;
|
||||
break;
|
||||
|
@ -358,8 +361,9 @@ Wallet create_empty_wallet(Client& client) {
|
|||
Wallet wallet{"", {key->public_key_, std::move(key->secret_)}};
|
||||
|
||||
auto account_address =
|
||||
sync_send(client, make_object<tonlib_api::wallet_getAccountAddress>(
|
||||
make_object<tonlib_api::wallet_initialAccountState>(wallet.key.public_key)))
|
||||
sync_send(client,
|
||||
make_object<tonlib_api::wallet_v3_getAccountAddress>(
|
||||
make_object<tonlib_api::wallet_v3_initialAccountState>(wallet.key.public_key, default_wallet_id)))
|
||||
.move_as_ok();
|
||||
|
||||
wallet.address = account_address->account_address_;
|
||||
|
@ -529,6 +533,10 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
Client client;
|
||||
{
|
||||
auto info = sync_send(client, make_object<tonlib_api::options_validateConfig>(
|
||||
make_object<tonlib_api::config>(global_config_str, "", false, false)))
|
||||
.move_as_ok();
|
||||
default_wallet_id = static_cast<td::uint32>(info->default_wallet_id_);
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
|
||||
make_object<tonlib_api::config>(global_config_str, "", false, false),
|
||||
make_object<tonlib_api::keyStoreTypeDirectory>(keystore_dir))))
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "smc-envelope/GenericAccount.h"
|
||||
#include "smc-envelope/TestWallet.h"
|
||||
#include "smc-envelope/Wallet.h"
|
||||
#include "smc-envelope/WalletV3.h"
|
||||
#include "smc-envelope/TestGiver.h"
|
||||
|
||||
#include "auto/tl/tonlib_api.hpp"
|
||||
|
@ -41,6 +42,7 @@
|
|||
|
||||
#include "vm/boc.h"
|
||||
|
||||
#include "td/utils/as.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/optional.h"
|
||||
#include "td/utils/overloaded.h"
|
||||
|
@ -121,7 +123,8 @@ std::string to_bytes(td::Ref<vm::Cell> cell) {
|
|||
|
||||
class AccountState {
|
||||
public:
|
||||
AccountState(block::StdAddress address, RawAccountState&& raw) : address_(std::move(address)), raw_(std::move(raw)) {
|
||||
AccountState(block::StdAddress address, RawAccountState&& raw, td::uint32 wallet_id)
|
||||
: address_(std::move(address)), raw_(std::move(raw)), wallet_id_(wallet_id) {
|
||||
wallet_type_ = guess_type();
|
||||
}
|
||||
|
||||
|
@ -162,6 +165,17 @@ class AccountState {
|
|||
return tonlib_api::make_object<tonlib_api::wallet_accountState>(get_balance(), static_cast<td::uint32>(seqno),
|
||||
to_transaction_id(raw().info), get_sync_time());
|
||||
}
|
||||
td::Result<tonlib_api::object_ptr<tonlib_api::wallet_v3_accountState>> to_wallet_v3_accountState() const {
|
||||
if (wallet_type_ != WalletV3) {
|
||||
return TonlibError::AccountTypeUnexpected("WalletV3");
|
||||
}
|
||||
auto wallet = ton::WalletV3(get_smc_state());
|
||||
TRY_RESULT(seqno, wallet.get_seqno());
|
||||
TRY_RESULT(wallet_id, wallet.get_wallet_id());
|
||||
return tonlib_api::make_object<tonlib_api::wallet_v3_accountState>(
|
||||
get_balance(), static_cast<td::uint32>(wallet_id), static_cast<td::uint32>(seqno),
|
||||
to_transaction_id(raw().info), get_sync_time());
|
||||
}
|
||||
|
||||
td::Result<tonlib_api::object_ptr<tonlib_api::testGiver_accountState>> to_testGiver_accountState() const {
|
||||
if (wallet_type_ != Giver) {
|
||||
|
@ -191,11 +205,15 @@ class AccountState {
|
|||
TRY_RESULT(res, to_wallet_accountState());
|
||||
return tonlib_api::make_object<tonlib_api::generic_accountStateWallet>(std::move(res));
|
||||
}
|
||||
case WalletV3: {
|
||||
TRY_RESULT(res, to_wallet_v3_accountState());
|
||||
return tonlib_api::make_object<tonlib_api::generic_accountStateWalletV3>(std::move(res));
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
enum WalletType { Empty, Unknown, Giver, SimpleWallet, Wallet };
|
||||
enum WalletType { Empty, Unknown, Giver, SimpleWallet, Wallet, WalletV3 };
|
||||
WalletType get_wallet_type() const {
|
||||
return wallet_type_;
|
||||
}
|
||||
|
@ -235,6 +253,10 @@ class AccountState {
|
|||
address_.addr) {
|
||||
set_new_state({ton::Wallet::get_init_code(), ton::Wallet::get_init_data(key)});
|
||||
wallet_type_ = WalletType::Wallet;
|
||||
} else if (ton::GenericAccount::get_address(address_.workchain, ton::WalletV3::get_init_state(key, wallet_id_))
|
||||
.addr == address_.addr) {
|
||||
set_new_state({ton::WalletV3::get_init_code(), ton::WalletV3::get_init_data(key, wallet_id_)});
|
||||
wallet_type_ = WalletType::WalletV3;
|
||||
}
|
||||
return wallet_type_;
|
||||
}
|
||||
|
@ -243,8 +265,8 @@ class AccountState {
|
|||
if (wallet_type_ != WalletType::Empty) {
|
||||
return wallet_type_;
|
||||
}
|
||||
set_new_state({ton::Wallet::get_init_code(), ton::Wallet::get_init_data(key)});
|
||||
wallet_type_ = WalletType::Wallet;
|
||||
set_new_state({ton::WalletV3::get_init_code(), ton::WalletV3::get_init_data(key, wallet_id_)});
|
||||
wallet_type_ = WalletType::WalletV3;
|
||||
return wallet_type_;
|
||||
}
|
||||
|
||||
|
@ -274,6 +296,7 @@ class AccountState {
|
|||
block::StdAddress address_;
|
||||
RawAccountState raw_;
|
||||
WalletType wallet_type_{Unknown};
|
||||
td::uint32 wallet_id_{0};
|
||||
bool has_new_state_{false};
|
||||
|
||||
WalletType guess_type() const {
|
||||
|
@ -290,6 +313,9 @@ class AccountState {
|
|||
if (code_hash == ton::Wallet::get_init_code_hash()) {
|
||||
return WalletType::Wallet;
|
||||
}
|
||||
if (code_hash == ton::WalletV3::get_init_code_hash()) {
|
||||
return WalletType::WalletV3;
|
||||
}
|
||||
LOG(WARNING) << "Unknown code hash: " << td::base64_encode(code_hash.as_slice());
|
||||
return WalletType::Unknown;
|
||||
}
|
||||
|
@ -999,6 +1025,7 @@ bool TonlibClient::is_static_request(td::int32 id) {
|
|||
case tonlib_api::raw_getAccountAddress::ID:
|
||||
case tonlib_api::testWallet_getAccountAddress::ID:
|
||||
case tonlib_api::wallet_getAccountAddress::ID:
|
||||
case tonlib_api::wallet_v3_getAccountAddress::ID:
|
||||
case tonlib_api::testGiver_getAccountAddress::ID:
|
||||
case tonlib_api::packAccountAddress::ID:
|
||||
case tonlib_api::unpackAccountAddress::ID:
|
||||
|
@ -1062,6 +1089,12 @@ td::Result<block::StdAddress> get_account_address(const tonlib_api::wallet_initi
|
|||
auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key));
|
||||
return ton::GenericAccount::get_address(0 /*zerochain*/, ton::Wallet::get_init_state(key));
|
||||
}
|
||||
td::Result<block::StdAddress> get_account_address(const tonlib_api::wallet_v3_initialAccountState& test_wallet_state) {
|
||||
TRY_RESULT(key_bytes, get_public_key(test_wallet_state.public_key_));
|
||||
auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key));
|
||||
return ton::GenericAccount::get_address(
|
||||
0 /*zerochain*/, ton::WalletV3::get_init_state(key, static_cast<td::uint32>(test_wallet_state.wallet_id_)));
|
||||
}
|
||||
|
||||
td::Result<block::StdAddress> get_account_address(td::Slice account_address) {
|
||||
TRY_RESULT_PREFIX(address, block::StdAddress::parse(account_address), TonlibError::InvalidAccountAddress());
|
||||
|
@ -1070,6 +1103,9 @@ td::Result<block::StdAddress> get_account_address(td::Slice account_address) {
|
|||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
||||
const tonlib_api::raw_getAccountAddress& request) {
|
||||
if (!request.initital_account_state_) {
|
||||
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
|
||||
}
|
||||
auto r_account_address = get_account_address(*request.initital_account_state_);
|
||||
if (r_account_address.is_error()) {
|
||||
return status_to_tonlib_api(r_account_address.error());
|
||||
|
@ -1079,6 +1115,12 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
|||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
||||
const tonlib_api::testWallet_getAccountAddress& request) {
|
||||
if (!request.initital_account_state_) {
|
||||
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
|
||||
}
|
||||
if (!request.initital_account_state_) {
|
||||
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
|
||||
}
|
||||
auto r_account_address = get_account_address(*request.initital_account_state_);
|
||||
if (r_account_address.is_error()) {
|
||||
return status_to_tonlib_api(r_account_address.error());
|
||||
|
@ -1088,6 +1130,20 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
|||
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
||||
const tonlib_api::wallet_getAccountAddress& request) {
|
||||
if (!request.initital_account_state_) {
|
||||
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
|
||||
}
|
||||
auto r_account_address = get_account_address(*request.initital_account_state_);
|
||||
if (r_account_address.is_error()) {
|
||||
return status_to_tonlib_api(r_account_address.error());
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::accountAddress>(r_account_address.ok().rserialize(true));
|
||||
}
|
||||
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
||||
const tonlib_api::wallet_v3_getAccountAddress& request) {
|
||||
if (!request.initital_account_state_) {
|
||||
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
|
||||
}
|
||||
auto r_account_address = get_account_address(*request.initital_account_state_);
|
||||
if (r_account_address.is_error()) {
|
||||
return status_to_tonlib_api(r_account_address.error());
|
||||
|
@ -1249,12 +1305,14 @@ td::Result<TonlibClient::FullConfig> TonlibClient::validate_config(tonlib_api::o
|
|||
res.o_master_config = std::move(o_master_config);
|
||||
res.ignore_cache = config->ignore_cache_;
|
||||
res.use_callbacks_for_network = config->use_callbacks_for_network_;
|
||||
res.wallet_id = td::as<td::uint32>(res.config.zero_state_id.root_hash.as_slice().data());
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
void TonlibClient::set_config(FullConfig full_config) {
|
||||
config_ = std::move(full_config.config);
|
||||
config_generation_++;
|
||||
wallet_id_ = full_config.wallet_id;
|
||||
blockchain_name_ = config_.zero_state_id.root_hash.as_slice().str();
|
||||
|
||||
use_callbacks_for_network_ = full_config.use_callbacks_for_network;
|
||||
|
@ -1280,7 +1338,7 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
|
|||
if (r_config.is_error()) {
|
||||
return status_to_tonlib_api(r_config.move_as_error());
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::ok>();
|
||||
return tonlib_api::make_object<tonlib_api::options_configInfo>(r_config.ok().wallet_id);
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(tonlib_api::options_setConfig& request,
|
||||
|
@ -1893,6 +1951,23 @@ class GenericCreateSendGrams : public TonlibQueryActor {
|
|||
destination_->get_address());
|
||||
break;
|
||||
}
|
||||
case AccountState::WalletV3: {
|
||||
if (!private_key_) {
|
||||
return TonlibError::EmptyField("private_key");
|
||||
}
|
||||
if (message.size() > ton::WalletV3::max_message_size) {
|
||||
return TonlibError::MessageTooLong();
|
||||
}
|
||||
auto wallet = ton::WalletV3(source_->get_smc_state());
|
||||
TRY_RESULT(seqno, wallet.get_seqno());
|
||||
TRY_RESULT(wallet_id, wallet.get_wallet_id());
|
||||
auto valid_until = source_->get_sync_time();
|
||||
valid_until += send_grams_.timeout_ == 0 ? 60 : send_grams_.timeout_;
|
||||
raw.valid_until = valid_until;
|
||||
raw.message_body = ton::WalletV3::make_a_gift_message(private_key_.unwrap(), wallet_id, seqno, valid_until,
|
||||
amount, message, destination_->get_address());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
raw.new_state = source_->get_new_state();
|
||||
|
@ -2433,8 +2508,8 @@ td::Status TonlibClient::do_request(int_api::GetAccountState request,
|
|||
auto actor_id = actor_id_++;
|
||||
actors_[actor_id] = td::actor::create_actor<GetRawAccountState>(
|
||||
"GetAccountState", client_.get_client(), request.address, actor_shared(this, actor_id),
|
||||
promise.wrap([address = request.address](auto&& state) mutable {
|
||||
return td::make_unique<AccountState>(std::move(address), std::move(state));
|
||||
promise.wrap([address = request.address, wallet_id = wallet_id_](auto&& state) mutable {
|
||||
return td::make_unique<AccountState>(std::move(address), std::move(state), wallet_id);
|
||||
}));
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
@ -2481,6 +2556,11 @@ td::Status TonlibClient::do_request(const tonlib_api::wallet_getAccountAddress&
|
|||
return TonlibError::Internal();
|
||||
}
|
||||
template <class P>
|
||||
td::Status TonlibClient::do_request(const tonlib_api::wallet_v3_getAccountAddress& request, P&&) {
|
||||
UNREACHABLE();
|
||||
return TonlibError::Internal();
|
||||
}
|
||||
template <class P>
|
||||
td::Status TonlibClient::do_request(const tonlib_api::testGiver_getAccountAddress& request, P&&) {
|
||||
UNREACHABLE();
|
||||
return TonlibError::Internal();
|
||||
|
|
|
@ -65,6 +65,7 @@ class TonlibClient : public td::actor::Actor {
|
|||
// Config
|
||||
Config config_;
|
||||
td::uint32 config_generation_{0};
|
||||
td::uint32 wallet_id_;
|
||||
std::string blockchain_name_;
|
||||
bool ignore_cache_{false};
|
||||
bool use_callbacks_for_network_{false};
|
||||
|
@ -123,6 +124,7 @@ class TonlibClient : public td::actor::Actor {
|
|||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::raw_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testWallet_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::wallet_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::wallet_v3_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testGiver_getAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::packAccountAddress& request);
|
||||
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::unpackAccountAddress& request);
|
||||
|
@ -151,6 +153,8 @@ class TonlibClient : public td::actor::Actor {
|
|||
template <class P>
|
||||
td::Status do_request(const tonlib_api::wallet_getAccountAddress& request, P&&);
|
||||
template <class P>
|
||||
td::Status do_request(const tonlib_api::wallet_v3_getAccountAddress& request, P&&);
|
||||
template <class P>
|
||||
td::Status do_request(const tonlib_api::testGiver_getAccountAddress& request, P&&);
|
||||
template <class P>
|
||||
td::Status do_request(const tonlib_api::packAccountAddress& request, P&&);
|
||||
|
@ -198,6 +202,7 @@ class TonlibClient : public td::actor::Actor {
|
|||
td::optional<Config> o_master_config;
|
||||
bool use_callbacks_for_network;
|
||||
bool ignore_cache;
|
||||
td::uint32 wallet_id;
|
||||
};
|
||||
static td::Result<FullConfig> validate_config(tonlib_api::object_ptr<tonlib_api::config> config);
|
||||
void set_config(FullConfig config);
|
||||
|
|
|
@ -79,6 +79,9 @@ struct TonlibError {
|
|||
static td::Status InvalidPemKey() {
|
||||
return td::Status::Error(400, "INVALID_PEM_KEY");
|
||||
}
|
||||
static td::Status NeedConfig() {
|
||||
return td::Status::Error(400, "NeedConfig");
|
||||
}
|
||||
static td::Status MessageTooLong() {
|
||||
return td::Status::Error(400, "MESSAGE_TOO_LONG");
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
std::string key_dir{"."};
|
||||
bool in_memory{false};
|
||||
bool use_callbacks_for_network{false};
|
||||
bool use_simple_wallet{false};
|
||||
td::int32 wallet_version = 2;
|
||||
bool ignore_cache{false};
|
||||
|
||||
bool one_shot{false};
|
||||
|
@ -96,6 +96,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
td::actor::ActorOwn<tonlib::TonlibClient> client_;
|
||||
std::uint64_t next_query_id_{1};
|
||||
td::Promise<td::Slice> cont_;
|
||||
td::uint32 wallet_id_;
|
||||
|
||||
struct KeyInfo {
|
||||
std::string public_key;
|
||||
|
@ -176,6 +177,10 @@ class TonlibCli : public td::actor::Actor {
|
|||
? make_object<tonlib_api::config>(options_.config, options_.name,
|
||||
options_.use_callbacks_for_network, options_.ignore_cache)
|
||||
: nullptr;
|
||||
auto config2 = !options_.config.empty()
|
||||
? make_object<tonlib_api::config>(options_.config, options_.name,
|
||||
options_.use_callbacks_for_network, options_.ignore_cache)
|
||||
: nullptr;
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::KeyStoreType> ks_type;
|
||||
if (options_.in_memory) {
|
||||
|
@ -183,6 +188,14 @@ class TonlibCli : public td::actor::Actor {
|
|||
} else {
|
||||
ks_type = make_object<tonlib_api::keyStoreTypeDirectory>(options_.key_dir);
|
||||
}
|
||||
auto obj =
|
||||
tonlib::TonlibClient::static_request(make_object<tonlib_api::options_validateConfig>(std::move(config2)));
|
||||
if (obj->get_id() != tonlib_api::error::ID) {
|
||||
auto info = ton::move_tl_object_as<tonlib_api::options_configInfo>(obj);
|
||||
wallet_id_ = static_cast<td::uint32>(info->default_wallet_id_);
|
||||
} else {
|
||||
LOG(ERROR) << "Invalid config";
|
||||
}
|
||||
send_query(make_object<tonlib_api::init>(make_object<tonlib_api::options>(std::move(config), std::move(ks_type))),
|
||||
[](auto r_ok) {
|
||||
LOG_IF(ERROR, r_ok.is_error()) << r_ok.error();
|
||||
|
@ -519,7 +532,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
}));
|
||||
} else {
|
||||
send_query(make_object<tonlib_api::options_validateConfig>(std::move(config)), promise.wrap([](auto&& info) {
|
||||
td::TerminalIO::out() << "Config is valid\n";
|
||||
td::TerminalIO::out() << "Config is valid: " << to_string(info) << "\n";
|
||||
return td::Unit();
|
||||
}));
|
||||
}
|
||||
|
@ -824,11 +837,19 @@ class TonlibCli : public td::actor::Actor {
|
|||
auto r_key_i = to_key_i(key);
|
||||
using tonlib_api::make_object;
|
||||
if (r_key_i.is_ok()) {
|
||||
auto obj = options_.use_simple_wallet
|
||||
? tonlib::TonlibClient::static_request(make_object<tonlib_api::testWallet_getAccountAddress>(
|
||||
make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key)))
|
||||
: tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_getAccountAddress>(
|
||||
make_object<tonlib_api::wallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
|
||||
auto obj = [&](td::int32 version) {
|
||||
if (version == 1) {
|
||||
return tonlib::TonlibClient::static_request(make_object<tonlib_api::testWallet_getAccountAddress>(
|
||||
make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
|
||||
}
|
||||
if (version == 2) {
|
||||
return tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_getAccountAddress>(
|
||||
make_object<tonlib_api::wallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
|
||||
}
|
||||
return tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_v3_getAccountAddress>(
|
||||
make_object<tonlib_api::wallet_v3_initialAccountState>(keys_[r_key_i.ok()].public_key, wallet_id_)));
|
||||
UNREACHABLE();
|
||||
}(options_.wallet_version);
|
||||
if (obj->get_id() != tonlib_api::error::ID) {
|
||||
Address res;
|
||||
res.address = ton::move_tl_object_as<tonlib_api::accountAddress>(obj);
|
||||
|
@ -1166,7 +1187,7 @@ class TonlibCli : public td::actor::Actor {
|
|||
|
||||
void init_simple_wallet(std::string key, size_t key_i, td::Slice password) {
|
||||
using tonlib_api::make_object;
|
||||
if (options_.use_simple_wallet) {
|
||||
if (options_.wallet_version == 1) {
|
||||
send_query(make_object<tonlib_api::testWallet_init>(make_object<tonlib_api::inputKeyRegular>(
|
||||
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy()),
|
||||
td::SecureString(password))),
|
||||
|
@ -1259,8 +1280,8 @@ int main(int argc, char* argv[]) {
|
|||
options.use_callbacks_for_network = true;
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('S', "use-simple-wallet", "do not use this", [&]() {
|
||||
options.use_simple_wallet = true;
|
||||
p.add_option('W', "wallet-version", "do not use this", [&](td::Slice arg) {
|
||||
options.wallet_version = td::to_integer<td::int32>(arg);
|
||||
return td::Status::OK();
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue