Ton fixes

This commit is contained in:
Peter
2019-07-16 15:24:19 +01:00
parent 59b9a8b30a
commit 2d1edc9f4a
3 changed files with 261 additions and 19 deletions

View File

@@ -4,6 +4,12 @@ NS_ASSUME_NONNULL_BEGIN
@class MTSignal;
@interface TONError : NSObject
@property (nonatomic, strong, readonly) NSString *text;
@end
@interface TONKey : NSObject
@property (nonatomic, strong, readonly) NSString *publicKey;
@@ -13,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
@end
@interface TONTestGiverAccountState : NSObject
@interface TONAccountState : NSObject
@property (nonatomic, readonly) int64_t balance;
@property (nonatomic, readonly) int32_t seqno;
@@ -29,8 +35,12 @@ NS_ASSUME_NONNULL_BEGIN
- (MTSignal *)createKeyWithLocalPassword:(NSString *)localPassword mnemonicPassword:(NSString *)mnemonicPassword;
- (MTSignal *)getTestWalletAccountAddressWithPublicKey:(NSString *)publicKey;
- (MTSignal *)getTestGiverAccountState;
- (MTSignal *)testGiverSendGramsWithAccountState:(TONTestGiverAccountState *)accountState accountAddress:(NSString *)accountAddress amount:(int64_t)amount;
- (MTSignal *)testGiverSendGramsWithAccountState:(TONAccountState *)accountState accountAddress:(NSString *)accountAddress amount:(int64_t)amount;
- (MTSignal *)getAccountStateWithAddress:(NSString *)accountAddress;
- (MTSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSString *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount;
- (MTSignal *)exportKey:(TONKey *)key localPassword:(NSString *)localPassword;
- (MTSignal *)importKeyWithLocalPassword:(NSString *)localPassword mnemonicPassword:(NSString *)mnemonicPassword wordList:(NSArray<NSString *> *)wordList;
- (MTSignal *)deleteKeyWithPublicKey:(NSString *)publicKey;
@end

View File

@@ -19,7 +19,7 @@
@end
@implementation TONTestGiverAccountState
@implementation TONAccountState
- (instancetype)initWithBalance:(int64_t)balance seqno:(int32_t)seqno {
self = [super init];
@@ -72,12 +72,6 @@ using tonlib_api::make_object;
@end
@interface TONError : NSObject
@property (nonatomic, strong, readonly) NSString *text;
@end
@implementation TONError
- (instancetype)initWithText:(NSString *)text {
@@ -239,7 +233,7 @@ using tonlib_api::make_object;
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else if (object->get_id() == tonlib_api::testGiver_accountState::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::testGiver_accountState>(object);
[subscriber putNext:[[TONTestGiverAccountState alloc] initWithBalance:result->balance_ seqno:result->seqno_]];
[subscriber putNext:[[TONAccountState alloc] initWithBalance:result->balance_ seqno:result->seqno_]];
[subscriber putCompletion];
} else {
assert(false);
@@ -254,7 +248,7 @@ using tonlib_api::make_object;
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
- (MTSignal *)testGiverSendGramsWithAccountState:(TONTestGiverAccountState *)accountState accountAddress:(NSString *)accountAddress amount:(int64_t)amount {
- (MTSignal *)testGiverSendGramsWithAccountState:(TONAccountState *)accountState accountAddress:(NSString *)accountAddress amount:(int64_t)amount {
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
@@ -287,7 +281,11 @@ using tonlib_api::make_object;
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else if (object->get_id() == tonlib_api::generic_accountStateUninited::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateUninited>(object);
[subscriber putNext:@(result->account_state_->balance_)];
[subscriber putNext:[[TONAccountState alloc] initWithBalance:result->account_state_->balance_ seqno:-1]];
[subscriber putCompletion];
} else if (object->get_id() == tonlib_api::generic_accountStateTestWallet::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateTestWallet>(object);
[subscriber putNext:[[TONAccountState alloc] initWithBalance:result->account_state_->balance_ seqno:result->account_state_->seqno_]];
[subscriber putCompletion];
} else {
assert(false);
@@ -302,4 +300,140 @@ using tonlib_api::make_object;
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
- (MTSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSString *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount {
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
_requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else {
[subscriber putCompletion];
}
}];
NSData *publicKeyData = [[NSData alloc] initWithBase64EncodedString:key.publicKey options:0];
std::string publicKeyString((uint8_t *)publicKeyData.bytes, (uint8_t *)publicKeyData.bytes + publicKeyData.length);
NSData *secretData = [[NSData alloc] initWithBase64EncodedString:key.secret options:0];
std::string secretString((uint8_t *)secretData.bytes, (uint8_t *)secretData.bytes + secretData.length);
NSData *localPasswordData = [localPassword dataUsingEncoding:NSUTF8StringEncoding];
std::string localPasswordString((uint8_t *)localPasswordData.bytes, (uint8_t *)localPasswordData.bytes + localPasswordData.length);
auto query = make_object<tonlib_api::generic_sendGrams>(make_object<tonlib_api::inputKey>(make_object<tonlib_api::key>(publicKeyString, secretString), localPasswordString), make_object<tonlib_api::accountAddress>(fromAddress.UTF8String), make_object<tonlib_api::accountAddress>(address.UTF8String), amount);
_client->send({ requestId, std::move(query) });
return [[MTBlockDisposable alloc] initWithBlock:^{
}];
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
- (MTSignal *)exportKey:(TONKey *)key localPassword:(NSString *)localPassword {
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
_requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else if (object->get_id() == tonlib_api::exportedKey::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::exportedKey>(object);
NSMutableArray *wordList = [[NSMutableArray alloc] init];
for (auto it : result->word_list_) {
[wordList addObject:[[NSString alloc] initWithUTF8String:it.c_str()]];
}
[subscriber putNext:wordList];
[subscriber putCompletion];
} else {
assert(false);
}
}];
NSData *publicKeyData = [[NSData alloc] initWithBase64EncodedString:key.publicKey options:0];
std::string publicKeyString((uint8_t *)publicKeyData.bytes, (uint8_t *)publicKeyData.bytes + publicKeyData.length);
NSData *secretData = [[NSData alloc] initWithBase64EncodedString:key.secret options:0];
std::string secretString((uint8_t *)secretData.bytes, (uint8_t *)secretData.bytes + secretData.length);
NSData *localPasswordData = [localPassword dataUsingEncoding:NSUTF8StringEncoding];
std::string localPasswordString((uint8_t *)localPasswordData.bytes, (uint8_t *)localPasswordData.bytes + localPasswordData.length);
auto query = make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKey>(make_object<tonlib_api::key>(publicKeyString, secretString), localPasswordString));
_client->send({ requestId, std::move(query) });
return [[MTBlockDisposable alloc] initWithBlock:^{
}];
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
- (MTSignal *)importKeyWithLocalPassword:(NSString *)localPassword mnemonicPassword:(NSString *)mnemonicPassword wordList:(NSArray<NSString *> *)wordList {
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
_requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else if (object->get_id() == tonlib_api::key::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::key>(object);
NSString *publicKey = [[[NSData alloc] initWithBytes:result->public_key_.data() length:result->public_key_.length()] base64EncodedStringWithOptions:0];
NSString *secret = [[[NSData alloc] initWithBytes:result->secret_.data() length:result->secret_.length()] base64EncodedStringWithOptions:0];
[subscriber putNext:[[TONKey alloc] initWithPublicKey:publicKey secret:secret]];
[subscriber putCompletion];
} else {
assert(false);
}
}];
NSData *localPasswordData = [localPassword dataUsingEncoding:NSUTF8StringEncoding];
std::string localPasswordString((uint8_t *)localPasswordData.bytes, (uint8_t *)localPasswordData.bytes + localPasswordData.length);
NSData *mnemonicPasswordData = [mnemonicPassword dataUsingEncoding:NSUTF8StringEncoding];
std::string mnemonicPasswordString((uint8_t *)mnemonicPasswordData.bytes, (uint8_t *)mnemonicPasswordData.bytes + mnemonicPasswordData.length);
std::vector<std::string> wordVector;
for (NSString *word in wordList) {
NSData *wordData = [word dataUsingEncoding:NSUTF8StringEncoding];
std::string wordString((uint8_t *)wordData.bytes, (uint8_t *)wordData.bytes + wordData.length);
wordVector.push_back(wordString);
}
auto query = make_object<tonlib_api::importKey>(localPasswordString, mnemonicPasswordString, make_object<tonlib_api::exportedKey>(std::move(wordVector)));
_client->send({ requestId, std::move(query) });
return [[MTBlockDisposable alloc] initWithBlock:^{
}];
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
- (MTSignal *)deleteKeyWithPublicKey:(NSString *)publicKey {
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
_requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else {
[subscriber putCompletion];
}
}];
NSData *publicKeyData = [[NSData alloc] initWithBase64EncodedString:publicKey options:0];
std::string publicKeyString((uint8_t *)publicKeyData.bytes, (uint8_t *)publicKeyData.bytes + publicKeyData.length);
auto query = make_object<tonlib_api::deleteKey>(publicKeyString);
_client->send({ requestId, std::move(query) });
return [[MTBlockDisposable alloc] initWithBlock:^{
}];
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
@end

View File

@@ -2378,13 +2378,13 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
let _ = transaction.addMessages([message], location: .UpperHistoryBlock)
}).start()
let _ = strongSelf.context.ton?.getAccountState(withAddress: components[2]).start(next: { balance in
guard let balance = balance as? Int64 else {
let _ = strongSelf.context.ton?.getAccountState(withAddress: components[2]).start(next: { state in
guard let state = state as? TONAccountState else {
return
}
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "balance: \(balance)", attributes: [], media: [])
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "balance: \(state.balance)", attributes: [], media: [])
let _ = transaction.addMessages([message1], location: .UpperHistoryBlock)
}).start()
})
@@ -2398,7 +2398,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
}).start()
let _ = strongSelf.context.ton?.getTestGiverAccountState().start(next: { state in
guard let state = state as? TONTestGiverAccountState else {
guard let state = state as? TONAccountState else {
return
}
let _ = strongSelf.context.ton?.testGiverSendGrams(with: state, accountAddress: components[2], amount: amount).start(next: nil, completed: {
@@ -2411,6 +2411,70 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
})
}
} else if components[1] == "sendgrams" {
if components.count >= 7, let amount = Int64(components[6]) {
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: strongSelf.context.account.peerId, text: message.text, attributes: [], media: [])
let _ = transaction.addMessages([message], location: .UpperHistoryBlock)
}).start()
let _ = strongSelf.context.ton?.getTestWalletAccountAddress(withPublicKey: components[2]).start(next: { localAddress in
guard let localAddress = localAddress as? String else {
return
}
let _ = strongSelf.context.ton?.sendGrams(from: TONKey(publicKey: components[2], secret: components[3]), localPassword: components[4], fromAddress: localAddress, toAddress: components[5], amount: amount).start(next: nil, error: { error in
guard let error = error as? TONError else {
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "error: \(error.text)", attributes: [], media: [])
let _ = transaction.addMessages([message1], location: .UpperHistoryBlock)
}).start()
}, completed: {
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "sent", attributes: [], media: [])
let _ = transaction.addMessages([message1], location: .UpperHistoryBlock)
}).start()
})
})
}
} else if components[1] == "exportkey" {
if components.count >= 5 {
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: strongSelf.context.account.peerId, text: message.text, attributes: [], media: [])
let _ = transaction.addMessages([message], location: .UpperHistoryBlock)
}).start()
let _ = strongSelf.context.ton?.export(TONKey(publicKey: components[2], secret: components[3]), localPassword: components[4]).start(next: { wordList in
guard let wordList = wordList as? [String] else {
return
}
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "word list:", attributes: [], media: [])
var listText = ""
for word in wordList {
if !listText.isEmpty {
listText.append(" ")
}
listText.append(word)
}
let message2 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "\(listText)", attributes: [], media: [])
let _ = transaction.addMessages([message1, message2], location: .UpperHistoryBlock)
}).start()
}, error: { error in
guard let error = error as? TONError else {
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "error: \(error.text)", attributes: [], media: [])
let _ = transaction.addMessages([message1], location: .UpperHistoryBlock)
}).start()
}, completed: nil)
}
} else if components[1] == "importkey" {
if components.count >= 4 {
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
@@ -2418,13 +2482,47 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
let _ = transaction.addMessages([message], location: .UpperHistoryBlock)
}).start()
let _ = strongSelf.context.ton?.getAccountState(withAddress: components[2]).start(next: { balance in
guard let balance = balance as? Int64 else {
let _ = strongSelf.context.ton?.importKey(withLocalPassword: components[2], mnemonicPassword: components[3], wordList: Array(components[4...])).start(next: { key in
guard let key = key as? TONKey else {
return
}
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "balance: \(balance)", attributes: [], media: [])
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "imported key (public, secret):", attributes: [], media: [])
let message2 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "\(key.publicKey)", attributes: [], media: [])
let message3 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "\(key.secret)", attributes: [], media: [])
let _ = transaction.addMessages([message1, message2, message3], location: .UpperHistoryBlock)
}).start()
}, error: { error in
guard let error = error as? TONError else {
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "error: \(error.text)", attributes: [], media: [])
let _ = transaction.addMessages([message1], location: .UpperHistoryBlock)
}).start()
}, completed: nil)
}
} else if components[1] == "deletekey" {
if components.count >= 3 {
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: strongSelf.context.account.peerId, text: message.text, attributes: [], media: [])
let _ = transaction.addMessages([message], location: .UpperHistoryBlock)
}).start()
let _ = strongSelf.context.ton?.deleteKey(withPublicKey: components[2]).start(next: nil, error: { error in
guard let error = error as? TONError else {
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "error: \(error.text)", attributes: [], media: [])
let _ = transaction.addMessages([message1], location: .UpperHistoryBlock)
}).start()
}, completed: {
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
let _ = (strongSelf.context.account.postbox.transaction { transaction in
let message1 = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: "deleted", attributes: [], media: [])
let _ = transaction.addMessages([message1], location: .UpperHistoryBlock)
}).start()
})