blockchainethereumblockchain-walleterc20erc721walletxdaidappdecentralizederc1155erc875iosswifttokens
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.6 KiB
130 lines
3.6 KiB
import BigInt
|
|
import TrustKeystore
|
|
|
|
public struct Order {
|
|
var price: BigUInt
|
|
var indices: [UInt16]
|
|
var expiry: BigUInt
|
|
var contractAddress: String
|
|
//for mapping to server
|
|
var start: BigUInt
|
|
var count: Int
|
|
}
|
|
|
|
public struct SignedOrder {
|
|
var order: Order
|
|
var message: [UInt8]
|
|
var signature: String
|
|
}
|
|
|
|
extension String {
|
|
var hexa2Bytes: [UInt8] {
|
|
let hexa = Array(characters)
|
|
return stride(from: 0, to: count, by: 2).flatMap {
|
|
UInt8(String(hexa[$0..<$0.advanced(by: 2)]), radix: 16)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension BinaryInteger {
|
|
var data: Data {
|
|
var source = self
|
|
return Data(bytes: &source, count: MemoryLayout<Self>.size)
|
|
}
|
|
}
|
|
|
|
extension Data {
|
|
var array: [UInt8] {
|
|
return Array(self)
|
|
}
|
|
}
|
|
|
|
public class OrderHandler {
|
|
|
|
private let keyStore = try! EtherKeystore()
|
|
|
|
func signOrders(orders: [Order], account: Account) throws -> [SignedOrder] {
|
|
var signedOrders = [SignedOrder]()
|
|
var messages = [Data]()
|
|
|
|
for i in 0...orders.count - 1 {
|
|
let message: [UInt8] = encodeMessageForTrade(
|
|
price: orders[i].price,
|
|
expiryBuffer: orders[i].expiry,
|
|
tickets: orders[i].indices,
|
|
contractAddress: orders[i].contractAddress
|
|
)
|
|
messages.append(Data(bytes: message))
|
|
}
|
|
|
|
let signatures: [Data] = try! keyStore.signMessageBulk(messages, for: account).dematerialize()
|
|
|
|
for i in 0...signatures.count - 1 {
|
|
let signedOrder = SignedOrder(
|
|
order: orders[i],
|
|
message: messages[i].bytes,
|
|
signature: signatures[i].hexString
|
|
)
|
|
signedOrders.append(signedOrder)
|
|
}
|
|
return signedOrders
|
|
}
|
|
|
|
//buffer size is 84 + tickets
|
|
//first 32 bytes is allocated for price
|
|
//next 32 for expiry
|
|
//20 for contract address
|
|
//remaining for tickets
|
|
func encodeMessageForTrade(price: BigUInt,
|
|
expiryBuffer: BigUInt,
|
|
tickets: [UInt16],
|
|
contractAddress: String) -> [UInt8] {
|
|
//ticket count * 2 because it is 16 bits not 8
|
|
let arrayLength: Int = 84 + tickets.count * 2
|
|
var buffer = [UInt8]()
|
|
buffer.reserveCapacity(arrayLength)
|
|
|
|
var priceInWei = Array(price.serialize())
|
|
var expiry = Array(expiryBuffer.serialize())
|
|
for _ in 0...31 - priceInWei.count {
|
|
//pad with zeros
|
|
priceInWei.insert(0, at: 0)
|
|
}
|
|
for i in 0...31 {
|
|
buffer.append(priceInWei[i])
|
|
}
|
|
|
|
for _ in 0...31 - expiry.count {
|
|
expiry.insert(0, at: 0)
|
|
}
|
|
|
|
for i in 0...31 {
|
|
buffer.append(expiry[i])
|
|
}
|
|
//no leading zeros issue here
|
|
var contractAddr = contractAddress.hexa2Bytes
|
|
|
|
for i in 0...19 {
|
|
buffer.append(contractAddr[i])
|
|
}
|
|
|
|
var ticketsUint8 = OrderHandler.uInt16ArrayToUInt8(arrayOfUInt16: tickets)
|
|
|
|
for i in 0...ticketsUint8.count - 1 {
|
|
buffer.append(ticketsUint8[i])
|
|
}
|
|
|
|
return buffer
|
|
}
|
|
|
|
public static func uInt16ArrayToUInt8(arrayOfUInt16: [UInt16]) -> [UInt8] {
|
|
var arrayOfUint8 = [UInt8]()
|
|
for i in 0...arrayOfUInt16.count - 1 {
|
|
var UInt8ArrayPair = arrayOfUInt16[i].bigEndian.data.array
|
|
arrayOfUint8.append(UInt8ArrayPair[0])
|
|
arrayOfUint8.append(UInt8ArrayPair[1])
|
|
}
|
|
return arrayOfUint8
|
|
}
|
|
|
|
}
|
|
|