From 9cc4787973034dc99f20c2dc869ecfcc92500d1a Mon Sep 17 00:00:00 2001 From: Max Voloshinskii Date: Mon, 6 May 2024 23:07:07 +0300 Subject: [PATCH 1/3] Feature: Swap message builder --- .../TonSwift/Jettons/JettonTransferData.swift | 23 ++++------- .../Jettons/JettonTransferMessage.swift | 7 +++- Source/TonSwift/NFT/NFTTransferData.swift | 2 +- .../TonSwift/StonfiSwap/StonfiSwapData.swift | 35 +++++++++++++++++ .../StonfiSwap/StonfiSwapMessage.swift | 38 ++++++++++++++++++ Source/TonSwift/Util/OpCodes.swift | 13 +++++++ Source/TonSwift/Util/StonfiConstants.swift | 39 +++++++++++++++++++ 7 files changed, 139 insertions(+), 18 deletions(-) create mode 100644 Source/TonSwift/StonfiSwap/StonfiSwapData.swift create mode 100644 Source/TonSwift/StonfiSwap/StonfiSwapMessage.swift create mode 100644 Source/TonSwift/Util/OpCodes.swift create mode 100644 Source/TonSwift/Util/StonfiConstants.swift diff --git a/Source/TonSwift/Jettons/JettonTransferData.swift b/Source/TonSwift/Jettons/JettonTransferData.swift index 50aff88..ac8eb4a 100644 --- a/Source/TonSwift/Jettons/JettonTransferData.swift +++ b/Source/TonSwift/Jettons/JettonTransferData.swift @@ -14,21 +14,17 @@ public struct JettonTransferData: CellCodable { public let toAddress: Address public let responseAddress: Address public let forwardAmount: BigUInt - public let comment: String? - + public let forwardPayload: Cell? + public func storeTo(builder: Builder) throws { - try builder.store(uint: 0xf8a7ea5, bits: 32) + try builder.store(uint: OpCodes.JETTON_TRANSFER, bits: 32) try builder.store(uint: queryId, bits: 64) try builder.store(coins: Coins(amount.magnitude)) try builder.store(AnyAddress(toAddress)) try builder.store(AnyAddress(responseAddress)) try builder.store(bit: false) try builder.store(coins: Coins(forwardAmount.magnitude)) - var commentCell: Cell? - if let comment = comment { - commentCell = try Builder().store(int: 0, bits: 32).writeSnakeData(Data(comment.utf8)).endCell() - } - try builder.storeMaybe(ref: commentCell) + try builder.storeMaybe(ref: forwardPayload) } public static func loadFrom(slice: Slice) throws -> JettonTransferData { @@ -41,19 +37,14 @@ public struct JettonTransferData: CellCodable { let forwardAmount = try slice.loadCoins().amount let hasComment = try slice.loadBoolean() - var comment: String? - if hasComment { - let commentCell = try slice.loadRef() - let slice = try commentCell.toSlice() - try slice.skip(32) - comment = try slice.loadSnakeString() - } + let forwardPayload = try slice.loadRef() + return JettonTransferData(queryId: queryId, amount: amount, toAddress: toAddress, responseAddress: responseAddress, forwardAmount: forwardAmount, - comment: comment) + forwardPayload: forwardPayload) } } diff --git a/Source/TonSwift/Jettons/JettonTransferMessage.swift b/Source/TonSwift/Jettons/JettonTransferMessage.swift index 1e6ad5b..371e8f9 100644 --- a/Source/TonSwift/Jettons/JettonTransferMessage.swift +++ b/Source/TonSwift/Jettons/JettonTransferMessage.swift @@ -18,13 +18,18 @@ public struct JettonTransferMessage { let forwardAmount = BigUInt(stringLiteral: "1") let jettonTransferAmount = BigUInt(stringLiteral: "640000000") let queryId = UInt64(Date().timeIntervalSince1970) + + var commentCell: Cell? + if let comment = comment { + commentCell = try Builder().store(int: 0, bits: 32).writeSnakeData(Data(comment.utf8)).endCell() + } let jettonTransferData = JettonTransferData(queryId: queryId, amount: amount.magnitude, toAddress: to, responseAddress: from, forwardAmount: forwardAmount, - comment: comment) + forwardPayload: commentCell) return MessageRelaxed.internal( to: jettonAddress, diff --git a/Source/TonSwift/NFT/NFTTransferData.swift b/Source/TonSwift/NFT/NFTTransferData.swift index ed23123..650f010 100644 --- a/Source/TonSwift/NFT/NFTTransferData.swift +++ b/Source/TonSwift/NFT/NFTTransferData.swift @@ -16,7 +16,7 @@ public struct NFTTransferData: CellCodable { public let forwardPayload: Cell? public func storeTo(builder: Builder) throws { - try builder.store(uint: 0x5fcc3d14, bits: 32) // transfer op + try builder.store(uint: OpCodes.NFT_TRANSFER, bits: 32) // transfer op try builder.store(uint: queryId, bits: 64) try builder.store(AnyAddress(newOwnerAddress)) try builder.store(AnyAddress(responseAddress)) diff --git a/Source/TonSwift/StonfiSwap/StonfiSwapData.swift b/Source/TonSwift/StonfiSwap/StonfiSwapData.swift new file mode 100644 index 0000000..dcc9a21 --- /dev/null +++ b/Source/TonSwift/StonfiSwap/StonfiSwapData.swift @@ -0,0 +1,35 @@ +import Foundation +import BigInt + +public struct StonfiSwapData: CellCodable { + public let assetToSwap: Address + public let minAskAmount: BigUInt + public let userWalletAddress: Address + public let referralAddress: Address? + + public func storeTo(builder: Builder) throws { + try builder.store(uint: OpCodes.STONFI_SWAP, bits: 32) + try builder.store(AnyAddress(assetToSwap)) + try builder.store(coins: Coins(minAskAmount.magnitude)) + try builder.store(AnyAddress(userWalletAddress)) + + if referralAddress != nil { + try builder.store(bit: true) + try builder.store(AnyAddress(referralAddress)) + } else { + try builder.store(bit: false) + } + } + + public static func loadFrom(slice: Slice) throws -> StonfiSwapData { + _ = try slice.loadUint(bits: 32) + let assetToSwap: Address = try slice.loadType() + let minAskAmount = try slice.loadCoins().amount + + let userWalletAddress: Address = try slice.loadType() + let referralAddress: Address? = try slice.loadType() + + + return StonfiSwapData(assetToSwap: assetToSwap, minAskAmount: minAskAmount, userWalletAddress: userWalletAddress, referralAddress: referralAddress) + } +} diff --git a/Source/TonSwift/StonfiSwap/StonfiSwapMessage.swift b/Source/TonSwift/StonfiSwap/StonfiSwapMessage.swift new file mode 100644 index 0000000..6487d06 --- /dev/null +++ b/Source/TonSwift/StonfiSwap/StonfiSwapMessage.swift @@ -0,0 +1,38 @@ +import Foundation +import BigInt + +public struct StonfiSwapMessage { + /// Jetton --> Jetton swap message + public static func internalMessage(userWalletAddress: Address, + minAskAmount: BigUInt, + offerAmount: BigUInt, + jettonFromWalletAddress: Address, + jettonToWalletAddress: Address, + referralAddress: Address? = nil, + forwardAmount: BigUInt, + attachedAmount: BigUInt + ) throws -> MessageRelaxed { + let queryId = UInt64(Date().timeIntervalSince1970) + + let stonfiSwapData = StonfiSwapData(assetToSwap: jettonToWalletAddress, minAskAmount: minAskAmount, userWalletAddress: userWalletAddress, referralAddress: referralAddress) + + let stonfiSwapCell = try Builder().store(stonfiSwapData).endCell() + + let jettonTransferData = JettonTransferData( + queryId: queryId, + amount: offerAmount, + toAddress: try! Address.parse(STONFI_CONSTANTS.RouterAddress), + responseAddress: userWalletAddress, + forwardAmount: forwardAmount, + forwardPayload: stonfiSwapCell + ) + + return MessageRelaxed.internal( + to: jettonFromWalletAddress, + value: attachedAmount, + bounce: true, + body: try Builder().store(jettonTransferData).endCell() + ) + } +} + diff --git a/Source/TonSwift/Util/OpCodes.swift b/Source/TonSwift/Util/OpCodes.swift new file mode 100644 index 0000000..49b0bef --- /dev/null +++ b/Source/TonSwift/Util/OpCodes.swift @@ -0,0 +1,13 @@ +import BigInt + +public enum OpCodes { + public static var JETTON_TRANSFER: BigInt { + BigInt(0xf8a7ea5) + } + public static var NFT_TRANSFER: BigInt { + BigInt(0x5fcc3d14) + } + public static var STONFI_SWAP: BigInt { + BigInt(0x25938561) + } +} diff --git a/Source/TonSwift/Util/StonfiConstants.swift b/Source/TonSwift/Util/StonfiConstants.swift new file mode 100644 index 0000000..c6f4b4b --- /dev/null +++ b/Source/TonSwift/Util/StonfiConstants.swift @@ -0,0 +1,39 @@ +import BigInt + +enum DEX_VERSION: String { + case v1 = "v1" +} + +public enum STONFI_CONSTANTS { + public static var RouterAddress: String { + "0:779dcc815138d9500e449c5291e7f12738c23d575b5310000f6a253bd607384e" + } + + public static var TONProxyAddress: String { + "0:8cdc1d7640ad5ee326527fc1ad0514f468b30dc84b0173f0e155f451b4e11f7c" + } + + public enum SWAP_JETTON_TO_JETTON { + public static var GasAmount: BigUInt { + BigUInt("265000000") + } + public static var ForwardGasAmount: BigUInt { + BigUInt("205000000") + } + } + + public enum SWAP_JETTON_TO_TON { + public static var GasAmount: BigUInt { + BigUInt("185000000") + } + public static var ForwardGasAmount: BigUInt { + BigUInt("125000000") + } + } + + public enum SWAP_TON_TO_JETTON { + public static var ForwardGasAmount: BigUInt { + BigUInt("215000000") + } + } +} From 04d70cc9581e2ae61e170932ca23067988481617 Mon Sep 17 00:00:00 2001 From: Max Voloshinskii Date: Tue, 7 May 2024 12:23:55 +0300 Subject: [PATCH 2/3] Fixes after review --- Source/TonSwift/StonfiSwap/StonfiSwapData.swift | 7 ++++++- Source/TonSwift/Util/OpCodes.swift | 12 +++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Source/TonSwift/StonfiSwap/StonfiSwapData.swift b/Source/TonSwift/StonfiSwap/StonfiSwapData.swift index dcc9a21..820007f 100644 --- a/Source/TonSwift/StonfiSwap/StonfiSwapData.swift +++ b/Source/TonSwift/StonfiSwap/StonfiSwapData.swift @@ -27,7 +27,12 @@ public struct StonfiSwapData: CellCodable { let minAskAmount = try slice.loadCoins().amount let userWalletAddress: Address = try slice.loadType() - let referralAddress: Address? = try slice.loadType() + let withReferral = try slice.loadBoolean() + + var referralAddress: Address? = nil + if withReferral { + referralAddress = try slice.loadType() + } return StonfiSwapData(assetToSwap: assetToSwap, minAskAmount: minAskAmount, userWalletAddress: userWalletAddress, referralAddress: referralAddress) diff --git a/Source/TonSwift/Util/OpCodes.swift b/Source/TonSwift/Util/OpCodes.swift index 49b0bef..11b0dd6 100644 --- a/Source/TonSwift/Util/OpCodes.swift +++ b/Source/TonSwift/Util/OpCodes.swift @@ -1,13 +1,7 @@ import BigInt public enum OpCodes { - public static var JETTON_TRANSFER: BigInt { - BigInt(0xf8a7ea5) - } - public static var NFT_TRANSFER: BigInt { - BigInt(0x5fcc3d14) - } - public static var STONFI_SWAP: BigInt { - BigInt(0x25938561) - } + public static var JETTON_TRANSFER: Int32 = 0xf8a7ea5 + public static var NFT_TRANSFER: Int32 = 0x5fcc3d14 + public static var STONFI_SWAP: Int32 = 0x25938561 } From 616917fd709c189ec863ed510d83c85eb98a2843 Mon Sep 17 00:00:00 2001 From: Max Voloshinskii Date: Tue, 7 May 2024 12:24:46 +0300 Subject: [PATCH 3/3] Remove unnecessary import --- Source/TonSwift/Util/OpCodes.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/TonSwift/Util/OpCodes.swift b/Source/TonSwift/Util/OpCodes.swift index 11b0dd6..18a81b5 100644 --- a/Source/TonSwift/Util/OpCodes.swift +++ b/Source/TonSwift/Util/OpCodes.swift @@ -1,5 +1,3 @@ -import BigInt - public enum OpCodes { public static var JETTON_TRANSFER: Int32 = 0xf8a7ea5 public static var NFT_TRANSFER: Int32 = 0x5fcc3d14