|
|
|
@ -364,134 +364,6 @@ extension ActivitiesViewController { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
extension ActivitiesViewController.functional { |
|
|
|
|
static func extractTokenAndActivityName(fromTransactionRow transactionRow: TransactionRow, tokensStorages: ServerDictionary<TokensDataStore>, wallet: AlphaWallet.Address) -> (token: TokenObject, activityName: String)? { |
|
|
|
|
enum TokenOperation { |
|
|
|
|
case nativeCryptoTransfer(TokenObject) |
|
|
|
|
case completedTransfer(TokenObject) |
|
|
|
|
case pendingTransfer(TokenObject) |
|
|
|
|
case completedErc20Approval(TokenObject) |
|
|
|
|
case pendingErc20Approval(TokenObject) |
|
|
|
|
|
|
|
|
|
var token: TokenObject { |
|
|
|
|
switch self { |
|
|
|
|
case .nativeCryptoTransfer(let token): |
|
|
|
|
return token |
|
|
|
|
case .completedTransfer(let token): |
|
|
|
|
return token |
|
|
|
|
case .pendingTransfer(let token): |
|
|
|
|
return token |
|
|
|
|
case .completedErc20Approval(let token): |
|
|
|
|
return token |
|
|
|
|
case .pendingErc20Approval(let token): |
|
|
|
|
return token |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let erc20TokenOperation: TokenOperation? |
|
|
|
|
if transactionRow.operation == nil { |
|
|
|
|
erc20TokenOperation = .nativeCryptoTransfer(TokensDataStore.etherToken(forServer: transactionRow.server)) |
|
|
|
|
} else { |
|
|
|
|
switch (transactionRow.state, transactionRow.operation?.operationType) { |
|
|
|
|
case (.pending, .nativeCurrencyTokenTransfer), (.pending, .erc20TokenTransfer), (.pending, .erc721TokenTransfer), (.pending, .erc875TokenTransfer): |
|
|
|
|
erc20TokenOperation = transactionRow.operation?.contractAddress.flatMap { tokensStorages[transactionRow.server].token(forContract: $0) }.flatMap { TokenOperation.pendingTransfer($0) } |
|
|
|
|
case (.completed, .nativeCurrencyTokenTransfer), (.completed, .erc20TokenTransfer), (.completed, .erc721TokenTransfer), (.completed, .erc875TokenTransfer): |
|
|
|
|
erc20TokenOperation = transactionRow.operation?.contractAddress.flatMap { tokensStorages[transactionRow.server].token(forContract: $0) }.flatMap { TokenOperation.completedTransfer($0) } |
|
|
|
|
//Explicitly listing out combinations so future changes to enums will be caught by compiler |
|
|
|
|
case (.pending, .erc20TokenApprove): |
|
|
|
|
erc20TokenOperation = transactionRow.operation?.contractAddress.flatMap { tokensStorages[transactionRow.server].token(forContract: $0) }.flatMap { TokenOperation.pendingErc20Approval($0) } |
|
|
|
|
case (.completed, .erc20TokenApprove): |
|
|
|
|
erc20TokenOperation = transactionRow.operation?.contractAddress.flatMap { tokensStorages[transactionRow.server].token(forContract: $0) }.flatMap { TokenOperation.completedErc20Approval($0) } |
|
|
|
|
case (.unknown, _), (.error, _), (.failed, _), (_, .unknown), (.completed, .none), (.pending, nil): |
|
|
|
|
erc20TokenOperation = .none |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
guard let token = erc20TokenOperation?.token else { return nil } |
|
|
|
|
let activityName: String |
|
|
|
|
switch erc20TokenOperation { |
|
|
|
|
case .nativeCryptoTransfer, .completedTransfer, .pendingTransfer, .none: |
|
|
|
|
if wallet.sameContract(as: transactionRow.from) { |
|
|
|
|
activityName = "sent" |
|
|
|
|
} else { |
|
|
|
|
activityName = "received" |
|
|
|
|
} |
|
|
|
|
case .completedErc20Approval, .pendingErc20Approval: |
|
|
|
|
activityName = "ownerApproved" |
|
|
|
|
} |
|
|
|
|
return (token: token, activityName: activityName) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static func createPseudoActivity(fromTransactionRow transactionRow: TransactionRow, tokensStorages: ServerDictionary<TokensDataStore>, wallet: AlphaWallet.Address) -> Activity? { |
|
|
|
|
guard let (token, activityName) = extractTokenAndActivityName(fromTransactionRow: transactionRow, tokensStorages: tokensStorages, wallet: wallet) else { return nil } |
|
|
|
|
var cardAttributes = [AttributeId: AssetInternalValue]() |
|
|
|
|
cardAttributes["symbol"] = .string(transactionRow.server.symbol) |
|
|
|
|
|
|
|
|
|
if let operation = transactionRow.operation, operation.symbol != nil, let value = BigUInt(operation.value) { |
|
|
|
|
cardAttributes["amount"] = .uint(value) |
|
|
|
|
} else { |
|
|
|
|
if let value = BigUInt(transactionRow.value) { |
|
|
|
|
cardAttributes["amount"] = .uint(value) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if let value = AlphaWallet.Address(string: transactionRow.from) { |
|
|
|
|
cardAttributes["from"] = .address(value) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if let toString = transactionRow.operation?.to, let to = AlphaWallet.Address(string: toString) { |
|
|
|
|
cardAttributes["to"] = .address(to) |
|
|
|
|
} else { |
|
|
|
|
if let value = AlphaWallet.Address(string: transactionRow.to) { |
|
|
|
|
cardAttributes["to"] = .address(value) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var timestamp: GeneralisedTime = .init() |
|
|
|
|
timestamp.date = transactionRow.date |
|
|
|
|
cardAttributes["timestamp"] = .generalisedTime(timestamp) |
|
|
|
|
let state: Activity.State |
|
|
|
|
switch transactionRow.state { |
|
|
|
|
case .pending: |
|
|
|
|
state = .pending |
|
|
|
|
case .completed: |
|
|
|
|
state = .completed |
|
|
|
|
case .error, .failed: |
|
|
|
|
state = .failed |
|
|
|
|
//TODO we don't need the other states at the moment |
|
|
|
|
case .unknown: |
|
|
|
|
state = .completed |
|
|
|
|
} |
|
|
|
|
let rowType: ActivityRowType |
|
|
|
|
switch transactionRow { |
|
|
|
|
case .standalone: |
|
|
|
|
rowType = .standalone |
|
|
|
|
case .group: |
|
|
|
|
rowType = .group |
|
|
|
|
case .item: |
|
|
|
|
rowType = .item |
|
|
|
|
} |
|
|
|
|
return .init( |
|
|
|
|
//We only use this ID for refreshing the display of specific activity, since the display for ETH send/receives don't ever need to be refreshed, just need a number that don't clash with other activities |
|
|
|
|
id: transactionRow.blockNumber + 10000000, |
|
|
|
|
rowType: rowType, |
|
|
|
|
tokenObject: Activity.AssignedToken(tokenObject: token), |
|
|
|
|
server: transactionRow.server, |
|
|
|
|
name: activityName, |
|
|
|
|
eventName: activityName, |
|
|
|
|
blockNumber: transactionRow.blockNumber, |
|
|
|
|
transactionId: transactionRow.id, |
|
|
|
|
transactionIndex: transactionRow.transactionIndex, |
|
|
|
|
//We don't use this for transactions, so it's ok |
|
|
|
|
logIndex: 0, |
|
|
|
|
date: transactionRow.date, |
|
|
|
|
values: (token: .init(), card: cardAttributes), |
|
|
|
|
view: (html: "", style: ""), |
|
|
|
|
itemView: (html: "", style: ""), |
|
|
|
|
isBaseCard: true, |
|
|
|
|
state: state |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate static func headerView(for section: Int, viewModel: ActivitiesViewModel) -> UIView { |
|
|
|
|
let container = UIView() |
|
|
|
|
container.backgroundColor = viewModel.headerBackgroundColor |
|
|
|
|