diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index b2d578e6f0..9828490834 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -4755,20 +4755,20 @@ Any member of this group will be able to see messages in the channel."; "ChatSearch.ResultsTooltip" = "Tap to view as a list."; -"Updated.JustNow" = "updated just now"; -"Updated.MinutesAgo_0" = "updated %@ minutes ago"; //three to ten -"Updated.MinutesAgo_1" = "updated 1 minute ago"; //one -"Updated.MinutesAgo_2" = "updated 2 minutes ago"; //two -"Updated.MinutesAgo_3_10" = "updated %@ minutes ago"; //three to ten -"Updated.MinutesAgo_many" = "updated %@ minutes ago"; // more than ten -"Updated.MinutesAgo_any" = "updated %@ minutes ago"; // more than ten -"Updated.HoursAgo_0" = "updated %@ hours ago"; -"Updated.HoursAgo_1" = "updated 1 hour ago"; -"Updated.HoursAgo_2" = "updated 2 hours ago"; -"Updated.HoursAgo_3_10" = "updated %@ hours ago"; -"Updated.HoursAgo_any" = "updated %@ hours ago"; -"Updated.HoursAgo_many" = "updated %@ hours ago"; -"Updated.HoursAgo_0" = "updated %@ hours ago"; -"Updated.YesterdayAt" = "updated yesterday at %@"; -"Updated.AtDate" = "updated %@"; -"Updated.TodayAt" = "updated today at %@"; \ No newline at end of file +"Updated.JustNow" = "just now"; +"Updated.MinutesAgo_0" = "%@ minutes ago"; //three to ten +"Updated.MinutesAgo_1" = "1 minute ago"; //one +"Updated.MinutesAgo_2" = "2 minutes ago"; //two +"Updated.MinutesAgo_3_10" = "%@ minutes ago"; //three to ten +"Updated.MinutesAgo_many" = "%@ minutes ago"; // more than ten +"Updated.MinutesAgo_any" = "%@ minutes ago"; // more than ten +"Updated.HoursAgo_0" = "%@ hours ago"; +"Updated.HoursAgo_1" = "1 hour ago"; +"Updated.HoursAgo_2" = "2 hours ago"; +"Updated.HoursAgo_3_10" = "%@ hours ago"; +"Updated.HoursAgo_any" = "%@ hours ago"; +"Updated.HoursAgo_many" = "%@ hours ago"; +"Updated.HoursAgo_0" = "%@ hours ago"; +"Updated.YesterdayAt" = "yesterday at %@"; +"Updated.AtDate" = "%@"; +"Updated.TodayAt" = "today at %@"; diff --git a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+IntentsExtension.xcscheme b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+IntentsExtension.xcscheme index ce9b325629..a48bce0372 100644 --- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+IntentsExtension.xcscheme +++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+IntentsExtension.xcscheme @@ -44,6 +44,8 @@ shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + + + + + + + + + + + + + + + + + + + deliverOnMainQueue).start(completed: { f(.default) diff --git a/submodules/Display/Display/DisplayLinkAnimator.swift b/submodules/Display/Display/DisplayLinkAnimator.swift index a7cbd79858..acd8db711f 100644 --- a/submodules/Display/Display/DisplayLinkAnimator.swift +++ b/submodules/Display/Display/DisplayLinkAnimator.swift @@ -65,3 +65,45 @@ public final class DisplayLinkAnimator { } } } + +public final class ConstantDisplayLinkAnimator { + private var displayLink: CADisplayLink! + private let update: () -> Void + private var completed = false + + public var isPaused: Bool = true { + didSet { + if self.isPaused != oldValue { + self.displayLink.isPaused = self.isPaused + } + } + } + + public init(update: @escaping () -> Void) { + self.update = update + + self.displayLink = CADisplayLink(target: DisplayLinkTarget({ [weak self] in + self?.tick() + }), selector: #selector(DisplayLinkTarget.event)) + self.displayLink.isPaused = true + self.displayLink.add(to: RunLoop.main, forMode: .common) + } + + deinit { + self.displayLink.isPaused = true + self.displayLink.invalidate() + } + + public func invalidate() { + self.displayLink.isPaused = true + self.displayLink.invalidate() + } + + @objc private func tick() { + if self.completed { + return + } + self.update() + } +} + diff --git a/submodules/Display/Display/KeyboardManager.swift b/submodules/Display/Display/KeyboardManager.swift index 56769ae4b9..3cea17e8f1 100644 --- a/submodules/Display/Display/KeyboardManager.swift +++ b/submodules/Display/Display/KeyboardManager.swift @@ -144,3 +144,23 @@ class KeyboardManager { self.previousFirstResponderView = firstResponderView } } + +final class KeyboardViewManager { + private let host: StatusBarHost + + init(host: StatusBarHost) { + self.host = host + } + + func update(leftEdge: CGFloat, transition: ContainedViewLayoutTransition) { + guard let keyboardWindow = self.host.keyboardWindow else { + return + } + let previousPosition = keyboardWindow.layer.position + let updatedPosition = CGPoint(x: leftEdge + keyboardWindow.layer.bounds.width / 2.0, y: previousPosition.y) + keyboardWindow.layer.position = updatedPosition + if transition.isAnimated && !previousPosition.x.isEqual(to: updatedPosition.x) { + transition.animatePositionAdditive(layer: keyboardWindow.layer, offset: CGPoint(x: previousPosition.x - updatedPosition.x, y: 0.0)) + } + } +} diff --git a/submodules/Display/Display/Navigation/NavigationContainer.swift b/submodules/Display/Display/Navigation/NavigationContainer.swift index add58d141f..0321302ae4 100644 --- a/submodules/Display/Display/Navigation/NavigationContainer.swift +++ b/submodules/Display/Display/Navigation/NavigationContainer.swift @@ -54,10 +54,12 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { } private final class TopTransition { + let type: PendingChild.TransitionType let previous: Child let coordinator: NavigationTransitionCoordinator - init(previous: Child, coordinator: NavigationTransitionCoordinator) { + init(type: PendingChild.TransitionType, previous: Child, coordinator: NavigationTransitionCoordinator) { + self.type = type self.previous = previous self.coordinator = coordinator } @@ -77,10 +79,10 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { private(set) var isReady: Bool = false var isReadyUpdated: (() -> Void)? var controllerRemoved: (ViewController) -> Void - var keyboardManager: KeyboardManager? { + var keyboardViewManager: KeyboardViewManager? { didSet { - if self.keyboardManager !== oldValue { - self.keyboardManager?.surfaces = self.state.top?.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] + if self.keyboardViewManager !== oldValue { + } } } @@ -139,14 +141,17 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { } topController.viewWillDisappear(true) - let topView = topController.view! + let topNode = topController.displayNode bottomController.containerLayoutUpdated(layout, transition: .immediate) bottomController.viewWillAppear(true) - let bottomView = bottomController.view! + let bottomNode = bottomController.displayNode - let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, container: self.view, topView: topView, topNavigationBar: topController.navigationBar, bottomView: bottomView, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] progress, transition in + let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, container: self, topNode: topNode, topNavigationBar: topController.navigationBar, bottomNode: bottomNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] progress, transition, topFrame, bottomFrame in if let strongSelf = self { - strongSelf.keyboardManager?.surfaces = strongSelf.state.top?.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] + if let top = strongSelf.state.top { + strongSelf.syncKeyboard(leftEdge: top.value.displayNode.frame.minX, transition: transition) + } + //strongSelf.keyboardManager?.surfaces = strongSelf.state.top?.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] /*for i in 0 ..< strongSelf._viewControllers.count { if let controller = strongSelf._viewControllers[i].controller as? ViewController { if i < strongSelf._viewControllers.count - 1 { @@ -159,13 +164,13 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { } }) bottomController.displayNode.recursivelyEnsureDisplaySynchronously(true) - self.state.transition = TopTransition(previous: Child(value: bottomController, layout: layout), coordinator: navigationTransitionCoordinator) + self.state.transition = TopTransition(type: .pop, previous: Child(value: bottomController, layout: layout), coordinator: navigationTransitionCoordinator) } case .changed: if let navigationTransitionCoordinator = self.state.transition?.coordinator, !navigationTransitionCoordinator.animatingCompletion { let translation = recognizer.translation(in: self.view).x let progress = max(0.0, min(1.0, translation / self.view.frame.width)) - navigationTransitionCoordinator.progress = progress + navigationTransitionCoordinator.updateProgress(progress, transition: .immediate, completion: {}) } case .ended, .cancelled: if let navigationTransitionCoordinator = self.state.transition?.coordinator, !navigationTransitionCoordinator.animatingCompletion { @@ -274,7 +279,7 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { if pending.isReady { self.state.pending = nil let previous = self.state.top - previous?.value.view.endEditing(true) + //previous?.value.view.endEditing(true) self.state.top = pending.value self.topTransition(from: previous, to: pending.value, transitionType: pending.transitionType, layout: layout.withUpdatedInputHeight(nil), transition: pending.transition) statusBarTransition = pending.transition @@ -293,7 +298,7 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { var updatedStatusBarStyle = self.statusBarStyle if let top = self.state.top { - self.applyLayout(layout: layout, to: top, transition: transition) + self.applyLayout(layout: layout, to: top, isMaster: true, transition: transition) updatedStatusBarStyle = top.value.statusBar.statusBarStyle } else { updatedStatusBarStyle = .Ignore @@ -304,13 +309,13 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { } if self.state.transition == nil { - self.keyboardManager?.surfaces = self.state.top?.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] + //self.keyboardManager?.surfaces = self.state.top?.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] } } private func topTransition(from fromValue: Child?, to toValue: Child?, transitionType: PendingChild.TransitionType, layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { if case .animated = transition, let fromValue = fromValue, let toValue = toValue { - self.keyboardManager?.surfaces = fromValue.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] + //self.keyboardManager?.surfaces = fromValue.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] if let currentTransition = self.state.transition { assertionFailure() } @@ -338,7 +343,17 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { } toValue.value.setIgnoreAppearanceMethodInvocations(false) - let topTransition = TopTransition(previous: fromValue, coordinator: NavigationTransitionCoordinator(transition: mappedTransitionType, container: self.view, topView: topController.view, topNavigationBar: topController.navigationBar, bottomView: bottomController.view, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: nil)) + let topTransition = TopTransition(type: transitionType, previous: fromValue, coordinator: NavigationTransitionCoordinator(transition: mappedTransitionType, container: self, topNode: topController.displayNode, topNavigationBar: topController.navigationBar, bottomNode: bottomController.displayNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] _, transition, topFrame, bottomFrame in + guard let strongSelf = self else { + return + } + switch transitionType { + case .push: + strongSelf.syncKeyboard(leftEdge: topFrame.minX - bottomFrame.width, transition: transition) + case .pop: + strongSelf.syncKeyboard(leftEdge: topFrame.minX, transition: transition) + } + })) self.state.transition = topTransition topTransition.coordinator.animateCompletion(0.0, completion: { [weak self, weak topTransition] in @@ -353,13 +368,13 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { topTransition.previous.value.viewDidDisappear(true) if let toValue = strongSelf.state.top, let layout = strongSelf.state.layout { toValue.value.displayNode.frame = CGRect(origin: CGPoint(), size: layout.size) - strongSelf.applyLayout(layout: layout, to: toValue, transition: .immediate) + strongSelf.applyLayout(layout: layout, to: toValue, isMaster: true, transition: .immediate) toValue.value.viewDidAppear(true) - strongSelf.keyboardManager?.surfaces = toValue.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] + //strongSelf.keyboardManager?.surfaces = toValue.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] } }) } else { - self.keyboardManager?.surfaces = toValue?.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] + //self.keyboardManager?.surfaces = toValue?.value.view.flatMap({ [KeyboardSurface(host: $0)] }) ?? [] if let fromValue = fromValue { fromValue.value.viewWillDisappear(false) fromValue.value.setIgnoreAppearanceMethodInvocations(true) @@ -368,7 +383,7 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { fromValue.value.viewDidDisappear(false) } if let toValue = toValue { - self.applyLayout(layout: layout, to: toValue, transition: .immediate) + self.applyLayout(layout: layout, to: toValue, isMaster: true, transition: .immediate) toValue.value.displayNode.frame = CGRect(origin: CGPoint(), size: layout.size) toValue.value.viewWillAppear(false) toValue.value.setIgnoreAppearanceMethodInvocations(true) @@ -384,17 +399,34 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { return Child(value: value, layout: layout) } - private func applyLayout(layout: ContainerViewLayout, to child: Child, transition: ContainedViewLayoutTransition) { - let childFrame = CGRect(origin: CGPoint(), size: layout.size) + private func applyLayout(layout: ContainerViewLayout, to child: Child, isMaster: Bool, transition: ContainedViewLayoutTransition) { + var childFrame = CGRect(origin: CGPoint(), size: layout.size) + var shouldSyncKeyboard = false + if let transition = self.state.transition { + childFrame.origin.x = child.value.displayNode.frame.origin.x + switch transition.type { + case .pop: + shouldSyncKeyboard = true + case .push: + break + } + } if child.value.displayNode.frame != childFrame { transition.updateFrame(node: child.value.displayNode, frame: childFrame) } + if shouldSyncKeyboard && isMaster { + self.syncKeyboard(leftEdge: childFrame.minX, transition: transition) + } if child.layout != layout { child.layout = layout child.value.containerLayoutUpdated(layout, transition: transition) } } + private func syncKeyboard(leftEdge: CGFloat, transition: ContainedViewLayoutTransition) { + self.keyboardViewManager?.update(leftEdge: leftEdge, transition: transition) + } + private func pendingChildIsReady(_ child: PendingChild) { if let pending = self.state.pending, pending === child { pending.isReady = true diff --git a/submodules/Display/Display/Navigation/NavigationController.swift b/submodules/Display/Display/Navigation/NavigationController.swift index a206e983e6..384179b408 100644 --- a/submodules/Display/Display/Navigation/NavigationController.swift +++ b/submodules/Display/Display/Navigation/NavigationController.swift @@ -151,7 +151,7 @@ open class NavigationController: UINavigationController, ContainableController, } var statusBarHost: StatusBarHost? - var keyboardManager: KeyboardManager? + var keyboardViewManager: KeyboardViewManager? public func updateMasterDetailsBlackout(_ blackout: MasterDetailLayoutBlackout?, transition: ContainedViewLayoutTransition) { self.masterDetailsBlackout = blackout @@ -341,12 +341,12 @@ open class NavigationController: UINavigationController, ContainableController, if previousModalContainer == nil { topModalDismissProgress = modalContainer.dismissProgress if case .compact = layout.metrics.widthClass { - modalContainer.container.keyboardManager = self.keyboardManager + modalContainer.container.keyboardViewManager = self.keyboardViewManager } else { - modalContainer.container.keyboardManager = nil + modalContainer.container.keyboardViewManager = nil } } else { - modalContainer.container.keyboardManager = nil + modalContainer.container.keyboardViewManager = nil } previousModalContainer = modalContainer } @@ -358,9 +358,9 @@ open class NavigationController: UINavigationController, ContainableController, switch rootContainer { case let .flat(flatContainer): if previousModalContainer == nil { - flatContainer.keyboardManager = self.keyboardManager + flatContainer.keyboardViewManager = self.keyboardViewManager } else { - flatContainer.keyboardManager = nil + flatContainer.keyboardViewManager = nil } transition.updateFrame(node: flatContainer, frame: CGRect(origin: CGPoint(), size: layout.size)) flatContainer.update(layout: layout, canBeClosed: false, controllers: controllers, transition: transition) diff --git a/submodules/Display/Display/Navigation/NavigationModalContainer.swift b/submodules/Display/Display/Navigation/NavigationModalContainer.swift index ad53c8c39e..0d01ad0723 100644 --- a/submodules/Display/Display/Navigation/NavigationModalContainer.swift +++ b/submodules/Display/Display/Navigation/NavigationModalContainer.swift @@ -53,6 +53,8 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate { override func didLoad() { super.didLoad() + self.view.disablesInteractiveKeyboardGestureRecognizer = true + self.scrollNode.view.alwaysBounceVertical = false self.scrollNode.view.alwaysBounceHorizontal = false self.scrollNode.view.bounces = false diff --git a/submodules/Display/Display/NavigationTransitionCoordinator.swift b/submodules/Display/Display/NavigationTransitionCoordinator.swift index 7ebe56c0fa..5cbf82a864 100644 --- a/submodules/Display/Display/NavigationTransitionCoordinator.swift +++ b/submodules/Display/Display/NavigationTransitionCoordinator.swift @@ -20,49 +20,41 @@ class NavigationTransitionCoordinator { get { return self._progress } - set(value) { - self._progress = value - self.updateProgress(transition: .immediate) - } } - private let container: UIView + private let container: ASDisplayNode private let transition: NavigationTransition - let topView: UIView - private let viewSuperview: UIView? - let bottomView: UIView + let topNode: ASDisplayNode + let bottomNode: ASDisplayNode private let topNavigationBar: NavigationBar? private let bottomNavigationBar: NavigationBar? - private let dimView: UIView - private let shadowView: UIImageView + private let dimNode: ASDisplayNode + private let shadowNode: ASImageNode private let inlineNavigationBarTransition: Bool private(set) var animatingCompletion = false private var currentCompletion: (() -> Void)? - private var didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition) -> Void)? + private var didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? - init(transition: NavigationTransition, container: UIView, topView: UIView, topNavigationBar: NavigationBar?, bottomView: UIView, bottomNavigationBar: NavigationBar?, didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition) -> Void)? = nil) { + init(transition: NavigationTransition, container: ASDisplayNode, topNode: ASDisplayNode, topNavigationBar: NavigationBar?, bottomNode: ASDisplayNode, bottomNavigationBar: NavigationBar?, didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? = nil) { self.transition = transition self.container = container self.didUpdateProgress = didUpdateProgress - self.topView = topView - switch transition { - case .Push: - self.viewSuperview = bottomView.superview - case .Pop: - self.viewSuperview = topView.superview - } - self.bottomView = bottomView + self.topNode = topNode + self.bottomNode = bottomNode self.topNavigationBar = topNavigationBar self.bottomNavigationBar = bottomNavigationBar - self.dimView = UIView() - self.dimView.backgroundColor = UIColor.black - self.shadowView = UIImageView(image: shadowImage) + self.dimNode = ASDisplayNode() + self.dimNode.backgroundColor = UIColor.black + self.shadowNode = ASImageNode() + self.shadowNode.displaysAsynchronously = false + self.shadowNode.displayWithoutProcessing = true + self.shadowNode.image = shadowImage if let topNavigationBar = topNavigationBar, let bottomNavigationBar = bottomNavigationBar, !topNavigationBar.isHidden, !bottomNavigationBar.isHidden, topNavigationBar.canTransitionInline, bottomNavigationBar.canTransitionInline, topNavigationBar.item?.leftBarButtonItem == nil { - var topFrame = topNavigationBar.view.convert(topNavigationBar.bounds, to: container) - var bottomFrame = bottomNavigationBar.view.convert(bottomNavigationBar.bounds, to: container) + var topFrame = topNavigationBar.view.convert(topNavigationBar.bounds, to: container.view) + var bottomFrame = bottomNavigationBar.view.convert(bottomNavigationBar.bounds, to: container.view) topFrame.origin.x = 0.0 bottomFrame.origin.x = 0.0 self.inlineNavigationBarTransition = true// topFrame.equalTo(bottomFrame) @@ -72,23 +64,25 @@ class NavigationTransitionCoordinator { switch transition { case .Push: - self.viewSuperview?.insertSubview(topView, belowSubview: topView) + self.container.insertSubnode(topNode, belowSubnode: topNode) case .Pop: - self.viewSuperview?.insertSubview(bottomView, belowSubview: topView) + self.container.insertSubnode(bottomNode, belowSubnode: topNode) } - self.viewSuperview?.insertSubview(self.dimView, belowSubview: topView) - self.viewSuperview?.insertSubview(self.shadowView, belowSubview: dimView) + self.container.insertSubnode(self.dimNode, belowSubnode: topNode) + self.container.insertSubnode(self.shadowNode, belowSubnode: dimNode) self.maybeCreateNavigationBarTransition() - self.updateProgress(transition: .immediate) + self.updateProgress(0.0, transition: .immediate, completion: {}) } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - func updateProgress(transition: ContainedViewLayoutTransition) { + func updateProgress(_ progress: CGFloat, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) { + self._progress = progress + let position: CGFloat switch self.transition { case .Push: @@ -104,19 +98,25 @@ class NavigationTransitionCoordinator { let containerSize = self.container.bounds.size - self.topView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels(position * containerSize.width), y: 0.0), size: containerSize) - self.dimView.frame = CGRect(origin: CGPoint(x: 0.0, y: dimInset), size: CGSize(width: max(0.0, self.topView.frame.minX), height: self.container.bounds.size.height - dimInset)) - self.shadowView.frame = CGRect(origin: CGPoint(x: self.dimView.frame.maxX - shadowWidth, y: dimInset), size: CGSize(width: shadowWidth, height: containerSize.height - dimInset)) - self.dimView.alpha = (1.0 - position) * 0.15 - self.shadowView.alpha = (1.0 - position) * 0.9 - self.bottomView.frame = CGRect(origin: CGPoint(x: ((position - 1.0) * containerSize.width * 0.3), y: 0.0), size: containerSize) + let topFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(position * containerSize.width), y: 0.0), size: containerSize) + let bottomFrame = CGRect(origin: CGPoint(x: ((position - 1.0) * containerSize.width * 0.3), y: 0.0), size: containerSize) - self.updateNavigationBarTransition() + transition.updateFrame(node: self.topNode, frame: topFrame, completion: { _ in + completion() + }) + transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(x: 0.0, y: dimInset), size: CGSize(width: max(0.0, topFrame.minX), height: self.container.bounds.size.height - dimInset))) + transition.updateFrame(node: self.shadowNode, frame: CGRect(origin: CGPoint(x: self.dimNode.frame.maxX - shadowWidth, y: dimInset), size: CGSize(width: shadowWidth, height: containerSize.height - dimInset))) + transition.updateAlpha(node: self.dimNode, alpha: (1.0 - position) * 0.15) + transition.updateAlpha(node: self.shadowNode, alpha: (1.0 - position) * 0.9) - self.didUpdateProgress?(self.progress, transition) + transition.updateFrame(node: self.bottomNode, frame: bottomFrame) + + self.updateNavigationBarTransition(transition: transition) + + self.didUpdateProgress?(self.progress, transition, topFrame, bottomFrame) } - func updateNavigationBarTransition() { + func updateNavigationBarTransition(transition: ContainedViewLayoutTransition) { if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar, self.inlineNavigationBarTransition { let position: CGFloat switch self.transition { @@ -126,8 +126,10 @@ class NavigationTransitionCoordinator { position = progress } - topNavigationBar.transitionState = NavigationBarTransitionState(navigationBar: bottomNavigationBar, transition: self.transition, role: .top, progress: position) - bottomNavigationBar.transitionState = NavigationBarTransitionState(navigationBar: topNavigationBar, transition: self.transition, role: .bottom, progress: position) + transition.animateView { + topNavigationBar.transitionState = NavigationBarTransitionState(navigationBar: bottomNavigationBar, transition: self.transition, role: .top, progress: position) + bottomNavigationBar.transitionState = NavigationBarTransitionState(navigationBar: topNavigationBar, transition: self.transition, role: .bottom, progress: position) + } } } @@ -156,45 +158,36 @@ class NavigationTransitionCoordinator { func animateCancel(_ completion: @escaping () -> ()) { self.currentCompletion = completion - UIView.animate(withDuration: 0.1, delay: 0.0, options: UIView.AnimationOptions(), animations: { () -> Void in - self.progress = 0.0 - }) { (completed) -> Void in - switch self.transition { - case .Push: - if let viewSuperview = self.viewSuperview { - viewSuperview.addSubview(self.bottomView) - } else { - self.bottomView.removeFromSuperview() - } - self.topView.removeFromSuperview() - case .Pop: - if let viewSuperview = self.viewSuperview { - viewSuperview.addSubview(self.topView) - } else { - self.topView.removeFromSuperview() - } - self.bottomView.removeFromSuperview() + self.updateProgress(0.0, transition: .animated(duration: 0.1, curve: .easeInOut), completion: { [weak self] in + guard let strongSelf = self else { + return + } + switch strongSelf.transition { + case .Push: + strongSelf.topNode.removeFromSupernode() + case .Pop: + strongSelf.bottomNode.removeFromSupernode() } - self.dimView.removeFromSuperview() - self.shadowView.removeFromSuperview() + strongSelf.dimNode.removeFromSupernode() + strongSelf.shadowNode.removeFromSupernode() - self.endNavigationBarTransition() + strongSelf.endNavigationBarTransition() - if let currentCompletion = self.currentCompletion { - self.currentCompletion = nil + if let currentCompletion = strongSelf.currentCompletion { + strongSelf.currentCompletion = nil currentCompletion() } - } + }) } func complete() { self.animatingCompletion = true - self.progress = 1.0 + self._progress = 1.0 - self.dimView.removeFromSuperview() - self.shadowView.removeFromSuperview() + self.dimNode.removeFromSupernode() + self.shadowNode.removeFromSupernode() self.endNavigationBarTransition() @@ -224,8 +217,8 @@ class NavigationTransitionCoordinator { } }*/ - self.dimView.removeFromSuperview() - self.shadowView.removeFromSuperview() + self.dimNode.removeFromSupernode() + self.shadowNode.removeFromSupernode() self.endNavigationBarTransition() @@ -236,17 +229,13 @@ class NavigationTransitionCoordinator { } if abs(velocity) < CGFloat.ulpOfOne && abs(self.progress) < CGFloat.ulpOfOne { - UIView.animate(withDuration: 0.5, delay: 0.0, options: UIView.AnimationOptions(rawValue: 7 << 16), animations: { - self.progress = 1.0 - }, completion: { _ in + self.updateProgress(1.0, transition: .animated(duration: 0.5, curve: .spring), completion: { f() }) } else { - UIView.animate(withDuration: Double(max(0.05, min(0.2, abs(distance / velocity)))), delay: 0.0, options:UIView.AnimationOptions(), animations: { () -> Void in - self.progress = 1.0 - }) { (completed) -> Void in + self.updateProgress(1.0, transition: .animated(duration: Double(max(0.05, min(0.2, abs(distance / velocity)))), curve: .easeInOut), completion: { f() - } + }) } } } diff --git a/submodules/Display/Display/Spring.swift b/submodules/Display/Display/Spring.swift index 169ed107db..ce4a55adf8 100644 --- a/submodules/Display/Display/Spring.swift +++ b/submodules/Display/Display/Spring.swift @@ -57,7 +57,7 @@ private func getTForX(_ x: CGFloat, _ x1: CGFloat, _ x2: CGFloat) -> CGFloat { return t } -func bezierPoint(_ x1: CGFloat, _ y1: CGFloat, _ x2: CGFloat, _ y2: CGFloat, _ x: CGFloat) -> CGFloat +public func bezierPoint(_ x1: CGFloat, _ y1: CGFloat, _ x2: CGFloat, _ y2: CGFloat, _ x: CGFloat) -> CGFloat { var value = calcBezier(getTForX(x, x1, x2), y1, y2) if value >= 0.997 { diff --git a/submodules/Display/Display/UIViewController+Navigation.h b/submodules/Display/Display/UIViewController+Navigation.h index 9c3f5dc007..ed78c4f164 100644 --- a/submodules/Display/Display/UIViewController+Navigation.h +++ b/submodules/Display/Display/UIViewController+Navigation.h @@ -21,6 +21,7 @@ typedef NS_OPTIONS(NSUInteger, UIResponderDisableAutomaticKeyboardHandling) { @interface UIView (Navigation) @property (nonatomic) bool disablesInteractiveTransitionGestureRecognizer; +@property (nonatomic) bool disablesInteractiveKeyboardGestureRecognizer; @property (nonatomic, copy) bool (^ disablesInteractiveTransitionGestureRecognizerNow)(); @property (nonatomic) UIResponderDisableAutomaticKeyboardHandling disableAutomaticKeyboardHandling; diff --git a/submodules/Display/Display/UIViewController+Navigation.m b/submodules/Display/Display/UIViewController+Navigation.m index d08b6a9780..09a327f821 100644 --- a/submodules/Display/Display/UIViewController+Navigation.m +++ b/submodules/Display/Display/UIViewController+Navigation.m @@ -35,6 +35,7 @@ static const void *UIViewControllerNavigationControllerKey = &UIViewControllerNa static const void *UIViewControllerPresentingControllerKey = &UIViewControllerPresentingControllerKey; static const void *UIViewControllerPresentingProxyControllerKey = &UIViewControllerPresentingProxyControllerKey; static const void *disablesInteractiveTransitionGestureRecognizerKey = &disablesInteractiveTransitionGestureRecognizerKey; +static const void *disablesInteractiveKeyboardGestureRecognizerKey = &disablesInteractiveKeyboardGestureRecognizerKey; static const void *disablesInteractiveTransitionGestureRecognizerNowKey = &disablesInteractiveTransitionGestureRecognizerNowKey; static const void *disableAutomaticKeyboardHandlingKey = &disableAutomaticKeyboardHandlingKey; static const void *setNeedsStatusBarAppearanceUpdateKey = &setNeedsStatusBarAppearanceUpdateKey; @@ -233,6 +234,14 @@ static bool notyfyingShiftState = false; [self setAssociatedObject:@(disablesInteractiveTransitionGestureRecognizer) forKey:disablesInteractiveTransitionGestureRecognizerKey]; } +- (bool)disablesInteractiveKeyboardGestureRecognizer { + return [[self associatedObjectForKey:disablesInteractiveKeyboardGestureRecognizerKey] boolValue]; +} + +- (void)setDisablesInteractiveKeyboardGestureRecognizer:(bool)disablesInteractiveKeyboardGestureRecognizer { + [self setAssociatedObject:@(disablesInteractiveKeyboardGestureRecognizer) forKey:disablesInteractiveKeyboardGestureRecognizerKey]; +} + - (bool (^)())disablesInteractiveTransitionGestureRecognizerNow { return [self associatedObjectForKey:disablesInteractiveTransitionGestureRecognizerNowKey]; } diff --git a/submodules/Display/Display/WindowContent.swift b/submodules/Display/Display/WindowContent.swift index b592479516..8a2562fd69 100644 --- a/submodules/Display/Display/WindowContent.swift +++ b/submodules/Display/Display/WindowContent.swift @@ -129,6 +129,9 @@ public func doesViewTreeDisableInteractiveTransitionGestureRecognizer(_ view: UI if view.disablesInteractiveTransitionGestureRecognizer { return true } + if view.disablesInteractiveKeyboardGestureRecognizer { + return true + } if let f = view.disablesInteractiveTransitionGestureRecognizerNow, f() { return true } @@ -279,6 +282,7 @@ public class Window1 { private let statusBarHost: StatusBarHost? private let statusBarManager: StatusBarManager? private let keyboardManager: KeyboardManager? + private let keyboardViewManager: KeyboardViewManager? private var statusBarChangeObserver: AnyObject? private var keyboardRotationChangeObserver: AnyObject? private var keyboardFrameChangeObserver: AnyObject? @@ -344,10 +348,12 @@ public class Window1 { statusBarHeight = statusBarHost.statusBarFrame.size.height self.statusBarManager = StatusBarManager(host: statusBarHost, volumeControlStatusBar: self.volumeControlStatusBar, volumeControlStatusBarNode: self.volumeControlStatusBarNode) self.keyboardManager = KeyboardManager(host: statusBarHost) + self.keyboardViewManager = KeyboardViewManager(host: statusBarHost) } else { statusBarHeight = self.deviceMetrics.statusBarHeight self.statusBarManager = nil self.keyboardManager = nil + self.keyboardViewManager = nil } let isLandscape = boundsSize.width > boundsSize.height @@ -692,7 +698,7 @@ public class Window1 { if let rootController = self._rootController { if let rootController = rootController as? NavigationController { rootController.statusBarHost = self.statusBarHost - rootController.keyboardManager = self.keyboardManager + rootController.keyboardViewManager = self.keyboardViewManager } if !self.windowLayout.size.width.isZero && !self.windowLayout.size.height.isZero { rootController.displayNode.frame = CGRect(origin: CGPoint(), size: self.windowLayout.size) diff --git a/submodules/MtProtoKit/TON/TON.h b/submodules/MtProtoKit/TON/TON.h index 18d6b5585a..79084ea377 100644 --- a/submodules/MtProtoKit/TON/TON.h +++ b/submodules/MtProtoKit/TON/TON.h @@ -78,16 +78,12 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithKeystoreDirectory:(NSString *)keystoreDirectory config:(NSString *)config performExternalRequest:(void (^)(TONExternalRequest * _Nonnull))performExternalRequest; - (MTSignal *)createKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword; -- (MTSignal *)getTestWalletAccountAddressWithPublicKey:(NSString *)publicKey; -- (MTSignal *)getTestGiverAccountState; -- (MTSignal *)getTestGiverAddress; -- (MTSignal *)testGiverSendGramsWithAccountState:(TONAccountState *)accountState accountAddress:(NSString *)accountAddress amount:(int64_t)amount; +- (MTSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey; - (MTSignal *)getAccountStateWithAddress:(NSString *)accountAddress; - (MTSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSString *)textMessage; - (MTSignal *)exportKey:(TONKey *)key localPassword:(NSData *)localPassword; - (MTSignal *)importKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword wordList:(NSArray *)wordList; -- (MTSignal *)deleteKeyWithPublicKey:(NSString *)publicKey; -- (MTSignal *)makeWalletInitialized:(TONKey *)key localPassword:(NSData *)localPassword; +- (MTSignal *)deleteKey:(TONKey *)key; - (MTSignal *)getTransactionListWithAddress:(NSString * _Nonnull)address lt:(int64_t)lt hash:(NSData * _Nonnull)hash; @end diff --git a/submodules/MtProtoKit/TON/TON.mm b/submodules/MtProtoKit/TON/TON.mm index 35f14ea149..6c483c6c9e 100644 --- a/submodules/MtProtoKit/TON/TON.mm +++ b/submodules/MtProtoKit/TON/TON.mm @@ -353,11 +353,11 @@ typedef enum { }] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]]; } -- (MTSignal *)getTestWalletAccountAddressWithPublicKey:(NSString *)publicKey { +- (MTSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey { return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) { NSData *publicKeyData = [publicKey dataUsingEncoding:NSUTF8StringEncoding]; if (publicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in getTestWalletAccountAddressWithPublicKey"]]; + [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in getWalletAccountAddressWithPublicKey"]]; return [[MTBlockDisposable alloc] initWithBlock:^{}]; } @@ -377,8 +377,8 @@ typedef enum { } }]; - auto query = make_object( - make_object( + auto query = make_object( + make_object( makeString(publicKeyData) ) ); @@ -389,89 +389,6 @@ typedef enum { }] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]]; } -- (MTSignal *)getTestGiverAccountState { - return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(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(object); - TONTransactionId *lastTransactionId = nil; - if (result->last_transaction_id_ != nullptr) { - lastTransactionId = [[TONTransactionId alloc] initWithLt:result->last_transaction_id_->lt_ transactionHash:makeData(result->last_transaction_id_->hash_)]; - } - [subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->balance_ seqno:result->seqno_ lastTransactionId:lastTransactionId syncUtime:result->sync_utime_]]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - auto query = make_object(); - _client->send({ requestId, std::move(query) }); - - return [[MTBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]]; -} - -- (MTSignal *)getTestGiverAddress { - return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::accountAddress::ID) { - auto result = tonlib_api::move_object_as(object); - [subscriber putNext:[[NSString alloc] initWithUTF8String:result->account_address_.c_str()]]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - auto query = make_object(); - _client->send({ requestId, std::move(query) }); - - return [[MTBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]]; -} - -- (MTSignal *)testGiverSendGramsWithAccountState:(TONAccountState *)accountState accountAddress:(NSString *)accountAddress amount:(int64_t)amount { - return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else { - [subscriber putCompletion]; - } - }]; - - auto query = make_object(make_object( - accountAddress.UTF8String), - accountState.seqno, - amount, - std::string() - ); - _client->send({ requestId, std::move(query) }); - - return [[MTBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]]; -} - - (MTSignal *)getAccountStateWithAddress:(NSString *)accountAddress { return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) { uint64_t requestId = _nextRequestId; @@ -489,16 +406,8 @@ typedef enum { } [subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:false balance:result->account_state_->balance_ seqno:-1 lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]]; [subscriber putCompletion]; - } else if (object->get_id() == tonlib_api::generic_accountStateTestWallet::ID) { - auto result = tonlib_api::move_object_as(object); - TONTransactionId *lastTransactionId = nil; - if (result->account_state_->last_transaction_id_ != nullptr) { - lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)]; - } - [subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]]; - [subscriber putCompletion]; - } else if (object->get_id() == tonlib_api::generic_accountStateTestGiver::ID) { - auto result = tonlib_api::move_object_as(object); + } else if (object->get_id() == tonlib_api::generic_accountStateWallet::ID) { + auto result = tonlib_api::move_object_as(object); TONTransactionId *lastTransactionId = nil; if (result->account_state_->last_transaction_id_ != nullptr) { lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)]; @@ -611,42 +520,6 @@ typedef enum { }] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]]; } -- (MTSignal *)makeWalletInitialized:(TONKey *)key localPassword:(NSData *)localPassword { - return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) { - NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding]; - if (publicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in exportKey"]]; - return [[MTBlockDisposable alloc] initWithBlock:^{}]; - } - - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else { - [subscriber putCompletion]; - } - }]; - - auto query = make_object( - make_object( - make_object( - makeString(publicKeyData), - makeSecureString(key.secret) - ), - makeSecureString(localPassword) - ) - ); - _client->send({ requestId, std::move(query) }); - - return [[MTBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]]; -} - - (MTSignal *)importKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword wordList:(NSArray *)wordList { return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) { uint64_t requestId = _nextRequestId; @@ -688,11 +561,11 @@ typedef enum { }] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]]; } -- (MTSignal *)deleteKeyWithPublicKey:(NSString *)publicKey { +- (MTSignal *)deleteKey:(TONKey *)key { return [[[[MTSignal alloc] initWithGenerator:^id(MTSubscriber *subscriber) { - NSData *publicKeyData = [publicKey dataUsingEncoding:NSUTF8StringEncoding]; + NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding]; if (publicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in deleteKeyWithPublicKey"]]; + [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in deleteKey"]]; return [[MTBlockDisposable alloc] initWithBlock:^{}]; } @@ -709,7 +582,10 @@ typedef enum { }]; auto query = make_object( - makeString(publicKeyData) + make_object( + makeString(publicKeyData), + makeSecureString(key.secret) + ) ); _client->send({ requestId, std::move(query) }); diff --git a/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.xcodeproj/xcshareddata/xcschemes/SwiftSignalKit.xcscheme b/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.xcodeproj/xcshareddata/xcschemes/SwiftSignalKit.xcscheme index 843e7441be..c82fe8764f 100644 --- a/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.xcodeproj/xcshareddata/xcschemes/SwiftSignalKit.xcscheme +++ b/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.xcodeproj/xcshareddata/xcschemes/SwiftSignalKit.xcscheme @@ -29,6 +29,8 @@ shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + + + deliverOnMainQueue).start(next: { wallets in - if let tonContext = context.tonContext { - if !wallets.wallets.isEmpty { - let _ = (testGiverWalletAddress(tonInstance: tonContext.instance) - |> deliverOnMainQueue).start(next: { address in - arguments.pushController(WalletInfoScreen(context: context, tonContext: tonContext, walletInfo: wallets.wallets[0].info, address: address)) - }) - } - } - }) - }) - case let .getGrams(theme): - return ItemListActionItem(theme: theme, title: "Update Wallet", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { - guard let context = arguments.context else { - return - } - let _ = (availableWallets(postbox: context.account.postbox) - |> deliverOnMainQueue).start(next: { wallets in - if let tonContext = context.tonContext { - if !wallets.wallets.isEmpty { - let _ = (walletAddress(publicKey: wallets.wallets[0].info.publicKey, tonInstance: tonContext.instance) - |> deliverOnMainQueue).start(next: { address in - let _ = (getGramsFromTestGiver(address: address, amount: 1500000000, tonInstance: tonContext.instance) - |> deliverOnMainQueue).start(completed: { - let presentationData = arguments.sharedContext.currentPresentationData.with { $0 } - let controller = OverlayStatusController(theme: presentationData.theme, strings: presentationData.strings, type: .success) - arguments.presentController(controller, nil) - }) - }) - } - } - }) - }) case let .optimizeDatabase(theme): return ItemListActionItem(theme: theme, title: "Optimize Database", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { guard let context = arguments.context else { @@ -599,8 +552,6 @@ private func debugControllerEntries(presentationData: PresentationData, loggingS entries.append(.resetData(presentationData.theme)) entries.append(.resetDatabase(presentationData.theme)) entries.append(.resetHoles(presentationData.theme)) - entries.append(.openDebugWallet(presentationData.theme)) - entries.append(.getGrams(presentationData.theme)) entries.append(.optimizeDatabase(presentationData.theme)) entries.append(.photoPreview(presentationData.theme, experimentalSettings.chatListPhotos)) entries.append(.knockoutWallpaper(presentationData.theme, experimentalSettings.knockoutWallpaper)) diff --git a/submodules/TelegramCore/TelegramCore/Wallets.swift b/submodules/TelegramCore/TelegramCore/Wallets.swift index b216bb67e0..b198a21183 100644 --- a/submodules/TelegramCore/TelegramCore/Wallets.swift +++ b/submodules/TelegramCore/TelegramCore/Wallets.swift @@ -186,7 +186,7 @@ public final class TonInstance { self.impl.with { impl in impl.withInstance { ton in - let cancel = ton.getTestWalletAccountAddress(withPublicKey: publicKey.rawValue).start(next: { address in + let cancel = ton.getWalletAccountAddress(withPublicKey: publicKey.rawValue).start(next: { address in guard let address = address as? String else { return } @@ -205,32 +205,7 @@ public final class TonInstance { } } - fileprivate func testGiverWalletAddress() -> Signal { - return Signal { subscriber in - let disposable = MetaDisposable() - - self.impl.with { impl in - impl.withInstance { ton in - let cancel = ton.getTestGiverAddress().start(next: { address in - guard let address = address as? String else { - return - } - subscriber.putNext(address) - subscriber.putCompletion() - }, error: { _ in - }, completed: { - }) - disposable.set(ActionDisposable { - cancel?.dispose() - }) - } - } - - return disposable - } - } - - private func getWalletStateRaw(address: String) -> Signal { + private func getWalletStateRaw(address: String) -> Signal { return Signal { subscriber in let disposable = MetaDisposable() @@ -242,6 +217,7 @@ public final class TonInstance { } subscriber.putNext(state) }, error: { _ in + subscriber.putError(.generic) }, completed: { subscriber.putCompletion() }) @@ -255,7 +231,7 @@ public final class TonInstance { } } - fileprivate func getWalletState(address: String) -> Signal<(WalletState, Int64), NoError> { + fileprivate func getWalletState(address: String) -> Signal<(WalletState, Int64), GetWalletStateError> { return self.getWalletStateRaw(address: address) |> map { state in return (WalletState(balance: state.balance, lastTransactionId: state.lastTransactionId.flatMap(WalletTransactionId.init(tonTransactionId:))), state.syncUtime) @@ -314,40 +290,20 @@ public final class TonInstance { } } - fileprivate func getTestGiverAccountState() -> Signal { - return Signal { subscriber in - let disposable = MetaDisposable() - - self.impl.with { impl in - impl.withInstance { ton in - let cancel = ton.getTestGiverAccountState().start(next: { state in - subscriber.putNext(state as? TONAccountState) - subscriber.putCompletion() - }, error: { _ in - subscriber.putNext(nil) - subscriber.putCompletion() - }, completed: { - }) - } - } - - return disposable + fileprivate func sendGramsFromWallet(keychain: TonKeychain, serverSalt: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: String) -> Signal { + return keychain.decrypt(walletInfo.encryptedSecret) + |> mapError { _ -> SendGramsFromWalletError in + return .secretDecryptionFailed } - } - - fileprivate func getGramsFromTestGiver(address: String, amount: Int64) -> Signal { - return self.getTestGiverAccountState() - |> castError(GetGramsFromTestGiverError.self) - |> mapToSignal { state in - guard let state = state else { - return .fail(.generic) - } + |> mapToSignal { decryptedSecret -> Signal in + let key = TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret) return Signal { subscriber in let disposable = MetaDisposable() self.impl.with { impl in impl.withInstance { ton in - let cancel = ton.testGiverSendGrams(with: state, accountAddress: address, amount: amount).start(next: { _ in + let cancel = ton.sendGrams(from: key, localPassword: serverSalt, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage).start(next: { _ in + preconditionFailure() }, error: { _ in subscriber.putError(.generic) }, completed: { @@ -364,104 +320,6 @@ public final class TonInstance { } } - private enum MakeWalletInitializedError { - case generic - } - - private func makeWalletInitialized(key: TONKey, serverSalt: Data) -> Signal { - return Signal { subscriber in - let disposable = MetaDisposable() - - self.impl.with { impl in - impl.withInstance { ton in - let cancel = ton.makeWalletInitialized(key, localPassword: serverSalt).start(next: { _ in - preconditionFailure() - }, error: { _ in - subscriber.putError(.generic) - }, completed: { - subscriber.putCompletion() - }) - disposable.set(ActionDisposable { - cancel?.dispose() - }) - } - } - - return disposable - } - } - - private func ensureWalletInitialized(address: String, key: TONKey, serverSalt: Data) -> Signal { - return self.getWalletStateRaw(address: address) - |> castError(MakeWalletInitializedError.self) - |> mapToSignal { state -> Signal in - if state.isInitialized { - return .complete() - } else { - let poll: Signal = self.getWalletStateRaw(address: address) - |> castError(MakeWalletInitializedError.self) - |> mapToSignal { state -> Signal in - if state.isInitialized { - return .single(Void()) - } else { - return .complete() - } - } - - let pollUntilInitialized = ( - poll - |> then(.complete() - |> delay(2.0, queue: Queue.concurrentDefaultQueue())) - ) - |> restart - |> take(1) - - return self.makeWalletInitialized(key: key, serverSalt: serverSalt) - |> then( - pollUntilInitialized - |> ignoreValues - ) - } - } - } - - fileprivate func sendGramsFromWallet(keychain: TonKeychain, serverSalt: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: String) -> Signal { - return keychain.decrypt(walletInfo.encryptedSecret) - |> mapError { _ -> SendGramsFromWalletError in - return .secretDecryptionFailed - } - |> mapToSignal { decryptedSecret -> Signal in - let key = TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret) - - return self.ensureWalletInitialized(address: fromAddress, key: key, serverSalt: serverSalt) - |> mapError { _ -> SendGramsFromWalletError in - return .generic - } - |> then( - Signal { subscriber in - let disposable = MetaDisposable() - - self.impl.with { impl in - impl.withInstance { ton in - let cancel = ton.sendGrams(from: key, localPassword: serverSalt, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage).start(next: { _ in - preconditionFailure() - }, error: { _ in - subscriber.putError(.generic) - }, completed: { - subscriber.putCompletion() - }) - disposable.set(ActionDisposable { - cancel?.dispose() - }) - } - } - - return disposable - } - ) - } - } - fileprivate func walletRestoreWords(walletInfo: WalletInfo, keychain: TonKeychain, serverSalt: Data) -> Signal<[String], WalletRestoreWordsError> { return keychain.decrypt(walletInfo.encryptedSecret) |> mapError { _ -> WalletRestoreWordsError in @@ -494,6 +352,35 @@ public final class TonInstance { } } } + + fileprivate func deleteLocalWalletData(walletInfo: WalletInfo, keychain: TonKeychain, serverSalt: Data) -> Signal { + return keychain.decrypt(walletInfo.encryptedSecret) + |> mapError { _ -> DeleteLocalWalletDataError in + return .secretDecryptionFailed + } + |> mapToSignal { decryptedSecret -> Signal in + return Signal { subscriber in + let disposable = MetaDisposable() + + self.impl.with { impl in + impl.withInstance { ton in + let cancel = ton.delete(TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret)).start(next: { _ in + assertionFailure() + }, error: { _ in + subscriber.putError(.generic) + }, completed: { + subscriber.putCompletion() + }) + disposable.set(ActionDisposable { + cancel?.dispose() + }) + } + } + + return disposable + } + } + } } public struct WalletPublicKey: Codable, Hashable { @@ -663,15 +550,35 @@ public func importWallet(postbox: Postbox, network: Network, tonInstance: TonIns } } -public func debugDeleteWallets(postbox: Postbox) -> Signal { - return postbox.transaction { transaction -> Void in - transaction.updatePreferencesEntry(key: PreferencesKeys.walletCollection, { current in - var walletCollection = (current as? WalletCollection) ?? WalletCollection(wallets: []) - walletCollection.wallets = [] - return walletCollection - }) +public enum DeleteLocalWalletDataError { + case generic + case secretDecryptionFailed +} + +public func deleteLocalWalletData(postbox: Postbox, network: Network, tonInstance: TonInstance, keychain: TonKeychain, walletInfo: WalletInfo) -> Signal { + return getServerWalletSalt(network: network) + |> mapError { _ -> DeleteLocalWalletDataError in + return .generic + } + |> mapToSignal { serverSalt -> Signal in + return tonInstance.deleteLocalWalletData(walletInfo: walletInfo, keychain: keychain, serverSalt: serverSalt) + |> then( + postbox.transaction { transaction -> Void in + transaction.updatePreferencesEntry(key: PreferencesKeys.walletCollection, { current in + var walletCollection = (current as? WalletCollection) ?? WalletCollection(wallets: []) + for i in 0 ..< walletCollection.wallets.count { + if walletCollection.wallets[i].info.publicKey == walletInfo.publicKey { + walletCollection.wallets.remove(at: i) + break + } + } + return walletCollection + }) + } + |> castError(DeleteLocalWalletDataError.self) + |> ignoreValues + ) } - |> ignoreValues } public enum WalletRestoreWordsError { @@ -703,11 +610,11 @@ public func walletAddress(publicKey: WalletPublicKey, tonInstance: TonInstance) return tonInstance.walletAddress(publicKey: publicKey) } -public func testGiverWalletAddress(tonInstance: TonInstance) -> Signal { - return tonInstance.testGiverWalletAddress() +private enum GetWalletStateError { + case generic } -private func getWalletState(address: String, tonInstance: TonInstance) -> Signal<(WalletState, Int64), NoError> { +private func getWalletState(address: String, tonInstance: TonInstance) -> Signal<(WalletState, Int64), GetWalletStateError> { return tonInstance.getWalletState(address: address) } @@ -738,7 +645,9 @@ public func getCombinedWalletState(postbox: Postbox, walletInfo: WalletInfo, ton |> castError(GetCombinedWalletStateError.self) |> mapToSignal { address -> Signal in return getWalletState(address: address, tonInstance: tonInstance) - |> castError(GetCombinedWalletStateError.self) + |> mapError { _ -> GetCombinedWalletStateError in + return .generic + } |> mapToSignal { walletState, syncUtime -> Signal in let topTransactions: Signal<[WalletTransaction], GetCombinedWalletStateError> if walletState.lastTransactionId == cachedState?.walletState.lastTransactionId { @@ -772,14 +681,6 @@ public func getCombinedWalletState(postbox: Postbox, walletInfo: WalletInfo, ton } } -public enum GetGramsFromTestGiverError { - case generic -} - -public func getGramsFromTestGiver(address: String, amount: Int64, tonInstance: TonInstance) -> Signal { - return tonInstance.getGramsFromTestGiver(address: address, amount: amount) -} - public enum SendGramsFromWalletError { case generic case secretDecryptionFailed diff --git a/submodules/TelegramUI/Images.xcassets/Wallet/RefreshIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Wallet/RefreshIcon.imageset/Contents.json new file mode 100644 index 0000000000..f35b36343a --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Wallet/RefreshIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "􀊯 2.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Wallet/RefreshIcon.imageset/􀊯 2.pdf b/submodules/TelegramUI/Images.xcassets/Wallet/RefreshIcon.imageset/􀊯 2.pdf new file mode 100644 index 0000000000..d557394c0a Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Wallet/RefreshIcon.imageset/􀊯 2.pdf differ diff --git a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift index 4ccaa6a4e9..a78fafa318 100644 --- a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift @@ -600,7 +600,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var effectiveInputNodeHeight: CGFloat? if let inputNodeHeightAndOverflow = inputNodeHeightAndOverflow { if let upperInputPositionBound = self.upperInputPositionBound { - effectiveInputNodeHeight = min(layout.size.height - max(0.0, upperInputPositionBound), inputNodeHeightAndOverflow.0) + effectiveInputNodeHeight = max(0.0, min(layout.size.height - max(0.0, upperInputPositionBound), inputNodeHeightAndOverflow.0)) } else { effectiveInputNodeHeight = inputNodeHeightAndOverflow.0 } diff --git a/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/SendingGrams.tgs b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/SendingGrams.tgs new file mode 100644 index 0000000000..9876c9658e Binary files /dev/null and b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/SendingGrams.tgs differ diff --git a/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletCreated.tgs b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletCreated.tgs new file mode 100644 index 0000000000..f5bac9d80b Binary files /dev/null and b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletCreated.tgs differ diff --git a/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletEmpty.tgs b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletEmpty.tgs new file mode 100644 index 0000000000..b33b54599f Binary files /dev/null and b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletEmpty.tgs differ diff --git a/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletIntroStatic.tgs b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletIntroStatic.tgs new file mode 100644 index 0000000000..63e8e22514 Binary files /dev/null and b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletIntroStatic.tgs differ diff --git a/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletWordCheck.tgs b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletWordCheck.tgs new file mode 100644 index 0000000000..9008fc51e2 Binary files /dev/null and b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletWordCheck.tgs differ diff --git a/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletWordList.tgs b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletWordList.tgs new file mode 100644 index 0000000000..278b1531b6 Binary files /dev/null and b/submodules/TelegramUI/TelegramUI/Resources/WalletAnimations/WalletWordList.tgs differ diff --git a/submodules/WalletUI/Sources/WalletInfoEmptyNode.swift b/submodules/WalletUI/Sources/WalletInfoEmptyNode.swift index e4411116b0..e2b570db60 100644 --- a/submodules/WalletUI/Sources/WalletInfoEmptyNode.swift +++ b/submodules/WalletUI/Sources/WalletInfoEmptyNode.swift @@ -6,15 +6,18 @@ import TelegramPresentationData import TelegramCore import AnimationUI import SwiftSignalKit +import AppBundle class WalletInfoEmptyItem: ListViewItem { + let account: Account let theme: PresentationTheme let strings: PresentationStrings let address: String let selectable: Bool = false - init(theme: PresentationTheme, strings: PresentationStrings, address: String) { + init(account: Account, theme: PresentationTheme, strings: PresentationStrings, address: String) { + self.account = account self.theme = theme self.strings = strings self.address = address @@ -22,7 +25,7 @@ class WalletInfoEmptyItem: ListViewItem { func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { async { - let node = WalletInfoEmptyItemNode() + let node = WalletInfoEmptyItemNode(account: self.account) node.insets = UIEdgeInsets() node.layoutForParams(params, item: self, previousItem: previousItem, nextItem: nextItem) Queue.mainQueue().async { @@ -54,21 +57,20 @@ class WalletInfoEmptyItem: ListViewItem { final class WalletInfoEmptyItemNode: ListViewItemNode { private let offsetContainer: ASDisplayNode - private let iconNode: ASImageNode private let animationNode: AnimatedStickerNode private let titleNode: TextNode private let textNode: TextNode private let addressNode: TextNode - init() { + init(account: Account) { self.offsetContainer = ASDisplayNode() - self.iconNode = ASImageNode() - self.iconNode.displayWithoutProcessing = true - self.iconNode.displaysAsynchronously = false - self.iconNode.image = UIImage(bundleImageName: "Wallet/DuckIcon") - self.animationNode = AnimatedStickerNode() + if let path = getAppBundle().path(forResource: "WalletEmpty", ofType: "tgs") { + self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct) + self.animationNode.visibility = true + } + self.animationNode.visibility = true self.titleNode = TextNode() self.titleNode.displaysAsynchronously = false @@ -79,7 +81,6 @@ final class WalletInfoEmptyItemNode: ListViewItemNode { self.wantsTrailingItemSpaceUpdates = true - self.offsetContainer.addSubnode(self.iconNode) self.offsetContainer.addSubnode(self.animationNode) self.offsetContainer.addSubnode(self.titleNode) self.offsetContainer.addSubnode(self.textNode) @@ -101,8 +102,8 @@ final class WalletInfoEmptyItemNode: ListViewItemNode { let termsSpacing: CGFloat = 11.0 let buttonHeight: CGFloat = 50.0 - let iconSize: CGSize - iconSize = self.iconNode.image?.size ?? CGSize(width: 140.0, height: 140.0) + let iconSize = CGSize(width: 140.0, height: 140.0) + self.animationNode.updateLayout(size: iconSize) let makeTitleLayout = TextNode.asyncLayout(self.titleNode) let makeTextLayout = TextNode.asyncLayout(self.textNode) @@ -145,7 +146,7 @@ final class WalletInfoEmptyItemNode: ListViewItemNode { let transition: ContainedViewLayoutTransition = .immediate - transition.updateFrameAdditive(node: strongSelf.iconNode, frame: iconFrame) + transition.updateFrameAdditive(node: strongSelf.animationNode, frame: iconFrame) strongSelf.animationNode.updateLayout(size: iconFrame.size) transition.updateFrameAdditive(node: strongSelf.animationNode, frame: iconFrame) transition.updateFrameAdditive(node: strongSelf.titleNode, frame: titleFrame) diff --git a/submodules/WalletUI/Sources/WalletInfoScreen.swift b/submodules/WalletUI/Sources/WalletInfoScreen.swift index fd3a253f1c..0ec3c238c6 100644 --- a/submodules/WalletUI/Sources/WalletInfoScreen.swift +++ b/submodules/WalletUI/Sources/WalletInfoScreen.swift @@ -8,63 +8,10 @@ import Display import Postbox import TelegramCore import SolidRoundedButtonNode -import AnimationUI import SwiftSignalKit import MergeLists import TelegramStringFormatting -private func stringForRelativeUpdateTime(strings: PresentationStrings, day: RelativeTimestampFormatDay, dateTimeFormat: PresentationDateTimeFormat, hours: Int32, minutes: Int32) -> String { - let dayString: String - switch day { - case .today: - dayString = strings.Updated_TodayAt(stringForShortTimestamp(hours: hours, minutes: minutes, dateTimeFormat: dateTimeFormat)).0 - case .yesterday: - dayString = strings.Updated_YesterdayAt(stringForShortTimestamp(hours: hours, minutes: minutes, dateTimeFormat: dateTimeFormat)).0 - } - return dayString -} - -private func lastUpdateTimestampString(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, statusTimestamp: Int32, relativeTo timestamp: Int32) -> String { - let difference = timestamp - statusTimestamp - let expanded = true - if difference < 60 { - return strings.Updated_JustNow - } else if difference < 60 * 60 && !expanded { - let minutes = difference / 60 - return strings.Updated_MinutesAgo(minutes) - } else { - var t: time_t = time_t(statusTimestamp) - var timeinfo: tm = tm() - localtime_r(&t, &timeinfo) - - var now: time_t = time_t(timestamp) - var timeinfoNow: tm = tm() - localtime_r(&now, &timeinfoNow) - - if timeinfo.tm_year != timeinfoNow.tm_year { - return strings.Updated_AtDate(stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat)).0 - } - - let dayDifference = timeinfo.tm_yday - timeinfoNow.tm_yday - if dayDifference == 0 || dayDifference == -1 { - let day: RelativeTimestampFormatDay - if dayDifference == 0 { - if expanded { - day = .today - } else { - let minutes = difference / (60 * 60) - return strings.Updated_HoursAgo(minutes) - } - } else { - day = .yesterday - } - return stringForRelativeUpdateTime(strings: strings, day: day, dateTimeFormat: dateTimeFormat, hours: timeinfo.tm_hour, minutes: timeinfo.tm_min) - } else { - return strings.Updated_AtDate(stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat)).0 - } - } -} - public final class WalletInfoScreen: ViewController { private let context: AccountContext private let tonContext: TonContext @@ -132,6 +79,11 @@ public final class WalletInfoScreen: ViewController { return } strongSelf.push(walletTransactionInfoController(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: strongSelf.walletInfo, walletTransaction: transaction)) + }, present: { [weak self] c in + guard let strongSelf = self else { + return + } + strongSelf.present(c, in: .window(.root)) }) self.displayNodeDidLoad() @@ -147,22 +99,39 @@ public final class WalletInfoScreen: ViewController { } private final class WalletInfoBalanceNode: ASDisplayNode { - let balanceTextNode: ImmediateTextNode + let balanceIntegralTextNode: ImmediateTextNode + let balanceFractionalTextNode: ImmediateTextNode let balanceIconNode: ASImageNode var balance: String = " " { didSet { - self.balanceTextNode.attributedText = NSAttributedString(string: self.balance, font: Font.bold(39.0), textColor: .white) + let integralString = NSMutableAttributedString() + let fractionalString = NSMutableAttributedString() + if let range = self.balance.range(of: ".") { + let integralPart = String(self.balance[.. CGFloat { + func update(width: CGFloat, scaleTransition: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat { let sideInset: CGFloat = 16.0 let balanceIconSpacing: CGFloat = 8.0 - let balanceTextSize = self.balanceTextNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: 200.0)) + let balanceIntegralTextSize = self.balanceIntegralTextNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: 200.0)) + let balanceFractionalTextSize = self.balanceFractionalTextNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: 200.0)) let balanceIconSize = self.balanceIconNode.image?.size ?? CGSize(width: 38.0, height: 34.0) - let balanceOrigin = CGPoint(x: floor((width - balanceTextSize.width - balanceIconSpacing - balanceIconSize.width / 2.0) / 2.0), y: 0.0) - let balanceTextFrame = CGRect(origin: balanceOrigin, size: balanceTextSize) + let fractionalScale: CGFloat = scaleTransition * 0.5 + (1.0 - scaleTransition) * 1.0 + + let balanceOrigin = CGPoint(x: floor((width - balanceIntegralTextSize.width - balanceFractionalTextSize.width * fractionalScale - balanceIconSpacing - balanceIconSize.width / 2.0) / 2.0), y: 0.0) + + let balanceIntegralTextFrame = CGRect(origin: balanceOrigin, size: balanceIntegralTextSize) + var balanceFractionalTextFrame = CGRect(origin: CGPoint(x: balanceIntegralTextFrame.maxX, y: balanceIntegralTextFrame.maxY - balanceFractionalTextSize.height), size: balanceFractionalTextSize) + let apparentBalanceFractionalTextFrame = CGRect(origin: balanceFractionalTextFrame.origin, size: CGSize(width: balanceFractionalTextFrame.width * fractionalScale, height: balanceFractionalTextFrame.height * fractionalScale)) + balanceFractionalTextFrame.origin.x -= balanceFractionalTextFrame.width / 2.0 * (1.0 - fractionalScale) + balanceFractionalTextFrame.origin.y += balanceFractionalTextFrame.height / 4.0 * (1.0 - fractionalScale) + let balanceIconFrame: CGRect - balanceIconFrame = CGRect(origin: CGPoint(x: balanceTextFrame.maxX + balanceIconSpacing, y: balanceTextFrame.minY + floor((balanceTextFrame.height - balanceIconSize.height) / 2.0)), size: balanceIconSize) - transition.updateFrameAdditive(node: self.balanceTextNode, frame: balanceTextFrame) + balanceIconFrame = CGRect(origin: CGPoint(x: apparentBalanceFractionalTextFrame.maxX + balanceIconSpacing, y: balanceIntegralTextFrame.minY + floor((balanceIntegralTextFrame.height - balanceIconSize.height) / 2.0)), size: balanceIconSize) + + transition.updateFrameAdditive(node: self.balanceIntegralTextNode, frame: balanceIntegralTextFrame) + transition.updateFrameAsPositionAndBounds(node: self.balanceFractionalTextNode, frame: balanceFractionalTextFrame) + transition.updateTransformScale(node: self.balanceFractionalTextNode, scale: fractionalScale) transition.updateFrame(node: self.balanceIconNode, frame: balanceIconFrame) - return balanceTextSize.height + return balanceIntegralTextSize.height } } private final class WalletInfoHeaderNode: ASDisplayNode { var balance: Int64? var isRefreshing: Bool = false - - var timestampString: String = "" { - didSet { - self.balanceTimestampNode.attributedText = NSAttributedString(string: self.timestampString, font: Font.regular(13), textColor: UIColor(white: 1.0, alpha: 0.6)) - } - } + var timestamp: Int32? let balanceNode: WalletInfoBalanceNode - private let refreshNode: AnimatedStickerNode + private let refreshNode: WalletRefreshNode private let balanceSubtitleNode: ImmediateTextNode - private let balanceTimestampNode: ImmediateTextNode private let receiveButtonNode: SolidRoundedButtonNode private let sendButtonNode: SolidRoundedButtonNode private let headerBackgroundNode: ASImageNode - init(account: Account, theme: PresentationTheme, sendAction: @escaping () -> Void, receiveAction: @escaping () -> Void) { - self.balanceNode = WalletInfoBalanceNode(theme: theme) + init(account: Account, presentationData: PresentationData, sendAction: @escaping () -> Void, receiveAction: @escaping () -> Void) { + self.balanceNode = WalletInfoBalanceNode(theme: presentationData.theme) self.balanceSubtitleNode = ImmediateTextNode() self.balanceSubtitleNode.displaysAsynchronously = false self.balanceSubtitleNode.attributedText = NSAttributedString(string: "your balance", font: Font.regular(13), textColor: UIColor(white: 1.0, alpha: 0.6)) - self.balanceTimestampNode = ImmediateTextNode() - self.balanceTimestampNode.displaysAsynchronously = false - self.balanceTimestampNode.attributedText = NSAttributedString(string: "", font: Font.regular(13), textColor: UIColor(white: 1.0, alpha: 0.6)) - self.headerBackgroundNode = ASImageNode() self.headerBackgroundNode.displaysAsynchronously = false self.headerBackgroundNode.displayWithoutProcessing = true @@ -237,12 +209,7 @@ private final class WalletInfoHeaderNode: ASDisplayNode { self.receiveButtonNode = SolidRoundedButtonNode(title: "Receive", icon: UIImage(bundleImageName: "Wallet/ReceiveButtonIcon"), theme: SolidRoundedButtonTheme(backgroundColor: .white, foregroundColor: .black), height: 50.0, cornerRadius: 10.0, gloss: false) self.sendButtonNode = SolidRoundedButtonNode(title: "Send", icon: UIImage(bundleImageName: "Wallet/SendButtonIcon"), theme: SolidRoundedButtonTheme(backgroundColor: .white, foregroundColor: .black), height: 50.0, cornerRadius: 10.0, gloss: false) - self.refreshNode = AnimatedStickerNode() - self.refreshNode.playToCompletionOnStop = true - self.refreshNode.automaticallyLoadFirstFrame = true - if let path = getAppBundle().path(forResource: "celebrate", ofType: "tgs") { - self.refreshNode.setup(account: account, resource: .localFile(path), width: Int(32.0 * UIScreenScale), height: Int(32.0 * UIScreenScale), mode: .direct) - } + self.refreshNode = WalletRefreshNode(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat) super.init() @@ -251,7 +218,6 @@ private final class WalletInfoHeaderNode: ASDisplayNode { self.addSubnode(self.sendButtonNode) self.addSubnode(self.balanceNode) self.addSubnode(self.balanceSubtitleNode) - self.addSubnode(self.balanceTimestampNode) self.addSubnode(self.refreshNode) self.receiveButtonNode.pressed = { @@ -284,9 +250,10 @@ private final class WalletInfoHeaderNode: ASDisplayNode { let buttonAlpha = buttonTransition * 1.0 let balanceSubtitleSize = self.balanceSubtitleNode.updateLayout(CGSize(width: size.width - sideInset * 2.0, height: 200.0)) - let balanceTimestampSize = self.balanceTimestampNode.updateLayout(CGSize(width: size.width - sideInset * 2.0, height: 200.0)) - let balanceHeight = self.balanceNode.update(width: size.width, transition: transition) + let headerScaleTransition: CGFloat = max(0.0, min(1.0, (effectiveOffset - minHeaderOffset) / (maxHeaderOffset - minHeaderOffset))) + + let balanceHeight = self.balanceNode.update(width: size.width, scaleTransition: headerScaleTransition, transition: transition) let balanceSize = CGSize(width: size.width, height: balanceHeight) let maxHeaderScale: CGFloat = min(1.0, (size.width - 40.0) / balanceSize.width) @@ -296,29 +263,21 @@ private final class WalletInfoHeaderNode: ASDisplayNode { let minHeaderY = navigationHeight - 44.0 + floor((44.0 - minHeaderHeight) / 2.0) let maxHeaderY = floor((size.height - balanceSize.height) / 2.0 - balanceSubtitleSize.height) - let headerScaleTransition: CGFloat = max(0.0, min(1.0, (effectiveOffset - minHeaderOffset) / (maxHeaderOffset - minHeaderOffset))) let headerPositionTransition: CGFloat = max(0.0, (effectiveOffset - minHeaderOffset) / (maxOffset - minHeaderOffset)) let headerY = headerPositionTransition * maxHeaderY + (1.0 - headerPositionTransition) * minHeaderY let headerScale = headerScaleTransition * maxHeaderScale + (1.0 - headerScaleTransition) * minHeaderScale - let refreshSize = CGSize(width: 32.0, height: 32.0) - self.refreshNode.updateLayout(size: refreshSize) + let refreshSize = CGSize(width: 0.0, height: 0.0) transition.updateFrame(node: self.refreshNode, frame: CGRect(origin: CGPoint(x: floor((size.width - refreshSize.width) / 2.0), y: navigationHeight - 44.0 + floor((44.0 - refreshSize.height) / 2.0)), size: refreshSize)) + transition.updateAlpha(node: self.refreshNode, alpha: headerScaleTransition) if self.balance == nil { - transition.updateAlpha(node: self.refreshNode, alpha: 0.0) - transition.updateSublayerTransformScale(node: self.refreshNode, scale: 0.1) - self.refreshNode.visibility = false + self.refreshNode.update(state: .pullToRefresh(self.timestamp ?? 0, 0.0)) } else if self.isRefreshing { - transition.updateAlpha(node: self.refreshNode, alpha: 1.0) - transition.updateSublayerTransformScale(node: self.refreshNode, scale: 1.0) - self.refreshNode.visibility = true + self.refreshNode.update(state: .refreshing) } else { let refreshOffset: CGFloat = 20.0 - let refreshScaleTransition: CGFloat = max(0.0, min(1.0, (offset - maxOffset) / refreshOffset)) - transition.updateAlpha(node: self.refreshNode, alpha: refreshScaleTransition) - let refreshScale: CGFloat = refreshScaleTransition * 1.0 + (1.0 - refreshScaleTransition) * 0.1 - transition.updateSublayerTransformScale(node: self.refreshNode, scale: refreshScale) - self.refreshNode.visibility = false + let refreshScaleTransition: CGFloat = max(0.0, (offset - maxOffset) / refreshOffset) + self.refreshNode.update(state: .pullToRefresh(self.timestamp ?? 0, refreshScaleTransition * 0.25)) } let balanceFrame = CGRect(origin: CGPoint(x: 0.0, y: headerY), size: balanceSize) @@ -328,11 +287,6 @@ private final class WalletInfoHeaderNode: ASDisplayNode { let balanceSubtitleFrame = CGRect(origin: CGPoint(x: floor((size.width - balanceSubtitleSize.width) / 2.0), y: balanceFrame.midY + (balanceFrame.height / 2.0 * headerScale) + balanceSubtitleSpacing), size: balanceSubtitleSize) transition.updateFrameAdditive(node: self.balanceSubtitleNode, frame: balanceSubtitleFrame) - let balanceTimestampFrame = CGRect(origin: CGPoint(x: floor((size.width - balanceTimestampSize.width) / 2.0), y: balanceSubtitleFrame.maxY + 2.0), size: balanceTimestampSize) - transition.updateFrameAdditive(node: self.balanceTimestampNode, frame: balanceTimestampFrame) - - transition.updateAlpha(node: self.balanceTimestampNode, alpha: headerScaleTransition) - let headerHeight: CGFloat = 1000.0 transition.updateFrame(node: self.headerBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: effectiveOffset + 10.0 - headerHeight), size: CGSize(width: size.width, height: headerHeight))) @@ -360,11 +314,11 @@ private final class WalletInfoHeaderNode: ASDisplayNode { if self.balance == nil { self.balanceNode.isHidden = true self.balanceSubtitleNode.isHidden = true - self.balanceTimestampNode.isHidden = true + self.refreshNode.isHidden = true } else { self.balanceNode.isHidden = false self.balanceSubtitleNode.isHidden = false - self.balanceTimestampNode.isHidden = false + self.refreshNode.isHidden = false } transition.updateFrame(node: self.receiveButtonNode, frame: receiveButtonFrame) transition.updateAlpha(node: self.receiveButtonNode, alpha: buttonAlpha) @@ -390,14 +344,10 @@ private final class WalletInfoHeaderNode: ASDisplayNode { self.receiveButtonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.balanceNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.balanceSubtitleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - self.balanceTimestampNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.refreshNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } self.balanceNode.isLoading = false } - - func animateBeganRefreshing() { - //self.refreshNode.layer.animate(from: 0.5 as NSNumber, to: 0.0 as NSNumber, keyPath: "transform.scale", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 0.2, delay: 0.0, removeOnCompletion: true, additive: true) - } } private struct WalletInfoListTransaction { @@ -443,10 +393,10 @@ private enum WalletInfoListEntry: Equatable, Comparable, Identifiable { } } - func item(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, action: @escaping (WalletTransaction) -> Void) -> ListViewItem { + func item(account: Account, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, action: @escaping (WalletTransaction) -> Void) -> ListViewItem { switch self { case let .empty(address): - return WalletInfoEmptyItem(theme: theme, strings: strings, address: address) + return WalletInfoEmptyItem(account: account, theme: theme, strings: strings, address: address) case let .transaction(_, transaction): return WalletInfoTransactionItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, walletTransaction: transaction, action: { action(transaction) @@ -455,12 +405,12 @@ private enum WalletInfoListEntry: Equatable, Comparable, Identifiable { } } -private func preparedTransition(from fromEntries: [WalletInfoListEntry], to toEntries: [WalletInfoListEntry], presentationData: PresentationData, action: @escaping (WalletTransaction) -> Void) -> WalletInfoListTransaction { +private func preparedTransition(from fromEntries: [WalletInfoListEntry], to toEntries: [WalletInfoListEntry], account: Account, presentationData: PresentationData, action: @escaping (WalletTransaction) -> Void) -> WalletInfoListTransaction { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } - let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, action: action), directionHint: nil) } - let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, action: action), directionHint: nil) } + let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, action: action), directionHint: nil) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, action: action), directionHint: nil) } return WalletInfoListTransaction(deletions: deletions, insertions: insertions, updates: updates) } @@ -473,6 +423,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { private let address: String private let openTransaction: (WalletTransaction) -> Void + private let present: (ViewController) -> Void private let hapticFeedback = HapticFeedback() @@ -502,15 +453,16 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { private var updateTimestampTimer: SwiftSignalKit.Timer? - init(account: Account, tonContext: TonContext, presentationData: PresentationData, walletInfo: WalletInfo, address: String, sendAction: @escaping () -> Void, receiveAction: @escaping () -> Void, openTransaction: @escaping (WalletTransaction) -> Void) { + init(account: Account, tonContext: TonContext, presentationData: PresentationData, walletInfo: WalletInfo, address: String, sendAction: @escaping () -> Void, receiveAction: @escaping () -> Void, openTransaction: @escaping (WalletTransaction) -> Void, present: @escaping (ViewController) -> Void) { self.account = account self.tonContext = tonContext self.presentationData = presentationData self.walletInfo = walletInfo self.address = address self.openTransaction = openTransaction + self.present = present - self.headerNode = WalletInfoHeaderNode(account: account, theme: presentationData.theme, sendAction: sendAction, receiveAction: receiveAction) + self.headerNode = WalletInfoHeaderNode(account: account, presentationData: presentationData, sendAction: sendAction, receiveAction: receiveAction) self.listNode = ListView() self.listNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor @@ -521,7 +473,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { super.init() - self.backgroundColor = .white + self.backgroundColor = self.presentationData.theme.list.itemBlocksBackgroundColor self.addSubnode(self.listNode) self.addSubnode(self.headerNode) @@ -548,8 +500,6 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { if !strongSelf.reloadingState && canBeginRefresh && isScrolling { if offset >= headerHeight + 100.0 { canBeginRefresh = false - strongSelf.headerNode.isRefreshing = true - strongSelf.headerNode.animateBeganRefreshing() strongSelf.hapticFeedback.impact() strongSelf.refreshTransactions() } @@ -596,13 +546,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { guard let strongSelf = self, let combinedState = strongSelf.combinedState, !strongSelf.reloadingState else { return } - let string = lastUpdateTimestampString(strings: strongSelf.presentationData.strings, dateTimeFormat: strongSelf.presentationData.dateTimeFormat, statusTimestamp: Int32(clamping: combinedState.timestamp), relativeTo: Int32(Date().timeIntervalSince1970)) - if strongSelf.headerNode.timestampString != string { - strongSelf.headerNode.timestampString = string - if let (layout, navigationHeight) = strongSelf.validLayout { - strongSelf.headerNode.update(size: strongSelf.headerNode.bounds.size, navigationHeight: navigationHeight, offset: strongSelf.listOffset ?? 0.0, transition: .immediate) - } - } + strongSelf.headerNode.timestamp = Int32(clamping: combinedState.timestamp) }, queue: .mainQueue()) self.updateTimestampTimer?.start() } @@ -687,10 +631,9 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { self.loadingMoreTransactions = true self.reloadingState = true - self.headerNode.timestampString = "updating" + self.headerNode.isRefreshing = true self.stateDisposable.set((getCombinedWalletState(postbox: self.account.postbox, walletInfo: self.walletInfo, tonInstance: self.tonContext.instance) - |> delay(self.combinedState == nil ? 0.0 : 2.0, queue: .mainQueue()) |> deliverOnMainQueue).start(next: { [weak self] value in guard let strongSelf = self else { return @@ -698,6 +641,9 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { let combinedState: CombinedWalletState? switch value { case let .cached(state): + if strongSelf.combinedState != nil { + return + } if state == nil { strongSelf.loadingIndicator.startAnimating() } else { @@ -722,7 +668,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { strongSelf.reloadingState = false - strongSelf.headerNode.timestampString = lastUpdateTimestampString(strings: strongSelf.presentationData.strings, dateTimeFormat: strongSelf.presentationData.dateTimeFormat, statusTimestamp: Int32(clamping: combinedState.timestamp), relativeTo: Int32(Date().timeIntervalSince1970)) + strongSelf.headerNode.timestamp = Int32(clamping: combinedState.timestamp) if strongSelf.isReady, let (layout, navigationHeight) = strongSelf.validLayout { strongSelf.headerNode.update(size: strongSelf.headerNode.bounds.size, navigationHeight: navigationHeight, offset: strongSelf.listOffset ?? 0.0, transition: .immediate) @@ -756,6 +702,35 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { guard let strongSelf = self else { return } + + strongSelf.reloadingState = false + + if let combinedState = strongSelf.combinedState { + strongSelf.headerNode.timestamp = Int32(clamping: combinedState.timestamp) + } + + if strongSelf.isReady, let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.headerNode.update(size: strongSelf.headerNode.bounds.size, navigationHeight: navigationHeight, offset: strongSelf.listOffset ?? 0.0, transition: .immediate) + } + + strongSelf.loadingMoreTransactions = false + strongSelf.canLoadMoreTransactions = false + + strongSelf.headerNode.isRefreshing = false + + if strongSelf.isReady, let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.headerNode.update(size: strongSelf.headerNode.bounds.size, navigationHeight: navigationHeight, offset: strongSelf.listOffset ?? 0.0, transition: .animated(duration: 0.2, curve: .easeInOut)) + } + + if !strongSelf.didSetContentReady { + strongSelf.didSetContentReady = true + strongSelf.contentReady.set(.single(true)) + } + + strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: "An Error Occurred", text: "The wallet state can not be retrieved at this time. Please try again later.", actions: [ + TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: { + }) + ], actionLayout: .vertical)) })) } @@ -831,7 +806,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode { } } - let transaction = preparedTransition(from: self.currentEntries ?? [], to: updatedEntries, presentationData: self.presentationData, action: { [weak self] transaction in + let transaction = preparedTransition(from: self.currentEntries ?? [], to: updatedEntries, account: self.account, presentationData: self.presentationData, action: { [weak self] transaction in guard let strongSelf = self else { return } diff --git a/submodules/WalletUI/Sources/WalletInfoTransactionItem.swift b/submodules/WalletUI/Sources/WalletInfoTransactionItem.swift index fbddade9bc..89e138ea3d 100644 --- a/submodules/WalletUI/Sources/WalletInfoTransactionItem.swift +++ b/submodules/WalletUI/Sources/WalletInfoTransactionItem.swift @@ -112,7 +112,6 @@ class WalletInfoTransactionItemNode: ListViewItemNode { init() { self.backgroundNode = ASDisplayNode() self.backgroundNode.isLayerBacked = true - self.backgroundNode.backgroundColor = .white self.topStripeNode = ASDisplayNode() self.topStripeNode.isLayerBacked = true self.bottomStripeNode = ASDisplayNode() @@ -228,7 +227,17 @@ class WalletInfoTransactionItemNode: ListViewItemNode { let (directionLayout, directionApply) = makeDirectionLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: directionText, font: directionFont, textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftInset - 20.0 - dateLayout.size.width - directionLayout.size.width - iconSize.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let titleString = NSMutableAttributedString() + if let range = title.range(of: ".") { + let integralPart = String(title[.. String { + let dayString: String + switch day { + case .today: + dayString = strings.Updated_TodayAt(stringForShortTimestamp(hours: hours, minutes: minutes, dateTimeFormat: dateTimeFormat)).0 + case .yesterday: + dayString = strings.Updated_YesterdayAt(stringForShortTimestamp(hours: hours, minutes: minutes, dateTimeFormat: dateTimeFormat)).0 + } + return dayString +} + +private func lastUpdateTimestampString(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, statusTimestamp: Int32, relativeTo timestamp: Int32) -> String { + let difference = timestamp - statusTimestamp + let expanded = true + if difference < 60 { + return strings.Updated_JustNow + } else if difference < 60 * 60 && !expanded { + let minutes = difference / 60 + return strings.Updated_MinutesAgo(minutes) + } else { + var t: time_t = time_t(statusTimestamp) + var timeinfo: tm = tm() + localtime_r(&t, &timeinfo) + + var now: time_t = time_t(timestamp) + var timeinfoNow: tm = tm() + localtime_r(&now, &timeinfoNow) + + if timeinfo.tm_year != timeinfoNow.tm_year { + return strings.Updated_AtDate(stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat)).0 + } + + let dayDifference = timeinfo.tm_yday - timeinfoNow.tm_yday + if dayDifference == 0 || dayDifference == -1 { + let day: RelativeTimestampFormatDay + if dayDifference == 0 { + if expanded { + day = .today + } else { + let minutes = difference / (60 * 60) + return strings.Updated_HoursAgo(minutes) + } + } else { + day = .yesterday + } + return stringForRelativeUpdateTime(strings: strings, day: day, dateTimeFormat: dateTimeFormat, hours: timeinfo.tm_hour, minutes: timeinfo.tm_min) + } else { + return strings.Updated_AtDate(stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat)).0 + } + } +} + +enum WalletRefreshState: Equatable { + case pullToRefresh(Int32, CGFloat) + case refreshing +} + +final class WalletRefreshNode: ASDisplayNode { + private let strings: PresentationStrings + private let dateTimeFormat: PresentationDateTimeFormat + private let iconContainer: ASDisplayNode + private let iconNode: ASImageNode + private let titleNode: ImmediateTextNode + + private var state: WalletRefreshState? + + private let animator: ConstantDisplayLinkAnimator + + init(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) { + self.strings = strings + self.dateTimeFormat = dateTimeFormat + + self.iconContainer = ASDisplayNode() + + self.iconNode = ASImageNode() + self.iconNode.displaysAsynchronously = false + self.iconNode.displayWithoutProcessing = true + self.iconNode.image = UIImage(bundleImageName: "Wallet/RefreshIcon") + if let image = self.iconNode.image { + self.iconNode.frame = CGRect(origin: CGPoint(), size: image.size) + } + + self.titleNode = ImmediateTextNode() + self.titleNode.displaysAsynchronously = false + + var updateImpl: (() -> Void)? + self.animator = ConstantDisplayLinkAnimator(update: { + updateImpl?() + }) + + super.init() + + self.iconContainer.addSubnode(self.iconNode) + self.addSubnode(self.iconContainer) + self.addSubnode(self.titleNode) + + updateImpl = { [weak self] in + self?.updateAnimation() + } + } + + private var currentAngle: CGFloat = 0.0 + private var currentExtraSpeed: CGFloat = 0.0 + private var animateToZeroState: (Double, CGFloat)? + + private func updateAnimation() { + guard let state = self.state else { + return + } + + var speed: CGFloat = 0.0 + var baseValue: CGFloat = 0.0 + + switch state { + case .refreshing: + speed = 0.01 + self.animateToZeroState = nil + case let .pullToRefresh(_, value): + if self.currentExtraSpeed.isZero && self.animateToZeroState == nil && !self.currentAngle.isZero { + self.animateToZeroState = (CACurrentMediaTime(), self.currentAngle) + } + if self.animateToZeroState == nil { + baseValue = value + } + } + + if let (startTime, startValue) = self.animateToZeroState { + let endValue: CGFloat = floor(startValue) + 1.0 + let duration: Double = Double(endValue - startValue) * 1.0 + let timeDelta = (startTime + duration - CACurrentMediaTime()) + let t: CGFloat = 1.0 - CGFloat(max(0.0, min(1.0, timeDelta / duration))) + if t >= 1.0 - CGFloat.ulpOfOne { + self.animateToZeroState = nil + self.currentAngle = 0.0 + } else { + let bt = bezierPoint(0.23, 1.0, 0.32, 1.0, t) + self.currentAngle = startValue * (1.0 - bt) + endValue * bt + } + } else { + self.currentAngle += speed + self.currentExtraSpeed + } + self.currentExtraSpeed *= 0.97 + if abs(self.currentExtraSpeed) < 0.0001 { + self.currentExtraSpeed = 0.0 + } + + self.iconNode.layer.transform = CATransform3DMakeRotation((baseValue + self.currentAngle) * CGFloat.pi * 2.0, 0.0, 0.0, 1.0) + + if !self.currentExtraSpeed.isZero || !speed.isZero || self.animateToZeroState != nil { + self.animator.isPaused = false + } else { + self.animator.isPaused = true + } + } + + func update(state: WalletRefreshState) { + if self.state == state { + return + } + let previousState = self.state + self.state = state + + var pullProgress: CGFloat = 0.0 + + let title: String + switch state { + case let .pullToRefresh(ts, progress): + title = lastUpdateTimestampString(strings: self.strings, dateTimeFormat: dateTimeFormat, statusTimestamp: ts, relativeTo: Int32(Date().timeIntervalSince1970)) + pullProgress = progress + case .refreshing: + title = "updating" + } + + if let previousState = previousState { + switch state { + case .refreshing: + switch previousState { + case .refreshing: + break + default: + self.currentExtraSpeed = 0.05 + } + default: + self.currentExtraSpeed = 0.0 + } + } + + self.updateAnimation() + + self.titleNode.attributedText = NSAttributedString(string: title, font: Font.regular(13.0), textColor: UIColor(white: 1.0, alpha: 0.6)) + + let iconSize = self.iconNode.image?.size ?? CGSize(width: 20.0, height: 20.0) + let titleSize = self.titleNode.updateLayout(CGSize(width: 200.0, height: 100.0)) + let iconSpacing: CGFloat = 5.0 + + let contentWidth = iconSize.width + titleSize.width + iconSpacing + let contentOrigin = floor(-contentWidth / 2.0) + + self.iconContainer.frame = CGRect(origin: CGPoint(x: contentOrigin, y: floor(-iconSize.height / 2.0)), size: iconSize) + self.titleNode.frame = CGRect(origin: CGPoint(x: contentOrigin + iconSize.width + iconSpacing, y: floor(-titleSize.height / 2.0)), size: titleSize) + } +} diff --git a/submodules/WalletUI/Sources/WalletSettingsScreen.swift b/submodules/WalletUI/Sources/WalletSettingsScreen.swift index ee844ec86b..c691f15d90 100644 --- a/submodules/WalletUI/Sources/WalletSettingsScreen.swift +++ b/submodules/WalletUI/Sources/WalletSettingsScreen.swift @@ -104,11 +104,10 @@ public func walletSettingsController(context: AccountContext, tonContext: TonCon actionSheet.setItemGroups([ActionSheetItemGroup(items: [ ActionSheetButtonItem(title: "Delete Wallet", color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - let _ = (debugDeleteWallets(postbox: context.account.postbox) - |> deliverOnMainQueue).start(completed: { - if let tonContext = context.tonContext { - replaceAllWalletControllersImpl?(WalletSplashScreen(context: context, tonContext: tonContext, mode: .intro)) - } + let _ = (deleteLocalWalletData(postbox: context.account.postbox, network: context.account.network, tonInstance: tonContext.instance, keychain: tonContext.keychain, walletInfo: walletInfo) + |> deliverOnMainQueue).start(error: { _ in + }, completed: { + replaceAllWalletControllersImpl?(WalletSplashScreen(context: context, tonContext: tonContext, mode: .intro)) }) }) ]), ActionSheetItemGroup(items: [ diff --git a/submodules/WalletUI/Sources/WalletSplashScreen.swift b/submodules/WalletUI/Sources/WalletSplashScreen.swift index be9679e21f..877316dbc7 100644 --- a/submodules/WalletUI/Sources/WalletSplashScreen.swift +++ b/submodules/WalletUI/Sources/WalletSplashScreen.swift @@ -49,6 +49,7 @@ public final class WalletSplashScreen: ViewController { super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: defaultNavigationPresentationData.strings)) + self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style self.navigationPresentation = .modalInLargeLayout self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) self.navigationBar?.intrinsicCanTransitionInline = false @@ -287,14 +288,22 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode { let body = MarkdownAttributeSet(font: Font.regular(13.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor, additionalAttributes: [:]) let link = MarkdownAttributeSet(font: Font.regular(13.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor, additionalAttributes: [NSAttributedString.Key.underlineStyle.rawValue: NSUnderlineStyle.single.rawValue as NSNumber]) termsText = parseMarkdownIntoAttributedString("By creating the wallet you accept\n[Terms of Conditions]().", attributes: MarkdownAttributes(body: body, bold: body, link: link, linkAttribute: { _ in nil }), textAlignment: .center) - self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/IntroIcon") + self.iconNode.image = nil + if let path = getAppBundle().path(forResource: "WalletIntroStatic", ofType: "tgs") { + self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct) + self.animationNode.visibility = true + } secondaryActionText = "" case .created: title = "Congratulations" text = NSAttributedString(string: "Your Gram wallet has just been created. Only you control it.\n\nTo be able to always have access to it, please write down secret words and\nset up a secure passcode.", font: textFont, textColor: textColor) buttonText = "Proceed" termsText = NSAttributedString(string: "") - self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/CreatedIcon") + self.iconNode.image = nil + if let path = getAppBundle().path(forResource: "WalletCreated", ofType: "tgs") { + self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct) + self.animationNode.visibility = true + } secondaryActionText = "" case .success: title = "Ready to go!" @@ -323,7 +332,11 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode { text = NSAttributedString(string: "Please wait a few seconds for your transaction to be processed...", font: textFont, textColor: textColor) buttonText = "" termsText = NSAttributedString(string: "") - self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/SendingIcon") + self.iconNode.image = nil + if let path = getAppBundle().path(forResource: "SendingGrams", ofType: "tgs") { + self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct) + self.animationNode.visibility = true + } secondaryActionText = "" case let .sent(_, amount): title = "Done!" @@ -392,7 +405,7 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode { self.secondaryActionButtonNode = HighlightTrackingButtonNode() - self.buttonNode = SolidRoundedButtonNode(title: buttonText, theme: SolidRoundedButtonTheme(theme: self.presentationData.theme), height: 50.0, cornerRadius: 10.0, gloss: true) + self.buttonNode = SolidRoundedButtonNode(title: buttonText, theme: SolidRoundedButtonTheme(theme: self.presentationData.theme), height: 50.0, cornerRadius: 10.0, gloss: false) self.buttonNode.isHidden = buttonText.isEmpty super.init() diff --git a/submodules/WalletUI/Sources/WalletTransactionInfoScreen.swift b/submodules/WalletUI/Sources/WalletTransactionInfoScreen.swift index 2973664876..d02d745564 100644 --- a/submodules/WalletUI/Sources/WalletTransactionInfoScreen.swift +++ b/submodules/WalletUI/Sources/WalletTransactionInfoScreen.swift @@ -80,7 +80,7 @@ private enum WalletTransactionInfoEntry: ItemListNodeEntry { case let .infoHeader(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) case let .infoAddress(theme, text): - return ItemListMultilineTextItem(theme: theme, text: text, enabledEntityTypes: [], sectionId: self.section, style: .blocks) + return ItemListMultilineTextItem(theme: theme, text: text, enabledEntityTypes: [], font: .monospace, sectionId: self.section, style: .blocks) case let .infoCopyAddress(theme, text): return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { arguments.copyWalletAddress() @@ -346,20 +346,30 @@ private class WalletTransactionHeaderItemNode: ListViewItemNode { let leftInset: CGFloat = 15.0 + params.leftInset let verticalInset: CGFloat = 24.0 - let title: String + let balanceString: String let titleColor: UIColor let transferredValue = item.walletTransaction.transferredValue if transferredValue <= 0 { - title = "\(formatBalanceText(transferredValue, decimalSeparator: item.dateTimeFormat.decimalSeparator))" + balanceString = "\(formatBalanceText(transferredValue, decimalSeparator: item.dateTimeFormat.decimalSeparator))" titleColor = item.theme.list.itemPrimaryTextColor } else { - title = "+\(formatBalanceText(transferredValue, decimalSeparator: item.dateTimeFormat.decimalSeparator))" + balanceString = "+\(formatBalanceText(transferredValue, decimalSeparator: item.dateTimeFormat.decimalSeparator))" titleColor = item.theme.chatList.secretTitleColor } + let title = NSMutableAttributedString() + if let range = balanceString.range(of: ".") { + let integralPart = String(balanceString[.. Void, secondaryAction: @escaping () -> Void) { + init(account: Account, presentationData: PresentationData, mode: WalletWordCheckMode, possibleWordList: [String], action: @escaping () -> Void, secondaryAction: @escaping () -> Void) { self.presentationData = presentationData self.mode = mode self.action = action @@ -2576,9 +2578,7 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro self.scrollNode = ASScrollNode() self.scrollNode.canCancelAllTouchesInViews = true - self.iconNode = ASImageNode() - self.iconNode.displayWithoutProcessing = true - self.iconNode.displaysAsynchronously = false + self.animationNode = AnimatedStickerNode() let title: String let text: NSAttributedString @@ -2598,14 +2598,16 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro buttonText = "Continue" secondaryActionText = "" - self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/WordsCheckIcon") + if let path = getAppBundle().path(forResource: "WalletWordCheck", ofType: "tgs") { + self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct) + self.animationNode.visibility = true + } case .import: title = "24 Secret Words" text = NSAttributedString(string: "Please restore access to your wallet by\nentering the 24 secret words you wrote down when creating the wallet.", font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) buttonText = "Continue" secondaryActionText = "I don't have those" wordIndices = Array(0 ..< 24) - self.iconNode.image = nil } self.navigationTitleNode = ImmediateTextNode() @@ -2660,7 +2662,7 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro self.addSubnode(self.scrollNode) - self.scrollNode.addSubnode(self.iconNode) + self.scrollNode.addSubnode(self.animationNode) self.scrollNode.addSubnode(self.titleNode) self.scrollNode.addSubnode(self.textNode) self.scrollNode.addSubnode(self.secondaryActionTitleNode) @@ -2773,7 +2775,14 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: contentAreaSize)) - let iconSize = self.iconNode.image?.size ?? CGSize() + let iconSize: CGSize + switch self.mode { + case .import: + iconSize = CGSize() + case .verify: + iconSize = CGSize(width: 140.0, height: 140.0) + self.animationNode.updateLayout(size: iconSize) + } let titleSize = self.titleNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height)) let navigationTitleSize = self.navigationTitleNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height)) @@ -2787,7 +2796,7 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro let contentVerticalOrigin = navigationHeight + 10.0 let iconFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize) - transition.updateFrameAdditive(node: self.iconNode, frame: iconFrame) + transition.updateFrame(node: self.animationNode, frame: iconFrame) let titleFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize) transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame) let textFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize) diff --git a/submodules/WalletUI/Sources/WalletWordDisplayScreen.swift b/submodules/WalletUI/Sources/WalletWordDisplayScreen.swift index 91ddd75057..09ebdbea8c 100644 --- a/submodules/WalletUI/Sources/WalletWordDisplayScreen.swift +++ b/submodules/WalletUI/Sources/WalletWordDisplayScreen.swift @@ -10,6 +10,7 @@ import TelegramCore import SolidRoundedButtonNode import UndoUI import AlertUI +import AnimationUI public final class WalletWordDisplayScreen: ViewController { private let context: AccountContext @@ -35,6 +36,7 @@ public final class WalletWordDisplayScreen: ViewController { super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: defaultNavigationPresentationData.strings)) + self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style self.navigationPresentation = .modalInLargeLayout self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) self.navigationBar?.intrinsicCanTransitionInline = false @@ -51,7 +53,7 @@ public final class WalletWordDisplayScreen: ViewController { } override public func loadDisplayNode() { - self.displayNode = WalletWordDisplayScreenNode(presentationData: self.presentationData, wordList: self.wordList, action: { [weak self] in + self.displayNode = WalletWordDisplayScreenNode(account: self.context.account, presentationData: self.presentationData, wordList: self.wordList, action: { [weak self] in guard let strongSelf = self else { return } @@ -103,7 +105,7 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc private let navigationSeparatorNode: ASDisplayNode private let navigationTitleNode: ImmediateTextNode private let scrollNode: ASScrollNode - private let iconNode: ASImageNode + private let animationNode: AnimatedStickerNode private let titleNode: ImmediateTextNode private let textNode: ImmediateTextNode private let wordNodes: [(ImmediateTextNode, ImmediateTextNode, ImmediateTextNode)] @@ -111,7 +113,7 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc private var navigationHeight: CGFloat? - init(presentationData: PresentationData, wordList: [String], action: @escaping () -> Void) { + init(account: Account, presentationData: PresentationData, wordList: [String], action: @escaping () -> Void) { self.presentationData = presentationData self.wordList = wordList self.action = action @@ -124,16 +126,16 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc self.scrollNode = ASScrollNode() - self.iconNode = ASImageNode() - self.iconNode.displayWithoutProcessing = true - self.iconNode.displaysAsynchronously = false + self.animationNode = AnimatedStickerNode() + if let path = getAppBundle().path(forResource: "WalletWordList", ofType: "tgs") { + self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct) + self.animationNode.visibility = true + } let title: String = "24 Secret Words" let text: String = "Write down these 24 words in the correct order and store them in a secret place.\n\nUse these secret words to restore access to your wallet if you lose your passcode or Telegram account." let buttonText: String = "Done" - self.iconNode.image = UIImage(bundleImageName: "Settings/Wallet/WordsDisplayIcon") - self.titleNode = ImmediateTextNode() self.titleNode.displaysAsynchronously = false self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(32.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) @@ -187,7 +189,7 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc self.addSubnode(self.scrollNode) - self.scrollNode.addSubnode(self.iconNode) + self.scrollNode.addSubnode(self.animationNode) self.scrollNode.addSubnode(self.titleNode) self.scrollNode.addSubnode(self.textNode) self.scrollNode.addSubnode(self.buttonNode) @@ -257,7 +259,8 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - let iconSize = self.iconNode.image?.size ?? CGSize(width: 50.0, height: 50.0) + let iconSize = CGSize(width: 140.0, height: 140.0) + self.animationNode.updateLayout(size: iconSize) let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height)) let navigationTitleSize = self.navigationTitleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height)) @@ -268,7 +271,7 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc let contentVerticalOrigin = navigationHeight + 10.0 let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize) - transition.updateFrameAdditive(node: self.iconNode, frame: iconFrame) + transition.updateFrameAdditive(node: self.animationNode, frame: iconFrame) let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize) transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame) let textFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize) diff --git a/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj b/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj index 66750110b2..05ecee3e32 100644 --- a/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj +++ b/submodules/WalletUI/WalletUI.xcodeproj/project.pbxproj @@ -931,6 +931,17 @@ sourceTree SOURCE_ROOT + 1DD70E293117BD4900000000 + + isa + PBXFileReference + name + WalletRefreshNode.swift + path + Sources/WalletRefreshNode.swift + sourceTree + SOURCE_ROOT + 1DD70E2948FA33F200000000 isa @@ -1015,6 +1026,7 @@ 1DD70E296D49CFFF00000000 1DD70E29DE28A96800000000 1DD70E2979DDEBBB00000000 + 1DD70E293117BD4900000000 1DD70E2948FA33F200000000 1DD70E2986544B8D00000000 1DD70E2964068E1100000000 @@ -1109,6 +1121,13 @@ fileRef 1DD70E2979DDEBBB00000000 + E7A30F043117BD4900000000 + + isa + PBXBuildFile + fileRef + 1DD70E293117BD4900000000 + E7A30F0448FA33F200000000 isa @@ -1165,6 +1184,7 @@ E7A30F046D49CFFF00000000 E7A30F04DE28A96800000000 E7A30F0479DDEBBB00000000 + E7A30F043117BD4900000000 E7A30F0448FA33F200000000 E7A30F0486544B8D00000000 E7A30F0464068E1100000000 diff --git a/submodules/ton/tonlib-src/CMakeLists.txt b/submodules/ton/tonlib-src/CMakeLists.txt index 7f01f988b1..a2bb0676cb 100644 --- a/submodules/ton/tonlib-src/CMakeLists.txt +++ b/submodules/ton/tonlib-src/CMakeLists.txt @@ -375,6 +375,10 @@ target_link_libraries(test-tonlib tdutils tdactor adnllite tl_api ton_crypto ton add_executable(test-tonlib-offline test/test-td-main.cpp ${TONLIB_OFFLINE_TEST_SOURCE}) target_link_libraries(test-tonlib-offline tdutils tdactor adnllite tl_api ton_crypto ton_block fift-lib tl_tonlib_api tonlib) + +if (NOT CMAKE_CROSSCOMPILING) + add_dependencies(test-tonlib-offline gen_fif) +endif() #END tonlib diff --git a/submodules/ton/tonlib-src/crypto/block/check-proof.cpp b/submodules/ton/tonlib-src/crypto/block/check-proof.cpp index a856c876ee..c459b1b458 100644 --- a/submodules/ton/tonlib-src/crypto/block/check-proof.cpp +++ b/submodules/ton/tonlib-src/crypto/block/check-proof.cpp @@ -32,7 +32,7 @@ namespace block { using namespace std::literals::string_literals; td::Status check_block_header_proof(td::Ref root, ton::BlockIdExt blkid, ton::Bits256* store_shard_hash_to, - bool check_state_hash) { + bool check_state_hash, td::uint32* save_utime) { ton::RootHash vhash{root->get_hash().bits()}; if (vhash != blkid.root_hash) { return td::Status::Error(PSTRING() << " block header for block " << blkid.to_str() << " has incorrect root hash " @@ -47,6 +47,9 @@ td::Status check_block_header_proof(td::Ref root, ton::BlockIdExt blki if (!(tlb::unpack_cell(root, blk) && tlb::unpack_cell(blk.info, info))) { return td::Status::Error(std::string{"cannot unpack header for block "} + blkid.to_str()); } + if (save_utime) { + *save_utime = info.gen_utime; + } if (store_shard_hash_to) { vm::CellSlice upd_cs{vm::NoVmSpec(), blk.state_update}; if (!(upd_cs.is_special() && upd_cs.prefetch_long(8) == 4 // merkle update @@ -153,7 +156,8 @@ td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td: } td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr, - td::Ref root, ton::LogicalTime* last_trans_lt, ton::Bits256* last_trans_hash) { + td::Ref root, ton::LogicalTime* last_trans_lt, ton::Bits256* last_trans_hash, + td::uint32* save_utime) { TRY_RESULT_PREFIX(Q_roots, vm::std_boc_deserialize_multi(std::move(proof)), "cannot deserialize account proof"); if (Q_roots.size() != 2) { return td::Status::Error(PSLICE() << "account state proof must have exactly two roots"); @@ -169,9 +173,9 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const return td::Status::Error("account state proof is invalid"); } ton::Bits256 state_hash = state_root->get_hash().bits(); - TRY_STATUS_PREFIX( - check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0]), 1), shard_blk, &state_hash, true), - "error in account shard block header proof : "); + TRY_STATUS_PREFIX(check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0]), 1), shard_blk, + &state_hash, true, save_utime), + "error in account shard block header proof : "); block::gen::ShardStateUnsplit::Record sstate; if (!(tlb::unpack_cell(std::move(state_root), sstate))) { return td::Status::Error("cannot unpack state header"); @@ -233,8 +237,8 @@ td::Result AccountState::validate(ton::BlockIdExt ref_blk, b TRY_STATUS(block::check_shard_proof(blk, shard_blk, shard_proof.as_slice())); Info res; - TRY_STATUS( - block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt, &res.last_trans_hash)); + TRY_STATUS(block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt, + &res.last_trans_hash, &res.gen_utime)); res.root = std::move(root); return res; diff --git a/submodules/ton/tonlib-src/crypto/block/check-proof.h b/submodules/ton/tonlib-src/crypto/block/check-proof.h index 664028155d..87d6b442b7 100644 --- a/submodules/ton/tonlib-src/crypto/block/check-proof.h +++ b/submodules/ton/tonlib-src/crypto/block/check-proof.h @@ -25,11 +25,12 @@ namespace block { using td::Ref; td::Status check_block_header_proof(td::Ref root, ton::BlockIdExt blkid, - ton::Bits256* store_shard_hash_to = nullptr, bool check_state_hash = false); + ton::Bits256* store_shard_hash_to = nullptr, bool check_state_hash = false, + td::uint32* save_utime = nullptr); td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td::Slice shard_proof); td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr, td::Ref root, ton::LogicalTime* last_trans_lt = nullptr, - ton::Bits256* last_trans_hash = nullptr); + ton::Bits256* last_trans_hash = nullptr, td::uint32* save_utime = nullptr); td::Result check_state_proof(ton::BlockIdExt blkid, td::Slice proof); td::Result> check_extract_state_proof(ton::BlockIdExt blkid, td::Slice proof, td::Slice data); @@ -47,6 +48,7 @@ struct AccountState { td::Ref root; ton::LogicalTime last_trans_lt = 0; ton::Bits256 last_trans_hash; + td::uint32 gen_utime{0}; }; td::Result validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const; diff --git a/submodules/ton/tonlib-src/crypto/fift/IntCtx.h b/submodules/ton/tonlib-src/crypto/fift/IntCtx.h index 753d2cb1d4..1adb8f325a 100644 --- a/submodules/ton/tonlib-src/crypto/fift/IntCtx.h +++ b/submodules/ton/tonlib-src/crypto/fift/IntCtx.h @@ -77,6 +77,7 @@ struct IntCtx { vm::TonDb* ton_db{nullptr}; Dictionary* dictionary{nullptr}; SourceLookup* source_lookup{nullptr}; + int* now{nullptr}; private: std::string str; diff --git a/submodules/ton/tonlib-src/crypto/fift/SourceLookup.h b/submodules/ton/tonlib-src/crypto/fift/SourceLookup.h index 73d2cd918f..33ee71d4ef 100644 --- a/submodules/ton/tonlib-src/crypto/fift/SourceLookup.h +++ b/submodules/ton/tonlib-src/crypto/fift/SourceLookup.h @@ -20,6 +20,7 @@ #include #include "td/utils/Status.h" +#include "td/utils/Time.h" namespace fift { class FileLoader { @@ -43,10 +44,21 @@ class OsFileLoader : public FileLoader { bool is_file_exists(td::CSlice filename) override; }; +class OsTime { + public: + virtual ~OsTime() = default; + virtual td::uint32 now() = 0; +}; + +//TODO: rename SourceLookup class SourceLookup { public: SourceLookup() = default; - explicit SourceLookup(std::unique_ptr file_loader) : file_loader_(std::move(file_loader)) { + explicit SourceLookup(std::unique_ptr file_loader, std::unique_ptr os_time = {}) + : file_loader_(std::move(file_loader)), os_time_(std::move(os_time)) { + } + void set_os_time(std::unique_ptr os_time) { + os_time_ = std::move(os_time); } void add_include_path(td::string path); td::Result lookup_source(std::string filename, std::string current_dir); @@ -63,9 +75,16 @@ class SourceLookup { bool is_file_exists(td::CSlice filename) { return file_loader_->is_file_exists(filename); } + td::uint32 now() { + if (os_time_) { + return os_time_->now(); + } + return static_cast(td::Time::now()); + } protected: std::unique_ptr file_loader_; + std::unique_ptr os_time_; std::vector source_include_path_; }; } // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/utils.cpp b/submodules/ton/tonlib-src/crypto/fift/utils.cpp index e5f9a597e5..1c16b2cd4a 100644 --- a/submodules/ton/tonlib-src/crypto/fift/utils.cpp +++ b/submodules/ton/tonlib-src/crypto/fift/utils.cpp @@ -163,13 +163,15 @@ td::Result create_mem_source_lookup(std::string main, std::s return create_source_lookup(main, need_preamble, need_asm, need_ton_util, fift_dir); } -td::Result> compile_asm(td::Slice asm_code, std::string fift_dir) { +td::Result> compile_asm(td::Slice asm_code, std::string fift_dir, bool is_raw) { std::stringstream ss; TRY_RESULT(source_lookup, - create_source_lookup(PSTRING() << "\"Asm.fif\" include\n<{ " << asm_code << "\n}>c boc>B \"res\" B>file", + create_source_lookup(PSTRING() << "\"Asm.fif\" include\n " << (is_raw ? "<{" : "") << asm_code << "\n" + << (is_raw ? "}>c" : "") << " boc>B \"res\" B>file", true, true, true, fift_dir)); TRY_RESULT(res, run_fift(std::move(source_lookup), &ss)); TRY_RESULT(boc, res.read_file("res")); return vm::std_boc_deserialize(std::move(boc.data)); } + } // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/utils.h b/submodules/ton/tonlib-src/crypto/fift/utils.h index e6ed145287..e17eb8ae2c 100644 --- a/submodules/ton/tonlib-src/crypto/fift/utils.h +++ b/submodules/ton/tonlib-src/crypto/fift/utils.h @@ -31,5 +31,5 @@ td::Result create_mem_source_lookup(std::string main, std::s bool need_ton_util = true); td::Result mem_run_fift(std::string source, std::vector args = {}, std::string fift_dir = ""); td::Result mem_run_fift(SourceLookup source_lookup, std::vector args); -td::Result> compile_asm(td::Slice asm_code, std::string fift_dir = ""); +td::Result> compile_asm(td::Slice asm_code, std::string fift_dir = "", bool is_raw = true); } // namespace fift diff --git a/submodules/ton/tonlib-src/crypto/fift/words.cpp b/submodules/ton/tonlib-src/crypto/fift/words.cpp index 5c217fad44..01dcf802c8 100644 --- a/submodules/ton/tonlib-src/crypto/fift/words.cpp +++ b/submodules/ton/tonlib-src/crypto/fift/words.cpp @@ -1289,8 +1289,8 @@ void interpret_file_exists(IntCtx& ctx) { // custom and crypto -void interpret_now(vm::Stack& stack) { - stack.push_smallint(std::time(nullptr)); +void interpret_now(IntCtx& ctx) { + ctx.stack.push_smallint(ctx.source_lookup->now()); } void interpret_new_keypair(vm::Stack& stack) { @@ -2534,7 +2534,7 @@ void init_words_common(Dictionary& d) { d.def_ctx_word("B>file ", interpret_write_file); d.def_ctx_word("file-exists? ", interpret_file_exists); // custom & crypto - d.def_stack_word("now ", interpret_now); + d.def_ctx_word("now ", interpret_now); d.def_stack_word("newkeypair ", interpret_new_keypair); d.def_stack_word("priv>pub ", interpret_priv_key_to_pub); d.def_stack_word("ed25519_sign ", interpret_ed25519_sign); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif new file mode 100644 index 0000000000..eac43b168b --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif @@ -0,0 +1,62 @@ +#!/usr/bin/env fift -s +"TonUtil.fif" include +"Asm.fif" include + +{ ."usage: " @' $0 type ." []" cr + ."Creates a new advanced wallet in specified workchain, with private key saved to or loaded from .pk" cr + ."('new-wallet.pk' by default)" cr 1 halt +} : usage +$# 1- -2 and ' usage if + +$1 parse-workchain-id =: wc // set workchain id from command line argument +def? $2 { @' $2 } { "new-wallet" } cond constant file-base + +."Creating new advanced wallet in workchain " wc . cr + +// Create new advanced wallet; code adapted from `wallet-code.fif` +<{ 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 // signature in_msg msg_seqno valid_until cs + SWAP NOW LEQ 35 THROWIF // signature in_msg msg_seqno cs + c4 PUSH CTOS 32 LDU 256 LDU ENDS // signature in_msg msg_seqno cs stored_seqno public_key + s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno + EQUAL 33 THROWIFNOT // signature in_msg public_key cs stored_seqno + s0 s3 XCHG HASHSU // signature stored_seqno public_key cs hash + s0 s4 s2 XC2PU CHKSIGNU 34 THROWIFNOT // cs stored_seqno public_key + ACCEPT + s0 s2 XCHG // public_key stored_seqno cs + WHILE:<{ + DUP SREFS // public_key stored_seqno cs _40 + }>DO<{ // public_key stored_seqno cs + // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance + 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno cs _45 mode + SENDRAWMSG // public_key stored_seqno cs + }> + ENDS INC // public_key seqno' + NEWC 32 STU 256 STU ENDC c4 POP +}>c // >libref +// code + // data +null // no libraries + // create StateInit +dup ."StateInit: " +dup ."signing message: " +dup ."External message for initialization is " B dup Bx. cr +file-base +"-query.boc" tuck B>file +."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif b/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif index bd9f8860c3..fe812487a5 100644 --- a/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif @@ -24,7 +24,7 @@ dest_addr 2dup bounce 7 + .Addr ." = " .addr // create a message (NB: 01b00.., b = bounce) + amount Gram, 0 9 64 32 + + 1+ 1+ u, 0 32 u, "GIFT" $, b> dup ."enveloping message: " [-B ] []" cr + ."Creates a request to advanced wallet created by new-wallet-v2.fif, with private key loaded from file .pk " + ."and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" cr 1 halt +} : usage +def? $6 { @' $5 "-B" $= { @' $6 =: body-boc-file [forget] $6 def? $7 { @' $7 =: $5 [forget] $7 } { [forget] $5 } cond + @' $# 2- =: $# } if } if +$# dup 4 < swap 5 > or ' usage if + +true constant bounce + +$1 =: file-base +$2 bounce parse-load-address =: bounce 2=: dest_addr +$3 parse-int =: seqno +$4 $>GR =: amount +def? $5 { @' $5 } { "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 } { } cond +constant body-cell + +."Transferring " amount .GR ."to account " +dest_addr 2dup bounce 7 + .Addr ." = " .addr +."seqno=0x" seqno x. ."bounce=" bounce . cr +."Body of transfer message is " body-cell + +dup ."signing message: " +dup ."resulting external message: " B dup Bx. cr +savefile +".boc" tuck B>file +."Query expires in " timeout . ."seconds" cr +."(Saved to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif index 8742e3cc69..1159796399 100644 --- a/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif @@ -5,9 +5,9 @@ ."Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file .pk " ."and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" cr 1 halt } : usage -$# dup 4 < swap 5 > or ' usage if def? $6 { @' $5 "-B" $= { @' $6 =: body-boc-file [forget] $6 def? $7 { @' $7 =: $5 [forget] $7 } { [forget] $5 } cond @' $# 2- =: $# } if } if +$# dup 4 < swap 5 > or ' usage if true constant bounce @@ -16,13 +16,14 @@ $2 bounce parse-load-address =: bounce 2=: dest_addr $3 parse-int =: seqno $4 $>GR =: amount def? $5 { @' $5 } { "wallet-query" } cond constant savefile +3 constant send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors 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 } { } cond +def? body-boc-file { @' body-boc-file file>B B>boc } { } cond constant body-cell ."Transferring " amount .GR ."to account " @@ -34,7 +35,7 @@ dest_addr 2dup bounce 7 + .Addr ." = " .addr - + dup ."signing message: " "); + store_field_end(); + } + template void store_field(const char *name, const T &value) { store_field_begin(name); @@ -240,6 +247,12 @@ class TlStorerToString { store_field_end(); } + void store_bytes_field(const char *name, const SecureString &value) { + store_field_begin(name); + result.append(""); + store_field_end(); + } + template void store_bytes_field(const char *name, const BytesT &value) { static const char *hex = "0123456789ABCDEF"; diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp index bfbdee4ed8..c6c6f32804 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp @@ -446,6 +446,8 @@ object_ptr Object::fetch(td::TlParser &p) { return tonNode_blockIdExt::fetch(p); case tonNode_blockSignature::ID: return tonNode_blockSignature::fetch(p); + case tonNode_blocksDescription::ID: + return tonNode_blocksDescription::fetch(p); case tonNode_blockBroadcast::ID: return tonNode_blockBroadcast::fetch(p); case tonNode_ihrMessageBroadcast::ID: @@ -454,8 +456,16 @@ object_ptr Object::fetch(td::TlParser &p) { return tonNode_externalMessageBroadcast::fetch(p); case tonNode_newShardBlockBroadcast::ID: return tonNode_newShardBlockBroadcast::fetch(p); + case tonNode_capabilities::ID: + return tonNode_capabilities::fetch(p); case tonNode_data::ID: return tonNode_data::fetch(p); + case tonNode_dataFull::ID: + return tonNode_dataFull::fetch(p); + case tonNode_dataFullEmpty::ID: + return tonNode_dataFullEmpty::fetch(p); + case tonNode_dataList::ID: + return tonNode_dataList::fetch(p); case tonNode_externalMessage::ID: return tonNode_externalMessage::fetch(p); case tonNode_ihrMessage::ID: @@ -482,6 +492,8 @@ object_ptr Object::fetch(td::TlParser &p) { return tonNode_sessionId::fetch(p); case tonNode_shardPublicOverlayId::ID: return tonNode_shardPublicOverlayId::fetch(p); + case tonNode_success::ID: + return tonNode_success::fetch(p); case tonNode_zeroStateIdExt::ID: return tonNode_zeroStateIdExt::fetch(p); case validator_group::ID: @@ -632,24 +644,44 @@ object_ptr Function::fetch(td::TlParser &p) { return tcp_ping::fetch(p); case tonNode_downloadBlock::ID: return tonNode_downloadBlock::fetch(p); + case tonNode_downloadBlockFull::ID: + return tonNode_downloadBlockFull::fetch(p); case tonNode_downloadBlockProof::ID: return tonNode_downloadBlockProof::fetch(p); case tonNode_downloadBlockProofLink::ID: return tonNode_downloadBlockProofLink::fetch(p); + case tonNode_downloadBlockProofLinks::ID: + return tonNode_downloadBlockProofLinks::fetch(p); + case tonNode_downloadBlockProofs::ID: + return tonNode_downloadBlockProofs::fetch(p); + case tonNode_downloadBlocks::ID: + return tonNode_downloadBlocks::fetch(p); + case tonNode_downloadNextBlockFull::ID: + return tonNode_downloadNextBlockFull::fetch(p); case tonNode_downloadPersistentState::ID: return tonNode_downloadPersistentState::fetch(p); case tonNode_downloadPersistentStateSlice::ID: return tonNode_downloadPersistentStateSlice::fetch(p); case tonNode_downloadZeroState::ID: return tonNode_downloadZeroState::fetch(p); + case tonNode_getCapabilities::ID: + return tonNode_getCapabilities::fetch(p); case tonNode_getNextBlockDescription::ID: return tonNode_getNextBlockDescription::fetch(p); + case tonNode_getNextBlocksDescription::ID: + return tonNode_getNextBlocksDescription::fetch(p); case tonNode_getNextKeyBlockIds::ID: return tonNode_getNextKeyBlockIds::fetch(p); + case tonNode_getPrevBlocksDescription::ID: + return tonNode_getPrevBlocksDescription::fetch(p); case tonNode_prepareBlock::ID: return tonNode_prepareBlock::fetch(p); case tonNode_prepareBlockProof::ID: return tonNode_prepareBlockProof::fetch(p); + case tonNode_prepareBlockProofs::ID: + return tonNode_prepareBlockProofs::fetch(p); + case tonNode_prepareBlocks::ID: + return tonNode_prepareBlocks::fetch(p); case tonNode_preparePersistentState::ID: return tonNode_preparePersistentState::fetch(p); case tonNode_prepareZeroState::ID: @@ -10634,6 +10666,50 @@ void tonNode_blockSignature::store(td::TlStorerToString &s, const char *field_na } } +tonNode_blocksDescription::tonNode_blocksDescription() + : ids_() + , incomplete_() +{} + +tonNode_blocksDescription::tonNode_blocksDescription(std::vector> &&ids_, bool incomplete_) + : ids_(std::move(ids_)) + , incomplete_(incomplete_) +{} + +const std::int32_t tonNode_blocksDescription::ID; + +object_ptr tonNode_blocksDescription::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_blocksDescription::tonNode_blocksDescription(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : ids_(TlFetchVector>::parse(p)) + , incomplete_(TlFetchBool::parse(p)) +#undef FAIL +{} + +void tonNode_blocksDescription::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + TlStoreVector::store(ids_, s); + TlStoreBool::store(incomplete_, s); +} + +void tonNode_blocksDescription::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + TlStoreVector::store(ids_, s); + TlStoreBool::store(incomplete_, s); +} + +void tonNode_blocksDescription::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_blocksDescription"); + { const std::vector> &v = ids_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("ids", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); } + s.store_field("incomplete", incomplete_); + s.store_class_end(); + } +} + object_ptr tonNode_Broadcast::fetch(td::TlParser &p) { #define FAIL(error) p.set_error(error); return nullptr; int constructor = p.fetch_int(); @@ -10834,6 +10910,50 @@ void tonNode_newShardBlockBroadcast::store(td::TlStorerToString &s, const char * } } +tonNode_capabilities::tonNode_capabilities() + : version_() + , capabilities_() +{} + +tonNode_capabilities::tonNode_capabilities(std::int32_t version_, std::int64_t capabilities_) + : version_(version_) + , capabilities_(capabilities_) +{} + +const std::int32_t tonNode_capabilities::ID; + +object_ptr tonNode_capabilities::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_capabilities::tonNode_capabilities(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : version_(TlFetchInt::parse(p)) + , capabilities_(TlFetchLong::parse(p)) +#undef FAIL +{} + +void tonNode_capabilities::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + TlStoreBinary::store(version_, s); + TlStoreBinary::store(capabilities_, s); +} + +void tonNode_capabilities::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + TlStoreBinary::store(version_, s); + TlStoreBinary::store(capabilities_, s); +} + +void tonNode_capabilities::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_capabilities"); + s.store_field("version", version_); + s.store_field("capabilities", capabilities_); + s.store_class_end(); + } +} + tonNode_data::tonNode_data() : data_() {} @@ -10872,6 +10992,145 @@ void tonNode_data::store(td::TlStorerToString &s, const char *field_name) const } } +object_ptr tonNode_DataFull::fetch(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return nullptr; + int constructor = p.fetch_int(); + switch (constructor) { + case tonNode_dataFull::ID: + return tonNode_dataFull::fetch(p); + case tonNode_dataFullEmpty::ID: + return tonNode_dataFullEmpty::fetch(p); + default: + FAIL(PSTRING() << "Unknown constructor found " << td::format::as_hex(constructor)); + } +#undef FAIL +} + +tonNode_dataFull::tonNode_dataFull() + : id_() + , proof_() + , block_() + , is_link_() +{} + +tonNode_dataFull::tonNode_dataFull(object_ptr &&id_, td::BufferSlice &&proof_, td::BufferSlice &&block_, bool is_link_) + : id_(std::move(id_)) + , proof_(std::move(proof_)) + , block_(std::move(block_)) + , is_link_(is_link_) +{} + +const std::int32_t tonNode_dataFull::ID; + +object_ptr tonNode_dataFull::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_dataFull::tonNode_dataFull(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : id_(TlFetchObject::parse(p)) + , proof_(TlFetchBytes::parse(p)) + , block_(TlFetchBytes::parse(p)) + , is_link_(TlFetchBool::parse(p)) +#undef FAIL +{} + +void tonNode_dataFull::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + TlStoreObject::store(id_, s); + TlStoreString::store(proof_, s); + TlStoreString::store(block_, s); + TlStoreBool::store(is_link_, s); +} + +void tonNode_dataFull::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + TlStoreObject::store(id_, s); + TlStoreString::store(proof_, s); + TlStoreString::store(block_, s); + TlStoreBool::store(is_link_, s); +} + +void tonNode_dataFull::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_dataFull"); + if (id_ == nullptr) { s.store_field("id", "null"); } else { id_->store(s, "id"); } + s.store_bytes_field("proof", proof_); + s.store_bytes_field("block", block_); + s.store_field("is_link", is_link_); + s.store_class_end(); + } +} + +tonNode_dataFullEmpty::tonNode_dataFullEmpty() { +} + +const std::int32_t tonNode_dataFullEmpty::ID; + +object_ptr tonNode_dataFullEmpty::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_dataFullEmpty::tonNode_dataFullEmpty(td::TlParser &p) +#define FAIL(error) p.set_error(error) +#undef FAIL +{ + (void)p; +} + +void tonNode_dataFullEmpty::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); +} + +void tonNode_dataFullEmpty::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); +} + +void tonNode_dataFullEmpty::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_dataFullEmpty"); + s.store_class_end(); + } +} + +tonNode_dataList::tonNode_dataList() + : data_() +{} + +tonNode_dataList::tonNode_dataList(std::vector &&data_) + : data_(std::move(data_)) +{} + +const std::int32_t tonNode_dataList::ID; + +object_ptr tonNode_dataList::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_dataList::tonNode_dataList(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : data_(TlFetchVector>::parse(p)) +#undef FAIL +{} + +void tonNode_dataList::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + TlStoreVector::store(data_, s); +} + +void tonNode_dataList::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + TlStoreVector::store(data_, s); +} + +void tonNode_dataList::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_dataList"); + { const std::vector &v = data_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("data", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { s.store_bytes_field("", v[i]); } s.store_class_end(); } + s.store_class_end(); + } +} + tonNode_externalMessage::tonNode_externalMessage() : data_() {} @@ -11415,6 +11674,37 @@ void tonNode_shardPublicOverlayId::store(td::TlStorerToString &s, const char *fi } } +tonNode_success::tonNode_success() { +} + +const std::int32_t tonNode_success::ID; + +object_ptr tonNode_success::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_success::tonNode_success(td::TlParser &p) +#define FAIL(error) p.set_error(error) +#undef FAIL +{ + (void)p; +} + +void tonNode_success::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); +} + +void tonNode_success::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); +} + +void tonNode_success::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_success"); + s.store_class_end(); + } +} + tonNode_zeroStateIdExt::tonNode_zeroStateIdExt() : workchain_() , root_hash_() @@ -14937,6 +15227,52 @@ tonNode_downloadBlock::ReturnType tonNode_downloadBlock::fetch_result(td::TlPars #undef FAIL } +tonNode_downloadBlockFull::tonNode_downloadBlockFull() + : block_() +{} + +tonNode_downloadBlockFull::tonNode_downloadBlockFull(object_ptr &&block_) + : block_(std::move(block_)) +{} + +const std::int32_t tonNode_downloadBlockFull::ID; + +object_ptr tonNode_downloadBlockFull::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_downloadBlockFull::tonNode_downloadBlockFull(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : block_(TlFetchObject::parse(p)) +#undef FAIL +{} + +void tonNode_downloadBlockFull::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(1780991133); + TlStoreObject::store(block_, s); +} + +void tonNode_downloadBlockFull::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(1780991133); + TlStoreObject::store(block_, s); +} + +void tonNode_downloadBlockFull::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_downloadBlockFull"); + if (block_ == nullptr) { s.store_field("block", "null"); } else { block_->store(s, "block"); } + s.store_class_end(); + } +} + +tonNode_downloadBlockFull::ReturnType tonNode_downloadBlockFull::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchObject::parse(p); +#undef FAIL +} + tonNode_downloadBlockProof::tonNode_downloadBlockProof() : block_() {} @@ -15029,6 +15365,190 @@ tonNode_downloadBlockProofLink::ReturnType tonNode_downloadBlockProofLink::fetch #undef FAIL } +tonNode_downloadBlockProofLinks::tonNode_downloadBlockProofLinks() + : blocks_() +{} + +tonNode_downloadBlockProofLinks::tonNode_downloadBlockProofLinks(std::vector> &&blocks_) + : blocks_(std::move(blocks_)) +{} + +const std::int32_t tonNode_downloadBlockProofLinks::ID; + +object_ptr tonNode_downloadBlockProofLinks::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_downloadBlockProofLinks::tonNode_downloadBlockProofLinks(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : blocks_(TlFetchVector>::parse(p)) +#undef FAIL +{} + +void tonNode_downloadBlockProofLinks::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(684796771); + TlStoreVector::store(blocks_, s); +} + +void tonNode_downloadBlockProofLinks::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(684796771); + TlStoreVector::store(blocks_, s); +} + +void tonNode_downloadBlockProofLinks::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_downloadBlockProofLinks"); + { const std::vector> &v = blocks_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("blocks", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); } + s.store_class_end(); + } +} + +tonNode_downloadBlockProofLinks::ReturnType tonNode_downloadBlockProofLinks::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchBoxed, 351548179>::parse(p); +#undef FAIL +} + +tonNode_downloadBlockProofs::tonNode_downloadBlockProofs() + : blocks_() +{} + +tonNode_downloadBlockProofs::tonNode_downloadBlockProofs(std::vector> &&blocks_) + : blocks_(std::move(blocks_)) +{} + +const std::int32_t tonNode_downloadBlockProofs::ID; + +object_ptr tonNode_downloadBlockProofs::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_downloadBlockProofs::tonNode_downloadBlockProofs(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : blocks_(TlFetchVector>::parse(p)) +#undef FAIL +{} + +void tonNode_downloadBlockProofs::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(-1515170827); + TlStoreVector::store(blocks_, s); +} + +void tonNode_downloadBlockProofs::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(-1515170827); + TlStoreVector::store(blocks_, s); +} + +void tonNode_downloadBlockProofs::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_downloadBlockProofs"); + { const std::vector> &v = blocks_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("blocks", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); } + s.store_class_end(); + } +} + +tonNode_downloadBlockProofs::ReturnType tonNode_downloadBlockProofs::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchBoxed, 351548179>::parse(p); +#undef FAIL +} + +tonNode_downloadBlocks::tonNode_downloadBlocks() + : blocks_() +{} + +tonNode_downloadBlocks::tonNode_downloadBlocks(std::vector> &&blocks_) + : blocks_(std::move(blocks_)) +{} + +const std::int32_t tonNode_downloadBlocks::ID; + +object_ptr tonNode_downloadBlocks::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_downloadBlocks::tonNode_downloadBlocks(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : blocks_(TlFetchVector>::parse(p)) +#undef FAIL +{} + +void tonNode_downloadBlocks::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(1985594749); + TlStoreVector::store(blocks_, s); +} + +void tonNode_downloadBlocks::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(1985594749); + TlStoreVector::store(blocks_, s); +} + +void tonNode_downloadBlocks::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_downloadBlocks"); + { const std::vector> &v = blocks_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("blocks", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); } + s.store_class_end(); + } +} + +tonNode_downloadBlocks::ReturnType tonNode_downloadBlocks::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchBoxed, 351548179>::parse(p); +#undef FAIL +} + +tonNode_downloadNextBlockFull::tonNode_downloadNextBlockFull() + : prev_block_() +{} + +tonNode_downloadNextBlockFull::tonNode_downloadNextBlockFull(object_ptr &&prev_block_) + : prev_block_(std::move(prev_block_)) +{} + +const std::int32_t tonNode_downloadNextBlockFull::ID; + +object_ptr tonNode_downloadNextBlockFull::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_downloadNextBlockFull::tonNode_downloadNextBlockFull(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : prev_block_(TlFetchObject::parse(p)) +#undef FAIL +{} + +void tonNode_downloadNextBlockFull::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(1855993674); + TlStoreObject::store(prev_block_, s); +} + +void tonNode_downloadNextBlockFull::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(1855993674); + TlStoreObject::store(prev_block_, s); +} + +void tonNode_downloadNextBlockFull::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_downloadNextBlockFull"); + if (prev_block_ == nullptr) { s.store_field("prev_block", "null"); } else { prev_block_->store(s, "prev_block"); } + s.store_class_end(); + } +} + +tonNode_downloadNextBlockFull::ReturnType tonNode_downloadNextBlockFull::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchObject::parse(p); +#undef FAIL +} + tonNode_downloadPersistentState::tonNode_downloadPersistentState() : block_() , masterchain_block_() @@ -15191,6 +15711,45 @@ tonNode_downloadZeroState::ReturnType tonNode_downloadZeroState::fetch_result(td #undef FAIL } +tonNode_getCapabilities::tonNode_getCapabilities() { +} + +const std::int32_t tonNode_getCapabilities::ID; + +object_ptr tonNode_getCapabilities::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_getCapabilities::tonNode_getCapabilities(td::TlParser &p) +#define FAIL(error) p.set_error(error) +#undef FAIL +{ + (void)p; +} + +void tonNode_getCapabilities::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(-555345672); +} + +void tonNode_getCapabilities::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(-555345672); +} + +void tonNode_getCapabilities::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_getCapabilities"); + s.store_class_end(); + } +} + +tonNode_getCapabilities::ReturnType tonNode_getCapabilities::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchBoxed, -172007232>::parse(p); +#undef FAIL +} + tonNode_getNextBlockDescription::tonNode_getNextBlockDescription() : prev_block_() {} @@ -15237,6 +15796,58 @@ tonNode_getNextBlockDescription::ReturnType tonNode_getNextBlockDescription::fet #undef FAIL } +tonNode_getNextBlocksDescription::tonNode_getNextBlocksDescription() + : prev_block_() + , limit_() +{} + +tonNode_getNextBlocksDescription::tonNode_getNextBlocksDescription(object_ptr &&prev_block_, std::int32_t limit_) + : prev_block_(std::move(prev_block_)) + , limit_(limit_) +{} + +const std::int32_t tonNode_getNextBlocksDescription::ID; + +object_ptr tonNode_getNextBlocksDescription::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_getNextBlocksDescription::tonNode_getNextBlocksDescription(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : prev_block_(TlFetchObject::parse(p)) + , limit_(TlFetchInt::parse(p)) +#undef FAIL +{} + +void tonNode_getNextBlocksDescription::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(1059590852); + TlStoreObject::store(prev_block_, s); + TlStoreBinary::store(limit_, s); +} + +void tonNode_getNextBlocksDescription::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(1059590852); + TlStoreObject::store(prev_block_, s); + TlStoreBinary::store(limit_, s); +} + +void tonNode_getNextBlocksDescription::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_getNextBlocksDescription"); + if (prev_block_ == nullptr) { s.store_field("prev_block", "null"); } else { prev_block_->store(s, "prev_block"); } + s.store_field("limit", limit_); + s.store_class_end(); + } +} + +tonNode_getNextBlocksDescription::ReturnType tonNode_getNextBlocksDescription::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchBoxed, -701865684>::parse(p); +#undef FAIL +} + tonNode_getNextKeyBlockIds::tonNode_getNextKeyBlockIds() : block_() , max_size_() @@ -15289,6 +15900,64 @@ tonNode_getNextKeyBlockIds::ReturnType tonNode_getNextKeyBlockIds::fetch_result( #undef FAIL } +tonNode_getPrevBlocksDescription::tonNode_getPrevBlocksDescription() + : next_block_() + , limit_() + , cutoff_seqno_() +{} + +tonNode_getPrevBlocksDescription::tonNode_getPrevBlocksDescription(object_ptr &&next_block_, std::int32_t limit_, std::int32_t cutoff_seqno_) + : next_block_(std::move(next_block_)) + , limit_(limit_) + , cutoff_seqno_(cutoff_seqno_) +{} + +const std::int32_t tonNode_getPrevBlocksDescription::ID; + +object_ptr tonNode_getPrevBlocksDescription::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_getPrevBlocksDescription::tonNode_getPrevBlocksDescription(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : next_block_(TlFetchObject::parse(p)) + , limit_(TlFetchInt::parse(p)) + , cutoff_seqno_(TlFetchInt::parse(p)) +#undef FAIL +{} + +void tonNode_getPrevBlocksDescription::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(1550675145); + TlStoreObject::store(next_block_, s); + TlStoreBinary::store(limit_, s); + TlStoreBinary::store(cutoff_seqno_, s); +} + +void tonNode_getPrevBlocksDescription::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(1550675145); + TlStoreObject::store(next_block_, s); + TlStoreBinary::store(limit_, s); + TlStoreBinary::store(cutoff_seqno_, s); +} + +void tonNode_getPrevBlocksDescription::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_getPrevBlocksDescription"); + if (next_block_ == nullptr) { s.store_field("next_block", "null"); } else { next_block_->store(s, "next_block"); } + s.store_field("limit", limit_); + s.store_field("cutoff_seqno", cutoff_seqno_); + s.store_class_end(); + } +} + +tonNode_getPrevBlocksDescription::ReturnType tonNode_getPrevBlocksDescription::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchBoxed, -701865684>::parse(p); +#undef FAIL +} + tonNode_prepareBlock::tonNode_prepareBlock() : block_() {} @@ -15387,6 +16056,104 @@ tonNode_prepareBlockProof::ReturnType tonNode_prepareBlockProof::fetch_result(td #undef FAIL } +tonNode_prepareBlockProofs::tonNode_prepareBlockProofs() + : blocks_() + , allow_partial_() +{} + +tonNode_prepareBlockProofs::tonNode_prepareBlockProofs(std::vector> &&blocks_, bool allow_partial_) + : blocks_(std::move(blocks_)) + , allow_partial_(allow_partial_) +{} + +const std::int32_t tonNode_prepareBlockProofs::ID; + +object_ptr tonNode_prepareBlockProofs::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_prepareBlockProofs::tonNode_prepareBlockProofs(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : blocks_(TlFetchVector>::parse(p)) + , allow_partial_(TlFetchBool::parse(p)) +#undef FAIL +{} + +void tonNode_prepareBlockProofs::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(-310791496); + TlStoreVector::store(blocks_, s); + TlStoreBool::store(allow_partial_, s); +} + +void tonNode_prepareBlockProofs::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(-310791496); + TlStoreVector::store(blocks_, s); + TlStoreBool::store(allow_partial_, s); +} + +void tonNode_prepareBlockProofs::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_prepareBlockProofs"); + { const std::vector> &v = blocks_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("blocks", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); } + s.store_field("allow_partial", allow_partial_); + s.store_class_end(); + } +} + +tonNode_prepareBlockProofs::ReturnType tonNode_prepareBlockProofs::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchObject::parse(p); +#undef FAIL +} + +tonNode_prepareBlocks::tonNode_prepareBlocks() + : blocks_() +{} + +tonNode_prepareBlocks::tonNode_prepareBlocks(std::vector> &&blocks_) + : blocks_(std::move(blocks_)) +{} + +const std::int32_t tonNode_prepareBlocks::ID; + +object_ptr tonNode_prepareBlocks::fetch(td::TlParser &p) { + return make_object(p); +} + +tonNode_prepareBlocks::tonNode_prepareBlocks(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : blocks_(TlFetchVector>::parse(p)) +#undef FAIL +{} + +void tonNode_prepareBlocks::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + s.store_binary(1795140604); + TlStoreVector::store(blocks_, s); +} + +void tonNode_prepareBlocks::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + s.store_binary(1795140604); + TlStoreVector::store(blocks_, s); +} + +void tonNode_prepareBlocks::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "tonNode_prepareBlocks"); + { const std::vector> &v = blocks_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("blocks", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); } + s.store_class_end(); + } +} + +tonNode_prepareBlocks::ReturnType tonNode_prepareBlocks::fetch_result(td::TlParser &p) { +#define FAIL(error) p.set_error(error); return ReturnType() + return TlFetchObject::parse(p); +#undef FAIL +} + tonNode_preparePersistentState::tonNode_preparePersistentState() : block_() , masterchain_block_() @@ -15546,13 +16313,13 @@ tonNode_slave_sendExtMessage::tonNode_slave_sendExtMessage(td::TlParser &p) void tonNode_slave_sendExtMessage::store(td::TlStorerCalcLength &s) const { (void)sizeof(s); - s.store_binary(2067425040); + s.store_binary(58127017); TlStoreObject::store(message_, s); } void tonNode_slave_sendExtMessage::store(td::TlStorerUnsafe &s) const { (void)sizeof(s); - s.store_binary(2067425040); + s.store_binary(58127017); TlStoreObject::store(message_, s); } @@ -15566,7 +16333,7 @@ void tonNode_slave_sendExtMessage::store(td::TlStorerToString &s, const char *fi tonNode_slave_sendExtMessage::ReturnType tonNode_slave_sendExtMessage::fetch_result(td::TlParser &p) { #define FAIL(error) p.set_error(error); return ReturnType() - return TlFetchBoxed::parse(p); + return TlFetchBoxed, -1063902129>::parse(p); #undef FAIL } diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h index 41eec24536..537ece403d 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h @@ -310,10 +310,18 @@ class tonNode_blockIdExt; class tonNode_blockSignature; +class tonNode_blocksDescription; + class tonNode_Broadcast; +class tonNode_capabilities; + class tonNode_data; +class tonNode_DataFull; + +class tonNode_dataList; + class tonNode_externalMessage; class tonNode_ihrMessage; @@ -332,6 +340,8 @@ class tonNode_sessionId; class tonNode_shardPublicOverlayId; +class tonNode_success; + class tonNode_zeroStateIdExt; class validator_group; @@ -5806,6 +5816,31 @@ class tonNode_blockSignature final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class tonNode_blocksDescription final : public Object { + public: + std::vector> ids_; + bool incomplete_; + + tonNode_blocksDescription(); + + tonNode_blocksDescription(std::vector> &&ids_, bool incomplete_); + + static const std::int32_t ID = -701865684; + std::int32_t get_id() const final { + return ID; + } + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_blocksDescription(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class tonNode_Broadcast: public Object { public: @@ -5913,6 +5948,31 @@ class tonNode_newShardBlockBroadcast final : public tonNode_Broadcast { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class tonNode_capabilities final : public Object { + public: + std::int32_t version_; + std::int64_t capabilities_; + + tonNode_capabilities(); + + tonNode_capabilities(std::int32_t version_, std::int64_t capabilities_); + + static const std::int32_t ID = -172007232; + std::int32_t get_id() const final { + return ID; + } + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_capabilities(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class tonNode_data final : public Object { public: td::BufferSlice data_; @@ -5937,6 +5997,84 @@ class tonNode_data final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class tonNode_DataFull: public Object { + public: + + static object_ptr fetch(td::TlParser &p); +}; + +class tonNode_dataFull final : public tonNode_DataFull { + public: + object_ptr id_; + td::BufferSlice proof_; + td::BufferSlice block_; + bool is_link_; + + tonNode_dataFull(); + + tonNode_dataFull(object_ptr &&id_, td::BufferSlice &&proof_, td::BufferSlice &&block_, bool is_link_); + + static const std::int32_t ID = -1101488237; + std::int32_t get_id() const final { + return ID; + } + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_dataFull(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class tonNode_dataFullEmpty final : public tonNode_DataFull { + public: + + tonNode_dataFullEmpty(); + + static const std::int32_t ID = 1466861002; + std::int32_t get_id() const final { + return ID; + } + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_dataFullEmpty(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class tonNode_dataList final : public Object { + public: + std::vector data_; + + tonNode_dataList(); + + explicit tonNode_dataList(std::vector &&data_); + + static const std::int32_t ID = 351548179; + std::int32_t get_id() const final { + return ID; + } + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_dataList(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class tonNode_externalMessage final : public Object { public: td::BufferSlice data_; @@ -6255,6 +6393,27 @@ class tonNode_shardPublicOverlayId final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class tonNode_success final : public Object { + public: + + tonNode_success(); + + static const std::int32_t ID = -1063902129; + std::int32_t get_id() const final { + return ID; + } + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_success(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class tonNode_zeroStateIdExt final : public Object { public: std::int32_t workchain_; @@ -8201,6 +8360,34 @@ class tonNode_downloadBlock final : public Function { static ReturnType fetch_result(td::TlParser &p); }; +class tonNode_downloadBlockFull final : public Function { + public: + object_ptr block_; + + tonNode_downloadBlockFull(); + + explicit tonNode_downloadBlockFull(object_ptr &&block_); + + static const std::int32_t ID = 1780991133; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_downloadBlockFull(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + class tonNode_downloadBlockProof final : public Function { public: object_ptr block_; @@ -8257,6 +8444,118 @@ class tonNode_downloadBlockProofLink final : public Function { static ReturnType fetch_result(td::TlParser &p); }; +class tonNode_downloadBlockProofLinks final : public Function { + public: + std::vector> blocks_; + + tonNode_downloadBlockProofLinks(); + + explicit tonNode_downloadBlockProofLinks(std::vector> &&blocks_); + + static const std::int32_t ID = 684796771; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_downloadBlockProofLinks(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + +class tonNode_downloadBlockProofs final : public Function { + public: + std::vector> blocks_; + + tonNode_downloadBlockProofs(); + + explicit tonNode_downloadBlockProofs(std::vector> &&blocks_); + + static const std::int32_t ID = -1515170827; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_downloadBlockProofs(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + +class tonNode_downloadBlocks final : public Function { + public: + std::vector> blocks_; + + tonNode_downloadBlocks(); + + explicit tonNode_downloadBlocks(std::vector> &&blocks_); + + static const std::int32_t ID = 1985594749; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_downloadBlocks(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + +class tonNode_downloadNextBlockFull final : public Function { + public: + object_ptr prev_block_; + + tonNode_downloadNextBlockFull(); + + explicit tonNode_downloadNextBlockFull(object_ptr &&prev_block_); + + static const std::int32_t ID = 1855993674; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_downloadNextBlockFull(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + class tonNode_downloadPersistentState final : public Function { public: object_ptr block_; @@ -8345,6 +8644,31 @@ class tonNode_downloadZeroState final : public Function { static ReturnType fetch_result(td::TlParser &p); }; +class tonNode_getCapabilities final : public Function { + public: + + tonNode_getCapabilities(); + + static const std::int32_t ID = -555345672; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_getCapabilities(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + class tonNode_getNextBlockDescription final : public Function { public: object_ptr prev_block_; @@ -8373,6 +8697,35 @@ class tonNode_getNextBlockDescription final : public Function { static ReturnType fetch_result(td::TlParser &p); }; +class tonNode_getNextBlocksDescription final : public Function { + public: + object_ptr prev_block_; + std::int32_t limit_; + + tonNode_getNextBlocksDescription(); + + tonNode_getNextBlocksDescription(object_ptr &&prev_block_, std::int32_t limit_); + + static const std::int32_t ID = 1059590852; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_getNextBlocksDescription(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + class tonNode_getNextKeyBlockIds final : public Function { public: object_ptr block_; @@ -8402,6 +8755,36 @@ class tonNode_getNextKeyBlockIds final : public Function { static ReturnType fetch_result(td::TlParser &p); }; +class tonNode_getPrevBlocksDescription final : public Function { + public: + object_ptr next_block_; + std::int32_t limit_; + std::int32_t cutoff_seqno_; + + tonNode_getPrevBlocksDescription(); + + tonNode_getPrevBlocksDescription(object_ptr &&next_block_, std::int32_t limit_, std::int32_t cutoff_seqno_); + + static const std::int32_t ID = 1550675145; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_getPrevBlocksDescription(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + class tonNode_prepareBlock final : public Function { public: object_ptr block_; @@ -8459,6 +8842,63 @@ class tonNode_prepareBlockProof final : public Function { static ReturnType fetch_result(td::TlParser &p); }; +class tonNode_prepareBlockProofs final : public Function { + public: + std::vector> blocks_; + bool allow_partial_; + + tonNode_prepareBlockProofs(); + + tonNode_prepareBlockProofs(std::vector> &&blocks_, bool allow_partial_); + + static const std::int32_t ID = -310791496; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_prepareBlockProofs(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + +class tonNode_prepareBlocks final : public Function { + public: + std::vector> blocks_; + + tonNode_prepareBlocks(); + + explicit tonNode_prepareBlocks(std::vector> &&blocks_); + + static const std::int32_t ID = 1795140604; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + static object_ptr fetch(td::TlParser &p); + + explicit tonNode_prepareBlocks(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; + + static ReturnType fetch_result(td::TlParser &p); +}; + class tonNode_preparePersistentState final : public Function { public: object_ptr block_; @@ -8549,12 +8989,12 @@ class tonNode_slave_sendExtMessage final : public Function { explicit tonNode_slave_sendExtMessage(object_ptr &&message_); - static const std::int32_t ID = 2067425040; + static const std::int32_t ID = 58127017; std::int32_t get_id() const final { return ID; } - using ReturnType = bool; + using ReturnType = object_ptr; static object_ptr fetch(td::TlParser &p); diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.hpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.hpp index 6471596805..1f033147db 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.hpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.hpp @@ -647,6 +647,9 @@ bool downcast_call(Object &obj, const T &func) { case tonNode_blockSignature::ID: func(static_cast(obj)); return true; + case tonNode_blocksDescription::ID: + func(static_cast(obj)); + return true; case tonNode_blockBroadcast::ID: func(static_cast(obj)); return true; @@ -659,9 +662,21 @@ bool downcast_call(Object &obj, const T &func) { case tonNode_newShardBlockBroadcast::ID: func(static_cast(obj)); return true; + case tonNode_capabilities::ID: + func(static_cast(obj)); + return true; case tonNode_data::ID: func(static_cast(obj)); return true; + case tonNode_dataFull::ID: + func(static_cast(obj)); + return true; + case tonNode_dataFullEmpty::ID: + func(static_cast(obj)); + return true; + case tonNode_dataList::ID: + func(static_cast(obj)); + return true; case tonNode_externalMessage::ID: func(static_cast(obj)); return true; @@ -701,6 +716,9 @@ bool downcast_call(Object &obj, const T &func) { case tonNode_shardPublicOverlayId::ID: func(static_cast(obj)); return true; + case tonNode_success::ID: + func(static_cast(obj)); + return true; case tonNode_zeroStateIdExt::ID: func(static_cast(obj)); return true; @@ -925,12 +943,27 @@ bool downcast_call(Function &obj, const T &func) { case tonNode_downloadBlock::ID: func(static_cast(obj)); return true; + case tonNode_downloadBlockFull::ID: + func(static_cast(obj)); + return true; case tonNode_downloadBlockProof::ID: func(static_cast(obj)); return true; case tonNode_downloadBlockProofLink::ID: func(static_cast(obj)); return true; + case tonNode_downloadBlockProofLinks::ID: + func(static_cast(obj)); + return true; + case tonNode_downloadBlockProofs::ID: + func(static_cast(obj)); + return true; + case tonNode_downloadBlocks::ID: + func(static_cast(obj)); + return true; + case tonNode_downloadNextBlockFull::ID: + func(static_cast(obj)); + return true; case tonNode_downloadPersistentState::ID: func(static_cast(obj)); return true; @@ -940,18 +973,33 @@ bool downcast_call(Function &obj, const T &func) { case tonNode_downloadZeroState::ID: func(static_cast(obj)); return true; + case tonNode_getCapabilities::ID: + func(static_cast(obj)); + return true; case tonNode_getNextBlockDescription::ID: func(static_cast(obj)); return true; + case tonNode_getNextBlocksDescription::ID: + func(static_cast(obj)); + return true; case tonNode_getNextKeyBlockIds::ID: func(static_cast(obj)); return true; + case tonNode_getPrevBlocksDescription::ID: + func(static_cast(obj)); + return true; case tonNode_prepareBlock::ID: func(static_cast(obj)); return true; case tonNode_prepareBlockProof::ID: func(static_cast(obj)); return true; + case tonNode_prepareBlockProofs::ID: + func(static_cast(obj)); + return true; + case tonNode_prepareBlocks::ID: + func(static_cast(obj)); + return true; case tonNode_preparePersistentState::ID: func(static_cast(obj)); return true; @@ -1743,6 +1791,26 @@ bool downcast_call(tonNode_Broadcast &obj, const T &func) { } } +/** + * Calls specified function object with the specified object downcasted to the most-derived type. + * \param[in] obj Object to pass as an argument to the function object. + * \param[in] func Function object to which the object will be passed. + * \returns whether function object call has happened. Should always return true for correct parameters. + */ +template +bool downcast_call(tonNode_DataFull &obj, const T &func) { + switch (obj.get_id()) { + case tonNode_dataFull::ID: + func(static_cast(obj)); + return true; + case tonNode_dataFullEmpty::ID: + func(static_cast(obj)); + return true; + default: + return false; + } +} + /** * Calls specified function object with the specified object downcasted to the most-derived type. * \param[in] obj Object to pass as an argument to the function object. diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp index d08d906c9d..66c7c9df17 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp @@ -400,6 +400,17 @@ Result tl_constructor_from_string(ton_api::tonNode_Broadcast *object, con } return it->second; } +Result tl_constructor_from_string(ton_api::tonNode_DataFull *object, const std::string &str) { + static const std::unordered_map m = { + {"tonNode.dataFull", -1101488237}, + {"tonNode.dataFullEmpty", 1466861002} + }; + auto it = m.find(str); + if (it == m.end()) { + return Status::Error(str + "Unknown class"); + } + return it->second; +} Result tl_constructor_from_string(ton_api::tonNode_Prepared *object, const std::string &str) { static const std::unordered_map m = { {"tonNode.prepared", -356205619}, @@ -686,11 +697,16 @@ Result tl_constructor_from_string(ton_api::Object *object, const std::str {"tonNode.blockId", -1211256473}, {"tonNode.blockIdExt", 1733487480}, {"tonNode.blockSignature", 1357921331}, + {"tonNode.blocksDescription", -701865684}, {"tonNode.blockBroadcast", -1372712699}, {"tonNode.ihrMessageBroadcast", 1381868723}, {"tonNode.externalMessageBroadcast", 1025185895}, {"tonNode.newShardBlockBroadcast", 183696060}, + {"tonNode.capabilities", -172007232}, {"tonNode.data", 1443505284}, + {"tonNode.dataFull", -1101488237}, + {"tonNode.dataFullEmpty", 1466861002}, + {"tonNode.dataList", 351548179}, {"tonNode.externalMessage", -596270583}, {"tonNode.ihrMessage", 1161085703}, {"tonNode.keyBlocks", 124144985}, @@ -704,6 +720,7 @@ Result tl_constructor_from_string(ton_api::Object *object, const std::str {"tonNode.notFoundState", 842598993}, {"tonNode.sessionId", 2056402618}, {"tonNode.shardPublicOverlayId", 1302254377}, + {"tonNode.success", -1063902129}, {"tonNode.zeroStateIdExt", 494024110}, {"validator.group", -120029535}, {"validator.config.global", -2038562966}, @@ -783,19 +800,29 @@ Result tl_constructor_from_string(ton_api::Function *object, const std::s {"overlay.query", -855800765}, {"tcp.ping", 1292381082}, {"tonNode.downloadBlock", -495814205}, + {"tonNode.downloadBlockFull", 1780991133}, {"tonNode.downloadBlockProof", 1272334218}, {"tonNode.downloadBlockProofLink", 632488134}, + {"tonNode.downloadBlockProofLinks", 684796771}, + {"tonNode.downloadBlockProofs", -1515170827}, + {"tonNode.downloadBlocks", 1985594749}, + {"tonNode.downloadNextBlockFull", 1855993674}, {"tonNode.downloadPersistentState", 2140791736}, {"tonNode.downloadPersistentStateSlice", -169220381}, {"tonNode.downloadZeroState", -1379131814}, + {"tonNode.getCapabilities", -555345672}, {"tonNode.getNextBlockDescription", 341160179}, + {"tonNode.getNextBlocksDescription", 1059590852}, {"tonNode.getNextKeyBlockIds", -219689029}, + {"tonNode.getPrevBlocksDescription", 1550675145}, {"tonNode.prepareBlock", 1973649230}, {"tonNode.prepareBlockProof", -2024000760}, + {"tonNode.prepareBlockProofs", -310791496}, + {"tonNode.prepareBlocks", 1795140604}, {"tonNode.preparePersistentState", -18209122}, {"tonNode.prepareZeroState", 1104021541}, {"tonNode.query", 1777542355}, - {"tonNode.slave.sendExtMessage", 2067425040}, + {"tonNode.slave.sendExtMessage", 58127017}, {"validatorSession.downloadCandidate", -520274443}, {"validatorSession.ping", 1745111469} }; @@ -4150,6 +4177,21 @@ Status from_json(ton_api::tonNode_blockSignature &to, JsonObject &from) { } return Status::OK(); } +Status from_json(ton_api::tonNode_blocksDescription &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "ids", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.ids_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "incomplete", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.incomplete_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::tonNode_blockBroadcast &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); @@ -4216,6 +4258,21 @@ Status from_json(ton_api::tonNode_newShardBlockBroadcast &to, JsonObject &from) } return Status::OK(); } +Status from_json(ton_api::tonNode_capabilities &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "version", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.version_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "capabilities", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.capabilities_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::tonNode_data &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "data", JsonValue::Type::Null, true)); @@ -4225,6 +4282,45 @@ Status from_json(ton_api::tonNode_data &to, JsonObject &from) { } return Status::OK(); } +Status from_json(ton_api::tonNode_dataFull &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.id_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "proof", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.proof_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "block", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.block_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "is_link", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.is_link_, value)); + } + } + return Status::OK(); +} +Status from_json(ton_api::tonNode_dataFullEmpty &to, JsonObject &from) { + return Status::OK(); +} +Status from_json(ton_api::tonNode_dataList &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "data", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_vector_bytes(to.data_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::tonNode_externalMessage &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "data", JsonValue::Type::Null, true)); @@ -4354,6 +4450,9 @@ Status from_json(ton_api::tonNode_shardPublicOverlayId &to, JsonObject &from) { } return Status::OK(); } +Status from_json(ton_api::tonNode_success &to, JsonObject &from) { + return Status::OK(); +} Status from_json(ton_api::tonNode_zeroStateIdExt &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "workchain", JsonValue::Type::Null, true)); @@ -5416,6 +5515,15 @@ Status from_json(ton_api::tonNode_downloadBlock &to, JsonObject &from) { } return Status::OK(); } +Status from_json(ton_api::tonNode_downloadBlockFull &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "block", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.block_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::tonNode_downloadBlockProof &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "block", JsonValue::Type::Null, true)); @@ -5434,6 +5542,42 @@ Status from_json(ton_api::tonNode_downloadBlockProofLink &to, JsonObject &from) } return Status::OK(); } +Status from_json(ton_api::tonNode_downloadBlockProofLinks &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "blocks", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.blocks_, value)); + } + } + return Status::OK(); +} +Status from_json(ton_api::tonNode_downloadBlockProofs &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "blocks", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.blocks_, value)); + } + } + return Status::OK(); +} +Status from_json(ton_api::tonNode_downloadBlocks &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "blocks", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.blocks_, value)); + } + } + return Status::OK(); +} +Status from_json(ton_api::tonNode_downloadNextBlockFull &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "prev_block", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.prev_block_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::tonNode_downloadPersistentState &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "block", JsonValue::Type::Null, true)); @@ -5485,6 +5629,9 @@ Status from_json(ton_api::tonNode_downloadZeroState &to, JsonObject &from) { } return Status::OK(); } +Status from_json(ton_api::tonNode_getCapabilities &to, JsonObject &from) { + return Status::OK(); +} Status from_json(ton_api::tonNode_getNextBlockDescription &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "prev_block", JsonValue::Type::Null, true)); @@ -5494,6 +5641,21 @@ Status from_json(ton_api::tonNode_getNextBlockDescription &to, JsonObject &from) } return Status::OK(); } +Status from_json(ton_api::tonNode_getNextBlocksDescription &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "prev_block", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.prev_block_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "limit", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.limit_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::tonNode_getNextKeyBlockIds &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "block", JsonValue::Type::Null, true)); @@ -5509,6 +5671,27 @@ Status from_json(ton_api::tonNode_getNextKeyBlockIds &to, JsonObject &from) { } return Status::OK(); } +Status from_json(ton_api::tonNode_getPrevBlocksDescription &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "next_block", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.next_block_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "limit", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.limit_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "cutoff_seqno", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.cutoff_seqno_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::tonNode_prepareBlock &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "block", JsonValue::Type::Null, true)); @@ -5533,6 +5716,30 @@ Status from_json(ton_api::tonNode_prepareBlockProof &to, JsonObject &from) { } return Status::OK(); } +Status from_json(ton_api::tonNode_prepareBlockProofs &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "blocks", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.blocks_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "allow_partial", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.allow_partial_, value)); + } + } + return Status::OK(); +} +Status from_json(ton_api::tonNode_prepareBlocks &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "blocks", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.blocks_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::tonNode_preparePersistentState &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "block", JsonValue::Type::Null, true)); @@ -7164,6 +7371,12 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_blockSignature &object) jo << ctie("who", ToJson(object.who_)); jo << ctie("signature", ToJson(JsonBytes{object.signature_})); } +void to_json(JsonValueScope &jv, const ton_api::tonNode_blocksDescription &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.blocksDescription"); + jo << ctie("ids", ToJson(object.ids_)); + jo << ctie("incomplete", ToJson(object.incomplete_)); +} void to_json(JsonValueScope &jv, const ton_api::tonNode_Broadcast &object) { ton_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); } @@ -7200,11 +7413,39 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_newShardBlockBroadcast & jo << ctie("block", ToJson(object.block_)); } } +void to_json(JsonValueScope &jv, const ton_api::tonNode_capabilities &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.capabilities"); + jo << ctie("version", ToJson(object.version_)); + jo << ctie("capabilities", ToJson(JsonInt64{object.capabilities_})); +} void to_json(JsonValueScope &jv, const ton_api::tonNode_data &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.data"); jo << ctie("data", ToJson(JsonBytes{object.data_})); } +void to_json(JsonValueScope &jv, const ton_api::tonNode_DataFull &object) { + ton_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); +} +void to_json(JsonValueScope &jv, const ton_api::tonNode_dataFull &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.dataFull"); + if (object.id_) { + jo << ctie("id", ToJson(object.id_)); + } + jo << ctie("proof", ToJson(JsonBytes{object.proof_})); + jo << ctie("block", ToJson(JsonBytes{object.block_})); + jo << ctie("is_link", ToJson(object.is_link_)); +} +void to_json(JsonValueScope &jv, const ton_api::tonNode_dataFullEmpty &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.dataFullEmpty"); +} +void to_json(JsonValueScope &jv, const ton_api::tonNode_dataList &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.dataList"); + jo << ctie("data", ToJson(JsonVectorBytes(object.data_))); +} void to_json(JsonValueScope &jv, const ton_api::tonNode_externalMessage &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.externalMessage"); @@ -7283,6 +7524,10 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_shardPublicOverlayId &ob jo << ctie("shard", ToJson(JsonInt64{object.shard_})); jo << ctie("zero_state_file_hash", ToJson(object.zero_state_file_hash_)); } +void to_json(JsonValueScope &jv, const ton_api::tonNode_success &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.success"); +} void to_json(JsonValueScope &jv, const ton_api::tonNode_zeroStateIdExt &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.zeroStateIdExt"); @@ -7736,6 +7981,13 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlock &object) { jo << ctie("block", ToJson(object.block_)); } } +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockFull &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.downloadBlockFull"); + if (object.block_) { + jo << ctie("block", ToJson(object.block_)); + } +} void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockProof &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.downloadBlockProof"); @@ -7750,6 +8002,28 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockProofLink & jo << ctie("block", ToJson(object.block_)); } } +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockProofLinks &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.downloadBlockProofLinks"); + jo << ctie("blocks", ToJson(object.blocks_)); +} +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockProofs &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.downloadBlockProofs"); + jo << ctie("blocks", ToJson(object.blocks_)); +} +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlocks &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.downloadBlocks"); + jo << ctie("blocks", ToJson(object.blocks_)); +} +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadNextBlockFull &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.downloadNextBlockFull"); + if (object.prev_block_) { + jo << ctie("prev_block", ToJson(object.prev_block_)); + } +} void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadPersistentState &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.downloadPersistentState"); @@ -7779,6 +8053,10 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadZeroState &objec jo << ctie("block", ToJson(object.block_)); } } +void to_json(JsonValueScope &jv, const ton_api::tonNode_getCapabilities &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.getCapabilities"); +} void to_json(JsonValueScope &jv, const ton_api::tonNode_getNextBlockDescription &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.getNextBlockDescription"); @@ -7786,6 +8064,14 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_getNextBlockDescription jo << ctie("prev_block", ToJson(object.prev_block_)); } } +void to_json(JsonValueScope &jv, const ton_api::tonNode_getNextBlocksDescription &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.getNextBlocksDescription"); + if (object.prev_block_) { + jo << ctie("prev_block", ToJson(object.prev_block_)); + } + jo << ctie("limit", ToJson(object.limit_)); +} void to_json(JsonValueScope &jv, const ton_api::tonNode_getNextKeyBlockIds &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.getNextKeyBlockIds"); @@ -7794,6 +8080,15 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_getNextKeyBlockIds &obje } jo << ctie("max_size", ToJson(object.max_size_)); } +void to_json(JsonValueScope &jv, const ton_api::tonNode_getPrevBlocksDescription &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.getPrevBlocksDescription"); + if (object.next_block_) { + jo << ctie("next_block", ToJson(object.next_block_)); + } + jo << ctie("limit", ToJson(object.limit_)); + jo << ctie("cutoff_seqno", ToJson(object.cutoff_seqno_)); +} void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareBlock &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.prepareBlock"); @@ -7809,6 +8104,17 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareBlockProof &objec } jo << ctie("allow_partial", ToJson(object.allow_partial_)); } +void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareBlockProofs &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.prepareBlockProofs"); + jo << ctie("blocks", ToJson(object.blocks_)); + jo << ctie("allow_partial", ToJson(object.allow_partial_)); +} +void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareBlocks &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "tonNode.prepareBlocks"); + jo << ctie("blocks", ToJson(object.blocks_)); +} void to_json(JsonValueScope &jv, const ton_api::tonNode_preparePersistentState &object) { auto jo = jv.enter_object(); jo << ctie("@type", "tonNode.preparePersistentState"); diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.h index a7e2b68ab8..cfa271e76f 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.h +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.h @@ -41,6 +41,7 @@ Result tl_constructor_from_string(ton_api::tcp_Message *object, const std Result tl_constructor_from_string(ton_api::ton_BlockId *object, const std::string &str); Result tl_constructor_from_string(ton_api::tonNode_BlockDescription *object, const std::string &str); Result tl_constructor_from_string(ton_api::tonNode_Broadcast *object, const std::string &str); +Result tl_constructor_from_string(ton_api::tonNode_DataFull *object, const std::string &str); Result tl_constructor_from_string(ton_api::tonNode_Prepared *object, const std::string &str); Result tl_constructor_from_string(ton_api::tonNode_PreparedProof *object, const std::string &str); Result tl_constructor_from_string(ton_api::tonNode_PreparedState *object, const std::string &str); @@ -260,11 +261,16 @@ Status from_json(ton_api::tonNode_blockDescription &to, JsonObject &from); Status from_json(ton_api::tonNode_blockId &to, JsonObject &from); Status from_json(ton_api::tonNode_blockIdExt &to, JsonObject &from); Status from_json(ton_api::tonNode_blockSignature &to, JsonObject &from); +Status from_json(ton_api::tonNode_blocksDescription &to, JsonObject &from); Status from_json(ton_api::tonNode_blockBroadcast &to, JsonObject &from); Status from_json(ton_api::tonNode_ihrMessageBroadcast &to, JsonObject &from); Status from_json(ton_api::tonNode_externalMessageBroadcast &to, JsonObject &from); Status from_json(ton_api::tonNode_newShardBlockBroadcast &to, JsonObject &from); +Status from_json(ton_api::tonNode_capabilities &to, JsonObject &from); Status from_json(ton_api::tonNode_data &to, JsonObject &from); +Status from_json(ton_api::tonNode_dataFull &to, JsonObject &from); +Status from_json(ton_api::tonNode_dataFullEmpty &to, JsonObject &from); +Status from_json(ton_api::tonNode_dataList &to, JsonObject &from); Status from_json(ton_api::tonNode_externalMessage &to, JsonObject &from); Status from_json(ton_api::tonNode_ihrMessage &to, JsonObject &from); Status from_json(ton_api::tonNode_keyBlocks &to, JsonObject &from); @@ -278,6 +284,7 @@ Status from_json(ton_api::tonNode_preparedState &to, JsonObject &from); Status from_json(ton_api::tonNode_notFoundState &to, JsonObject &from); Status from_json(ton_api::tonNode_sessionId &to, JsonObject &from); Status from_json(ton_api::tonNode_shardPublicOverlayId &to, JsonObject &from); +Status from_json(ton_api::tonNode_success &to, JsonObject &from); Status from_json(ton_api::tonNode_zeroStateIdExt &to, JsonObject &from); Status from_json(ton_api::validator_group &to, JsonObject &from); Status from_json(ton_api::validator_config_global &to, JsonObject &from); @@ -348,15 +355,25 @@ Status from_json(ton_api::overlay_getRandomPeers &to, JsonObject &from); Status from_json(ton_api::overlay_query &to, JsonObject &from); Status from_json(ton_api::tcp_ping &to, JsonObject &from); Status from_json(ton_api::tonNode_downloadBlock &to, JsonObject &from); +Status from_json(ton_api::tonNode_downloadBlockFull &to, JsonObject &from); Status from_json(ton_api::tonNode_downloadBlockProof &to, JsonObject &from); Status from_json(ton_api::tonNode_downloadBlockProofLink &to, JsonObject &from); +Status from_json(ton_api::tonNode_downloadBlockProofLinks &to, JsonObject &from); +Status from_json(ton_api::tonNode_downloadBlockProofs &to, JsonObject &from); +Status from_json(ton_api::tonNode_downloadBlocks &to, JsonObject &from); +Status from_json(ton_api::tonNode_downloadNextBlockFull &to, JsonObject &from); Status from_json(ton_api::tonNode_downloadPersistentState &to, JsonObject &from); Status from_json(ton_api::tonNode_downloadPersistentStateSlice &to, JsonObject &from); Status from_json(ton_api::tonNode_downloadZeroState &to, JsonObject &from); +Status from_json(ton_api::tonNode_getCapabilities &to, JsonObject &from); Status from_json(ton_api::tonNode_getNextBlockDescription &to, JsonObject &from); +Status from_json(ton_api::tonNode_getNextBlocksDescription &to, JsonObject &from); Status from_json(ton_api::tonNode_getNextKeyBlockIds &to, JsonObject &from); +Status from_json(ton_api::tonNode_getPrevBlocksDescription &to, JsonObject &from); Status from_json(ton_api::tonNode_prepareBlock &to, JsonObject &from); Status from_json(ton_api::tonNode_prepareBlockProof &to, JsonObject &from); +Status from_json(ton_api::tonNode_prepareBlockProofs &to, JsonObject &from); +Status from_json(ton_api::tonNode_prepareBlocks &to, JsonObject &from); Status from_json(ton_api::tonNode_preparePersistentState &to, JsonObject &from); Status from_json(ton_api::tonNode_prepareZeroState &to, JsonObject &from); Status from_json(ton_api::tonNode_query &to, JsonObject &from); @@ -603,12 +620,18 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_blockDescription &object void to_json(JsonValueScope &jv, const ton_api::tonNode_blockId &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_blockIdExt &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_blockSignature &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_blocksDescription &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_Broadcast &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_blockBroadcast &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_ihrMessageBroadcast &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_externalMessageBroadcast &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_newShardBlockBroadcast &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_capabilities &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_data &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_DataFull &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_dataFull &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_dataFullEmpty &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_dataList &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_externalMessage &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_ihrMessage &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_keyBlocks &object); @@ -625,6 +648,7 @@ void to_json(JsonValueScope &jv, const ton_api::tonNode_preparedState &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_notFoundState &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_sessionId &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_shardPublicOverlayId &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_success &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_zeroStateIdExt &object); void to_json(JsonValueScope &jv, const ton_api::validator_group &object); void to_json(JsonValueScope &jv, const ton_api::validator_config_global &object); @@ -698,15 +722,25 @@ void to_json(JsonValueScope &jv, const ton_api::overlay_getRandomPeers &object); void to_json(JsonValueScope &jv, const ton_api::overlay_query &object); void to_json(JsonValueScope &jv, const ton_api::tcp_ping &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlock &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockFull &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockProof &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockProofLink &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockProofLinks &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlockProofs &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadBlocks &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadNextBlockFull &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadPersistentState &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadPersistentStateSlice &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_downloadZeroState &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_getCapabilities &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_getNextBlockDescription &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_getNextBlocksDescription &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_getNextKeyBlockIds &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_getPrevBlocksDescription &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareBlock &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareBlockProof &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareBlockProofs &object); +void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareBlocks &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_preparePersistentState &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_prepareZeroState &object); void to_json(JsonValueScope &jv, const ton_api::tonNode_query &object); diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp index 0a6d3b95d8..42cb78eaac 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp @@ -172,6 +172,87 @@ void key::store(td::TlStorerToString &s, const char *field_name) const { } } +logStreamDefault::logStreamDefault() { +} + +const std::int32_t logStreamDefault::ID; + +void logStreamDefault::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "logStreamDefault"); + s.store_class_end(); + } +} + +logStreamFile::logStreamFile() + : path_() + , max_file_size_() +{} + +logStreamFile::logStreamFile(std::string const &path_, std::int64_t max_file_size_) + : path_(std::move(path_)) + , max_file_size_(max_file_size_) +{} + +const std::int32_t logStreamFile::ID; + +void logStreamFile::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "logStreamFile"); + s.store_field("path", path_); + s.store_field("max_file_size", max_file_size_); + s.store_class_end(); + } +} + +logStreamEmpty::logStreamEmpty() { +} + +const std::int32_t logStreamEmpty::ID; + +void logStreamEmpty::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "logStreamEmpty"); + s.store_class_end(); + } +} + +logTags::logTags() + : tags_() +{} + +logTags::logTags(std::vector &&tags_) + : tags_(std::move(tags_)) +{} + +const std::int32_t logTags::ID; + +void logTags::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "logTags"); + { const std::vector &v = tags_; const std::uint32_t multiplicity = static_cast(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("tags", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { s.store_field("", v[i]); } s.store_class_end(); } + s.store_class_end(); + } +} + +logVerbosityLevel::logVerbosityLevel() + : verbosity_level_() +{} + +logVerbosityLevel::logVerbosityLevel(std::int32_t verbosity_level_) + : verbosity_level_(verbosity_level_) +{} + +const std::int32_t logVerbosityLevel::ID; + +void logVerbosityLevel::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "logVerbosityLevel"); + s.store_field("verbosity_level", verbosity_level_); + s.store_class_end(); + } +} + ok::ok() { } @@ -265,6 +346,24 @@ void generic_accountStateTestWallet::store(td::TlStorerToString &s, const char * } } +generic_accountStateWallet::generic_accountStateWallet() + : account_state_() +{} + +generic_accountStateWallet::generic_accountStateWallet(object_ptr &&account_state_) + : account_state_(std::move(account_state_)) +{} + +const std::int32_t generic_accountStateWallet::ID; + +void generic_accountStateWallet::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "generic_accountStateWallet"); + if (account_state_ == nullptr) { s.store_field("account_state", "null"); } else { account_state_->store(s, "account_state"); } + s.store_class_end(); + } +} + generic_accountStateTestGiver::generic_accountStateTestGiver() : account_state_() {} @@ -301,42 +400,6 @@ void generic_accountStateUninited::store(td::TlStorerToString &s, const char *fi } } -generic_initialAccountStateRaw::generic_initialAccountStateRaw() - : initital_account_state_() -{} - -generic_initialAccountStateRaw::generic_initialAccountStateRaw(object_ptr &&initital_account_state_) - : initital_account_state_(std::move(initital_account_state_)) -{} - -const std::int32_t generic_initialAccountStateRaw::ID; - -void generic_initialAccountStateRaw::store(td::TlStorerToString &s, const char *field_name) const { - if (!LOG_IS_STRIPPED(ERROR)) { - s.store_class_begin(field_name, "generic_initialAccountStateRaw"); - if (initital_account_state_ == nullptr) { s.store_field("initital_account_state", "null"); } else { initital_account_state_->store(s, "initital_account_state"); } - s.store_class_end(); - } -} - -generic_initialAccountStateTestWallet::generic_initialAccountStateTestWallet() - : initital_account_state_() -{} - -generic_initialAccountStateTestWallet::generic_initialAccountStateTestWallet(object_ptr &&initital_account_state_) - : initital_account_state_(std::move(initital_account_state_)) -{} - -const std::int32_t generic_initialAccountStateTestWallet::ID; - -void generic_initialAccountStateTestWallet::store(td::TlStorerToString &s, const char *field_name) const { - if (!LOG_IS_STRIPPED(ERROR)) { - s.store_class_begin(field_name, "generic_initialAccountStateTestWallet"); - if (initital_account_state_ == nullptr) { s.store_field("initital_account_state", "null"); } else { initital_account_state_->store(s, "initital_account_state"); } - s.store_class_end(); - } -} - internal_transactionId::internal_transactionId() : lt_() , hash_() @@ -586,6 +649,72 @@ void uninited_accountState::store(td::TlStorerToString &s, const char *field_nam } } +wallet_accountState::wallet_accountState() + : balance_() + , seqno_() + , last_transaction_id_() + , sync_utime_() +{} + +wallet_accountState::wallet_accountState(std::int64_t balance_, std::int32_t seqno_, object_ptr &&last_transaction_id_, std::int64_t sync_utime_) + : balance_(balance_) + , seqno_(seqno_) + , last_transaction_id_(std::move(last_transaction_id_)) + , sync_utime_(sync_utime_) +{} + +const std::int32_t wallet_accountState::ID; + +void wallet_accountState::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "wallet_accountState"); + s.store_field("balance", balance_); + s.store_field("seqno", seqno_); + if (last_transaction_id_ == nullptr) { s.store_field("last_transaction_id", "null"); } else { last_transaction_id_->store(s, "last_transaction_id"); } + s.store_field("sync_utime", sync_utime_); + s.store_class_end(); + } +} + +wallet_initialAccountState::wallet_initialAccountState() + : public_key_() +{} + +wallet_initialAccountState::wallet_initialAccountState(std::string const &public_key_) + : public_key_(std::move(public_key_)) +{} + +const std::int32_t wallet_initialAccountState::ID; + +void wallet_initialAccountState::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "wallet_initialAccountState"); + s.store_field("public_key", public_key_); + s.store_class_end(); + } +} + +addLogMessage::addLogMessage() + : verbosity_level_() + , text_() +{} + +addLogMessage::addLogMessage(std::int32_t verbosity_level_, std::string const &text_) + : verbosity_level_(verbosity_level_) + , text_(std::move(text_)) +{} + +const std::int32_t addLogMessage::ID; + +void addLogMessage::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "addLogMessage"); + s.store_field("verbosity_level", verbosity_level_); + s.store_field("text", text_); + s.store_class_end(); + } +} + changeLocalPassword::changeLocalPassword() : input_key_() , new_local_password_() @@ -644,11 +773,11 @@ void createNewKey::store(td::TlStorerToString &s, const char *field_name) const } deleteKey::deleteKey() - : public_key_() + : key_() {} -deleteKey::deleteKey(std::string const &public_key_) - : public_key_(std::move(public_key_)) +deleteKey::deleteKey(object_ptr &&key_) + : key_(std::move(key_)) {} const std::int32_t deleteKey::ID; @@ -656,7 +785,7 @@ const std::int32_t deleteKey::ID; void deleteKey::store(td::TlStorerToString &s, const char *field_name) const { if (!LOG_IS_STRIPPED(ERROR)) { s.store_class_begin(field_name, "deleteKey"); - s.store_field("public_key", public_key_); + if (key_ == nullptr) { s.store_field("key", "null"); } else { key_->store(s, "key"); } s.store_class_end(); } } @@ -787,6 +916,60 @@ void getBip39Hints::store(td::TlStorerToString &s, const char *field_name) const } } +getLogStream::getLogStream() { +} + +const std::int32_t getLogStream::ID; + +void getLogStream::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "getLogStream"); + s.store_class_end(); + } +} + +getLogTagVerbosityLevel::getLogTagVerbosityLevel() + : tag_() +{} + +getLogTagVerbosityLevel::getLogTagVerbosityLevel(std::string const &tag_) + : tag_(std::move(tag_)) +{} + +const std::int32_t getLogTagVerbosityLevel::ID; + +void getLogTagVerbosityLevel::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "getLogTagVerbosityLevel"); + s.store_field("tag", tag_); + s.store_class_end(); + } +} + +getLogTags::getLogTags() { +} + +const std::int32_t getLogTags::ID; + +void getLogTags::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "getLogTags"); + s.store_class_end(); + } +} + +getLogVerbosityLevel::getLogVerbosityLevel() { +} + +const std::int32_t getLogVerbosityLevel::ID; + +void getLogVerbosityLevel::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "getLogVerbosityLevel"); + s.store_class_end(); + } +} + importEncryptedKey::importEncryptedKey() : local_password_() , key_password_() @@ -1036,6 +1219,63 @@ void runTests::store(td::TlStorerToString &s, const char *field_name) const { } } +setLogStream::setLogStream() + : log_stream_() +{} + +setLogStream::setLogStream(object_ptr &&log_stream_) + : log_stream_(std::move(log_stream_)) +{} + +const std::int32_t setLogStream::ID; + +void setLogStream::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "setLogStream"); + if (log_stream_ == nullptr) { s.store_field("log_stream", "null"); } else { log_stream_->store(s, "log_stream"); } + s.store_class_end(); + } +} + +setLogTagVerbosityLevel::setLogTagVerbosityLevel() + : tag_() + , new_verbosity_level_() +{} + +setLogTagVerbosityLevel::setLogTagVerbosityLevel(std::string const &tag_, std::int32_t new_verbosity_level_) + : tag_(std::move(tag_)) + , new_verbosity_level_(new_verbosity_level_) +{} + +const std::int32_t setLogTagVerbosityLevel::ID; + +void setLogTagVerbosityLevel::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "setLogTagVerbosityLevel"); + s.store_field("tag", tag_); + s.store_field("new_verbosity_level", new_verbosity_level_); + s.store_class_end(); + } +} + +setLogVerbosityLevel::setLogVerbosityLevel() + : new_verbosity_level_() +{} + +setLogVerbosityLevel::setLogVerbosityLevel(std::int32_t new_verbosity_level_) + : new_verbosity_level_(new_verbosity_level_) +{} + +const std::int32_t setLogVerbosityLevel::ID; + +void setLogVerbosityLevel::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "setLogVerbosityLevel"); + s.store_field("new_verbosity_level", new_verbosity_level_); + s.store_class_end(); + } +} + testGiver_getAccountAddress::testGiver_getAccountAddress() { } @@ -1170,5 +1410,92 @@ void testWallet_sendGrams::store(td::TlStorerToString &s, const char *field_name s.store_class_end(); } } + +wallet_getAccountAddress::wallet_getAccountAddress() + : initital_account_state_() +{} + +wallet_getAccountAddress::wallet_getAccountAddress(object_ptr &&initital_account_state_) + : initital_account_state_(std::move(initital_account_state_)) +{} + +const std::int32_t wallet_getAccountAddress::ID; + +void wallet_getAccountAddress::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "wallet_getAccountAddress"); + if (initital_account_state_ == nullptr) { s.store_field("initital_account_state", "null"); } else { initital_account_state_->store(s, "initital_account_state"); } + s.store_class_end(); + } +} + +wallet_getAccountState::wallet_getAccountState() + : account_address_() +{} + +wallet_getAccountState::wallet_getAccountState(object_ptr &&account_address_) + : account_address_(std::move(account_address_)) +{} + +const std::int32_t wallet_getAccountState::ID; + +void wallet_getAccountState::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "wallet_getAccountState"); + if (account_address_ == nullptr) { s.store_field("account_address", "null"); } else { account_address_->store(s, "account_address"); } + s.store_class_end(); + } +} + +wallet_init::wallet_init() + : private_key_() +{} + +wallet_init::wallet_init(object_ptr &&private_key_) + : private_key_(std::move(private_key_)) +{} + +const std::int32_t wallet_init::ID; + +void wallet_init::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "wallet_init"); + if (private_key_ == nullptr) { s.store_field("private_key", "null"); } else { private_key_->store(s, "private_key"); } + s.store_class_end(); + } +} + +wallet_sendGrams::wallet_sendGrams() + : private_key_() + , destination_() + , seqno_() + , valid_until_() + , amount_() + , message_() +{} + +wallet_sendGrams::wallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t valid_until_, std::int64_t amount_, std::string const &message_) + : private_key_(std::move(private_key_)) + , destination_(std::move(destination_)) + , seqno_(seqno_) + , valid_until_(valid_until_) + , amount_(amount_) + , message_(std::move(message_)) +{} + +const std::int32_t wallet_sendGrams::ID; + +void wallet_sendGrams::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "wallet_sendGrams"); + if (private_key_ == nullptr) { s.store_field("private_key", "null"); } else { private_key_->store(s, "private_key"); } + if (destination_ == nullptr) { s.store_field("destination", "null"); } else { destination_->store(s, "destination"); } + s.store_field("seqno", seqno_); + s.store_field("valid_until", valid_until_); + s.store_field("amount", amount_); + s.store_bytes_field("message", message_); + s.store_class_end(); + } +} } // namespace tonlib_api } // namespace ton diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h index 36277cd3a0..b1fabda282 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h @@ -60,6 +60,12 @@ class inputKey; class key; +class LogStream; + +class logTags; + +class logVerbosityLevel; + class ok; class options; @@ -68,8 +74,6 @@ class updateSendLiteServerQuery; class generic_AccountState; -class generic_InitialAccountState; - class internal_transactionId; class raw_accountState; @@ -90,6 +94,10 @@ class testWallet_initialAccountState; class uninited_accountState; +class wallet_accountState; + +class wallet_initialAccountState; + class Object; class Object: public TlObject { @@ -231,6 +239,85 @@ class key final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class LogStream: public Object { + public: +}; + +class logStreamDefault final : public LogStream { + public: + + logStreamDefault(); + + static const std::int32_t ID = 1390581436; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class logStreamFile final : public LogStream { + public: + std::string path_; + std::int64_t max_file_size_; + + logStreamFile(); + + logStreamFile(std::string const &path_, std::int64_t max_file_size_); + + static const std::int32_t ID = -1880085930; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class logStreamEmpty final : public LogStream { + public: + + logStreamEmpty(); + + static const std::int32_t ID = -499912244; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class logTags final : public Object { + public: + std::vector tags_; + + logTags(); + + explicit logTags(std::vector &&tags_); + + static const std::int32_t ID = -1604930601; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class logVerbosityLevel final : public Object { + public: + std::int32_t verbosity_level_; + + logVerbosityLevel(); + + explicit logVerbosityLevel(std::int32_t verbosity_level_); + + static const std::int32_t ID = 1734624234; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class ok final : public Object { public: @@ -315,6 +402,22 @@ class generic_accountStateTestWallet final : public generic_AccountState { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class generic_accountStateWallet final : public generic_AccountState { + public: + object_ptr account_state_; + + generic_accountStateWallet(); + + explicit generic_accountStateWallet(object_ptr &&account_state_); + + static const std::int32_t ID = 942582925; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class generic_accountStateTestGiver final : public generic_AccountState { public: object_ptr account_state_; @@ -347,42 +450,6 @@ class generic_accountStateUninited final : public generic_AccountState { void store(td::TlStorerToString &s, const char *field_name) const final; }; -class generic_InitialAccountState: public Object { - public: -}; - -class generic_initialAccountStateRaw final : public generic_InitialAccountState { - public: - object_ptr initital_account_state_; - - generic_initialAccountStateRaw(); - - explicit generic_initialAccountStateRaw(object_ptr &&initital_account_state_); - - static const std::int32_t ID = -1178429153; - std::int32_t get_id() const final { - return ID; - } - - void store(td::TlStorerToString &s, const char *field_name) const final; -}; - -class generic_initialAccountStateTestWallet final : public generic_InitialAccountState { - public: - object_ptr initital_account_state_; - - generic_initialAccountStateTestWallet(); - - explicit generic_initialAccountStateTestWallet(object_ptr &&initital_account_state_); - - static const std::int32_t ID = 710924204; - std::int32_t get_id() const final { - return ID; - } - - void store(td::TlStorerToString &s, const char *field_name) const final; -}; - class internal_transactionId final : public Object { public: std::int64_t lt_; @@ -566,6 +633,60 @@ class uninited_accountState final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class wallet_accountState final : public Object { + public: + std::int64_t balance_; + std::int32_t seqno_; + object_ptr last_transaction_id_; + std::int64_t sync_utime_; + + wallet_accountState(); + + wallet_accountState(std::int64_t balance_, std::int32_t seqno_, object_ptr &&last_transaction_id_, std::int64_t sync_utime_); + + static const std::int32_t ID = -1919815977; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class wallet_initialAccountState final : public Object { + public: + std::string public_key_; + + wallet_initialAccountState(); + + explicit wallet_initialAccountState(std::string const &public_key_); + + static const std::int32_t ID = -1079249978; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class addLogMessage final : public Function { + public: + std::int32_t verbosity_level_; + std::string text_; + + addLogMessage(); + + addLogMessage(std::int32_t verbosity_level_, std::string const &text_); + + static const std::int32_t ID = 1597427692; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class changeLocalPassword final : public Function { public: object_ptr input_key_; @@ -622,13 +743,13 @@ class createNewKey final : public Function { class deleteKey final : public Function { public: - std::string public_key_; + object_ptr key_; deleteKey(); - explicit deleteKey(std::string const &public_key_); + explicit deleteKey(object_ptr &&key_); - static const std::int32_t ID = 917647652; + static const std::int32_t ID = -1579595571; std::int32_t get_id() const final { return ID; } @@ -752,6 +873,69 @@ class getBip39Hints final : public Function { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class getLogStream final : public Function { + public: + + getLogStream(); + + static const std::int32_t ID = 1167608667; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class getLogTagVerbosityLevel final : public Function { + public: + std::string tag_; + + getLogTagVerbosityLevel(); + + explicit getLogTagVerbosityLevel(std::string const &tag_); + + static const std::int32_t ID = 951004547; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class getLogTags final : public Function { + public: + + getLogTags(); + + static const std::int32_t ID = -254449190; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class getLogVerbosityLevel final : public Function { + public: + + getLogVerbosityLevel(); + + static const std::int32_t ID = 594057956; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class importEncryptedKey final : public Function { public: td::SecureString local_password_; @@ -979,6 +1163,61 @@ class runTests final : public Function { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class setLogStream final : public Function { + public: + object_ptr log_stream_; + + setLogStream(); + + explicit setLogStream(object_ptr &&log_stream_); + + static const std::int32_t ID = -1364199535; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class setLogTagVerbosityLevel final : public Function { + public: + std::string tag_; + std::int32_t new_verbosity_level_; + + setLogTagVerbosityLevel(); + + setLogTagVerbosityLevel(std::string const &tag_, std::int32_t new_verbosity_level_); + + static const std::int32_t ID = -2095589738; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class setLogVerbosityLevel final : public Function { + public: + std::int32_t new_verbosity_level_; + + setLogVerbosityLevel(); + + explicit setLogVerbosityLevel(std::int32_t new_verbosity_level_); + + static const std::int32_t ID = -303429678; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class testGiver_getAccountAddress final : public Function { public: @@ -1106,5 +1345,82 @@ class testWallet_sendGrams final : public Function { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class wallet_getAccountAddress final : public Function { + public: + object_ptr initital_account_state_; + + wallet_getAccountAddress(); + + explicit wallet_getAccountAddress(object_ptr &&initital_account_state_); + + static const std::int32_t ID = -1004103180; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class wallet_getAccountState final : public Function { + public: + object_ptr account_address_; + + wallet_getAccountState(); + + explicit wallet_getAccountState(object_ptr &&account_address_); + + static const std::int32_t ID = 462294850; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class wallet_init final : public Function { + public: + object_ptr private_key_; + + wallet_init(); + + explicit wallet_init(object_ptr &&private_key_); + + static const std::int32_t ID = 1528056782; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class wallet_sendGrams final : public Function { + public: + object_ptr private_key_; + object_ptr destination_; + std::int32_t seqno_; + std::int64_t valid_until_; + std::int64_t amount_; + std::string message_; + + wallet_sendGrams(); + + wallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t valid_until_, std::int64_t amount_, std::string const &message_); + + static const std::int32_t ID = 789731197; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + } // namespace tonlib_api } // namespace ton diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.hpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.hpp index 6631b6d8f0..bbc4c26f3f 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.hpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.hpp @@ -38,6 +38,21 @@ bool downcast_call(Object &obj, const T &func) { case key::ID: func(static_cast(obj)); return true; + case logStreamDefault::ID: + func(static_cast(obj)); + return true; + case logStreamFile::ID: + func(static_cast(obj)); + return true; + case logStreamEmpty::ID: + func(static_cast(obj)); + return true; + case logTags::ID: + func(static_cast(obj)); + return true; + case logVerbosityLevel::ID: + func(static_cast(obj)); + return true; case ok::ID: func(static_cast(obj)); return true; @@ -53,18 +68,15 @@ bool downcast_call(Object &obj, const T &func) { case generic_accountStateTestWallet::ID: func(static_cast(obj)); return true; + case generic_accountStateWallet::ID: + func(static_cast(obj)); + return true; case generic_accountStateTestGiver::ID: func(static_cast(obj)); return true; case generic_accountStateUninited::ID: func(static_cast(obj)); return true; - case generic_initialAccountStateRaw::ID: - func(static_cast(obj)); - return true; - case generic_initialAccountStateTestWallet::ID: - func(static_cast(obj)); - return true; case internal_transactionId::ID: func(static_cast(obj)); return true; @@ -95,6 +107,12 @@ bool downcast_call(Object &obj, const T &func) { case uninited_accountState::ID: func(static_cast(obj)); return true; + case wallet_accountState::ID: + func(static_cast(obj)); + return true; + case wallet_initialAccountState::ID: + func(static_cast(obj)); + return true; default: return false; } @@ -109,6 +127,9 @@ bool downcast_call(Object &obj, const T &func) { template bool downcast_call(Function &obj, const T &func) { switch (obj.get_id()) { + case addLogMessage::ID: + func(static_cast(obj)); + return true; case changeLocalPassword::ID: func(static_cast(obj)); return true; @@ -139,6 +160,18 @@ bool downcast_call(Function &obj, const T &func) { case getBip39Hints::ID: func(static_cast(obj)); return true; + case getLogStream::ID: + func(static_cast(obj)); + return true; + case getLogTagVerbosityLevel::ID: + func(static_cast(obj)); + return true; + case getLogTags::ID: + func(static_cast(obj)); + return true; + case getLogVerbosityLevel::ID: + func(static_cast(obj)); + return true; case importEncryptedKey::ID: func(static_cast(obj)); return true; @@ -175,6 +208,15 @@ bool downcast_call(Function &obj, const T &func) { case runTests::ID: func(static_cast(obj)); return true; + case setLogStream::ID: + func(static_cast(obj)); + return true; + case setLogTagVerbosityLevel::ID: + func(static_cast(obj)); + return true; + case setLogVerbosityLevel::ID: + func(static_cast(obj)); + return true; case testGiver_getAccountAddress::ID: func(static_cast(obj)); return true; @@ -196,6 +238,41 @@ bool downcast_call(Function &obj, const T &func) { case testWallet_sendGrams::ID: func(static_cast(obj)); return true; + case wallet_getAccountAddress::ID: + func(static_cast(obj)); + return true; + case wallet_getAccountState::ID: + func(static_cast(obj)); + return true; + case wallet_init::ID: + func(static_cast(obj)); + return true; + case wallet_sendGrams::ID: + func(static_cast(obj)); + return true; + default: + return false; + } +} + +/** + * Calls specified function object with the specified object downcasted to the most-derived type. + * \param[in] obj Object to pass as an argument to the function object. + * \param[in] func Function object to which the object will be passed. + * \returns whether function object call has happened. Should always return true for correct parameters. + */ +template +bool downcast_call(LogStream &obj, const T &func) { + switch (obj.get_id()) { + case logStreamDefault::ID: + func(static_cast(obj)); + return true; + case logStreamFile::ID: + func(static_cast(obj)); + return true; + case logStreamEmpty::ID: + func(static_cast(obj)); + return true; default: return false; } @@ -216,6 +293,9 @@ bool downcast_call(generic_AccountState &obj, const T &func) { case generic_accountStateTestWallet::ID: func(static_cast(obj)); return true; + case generic_accountStateWallet::ID: + func(static_cast(obj)); + return true; case generic_accountStateTestGiver::ID: func(static_cast(obj)); return true; @@ -227,25 +307,5 @@ bool downcast_call(generic_AccountState &obj, const T &func) { } } -/** - * Calls specified function object with the specified object downcasted to the most-derived type. - * \param[in] obj Object to pass as an argument to the function object. - * \param[in] func Function object to which the object will be passed. - * \returns whether function object call has happened. Should always return true for correct parameters. - */ -template -bool downcast_call(generic_InitialAccountState &obj, const T &func) { - switch (obj.get_id()) { - case generic_initialAccountStateRaw::ID: - func(static_cast(obj)); - return true; - case generic_initialAccountStateTestWallet::ID: - func(static_cast(obj)); - return true; - default: - return false; - } -} - } // namespace tonlib_api } // namespace ton diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp index 3c1402d996..eaef24cd46 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp @@ -14,12 +14,11 @@ namespace ton { namespace tonlib_api{ using namespace td; -Result tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str) { +Result tl_constructor_from_string(tonlib_api::LogStream *object, const std::string &str) { static const std::unordered_map m = { - {"generic.accountStateRaw", -1387096685}, - {"generic.accountStateTestWallet", -1041955397}, - {"generic.accountStateTestGiver", 1134654598}, - {"generic.accountStateUninited", -908702008} + {"logStreamDefault", 1390581436}, + {"logStreamFile", -1880085930}, + {"logStreamEmpty", -499912244} }; auto it = m.find(str); if (it == m.end()) { @@ -27,10 +26,13 @@ Result tl_constructor_from_string(tonlib_api::generic_AccountState *objec } return it->second; } -Result tl_constructor_from_string(tonlib_api::generic_InitialAccountState *object, const std::string &str) { +Result tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str) { static const std::unordered_map m = { - {"generic.initialAccountStateRaw", -1178429153}, - {"generic.initialAccountStateTestWallet", 710924204} + {"generic.accountStateRaw", -1387096685}, + {"generic.accountStateTestWallet", -1041955397}, + {"generic.accountStateWallet", 942582925}, + {"generic.accountStateTestGiver", 1134654598}, + {"generic.accountStateUninited", -908702008} }; auto it = m.find(str); if (it == m.end()) { @@ -48,15 +50,19 @@ Result tl_constructor_from_string(tonlib_api::Object *object, const std:: {"exportedPemKey", 1425473725}, {"inputKey", 869287093}, {"key", -1978362923}, + {"logStreamDefault", 1390581436}, + {"logStreamFile", -1880085930}, + {"logStreamEmpty", -499912244}, + {"logTags", -1604930601}, + {"logVerbosityLevel", 1734624234}, {"ok", -722616727}, {"options", -952483001}, {"updateSendLiteServerQuery", -1555130916}, {"generic.accountStateRaw", -1387096685}, {"generic.accountStateTestWallet", -1041955397}, + {"generic.accountStateWallet", 942582925}, {"generic.accountStateTestGiver", 1134654598}, {"generic.accountStateUninited", -908702008}, - {"generic.initialAccountStateRaw", -1178429153}, - {"generic.initialAccountStateTestWallet", 710924204}, {"internal.transactionId", -989527262}, {"raw.accountState", 461615898}, {"raw.initialAccountState", 777456197}, @@ -66,7 +72,9 @@ Result tl_constructor_from_string(tonlib_api::Object *object, const std:: {"testGiver.accountState", 860930426}, {"testWallet.accountState", 305698744}, {"testWallet.initialAccountState", -1231516227}, - {"uninited.accountState", 1768941188} + {"uninited.accountState", 1768941188}, + {"wallet.accountState", -1919815977}, + {"wallet.initialAccountState", -1079249978} }; auto it = m.find(str); if (it == m.end()) { @@ -76,16 +84,21 @@ Result tl_constructor_from_string(tonlib_api::Object *object, const std:: } Result tl_constructor_from_string(tonlib_api::Function *object, const std::string &str) { static const std::unordered_map m = { + {"addLogMessage", 1597427692}, {"changeLocalPassword", -1685491421}, {"close", -1187782273}, {"createNewKey", -1861385712}, - {"deleteKey", 917647652}, + {"deleteKey", -1579595571}, {"exportEncryptedKey", 155352861}, {"exportKey", 399723440}, {"exportPemKey", -2047752448}, {"generic.getAccountState", -657000446}, {"generic.sendGrams", 1523427648}, {"getBip39Hints", -1889640982}, + {"getLogStream", 1167608667}, + {"getLogTagVerbosityLevel", 951004547}, + {"getLogTags", -254449190}, + {"getLogVerbosityLevel", 594057956}, {"importEncryptedKey", 656724958}, {"importKey", -1607900903}, {"importPemKey", 76385617}, @@ -98,13 +111,20 @@ Result tl_constructor_from_string(tonlib_api::Function *object, const std {"raw.getTransactions", 935377269}, {"raw.sendMessage", 473889461}, {"runTests", -2039925427}, + {"setLogStream", -1364199535}, + {"setLogTagVerbosityLevel", -2095589738}, + {"setLogVerbosityLevel", -303429678}, {"testGiver.getAccountAddress", -540100768}, {"testGiver.getAccountState", 267738275}, {"testGiver.sendGrams", -1361914347}, {"testWallet.getAccountAddress", -1557748223}, {"testWallet.getAccountState", 654082364}, {"testWallet.init", 419055225}, - {"testWallet.sendGrams", 43200674} + {"testWallet.sendGrams", 43200674}, + {"wallet.getAccountAddress", -1004103180}, + {"wallet.getAccountState", 462294850}, + {"wallet.init", 1528056782}, + {"wallet.sendGrams", 789731197} }; auto it = m.find(str); if (it == m.end()) { @@ -202,6 +222,45 @@ Status from_json(tonlib_api::key &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::logStreamDefault &to, JsonObject &from) { + return Status::OK(); +} +Status from_json(tonlib_api::logStreamFile &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "path", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.path_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "max_file_size", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.max_file_size_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::logStreamEmpty &to, JsonObject &from) { + return Status::OK(); +} +Status from_json(tonlib_api::logTags &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "tags", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.tags_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::logVerbosityLevel &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "verbosity_level", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.verbosity_level_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::ok &to, JsonObject &from) { return Status::OK(); } @@ -259,6 +318,15 @@ Status from_json(tonlib_api::generic_accountStateTestWallet &to, JsonObject &fro } return Status::OK(); } +Status from_json(tonlib_api::generic_accountStateWallet &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "account_state", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.account_state_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::generic_accountStateTestGiver &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "account_state", JsonValue::Type::Null, true)); @@ -277,24 +345,6 @@ Status from_json(tonlib_api::generic_accountStateUninited &to, JsonObject &from) } return Status::OK(); } -Status from_json(tonlib_api::generic_initialAccountStateRaw &to, JsonObject &from) { - { - TRY_RESULT(value, get_json_object_field(from, "initital_account_state", JsonValue::Type::Null, true)); - if (value.type() != JsonValue::Type::Null) { - TRY_STATUS(from_json(to.initital_account_state_, value)); - } - } - return Status::OK(); -} -Status from_json(tonlib_api::generic_initialAccountStateTestWallet &to, JsonObject &from) { - { - TRY_RESULT(value, get_json_object_field(from, "initital_account_state", JsonValue::Type::Null, true)); - if (value.type() != JsonValue::Type::Null) { - TRY_STATUS(from_json(to.initital_account_state_, value)); - } - } - return Status::OK(); -} Status from_json(tonlib_api::internal_transactionId &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "lt", JsonValue::Type::Null, true)); @@ -523,6 +573,57 @@ Status from_json(tonlib_api::uninited_accountState &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::wallet_accountState &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "balance", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.balance_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "seqno", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.seqno_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "last_transaction_id", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.last_transaction_id_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "sync_utime", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.sync_utime_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::wallet_initialAccountState &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "public_key", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.public_key_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::addLogMessage &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "verbosity_level", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.verbosity_level_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "text", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.text_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::changeLocalPassword &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "input_key", JsonValue::Type::Null, true)); @@ -564,9 +665,9 @@ Status from_json(tonlib_api::createNewKey &to, JsonObject &from) { } Status from_json(tonlib_api::deleteKey &to, JsonObject &from) { { - TRY_RESULT(value, get_json_object_field(from, "public_key", JsonValue::Type::Null, true)); + TRY_RESULT(value, get_json_object_field(from, "key", JsonValue::Type::Null, true)); if (value.type() != JsonValue::Type::Null) { - TRY_STATUS(from_json(to.public_key_, value)); + TRY_STATUS(from_json(to.key_, value)); } } return Status::OK(); @@ -661,6 +762,24 @@ Status from_json(tonlib_api::getBip39Hints &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::getLogStream &to, JsonObject &from) { + return Status::OK(); +} +Status from_json(tonlib_api::getLogTagVerbosityLevel &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "tag", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.tag_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::getLogTags &to, JsonObject &from) { + return Status::OK(); +} +Status from_json(tonlib_api::getLogVerbosityLevel &to, JsonObject &from) { + return Status::OK(); +} Status from_json(tonlib_api::importEncryptedKey &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "local_password", JsonValue::Type::Null, true)); @@ -835,6 +954,39 @@ Status from_json(tonlib_api::runTests &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::setLogStream &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "log_stream", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.log_stream_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::setLogTagVerbosityLevel &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "tag", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.tag_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "new_verbosity_level", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.new_verbosity_level_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::setLogVerbosityLevel &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "new_verbosity_level", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.new_verbosity_level_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::testGiver_getAccountAddress &to, JsonObject &from) { return Status::OK(); } @@ -928,6 +1080,72 @@ Status from_json(tonlib_api::testWallet_sendGrams &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::wallet_getAccountAddress &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "initital_account_state", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.initital_account_state_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::wallet_getAccountState &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "account_address", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.account_address_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::wallet_init &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "private_key", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.private_key_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::wallet_sendGrams &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "private_key", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.private_key_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "destination", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.destination_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "seqno", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.seqno_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "valid_until", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.valid_until_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "amount", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.amount_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "message", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.message_, value)); + } + } + return Status::OK(); +} void to_json(JsonValueScope &jv, const tonlib_api::accountAddress &object) { auto jo = jv.enter_object(); jo << ctie("@type", "accountAddress"); @@ -973,6 +1191,33 @@ void to_json(JsonValueScope &jv, const tonlib_api::key &object) { jo << ctie("public_key", ToJson(object.public_key_)); jo << ctie("secret", ToJson(JsonBytes{object.secret_})); } +void to_json(JsonValueScope &jv, const tonlib_api::LogStream &object) { + tonlib_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); +} +void to_json(JsonValueScope &jv, const tonlib_api::logStreamDefault &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "logStreamDefault"); +} +void to_json(JsonValueScope &jv, const tonlib_api::logStreamFile &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "logStreamFile"); + jo << ctie("path", ToJson(object.path_)); + jo << ctie("max_file_size", ToJson(object.max_file_size_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::logStreamEmpty &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "logStreamEmpty"); +} +void to_json(JsonValueScope &jv, const tonlib_api::logTags &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "logTags"); + jo << ctie("tags", ToJson(object.tags_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::logVerbosityLevel &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "logVerbosityLevel"); + jo << ctie("verbosity_level", ToJson(object.verbosity_level_)); +} void to_json(JsonValueScope &jv, const tonlib_api::ok &object) { auto jo = jv.enter_object(); jo << ctie("@type", "ok"); @@ -1007,6 +1252,13 @@ void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateTestWalle jo << ctie("account_state", ToJson(object.account_state_)); } } +void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateWallet &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "generic.accountStateWallet"); + if (object.account_state_) { + jo << ctie("account_state", ToJson(object.account_state_)); + } +} void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateTestGiver &object) { auto jo = jv.enter_object(); jo << ctie("@type", "generic.accountStateTestGiver"); @@ -1021,23 +1273,6 @@ void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateUninited jo << ctie("account_state", ToJson(object.account_state_)); } } -void to_json(JsonValueScope &jv, const tonlib_api::generic_InitialAccountState &object) { - tonlib_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); -} -void to_json(JsonValueScope &jv, const tonlib_api::generic_initialAccountStateRaw &object) { - auto jo = jv.enter_object(); - jo << ctie("@type", "generic.initialAccountStateRaw"); - if (object.initital_account_state_) { - jo << ctie("initital_account_state", ToJson(object.initital_account_state_)); - } -} -void to_json(JsonValueScope &jv, const tonlib_api::generic_initialAccountStateTestWallet &object) { - auto jo = jv.enter_object(); - jo << ctie("@type", "generic.initialAccountStateTestWallet"); - if (object.initital_account_state_) { - jo << ctie("initital_account_state", ToJson(object.initital_account_state_)); - } -} void to_json(JsonValueScope &jv, const tonlib_api::internal_transactionId &object) { auto jo = jv.enter_object(); jo << ctie("@type", "internal.transactionId"); @@ -1125,6 +1360,27 @@ void to_json(JsonValueScope &jv, const tonlib_api::uninited_accountState &object } jo << ctie("sync_utime", ToJson(object.sync_utime_)); } +void to_json(JsonValueScope &jv, const tonlib_api::wallet_accountState &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "wallet.accountState"); + jo << ctie("balance", ToJson(JsonInt64{object.balance_})); + jo << ctie("seqno", ToJson(object.seqno_)); + if (object.last_transaction_id_) { + jo << ctie("last_transaction_id", ToJson(object.last_transaction_id_)); + } + jo << ctie("sync_utime", ToJson(object.sync_utime_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::wallet_initialAccountState &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "wallet.initialAccountState"); + jo << ctie("public_key", ToJson(object.public_key_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::addLogMessage &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "addLogMessage"); + jo << ctie("verbosity_level", ToJson(object.verbosity_level_)); + jo << ctie("text", ToJson(object.text_)); +} void to_json(JsonValueScope &jv, const tonlib_api::changeLocalPassword &object) { auto jo = jv.enter_object(); jo << ctie("@type", "changeLocalPassword"); @@ -1147,7 +1403,9 @@ void to_json(JsonValueScope &jv, const tonlib_api::createNewKey &object) { void to_json(JsonValueScope &jv, const tonlib_api::deleteKey &object) { auto jo = jv.enter_object(); jo << ctie("@type", "deleteKey"); - jo << ctie("public_key", ToJson(object.public_key_)); + if (object.key_) { + jo << ctie("key", ToJson(object.key_)); + } } void to_json(JsonValueScope &jv, const tonlib_api::exportEncryptedKey &object) { auto jo = jv.enter_object(); @@ -1199,6 +1457,23 @@ void to_json(JsonValueScope &jv, const tonlib_api::getBip39Hints &object) { jo << ctie("@type", "getBip39Hints"); jo << ctie("prefix", ToJson(object.prefix_)); } +void to_json(JsonValueScope &jv, const tonlib_api::getLogStream &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "getLogStream"); +} +void to_json(JsonValueScope &jv, const tonlib_api::getLogTagVerbosityLevel &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "getLogTagVerbosityLevel"); + jo << ctie("tag", ToJson(object.tag_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::getLogTags &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "getLogTags"); +} +void to_json(JsonValueScope &jv, const tonlib_api::getLogVerbosityLevel &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "getLogVerbosityLevel"); +} void to_json(JsonValueScope &jv, const tonlib_api::importEncryptedKey &object) { auto jo = jv.enter_object(); jo << ctie("@type", "importEncryptedKey"); @@ -1290,6 +1565,24 @@ void to_json(JsonValueScope &jv, const tonlib_api::runTests &object) { jo << ctie("@type", "runTests"); jo << ctie("dir", ToJson(object.dir_)); } +void to_json(JsonValueScope &jv, const tonlib_api::setLogStream &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "setLogStream"); + if (object.log_stream_) { + jo << ctie("log_stream", ToJson(object.log_stream_)); + } +} +void to_json(JsonValueScope &jv, const tonlib_api::setLogTagVerbosityLevel &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "setLogTagVerbosityLevel"); + jo << ctie("tag", ToJson(object.tag_)); + jo << ctie("new_verbosity_level", ToJson(object.new_verbosity_level_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::setLogVerbosityLevel &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "setLogVerbosityLevel"); + jo << ctie("new_verbosity_level", ToJson(object.new_verbosity_level_)); +} void to_json(JsonValueScope &jv, const tonlib_api::testGiver_getAccountAddress &object) { auto jo = jv.enter_object(); jo << ctie("@type", "testGiver.getAccountAddress"); @@ -1342,5 +1635,40 @@ void to_json(JsonValueScope &jv, const tonlib_api::testWallet_sendGrams &object) jo << ctie("amount", ToJson(JsonInt64{object.amount_})); jo << ctie("message", ToJson(JsonBytes{object.message_})); } +void to_json(JsonValueScope &jv, const tonlib_api::wallet_getAccountAddress &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "wallet.getAccountAddress"); + if (object.initital_account_state_) { + jo << ctie("initital_account_state", ToJson(object.initital_account_state_)); + } +} +void to_json(JsonValueScope &jv, const tonlib_api::wallet_getAccountState &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "wallet.getAccountState"); + if (object.account_address_) { + jo << ctie("account_address", ToJson(object.account_address_)); + } +} +void to_json(JsonValueScope &jv, const tonlib_api::wallet_init &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "wallet.init"); + if (object.private_key_) { + jo << ctie("private_key", ToJson(object.private_key_)); + } +} +void to_json(JsonValueScope &jv, const tonlib_api::wallet_sendGrams &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "wallet.sendGrams"); + if (object.private_key_) { + jo << ctie("private_key", ToJson(object.private_key_)); + } + if (object.destination_) { + jo << ctie("destination", ToJson(object.destination_)); + } + jo << ctie("seqno", ToJson(object.seqno_)); + jo << ctie("valid_until", ToJson(object.valid_until_)); + jo << ctie("amount", ToJson(JsonInt64{object.amount_})); + jo << ctie("message", ToJson(JsonBytes{object.message_})); +} } // namespace tonlib_api } // namespace ton diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.h index 3021c65ae1..af09060e74 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.h +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.h @@ -11,8 +11,8 @@ namespace ton { namespace tonlib_api{ using namespace td; +Result tl_constructor_from_string(tonlib_api::LogStream *object, const std::string &str); Result tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str); -Result tl_constructor_from_string(tonlib_api::generic_InitialAccountState *object, const std::string &str); Result tl_constructor_from_string(tonlib_api::Object *object, const std::string &str); Result tl_constructor_from_string(tonlib_api::Function *object, const std::string &str); Status from_json(tonlib_api::accountAddress &to, JsonObject &from); @@ -23,15 +23,19 @@ Status from_json(tonlib_api::exportedKey &to, JsonObject &from); Status from_json(tonlib_api::exportedPemKey &to, JsonObject &from); Status from_json(tonlib_api::inputKey &to, JsonObject &from); Status from_json(tonlib_api::key &to, JsonObject &from); +Status from_json(tonlib_api::logStreamDefault &to, JsonObject &from); +Status from_json(tonlib_api::logStreamFile &to, JsonObject &from); +Status from_json(tonlib_api::logStreamEmpty &to, JsonObject &from); +Status from_json(tonlib_api::logTags &to, JsonObject &from); +Status from_json(tonlib_api::logVerbosityLevel &to, JsonObject &from); Status from_json(tonlib_api::ok &to, JsonObject &from); Status from_json(tonlib_api::options &to, JsonObject &from); Status from_json(tonlib_api::updateSendLiteServerQuery &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateRaw &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateTestWallet &to, JsonObject &from); +Status from_json(tonlib_api::generic_accountStateWallet &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateTestGiver &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateUninited &to, JsonObject &from); -Status from_json(tonlib_api::generic_initialAccountStateRaw &to, JsonObject &from); -Status from_json(tonlib_api::generic_initialAccountStateTestWallet &to, JsonObject &from); Status from_json(tonlib_api::internal_transactionId &to, JsonObject &from); Status from_json(tonlib_api::raw_accountState &to, JsonObject &from); Status from_json(tonlib_api::raw_initialAccountState &to, JsonObject &from); @@ -42,6 +46,9 @@ Status from_json(tonlib_api::testGiver_accountState &to, JsonObject &from); Status from_json(tonlib_api::testWallet_accountState &to, JsonObject &from); Status from_json(tonlib_api::testWallet_initialAccountState &to, JsonObject &from); Status from_json(tonlib_api::uninited_accountState &to, JsonObject &from); +Status from_json(tonlib_api::wallet_accountState &to, JsonObject &from); +Status from_json(tonlib_api::wallet_initialAccountState &to, JsonObject &from); +Status from_json(tonlib_api::addLogMessage &to, JsonObject &from); Status from_json(tonlib_api::changeLocalPassword &to, JsonObject &from); Status from_json(tonlib_api::close &to, JsonObject &from); Status from_json(tonlib_api::createNewKey &to, JsonObject &from); @@ -52,6 +59,10 @@ Status from_json(tonlib_api::exportPemKey &to, JsonObject &from); Status from_json(tonlib_api::generic_getAccountState &to, JsonObject &from); Status from_json(tonlib_api::generic_sendGrams &to, JsonObject &from); Status from_json(tonlib_api::getBip39Hints &to, JsonObject &from); +Status from_json(tonlib_api::getLogStream &to, JsonObject &from); +Status from_json(tonlib_api::getLogTagVerbosityLevel &to, JsonObject &from); +Status from_json(tonlib_api::getLogTags &to, JsonObject &from); +Status from_json(tonlib_api::getLogVerbosityLevel &to, JsonObject &from); Status from_json(tonlib_api::importEncryptedKey &to, JsonObject &from); Status from_json(tonlib_api::importKey &to, JsonObject &from); Status from_json(tonlib_api::importPemKey &to, JsonObject &from); @@ -64,6 +75,9 @@ Status from_json(tonlib_api::raw_getAccountState &to, JsonObject &from); Status from_json(tonlib_api::raw_getTransactions &to, JsonObject &from); Status from_json(tonlib_api::raw_sendMessage &to, JsonObject &from); Status from_json(tonlib_api::runTests &to, JsonObject &from); +Status from_json(tonlib_api::setLogStream &to, JsonObject &from); +Status from_json(tonlib_api::setLogTagVerbosityLevel &to, JsonObject &from); +Status from_json(tonlib_api::setLogVerbosityLevel &to, JsonObject &from); Status from_json(tonlib_api::testGiver_getAccountAddress &to, JsonObject &from); Status from_json(tonlib_api::testGiver_getAccountState &to, JsonObject &from); Status from_json(tonlib_api::testGiver_sendGrams &to, JsonObject &from); @@ -71,6 +85,10 @@ Status from_json(tonlib_api::testWallet_getAccountAddress &to, JsonObject &from) Status from_json(tonlib_api::testWallet_getAccountState &to, JsonObject &from); Status from_json(tonlib_api::testWallet_init &to, JsonObject &from); Status from_json(tonlib_api::testWallet_sendGrams &to, JsonObject &from); +Status from_json(tonlib_api::wallet_getAccountAddress &to, JsonObject &from); +Status from_json(tonlib_api::wallet_getAccountState &to, JsonObject &from); +Status from_json(tonlib_api::wallet_init &to, JsonObject &from); +Status from_json(tonlib_api::wallet_sendGrams &to, JsonObject &from); void to_json(JsonValueScope &jv, const tonlib_api::accountAddress &object); void to_json(JsonValueScope &jv, const tonlib_api::bip39Hints &object); void to_json(JsonValueScope &jv, const tonlib_api::error &object); @@ -79,17 +97,21 @@ void to_json(JsonValueScope &jv, const tonlib_api::exportedKey &object); void to_json(JsonValueScope &jv, const tonlib_api::exportedPemKey &object); void to_json(JsonValueScope &jv, const tonlib_api::inputKey &object); void to_json(JsonValueScope &jv, const tonlib_api::key &object); +void to_json(JsonValueScope &jv, const tonlib_api::LogStream &object); +void to_json(JsonValueScope &jv, const tonlib_api::logStreamDefault &object); +void to_json(JsonValueScope &jv, const tonlib_api::logStreamFile &object); +void to_json(JsonValueScope &jv, const tonlib_api::logStreamEmpty &object); +void to_json(JsonValueScope &jv, const tonlib_api::logTags &object); +void to_json(JsonValueScope &jv, const tonlib_api::logVerbosityLevel &object); void to_json(JsonValueScope &jv, const tonlib_api::ok &object); void to_json(JsonValueScope &jv, const tonlib_api::options &object); void to_json(JsonValueScope &jv, const tonlib_api::updateSendLiteServerQuery &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_AccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateRaw &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateTestWallet &object); +void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateWallet &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateTestGiver &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateUninited &object); -void to_json(JsonValueScope &jv, const tonlib_api::generic_InitialAccountState &object); -void to_json(JsonValueScope &jv, const tonlib_api::generic_initialAccountStateRaw &object); -void to_json(JsonValueScope &jv, const tonlib_api::generic_initialAccountStateTestWallet &object); void to_json(JsonValueScope &jv, const tonlib_api::internal_transactionId &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_accountState &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_initialAccountState &object); @@ -100,6 +122,9 @@ void to_json(JsonValueScope &jv, const tonlib_api::testGiver_accountState &objec void to_json(JsonValueScope &jv, const tonlib_api::testWallet_accountState &object); void to_json(JsonValueScope &jv, const tonlib_api::testWallet_initialAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::uninited_accountState &object); +void to_json(JsonValueScope &jv, const tonlib_api::wallet_accountState &object); +void to_json(JsonValueScope &jv, const tonlib_api::wallet_initialAccountState &object); +void to_json(JsonValueScope &jv, const tonlib_api::addLogMessage &object); void to_json(JsonValueScope &jv, const tonlib_api::changeLocalPassword &object); void to_json(JsonValueScope &jv, const tonlib_api::close &object); void to_json(JsonValueScope &jv, const tonlib_api::createNewKey &object); @@ -110,6 +135,10 @@ void to_json(JsonValueScope &jv, const tonlib_api::exportPemKey &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_getAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_sendGrams &object); void to_json(JsonValueScope &jv, const tonlib_api::getBip39Hints &object); +void to_json(JsonValueScope &jv, const tonlib_api::getLogStream &object); +void to_json(JsonValueScope &jv, const tonlib_api::getLogTagVerbosityLevel &object); +void to_json(JsonValueScope &jv, const tonlib_api::getLogTags &object); +void to_json(JsonValueScope &jv, const tonlib_api::getLogVerbosityLevel &object); void to_json(JsonValueScope &jv, const tonlib_api::importEncryptedKey &object); void to_json(JsonValueScope &jv, const tonlib_api::importKey &object); void to_json(JsonValueScope &jv, const tonlib_api::importPemKey &object); @@ -122,6 +151,9 @@ void to_json(JsonValueScope &jv, const tonlib_api::raw_getAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_getTransactions &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_sendMessage &object); void to_json(JsonValueScope &jv, const tonlib_api::runTests &object); +void to_json(JsonValueScope &jv, const tonlib_api::setLogStream &object); +void to_json(JsonValueScope &jv, const tonlib_api::setLogTagVerbosityLevel &object); +void to_json(JsonValueScope &jv, const tonlib_api::setLogVerbosityLevel &object); void to_json(JsonValueScope &jv, const tonlib_api::testGiver_getAccountAddress &object); void to_json(JsonValueScope &jv, const tonlib_api::testGiver_getAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::testGiver_sendGrams &object); @@ -129,6 +161,10 @@ void to_json(JsonValueScope &jv, const tonlib_api::testWallet_getAccountAddress void to_json(JsonValueScope &jv, const tonlib_api::testWallet_getAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::testWallet_init &object); void to_json(JsonValueScope &jv, const tonlib_api::testWallet_sendGrams &object); +void to_json(JsonValueScope &jv, const tonlib_api::wallet_getAccountAddress &object); +void to_json(JsonValueScope &jv, const tonlib_api::wallet_getAccountState &object); +void to_json(JsonValueScope &jv, const tonlib_api::wallet_init &object); +void to_json(JsonValueScope &jv, const tonlib_api::wallet_sendGrams &object); inline void to_json(JsonValueScope &jv, const ton::tonlib_api::Object &object) { ton::tonlib_api::downcast_call(const_cast(object),[&jv](const auto &object) { to_json(jv, object); }); } diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl index 860ffd5d37..89827f7f5c 100644 --- a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl +++ b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl @@ -322,6 +322,7 @@ tonNode.zeroStateIdExt workchain:int root_hash:int256 file_hash:int256 = tonNode tonNode.blockDescriptionEmpty = tonNode.BlockDescription; tonNode.blockDescription id:tonNode.blockIdExt = tonNode.BlockDescription; +tonNode.blocksDescription ids:(vector tonNode.blockIdExt) incomplete:Bool = tonNode.BlocksDescription; tonNode.preparedProofEmpty = tonNode.PreparedProof; tonNode.preparedProof = tonNode.PreparedProof; tonNode.preparedProofLink = tonNode.PreparedProof; @@ -352,22 +353,42 @@ tonNode.keyBlocks blocks:(vector tonNode.blockIdExt) incomplete:Bool error:Bool ton.blockId root_cell_hash:int256 file_hash:int256 = ton.BlockId; ton.blockIdApprove root_cell_hash:int256 file_hash:int256 = ton.BlockId; +tonNode.dataList data:(vector bytes) = tonNode.DataList; + +tonNode.dataFull id:tonNode.blockIdExt proof:bytes block:bytes is_link:Bool = tonNode.DataFull; +tonNode.dataFullEmpty = tonNode.DataFull; + +tonNode.capabilities version:int capabilities:long = tonNode.Capabilities; + +tonNode.success = tonNode.Success; + ---functions--- tonNode.getNextBlockDescription prev_block:tonNode.blockIdExt = tonNode.BlockDescription; +tonNode.getNextBlocksDescription prev_block:tonNode.blockIdExt limit:int = tonNode.BlocksDescription; +tonNode.getPrevBlocksDescription next_block:tonNode.blockIdExt limit:int cutoff_seqno:int = tonNode.BlocksDescription; tonNode.prepareBlockProof block:tonNode.blockIdExt allow_partial:Bool = tonNode.PreparedProof; +tonNode.prepareBlockProofs blocks:(vector tonNode.blockIdExt) allow_partial:Bool = tonNode.PreparedProof; tonNode.prepareBlock block:tonNode.blockIdExt = tonNode.Prepared; +tonNode.prepareBlocks blocks:(vector tonNode.blockIdExt) = tonNode.Prepared; tonNode.preparePersistentState block:tonNode.blockIdExt masterchain_block:tonNode.blockIdExt = tonNode.PreparedState; tonNode.prepareZeroState block:tonNode.blockIdExt = tonNode.PreparedState; tonNode.getNextKeyBlockIds block:tonNode.blockIdExt max_size:int = tonNode.KeyBlocks; +tonNode.downloadNextBlockFull prev_block:tonNode.blockIdExt = tonNode.DataFull; +tonNode.downloadBlockFull block:tonNode.blockIdExt = tonNode.DataFull; tonNode.downloadBlock block:tonNode.blockIdExt = tonNode.Data; +tonNode.downloadBlocks blocks:(vector tonNode.blockIdExt) = tonNode.DataList; tonNode.downloadPersistentState block:tonNode.blockIdExt masterchain_block:tonNode.blockIdExt = tonNode.Data; tonNode.downloadPersistentStateSlice block:tonNode.blockIdExt masterchain_block:tonNode.blockIdExt offset:long max_size:long = tonNode.Data; tonNode.downloadZeroState block:tonNode.blockIdExt = tonNode.Data; tonNode.downloadBlockProof block:tonNode.blockIdExt = tonNode.Data; +tonNode.downloadBlockProofs blocks:(vector tonNode.blockIdExt) = tonNode.DataList; tonNode.downloadBlockProofLink block:tonNode.blockIdExt = tonNode.Data; +tonNode.downloadBlockProofLinks blocks:(vector tonNode.blockIdExt) = tonNode.DataList; -tonNode.slave.sendExtMessage message:tonNode.externalMessage = True; +tonNode.getCapabilities = tonNode.Capabilities; + +tonNode.slave.sendExtMessage message:tonNode.externalMessage = tonNode.Success; tonNode.query = Object; diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo index 7ad04d37e5..6959d9a3c9 100644 Binary files a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo and b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo differ diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl index 356f263c2d..db12f3f1cb 100644 --- a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl +++ b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl @@ -39,20 +39,45 @@ raw.transactions transactions:vector previous_transaction_id:in testWallet.initialAccountState public_key:string = testWallet.InitialAccountState; testWallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53 = testWallet.AccountState; +wallet.initialAccountState public_key:string = wallet.InitialAccountState; +wallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53 = wallet.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 sync_utime:int53 = uninited.AccountState; -generic.initialAccountStateRaw initital_account_state:raw.initialAccountState = generic.InitialAccountState; -generic.initialAccountStateTestWallet initital_account_state:testWallet.initialAccountState = generic.InitialAccountState; +//generic.initialAccountStateRaw initital_account_state:raw.initialAccountState = generic.InitialAccountState; +//generic.initialAccountStateTestWallet initital_account_state:testWallet.initialAccountState = generic.InitialAccountState; +//generic.initialAccountStateWallet initital_account_state:wallet.initialAccountState = generic.InitialAccountState; 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.accountStateTestGiver account_state:testGiver.accountState = generic.AccountState; generic.accountStateUninited account_state:uninited.accountState = generic.AccountState; +//generic.sendGramsResult sent_until:int53 = generic.SendGramsResult; + updateSendLiteServerQuery id:int64 data:bytes = Update; +//@class LogStream @description Describes a stream to which TDLib internal log is written + +//@description The log is written to stderr or an OS specific log +logStreamDefault = LogStream; + +//@description The log is written to a file @path Path to the file to where the internal TDLib log will be written @max_file_size Maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated +logStreamFile path:string max_file_size:int53 = LogStream; + +//@description The log is written nowhere +logStreamEmpty = LogStream; + + +//@description Contains a TDLib internal log verbosity level @verbosity_level Log verbosity level +logVerbosityLevel verbosity_level:int32 = LogVerbosityLevel; + +//@description Contains a list of available TDLib internal log tags @tags List of log tags +logTags tags:vector = LogTags; + ---functions--- init options:options = Ok; @@ -61,7 +86,7 @@ close = Ok; options.setConfig config:string = Ok; createNewKey local_password:secureBytes mnemonic_password:secureBytes random_extra_seed:secureBytes = Key; -deleteKey public_key:string = Ok; +deleteKey key:key = Ok; exportKey input_key:inputKey = ExportedKey; exportPemKey input_key:inputKey key_password:secureBytes = ExportedPemKey; exportEncryptedKey input_key:inputKey key_password:secureBytes = ExportedEncryptedKey; @@ -83,6 +108,11 @@ testWallet.getAccountAddress initital_account_state:testWallet.initialAccountSta testWallet.getAccountState account_address:accountAddress = testWallet.AccountState; testWallet.sendGrams private_key:inputKey destination:accountAddress seqno:int32 amount:int64 message:bytes = Ok; +wallet.init private_key:inputKey = Ok; +wallet.getAccountAddress initital_account_state:wallet.initialAccountState = AccountAddress; +wallet.getAccountState account_address:accountAddress = wallet.AccountState; +wallet.sendGrams private_key:inputKey destination:accountAddress seqno:int32 valid_until:int53 amount:int64 message:bytes = Ok; + testGiver.getAccountState = testGiver.AccountState; testGiver.getAccountAddress = AccountAddress; testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 message:bytes = Ok; @@ -95,3 +125,30 @@ onLiteServerQueryResult id:int64 bytes:bytes = Ok; onLiteServerQueryError id:int64 error:error = Ok; runTests dir:string = Ok; + +//@description Sets new log stream for internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously @log_stream New log stream +setLogStream log_stream:LogStream = Ok; + +//@description Returns information about currently used log stream for internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously +getLogStream = LogStream; + +//@description Sets the verbosity level of the internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously +//@new_verbosity_level New value of the verbosity level for logging. Value 0 corresponds to fatal errors, value 1 corresponds to errors, value 2 corresponds to warnings and debug warnings, value 3 corresponds to informational, value 4 corresponds to debug, value 5 corresponds to verbose debug, value greater than 5 and up to 1023 can be used to enable even more logging +setLogVerbosityLevel new_verbosity_level:int32 = Ok; + +//@description Returns current verbosity level of the internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously +getLogVerbosityLevel = LogVerbosityLevel; + +//@description Returns list of available TDLib internal log tags, for example, ["actor", "binlog", "connections", "notifications", "proxy"]. This is an offline method. Can be called before authorization. Can be called synchronously +getLogTags = LogTags; + +//@description Sets the verbosity level for a specified TDLib internal log tag. This is an offline method. Can be called before authorization. Can be called synchronously +//@tag Logging tag to change verbosity level @new_verbosity_level New verbosity level; 1-1024 +setLogTagVerbosityLevel tag:string new_verbosity_level:int32 = Ok; + +//@description Returns current verbosity level for a specified TDLib internal log tag. This is an offline method. Can be called before authorization. Can be called synchronously @tag Logging tag to change verbosity level +getLogTagVerbosityLevel tag:string = LogVerbosityLevel; + +//@description Adds a message to TDLib internal log. This is an offline method. Can be called before authorization. Can be called synchronously +//@verbosity_level Minimum verbosity level needed for the message to be logged, 0-1023 @text Text of a message to log +addLogMessage verbosity_level:int32 text:string = Ok; diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo index 40a4ccdce4..0a810f234f 100644 Binary files a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo and b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo differ diff --git a/submodules/ton/tonlib-src/tonlib/CMakeLists.txt b/submodules/ton/tonlib-src/tonlib/CMakeLists.txt index 9b9b81da08..3867779643 100644 --- a/submodules/ton/tonlib-src/tonlib/CMakeLists.txt +++ b/submodules/ton/tonlib-src/tonlib/CMakeLists.txt @@ -14,10 +14,12 @@ set(TONLIB_SOURCE tonlib/KeyStorage.cpp tonlib/LastBlock.cpp tonlib/LastBlockStorage.cpp + tonlib/Logging.cpp tonlib/TestGiver.cpp tonlib/TestWallet.cpp tonlib/TonlibClient.cpp tonlib/utils.cpp + tonlib/Wallet.cpp tonlib/Client.h tonlib/Config.h @@ -28,11 +30,13 @@ set(TONLIB_SOURCE tonlib/KeyStorage.h tonlib/LastBlock.h tonlib/LastBlockStorage.h + tonlib/Logging.h tonlib/TestGiver.h tonlib/TestWallet.h tonlib/TonlibCallback.h tonlib/TonlibClient.h tonlib/utils.h + tonlib/Wallet.h tonlib/keys/bip39.cpp tonlib/keys/DecryptedKey.cpp diff --git a/submodules/ton/tonlib-src/tonlib/test/offline.cpp b/submodules/ton/tonlib-src/tonlib/test/offline.cpp index e009adf7c7..851e51b009 100644 --- a/submodules/ton/tonlib-src/tonlib/test/offline.cpp +++ b/submodules/ton/tonlib-src/tonlib/test/offline.cpp @@ -31,6 +31,7 @@ #include "tonlib/utils.h" #include "tonlib/TestGiver.h" #include "tonlib/TestWallet.h" +#include "tonlib/Wallet.h" #include "tonlib/GenericAccount.h" #include "tonlib/TonlibClient.h" #include "tonlib/Client.h" @@ -90,6 +91,35 @@ INC NEWC 32 STU 256 STU ENDC c4 POPCTR return fift::compile_asm(code).move_as_ok(); } +td::Ref get_wallet_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 // signature in_msg msg_seqno valid_until cs + SWAP NOW LEQ 35 THROWIF // signature in_msg msg_seqno cs + c4 PUSH CTOS 32 LDU 256 LDU ENDS // signature in_msg msg_seqno cs stored_seqno public_key + s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno + EQUAL 33 THROWIFNOT // signature in_msg public_key cs stored_seqno + s0 s3 XCHG HASHSU // signature stored_seqno public_key cs hash + s0 s4 s2 XC2PU CHKSIGNU 34 THROWIFNOT // cs stored_seqno public_key + ACCEPT + s0 s2 XCHG // public_key stored_seqno cs + WHILE:<{ + DUP SREFS // public_key stored_seqno cs _40 + }>DO<{ // public_key stored_seqno cs + // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance + 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno cs _45 mode + SENDRAWMSG // public_key stored_seqno cs + }> + ENDS INC // public_key seqno' + NEWC 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()); CHECK(get_test_wallet_source()->get_hash() == TestWallet::get_init_code()->get_hash()); @@ -114,6 +144,74 @@ TEST(Tonlib, TestWallet) { 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.fif")).ensure(); + 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", "123", "321"}) + .move_as_ok(); + auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; + auto gift_message = GenericAccount::create_ext_message( + address, {}, TestWallet::make_a_gift_message(priv_key, 123, 321000000000ll, "TEST", 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()); +} + +td::Ref get_wallet_source_fc() { + return fift::compile_asm(load_source("smartcont/wallet-code.fif"), "", false).move_as_ok(); +} + +TEST(Tonlib, Wallet) { + LOG(ERROR) << td::base64_encode(std_boc_serialize(get_wallet_source()).move_as_ok()); + CHECK(get_wallet_source()->get_hash() == Wallet::get_init_code()->get_hash()); + + auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet-v2.fif"), {"aba", "0"}).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 = Wallet::get_init_state(pub_key); + auto init_message = Wallet::get_init_message(priv_key); + auto address = GenericAccount::get_address(0, init_state); + + CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); + + td::Ref res = 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-v2.fif")).ensure(); + class ZeroOsTime : public fift::OsTime { + public: + td::uint32 now() override { + return 0; + } + }; + fift_output.source_lookup.set_os_time(std::make_unique()); + 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", "123", "321"}) + .move_as_ok(); + auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; + auto gift_message = GenericAccount::create_ext_message( + address, {}, Wallet::make_a_gift_message(priv_key, 123, 60, 321000000000ll, "TESTv2", 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) { @@ -346,9 +444,9 @@ TEST(Tonlib, KeysApi) { //importKey local_password:bytes mnemonic_password:bytes exported_key:exportedKey = Key; auto new_local_password = td::SecureString("new_local_password"); // import already existed key - sync_send(client, make_object(new_local_password.copy(), mnemonic_password.copy(), - make_object(copy_word_list()))) - .ensure_error(); + //sync_send(client, make_object(new_local_password.copy(), mnemonic_password.copy(), + //make_object(copy_word_list()))) + //.ensure_error(); { auto export_password = td::SecureString("export password"); @@ -361,7 +459,9 @@ TEST(Tonlib, KeysApi) { export_password.copy())) .move_as_ok(); - sync_send(client, make_object(key->public_key_)).move_as_ok(); + sync_send(client, + make_object(make_object(key->public_key_, key->secret_.copy()))) + .move_as_ok(); sync_send(client, make_object( new_local_password.copy(), wrong_export_password.copy(), @@ -374,10 +474,13 @@ TEST(Tonlib, KeysApi) { make_object(exported_encrypted_key->data_.copy()))) .move_as_ok(); CHECK(imported_encrypted_key->public_key_ == key->public_key_); + key = std::move(imported_encrypted_key); } //deleteKey public_key:bytes = Ok; - sync_send(client, make_object(key->public_key_)).move_as_ok(); + sync_send(client, + make_object(make_object(key->public_key_, key->secret_.copy()))) + .move_as_ok(); auto err1 = sync_send(client, make_object( new_local_password.copy(), td::SecureString("wrong password"), @@ -410,11 +513,13 @@ TEST(Tonlib, KeysApi) { LOG(ERROR) << to_string(exported_pem_key); //importPemKey exported_key:exportedPemKey key_password:bytes = Key; - sync_send(client, make_object( - new_local_password.copy(), pem_password.copy(), - make_object(exported_pem_key->pem_.copy()))) - .ensure_error(); - sync_send(client, make_object(key->public_key_)).move_as_ok(); + //sync_send(client, make_object( + //new_local_password.copy(), pem_password.copy(), + //make_object(exported_pem_key->pem_.copy()))) + //.ensure_error(); + sync_send(client, make_object( + make_object(imported_key->public_key_, imported_key->secret_.copy()))) + .move_as_ok(); sync_send(client, make_object( new_local_password.copy(), td::SecureString("wrong pem password"), make_object(exported_pem_key->pem_.copy()))) diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/GenericAccount.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/GenericAccount.cpp index 330393c0e7..08ea33bdc9 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/GenericAccount.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/GenericAccount.cpp @@ -28,7 +28,7 @@ td::Ref GenericAccount::get_init_state(td::Ref code, td::Ref .finalize(); } block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id, const td::Ref& init_state) { - return block::StdAddress(workchain_id, init_state->get_hash().bits(), false); + return block::StdAddress(workchain_id, init_state->get_hash().bits(), true /*bounce*/); } td::Ref GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref new_state, td::Ref body) { diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.cpp index 1c25764328..6137c0e347 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.cpp @@ -24,14 +24,23 @@ #include "td/utils/filesystem.h" #include "td/utils/port/path.h" +#include "td/utils/crypto.h" namespace tonlib { -std::string to_file_name(td::Slice public_key) { - return td::buffer_to_hex(public_key); +std::string to_file_name_old(const KeyStorage::Key &key) { + return td::buffer_to_hex(key.public_key); } -std::string KeyStorage::to_file_path(td::Slice public_key) { - return directory_ + TD_DIR_SLASH + to_file_name(public_key); +std::string KeyStorage::to_file_path_old(const Key &key) { + return directory_ + TD_DIR_SLASH + to_file_name_old(key); +} + +std::string to_file_name(const KeyStorage::Key &key) { + return td::buffer_to_hex(td::sha512(key.secret.as_slice()).substr(0, 32)); +} + +std::string KeyStorage::to_file_path(const Key &key) { + return directory_ + TD_DIR_SLASH + to_file_name(key); } td::Status KeyStorage::set_directory(std::string directory) { TRY_RESULT(path, td::realpath(directory)); @@ -52,8 +61,8 @@ td::Result KeyStorage::save_key(const DecryptedKey &decrypted_k auto size = encrypted_key.encrypted_data.size(); - LOG(ERROR) << "SAVE " << to_file_name(res.public_key); - TRY_RESULT(to_file, td::FileFd::open(to_file_path(res.public_key), td::FileFd::CreateNew | td::FileFd::Write)); + LOG(ERROR) << "SAVE " << to_file_name(res); + TRY_RESULT(to_file, td::FileFd::open(to_file_path(res), td::FileFd::CreateNew | td::FileFd::Write)); TRY_RESULT(written, to_file.write(encrypted_key.encrypted_data)); if (written != static_cast(size)) { return td::Status::Error(PSLICE() << "Failed to write file: written " << written << " bytes instead of " << size); @@ -74,7 +83,16 @@ td::Result KeyStorage::create_new_key(td::Slice local_password, } td::Result KeyStorage::export_decrypted_key(InputKey input_key) { - TRY_RESULT(encrypted_data, td::read_file_secure(to_file_path(input_key.key.public_key))); + auto r_encrypted_data = td::read_file_secure(to_file_path(input_key.key)); + if (r_encrypted_data.is_error()) { + r_encrypted_data = td::read_file_secure(to_file_path_old(input_key.key)); + if (r_encrypted_data.is_ok()) { + LOG(WARNING) << "Restore private from deprecated location " << to_file_path_old(input_key.key) << " --> " + << to_file_path(input_key.key); + td::rename(to_file_path_old(input_key.key), to_file_path(input_key.key)).ignore(); + } + } + TRY_RESULT(encrypted_data, std::move(r_encrypted_data)); EncryptedKey encrypted_key{std::move(encrypted_data), td::Ed25519::PublicKey(std::move(input_key.key.public_key)), std::move(input_key.key.secret)}; return encrypted_key.decrypt(std::move(input_key.local_password)); @@ -94,8 +112,8 @@ td::Result KeyStorage::load_private_key(InputKey input_k return std::move(private_key); } -td::Status KeyStorage::delete_key(td::Slice public_key) { - return td::unlink(to_file_path(public_key)); +td::Status KeyStorage::delete_key(const Key &key) { + return td::unlink(to_file_path(key)); } td::Result KeyStorage::import_key(td::Slice local_password, td::Slice mnemonic_password, @@ -122,6 +140,7 @@ td::Result KeyStorage::change_local_password(InputKey input_key Key res; res.public_key = std::move(input_key.key.public_key); res.secret = std::move(new_secret); + TRY_STATUS(td::copy_file(to_file_path(input_key.key), to_file_path(res))); return std::move(res); } diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.h b/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.h index 305872be23..f7982805ef 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.h @@ -57,7 +57,7 @@ class KeyStorage { td::Result export_encrypted_key(InputKey input_key, td::Slice key_password); td::Result change_local_password(InputKey input_key, td::Slice new_local_password); - td::Status delete_key(td::Slice public_key); + td::Status delete_key(const Key& key); td::Result import_key(td::Slice local_password, td::Slice mnemonic_password, ExportedKey exported_key); td::Result import_pem_key(td::Slice local_password, td::Slice key_password, ExportedPemKey exported_key); @@ -72,6 +72,7 @@ class KeyStorage { td::Result save_key(const DecryptedKey& mnemonic, td::Slice local_password); td::Result export_decrypted_key(InputKey input_key); - std::string to_file_path(td::Slice public_key); + std::string to_file_path(const Key& key); + std::string to_file_path_old(const Key& key); }; } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.cpp index fa979a3ca3..684b2c056c 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.cpp @@ -1,3 +1,21 @@ +/* + 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 . + + Copyright 2017-2019 Telegram Systems LLP +*/ #include "LastBlockStorage.h" #include "td/utils/as.h" diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.h b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.h index fa920ef6ed..d8cbd3fcd1 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlockStorage.h @@ -1,3 +1,21 @@ +/* + 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 . + + Copyright 2017-2019 Telegram Systems LLP +*/ #pragma once #include "tonlib/LastBlock.h" diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/Logging.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/Logging.cpp new file mode 100644 index 0000000000..043fe0190d --- /dev/null +++ b/submodules/ton/tonlib-src/tonlib/tonlib/Logging.cpp @@ -0,0 +1,137 @@ +/* + 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 . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "Logging.h" + +#include "auto/tl/tonlib_api.h" + +#include "td/utils/FileLog.h" +#include "td/utils/logging.h" +#include "td/utils/misc.h" +#include "td/utils/misc.h" + +#include +#include +#include + +namespace tonlib { + +static std::mutex logging_mutex; +static td::FileLog file_log; +static td::TsLog ts_log(&file_log); +static td::NullLog null_log; + +td::int32 VERBOSITY_NAME(abc) = VERBOSITY_NAME(DEBUG); +td::int32 VERBOSITY_NAME(bcd) = VERBOSITY_NAME(DEBUG); +#define ADD_TAG(tag) \ + { #tag, &VERBOSITY_NAME(tag) } +static const std::map log_tags{ADD_TAG(abc), ADD_TAG(bcd)}; +#undef ADD_TAG + +td::Status Logging::set_current_stream(tonlib_api::object_ptr stream) { + if (stream == nullptr) { + return td::Status::Error("Log stream must not be empty"); + } + + std::lock_guard lock(logging_mutex); + switch (stream->get_id()) { + case tonlib_api::logStreamDefault::ID: + td::log_interface = td::default_log_interface; + return td::Status::OK(); + case tonlib_api::logStreamFile::ID: { + auto file_stream = tonlib_api::move_object_as(stream); + auto max_log_file_size = file_stream->max_file_size_; + if (max_log_file_size <= 0) { + return td::Status::Error("Max log file size should be positive"); + } + + TRY_STATUS(file_log.init(file_stream->path_, max_log_file_size)); + std::atomic_thread_fence(std::memory_order_release); // better than nothing + td::log_interface = &ts_log; + return td::Status::OK(); + } + case tonlib_api::logStreamEmpty::ID: + td::log_interface = &null_log; + return td::Status::OK(); + default: + UNREACHABLE(); + return td::Status::OK(); + } +} + +td::Result> Logging::get_current_stream() { + std::lock_guard lock(logging_mutex); + if (td::log_interface == td::default_log_interface) { + return tonlib_api::make_object(); + } + if (td::log_interface == &null_log) { + return tonlib_api::make_object(); + } + if (td::log_interface == &ts_log) { + return tonlib_api::make_object(file_log.get_path().str(), + file_log.get_rotate_threshold()); + } + return td::Status::Error("Log stream is unrecognized"); +} + +td::Status Logging::set_verbosity_level(int new_verbosity_level) { + std::lock_guard lock(logging_mutex); + if (0 <= new_verbosity_level && new_verbosity_level <= VERBOSITY_NAME(NEVER)) { + SET_VERBOSITY_LEVEL(VERBOSITY_NAME(FATAL) + new_verbosity_level); + return td::Status::OK(); + } + + return td::Status::Error("Wrong new verbosity level specified"); +} + +int Logging::get_verbosity_level() { + std::lock_guard lock(logging_mutex); + return GET_VERBOSITY_LEVEL(); +} + +td::vector Logging::get_tags() { + return transform(log_tags, [](auto &tag) { return tag.first.str(); }); +} + +td::Status Logging::set_tag_verbosity_level(td::Slice tag, int new_verbosity_level) { + auto it = log_tags.find(tag); + if (it == log_tags.end()) { + return td::Status::Error("Log tag is not found"); + } + + std::lock_guard lock(logging_mutex); + *it->second = td::clamp(new_verbosity_level, 1, VERBOSITY_NAME(NEVER)); + return td::Status::OK(); +} + +td::Result Logging::get_tag_verbosity_level(td::Slice tag) { + auto it = log_tags.find(tag); + if (it == log_tags.end()) { + return td::Status::Error("Log tag is not found"); + } + + std::lock_guard lock(logging_mutex); + return *it->second; +} + +void Logging::add_message(int log_verbosity_level, td::Slice message) { + int VERBOSITY_NAME(client) = td::clamp(log_verbosity_level, 0, VERBOSITY_NAME(NEVER)); + VLOG(client) << message; +} + +} // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/Logging.h b/submodules/ton/tonlib-src/tonlib/tonlib/Logging.h new file mode 100644 index 0000000000..9dbda9d367 --- /dev/null +++ b/submodules/ton/tonlib-src/tonlib/tonlib/Logging.h @@ -0,0 +1,49 @@ +/* + 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 . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#pragma once + +#include "auto/tl/tonlib_api.h" + +#include "td/utils/common.h" +#include "td/utils/Slice.h" +#include "td/utils/Status.h" + +namespace tonlib { +namespace tonlib_api = ton::tonlib_api; + +class Logging { + public: + static td::Status set_current_stream(tonlib_api::object_ptr stream); + + static td::Result> get_current_stream(); + + static td::Status set_verbosity_level(int new_verbosity_level); + + static int get_verbosity_level(); + + static std::vector get_tags(); + + static td::Status set_tag_verbosity_level(td::Slice tag, int new_verbosity_level); + + static td::Result get_tag_verbosity_level(td::Slice tag); + + static void add_message(int log_verbosity_level, td::Slice message); +}; + +} // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.cpp index 9ea58e54e2..50c68571ce 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/TestGiver.cpp @@ -34,7 +34,7 @@ vm::CellHash TestGiver::get_init_code_hash() { td::Ref TestGiver::make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message, const block::StdAddress& dest_address) { - CHECK(message.size() <= 128); + CHECK(message.size() <= 124); td::BigInt256 dest_addr; dest_addr.import_bits(dest_address.addr.as_bitslice()); vm::CellBuilder cb; @@ -45,7 +45,7 @@ td::Ref TestGiver::make_a_gift_message(td::uint32 seqno, td::uint64 gr .store_int256(dest_addr, 256); block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms)); - auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes(message).finalize(); + auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes("\0\0\0\0", 4).store_bytes(message).finalize(); return vm::CellBuilder().store_long(seqno, 32).store_long(1, 8).store_ref(message_inner).finalize(); } } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.cpp index c092bac29c..022eaca9db 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/TestWallet.cpp @@ -40,17 +40,20 @@ td::Ref TestWallet::get_init_message(const td::Ed25519::PrivateKey& pr td::Ref TestWallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, td::int64 gramms, td::Slice message, const block::StdAddress& dest_address) { - CHECK(message.size() <= 128); + CHECK(message.size() <= 124); td::BigInt256 dest_addr; dest_addr.import_bits(dest_address.addr.as_bitslice()); vm::CellBuilder cb; - cb.append_cellslice(binary_bitstring_to_cellslice("b{010000100}").move_as_ok()) + cb.append_cellslice(binary_bitstring_to_cellslice("b{01}").move_as_ok()) + .store_long(dest_address.bounceable, 1) + .append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok()) .store_long(dest_address.workchain, 8) .store_int256(dest_addr, 256); block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms)); - auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes(message).finalize(); - auto message_outer = vm::CellBuilder().store_long(seqno, 32).store_long(1, 8).store_ref(message_inner).finalize(); - std::string seq_no(4, 0); + auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes("\0\0\0\0", 4).store_bytes(message).finalize(); + td::int8 send_mode = 3; + auto message_outer = + vm::CellBuilder().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(); } diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp index ea0c6c81e9..babf6ed0a8 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp @@ -22,7 +22,9 @@ #include "tonlib/ExtClientOutbound.h" #include "tonlib/GenericAccount.h" #include "tonlib/LastBlock.h" +#include "tonlib/Logging.h" #include "tonlib/TestWallet.h" +#include "tonlib/Wallet.h" #include "tonlib/TestGiver.h" #include "tonlib/utils.h" #include "tonlib/keys/Mnemonic.h" @@ -72,7 +74,6 @@ struct RawAccountState { td::Ref code; td::Ref data; block::AccountState::Info info; - td::int64 sync_utime = 0; }; td::Result to_balance_or_throw(td::Ref balance_ref) { @@ -189,7 +190,7 @@ class GetRawAccountState : public td::actor::Actor { auto serialized_state = account_state.state.clone(); RawAccountState res; res.info = std::move(info); - res.sync_utime = last_block_.utime; + LOG_IF(ERROR, res.info.gen_utime > last_block_.utime) << res.info.gen_utime << " " << last_block_.utime; auto cell = res.info.root; if (cell.is_null()) { return res; @@ -412,8 +413,17 @@ bool TonlibClient::is_static_request(td::int32 id) { case tonlib_api::runTests::ID: case tonlib_api::raw_getAccountAddress::ID: case tonlib_api::testWallet_getAccountAddress::ID: + case tonlib_api::wallet_getAccountAddress::ID: case tonlib_api::testGiver_getAccountAddress::ID: case tonlib_api::getBip39Hints::ID: + case tonlib_api::setLogStream::ID: + case tonlib_api::getLogStream::ID: + case tonlib_api::setLogVerbosityLevel::ID: + case tonlib_api::getLogVerbosityLevel::ID: + case tonlib_api::getLogTags::ID: + case tonlib_api::setLogTagVerbosityLevel::ID: + case tonlib_api::getLogTagVerbosityLevel::ID: + case tonlib_api::addLogMessage::ID: return true; default: return false; @@ -449,6 +459,12 @@ td::Result get_account_address(const tonlib_api::testWallet_i return GenericAccount::get_address(0 /*zerochain*/, TestWallet::get_init_state(key)); } +td::Result get_account_address(const tonlib_api::wallet_initialAccountState& test_wallet_state) { + TRY_RESULT(key_bytes, block::PublicKey::parse(test_wallet_state.public_key_)); + auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key)); + return GenericAccount::get_address(0 /*zerochain*/, Wallet::get_init_state(key)); +} + tonlib_api::object_ptr TonlibClient::do_static_request( const tonlib_api::raw_getAccountAddress& request) { auto r_account_address = get_account_address(*request.initital_account_state_); @@ -465,6 +481,14 @@ tonlib_api::object_ptr TonlibClient::do_static_request( } return tonlib_api::make_object(r_account_address.ok().rserialize()); } +tonlib_api::object_ptr TonlibClient::do_static_request( + const tonlib_api::wallet_getAccountAddress& request) { + 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(r_account_address.ok().rserialize()); +} tonlib_api::object_ptr TonlibClient::do_static_request( const tonlib_api::testGiver_getAccountAddress& request) { return tonlib_api::make_object(TestGiver::address().rserialize()); @@ -547,8 +571,8 @@ td::Result> to_raw_accountS .as_slice() .str(); } - return tonlib_api::make_object(raw_state.balance, std::move(code), std::move(data), - to_transaction_id(raw_state.info), raw_state.sync_utime); + return tonlib_api::make_object( + raw_state.balance, std::move(code), std::move(data), to_transaction_id(raw_state.info), raw_state.info.gen_utime); } td::Result to_std_address_or_throw(td::Ref cs) { @@ -601,6 +625,10 @@ td::Result> to_raw_message_or_th if (body->size() % 8 == 0) { body_message = std::string(body->size() / 8, 0); body->prefetch_bytes(td::MutableSlice(body_message).ubegin(), body->size() / 8); + if (body_message.size() >= 4 && body_message[0] == 0 && body_message[1] == 0 && body_message[2] == 0 && + body_message[3] == 0) { + body_message = body_message.substr(4); + } } return tonlib_api::make_object(std::move(src), std::move(dest), balance, @@ -711,7 +739,22 @@ td::Result> to_testW return td::Status::Error("Failed to parse seq_no"); } return tonlib_api::make_object( - raw_state.balance, static_cast(seqno), to_transaction_id(raw_state.info), raw_state.sync_utime); + raw_state.balance, static_cast(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime); +} + +td::Result> to_wallet_accountState( + RawAccountState&& raw_state) { + if (raw_state.data.is_null()) { + return td::Status::Error(400, "Not a Wallet"); + } + auto ref = raw_state.data->prefetch_ref(); + auto cs = vm::load_cell_slice(std::move(ref)); + auto seqno = cs.fetch_ulong(32); + if (seqno == cs.fetch_ulong_eof) { + return td::Status::Error("Failed to parse seq_no"); + } + return tonlib_api::make_object( + raw_state.balance, static_cast(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime); } td::Result> to_testGiver_accountState( @@ -726,7 +769,7 @@ td::Result> to_testGi return td::Status::Error("Failed to parse seq_no"); } return tonlib_api::make_object( - raw_state.balance, static_cast(seqno), to_transaction_id(raw_state.info), raw_state.sync_utime); + raw_state.balance, static_cast(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime); } td::Result> to_generic_accountState( @@ -734,7 +777,7 @@ td::Result> to_generic_ if (raw_state.code.is_null()) { return tonlib_api::make_object( tonlib_api::make_object(raw_state.balance, to_transaction_id(raw_state.info), - raw_state.sync_utime)); + raw_state.info.gen_utime)); } auto code_hash = raw_state.code->prefetch_ref()->get_hash(); @@ -742,6 +785,10 @@ td::Result> to_generic_ TRY_RESULT(test_wallet, to_testWallet_accountState(std::move(raw_state))); return tonlib_api::make_object(std::move(test_wallet)); } + if (code_hash == Wallet::get_init_code_hash()) { + TRY_RESULT(wallet, to_wallet_accountState(std::move(raw_state))); + return tonlib_api::make_object(std::move(wallet)); + } if (code_hash == TestGiver::get_init_code_hash()) { TRY_RESULT(test_wallet, to_testGiver_accountState(std::move(raw_state))); return tonlib_api::make_object(std::move(test_wallet)); @@ -858,7 +905,7 @@ td::Status TonlibClient::do_request(const tonlib_api::testWallet_sendGrams& requ if (!request.private_key_) { return td::Status::Error(400, "Field private_key must not be empty"); } - if (request.message_.size() > 128) { + if (request.message_.size() > 124) { return td::Status::Error(400, "Message is too long"); } TRY_RESULT(account_address, block::StdAddress::parse(request.destination_->account_address_)); @@ -866,16 +913,22 @@ td::Status TonlibClient::do_request(const tonlib_api::testWallet_sendGrams& requ TRY_RESULT(input_key, from_tonlib(*request.private_key_)); auto address = GenericAccount::get_address( 0 /*zerochain*/, TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy()))); - TRY_RESULT(private_key, key_storage_.load_private_key(std::move(input_key))); - return do_request(tonlib_api::raw_sendMessage( - tonlib_api::make_object(address.rserialize()), "", - vm::std_boc_serialize(TestWallet::make_a_gift_message( - td::Ed25519::PrivateKey(std::move(private_key.private_key)), - request.seqno_, request.amount_, request.message_, account_address)) - .move_as_ok() - .as_slice() - .str()), - std::move(promise)); + TRY_RESULT(private_key_str, key_storage_.load_private_key(std::move(input_key))); + auto private_key = td::Ed25519::PrivateKey(std::move(private_key_str.private_key)); + std::string init_state; + if (request.seqno_ == 0) { + TRY_RESULT(public_key, private_key.get_public_key()); + init_state = vm::std_boc_serialize(TestWallet::get_init_state(public_key)).move_as_ok().as_slice().str(); + } + return do_request( + tonlib_api::raw_sendMessage( + tonlib_api::make_object(address.rserialize()), std::move(init_state), + vm::std_boc_serialize(TestWallet::make_a_gift_message(private_key, request.seqno_, request.amount_, + request.message_, account_address)) + .move_as_ok() + .as_slice() + .str()), + std::move(promise)); } td::Status TonlibClient::do_request(tonlib_api::testWallet_getAccountState& request, @@ -896,13 +949,84 @@ td::Status TonlibClient::do_request(tonlib_api::testWallet_getAccountState& requ return td::Status::OK(); } +// Wallet +td::Status TonlibClient::do_request(const tonlib_api::wallet_init& request, + td::Promise>&& promise) { + if (!request.private_key_) { + return td::Status::Error(400, "Field private_key must not be empty"); + } + TRY_RESULT(input_key, from_tonlib(*request.private_key_)); + auto init_state = Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())); + auto address = GenericAccount::get_address(0 /*zerochain*/, init_state); + TRY_RESULT(private_key, key_storage_.load_private_key(std::move(input_key))); + auto init_message = Wallet::get_init_message(td::Ed25519::PrivateKey(std::move(private_key.private_key))); + return do_request( + tonlib_api::raw_sendMessage(tonlib_api::make_object(address.rserialize()), + vm::std_boc_serialize(init_state).move_as_ok().as_slice().str(), + vm::std_boc_serialize(init_message).move_as_ok().as_slice().str()), + std::move(promise)); +} + +td::Status TonlibClient::do_request(const tonlib_api::wallet_sendGrams& request, + td::Promise>&& promise) { + if (!request.destination_) { + return td::Status::Error(400, "Field destination must not be empty"); + } + if (!request.private_key_) { + return td::Status::Error(400, "Field private_key must not be empty"); + } + if (request.message_.size() > 124) { + return td::Status::Error(400, "Message is too long"); + } + TRY_RESULT(valid_until, td::narrow_cast_safe(request.valid_until_)); + TRY_RESULT(account_address, block::StdAddress::parse(request.destination_->account_address_)); + account_address.bounceable = false; + TRY_RESULT(input_key, from_tonlib(*request.private_key_)); + auto address = GenericAccount::get_address( + 0 /*zerochain*/, Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy()))); + TRY_RESULT(private_key_str, key_storage_.load_private_key(std::move(input_key))); + auto private_key = td::Ed25519::PrivateKey(std::move(private_key_str.private_key)); + std::string init_state; + if (request.seqno_ == 0) { + TRY_RESULT(public_key, private_key.get_public_key()); + init_state = vm::std_boc_serialize(Wallet::get_init_state(public_key)).move_as_ok().as_slice().str(); + } + return do_request( + tonlib_api::raw_sendMessage( + tonlib_api::make_object(address.rserialize()), std::move(init_state), + vm::std_boc_serialize(Wallet::make_a_gift_message(private_key, request.seqno_, valid_until, request.amount_, + request.message_, account_address)) + .move_as_ok() + .as_slice() + .str()), + std::move(promise)); +} + +td::Status TonlibClient::do_request(tonlib_api::wallet_getAccountState& request, + td::Promise>&& promise) { + if (!request.account_address_) { + return td::Status::Error(400, "Field account_address must not be empty"); + } + TRY_RESULT(account_address, block::StdAddress::parse(request.account_address_->account_address_)); + td::actor::create_actor( + "GetAccountState", client_.get_client(), std::move(account_address), + [promise = std::move(promise)](td::Result r_state) mutable { + if (r_state.is_error()) { + return promise.set_error(r_state.move_as_error()); + } + promise.set_result(to_wallet_accountState(r_state.move_as_ok())); + }) + .release(); + return td::Status::OK(); +} + // TestGiver td::Status TonlibClient::do_request(const tonlib_api::testGiver_sendGrams& request, td::Promise>&& promise) { if (!request.destination_) { return td::Status::Error(400, "Field destination must not be empty"); } - if (request.message_.size() > 128) { + if (request.message_.size() > 124) { return td::Status::Error(400, "Message is too long"); } TRY_RESULT(account_address, block::StdAddress::parse(request.destination_->account_address_)); @@ -949,61 +1073,182 @@ td::Status TonlibClient::do_request(const tonlib_api::generic_getAccountState& r return td::Status::OK(); } +class TonlibQueryActor : public td::actor::Actor { + public: + TonlibQueryActor(td::actor::ActorShared client) : client_(std::move(client)) { + } + template + void send_query(QueryT query, td::Promise promise) { + td::actor::send_lambda(client_, + [self = client_.get(), query = std::move(query), promise = std::move(promise)]() mutable { + auto status = self.get_actor_unsafe().do_request(query, std::move(promise)); + if (status.is_error()) { + promise.set_error(std::move(status)); + } + }); + } + + private: + td::actor::ActorShared client_; +}; + +class GenericSendGrams : public TonlibQueryActor { + public: + GenericSendGrams(td::actor::ActorShared client, tonlib_api::generic_sendGrams send_grams, + td::Promise>&& promise) + : TonlibQueryActor(std::move(client)), send_grams_(std::move(send_grams)), promise_(std::move(promise)) { + } + + private: + tonlib_api::generic_sendGrams send_grams_; + td::Promise> promise_; + + tonlib_api::object_ptr source_state_; + block::StdAddress source_address_; + + tonlib_api::object_ptr destination_state_; + bool is_destination_bounce_{false}; + + void check(td::Status status) { + if (status.is_error()) { + LOG(ERROR) << status; + promise_.set_error(std::move(status)); + return stop(); + } + } + + void start_up() override { + check(do_start_up()); + } + + td::Status do_start_up() { + alarm_timestamp() = td::Timestamp::in(15); + if (!send_grams_.destination_) { + return td::Status::Error(400, "Field destination must not be empty"); + } + TRY_RESULT(destination_address, block::StdAddress::parse(send_grams_.destination_->account_address_)); + is_destination_bounce_ = destination_address.bounceable; + + if (!send_grams_.source_) { + return td::Status::Error(400, "Field source must not be empty"); + } + TRY_RESULT(source_address, block::StdAddress::parse(send_grams_.source_->account_address_)); + source_address_ = std::move(source_address); + + send_query(tonlib_api::generic_getAccountState( + tonlib_api::make_object(send_grams_.source_->account_address_)), + [actor_id = actor_id(this)](auto r_res) { + send_closure(actor_id, &GenericSendGrams::on_source_state, std::move(r_res)); + }); + send_query(tonlib_api::generic_getAccountState( + tonlib_api::make_object(send_grams_.destination_->account_address_)), + [actor_id = actor_id(this)](auto r_res) { + send_closure(actor_id, &GenericSendGrams::on_destination_state, std::move(r_res)); + }); + return do_loop(); + } + + static tonlib_api::object_ptr clone(const tonlib_api::object_ptr& ptr) { + if (!ptr) { + return nullptr; + } + return tonlib_api::make_object(ptr->public_key_, ptr->secret_.copy()); + } + + static tonlib_api::object_ptr clone(const tonlib_api::object_ptr& ptr) { + if (!ptr) { + return nullptr; + } + return tonlib_api::make_object(clone(ptr->key_), ptr->local_password_.copy()); + } + + void on_source_state(td::Result> r_state) { + check(do_on_source_state(std::move(r_state))); + } + + td::Status do_on_source_state(td::Result> r_state) { + TRY_RESULT(state, std::move(r_state)); + source_state_ = std::move(state); + if (source_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && send_grams_.private_key_ && + send_grams_.private_key_->key_) { + TRY_RESULT(key_bytes, block::PublicKey::parse(send_grams_.private_key_->key_->public_key_)); + auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key)); + + if (GenericAccount::get_address(0 /*zerochain*/, TestWallet::get_init_state(key)).addr == source_address_.addr) { + source_state_ = tonlib_api::make_object( + tonlib_api::make_object(-1, 0, nullptr, 0)); + } else if (GenericAccount::get_address(0 /*zerochain*/, Wallet::get_init_state(key)).addr == + source_address_.addr) { + source_state_ = tonlib_api::make_object( + tonlib_api::make_object(-1, 0, nullptr, 0)); + } + } + return do_loop(); + } + + void on_destination_state(td::Result> r_state) { + check(do_on_destination_state(std::move(r_state))); + } + + td::Status do_on_destination_state(td::Result> r_state) { + TRY_RESULT(state, std::move(r_state)); + destination_state_ = std::move(state); + if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID) { + //FIXME + //return td::Status::Error("Transfer to uninited wallet"); + } + return do_loop(); + } + + void alarm() override { + check(td::Status::Error("Timeout")); + } + td::Status do_loop() { + if (!source_state_ || !destination_state_) { + return td::Status::OK(); + } + downcast_call(*source_state_, + td::overloaded( + [&](tonlib_api::generic_accountStateTestGiver& test_giver_state) { + send_query(tonlib_api::testGiver_sendGrams( + std::move(send_grams_.destination_), test_giver_state.account_state_->seqno_, + send_grams_.amount_, std::move(send_grams_.message_)), + std::move(promise_)); + stop(); + }, + [&](tonlib_api::generic_accountStateTestWallet& test_wallet_state) { + send_query(tonlib_api::testWallet_sendGrams( + std::move(send_grams_.private_key_), std::move(send_grams_.destination_), + test_wallet_state.account_state_->seqno_, send_grams_.amount_, + std::move(send_grams_.message_)), + std::move(promise_)); + stop(); + }, + [&](tonlib_api::generic_accountStateWallet& test_wallet_state) { + send_query(tonlib_api::wallet_sendGrams( + std::move(send_grams_.private_key_), std::move(send_grams_.destination_), + test_wallet_state.account_state_->seqno_, std::numeric_limits::max(), + send_grams_.amount_, std::move(send_grams_.message_)), + std::move(promise_)); + stop(); + }, + [&](tonlib_api::generic_accountStateUninited&) { + promise_.set_error(td::Status::Error(400, "Account is not inited")); + stop(); + }, + [&](tonlib_api::generic_accountStateRaw&) { + promise_.set_error(td::Status::Error(400, "Unknown account type")); + stop(); + })); + return td::Status::OK(); + } +}; + td::Status TonlibClient::do_request(tonlib_api::generic_sendGrams& request, td::Promise>&& promise) { - TRY_RESULT(account_address, block::StdAddress::parse(request.source_->account_address_)); - LOG(INFO) << "Send " << request.amount_ << " nanograms from " << account_address.rserialize(); - td::actor::create_actor( - "GetAccountState", client_.get_client(), std::move(account_address), - [promise = std::move(promise), self = this, actor_id = td::actor::actor_id(), - private_key = std::move(request.private_key_), destination = std::move(request.destination_), - amount = request.amount_, message = std::move(request.message_)](td::Result r_state) mutable { - if (r_state.is_error()) { - return promise.set_error(r_state.move_as_error()); - } - auto rr_state = to_generic_accountState(r_state.move_as_ok()); - if (rr_state.is_error()) { - return promise.set_error(rr_state.move_as_error()); - } - auto state = rr_state.move_as_ok(); - - downcast_call(*state, td::overloaded( - [&](tonlib_api::generic_accountStateTestGiver& test_giver_state) { - send_lambda(actor_id, - [promise = std::move(promise), self, - query = tonlib_api::testGiver_sendGrams( - std::move(destination), test_giver_state.account_state_->seqno_, - amount, std::move(message))]() mutable { - LOG(INFO) << "Send " << to_string(query); - auto status = self->do_request(query, std::move(promise)); - if (status.is_error()) { - CHECK(promise); - promise.set_error(std::move(status)); - } - }); - return; - }, - [&](tonlib_api::generic_accountStateTestWallet& test_wallet_state) { - send_lambda(actor_id, [promise = std::move(promise), self, - query = tonlib_api::testWallet_sendGrams( - std::move(private_key), std::move(destination), - test_wallet_state.account_state_->seqno_, amount, - std::move(message))]() mutable { - auto status = self->do_request(query, std::move(promise)); - if (status.is_error()) { - CHECK(promise); - promise.set_error(std::move(status)); - } - }); - }, - [&](tonlib_api::generic_accountStateUninited&) { - promise.set_error(td::Status::Error(400, "Account is not inited")); - }, - [&](tonlib_api::generic_accountStateRaw&) { - promise.set_error(td::Status::Error(400, "Unknown account type")); - })); - }) - .release(); + auto id = actor_id_++; + actors_[id] = td::actor::create_actor("GenericSendGrams", actor_shared(this, id), + std::move(request), std::move(promise)); return td::Status::OK(); } @@ -1029,8 +1274,14 @@ td::Status TonlibClient::do_request(const tonlib_api::exportKey& request, td::Status TonlibClient::do_request(const tonlib_api::deleteKey& request, td::Promise>&& promise) { - TRY_RESULT(key_bytes, block::PublicKey::parse(request.public_key_)); - TRY_STATUS(key_storage_.delete_key(key_bytes.key)); + if (!request.key_) { + return td::Status::Error(400, "Field key must not be empty"); + } + TRY_RESULT(key_bytes, block::PublicKey::parse(request.key_->public_key_)); + KeyStorage::Key key; + key.public_key = td::SecureString(key_bytes.key); + key.secret = std::move(request.key_->secret_); + TRY_STATUS(key_storage_.delete_key(key)); promise.set_value(tonlib_api::make_object()); return td::Status::OK(); } @@ -1141,4 +1392,59 @@ td::Status TonlibClient::do_request(const tonlib_api::onLiteServerQueryError& re return td::Status::OK(); } +tonlib_api::object_ptr TonlibClient::do_static_request(tonlib_api::setLogStream& request) { + auto result = Logging::set_current_stream(std::move(request.log_stream_)); + if (result.is_ok()) { + return tonlib_api::make_object(); + } else { + return tonlib_api::make_object(400, result.message().str()); + } +} +tonlib_api::object_ptr TonlibClient::do_static_request(const tonlib_api::getLogStream& request) { + auto result = Logging::get_current_stream(); + if (result.is_ok()) { + return result.move_as_ok(); + } else { + return tonlib_api::make_object(400, result.error().message().str()); + } +} +tonlib_api::object_ptr TonlibClient::do_static_request( + const tonlib_api::setLogVerbosityLevel& request) { + auto result = Logging::set_verbosity_level(static_cast(request.new_verbosity_level_)); + if (result.is_ok()) { + return tonlib_api::make_object(); + } else { + return tonlib_api::make_object(400, result.message().str()); + } +} +tonlib_api::object_ptr TonlibClient::do_static_request( + const tonlib_api::setLogTagVerbosityLevel& request) { + auto result = Logging::set_tag_verbosity_level(request.tag_, static_cast(request.new_verbosity_level_)); + if (result.is_ok()) { + return tonlib_api::make_object(); + } else { + return tonlib_api::make_object(400, result.message().str()); + } +} +tonlib_api::object_ptr TonlibClient::do_static_request( + const tonlib_api::getLogVerbosityLevel& request) { + return tonlib_api::make_object(Logging::get_verbosity_level()); +} +tonlib_api::object_ptr TonlibClient::do_static_request( + const tonlib_api::getLogTagVerbosityLevel& request) { + auto result = Logging::get_tag_verbosity_level(request.tag_); + if (result.is_ok()) { + return tonlib_api::make_object(result.ok()); + } else { + return tonlib_api::make_object(400, result.error().message().str()); + } +} +tonlib_api::object_ptr TonlibClient::do_static_request(const tonlib_api::getLogTags& request) { + return tonlib_api::make_object(Logging::get_tags()); +} +tonlib_api::object_ptr TonlibClient::do_static_request(const tonlib_api::addLogMessage& request) { + Logging::add_message(request.verbosity_level_, request.text_); + return tonlib_api::make_object(); +} + } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.h b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.h index a45fd6fdfc..5ac81c2ca2 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.h @@ -28,6 +28,8 @@ #include "td/actor/actor.h" +#include + namespace tonlib { class TonlibClient : public td::actor::Actor { public: @@ -58,6 +60,9 @@ class TonlibClient : public td::actor::Actor { td::actor::ActorOwn raw_last_block_; ExtClient client_; + std::map> actors_; + td::int64 actor_id_{1}; + ExtClientRef get_client_ref(); void init_ext_client(); void init_last_block(); @@ -65,12 +70,17 @@ class TonlibClient : public td::actor::Actor { bool is_closing_{false}; td::uint32 ref_cnt_{1}; void hangup_shared() override { - ref_cnt_--; + auto it = actors_.find(get_link_token()); + if (it != actors_.end()) { + actors_.erase(it); + } else { + ref_cnt_--; + } try_stop(); } void hangup() override; void try_stop() { - if (is_closing_ && ref_cnt_ == 0) { + if (is_closing_ && ref_cnt_ == 0 && actors_.empty()) { stop(); } } @@ -86,8 +96,19 @@ class TonlibClient : public td::actor::Actor { static object_ptr do_static_request(const tonlib_api::runTests& request); static object_ptr do_static_request(const tonlib_api::raw_getAccountAddress& request); static object_ptr do_static_request(const tonlib_api::testWallet_getAccountAddress& request); + static object_ptr do_static_request(const tonlib_api::wallet_getAccountAddress& request); static object_ptr do_static_request(const tonlib_api::testGiver_getAccountAddress& request); static object_ptr do_static_request(tonlib_api::getBip39Hints& request); + + static object_ptr do_static_request(tonlib_api::setLogStream& request); + static object_ptr do_static_request(const tonlib_api::getLogStream& request); + static object_ptr do_static_request(const tonlib_api::setLogVerbosityLevel& request); + static object_ptr do_static_request(const tonlib_api::setLogTagVerbosityLevel& request); + static object_ptr do_static_request(const tonlib_api::getLogVerbosityLevel& request); + static object_ptr do_static_request(const tonlib_api::getLogTagVerbosityLevel& request); + static object_ptr do_static_request(const tonlib_api::getLogTags& request); + static object_ptr do_static_request(const tonlib_api::addLogMessage& request); + template td::Status do_request(const T& request, P&& promise) { return td::Status::Error(400, "Function is unsupported"); @@ -112,6 +133,11 @@ class TonlibClient : public td::actor::Actor { td::Status do_request(tonlib_api::testWallet_getAccountState& request, td::Promise>&& promise); + td::Status do_request(const tonlib_api::wallet_init& request, td::Promise>&& promise); + td::Status do_request(const tonlib_api::wallet_sendGrams& request, td::Promise>&& promise); + td::Status do_request(tonlib_api::wallet_getAccountState& request, + td::Promise>&& promise); + td::Status do_request(const tonlib_api::testGiver_getAccountState& request, td::Promise>&& promise); td::Status do_request(const tonlib_api::testGiver_sendGrams& request, @@ -145,5 +171,7 @@ class TonlibClient : public td::actor::Actor { td::Promise>&& promise); void proxy_request(td::int64 query_id, std::string data); + + friend class TonlibQueryActor; }; } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/Wallet.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/Wallet.cpp new file mode 100644 index 0000000000..7546e8fd22 --- /dev/null +++ b/submodules/ton/tonlib-src/tonlib/tonlib/Wallet.cpp @@ -0,0 +1,89 @@ +/* + 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 . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "tonlib/Wallet.h" +#include "tonlib/GenericAccount.h" +#include "tonlib/utils.h" + +#include "vm/boc.h" +#include "td/utils/base64.h" + +#include + +namespace tonlib { +td::Ref Wallet::get_init_state(const td::Ed25519::PublicKey& public_key) { + auto code = get_init_code(); + auto data = get_init_data(public_key); + return GenericAccount::get_init_state(std::move(code), std::move(data)); +} + +td::Ref Wallet::get_init_message(const td::Ed25519::PrivateKey& private_key) { + td::uint32 seqno = 0; + td::uint32 valid_until = std::numeric_limits::max(); + auto signature = + private_key + .sign(vm::CellBuilder().store_long(seqno, 32).store_long(valid_until, 32).finalize()->get_hash().as_slice()) + .move_as_ok(); + return vm::CellBuilder().store_bytes(signature).store_long(seqno, 32).store_long(valid_until, 32).finalize(); +} + +td::Ref Wallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, + td::uint32 valid_until, td::int64 gramms, td::Slice message, + const block::StdAddress& dest_address) { + CHECK(message.size() <= 124); + td::BigInt256 dest_addr; + dest_addr.import_bits(dest_address.addr.as_bitslice()); + vm::CellBuilder cb; + cb.append_cellslice(binary_bitstring_to_cellslice("b{01}").move_as_ok()) + .store_long(dest_address.bounceable, 1) + .append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok()) + .store_long(dest_address.workchain, 8) + .store_int256(dest_addr, 256); + block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms)); + auto message_inner = cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes("\0\0\0\0", 4).store_bytes(message).finalize(); + td::int8 send_mode = 3; + auto message_outer = vm::CellBuilder() + .store_long(seqno, 32) + .store_long(valid_until, 32) + .store_long(send_mode, 8) + .store_ref(message_inner) + .finalize(); + std::string seq_no(4, 0); + 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 Wallet::get_init_code() { + static auto res = [] { + auto serialized_code = td::base64_decode( + "te6ccgEEAQEAAAAAVwAAqv8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x8B+CO78mPtRNDTH9P/" + "0VExuvKhA/kBVBBC+RDyovgAApMg10qW0wfUAvsA6NGkyMsfy//J7VQ=") + .move_as_ok(); + return vm::std_boc_deserialize(serialized_code).move_as_ok(); + }(); + return res; +} + +vm::CellHash Wallet::get_init_code_hash() { + return get_init_code()->get_hash(); +} + +td::Ref Wallet::get_init_data(const td::Ed25519::PublicKey& public_key) { + return vm::CellBuilder().store_long(0, 32).store_bytes(public_key.as_octet_string()).finalize(); +} +} // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/Wallet.h b/submodules/ton/tonlib-src/tonlib/tonlib/Wallet.h new file mode 100644 index 0000000000..2f2d8a8de1 --- /dev/null +++ b/submodules/ton/tonlib-src/tonlib/tonlib/Wallet.h @@ -0,0 +1,38 @@ +/* + 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 . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#pragma once + +#include "vm/cells.h" +#include "Ed25519.h" +#include "block/block.h" + +namespace tonlib { +class Wallet { + public: + static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key); + static td::Ref get_init_message(const td::Ed25519::PrivateKey& private_key); + static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, + td::uint32 valid_until, td::int64 gramms, td::Slice message, + const block::StdAddress& dest_address); + + static td::Ref get_init_code(); + static vm::CellHash get_init_code_hash(); + static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key); +}; +} // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/tonlib-cli.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/tonlib-cli.cpp index f6ce8883a9..191adba647 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/tonlib-cli.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/tonlib-cli.cpp @@ -27,6 +27,7 @@ class TonlibCli : public td::actor::Actor { std::string config; std::string key_dir{"."}; bool use_callbacks_for_network{false}; + bool use_simple_wallet{false}; }; TonlibCli(Options options) : options_(std::move(options)) { } @@ -281,7 +282,7 @@ class TonlibCli : public td::actor::Actor { info.public_key = key->public_key_; info.secret = std::move(key->secret_); keys_.push_back(std::move(info)); - export_key(info.public_key, keys_.size() - 1, std::move(password)); + //export_key(key->public_key_, keys_.size() - 1, std::move(password)); store_keys(); }); } @@ -388,8 +389,11 @@ 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 = tonlib::TonlibClient::static_request(make_object( - make_object(keys_[r_key_i.ok()].public_key))); + auto obj = options_.use_simple_wallet + ? tonlib::TonlibClient::static_request(make_object( + make_object(keys_[r_key_i.ok()].public_key))) + : tonlib::TonlibClient::static_request(make_object( + make_object(keys_[r_key_i.ok()].public_key))); if (obj->get_id() != tonlib_api::error::ID) { Address res; res.address = ton::move_tl_object_as(obj); @@ -476,12 +480,19 @@ class TonlibCli : public td::actor::Actor { using tonlib_api::make_object; send_query(make_object(td::SecureString(password), td::SecureString(), make_object(std::move(words))), - [](auto r_res) { + [this, password = td::SecureString(password)](auto r_res) { if (r_res.is_error()) { td::TerminalIO::out() << "Can't import key " << r_res.error() << "\n"; return; } - td::TerminalIO::out() << to_string(r_res.ok()); + auto key = r_res.move_as_ok(); + LOG(ERROR) << to_string(key); + KeyInfo info; + info.public_key = key->public_key_; + info.secret = std::move(key->secret_); + keys_.push_back(std::move(info)); + export_key(key->public_key_, keys_.size() - 1, std::move(password)); + store_keys(); }); } @@ -618,7 +629,7 @@ class TonlibCli : public td::actor::Actor { std::move(to.address), grams, message.str()), [](auto r_res) { if (r_res.is_error()) { - td::TerminalIO::out() << "Can't get state: " << r_res.error() << "\n"; + td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n"; return; } td::TerminalIO::out() << to_string(r_res.ok()); @@ -648,16 +659,29 @@ 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; - send_query(make_object(make_object( - make_object(keys_[key_i].public_key, keys_[key_i].secret.copy()), - td::SecureString(password))), - [key = std::move(key)](auto r_res) { - if (r_res.is_error()) { - td::TerminalIO::out() << "Can't init wallet with key: [" << key << "] " << r_res.error() << "\n"; - return; - } - td::TerminalIO::out() << to_string(r_res.ok()); - }); + if (options_.use_simple_wallet) { + send_query(make_object(make_object( + make_object(keys_[key_i].public_key, keys_[key_i].secret.copy()), + td::SecureString(password))), + [key = std::move(key)](auto r_res) { + if (r_res.is_error()) { + td::TerminalIO::out() << "Can't init wallet with key: [" << key << "] " << r_res.error() << "\n"; + return; + } + td::TerminalIO::out() << to_string(r_res.ok()); + }); + } else { + send_query(make_object(make_object( + make_object(keys_[key_i].public_key, keys_[key_i].secret.copy()), + td::SecureString(password))), + [key = std::move(key)](auto r_res) { + if (r_res.is_error()) { + td::TerminalIO::out() << "Can't init wallet with key: [" << key << "] " << r_res.error() << "\n"; + return; + } + td::TerminalIO::out() << to_string(r_res.ok()); + }); + } } void get_hints(td::Slice prefix) { @@ -705,10 +729,14 @@ int main(int argc, char* argv[]) { options.config = std::move(data); return td::Status::OK(); }); - p.add_option('c', "use_callbacks_for_network (for debug)", "do not use this", [&]() { + p.add_option('c', "use-callbacks-for-network", "do not use this", [&]() { 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; + return td::Status::OK(); + }); auto S = p.run(argc, argv); if (S.is_error()) {