Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2019-09-27 08:54:49 +03:00
commit a8628602dd
84 changed files with 4958 additions and 1047 deletions

View file

@ -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 %@";
"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 %@";

View file

@ -58,7 +58,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, source: ChatC
})))
items.append(.separator)
case .recentSearch:
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
let _ = (removeRecentlySearchedPeer(postbox: context.account.postbox, peerId: peerId)
|> deliverOnMainQueue).start(completed: {
f(.default)

View file

@ -1232,7 +1232,14 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
}
}
case let .controller(controller):
break
let controllerPoint = self.view.convert(point, to: controller.controller.view)
if let result = controller.controller.view.hitTest(controllerPoint, with: event) {
if result is UIScrollView {
return result
} else if result is ListViewBackingView {
return result
}
}
}
}

View file

@ -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()
}
}

View file

@ -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))
}
}
}

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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()
}
})
}
}
}

View file

@ -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 {

View file

@ -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;

View file

@ -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];
}

View file

@ -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)

View file

@ -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<NSString *> *)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

View file

@ -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<MTDisposable>(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<tonlib_api::testWallet_getAccountAddress>(
make_object<tonlib_api::testWallet_initialAccountState>(
auto query = make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(
makeString(publicKeyData)
)
);
@ -389,89 +389,6 @@ typedef enum {
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
- (MTSignal *)getTestGiverAccountState {
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
_requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else if (object->get_id() == tonlib_api::testGiver_accountState::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::testGiver_accountState>(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<tonlib_api::testGiver_getAccountState>();
_client->send({ requestId, std::move(query) });
return [[MTBlockDisposable alloc] initWithBlock:^{
}];
}] startOn:[MTQueue mainQueue]] deliverOn:[MTQueue mainQueue]];
}
- (MTSignal *)getTestGiverAddress {
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
_requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else if (object->get_id() == tonlib_api::accountAddress::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::accountAddress>(object);
[subscriber putNext:[[NSString alloc] initWithUTF8String:result->account_address_.c_str()]];
[subscriber putCompletion];
} else {
assert(false);
}
}];
auto query = make_object<tonlib_api::testGiver_getAccountAddress>();
_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<MTDisposable>(MTSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
_requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else {
[subscriber putCompletion];
}
}];
auto query = make_object<tonlib_api::testGiver_sendGrams>(make_object<tonlib_api::accountAddress>(
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<MTDisposable>(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<tonlib_api::generic_accountStateTestWallet>(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<tonlib_api::generic_accountStateTestGiver>(object);
} else if (object->get_id() == tonlib_api::generic_accountStateWallet::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateWallet>(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<MTDisposable>(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<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else {
[subscriber putCompletion];
}
}];
auto query = make_object<tonlib_api::testWallet_init>(
make_object<tonlib_api::inputKey>(
make_object<tonlib_api::key>(
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<NSString *> *)wordList {
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(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<MTDisposable>(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<tonlib_api::deleteKey>(
makeString(publicKeyData)
make_object<tonlib_api::key>(
makeString(publicKeyData),
makeSecureString(key.secret)
)
);
_client->send({ requestId, std::move(query) });

View file

@ -67,8 +67,6 @@ private enum DebugControllerEntry: ItemListNodeEntry {
case resetDatabase(PresentationTheme)
case resetHoles(PresentationTheme)
case resetBiometricsData(PresentationTheme)
case openDebugWallet(PresentationTheme)
case getGrams(PresentationTheme)
case optimizeDatabase(PresentationTheme)
case photoPreview(PresentationTheme, Bool)
case knockoutWallpaper(PresentationTheme, Bool)
@ -86,7 +84,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return DebugControllerSection.logging.rawValue
case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries:
return DebugControllerSection.experiments.rawValue
case .clearTips, .reimport, .resetData, .resetDatabase, .resetHoles, .resetBiometricsData, .openDebugWallet, .getGrams, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .gradientBubbles:
case .clearTips, .reimport, .resetData, .resetDatabase, .resetHoles, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .gradientBubbles:
return DebugControllerSection.experiments.rawValue
case .hostInfo, .versionInfo:
return DebugControllerSection.info.rawValue
@ -131,10 +129,6 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return 16
case .resetBiometricsData:
return 17
case .openDebugWallet:
return 18
case .getGrams:
return 19
case .optimizeDatabase:
return 20
case .photoPreview:
@ -474,47 +468,6 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return settings.withUpdatedBiometricsDomainState(nil).withUpdatedShareBiometricsDomainState(nil)
}).start()
})
case let .openDebugWallet(theme):
return ItemListActionItem(theme: theme, title: "Delete Wallets", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
guard let context = arguments.context else {
return
}
let _ = debugDeleteWallets(postbox: context.account.postbox).start()
return
let _ = (availableWallets(postbox: context.account.postbox)
|> 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))

View file

@ -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<String, NoError> {
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<TONAccountState, NoError> {
private func getWalletStateRaw(address: String) -> Signal<TONAccountState, GetWalletStateError> {
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<TONAccountState?, NoError> {
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<Never, SendGramsFromWalletError> {
return keychain.decrypt(walletInfo.encryptedSecret)
|> mapError { _ -> SendGramsFromWalletError in
return .secretDecryptionFailed
}
}
fileprivate func getGramsFromTestGiver(address: String, amount: Int64) -> Signal<Void, GetGramsFromTestGiverError> {
return self.getTestGiverAccountState()
|> castError(GetGramsFromTestGiverError.self)
|> mapToSignal { state in
guard let state = state else {
return .fail(.generic)
}
|> mapToSignal { decryptedSecret -> Signal<Never, SendGramsFromWalletError> 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<Never, MakeWalletInitializedError> {
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<Never, MakeWalletInitializedError> {
return self.getWalletStateRaw(address: address)
|> castError(MakeWalletInitializedError.self)
|> mapToSignal { state -> Signal<Never, MakeWalletInitializedError> in
if state.isInitialized {
return .complete()
} else {
let poll: Signal<Void, MakeWalletInitializedError> = self.getWalletStateRaw(address: address)
|> castError(MakeWalletInitializedError.self)
|> mapToSignal { state -> Signal<Void, MakeWalletInitializedError> 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<Never, SendGramsFromWalletError> {
return keychain.decrypt(walletInfo.encryptedSecret)
|> mapError { _ -> SendGramsFromWalletError in
return .secretDecryptionFailed
}
|> mapToSignal { decryptedSecret -> Signal<Never, SendGramsFromWalletError> 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<Never, SendGramsFromWalletError> { 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<Never, DeleteLocalWalletDataError> {
return keychain.decrypt(walletInfo.encryptedSecret)
|> mapError { _ -> DeleteLocalWalletDataError in
return .secretDecryptionFailed
}
|> mapToSignal { decryptedSecret -> Signal<Never, DeleteLocalWalletDataError> 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<Never, NoError> {
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<Never, DeleteLocalWalletDataError> {
return getServerWalletSalt(network: network)
|> mapError { _ -> DeleteLocalWalletDataError in
return .generic
}
|> mapToSignal { serverSalt -> Signal<Never, DeleteLocalWalletDataError> 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<String, NoError> {
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<CombinedWalletStateResult, GetCombinedWalletStateError> in
return getWalletState(address: address, tonInstance: tonInstance)
|> castError(GetCombinedWalletStateError.self)
|> mapError { _ -> GetCombinedWalletStateError in
return .generic
}
|> mapToSignal { walletState, syncUtime -> Signal<CombinedWalletStateResult, GetCombinedWalletStateError> 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<Void, GetGramsFromTestGiverError> {
return tonInstance.getGramsFromTestGiver(address: address, amount: amount)
}
public enum SendGramsFromWalletError {
case generic
case secretDecryptionFailed

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "􀊯 2.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -656,13 +656,13 @@ final class SharedApplicationContext {
return .single(Data())
}, encrypt: { data in
return Signal { subscriber in
subscriber.putNext(data)
subscriber.putNext(TonKeychainEncryptedData(publicKey: Data(), data: data))
subscriber.putCompletion()
return EmptyDisposable
}
}, decrypt: { data in
return Signal { subscriber in
subscriber.putNext(data)
subscriber.putNext(data.data)
subscriber.putCompletion()
return EmptyDisposable
}

View file

@ -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
}
@ -1901,6 +1901,15 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
return self.navigationBar?.view
}
switch self.chatPresentationInterfaceState.mode {
case .standard(previewing: true):
if self.bounds.contains(point) {
return self.historyNode.view
}
default:
break
}
return nil
}

View file

@ -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<Void, NoError>?, (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)
@ -147,7 +148,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)

View file

@ -8,62 +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
}
}
}
import AnimationUI
public final class WalletInfoScreen: ViewController {
private let context: AccountContext
@ -132,6 +80,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,82 +100,110 @@ public final class WalletInfoScreen: ViewController {
}
private final class WalletInfoBalanceNode: ASDisplayNode {
let balanceTextNode: ImmediateTextNode
let balanceIconNode: ASImageNode
let balanceIntegralTextNode: ImmediateTextNode
let balanceFractionalTextNode: ImmediateTextNode
let balanceIconNode: AnimatedStickerNode
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[..<range.lowerBound])
let fractionalPart = String(self.balance[range.lowerBound...])
integralString.append(NSAttributedString(string: integralPart, font: Font.medium(48.0), textColor: .white))
fractionalString.append(NSAttributedString(string: fractionalPart, font: Font.medium(48.0), textColor: .white))
} else {
integralString.append(NSAttributedString(string: self.balance, font: Font.medium(48.0), textColor: .white))
}
self.balanceIntegralTextNode.attributedText = integralString
self.balanceFractionalTextNode.attributedText = fractionalString
}
}
var isLoading: Bool = true
init(theme: PresentationTheme) {
self.balanceTextNode = ImmediateTextNode()
self.balanceTextNode.displaysAsynchronously = false
self.balanceTextNode.attributedText = NSAttributedString(string: " ", font: Font.bold(39.0), textColor: .white)
self.balanceTextNode.layer.minificationFilter = .linear
init(account: Account, theme: PresentationTheme) {
self.balanceIntegralTextNode = ImmediateTextNode()
self.balanceIntegralTextNode.displaysAsynchronously = false
self.balanceIntegralTextNode.attributedText = NSAttributedString(string: " ", font: Font.bold(39.0), textColor: .white)
self.balanceIntegralTextNode.layer.minificationFilter = .linear
self.balanceIconNode = ASImageNode()
self.balanceIconNode.displaysAsynchronously = false
self.balanceIconNode.displayWithoutProcessing = true
self.balanceIconNode.image = UIImage(bundleImageName: "Wallet/BalanceGem")?.precomposed()
self.balanceFractionalTextNode = ImmediateTextNode()
self.balanceFractionalTextNode.displaysAsynchronously = false
self.balanceFractionalTextNode.attributedText = NSAttributedString(string: " ", font: Font.bold(39.0), textColor: .white)
self.balanceFractionalTextNode.layer.minificationFilter = .linear
self.balanceIconNode = AnimatedStickerNode()
if let path = getAppBundle().path(forResource: "WalletIntroStatic", ofType: "tgs") {
self.balanceIconNode.setup(account: account, resource: .localFile(path), width: 120, height: 120, mode: .direct)
self.balanceIconNode.visibility = true
}
super.init()
self.addSubnode(self.balanceTextNode)
self.addSubnode(self.balanceIntegralTextNode)
self.addSubnode(self.balanceFractionalTextNode)
self.addSubnode(self.balanceIconNode)
}
func update(width: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
func update(width: CGFloat, scaleTransition: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
let sideInset: CGFloat = 16.0
let balanceIconSpacing: CGFloat = 8.0
let balanceIconSpacing: CGFloat = scaleTransition * 0.0 + (1.0 - scaleTransition) * (-12.0)
let balanceVerticalIconOffset: CGFloat = scaleTransition * (-6.0) + (1.0 - scaleTransition) * (-2.0)
let balanceTextSize = self.balanceTextNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: 200.0))
let balanceIconSize = self.balanceIconNode.image?.size ?? CGSize(width: 38.0, height: 34.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 = CGSize(width: 60.0, height: 60.0)
let balanceOrigin = CGPoint(x: floor((width - balanceTextSize.width - balanceIconSpacing - balanceIconSize.width / 2.0) / 2.0), y: 0.0)
let integralScale: CGFloat = scaleTransition * 1.0 + (1.0 - scaleTransition) * 0.8
let fractionalScale: CGFloat = scaleTransition * 0.5 + (1.0 - scaleTransition) * 0.8
let balanceOrigin = CGPoint(x: floor((width - balanceIntegralTextSize.width * integralScale - balanceFractionalTextSize.width * fractionalScale - balanceIconSpacing - balanceIconSize.width / 2.0) / 2.0), y: 0.0)
let balanceIntegralTextFrame = CGRect(origin: balanceOrigin, size: balanceIntegralTextSize)
let apparentBalanceIntegralTextFrame = CGRect(origin: balanceIntegralTextFrame.origin, size: CGSize(width: balanceIntegralTextFrame.width * integralScale, height: balanceIntegralTextFrame.height * integralScale))
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 / 4.0) * scaleTransition + 0.25 * (balanceFractionalTextFrame.width / 2.0) * (1.0 - scaleTransition)
balanceFractionalTextFrame.origin.y += balanceFractionalTextFrame.height * 0.5 * (0.8 - fractionalScale)
let balanceTextFrame = CGRect(origin: balanceOrigin, size: balanceTextSize)
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)
transition.updateFrame(node: self.balanceIconNode, frame: balanceIconFrame)
balanceIconFrame = CGRect(origin: CGPoint(x: apparentBalanceFractionalTextFrame.maxX + balanceIconSpacing * integralScale, y: balanceIntegralTextFrame.midY - balanceIconSize.height / 2.0 + balanceVerticalIconOffset), size: balanceIconSize)
return balanceTextSize.height
transition.updateFrameAsPositionAndBounds(node: self.balanceIntegralTextNode, frame: balanceIntegralTextFrame)
transition.updateTransformScale(node: self.balanceIntegralTextNode, scale: integralScale)
transition.updateFrameAsPositionAndBounds(node: self.balanceFractionalTextNode, frame: balanceFractionalTextFrame)
transition.updateTransformScale(node: self.balanceFractionalTextNode, scale: fractionalScale)
self.balanceIconNode.updateLayout(size: balanceIconFrame.size)
transition.updateFrameAsPositionAndBounds(node: self.balanceIconNode, frame: balanceIconFrame)
transition.updateTransformScale(node: self.balanceIconNode, scale: scaleTransition * 1.0 + (1.0 - scaleTransition) * 0.8)
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(account: account, 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 +218,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 +227,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 +259,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,43 +272,31 @@ 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.1))
}
let balanceFrame = CGRect(origin: CGPoint(x: 0.0, y: headerY), size: balanceSize)
transition.updateFrame(node: self.balanceNode, frame: balanceFrame)
transition.updateSublayerTransformScale(node: self.balanceNode, scale: headerScale)
let balanceSubtitleFrame = CGRect(origin: CGPoint(x: floor((size.width - balanceSubtitleSize.width) / 2.0), y: balanceFrame.midY + (balanceFrame.height / 2.0 * headerScale) + balanceSubtitleSpacing), size: balanceSubtitleSize)
let balanceSubtitleOffset = headerScaleTransition * 27.0 + (1.0 - headerScaleTransition) * 9.0
let balanceSubtitleFrame = CGRect(origin: CGPoint(x: floor((size.width - balanceSubtitleSize.width) / 2.0), y: balanceFrame.midY + balanceSubtitleOffset), 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 +324,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 +354,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 +403,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 +415,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 +433,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 +463,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 = UIColor(white: 0.0, alpha: 0.3)
@ -521,7 +483,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 +510,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 +556,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 +641,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 +651,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 +678,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 +712,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 +816,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
}

View file

@ -106,7 +106,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()
@ -222,7 +221,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[..<range.lowerBound])
let fractionalPart = String(title[range.lowerBound...])
titleString.append(NSAttributedString(string: integralPart, font: Font.bold(17.0), textColor: titleColor))
titleString.append(NSAttributedString(string: fractionalPart, font: Font.regular(14.0), textColor: titleColor))
} else {
titleString.append(NSAttributedString(string: title, font: Font.bold(17.0), textColor: titleColor))
}
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, 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 (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: textFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@ -235,8 +244,8 @@ class WalletInfoTransactionItemNode: ListViewItemNode {
let itemBackgroundColor: UIColor
let itemSeparatorColor: UIColor
itemBackgroundColor = item.theme.list.plainBackgroundColor
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
let topInset: CGFloat = 11.0
let bottomInset: CGFloat = 11.0
@ -458,7 +467,7 @@ final class WalletInfoTransactionDateHeaderNode: ListViewItemHeaderNode {
self.backgroundNode = ASDisplayNode()
self.backgroundNode.isLayerBacked = true
self.backgroundNode.backgroundColor = theme.list.plainBackgroundColor.withAlphaComponent(0.9)
self.backgroundNode.backgroundColor = theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.9)
self.titleNode = ASTextNode()
self.titleNode.isUserInteractionEnabled = false

View file

@ -35,6 +35,7 @@ public final class WalletPasscodeScreen: 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

View file

@ -0,0 +1,210 @@
import Foundation
import UIKit
import Display
import AsyncDisplayKit
import TelegramPresentationData
import AppBundle
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
}
}
}
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)
}
}

View file

@ -96,7 +96,7 @@ public func walletSettingsController(context: AccountContext, tonContext: TonCon
let arguments = WalletSettingsControllerArguments(exportWallet: {
let _ = (walletRestoreWords(network: context.account.network, walletInfo: walletInfo, tonInstance: tonContext.instance, keychain: tonContext.keychain)
|> deliverOnMainQueue).start(next: { wordList in
pushControllerImpl?(WalletWordDisplayScreen(context: context, tonContext: tonContext, walletInfo: walletInfo, wordList: wordList))
pushControllerImpl?(WalletWordDisplayScreen(context: context, tonContext: tonContext, walletInfo: walletInfo, wordList: wordList, mode: .export))
})
}, deleteWallet: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -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: [

View file

@ -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
@ -94,9 +95,9 @@ public final class WalletSplashScreen: ViewController {
navigationController.setViewControllers(controllers, animated: true)
}
})
case .sent:
case .sent, .created:
self.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: ASDisplayNode())!, animated: false)
case .created, .success, .restoreFailed, .secureStorageNotAvailable, .secureStorageReset:
case .success, .restoreFailed, .secureStorageNotAvailable, .secureStorageReset:
break
}
@ -142,7 +143,7 @@ public final class WalletSplashScreen: ViewController {
], actionLayout: .vertical), in: .window(.root))
})
case let .created(walletInfo, wordList):
strongSelf.push(WalletWordDisplayScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: walletInfo, wordList: wordList))
strongSelf.push(WalletWordDisplayScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: walletInfo, wordList: wordList, mode: .check))
case let .success(walletInfo), let .sent(walletInfo, _):
let _ = (walletAddress(publicKey: walletInfo.publicKey, tonInstance: strongSelf.tonContext.instance)
|> deliverOnMainQueue).start(next: { address in
@ -244,7 +245,9 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
private let secondaryAction: () -> Void
private let iconNode: ASImageNode
private var animationSize: CGSize = CGSize()
private let animationNode: AnimatedStickerNode
private let alternativeAnimationNode: AnimatedStickerNode
private let titleNode: ImmediateTextNode
private let textNode: ImmediateTextNode
private let buttonNode: SolidRoundedButtonNode
@ -269,6 +272,7 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
self.iconNode.displaysAsynchronously = false
self.animationNode = AnimatedStickerNode()
self.alternativeAnimationNode = AnimatedStickerNode()
let title: String
let text: NSAttributedString
@ -287,14 +291,24 @@ 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: "WalletIntroLoading", ofType: "tgs") {
self.animationNode.setup(account: account, resource: .localFile(path), width: 248, height: 248, mode: .direct)
self.animationSize = CGSize(width: 124.0, height: 124.0)
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: 250, height: 250, playbackMode: .once, mode: .direct)
self.animationSize = CGSize(width: 125.0, height: 125.0)
self.animationNode.visibility = true
}
secondaryActionText = ""
case .success:
title = "Ready to go!"
@ -303,7 +317,8 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
termsText = NSAttributedString(string: "")
self.iconNode.image = nil
if let path = getAppBundle().path(forResource: "celebrate", ofType: "tgs") {
self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct)
self.animationNode.setup(account: account, resource: .localFile(path), width: 260, height: 260, playbackMode: .once, mode: .direct)
self.animationSize = CGSize(width: 130.0, height: 130.0)
self.animationNode.visibility = true
}
secondaryActionText = ""
@ -314,7 +329,8 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
termsText = NSAttributedString(string: "")
self.iconNode.image = nil
if let path = getAppBundle().path(forResource: "sad", ofType: "tgs") {
self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct)
self.animationNode.setup(account: account, resource: .localFile(path), width: 260, height: 260, playbackMode: .once, mode: .direct)
self.animationSize = CGSize(width: 130.0, height: 130.0)
self.animationNode.visibility = true
}
secondaryActionText = "Enter 24 words"
@ -323,7 +339,12 @@ 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: 260, height: 260, mode: .direct)
self.animationSize = CGSize(width: 130.0, height: 130.0)
self.animationNode.visibility = true
}
secondaryActionText = ""
case let .sent(_, amount):
title = "Done!"
@ -334,7 +355,8 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
termsText = NSAttributedString(string: "")
self.iconNode.image = nil
if let path = getAppBundle().path(forResource: "celebrate", ofType: "tgs") {
self.animationNode.setup(account: account, resource: .localFile(path), width: 280, height: 280, mode: .direct)
self.animationNode.setup(account: account, resource: .localFile(path), width: 260, height: 260, playbackMode: .once, mode: .direct)
self.animationSize = CGSize(width: 130.0, height: 130.0)
self.animationNode.visibility = true
}
secondaryActionText = ""
@ -392,7 +414,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()
@ -442,6 +464,17 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
}
}
override func didLoad() {
super.didLoad()
switch self.mode {
case .created, .sending, .sent:
self.view.disablesInteractiveTransitionGestureRecognizer = true
default:
break
}
}
@objc private func secondaryActionPressed() {
self.secondaryAction()
}
@ -449,19 +482,18 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
let sideInset: CGFloat = 32.0
let buttonSideInset: CGFloat = 48.0
let iconSpacing: CGFloat = 5.0
let iconSpacing: CGFloat = 8.0
let titleSpacing: CGFloat = 19.0
let termsSpacing: CGFloat = 11.0
let buttonHeight: CGFloat = 50.0
let iconSize: CGSize
let iconSize: CGSize = self.animationSize
var iconOffset = CGPoint()
switch self.mode {
case .success:
iconSize = CGSize(width: 140.0, height: 140.0)
iconOffset.x = 10.0
default:
iconSize = self.iconNode.image?.size ?? CGSize(width: 140.0, height: 140.0)
break
}
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))

View file

@ -94,7 +94,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()
@ -388,20 +388,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[..<range.lowerBound])
let fractionalPart = String(balanceString[range.lowerBound...])
title.append(NSAttributedString(string: integralPart, font: Font.bold(48.0), textColor: titleColor))
title.append(NSAttributedString(string: fractionalPart, font: Font.bold(24.0), textColor: titleColor))
} else {
title.append(NSAttributedString(string: balanceString, font: Font.bold(48.0), textColor: titleColor))
}
let subtitle: String = stringForFullDate(timestamp: Int32(clamping: item.walletTransaction.timestamp), strings: item.strings, dateTimeFormat: item.dateTimeFormat)
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: title, font: Font.semibold(39.0), textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: title, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: subtitle, font: Font.regular(13.0), textColor: item.theme.list.freeTextColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))

View file

@ -12,6 +12,7 @@ import UndoUI
import AlertUI
import SwiftSignalKit
import TextFormat
import AnimationUI
private let possibleWordList: [String] = [
"abandon",
@ -2091,6 +2092,7 @@ public final class WalletWordCheckScreen: 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
@ -2107,7 +2109,7 @@ public final class WalletWordCheckScreen: ViewController {
}
override public func loadDisplayNode() {
self.displayNode = WalletWordCheckScreenNode(presentationData: self.presentationData, mode: self.mode, possibleWordList: possibleWordList, action: { [weak self] in
self.displayNode = WalletWordCheckScreenNode(account: self.context.account, presentationData: self.presentationData, mode: self.mode, possibleWordList: possibleWordList, action: { [weak self] in
guard let strongSelf = self else {
return
}
@ -2241,7 +2243,7 @@ private func generateClearIcon(color: UIColor) -> UIImage? {
}
private final class WordCheckInputNode: ASDisplayNode, UITextFieldDelegate {
private let next: (WordCheckInputNode) -> Void
private let next: (WordCheckInputNode, Bool) -> Void
private let focused: (WordCheckInputNode) -> Void
private let pasteWords: ([String]) -> Void
@ -2261,7 +2263,7 @@ private final class WordCheckInputNode: ASDisplayNode, UITextFieldDelegate {
}
}
init(theme: PresentationTheme, index: Int, possibleWordList: [String], next: @escaping (WordCheckInputNode) -> Void, isLast: Bool, focused: @escaping (WordCheckInputNode) -> Void, pasteWords: @escaping ([String]) -> Void) {
init(theme: PresentationTheme, index: Int, possibleWordList: [String], next: @escaping (WordCheckInputNode, Bool) -> Void, isLast: Bool, focused: @escaping (WordCheckInputNode) -> Void, pasteWords: @escaping ([String]) -> Void) {
self.next = next
self.focused = focused
self.pasteWords = pasteWords
@ -2320,6 +2322,7 @@ private final class WordCheckInputNode: ASDisplayNode, UITextFieldDelegate {
return
}
strongSelf.inputNode.textField.text = word
strongSelf.next(strongSelf, false)
}
}
@ -2337,7 +2340,7 @@ private final class WordCheckInputNode: ASDisplayNode, UITextFieldDelegate {
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.next(self)
self.next(self, true)
return false
}
@ -2478,16 +2481,18 @@ private final class WordCheckInputAccesssoryView: UIInputView {
func updateText(_ text: String) {
var words: [String] = []
if !self.currentText.isEmpty && text.hasPrefix(self.currentText) {
for word in self.wordList {
if word.hasPrefix(text) {
words.append(word)
if !text.isEmpty {
if !self.currentText.isEmpty && text.hasPrefix(self.currentText) {
for wordView in self.wordViews {
if wordView.string.hasPrefix(text) {
words.append(wordView.string)
}
}
}
} else {
for wordView in self.wordViews {
if wordView.string.hasPrefix(text) {
words.append(wordView.string)
} else {
for word in self.wordList {
if word.hasPrefix(text) {
words.append(word)
}
}
}
}
@ -2550,7 +2555,7 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro
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 secondaryActionTitleNode: ImmediateTextNode
@ -2564,7 +2569,7 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro
return self.inputNodes.map { $0.text }
}
init(presentationData: PresentationData, mode: WalletWordCheckMode, possibleWordList: [String], action: @escaping () -> 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
@ -2579,9 +2584,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
@ -2601,14 +2604,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: 238, height: 238, playbackMode: .once, 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()
@ -2639,13 +2644,13 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro
var inputNodes: [WordCheckInputNode] = []
var nextWord: ((WordCheckInputNode) -> Void)?
var nextWord: ((WordCheckInputNode, Bool) -> Void)?
var focused: ((WordCheckInputNode) -> Void)?
var pasteWords: (([String]) -> Void)?
for i in 0 ..< wordIndices.count {
inputNodes.append(WordCheckInputNode(theme: presentationData.theme, index: wordIndices[i], possibleWordList: possibleWordList, next: { node in
nextWord?(node)
inputNodes.append(WordCheckInputNode(theme: presentationData.theme, index: wordIndices[i], possibleWordList: possibleWordList, next: { node, done in
nextWord?(node, done)
}, isLast: i == wordIndices.count - 1, focused: { node in
focused?(node)
}, pasteWords: { wordList in
@ -2663,7 +2668,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)
@ -2697,12 +2702,16 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro
self.secondaryActionButtonNode.addTarget(self, action: #selector(self.secondaryActionPressed), forControlEvents: .touchUpInside)
nextWord = { [weak self] node in
nextWord = { [weak self] node, done in
guard let strongSelf = self else {
return
}
if node === strongSelf.inputNodes.last {
action()
if done {
action()
} else {
strongSelf.scrollNode.view.scrollRectToVisible(strongSelf.buttonNode.frame.insetBy(dx: 0.0, dy: -20.0), animated: true)
}
} else {
if let index = strongSelf.inputNodes.firstIndex(where: { $0 === node }) {
strongSelf.inputNodes[index + 1].focus()
@ -2770,7 +2779,7 @@ private final class WalletWordCheckScreenNode: ViewControllerTracingNode, UIScro
let sideInset: CGFloat = 32.0
let buttonSideInset: CGFloat = 48.0
let iconSpacing: CGFloat = 5.0
let iconSpacing: CGFloat = 9.0
let titleSpacing: CGFloat = 19.0
let textSpacing: CGFloat = 30.0
let buttonHeight: CGFloat = 50.0
@ -2782,7 +2791,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: 119.0, height: 119.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))
@ -2796,7 +2812,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)

View file

@ -11,6 +11,12 @@ import TelegramCore
import SolidRoundedButtonNode
import UndoUI
import AlertUI
import AnimationUI
public enum WalletWordDisplayScreenMode {
case check
case export
}
public final class WalletWordDisplayScreen: ViewController {
private let context: AccountContext
@ -18,15 +24,17 @@ public final class WalletWordDisplayScreen: ViewController {
private var presentationData: PresentationData
private let walletInfo: WalletInfo
private let wordList: [String]
private let mode: WalletWordDisplayScreenMode
private let startTime: Double
private let idleTimerExtensionDisposable: Disposable
public init(context: AccountContext, tonContext: TonContext, walletInfo: WalletInfo, wordList: [String]) {
public init(context: AccountContext, tonContext: TonContext, walletInfo: WalletInfo, wordList: [String], mode: WalletWordDisplayScreenMode) {
self.context = context
self.tonContext = tonContext
self.walletInfo = walletInfo
self.wordList = wordList
self.mode = mode
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -38,6 +46,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
@ -58,10 +67,16 @@ 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
}
if case .export = strongSelf.mode {
strongSelf.dismiss()
return
}
let deltaTime = Date().timeIntervalSince1970 - strongSelf.startTime
let minimalTimeout: Double
#if DEBUG
@ -110,7 +125,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)]
@ -118,7 +133,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
@ -131,16 +146,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: 264, height: 264, playbackMode: .once, 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)
@ -194,7 +209,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)
@ -251,7 +266,7 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc
let sideInset: CGFloat = 32.0
let buttonSideInset: CGFloat = 48.0
let iconSpacing: CGFloat = 5.0
let iconSpacing: CGFloat = 18.0
let titleSpacing: CGFloat = 19.0
let textSpacing: CGFloat = 37.0
let buttonHeight: CGFloat = 50.0
@ -264,7 +279,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: 132.0, height: 132.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))
@ -274,8 +290,8 @@ 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)
let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0) + 12.0, y: contentVerticalOrigin), size: iconSize)
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)

View file

@ -956,6 +956,17 @@
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
</dict>
<key>1DD70E293117BD4900000000</key>
<dict>
<key>isa</key>
<string>PBXFileReference</string>
<key>name</key>
<string>WalletRefreshNode.swift</string>
<key>path</key>
<string>Sources/WalletRefreshNode.swift</string>
<key>sourceTree</key>
<string>SOURCE_ROOT</string>
</dict>
<key>1DD70E2948FA33F200000000</key>
<dict>
<key>isa</key>
@ -1052,6 +1063,7 @@
<string>1DD70E29DE28A96800000000</string>
<string>1DD70E298815219000000000</string>
<string>1DD70E2979DDEBBB00000000</string>
<string>1DD70E293117BD4900000000</string>
<string>1DD70E2948FA33F200000000</string>
<string>1DD70E2986544B8D00000000</string>
<string>1DD70E2964068E1100000000</string>
@ -1154,6 +1166,13 @@
<key>fileRef</key>
<string>1DD70E2979DDEBBB00000000</string>
</dict>
<key>E7A30F043117BD4900000000</key>
<dict>
<key>isa</key>
<string>PBXBuildFile</string>
<key>fileRef</key>
<string>1DD70E293117BD4900000000</string>
</dict>
<key>E7A30F0448FA33F200000000</key>
<dict>
<key>isa</key>
@ -1218,6 +1237,7 @@
<string>E7A30F04DE28A96800000000</string>
<string>E7A30F048815219000000000</string>
<string>E7A30F0479DDEBBB00000000</string>
<string>E7A30F043117BD4900000000</string>
<string>E7A30F0448FA33F200000000</string>
<string>E7A30F0486544B8D00000000</string>
<string>E7A30F0464068E1100000000</string>

View file

@ -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

View file

@ -32,7 +32,7 @@ namespace block {
using namespace std::literals::string_literals;
td::Status check_block_header_proof(td::Ref<vm::Cell> 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<vm::Cell> 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<vm::Cell> root, ton::LogicalTime* last_trans_lt, ton::Bits256* last_trans_hash) {
td::Ref<vm::Cell> 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::Info> 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;

View file

@ -25,11 +25,12 @@ namespace block {
using td::Ref;
td::Status check_block_header_proof(td::Ref<vm::Cell> 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<vm::Cell> 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<td::Bits256> check_state_proof(ton::BlockIdExt blkid, td::Slice proof);
td::Result<Ref<vm::Cell>> check_extract_state_proof(ton::BlockIdExt blkid, td::Slice proof, td::Slice data);
@ -47,6 +48,7 @@ struct AccountState {
td::Ref<vm::Cell> root;
ton::LogicalTime last_trans_lt = 0;
ton::Bits256 last_trans_hash;
td::uint32 gen_utime{0};
};
td::Result<Info> validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const;

View file

@ -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;

View file

@ -20,6 +20,7 @@
#include <iostream>
#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<FileLoader> file_loader) : file_loader_(std::move(file_loader)) {
explicit SourceLookup(std::unique_ptr<FileLoader> file_loader, std::unique_ptr<OsTime> os_time = {})
: file_loader_(std::move(file_loader)), os_time_(std::move(os_time)) {
}
void set_os_time(std::unique_ptr<OsTime> os_time) {
os_time_ = std::move(os_time);
}
void add_include_path(td::string path);
td::Result<FileLoader::File> 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::uint32>(td::Time::now());
}
protected:
std::unique_ptr<FileLoader> file_loader_;
std::unique_ptr<OsTime> os_time_;
std::vector<std::string> source_include_path_;
};
} // namespace fift

View file

@ -163,13 +163,15 @@ td::Result<fift::SourceLookup> 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<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir) {
td::Result<td::Ref<vm::Cell>> 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

View file

@ -31,5 +31,5 @@ td::Result<fift::SourceLookup> create_mem_source_lookup(std::string main, std::s
bool need_ton_util = true);
td::Result<FiftOutput> mem_run_fift(std::string source, std::vector<std::string> args = {}, std::string fift_dir = "");
td::Result<FiftOutput> mem_run_fift(SourceLookup source_lookup, std::vector<std::string> args);
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir = "");
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir = "", bool is_raw = true);
} // namespace fift

View file

@ -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);

View file

@ -0,0 +1,62 @@
#!/usr/bin/env fift -s
"TonUtil.fif" include
"Asm.fif" include
{ ."usage: " @' $0 type ." <workchain-id> [<filename-base>]" cr
."Creates a new advanced wallet in specified workchain, with private key saved to or loaded from <filename-base>.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
<b 0 32 u,
file-base +".pk" load-generate-keypair
constant wallet_pk
B,
b> // data
null // no libraries
<b b{0011} s, 3 roll ref, rot ref, swap dict, b> // create StateInit
dup ."StateInit: " <s csr. cr
dup hash wc swap 2dup 2constant wallet_addr
."new wallet address = " 2dup .addr cr
2dup file-base +".addr" save-address-verbose
."Non-bounceable address (for init): " 2dup 7 .Addr cr
."Bounceable address (for later access): " 6 .Addr cr
<b 0 32 u, -1 32 i, b>
dup ."signing message: " <s csr. cr
dup hash wallet_pk ed25519_sign_uint rot
<b b{1000100} s, wallet_addr addr, b{000010} s, swap <s s, b{0} s, swap B, swap <s s, b>
dup ."External message for initialization is " <s csr. cr
2 boc+>B dup Bx. cr
file-base +"-query.boc" tuck B>file
."(Saved wallet creating query to file " type .")" cr

View file

@ -24,7 +24,7 @@ dest_addr 2dup bounce 7 + .Addr ." = " .addr
// create a message (NB: 01b00.., b = bounce)
<b b{01} s, bounce 1 i, b{000100} s, dest_addr addr,
amount Gram, 0 9 64 32 + + 1+ 1+ u, "GIFT" $, b>
amount Gram, 0 9 64 32 + + 1+ 1+ u, 0 32 u, "GIFT" $, b>
<b seqno 32 u, 1 8 u, swap ref, b>
dup ."enveloping message: " <s csr. cr
<b b{1000100} s, giver_addr addr, 0 Gram, b{00} s,

View file

@ -8,7 +8,7 @@
var signature = in_msg~load_bits(512);
var cs = in_msg;
var (msg_seqno, valid_until) = (cs~load_uint(32), cs~load_uint(32));
throw_if(35, valid_until < now());
throw_if(35, valid_until <= now());
var ds = get_data().begin_parse();
var (stored_seqno, public_key) = (ds~load_uint(32), ds~load_uint(256));
ds.end_parse();

View file

@ -16,7 +16,7 @@ PROGRAM{
32 LDU // signature in_msg msg_seqno valid_until cs
NOW // signature in_msg msg_seqno valid_until cs _15
s1 s2 XCHG // signature in_msg msg_seqno cs valid_until _15
LESS // signature in_msg msg_seqno cs _16
LEQ // signature in_msg msg_seqno cs _16
35 THROWIF
c4 PUSH // signature in_msg msg_seqno cs _19
CTOS // signature in_msg msg_seqno cs ds

View file

@ -0,0 +1,48 @@
#!/usr/bin/env fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <filename-base> <dest-addr> <seqno> <amount> [-B <body-boc>] [<savefile>]" cr
."Creates a request to advanced wallet created by new-wallet-v2.fif, with private key loaded from file <filename-base>.pk "
."and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)" cr 1 halt
} : usage
def? $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 } { <b 0 32 u, "TESTv2" $, b> } 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 <s csr. cr
// create a message
<b b{01} s, bounce 1 i, b{000100} s, dest_addr addr, amount Gram, 0 9 64 32 + + 1+ u,
body-cell <s 2dup s-fits? not rot over 1 i, -rot { drop body-cell ref, } { s, } cond
b>
<b seqno 32 u, now timeout + 32 u, send-mode 8 u, swap ref, b>
dup ."signing message: " <s csr. cr
dup hash wallet_pk ed25519_sign_uint
<b b{1000100} s, wallet_addr addr, 0 Gram, b{00} s,
swap B, swap <s s, b>
dup ."resulting external message: " <s csr. cr
2 boc+>B dup Bx. cr
savefile +".boc" tuck B>file
."Query expires in " timeout . ."seconds" cr
."(Saved to file " type .")" cr

View file

@ -5,9 +5,9 @@
."Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file <filename-base>.pk "
."and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)" cr 1 halt
} : usage
$# 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 } { <b "TEST" $, b> } cond
def? body-boc-file { @' body-boc-file file>B B>boc } { <b 0 32 u, "TEST" $, b> } cond
constant body-cell
."Transferring " amount .GR ."to account "
@ -34,7 +35,7 @@ dest_addr 2dup bounce 7 + .Addr ." = " .addr
<b b{01} s, bounce 1 i, b{000100} s, dest_addr addr, amount Gram, 0 9 64 32 + + 1+ u,
body-cell <s 2dup s-fits? not rot over 1 i, -rot { drop body-cell ref, } { s, } cond
b>
<b seqno 32 u, 1 8 u, swap ref, b>
<b seqno 32 u, send-mode 8 u, swap ref, b>
dup ."signing message: " <s csr. cr
dup hash wallet_pk ed25519_sign_uint
<b b{1000100} s, wallet_addr addr, 0 Gram, b{00} s,

View file

@ -21,6 +21,7 @@
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/SharedSlice.h"
#include "td/utils/Slice.h"
#include "td/utils/StorerBase.h"
#include "td/utils/UInt.h"
@ -233,6 +234,12 @@ class TlStorerToString {
store_field_end();
}
void store_field(const char *name, const SecureString &value) {
store_field_begin(name);
result.append("<secret>");
store_field_end();
}
template <class T>
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("<secret>");
store_field_end();
}
template <class BytesT>
void store_bytes_field(const char *name, const BytesT &value) {
static const char *hex = "0123456789ABCDEF";

View file

@ -446,6 +446,8 @@ object_ptr<Object> 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> 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> 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> 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<object_ptr<tonNode_blockIdExt>> &&ids_, bool incomplete_)
: ids_(std::move(ids_))
, incomplete_(incomplete_)
{}
const std::int32_t tonNode_blocksDescription::ID;
object_ptr<tonNode_blocksDescription> tonNode_blocksDescription::fetch(td::TlParser &p) {
return make_object<tonNode_blocksDescription>(p);
}
tonNode_blocksDescription::tonNode_blocksDescription(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: ids_(TlFetchVector<TlFetchObject<tonNode_blockIdExt>>::parse(p))
, incomplete_(TlFetchBool::parse(p))
#undef FAIL
{}
void tonNode_blocksDescription::store(td::TlStorerCalcLength &s) const {
(void)sizeof(s);
TlStoreVector<TlStoreObject>::store(ids_, s);
TlStoreBool::store(incomplete_, s);
}
void tonNode_blocksDescription::store(td::TlStorerUnsafe &s) const {
(void)sizeof(s);
TlStoreVector<TlStoreObject>::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<object_ptr<tonNode_blockIdExt>> &v = ids_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(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> 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> tonNode_capabilities::fetch(td::TlParser &p) {
return make_object<tonNode_capabilities>(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> 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<tonNode_blockIdExt> &&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> tonNode_dataFull::fetch(td::TlParser &p) {
return make_object<tonNode_dataFull>(p);
}
tonNode_dataFull::tonNode_dataFull(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: id_(TlFetchObject<tonNode_blockIdExt>::parse(p))
, proof_(TlFetchBytes<td::BufferSlice>::parse(p))
, block_(TlFetchBytes<td::BufferSlice>::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_DataFull> tonNode_dataFullEmpty::fetch(td::TlParser &p) {
return make_object<tonNode_dataFullEmpty>(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<td::BufferSlice> &&data_)
: data_(std::move(data_))
{}
const std::int32_t tonNode_dataList::ID;
object_ptr<tonNode_dataList> tonNode_dataList::fetch(td::TlParser &p) {
return make_object<tonNode_dataList>(p);
}
tonNode_dataList::tonNode_dataList(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: data_(TlFetchVector<TlFetchBytes<td::BufferSlice>>::parse(p))
#undef FAIL
{}
void tonNode_dataList::store(td::TlStorerCalcLength &s) const {
(void)sizeof(s);
TlStoreVector<TlStoreString>::store(data_, s);
}
void tonNode_dataList::store(td::TlStorerUnsafe &s) const {
(void)sizeof(s);
TlStoreVector<TlStoreString>::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<td::BufferSlice> &v = data_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(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> tonNode_success::fetch(td::TlParser &p) {
return make_object<tonNode_success>(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<tonNode_blockIdExt> &&block_)
: block_(std::move(block_))
{}
const std::int32_t tonNode_downloadBlockFull::ID;
object_ptr<tonNode_downloadBlockFull> tonNode_downloadBlockFull::fetch(td::TlParser &p) {
return make_object<tonNode_downloadBlockFull>(p);
}
tonNode_downloadBlockFull::tonNode_downloadBlockFull(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: block_(TlFetchObject<tonNode_blockIdExt>::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<tonNode_DataFull>::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<object_ptr<tonNode_blockIdExt>> &&blocks_)
: blocks_(std::move(blocks_))
{}
const std::int32_t tonNode_downloadBlockProofLinks::ID;
object_ptr<tonNode_downloadBlockProofLinks> tonNode_downloadBlockProofLinks::fetch(td::TlParser &p) {
return make_object<tonNode_downloadBlockProofLinks>(p);
}
tonNode_downloadBlockProofLinks::tonNode_downloadBlockProofLinks(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: blocks_(TlFetchVector<TlFetchObject<tonNode_blockIdExt>>::parse(p))
#undef FAIL
{}
void tonNode_downloadBlockProofLinks::store(td::TlStorerCalcLength &s) const {
(void)sizeof(s);
s.store_binary(684796771);
TlStoreVector<TlStoreObject>::store(blocks_, s);
}
void tonNode_downloadBlockProofLinks::store(td::TlStorerUnsafe &s) const {
(void)sizeof(s);
s.store_binary(684796771);
TlStoreVector<TlStoreObject>::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<object_ptr<tonNode_blockIdExt>> &v = blocks_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(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<TlFetchObject<tonNode_dataList>, 351548179>::parse(p);
#undef FAIL
}
tonNode_downloadBlockProofs::tonNode_downloadBlockProofs()
: blocks_()
{}
tonNode_downloadBlockProofs::tonNode_downloadBlockProofs(std::vector<object_ptr<tonNode_blockIdExt>> &&blocks_)
: blocks_(std::move(blocks_))
{}
const std::int32_t tonNode_downloadBlockProofs::ID;
object_ptr<tonNode_downloadBlockProofs> tonNode_downloadBlockProofs::fetch(td::TlParser &p) {
return make_object<tonNode_downloadBlockProofs>(p);
}
tonNode_downloadBlockProofs::tonNode_downloadBlockProofs(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: blocks_(TlFetchVector<TlFetchObject<tonNode_blockIdExt>>::parse(p))
#undef FAIL
{}
void tonNode_downloadBlockProofs::store(td::TlStorerCalcLength &s) const {
(void)sizeof(s);
s.store_binary(-1515170827);
TlStoreVector<TlStoreObject>::store(blocks_, s);
}
void tonNode_downloadBlockProofs::store(td::TlStorerUnsafe &s) const {
(void)sizeof(s);
s.store_binary(-1515170827);
TlStoreVector<TlStoreObject>::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<object_ptr<tonNode_blockIdExt>> &v = blocks_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(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<TlFetchObject<tonNode_dataList>, 351548179>::parse(p);
#undef FAIL
}
tonNode_downloadBlocks::tonNode_downloadBlocks()
: blocks_()
{}
tonNode_downloadBlocks::tonNode_downloadBlocks(std::vector<object_ptr<tonNode_blockIdExt>> &&blocks_)
: blocks_(std::move(blocks_))
{}
const std::int32_t tonNode_downloadBlocks::ID;
object_ptr<tonNode_downloadBlocks> tonNode_downloadBlocks::fetch(td::TlParser &p) {
return make_object<tonNode_downloadBlocks>(p);
}
tonNode_downloadBlocks::tonNode_downloadBlocks(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: blocks_(TlFetchVector<TlFetchObject<tonNode_blockIdExt>>::parse(p))
#undef FAIL
{}
void tonNode_downloadBlocks::store(td::TlStorerCalcLength &s) const {
(void)sizeof(s);
s.store_binary(1985594749);
TlStoreVector<TlStoreObject>::store(blocks_, s);
}
void tonNode_downloadBlocks::store(td::TlStorerUnsafe &s) const {
(void)sizeof(s);
s.store_binary(1985594749);
TlStoreVector<TlStoreObject>::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<object_ptr<tonNode_blockIdExt>> &v = blocks_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(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<TlFetchObject<tonNode_dataList>, 351548179>::parse(p);
#undef FAIL
}
tonNode_downloadNextBlockFull::tonNode_downloadNextBlockFull()
: prev_block_()
{}
tonNode_downloadNextBlockFull::tonNode_downloadNextBlockFull(object_ptr<tonNode_blockIdExt> &&prev_block_)
: prev_block_(std::move(prev_block_))
{}
const std::int32_t tonNode_downloadNextBlockFull::ID;
object_ptr<tonNode_downloadNextBlockFull> tonNode_downloadNextBlockFull::fetch(td::TlParser &p) {
return make_object<tonNode_downloadNextBlockFull>(p);
}
tonNode_downloadNextBlockFull::tonNode_downloadNextBlockFull(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: prev_block_(TlFetchObject<tonNode_blockIdExt>::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<tonNode_DataFull>::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> tonNode_getCapabilities::fetch(td::TlParser &p) {
return make_object<tonNode_getCapabilities>(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<TlFetchObject<tonNode_capabilities>, -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<tonNode_blockIdExt> &&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> tonNode_getNextBlocksDescription::fetch(td::TlParser &p) {
return make_object<tonNode_getNextBlocksDescription>(p);
}
tonNode_getNextBlocksDescription::tonNode_getNextBlocksDescription(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: prev_block_(TlFetchObject<tonNode_blockIdExt>::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<TlFetchObject<tonNode_blocksDescription>, -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<tonNode_blockIdExt> &&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> tonNode_getPrevBlocksDescription::fetch(td::TlParser &p) {
return make_object<tonNode_getPrevBlocksDescription>(p);
}
tonNode_getPrevBlocksDescription::tonNode_getPrevBlocksDescription(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: next_block_(TlFetchObject<tonNode_blockIdExt>::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<TlFetchObject<tonNode_blocksDescription>, -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<object_ptr<tonNode_blockIdExt>> &&blocks_, bool allow_partial_)
: blocks_(std::move(blocks_))
, allow_partial_(allow_partial_)
{}
const std::int32_t tonNode_prepareBlockProofs::ID;
object_ptr<tonNode_prepareBlockProofs> tonNode_prepareBlockProofs::fetch(td::TlParser &p) {
return make_object<tonNode_prepareBlockProofs>(p);
}
tonNode_prepareBlockProofs::tonNode_prepareBlockProofs(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: blocks_(TlFetchVector<TlFetchObject<tonNode_blockIdExt>>::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<TlStoreObject>::store(blocks_, s);
TlStoreBool::store(allow_partial_, s);
}
void tonNode_prepareBlockProofs::store(td::TlStorerUnsafe &s) const {
(void)sizeof(s);
s.store_binary(-310791496);
TlStoreVector<TlStoreObject>::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<object_ptr<tonNode_blockIdExt>> &v = blocks_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(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<tonNode_PreparedProof>::parse(p);
#undef FAIL
}
tonNode_prepareBlocks::tonNode_prepareBlocks()
: blocks_()
{}
tonNode_prepareBlocks::tonNode_prepareBlocks(std::vector<object_ptr<tonNode_blockIdExt>> &&blocks_)
: blocks_(std::move(blocks_))
{}
const std::int32_t tonNode_prepareBlocks::ID;
object_ptr<tonNode_prepareBlocks> tonNode_prepareBlocks::fetch(td::TlParser &p) {
return make_object<tonNode_prepareBlocks>(p);
}
tonNode_prepareBlocks::tonNode_prepareBlocks(td::TlParser &p)
#define FAIL(error) p.set_error(error)
: blocks_(TlFetchVector<TlFetchObject<tonNode_blockIdExt>>::parse(p))
#undef FAIL
{}
void tonNode_prepareBlocks::store(td::TlStorerCalcLength &s) const {
(void)sizeof(s);
s.store_binary(1795140604);
TlStoreVector<TlStoreObject>::store(blocks_, s);
}
void tonNode_prepareBlocks::store(td::TlStorerUnsafe &s) const {
(void)sizeof(s);
s.store_binary(1795140604);
TlStoreVector<TlStoreObject>::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<object_ptr<tonNode_blockIdExt>> &v = blocks_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(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<tonNode_Prepared>::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<TlFetchTrue, 1072550713>::parse(p);
return TlFetchBoxed<TlFetchObject<tonNode_success>, -1063902129>::parse(p);
#undef FAIL
}

View file

@ -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<object_ptr<tonNode_blockIdExt>> ids_;
bool incomplete_;
tonNode_blocksDescription();
tonNode_blocksDescription(std::vector<object_ptr<tonNode_blockIdExt>> &&ids_, bool incomplete_);
static const std::int32_t ID = -701865684;
std::int32_t get_id() const final {
return ID;
}
static object_ptr<tonNode_blocksDescription> 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<tonNode_capabilities> 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<tonNode_DataFull> fetch(td::TlParser &p);
};
class tonNode_dataFull final : public tonNode_DataFull {
public:
object_ptr<tonNode_blockIdExt> id_;
td::BufferSlice proof_;
td::BufferSlice block_;
bool is_link_;
tonNode_dataFull();
tonNode_dataFull(object_ptr<tonNode_blockIdExt> &&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<tonNode_DataFull> 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<tonNode_DataFull> 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<td::BufferSlice> data_;
tonNode_dataList();
explicit tonNode_dataList(std::vector<td::BufferSlice> &&data_);
static const std::int32_t ID = 351548179;
std::int32_t get_id() const final {
return ID;
}
static object_ptr<tonNode_dataList> 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<tonNode_success> 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<tonNode_blockIdExt> block_;
tonNode_downloadBlockFull();
explicit tonNode_downloadBlockFull(object_ptr<tonNode_blockIdExt> &&block_);
static const std::int32_t ID = 1780991133;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tonNode_DataFull>;
static object_ptr<tonNode_downloadBlockFull> 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<tonNode_blockIdExt> 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<object_ptr<tonNode_blockIdExt>> blocks_;
tonNode_downloadBlockProofLinks();
explicit tonNode_downloadBlockProofLinks(std::vector<object_ptr<tonNode_blockIdExt>> &&blocks_);
static const std::int32_t ID = 684796771;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tonNode_dataList>;
static object_ptr<tonNode_downloadBlockProofLinks> 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<object_ptr<tonNode_blockIdExt>> blocks_;
tonNode_downloadBlockProofs();
explicit tonNode_downloadBlockProofs(std::vector<object_ptr<tonNode_blockIdExt>> &&blocks_);
static const std::int32_t ID = -1515170827;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tonNode_dataList>;
static object_ptr<tonNode_downloadBlockProofs> 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<object_ptr<tonNode_blockIdExt>> blocks_;
tonNode_downloadBlocks();
explicit tonNode_downloadBlocks(std::vector<object_ptr<tonNode_blockIdExt>> &&blocks_);
static const std::int32_t ID = 1985594749;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tonNode_dataList>;
static object_ptr<tonNode_downloadBlocks> 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<tonNode_blockIdExt> prev_block_;
tonNode_downloadNextBlockFull();
explicit tonNode_downloadNextBlockFull(object_ptr<tonNode_blockIdExt> &&prev_block_);
static const std::int32_t ID = 1855993674;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tonNode_DataFull>;
static object_ptr<tonNode_downloadNextBlockFull> 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<tonNode_blockIdExt> 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<tonNode_capabilities>;
static object_ptr<tonNode_getCapabilities> 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<tonNode_blockIdExt> 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<tonNode_blockIdExt> prev_block_;
std::int32_t limit_;
tonNode_getNextBlocksDescription();
tonNode_getNextBlocksDescription(object_ptr<tonNode_blockIdExt> &&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<tonNode_blocksDescription>;
static object_ptr<tonNode_getNextBlocksDescription> 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<tonNode_blockIdExt> 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<tonNode_blockIdExt> next_block_;
std::int32_t limit_;
std::int32_t cutoff_seqno_;
tonNode_getPrevBlocksDescription();
tonNode_getPrevBlocksDescription(object_ptr<tonNode_blockIdExt> &&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<tonNode_blocksDescription>;
static object_ptr<tonNode_getPrevBlocksDescription> 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<tonNode_blockIdExt> 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<object_ptr<tonNode_blockIdExt>> blocks_;
bool allow_partial_;
tonNode_prepareBlockProofs();
tonNode_prepareBlockProofs(std::vector<object_ptr<tonNode_blockIdExt>> &&blocks_, bool allow_partial_);
static const std::int32_t ID = -310791496;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tonNode_PreparedProof>;
static object_ptr<tonNode_prepareBlockProofs> 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<object_ptr<tonNode_blockIdExt>> blocks_;
tonNode_prepareBlocks();
explicit tonNode_prepareBlocks(std::vector<object_ptr<tonNode_blockIdExt>> &&blocks_);
static const std::int32_t ID = 1795140604;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tonNode_Prepared>;
static object_ptr<tonNode_prepareBlocks> 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<tonNode_blockIdExt> block_;
@ -8549,12 +8989,12 @@ class tonNode_slave_sendExtMessage final : public Function {
explicit tonNode_slave_sendExtMessage(object_ptr<tonNode_externalMessage> &&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<tonNode_success>;
static object_ptr<tonNode_slave_sendExtMessage> fetch(td::TlParser &p);

View file

@ -647,6 +647,9 @@ bool downcast_call(Object &obj, const T &func) {
case tonNode_blockSignature::ID:
func(static_cast<tonNode_blockSignature &>(obj));
return true;
case tonNode_blocksDescription::ID:
func(static_cast<tonNode_blocksDescription &>(obj));
return true;
case tonNode_blockBroadcast::ID:
func(static_cast<tonNode_blockBroadcast &>(obj));
return true;
@ -659,9 +662,21 @@ bool downcast_call(Object &obj, const T &func) {
case tonNode_newShardBlockBroadcast::ID:
func(static_cast<tonNode_newShardBlockBroadcast &>(obj));
return true;
case tonNode_capabilities::ID:
func(static_cast<tonNode_capabilities &>(obj));
return true;
case tonNode_data::ID:
func(static_cast<tonNode_data &>(obj));
return true;
case tonNode_dataFull::ID:
func(static_cast<tonNode_dataFull &>(obj));
return true;
case tonNode_dataFullEmpty::ID:
func(static_cast<tonNode_dataFullEmpty &>(obj));
return true;
case tonNode_dataList::ID:
func(static_cast<tonNode_dataList &>(obj));
return true;
case tonNode_externalMessage::ID:
func(static_cast<tonNode_externalMessage &>(obj));
return true;
@ -701,6 +716,9 @@ bool downcast_call(Object &obj, const T &func) {
case tonNode_shardPublicOverlayId::ID:
func(static_cast<tonNode_shardPublicOverlayId &>(obj));
return true;
case tonNode_success::ID:
func(static_cast<tonNode_success &>(obj));
return true;
case tonNode_zeroStateIdExt::ID:
func(static_cast<tonNode_zeroStateIdExt &>(obj));
return true;
@ -925,12 +943,27 @@ bool downcast_call(Function &obj, const T &func) {
case tonNode_downloadBlock::ID:
func(static_cast<tonNode_downloadBlock &>(obj));
return true;
case tonNode_downloadBlockFull::ID:
func(static_cast<tonNode_downloadBlockFull &>(obj));
return true;
case tonNode_downloadBlockProof::ID:
func(static_cast<tonNode_downloadBlockProof &>(obj));
return true;
case tonNode_downloadBlockProofLink::ID:
func(static_cast<tonNode_downloadBlockProofLink &>(obj));
return true;
case tonNode_downloadBlockProofLinks::ID:
func(static_cast<tonNode_downloadBlockProofLinks &>(obj));
return true;
case tonNode_downloadBlockProofs::ID:
func(static_cast<tonNode_downloadBlockProofs &>(obj));
return true;
case tonNode_downloadBlocks::ID:
func(static_cast<tonNode_downloadBlocks &>(obj));
return true;
case tonNode_downloadNextBlockFull::ID:
func(static_cast<tonNode_downloadNextBlockFull &>(obj));
return true;
case tonNode_downloadPersistentState::ID:
func(static_cast<tonNode_downloadPersistentState &>(obj));
return true;
@ -940,18 +973,33 @@ bool downcast_call(Function &obj, const T &func) {
case tonNode_downloadZeroState::ID:
func(static_cast<tonNode_downloadZeroState &>(obj));
return true;
case tonNode_getCapabilities::ID:
func(static_cast<tonNode_getCapabilities &>(obj));
return true;
case tonNode_getNextBlockDescription::ID:
func(static_cast<tonNode_getNextBlockDescription &>(obj));
return true;
case tonNode_getNextBlocksDescription::ID:
func(static_cast<tonNode_getNextBlocksDescription &>(obj));
return true;
case tonNode_getNextKeyBlockIds::ID:
func(static_cast<tonNode_getNextKeyBlockIds &>(obj));
return true;
case tonNode_getPrevBlocksDescription::ID:
func(static_cast<tonNode_getPrevBlocksDescription &>(obj));
return true;
case tonNode_prepareBlock::ID:
func(static_cast<tonNode_prepareBlock &>(obj));
return true;
case tonNode_prepareBlockProof::ID:
func(static_cast<tonNode_prepareBlockProof &>(obj));
return true;
case tonNode_prepareBlockProofs::ID:
func(static_cast<tonNode_prepareBlockProofs &>(obj));
return true;
case tonNode_prepareBlocks::ID:
func(static_cast<tonNode_prepareBlocks &>(obj));
return true;
case tonNode_preparePersistentState::ID:
func(static_cast<tonNode_preparePersistentState &>(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 <class T>
bool downcast_call(tonNode_DataFull &obj, const T &func) {
switch (obj.get_id()) {
case tonNode_dataFull::ID:
func(static_cast<tonNode_dataFull &>(obj));
return true;
case tonNode_dataFullEmpty::ID:
func(static_cast<tonNode_dataFullEmpty &>(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.

View file

@ -400,6 +400,17 @@ Result<int32> tl_constructor_from_string(ton_api::tonNode_Broadcast *object, con
}
return it->second;
}
Result<int32> tl_constructor_from_string(ton_api::tonNode_DataFull *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> 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<int32> tl_constructor_from_string(ton_api::tonNode_Prepared *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> m = {
{"tonNode.prepared", -356205619},
@ -686,11 +697,16 @@ Result<int32> 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<int32> 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<int32> 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<ton_api::tonNode_Broadcast &>(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<ton_api::tonNode_DataFull &>(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");

View file

@ -41,6 +41,7 @@ Result<int32> tl_constructor_from_string(ton_api::tcp_Message *object, const std
Result<int32> tl_constructor_from_string(ton_api::ton_BlockId *object, const std::string &str);
Result<int32> tl_constructor_from_string(ton_api::tonNode_BlockDescription *object, const std::string &str);
Result<int32> tl_constructor_from_string(ton_api::tonNode_Broadcast *object, const std::string &str);
Result<int32> tl_constructor_from_string(ton_api::tonNode_DataFull *object, const std::string &str);
Result<int32> tl_constructor_from_string(ton_api::tonNode_Prepared *object, const std::string &str);
Result<int32> tl_constructor_from_string(ton_api::tonNode_PreparedProof *object, const std::string &str);
Result<int32> 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);

View file

@ -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<std::string> &&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<std::string> &v = tags_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(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<wallet_accountState> &&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<raw_initialAccountState> &&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<testWallet_initialAccountState> &&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<internal_transactionId> &&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_)
: 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<LogStream> &&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<wallet_initialAccountState> &&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<accountAddress> &&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<inputKey> &&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<inputKey> &&private_key_, object_ptr<accountAddress> &&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

View file

@ -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<std::string> tags_;
logTags();
explicit logTags(std::vector<std::string> &&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<wallet_accountState> account_state_;
generic_accountStateWallet();
explicit generic_accountStateWallet(object_ptr<wallet_accountState> &&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<testGiver_accountState> 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<raw_initialAccountState> initital_account_state_;
generic_initialAccountStateRaw();
explicit generic_initialAccountStateRaw(object_ptr<raw_initialAccountState> &&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<testWallet_initialAccountState> initital_account_state_;
generic_initialAccountStateTestWallet();
explicit generic_initialAccountStateTestWallet(object_ptr<testWallet_initialAccountState> &&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<internal_transactionId> last_transaction_id_;
std::int64_t sync_utime_;
wallet_accountState();
wallet_accountState(std::int64_t balance_, std::int32_t seqno_, object_ptr<internal_transactionId> &&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<ok>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class changeLocalPassword final : public Function {
public:
object_ptr<inputKey> input_key_;
@ -622,13 +743,13 @@ class createNewKey final : public Function {
class deleteKey final : public Function {
public:
std::string public_key_;
object_ptr<key> key_;
deleteKey();
explicit deleteKey(std::string const &public_key_);
explicit deleteKey(object_ptr<key> &&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<LogStream>;
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<logVerbosityLevel>;
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<logTags>;
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<logVerbosityLevel>;
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<LogStream> log_stream_;
setLogStream();
explicit setLogStream(object_ptr<LogStream> &&log_stream_);
static const std::int32_t ID = -1364199535;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<ok>;
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<ok>;
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<ok>;
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<wallet_initialAccountState> initital_account_state_;
wallet_getAccountAddress();
explicit wallet_getAccountAddress(object_ptr<wallet_initialAccountState> &&initital_account_state_);
static const std::int32_t ID = -1004103180;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<accountAddress>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class wallet_getAccountState final : public Function {
public:
object_ptr<accountAddress> account_address_;
wallet_getAccountState();
explicit wallet_getAccountState(object_ptr<accountAddress> &&account_address_);
static const std::int32_t ID = 462294850;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<wallet_accountState>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class wallet_init final : public Function {
public:
object_ptr<inputKey> private_key_;
wallet_init();
explicit wallet_init(object_ptr<inputKey> &&private_key_);
static const std::int32_t ID = 1528056782;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<ok>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class wallet_sendGrams final : public Function {
public:
object_ptr<inputKey> private_key_;
object_ptr<accountAddress> destination_;
std::int32_t seqno_;
std::int64_t valid_until_;
std::int64_t amount_;
std::string message_;
wallet_sendGrams();
wallet_sendGrams(object_ptr<inputKey> &&private_key_, object_ptr<accountAddress> &&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<ok>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
} // namespace tonlib_api
} // namespace ton

View file

@ -38,6 +38,21 @@ bool downcast_call(Object &obj, const T &func) {
case key::ID:
func(static_cast<key &>(obj));
return true;
case logStreamDefault::ID:
func(static_cast<logStreamDefault &>(obj));
return true;
case logStreamFile::ID:
func(static_cast<logStreamFile &>(obj));
return true;
case logStreamEmpty::ID:
func(static_cast<logStreamEmpty &>(obj));
return true;
case logTags::ID:
func(static_cast<logTags &>(obj));
return true;
case logVerbosityLevel::ID:
func(static_cast<logVerbosityLevel &>(obj));
return true;
case ok::ID:
func(static_cast<ok &>(obj));
return true;
@ -53,18 +68,15 @@ bool downcast_call(Object &obj, const T &func) {
case generic_accountStateTestWallet::ID:
func(static_cast<generic_accountStateTestWallet &>(obj));
return true;
case generic_accountStateWallet::ID:
func(static_cast<generic_accountStateWallet &>(obj));
return true;
case generic_accountStateTestGiver::ID:
func(static_cast<generic_accountStateTestGiver &>(obj));
return true;
case generic_accountStateUninited::ID:
func(static_cast<generic_accountStateUninited &>(obj));
return true;
case generic_initialAccountStateRaw::ID:
func(static_cast<generic_initialAccountStateRaw &>(obj));
return true;
case generic_initialAccountStateTestWallet::ID:
func(static_cast<generic_initialAccountStateTestWallet &>(obj));
return true;
case internal_transactionId::ID:
func(static_cast<internal_transactionId &>(obj));
return true;
@ -95,6 +107,12 @@ bool downcast_call(Object &obj, const T &func) {
case uninited_accountState::ID:
func(static_cast<uninited_accountState &>(obj));
return true;
case wallet_accountState::ID:
func(static_cast<wallet_accountState &>(obj));
return true;
case wallet_initialAccountState::ID:
func(static_cast<wallet_initialAccountState &>(obj));
return true;
default:
return false;
}
@ -109,6 +127,9 @@ bool downcast_call(Object &obj, const T &func) {
template <class T>
bool downcast_call(Function &obj, const T &func) {
switch (obj.get_id()) {
case addLogMessage::ID:
func(static_cast<addLogMessage &>(obj));
return true;
case changeLocalPassword::ID:
func(static_cast<changeLocalPassword &>(obj));
return true;
@ -139,6 +160,18 @@ bool downcast_call(Function &obj, const T &func) {
case getBip39Hints::ID:
func(static_cast<getBip39Hints &>(obj));
return true;
case getLogStream::ID:
func(static_cast<getLogStream &>(obj));
return true;
case getLogTagVerbosityLevel::ID:
func(static_cast<getLogTagVerbosityLevel &>(obj));
return true;
case getLogTags::ID:
func(static_cast<getLogTags &>(obj));
return true;
case getLogVerbosityLevel::ID:
func(static_cast<getLogVerbosityLevel &>(obj));
return true;
case importEncryptedKey::ID:
func(static_cast<importEncryptedKey &>(obj));
return true;
@ -175,6 +208,15 @@ bool downcast_call(Function &obj, const T &func) {
case runTests::ID:
func(static_cast<runTests &>(obj));
return true;
case setLogStream::ID:
func(static_cast<setLogStream &>(obj));
return true;
case setLogTagVerbosityLevel::ID:
func(static_cast<setLogTagVerbosityLevel &>(obj));
return true;
case setLogVerbosityLevel::ID:
func(static_cast<setLogVerbosityLevel &>(obj));
return true;
case testGiver_getAccountAddress::ID:
func(static_cast<testGiver_getAccountAddress &>(obj));
return true;
@ -196,6 +238,41 @@ bool downcast_call(Function &obj, const T &func) {
case testWallet_sendGrams::ID:
func(static_cast<testWallet_sendGrams &>(obj));
return true;
case wallet_getAccountAddress::ID:
func(static_cast<wallet_getAccountAddress &>(obj));
return true;
case wallet_getAccountState::ID:
func(static_cast<wallet_getAccountState &>(obj));
return true;
case wallet_init::ID:
func(static_cast<wallet_init &>(obj));
return true;
case wallet_sendGrams::ID:
func(static_cast<wallet_sendGrams &>(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 <class T>
bool downcast_call(LogStream &obj, const T &func) {
switch (obj.get_id()) {
case logStreamDefault::ID:
func(static_cast<logStreamDefault &>(obj));
return true;
case logStreamFile::ID:
func(static_cast<logStreamFile &>(obj));
return true;
case logStreamEmpty::ID:
func(static_cast<logStreamEmpty &>(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<generic_accountStateTestWallet &>(obj));
return true;
case generic_accountStateWallet::ID:
func(static_cast<generic_accountStateWallet &>(obj));
return true;
case generic_accountStateTestGiver::ID:
func(static_cast<generic_accountStateTestGiver &>(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 <class T>
bool downcast_call(generic_InitialAccountState &obj, const T &func) {
switch (obj.get_id()) {
case generic_initialAccountStateRaw::ID:
func(static_cast<generic_initialAccountStateRaw &>(obj));
return true;
case generic_initialAccountStateTestWallet::ID:
func(static_cast<generic_initialAccountStateTestWallet &>(obj));
return true;
default:
return false;
}
}
} // namespace tonlib_api
} // namespace ton

View file

@ -14,12 +14,11 @@
namespace ton {
namespace tonlib_api{
using namespace td;
Result<int32> tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str) {
Result<int32> tl_constructor_from_string(tonlib_api::LogStream *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> 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<int32> tl_constructor_from_string(tonlib_api::generic_AccountState *objec
}
return it->second;
}
Result<int32> tl_constructor_from_string(tonlib_api::generic_InitialAccountState *object, const std::string &str) {
Result<int32> tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> 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<int32> 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<int32> 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<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::
}
Result<int32> tl_constructor_from_string(tonlib_api::Function *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> 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<int32> 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<tonlib_api::LogStream &>(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<tonlib_api::generic_InitialAccountState &>(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

View file

@ -11,8 +11,8 @@
namespace ton {
namespace tonlib_api{
using namespace td;
Result<int32> tl_constructor_from_string(tonlib_api::LogStream *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::generic_InitialAccountState *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::string &str);
Result<int32> 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<ton::tonlib_api::Object &>(object),[&jv](const auto &object) { to_json(jv, object); });
}

View file

@ -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;

View file

@ -39,20 +39,45 @@ raw.transactions transactions:vector<raw.Transaction> 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<string> = 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;

View file

@ -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

View file

@ -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<vm::Cell> 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<vm::Cell> 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<vm::Cell> 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<ZeroOsTime>());
auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok();
fift_output =
fift::mem_run_fift(std::move(fift_output.source_lookup),
{"aba", "new-wallet", "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "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<tonlib_api::importKey>(new_local_password.copy(), mnemonic_password.copy(),
make_object<tonlib_api::exportedKey>(copy_word_list())))
.ensure_error();
//sync_send(client, make_object<tonlib_api::importKey>(new_local_password.copy(), mnemonic_password.copy(),
//make_object<tonlib_api::exportedKey>(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<tonlib_api::deleteKey>(key->public_key_)).move_as_ok();
sync_send(client,
make_object<tonlib_api::deleteKey>(make_object<tonlib_api::key>(key->public_key_, key->secret_.copy())))
.move_as_ok();
sync_send(client, make_object<tonlib_api::importEncryptedKey>(
new_local_password.copy(), wrong_export_password.copy(),
@ -374,10 +474,13 @@ TEST(Tonlib, KeysApi) {
make_object<tonlib_api::exportedEncryptedKey>(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<tonlib_api::deleteKey>(key->public_key_)).move_as_ok();
sync_send(client,
make_object<tonlib_api::deleteKey>(make_object<tonlib_api::key>(key->public_key_, key->secret_.copy())))
.move_as_ok();
auto err1 = sync_send(client, make_object<tonlib_api::importKey>(
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<tonlib_api::importPemKey>(
new_local_password.copy(), pem_password.copy(),
make_object<tonlib_api::exportedPemKey>(exported_pem_key->pem_.copy())))
.ensure_error();
sync_send(client, make_object<tonlib_api::deleteKey>(key->public_key_)).move_as_ok();
//sync_send(client, make_object<tonlib_api::importPemKey>(
//new_local_password.copy(), pem_password.copy(),
//make_object<tonlib_api::exportedPemKey>(exported_pem_key->pem_.copy())))
//.ensure_error();
sync_send(client, make_object<tonlib_api::deleteKey>(
make_object<tonlib_api::key>(imported_key->public_key_, imported_key->secret_.copy())))
.move_as_ok();
sync_send(client, make_object<tonlib_api::importPemKey>(
new_local_password.copy(), td::SecureString("wrong pem password"),
make_object<tonlib_api::exportedPemKey>(exported_pem_key->pem_.copy())))

View file

@ -28,7 +28,7 @@ td::Ref<vm::Cell> GenericAccount::get_init_state(td::Ref<vm::Cell> code, td::Ref
.finalize();
}
block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id, const td::Ref<vm::Cell>& 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<vm::Cell> GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
td::Ref<vm::Cell> body) {

View file

@ -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::Key> 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_t>(size)) {
return td::Status::Error(PSLICE() << "Failed to write file: written " << written << " bytes instead of " << size);
@ -74,7 +83,16 @@ td::Result<KeyStorage::Key> KeyStorage::create_new_key(td::Slice local_password,
}
td::Result<DecryptedKey> 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::PrivateKey> 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::Key> KeyStorage::import_key(td::Slice local_password, td::Slice mnemonic_password,
@ -122,6 +140,7 @@ td::Result<KeyStorage::Key> 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);
}

View file

@ -57,7 +57,7 @@ class KeyStorage {
td::Result<ExportedEncryptedKey> export_encrypted_key(InputKey input_key, td::Slice key_password);
td::Result<Key> 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<Key> import_key(td::Slice local_password, td::Slice mnemonic_password, ExportedKey exported_key);
td::Result<Key> import_pem_key(td::Slice local_password, td::Slice key_password, ExportedPemKey exported_key);
@ -72,6 +72,7 @@ class KeyStorage {
td::Result<Key> save_key(const DecryptedKey& mnemonic, td::Slice local_password);
td::Result<DecryptedKey> 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

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "LastBlockStorage.h"
#include "td/utils/as.h"

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "tonlib/LastBlock.h"

View file

@ -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 <http://www.gnu.org/licenses/>.
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 <atomic>
#include <map>
#include <mutex>
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<td::Slice, int *> log_tags{ADD_TAG(abc), ADD_TAG(bcd)};
#undef ADD_TAG
td::Status Logging::set_current_stream(tonlib_api::object_ptr<tonlib_api::LogStream> stream) {
if (stream == nullptr) {
return td::Status::Error("Log stream must not be empty");
}
std::lock_guard<std::mutex> 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<tonlib_api::logStreamFile>(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<tonlib_api::object_ptr<tonlib_api::LogStream>> Logging::get_current_stream() {
std::lock_guard<std::mutex> lock(logging_mutex);
if (td::log_interface == td::default_log_interface) {
return tonlib_api::make_object<tonlib_api::logStreamDefault>();
}
if (td::log_interface == &null_log) {
return tonlib_api::make_object<tonlib_api::logStreamEmpty>();
}
if (td::log_interface == &ts_log) {
return tonlib_api::make_object<tonlib_api::logStreamFile>(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<std::mutex> 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<std::mutex> lock(logging_mutex);
return GET_VERBOSITY_LEVEL();
}
td::vector<td::string> 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<std::mutex> lock(logging_mutex);
*it->second = td::clamp(new_verbosity_level, 1, VERBOSITY_NAME(NEVER));
return td::Status::OK();
}
td::Result<int> 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<std::mutex> 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

View file

@ -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 <http://www.gnu.org/licenses/>.
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<tonlib_api::LogStream> stream);
static td::Result<tonlib_api::object_ptr<tonlib_api::LogStream>> get_current_stream();
static td::Status set_verbosity_level(int new_verbosity_level);
static int get_verbosity_level();
static std::vector<std::string> get_tags();
static td::Status set_tag_verbosity_level(td::Slice tag, int new_verbosity_level);
static td::Result<int> get_tag_verbosity_level(td::Slice tag);
static void add_message(int log_verbosity_level, td::Slice message);
};
} // namespace tonlib

View file

@ -34,7 +34,7 @@ vm::CellHash TestGiver::get_init_code_hash() {
td::Ref<vm::Cell> 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<vm::Cell> 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

View file

@ -40,17 +40,20 @@ td::Ref<vm::Cell> TestWallet::get_init_message(const td::Ed25519::PrivateKey& pr
td::Ref<vm::Cell> 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();
}

View file

@ -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<vm::CellSlice> code;
td::Ref<vm::CellSlice> data;
block::AccountState::Info info;
td::int64 sync_utime = 0;
};
td::Result<td::int64> to_balance_or_throw(td::Ref<vm::CellSlice> 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<block::StdAddress> get_account_address(const tonlib_api::testWallet_i
return GenericAccount::get_address(0 /*zerochain*/, TestWallet::get_init_state(key));
}
td::Result<block::StdAddress> 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<tonlib_api::Object> 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<tonlib_api::Object> TonlibClient::do_static_request(
}
return tonlib_api::make_object<tonlib_api::accountAddress>(r_account_address.ok().rserialize());
}
tonlib_api::object_ptr<tonlib_api::Object> 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<tonlib_api::accountAddress>(r_account_address.ok().rserialize());
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::testGiver_getAccountAddress& request) {
return tonlib_api::make_object<tonlib_api::accountAddress>(TestGiver::address().rserialize());
@ -547,8 +571,8 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_accountState>> to_raw_accountS
.as_slice()
.str();
}
return tonlib_api::make_object<tonlib_api::raw_accountState>(raw_state.balance, std::move(code), std::move(data),
to_transaction_id(raw_state.info), raw_state.sync_utime);
return tonlib_api::make_object<tonlib_api::raw_accountState>(
raw_state.balance, std::move(code), std::move(data), to_transaction_id(raw_state.info), raw_state.info.gen_utime);
}
td::Result<std::string> to_std_address_or_throw(td::Ref<vm::CellSlice> cs) {
@ -601,6 +625,10 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_message>> 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<tonlib_api::raw_message>(std::move(src), std::move(dest), balance,
@ -711,7 +739,22 @@ td::Result<tonlib_api::object_ptr<tonlib_api::testWallet_accountState>> to_testW
return td::Status::Error("Failed to parse seq_no");
}
return tonlib_api::make_object<tonlib_api::testWallet_accountState>(
raw_state.balance, static_cast<td::uint32>(seqno), to_transaction_id(raw_state.info), raw_state.sync_utime);
raw_state.balance, static_cast<td::uint32>(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime);
}
td::Result<tonlib_api::object_ptr<tonlib_api::wallet_accountState>> 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<tonlib_api::wallet_accountState>(
raw_state.balance, static_cast<td::uint32>(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime);
}
td::Result<tonlib_api::object_ptr<tonlib_api::testGiver_accountState>> to_testGiver_accountState(
@ -726,7 +769,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::testGiver_accountState>> to_testGi
return td::Status::Error("Failed to parse seq_no");
}
return tonlib_api::make_object<tonlib_api::testGiver_accountState>(
raw_state.balance, static_cast<td::uint32>(seqno), to_transaction_id(raw_state.info), raw_state.sync_utime);
raw_state.balance, static_cast<td::uint32>(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime);
}
td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> to_generic_accountState(
@ -734,7 +777,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> to_generic_
if (raw_state.code.is_null()) {
return tonlib_api::make_object<tonlib_api::generic_accountStateUninited>(
tonlib_api::make_object<tonlib_api::uninited_accountState>(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<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> to_generic_
TRY_RESULT(test_wallet, to_testWallet_accountState(std::move(raw_state)));
return tonlib_api::make_object<tonlib_api::generic_accountStateTestWallet>(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<tonlib_api::generic_accountStateWallet>(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<tonlib_api::generic_accountStateTestGiver>(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<tonlib_api::accountAddress>(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<tonlib_api::accountAddress>(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<object_ptr<tonlib_api::ok>>&& 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<tonlib_api::accountAddress>(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<object_ptr<tonlib_api::ok>>&& 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<td::uint32>(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<tonlib_api::accountAddress>(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<object_ptr<tonlib_api::wallet_accountState>>&& 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<GetRawAccountState>(
"GetAccountState", client_.get_client(), std::move(account_address),
[promise = std::move(promise)](td::Result<RawAccountState> 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<object_ptr<tonlib_api::ok>>&& 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<TonlibClient> client) : client_(std::move(client)) {
}
template <class QueryT>
void send_query(QueryT query, td::Promise<typename QueryT::ReturnType> 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<TonlibClient> client_;
};
class GenericSendGrams : public TonlibQueryActor {
public:
GenericSendGrams(td::actor::ActorShared<TonlibClient> client, tonlib_api::generic_sendGrams send_grams,
td::Promise<tonlib_api::object_ptr<tonlib_api::ok>>&& promise)
: TonlibQueryActor(std::move(client)), send_grams_(std::move(send_grams)), promise_(std::move(promise)) {
}
private:
tonlib_api::generic_sendGrams send_grams_;
td::Promise<tonlib_api::object_ptr<tonlib_api::ok>> promise_;
tonlib_api::object_ptr<tonlib_api::generic_AccountState> source_state_;
block::StdAddress source_address_;
tonlib_api::object_ptr<tonlib_api::generic_AccountState> 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<tonlib_api::accountAddress>(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<tonlib_api::accountAddress>(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<tonlib_api::key> clone(const tonlib_api::object_ptr<tonlib_api::key>& ptr) {
if (!ptr) {
return nullptr;
}
return tonlib_api::make_object<tonlib_api::key>(ptr->public_key_, ptr->secret_.copy());
}
static tonlib_api::object_ptr<tonlib_api::inputKey> clone(const tonlib_api::object_ptr<tonlib_api::inputKey>& ptr) {
if (!ptr) {
return nullptr;
}
return tonlib_api::make_object<tonlib_api::inputKey>(clone(ptr->key_), ptr->local_password_.copy());
}
void on_source_state(td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> r_state) {
check(do_on_source_state(std::move(r_state)));
}
td::Status do_on_source_state(td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> 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::generic_accountStateTestWallet>(
tonlib_api::make_object<tonlib_api::testWallet_accountState>(-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::generic_accountStateWallet>(
tonlib_api::make_object<tonlib_api::wallet_accountState>(-1, 0, nullptr, 0));
}
}
return do_loop();
}
void on_destination_state(td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> r_state) {
check(do_on_destination_state(std::move(r_state)));
}
td::Status do_on_destination_state(td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> 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<td::uint32>::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<object_ptr<tonlib_api::ok>>&& 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<GetRawAccountState>(
"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<RawAccountState> 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>("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<object_ptr<tonlib_api::ok>>&& 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<tonlib_api::ok>());
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<tonlib_api::Object> 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<tonlib_api::ok>();
} else {
return tonlib_api::make_object<tonlib_api::error>(400, result.message().str());
}
}
tonlib_api::object_ptr<tonlib_api::Object> 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<tonlib_api::error>(400, result.error().message().str());
}
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::setLogVerbosityLevel& request) {
auto result = Logging::set_verbosity_level(static_cast<int>(request.new_verbosity_level_));
if (result.is_ok()) {
return tonlib_api::make_object<tonlib_api::ok>();
} else {
return tonlib_api::make_object<tonlib_api::error>(400, result.message().str());
}
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::setLogTagVerbosityLevel& request) {
auto result = Logging::set_tag_verbosity_level(request.tag_, static_cast<int>(request.new_verbosity_level_));
if (result.is_ok()) {
return tonlib_api::make_object<tonlib_api::ok>();
} else {
return tonlib_api::make_object<tonlib_api::error>(400, result.message().str());
}
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::getLogVerbosityLevel& request) {
return tonlib_api::make_object<tonlib_api::logVerbosityLevel>(Logging::get_verbosity_level());
}
tonlib_api::object_ptr<tonlib_api::Object> 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<tonlib_api::logVerbosityLevel>(result.ok());
} else {
return tonlib_api::make_object<tonlib_api::error>(400, result.error().message().str());
}
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(const tonlib_api::getLogTags& request) {
return tonlib_api::make_object<tonlib_api::logTags>(Logging::get_tags());
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(const tonlib_api::addLogMessage& request) {
Logging::add_message(request.verbosity_level_, request.text_);
return tonlib_api::make_object<tonlib_api::ok>();
}
} // namespace tonlib

View file

@ -28,6 +28,8 @@
#include "td/actor/actor.h"
#include <map>
namespace tonlib {
class TonlibClient : public td::actor::Actor {
public:
@ -58,6 +60,9 @@ class TonlibClient : public td::actor::Actor {
td::actor::ActorOwn<LastBlock> raw_last_block_;
ExtClient client_;
std::map<td::int64, td::actor::ActorOwn<>> 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<tonlib_api::Object> do_static_request(const tonlib_api::runTests& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::raw_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testWallet_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::wallet_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testGiver_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::getBip39Hints& request);
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::setLogStream& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::getLogStream& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::setLogVerbosityLevel& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::setLogTagVerbosityLevel& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::getLogVerbosityLevel& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::getLogTagVerbosityLevel& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::getLogTags& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::addLogMessage& request);
template <class T, class P>
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<object_ptr<tonlib_api::testWallet_accountState>>&& promise);
td::Status do_request(const tonlib_api::wallet_init& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
td::Status do_request(const tonlib_api::wallet_sendGrams& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
td::Status do_request(tonlib_api::wallet_getAccountState& request,
td::Promise<object_ptr<tonlib_api::wallet_accountState>>&& promise);
td::Status do_request(const tonlib_api::testGiver_getAccountState& request,
td::Promise<object_ptr<tonlib_api::testGiver_accountState>>&& promise);
td::Status do_request(const tonlib_api::testGiver_sendGrams& request,
@ -145,5 +171,7 @@ class TonlibClient : public td::actor::Actor {
td::Promise<object_ptr<tonlib_api::ok>>&& promise);
void proxy_request(td::int64 query_id, std::string data);
friend class TonlibQueryActor;
};
} // namespace tonlib

View file

@ -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 <http://www.gnu.org/licenses/>.
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 <limits>
namespace tonlib {
td::Ref<vm::Cell> 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<vm::Cell> Wallet::get_init_message(const td::Ed25519::PrivateKey& private_key) {
td::uint32 seqno = 0;
td::uint32 valid_until = std::numeric_limits<td::uint32>::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<vm::Cell> 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<vm::Cell> 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<vm::Cell> 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

View file

@ -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 <http://www.gnu.org/licenses/>.
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<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key);
static td::Ref<vm::Cell> get_init_message(const td::Ed25519::PrivateKey& private_key);
static td::Ref<vm::Cell> 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<vm::Cell> get_init_code();
static vm::CellHash get_init_code_hash();
static td::Ref<vm::Cell> get_init_data(const td::Ed25519::PublicKey& public_key);
};
} // namespace tonlib

View file

@ -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<tonlib_api::testWallet_getAccountAddress>(
make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
auto obj = options_.use_simple_wallet
? tonlib::TonlibClient::static_request(make_object<tonlib_api::testWallet_getAccountAddress>(
make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key)))
: tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
if (obj->get_id() != tonlib_api::error::ID) {
Address res;
res.address = ton::move_tl_object_as<tonlib_api::accountAddress>(obj);
@ -476,12 +480,19 @@ class TonlibCli : public td::actor::Actor {
using tonlib_api::make_object;
send_query(make_object<tonlib_api::importKey>(td::SecureString(password), td::SecureString(),
make_object<tonlib_api::exportedKey>(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<tonlib_api::testWallet_init>(make_object<tonlib_api::inputKey>(
make_object<tonlib_api::key>(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<tonlib_api::testWallet_init>(make_object<tonlib_api::inputKey>(
make_object<tonlib_api::key>(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<tonlib_api::wallet_init>(make_object<tonlib_api::inputKey>(
make_object<tonlib_api::key>(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()) {