diff --git a/Source/TonSwift/Address/FriendlyAddress.swift b/Source/TonSwift/Address/FriendlyAddress.swift index c4c0ca2..4450ee5 100644 --- a/Source/TonSwift/Address/FriendlyAddress.swift +++ b/Source/TonSwift/Address/FriendlyAddress.swift @@ -89,7 +89,7 @@ public struct FriendlyAddress: Codable { var addrcrc = Data(count: 36) addrcrc[0...] = addr addrcrc[34...] = addr.crc16() - + if urlSafe { return addrcrc.base64EncodedString().replacingOccurrences(of: "+", with: "-").replacingOccurrences(of: "/", with: "_") } else { diff --git a/Source/TonSwift/Cells/Builder.swift b/Source/TonSwift/Cells/Builder.swift index 7f97be5..1207e83 100644 --- a/Source/TonSwift/Cells/Builder.swift +++ b/Source/TonSwift/Cells/Builder.swift @@ -523,4 +523,17 @@ public class Builder { } } + // MARK: Storing Address + + @discardableResult + public func store(address: Address?) throws -> Self { + if let address { + return try store(uint: 2, bits: 2) + .store(uint: 0, bits: 1) + .store(int: address.workchain, bits: 8) + .store(data: address.hash) + } else { + return try store(uint: 0, bits: 2) + } + } } diff --git a/Source/TonSwift/Contracts/Jetton/JettonMinter.swift b/Source/TonSwift/Contracts/Jetton/JettonMinter.swift new file mode 100644 index 0000000..c6ecd41 --- /dev/null +++ b/Source/TonSwift/Contracts/Jetton/JettonMinter.swift @@ -0,0 +1,79 @@ +// +// JettonMinter.swift +// +// +// Created by Kirill Kirilenko on 20/07/2023. +// + +import Foundation +import BigInt + +let jettonMinterBoc = "B5EE9C7241020B010001ED000114FF00F4A413F4BCF2C80B0102016202030202CC040502037A60090A03EFD9910E38048ADF068698180B8D848ADF07D201800E98FE99FF6A2687D007D206A6A18400AA9385D47181A9AA8AAE382F9702480FD207D006A18106840306B90FD001812881A28217804502A906428027D012C678B666664F6AA7041083DEECBEF29385D71811A92E001F1811802600271812F82C207F97840607080093DFC142201B82A1009AA0A01E428027D012C678B00E78B666491646580897A007A00658064907C80383A6465816503E5FFE4E83BC00C646582AC678B28027D0109E5B589666664B8FD80400FE3603FA00FA40F82854120870542013541403C85004FA0258CF1601CF16CCC922C8CB0112F400F400CB00C9F9007074C8CB02CA07CBFFC9D05008C705F2E04A12A1035024C85004FA0258CF16CCCCC9ED5401FA403020D70B01C3008E1F8210D53276DB708010C8CB055003CF1622FA0212CB6ACB1FCB3FC98042FB00915BE200303515C705F2E049FA403059C85004FA0258CF16CCCCC9ED54002E5143C705F2E049D43001C85004FA0258CF16CCCCC9ED54007DADBCF6A2687D007D206A6A183618FC1400B82A1009AA0A01E428027D012C678B00E78B666491646580897A007A00658064FC80383A6465816503E5FFE4E840001FAF16F6A2687D007D206A6A183FAA904051007F09" + +public class JettonMinter { + let cell: Cell + + init(bocString: String = jettonMinterBoc) throws { + cell = try Cell.fromBase64(src: bocString) + } + + func createDataCell( + owner: Address, + metadata: Cell, + jettonWalletCode: Cell + ) throws -> Cell { + try Builder() + .store(coins: .init(0)) // total supply + .store(address: owner) + .store(ref: metadata) + .store(ref: jettonWalletCode) + .endCell() + } + + func createMintBody( + destination: Address, + jettonAmount: BigInt, + amount: BigInt = 50000000, + queryId: Int = 0 + ) throws -> Cell { + try Builder() + .store(uint: 21, bits: 32) // OP-code mint + .store(uint: queryId, bits: 64) + .store(address: destination) + .store(coins: Coins(amount)) + .store( + ref: try Builder() + .store(uint: 0x178d4519, bits: 32) // OP-code transfer + .store(uint: queryId, bits: 64) + .store(coins: Coins(jettonAmount)) // jetton amount + .store(address: nil) // from_address + .store(address: nil) // response_address + .store(coins: .init(0)) // forward amount + .store(bit: .zero) // forward_payload in this slice, not separate cell + .endCell() + ) + .endCell() + } + + func createChangeAdminAddress( + newAdmin: Address, + queryId: Int = 0 + ) throws -> Cell { + try Builder() + .store(uint: 3, bits: 32) // OP-code + .store(uint: queryId, bits: 64) // query_id + .store(address: newAdmin) + .endCell() + } + + func createEditContent( + metadata: Cell, + queryId: Int = 0 + ) throws -> Cell { + try Builder() + .store(uint: 4, bits: 32) // OP-code + .store(uint: queryId, bits: 64) //query_id + .store(ref: metadata) + .endCell() + } +} diff --git a/Source/TonSwift/Contracts/Jetton/JettonWallet.swift b/Source/TonSwift/Contracts/Jetton/JettonWallet.swift new file mode 100644 index 0000000..4c08136 --- /dev/null +++ b/Source/TonSwift/Contracts/Jetton/JettonWallet.swift @@ -0,0 +1,54 @@ +// +// JettonWallet.swift +// +// +// Created by Kirill Kirilenko on 20/07/2023. +// + +import Foundation + +let jettonWalletBoc = "B5EE9C7241021201000328000114FF00F4A413F4BCF2C80B0102016202030202CC0405001BA0F605DA89A1F401F481F481A8610201D40607020148080900BB0831C02497C138007434C0C05C6C2544D7C0FC02F83E903E900C7E800C5C75C87E800C7E800C00B4C7E08403E29FA954882EA54C4D167C0238208405E3514654882EA58C511100FC02780D60841657C1EF2EA4D67C02B817C12103FCBC2000113E910C1C2EBCB853600201200A0B020120101101F500F4CFFE803E90087C007B51343E803E903E90350C144DA8548AB1C17CB8B04A30BFFCB8B0950D109C150804D50500F214013E809633C58073C5B33248B232C044BD003D0032C032483E401C1D3232C0B281F2FFF274013E903D010C7E801DE0063232C1540233C59C3E8085F2DAC4F3208405E351467232C7C6600C03F73B51343E803E903E90350C0234CFFE80145468017E903E9014D6F1C1551CDB5C150804D50500F214013E809633C58073C5B33248B232C044BD003D0032C0327E401C1D3232C0B281F2FFF274140371C1472C7CB8B0C2BE80146A2860822625A020822625A004AD822860822625A028062849F8C3C975C2C070C008E00D0E0F009ACB3F5007FA0222CF165006CF1625FA025003CF16C95005CC2391729171E25008A813A08208989680AA008208989680A0A014BCF2E2C504C98040FB001023C85004FA0258CF1601CF16CCC9ED5400705279A018A182107362D09CC8CB1F5230CB3F58FA025007CF165007CF16C9718018C8CB0524CF165006FA0215CB6A14CCC971FB0010241023000E10491038375F040076C200B08E218210D53276DB708010C8CB055008CF165004FA0216CB6A12CB1F12CB3FC972FB0093356C21E203C85004FA0258CF1601CF16CCC9ED5400DB3B51343E803E903E90350C01F4CFFE803E900C145468549271C17CB8B049F0BFFCB8B0A0822625A02A8005A805AF3CB8B0E0841EF765F7B232C7C572CFD400FE8088B3C58073C5B25C60063232C14933C59C3E80B2DAB33260103EC01004F214013E809633C58073C5B3327B55200083200835C87B51343E803E903E90350C0134C7E08405E3514654882EA0841EF765F784EE84AC7CB8B174CFCC7E800C04E81408F214013E809633C58073C5B3327B55205ECCF23D" + +public class JettonWallet { + let cell: Cell + + init(bocString: String = jettonWalletBoc) throws { + cell = try Cell.fromBase64(src: bocString) + } + + public func createTransfer( + to address: Address, + jettonAmount: Int, + forwardAmount: Int = 0, + forwardPayload: Bit? = nil, + responseAddress: Address? = nil, + queryId: Int = 0 + ) throws -> Cell { + let builder = try Builder() + .store(uint: 0xf8a7ea5, bits: 32) // request_transfer op + .store(uint: queryId, bits: 64) + .store(coins: .init(jettonAmount)) + .store(address: address) + .store(address: responseAddress ?? address) + .store(bit: 0) // custom_payload + .store(coins: .init(forwardAmount)) + if let forwardPayload { + try builder + .store(bit: forwardPayload) + } + return try builder.asCell() + } + + public func createBurn( + jettonAmount: Int, + responseAddress: Address? = nil, + queryId: Int = 0 + ) throws -> Cell { + try Builder() + .store(uint: 0x595f07bc, bits: 32) // burn OP + .store(uint: queryId, bits: 64) + .store(coins: .init(jettonAmount)) + .store(address: responseAddress) + .endCell() + } +}