An advanced Ethereum/EVM mobile wallet
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.
 
 
 
alpha-wallet-ios/AlphaWallet/Redeem/Helpers/CreateRedeem.swift

92 lines
3.3 KiB

//
// Created by James Sangalli on 2/3/18.
// Copyright © 2018 Stormbird PTE. LTD.
//
import Foundation
import BigInt
class CreateRedeem {
private let token: TokenObject
init(token: TokenObject) {
self.token = token
}
private func generateTimeStamp() -> String {
let time = NSDate().timeIntervalSince1970
//rotate qr every 30 seconds for security (preventing screenshot claims)
let minsTime = Int(time / 30)
return String(minsTime)
}
private func generateTimeStamp721Tickets() -> String {
let time = NSDate().timeIntervalSince1970
//use ten minute intervals
let minsTime = Int(time / 600)
return String(minsTime)
}
func redeemMessage(tokenIds: [BigUInt]) -> (message: String, qrCode: String) {
let contractAddress = token.contractAddress.eip55String.lowercased()
//TODO this only works with one token at a time
let tokensAsDecimalString = tokensToDecimalString(tokens: tokenIds)
var prefix = "0"
if tokensAsDecimalString.count < 10 {
prefix += ("0" + tokensAsDecimalString.count.description)
} else {
prefix += tokensAsDecimalString.count.description
}
let qrCodeData = prefix + tokensAsDecimalString
let messageForSigning = prefix + tokensToDecimalString(tokens: tokenIds)
+ "," + generateTimeStamp721Tickets() + "," + contractAddress
return (messageForSigning, qrCodeData)
}
func redeemMessage(indices: [UInt16]) -> (message: String, qrCode: String) {
let contractAddress = token.contractAddress.eip55String.lowercased()
let messageForSigning = formIndicesSelection(indices: indices)
+ "," + generateTimeStamp() + "," + contractAddress
let qrCodeData = formIndicesSelection(indices: indices)
return (messageForSigning, qrCodeData)
}
private func tokensToDecimalString(tokens: [BigUInt]) -> String {
//padding to 32 bytes can be done on the ushers side
return tokens.map({ $0.description }).joined(separator: ",")
}
private func formIndicesSelection(indices: [UInt16]) -> String {
let firstValue = indices[0] //lowest number
let NIBBLE = 4
let zeroCount = Int(firstValue) / NIBBLE
let correctionFactor = zeroCount * NIBBLE
/* the method here is easier to express with matrix programming like this:
indexList = indexList - correctionFactor # reduce every element of the list by an int
selection = sum(2^indexList) # raise every element and add the result back */
var bitFieldLookup = BigUInt(0)
for _ in 0...indices.count - 1 {
let adder = BigUInt(2).power(Int(indices[0]) - correctionFactor)
bitFieldLookup = bitFieldLookup.advanced(by: BigInt(adder))
}
let bitIntLength: Int = bitFieldLookup.description.count
var bitString = ""
if bitIntLength < 10 {
bitString = "0"
}
bitString += String(bitIntLength)
if zeroCount < 100 {
bitString += "0"
}
if zeroCount < 10 {
bitString += "0"
}
bitString += String(zeroCount)
bitString += String(bitFieldLookup)
return bitString
}
}