Skip to content

Commit

Permalink
Add Codable to Flow.Transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
lmcmz committed Jan 28, 2022
1 parent 8a0a716 commit a5f2851
Show file tree
Hide file tree
Showing 40 changed files with 585 additions and 303 deletions.
43 changes: 24 additions & 19 deletions Sources/Flow/Build/TransactionBuild.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ public func refBlock(text: () -> Flow.ID) -> Flow.TransactionBuild {
return Flow.TransactionBuild.refBlock(text())
}

extension Flow {
public extension Flow {
/// The list of all the acceptable property
public enum TransactionBuild {
enum TransactionBuild {
/// Cadence script
case script(Flow.Script)

Expand All @@ -186,7 +186,7 @@ extension Flow {

/// Use domain-specific language (DSL) to construct `Flow.Transaction`
@resultBuilder
public class TransactionBuilder {
enum TransactionBuilder {
public static func buildBlock() -> [Flow.TransactionBuild] { [] }

public static func buildArray(_ components: [[Flow.TransactionBuild]]) -> [Flow.TransactionBuild] {
Expand All @@ -199,14 +199,15 @@ extension Flow {
}
}

extension Flow {
public extension Flow {
/// Build flow transaction using `TransactionBuilder` with async way
/// - parameters:
/// - chainID: The chain id for the transaction, the default value is `flow.chainID`
/// - builder: The list of `Flow.TransactionBuild`
/// - returns: The type of `EventLoopFuture<Flow.Transaction>`
public func asyncBuildTransaction(chainID: Flow.ChainID = flow.chainID,
@Flow .TransactionBuilder builder: () -> [Flow.TransactionBuild]) throws -> EventLoopFuture<Flow.Transaction> {
func asyncBuildTransaction(chainID: Flow.ChainID = flow.chainID,
@Flow.TransactionBuilder builder: () -> [Flow.TransactionBuild]) throws -> EventLoopFuture<Flow.Transaction>
{
var script: Flow.Script = .init(data: Data())
var agrument: [Flow.Argument] = []
var authorizers: [Flow.Address] = []
Expand Down Expand Up @@ -300,8 +301,9 @@ extension Flow {
/// - chainID: The chain id for the transaction, the default value is `flow.chainID`
/// - builder: The list of `Flow.TransactionBuild`
/// - returns: The type of `Flow.Transaction`
public func buildTransaction(chainID: Flow.ChainID = flow.chainID,
@Flow .TransactionBuilder builder: () -> [Flow.TransactionBuild]) throws -> Flow.Transaction {
func buildTransaction(chainID: Flow.ChainID = flow.chainID,
@Flow.TransactionBuilder builder: () -> [Flow.TransactionBuild]) throws -> Flow.Transaction
{
return try asyncBuildTransaction(chainID: chainID, builder: builder).wait()
}

Expand All @@ -310,7 +312,7 @@ extension Flow {
/// - chainID: The chain id for the transaction, the default value is `flow.chainID`
/// - signedTransaction: The signed Flow transaction
/// - returns: A future value of transaction id
public func sendTransaction(chainID: ChainID = flow.chainID, signedTransaction: Transaction) throws -> EventLoopFuture<Flow.ID> {
func sendTransaction(chainID: ChainID = flow.chainID, signedTransaction: Transaction) throws -> EventLoopFuture<Flow.ID> {
let api = flow.createAccessAPI(chainID: chainID)
return api.sendTransaction(transaction: signedTransaction)
}
Expand All @@ -320,9 +322,10 @@ extension Flow {
/// - chainID: The chain id for the transaction, the default value is `flow.chainID`
/// - signedTransaction: The signed Flow transaction
/// - returns: The transaction id
public func sendTransactionWithWait(chainID: Flow.ChainID = flow.chainID,
signers: [FlowSigner],
@Flow .TransactionBuilder builder: () -> [Flow.TransactionBuild]) throws -> Flow.ID {
func sendTransactionWithWait(chainID: Flow.ChainID = flow.chainID,
signers: [FlowSigner],
@Flow.TransactionBuilder builder: () -> [Flow.TransactionBuild]) throws -> Flow.ID
{
return try flow.sendTransaction(chainID: chainID,
signers: signers,
builder: builder).wait()
Expand All @@ -334,9 +337,10 @@ extension Flow {
/// - signers: A list of `FlowSigner`, which will sign the transaction
/// - builder: The list of `Flow.TransactionBuild`
/// - returns: The transaction id
public func sendTransaction(chainID: Flow.ChainID = flow.chainID,
signers: [FlowSigner],
@Flow .TransactionBuilder builder: () -> [Flow.TransactionBuild]) throws -> EventLoopFuture<Flow.ID> {
func sendTransaction(chainID: Flow.ChainID = flow.chainID,
signers: [FlowSigner],
@Flow.TransactionBuilder builder: () -> [Flow.TransactionBuild]) throws -> EventLoopFuture<Flow.ID>
{
let api = flow.createAccessAPI(chainID: chainID)
let unsignedTx = try buildTransaction(chainID: chainID, builder: builder)
let signedTx = try flow.signTransaction(unsignedTransaction: unsignedTx, signers: signers)
Expand All @@ -350,10 +354,11 @@ extension Flow {
/// - signers: A list of `FlowSigner`, which will sign the transaction
/// - builder: The list of `Flow.TransactionBuild`
/// - completion: The block to handle the response
public func sendTransaction(chainID: Flow.ChainID = flow.chainID,
signers: [FlowSigner],
@Flow .TransactionBuilder builder: () -> [Flow.TransactionBuild],
completion: @escaping (Result<Flow.ID, Error>) -> Void) throws {
func sendTransaction(chainID: Flow.ChainID = flow.chainID,
signers: [FlowSigner],
@Flow.TransactionBuilder builder: () -> [Flow.TransactionBuild],
completion: @escaping (Result<Flow.ID, Error>) -> Void) throws
{
let api = flow.createAccessAPI(chainID: chainID)
let unsignedTx = try buildTransaction(chainID: chainID, builder: builder)
let signedTx = try flow.signTransaction(unsignedTransaction: unsignedTx, signers: signers)
Expand Down
61 changes: 34 additions & 27 deletions Sources/Flow/Cadence/CommonCadence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import NIO
extension Flow {
/// A collection of common operations in Flow
/// It includes `addKeyToAccount`, `addContractToAccount`, `createAccount`, `removeAccountKeyByIndex`, `removeContractFromAccount`, `updateContractOfAccount`
class CommonCadence {
enum CommonCadence {
/// The cadence code for adding key to account
static let addKeyToAccount = """
transaction(publicKey: String) {
Expand Down Expand Up @@ -134,14 +134,14 @@ extension Flow {
}
}

extension Flow {
public extension Flow {
/// Add public key to account
/// - parameters:
/// - address: The address of Account in `Flow.Address` type.
/// - accountKey: The public key to be added in `Flow.AccountKey` type.
/// - signers: A list of `FlowSigner` will sign the transaction.
/// - returns: A future value will receive transaction id in `Flow.ID` value.
public func addKeyToAccount(address: Flow.Address, accountKey: Flow.AccountKey, signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID> {
func addKeyToAccount(address: Flow.Address, accountKey: Flow.AccountKey, signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID> {
guard let encodedKey = accountKey.encoded else {
let promise = flow.accessAPI.clientChannel.eventLoop.makePromise(of: Flow.ID.self)
promise.fail(Flow.FError.encodeFailure)
Expand Down Expand Up @@ -171,10 +171,11 @@ extension Flow {
/// - code: Cadence code of the contract.
/// - signers: A list of `FlowSigner` will sign the transaction.
/// - returns: A future value will receive transaction id in `Flow.ID` value.
public func addContractToAccount(address: Flow.Address,
contractName: String,
code: String,
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID> {
func addContractToAccount(address: Flow.Address,
contractName: String,
code: String,
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID>
{
let script = Flow.Script(text: code)
return try sendTransaction(signers: signers) {
cadence {
Expand All @@ -199,10 +200,11 @@ extension Flow {
/// - contracts: A collection of cadence contracts, contract name is the `key`, cadence code is the `value`.
/// - signers: A list of `FlowSigner` will sign the transaction.
/// - returns: A future value will receive transaction id in `Flow.ID` value.
public func createAccount(address: Flow.Address,
publicKeys: [Flow.AccountKey],
contracts: [String: String] = [:],
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID> {
func createAccount(address: Flow.Address,
publicKeys: [Flow.AccountKey],
contracts: [String: String] = [:],
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID>
{
let contractArg = contracts.compactMap { name, cadence in
Flow.Argument.Dictionary(key: .init(value: .string(name)),
value: .init(value: .string(Flow.Script(text: cadence).hex)))
Expand Down Expand Up @@ -233,9 +235,10 @@ extension Flow {
/// - contracts: A collection of cadence contracts, contract name is the `key`, cadence code is the `value`.
/// - signers: A list of `FlowSigner` will sign the transaction.
/// - returns: A future value will receive transaction id in `Flow.ID` value.
public func removeAccountKeyByIndex(address: Flow.Address,
keyIndex: Int,
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID> {
func removeAccountKeyByIndex(address: Flow.Address,
keyIndex: Int,
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID>
{
return try sendTransaction(signers: signers) {
cadence {
CommonCadence.removeAccountKeyByIndex
Expand All @@ -252,9 +255,10 @@ extension Flow {
}
}

public func removeContractFromAccount(address: Flow.Address,
contractName: String,
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID> {
func removeContractFromAccount(address: Flow.Address,
contractName: String,
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID>
{
return try sendTransaction(signers: signers) {
cadence {
CommonCadence.removeContractFromAccount
Expand All @@ -271,10 +275,11 @@ extension Flow {
}
}

public func updateContractOfAccount(address: Flow.Address,
contractName: String,
script: String,
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID> {
func updateContractOfAccount(address: Flow.Address,
contractName: String,
script: String,
signers: [FlowSigner]) throws -> EventLoopFuture<Flow.ID>
{
return try sendTransaction(signers: signers) {
cadence {
CommonCadence.updateContractOfAccount
Expand All @@ -291,8 +296,9 @@ extension Flow {
}
}

public func verifyUserSignature(message: String,
signatures: [Flow.TransactionSignature]) throws -> EventLoopFuture<Flow.ScriptResponse> {
func verifyUserSignature(message: String,
signatures: [Flow.TransactionSignature]) throws -> EventLoopFuture<Flow.ScriptResponse>
{
let futures: [EventLoopFuture<Flow.Account>] = signatures.compactMap { signature in
flow.accessAPI.getAccountAtLatestBlock(address: signature.address).unwrap(orError: FError.invaildAccountInfo)
}
Expand All @@ -315,7 +321,8 @@ extension Flow {
var publicKeys: [Flow.Cadence.FValue] = []
signatures.forEach { sig in
if let account = accounts.first(where: { $0.address == sig.address }),
let key = account.keys[safe: sig.keyIndex] {
let key = account.keys[safe: sig.keyIndex]
{
weights.append(.ufix64(Double(key.weight)))
signAlgos.append(.uint(UInt(key.signAlgo.code)))
sigs.append(.string(sig.signature.hexValue))
Expand All @@ -327,10 +334,10 @@ extension Flow {
.array(publicKeys.toArguments()),
.array(weights.toArguments()),
.array(signAlgos.toArguments()),
.array(sigs.toArguments()),].toArguments()
.array(sigs.toArguments())].toArguments()
return flow.accessAPI.executeScriptAtLatestBlock(script:
Flow.Script(text: CommonCadence.verifyUserSignature),
arguments: arguments)
Flow.Script(text: CommonCadence.verifyUserSignature),
arguments: arguments)
}
}
}
4 changes: 2 additions & 2 deletions Sources/Flow/Error/FlowError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

import Foundation

extension Flow {
public extension Flow {
/// List of common error in Flow Swift SDK
public enum FError: String, Error {
enum FError: String, Error {
case generic
case urlEmpty
case urlInvaild
Expand Down
4 changes: 2 additions & 2 deletions Sources/Flow/Extension/Array.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ extension Array where Iterator.Element: Hashable {
}
}

extension Array where Element == Flow.Cadence.FValue {
public func toArguments() -> [Flow.Argument] {
public extension Array where Element == Flow.Cadence.FValue {
func toArguments() -> [Flow.Argument] {
return compactMap(Flow.Argument.init)
}
}
32 changes: 17 additions & 15 deletions Sources/Flow/Extension/Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,19 @@ extension Collection {
}
}

extension Array where Element == UInt8 {
public extension Array where Element == UInt8 {
/// Convert to `Data` type
var data: Data { .init(self) }
internal var data: Data { .init(self) }

/// Convert bytes to hex string
public var hexValue: String { map { .init(format: "%02x", $0) }.joined() }
var hexValue: String { map { .init(format: "%02x", $0) }.joined() }

/// Mutate data with adding zero padding to the left until fulfil the block size
/// - parameters:
/// - blockSize: The size of block.
/// - returns: self in `Data` type.
public mutating func padZeroLeft(blockSize: Int) -> [UInt8] {
@discardableResult
mutating func padZeroLeft(blockSize: Int) -> [UInt8] {
while count < blockSize {
insert(0, at: 0)
}
Expand All @@ -47,7 +48,8 @@ extension Array where Element == UInt8 {
/// - parameters:
/// - blockSize: The size of block.
/// - returns: self in `Data` type.
public mutating func padZeroRight(blockSize: Int) -> [UInt8] {
@discardableResult
mutating func padZeroRight(blockSize: Int) -> [UInt8] {
while count < blockSize {
append(0)
}
Expand All @@ -58,7 +60,7 @@ extension Array where Element == UInt8 {
/// - parameters:
/// - blockSize: The size of block.
/// - returns: A new `[UInt8]` type with padding zero.
public func paddingZeroLeft(blockSize: Int) -> [UInt8] {
func paddingZeroLeft(blockSize: Int) -> [UInt8] {
var bytes = self
while bytes.count < blockSize {
bytes.insert(0, at: 0)
Expand All @@ -70,7 +72,7 @@ extension Array where Element == UInt8 {
/// - parameters:
/// - blockSize: The size of block.
/// - returns: A new `[UInt8]` type with padding zero.
public func paddingZeroRight(blockSize: Int) -> [UInt8] {
func paddingZeroRight(blockSize: Int) -> [UInt8] {
var bytes = self
while bytes.count < blockSize {
bytes.append(0)
Expand All @@ -79,14 +81,14 @@ extension Array where Element == UInt8 {
}
}

extension Data {
public extension Data {
/// Convert data to list of byte
var bytes: Bytes {
internal var bytes: Bytes {
return Bytes(self)
}

/// Initial the data with hex string
static func fromHex(_ hex: String) -> Data? {
internal static func fromHex(_ hex: String) -> Data? {
let string = hex.lowercased().stripHexPrefix()
guard let array = string.data(using: .utf8)?.bytes else {
return nil
Expand All @@ -102,15 +104,15 @@ extension Data {
}

/// Convert data to hex string
public var hexValue: String {
var hexValue: String {
return reduce("") { $0 + String(format: "%02x", $1) }
}

/// Mutate data with adding zero padding to the left until fulfil the block size
/// - parameters:
/// - blockSize: The size of block.
/// - returns: self in `Data` type.
public mutating func padZeroLeft(blockSize: Int) -> Data {
mutating func padZeroLeft(blockSize: Int) -> Data {
while count < blockSize {
insert(0, at: 0)
}
Expand All @@ -121,7 +123,7 @@ extension Data {
/// - parameters:
/// - blockSize: The size of block.
/// - returns: self in `Data` type.
public mutating func padZeroRight(blockSize: Int) -> Data {
mutating func padZeroRight(blockSize: Int) -> Data {
while count < blockSize {
append(0)
}
Expand All @@ -132,7 +134,7 @@ extension Data {
/// - parameters:
/// - blockSize: The size of block.
/// - returns: A new `Data` type with padding zero.
public func paddingZeroLeft(blockSize: Int) -> Data {
func paddingZeroLeft(blockSize: Int) -> Data {
var bytes = self
while bytes.count < blockSize {
bytes.insert(0, at: 0)
Expand All @@ -144,7 +146,7 @@ extension Data {
/// - parameters:
/// - blockSize: The size of block.
/// - returns: A new `Data` type with padding zero.
public func paddingZeroRight(blockSize: Int) -> Data {
func paddingZeroRight(blockSize: Int) -> Data {
var bytes = self
while bytes.count < blockSize {
bytes.append(0)
Expand Down
Loading

0 comments on commit a5f2851

Please sign in to comment.