Merge branch 'master' into remove-unnecessary-arg-in-xmlhandler-getName

pull/634/head
James Sangalli 6 years ago committed by GitHub
commit a74d053b5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 70
      AlphaWallet/AssetDefinition/XMLHandler.swift
  2. 65
      AlphaWallet/Localization/en.lproj/Localizable.strings
  3. 65
      AlphaWallet/Localization/es.lproj/Localizable.strings
  4. 65
      AlphaWallet/Localization/zh-Hans.lproj/Localizable.strings
  5. 15
      AlphaWallet/Market/Coordinators/UniversalLinkCoordinator.swift
  6. 13
      AlphaWallet/Market/ViewControllers/ImportMagicTokenViewController.swift
  7. 6
      AlphaWallet/Market/ViewControllers/ImportTokenViewController.swift
  8. 5
      AlphaWallet/Market/ViewModels/ImportMagicTokenViewControllerViewModel.swift
  9. 10
      AlphaWallet/Models/Ether.swift
  10. 3
      AlphaWallet/Redeem/ViewControllers/RedeemTokenCardQuantitySelectionViewController.swift
  11. 3
      AlphaWallet/Redeem/ViewControllers/RedeemTokenViewController.swift
  12. 3
      AlphaWallet/Redeem/ViewControllers/TokenCardRedemptionViewController.swift
  13. 6
      AlphaWallet/Redeem/ViewModels/RedeemTokenCardQuantitySelectionViewModel.swift
  14. 3
      AlphaWallet/Redeem/ViewModels/RedeemTokenCardViewModel.swift
  15. 6
      AlphaWallet/Sell/ViewControllers/EnterSellTokensCardPriceQuantityViewController.swift
  16. 3
      AlphaWallet/Sell/ViewControllers/SellTokensCardViewController.swift
  17. 8
      AlphaWallet/Sell/ViewModels/EnterSellTokensCardPriceQuantityViewControllerViewModel.swift
  18. 11
      AlphaWallet/Sell/ViewModels/GenerateSellMagicLinkViewControllerViewModel.swift
  19. 6
      AlphaWallet/Sell/ViewModels/GenerateTransferMagicLinkViewControllerViewModel.swift
  20. 3
      AlphaWallet/Sell/ViewModels/SellTokensCardViewModel.swift
  21. 17
      AlphaWallet/Sell/ViewModels/SetSellTokensCardExpiryDateViewControllerViewModel.swift
  22. 35
      AlphaWallet/Settings/Types/Config.swift
  23. 9
      AlphaWallet/Settings/Types/Constants.swift
  24. 2
      AlphaWallet/Tokens/Types/Token.swift
  25. 6
      AlphaWallet/Tokens/Types/TokensDataStore.swift
  26. 2
      AlphaWallet/Tokens/Types/Web3Error.swift
  27. 2
      AlphaWallet/Tokens/ViewModels/EditTokenViewModel.swift
  28. 27
      AlphaWallet/Tokens/ViewModels/TokensViewModel.swift
  29. 11
      AlphaWallet/Transfer/Coordinators/TransferNFTCoordinator.swift
  30. 3
      AlphaWallet/Transfer/ViewControllers/TransferTokensCardQuantitySelectionViewController.swift
  31. 3
      AlphaWallet/Transfer/ViewControllers/TransferTokensCardViewController.swift
  32. 3
      AlphaWallet/Transfer/ViewModels/ChooseTokenCardTransferModeViewControllerViewModel.swift
  33. 3
      AlphaWallet/Transfer/ViewModels/SetTransferTokensCardExpiryDateViewControllerViewModel.swift
  34. 6
      AlphaWallet/Transfer/ViewModels/TransferTokensCardQuantitySelectionViewModel.swift
  35. 3
      AlphaWallet/Transfer/ViewModels/TransferTokensCardViaWalletAddressViewControllerViewModel.swift
  36. 3
      AlphaWallet/Transfer/ViewModels/TransferTokensCardViewModel.swift
  37. 2
      AlphaWalletTests/Market/UniversalLinkHandlerTests.swift
  38. 2
      AlphaWalletTests/Market/ViewControllers/ImportTokenViewControllerTests.swift
  39. 5
      AlphaWalletTests/Models/EtherTests.swift
  40. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.EnterSellTokensCardPriceQuantityViewControllerTests/testSellTokensCardPriceQuantityViewControllerDisplay_iPhone11_3_320x568@2x.png
  41. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.EnterSellTokensCardPriceQuantityViewControllerTests/testSellTokensCardPriceQuantityViewControllerDisplay_iPhone11_3_375x812@3x.png
  42. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.EnterSellTokensCardPriceQuantityViewControllerTests/testSellTokensCardPriceQuantityViewControllerDisplay_iPhone11_4_375x812@3x.png
  43. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.ImportTokenViewControllerTests/testImportTokenViewControllerDisplay_iPhone11_3_320x568@2x.png
  44. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.ImportTokenViewControllerTests/testImportTokenViewControllerDisplay_iPhone11_3_375x812@3x.png
  45. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.ImportTokenViewControllerTests/testImportTokenViewControllerDisplay_iPhone11_4_375x812@3x.png
  46. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.TransferTokensCardQuantitySelectionViewControllerTests/testTransferTokensCardQuantitySelectionViewControllerCanBeCreated_iPhone11_3_320x568@2x.png
  47. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.TransferTokensCardQuantitySelectionViewControllerTests/testTransferTokensCardQuantitySelectionViewControllerCanBeCreated_iPhone11_3_375x812@3x.png
  48. BIN
      AlphaWalletTests/Snapshots/ReferenceImage_64/AlphaWalletTests.TransferTokensCardQuantitySelectionViewControllerTests/testTransferTokensCardQuantitySelectionViewControllerCanBeCreated_iPhone11_4_375x812@3x.png
  49. 3
      AlphaWalletTests/Transfer/ViewControllers/TransferTokensCardQuantitySelectionViewControllerTests.swift

@ -10,6 +10,15 @@ import SwiftyXMLParser
import BigInt import BigInt
import TrustKeystore import TrustKeystore
enum SingularOrPlural {
case singular
case plural
}
enum TitlecaseOrNot {
case titlecase
case notTitlecase
}
// Interface to extract data from non fungible token // Interface to extract data from non fungible token
private class PrivateXMLHandler { private class PrivateXMLHandler {
@ -74,11 +83,61 @@ private class PrivateXMLHandler {
func getName() -> String { func getName() -> String {
let lang = getLang() let lang = getLang()
if let name = contract?["name"].getElementWithLangAttribute(equals: lang)?.text { if let name = contract?["name"].getElementWithLangAttribute(equals: lang)?.text {
if contractAddress.sameContract(as: Constants.ticketContractAddress) || contractAddress.sameContract(as: Constants.ticketContractAddressRopsten ) {
return "\(Constants.fifaWorldCup2018TokenNamePrefix) \(name)"
}
return name return name
} }
return "N/A" return "N/A"
} }
func getTokenTypeName(_ type: SingularOrPlural = .plural, titlecase: TitlecaseOrNot = .titlecase) -> String {
if contractAddress.sameContract(as: Constants.ticketContractAddress) || contractAddress.sameContract(as: Constants.ticketContractAddressRopsten) {
switch type {
case .singular:
switch titlecase {
case .titlecase:
return R.string.localizable.ticketTitlecase()
case .notTitlecase:
return R.string.localizable.ticketLowercase()
}
case .plural:
switch titlecase {
case .titlecase:
return R.string.localizable.ticketsTitlecase()
case .notTitlecase:
return R.string.localizable.ticketsLowercase()
}
}
}
if contractAddress.sameContract(as: Constants.cryptoKittiesContractAddress) {
switch titlecase {
case .titlecase:
return R.string.localizable.cryptokittiesTitlecase()
case .notTitlecase:
return R.string.localizable.cryptokittiesLowercase()
}
}
//TODO read from XML (and programatically titlecase if necessary) and fallback if missing
switch type {
case .singular:
switch titlecase {
case .titlecase:
return R.string.localizable.tokenTitlecase()
case .notTitlecase:
return R.string.localizable.tokenLowercase()
}
case .plural:
switch titlecase {
case .titlecase:
return R.string.localizable.tokensTitlecase()
case .notTitlecase:
return R.string.localizable.tokensLowercase()
}
}
}
private func getLang() -> String { private func getLang() -> String {
let lang = Locale.preferredLanguages[0] let lang = Locale.preferredLanguages[0]
if lang.hasPrefix("en") { if lang.hasPrefix("en") {
@ -142,6 +201,15 @@ public class XMLHandler {
return privateXMLHandler.getName() return privateXMLHandler.getName()
} }
/// Expected to return names like "cryptokitties", "tickets" that are specified in the asset definition. If absent, fallback to "tokens"
func getTokenTypeName(_ type: SingularOrPlural = .plural, titlecase: TitlecaseOrNot = .titlecase) -> String {
return privateXMLHandler.getTokenTypeName(type, titlecase: titlecase)
}
func getLang() -> String {
return privateXMLHandler.getLang()
}
func getIssuer() -> String { func getIssuer() -> String {
return privateXMLHandler.getIssuer() return privateXMLHandler.getIssuer()
} }

@ -101,7 +101,16 @@
"settings.wallets.button.title" = "Wallets"; "settings.wallets.button.title" = "Wallets";
"Symbol" = "Symbol"; "Symbol" = "Symbol";
"Today" = "Today"; "Today" = "Today";
"Tokens" = "Tokens"; "token.lowercase" = "token";
"token.titlecase" = "Token";
"tokens.lowercase" = "tokens";
"tokens.titlecase" = "Tokens";
"ticket.lowercase" = "ticket";
"ticket.titlecase" = "Ticket";
"tickets.lowercase" = "tickets";
"tickets.titlecase" = "Tickets";
"cryptokitties.lowercase" = "cryptokitties";
"cryptokitties.titlecase" = "Cryptokitties";
"tokens.newtoken.navigation.title" = "Add Custom Token"; "tokens.newtoken.navigation.title" = "Add Custom Token";
"transaction.cell.error.title" = "Error"; "transaction.cell.error.title" = "Error";
"transaction.cell.received.title" = "Received"; "transaction.cell.received.title" = "Received";
@ -150,31 +159,31 @@
"a.wallet.ticketToken.unverifiedContract" = "UNVERIFIED"; "a.wallet.ticketToken.unverifiedContract" = "UNVERIFIED";
"a.wallet.ticketToken.match.vs" = "%@-%@"; "a.wallet.ticketToken.match.vs" = "%@-%@";
"a.wallet.ticketToken.redeem.button.title" = "Redeem"; "a.wallet.ticketToken.redeem.button.title" = "Redeem";
"a.wallet.ticketToken.redeem.selectTickets.title" = "Select Tickets To Redeem:"; "a.wallet.ticketToken.redeem.selectTickets.title" = "Select %@ To Redeem:";
"a.wallet.ticketToken.redeem.selectTicketQuantity.atLeastOne.title" = "Please select quantity of tickets"; "a.wallet.ticketToken.redeem.selectTicketQuantity.atLeastOne.title" = "Please select quantity of %@";
"a.wallet.ticketToken.redeem.selectTickets.atLeastOne.title" = "Please select a ticket to redeem"; "a.wallet.ticketToken.redeem.selectTickets.atLeastOne.title" = "Please select a %@ to redeem";
"a.wallet.ticketToken.redeem.selectQuantity.title" = "Select Quantity of Tickets"; "a.wallet.ticketToken.redeem.selectQuantity.title" = "Select Quantity of %@";
"a.wallet.ticketToken.redeem.quantity.title" = "QUANTITY OF TICKETS"; "a.wallet.ticketToken.redeem.quantity.title" = "QUANTITY OF %@";
"a.wallet.ticketToken.redeem.showQRCode.title" = "Show QR Code to Redemption Booth"; "a.wallet.ticketToken.redeem.showQRCode.title" = "Show QR Code to Redemption Booth";
"a.wallet.ticketToken.redeem.successful.title" = "Congrats"; "a.wallet.ticketToken.redeem.successful.title" = "Congrats";
"a.wallet.ticketToken.redeem.successful.description" = "You have successfully redeemed your ticket(s)"; "a.wallet.ticketToken.redeem.successful.description" = "You have successfully redeemed your %@";
"a.wallet.ticketToken.sell.button.title" = "Sell"; "a.wallet.ticketToken.sell.button.title" = "Sell";
"a.wallet.ticketToken.sell.selectTickets.title" = "Select Tickets To Sell:"; "a.wallet.ticketToken.sell.selectTickets.title" = "Select %@ To Sell:";
"a.wallet.ticketToken.sell.selectTicketQuantity.atLeastOne.title" = "Please select quantity of tickets"; "a.wallet.ticketToken.sell.selectTicketQuantity.atLeastOne.title" = "Please select quantity of %@";
"a.wallet.ticketToken.sell.price.provide.title" = "Please enter price of tickets"; "a.wallet.ticketToken.sell.price.provide.title" = "Please enter price of %@";
"a.wallet.ticketToken.sell.selectTickets.atLeastOne.title" = "Please select a ticket to sell"; "a.wallet.ticketToken.sell.selectTickets.atLeastOne.title" = "Please select a %@ to sell";
"a.wallet.ticketToken.sell.selectQuantity.title" = "Set a Price"; "a.wallet.ticketToken.sell.selectQuantity.title" = "Set a Price";
"a.wallet.ticketToken.sell.pricePerTicket.title" = "PRICE PER TICKET"; "a.wallet.ticketToken.sell.pricePerTicket.title" = "PRICE PER %@";
"a.wallet.ticketToken.sell.dollarCostLabel.title" = "EQUIVALENT IN USD"; "a.wallet.ticketToken.sell.dollarCostLabel.title" = "EQUIVALENT IN USD";
"a.wallet.ticketToken.sell.quantity.title" = "QUANTITY OF TICKETS"; "a.wallet.ticketToken.sell.quantity.title" = "QUANTITY OF %@";
"a.wallet.ticketToken.sell.enterLinkExpiryDate.title" = "Set MagicLink Expiry"; "a.wallet.ticketToken.sell.enterLinkExpiryDate.title" = "Set MagicLink Expiry";
"a.wallet.ticketToken.sell.singleTicketSelected.title" = "1 Ticket Selected"; "a.wallet.ticketToken.sell.singleTicketSelected.title" = "1 %@ Selected";
"a.wallet.ticketToken.sell.multipleTicketSelected.title" = "%d Tickets Selected"; "a.wallet.ticketToken.sell.multipleTicketSelected.title" = "%d %@ Selected";
"a.wallet.ticketToken.sell.perTicketEthPrice.title" = "%@ ETH/Ticket"; "a.wallet.ticketToken.sell.perTicketEthPrice.title" = "%@ ETH/%@";
"a.wallet.ticketToken.sell.totalEthPrice.title" = "Total: %@ ETH"; "a.wallet.ticketToken.sell.totalEthPrice.title" = "Total: %@ ETH";
"a.wallet.ticketToken.sell.magicLinkDescription.title" = "A MagicLink will be created to allow buyers to purchase your tickets."; "a.wallet.ticketToken.sell.magicLinkDescription.title" = "A MagicLink will be created to allow buyers to purchase your %@.";
"a.wallet.ticketToken.sell.noteTitleLabel.title" = "IMPORTANT"; "a.wallet.ticketToken.sell.noteTitleLabel.title" = "IMPORTANT";
"a.wallet.ticketToken.sell.noteLabel.title" = "Before the link expires, anyone with the MagicLink can purchase your tickets with one click"; "a.wallet.ticketToken.sell.noteLabel.title" = "Before the link expires, anyone with the MagicLink can purchase your %@ with one click";
"a.wallet.ticketToken.sell.linkExpiryDate.title" = "LINK EXPIRY DATE"; "a.wallet.ticketToken.sell.linkExpiryDate.title" = "LINK EXPIRY DATE";
"a.wallet.ticketToken.sell.linkExpiryTime.title" = "LINK EXPIRY TIME"; "a.wallet.ticketToken.sell.linkExpiryTime.title" = "LINK EXPIRY TIME";
"a.wallet.ticketToken.sell.linkExpiryTime.atLeastNow.title" = "Please select a date in the future"; "a.wallet.ticketToken.sell.linkExpiryTime.atLeastNow.title" = "Please select a date in the future";
@ -184,14 +193,14 @@
"a.wallet.ticketToken.sell.confirm.cancel.button.title" = "Cancel"; "a.wallet.ticketToken.sell.confirm.cancel.button.title" = "Cancel";
"a.wallet.ticketToken.sell.confirm.button.title" = "Share MagicLink"; "a.wallet.ticketToken.sell.confirm.button.title" = "Share MagicLink";
"a.wallet.ticketToken.sell.confirm.expiryDateDescription" = "MagicLink expires on: %@"; "a.wallet.ticketToken.sell.confirm.expiryDateDescription" = "MagicLink expires on: %@";
"a.wallet.ticketToken.sell.confirm.singleTicketSelected.title" = "1 Ticket"; "a.wallet.ticketToken.sell.confirm.singleTicketSelected.title" = "1 %@";
"a.wallet.ticketToken.sell.confirm.multipleTicketSelected.title" = "%d Tickets"; "a.wallet.ticketToken.sell.confirm.multipleTicketSelected.title" = "%d %@";
"a.wallet.ticketToken.transfer.button.title" = "Transfer"; "a.wallet.ticketToken.transfer.button.title" = "Transfer";
"a.wallet.ticketToken.transfer.selectTickets.title" = "Select Tickets To Transfer:"; "a.wallet.ticketToken.transfer.selectTickets.title" = "Select %@ To Transfer:";
"a.wallet.ticketToken.transfer.selectTicketQuantity.atLeastOne.title" = "Please select quantity of tickets"; "a.wallet.ticketToken.transfer.selectTicketQuantity.atLeastOne.title" = "Please select quantity of %@";
"a.wallet.ticketToken.transfer.selectTickets.atLeastOne.title" = "Please select a ticket to transfer"; "a.wallet.ticketToken.transfer.selectTickets.atLeastOne.title" = "Please select a %@ to transfer";
"a.wallet.ticketToken.transfer.selectQuantity.title" = "Transfer Tickets"; "a.wallet.ticketToken.transfer.selectQuantity.title" = "Transfer %@";
"a.wallet.ticketToken.transfer.quantity.title" = "QUANTITY OF TICKETS"; "a.wallet.ticketToken.transfer.quantity.title" = "QUANTITY OF %@";
"a.wallet.ticketToken.transfer.mode.magicLink.button.title" = "MagicLink for Picking Up"; "a.wallet.ticketToken.transfer.mode.magicLink.button.title" = "MagicLink for Picking Up";
"a.wallet.ticketToken.transfer.mode.now.button.title" = "Transfer now"; "a.wallet.ticketToken.transfer.mode.now.button.title" = "Transfer now";
"a.wallet.ticketToken.transfer.confirm.title" = "Generate MagicLink"; "a.wallet.ticketToken.transfer.confirm.title" = "Generate MagicLink";
@ -201,9 +210,9 @@
"a.wallet.ticketToken.transfer.linkExpiryTime.atLeastNow.title" = "Please select a date in the future"; "a.wallet.ticketToken.transfer.linkExpiryTime.atLeastNow.title" = "Please select a date in the future";
"a.wallet.ticketToken.transfer" = "PHONE NUMBER"; "a.wallet.ticketToken.transfer" = "PHONE NUMBER";
"a.wallet.ticketToken.transfer.noteLabel.title" = "Before the link expires, anyone with the MagicLink can claim your tickets with one click"; "a.wallet.ticketToken.transfer.noteLabel.title" = "Before the link expires, anyone with the MagicLink can claim your tickets with one click";
"a.wallet.ticketToken.transfer.success.title" = "Your ticket has been transferred"; "a.wallet.ticketToken.transfer.success.title" = "Your %@ has been transferred";
"a.wallet.ticketToken.transfer.failed.title" = "Your ticket was not transferred"; "a.wallet.ticketToken.transfer.failed.title" = "Your %@ was not transferred";
"a.wallet.ticketToken.transfer.inProgress.title" = "Transferring ticket..."; "a.wallet.ticketToken.transfer.inProgress.title" = "Transferring %@...";
"a.wallet.ticketTokenBundle.status.sold.title" = "Sold"; "a.wallet.ticketTokenBundle.status.sold.title" = "Sold";
"a.wallet.ticketTokenBundle.status.redeemed.title" = "Redeemed"; "a.wallet.ticketTokenBundle.status.redeemed.title" = "Redeemed";
"a.wallet.ticketTokenBundle.status.transferred.title" = "Transferred"; "a.wallet.ticketTokenBundle.status.transferred.title" = "Transferred";

@ -111,7 +111,16 @@
"settings.wallets.button.title" = "Carteras"; "settings.wallets.button.title" = "Carteras";
"Symbol" = "Symbol"; "Symbol" = "Symbol";
"Today" = "Hoy"; "Today" = "Hoy";
"Tokens" = "Tokens"; "token.lowercase" = "token";
"token.titlecase" = "Token";
"tokens.lowercase" = "tokens";
"tokens.titlecase" = "Tokens";
"ticket.lowercase" = "ticket";
"ticket.titlecase" = "Ticket";
"tickets.lowercase" = "tickets";
"tickets.titlecase" = "Tickets";
"cryptokitties.lowercase" = "cryptokitties";
"cryptokitties.titlecase" = "Cryptokitties";
"tokens.newtoken.navigation.title" = "Add Custom Token"; "tokens.newtoken.navigation.title" = "Add Custom Token";
"transaction.cell.error.title" = "Error"; "transaction.cell.error.title" = "Error";
"transaction.cell.received.title" = "Recibido"; "transaction.cell.received.title" = "Recibido";
@ -150,31 +159,31 @@
"a.wallet.ticketToken.unverifiedContract" = "UNVERIFIED"; "a.wallet.ticketToken.unverifiedContract" = "UNVERIFIED";
"a.wallet.ticketToken.match.vs" = "%@-%@"; "a.wallet.ticketToken.match.vs" = "%@-%@";
"a.wallet.ticketToken.redeem.button.title" = "Redeem"; "a.wallet.ticketToken.redeem.button.title" = "Redeem";
"a.wallet.ticketToken.redeem.selectTickets.title" = "Select Tickets To Redeem:"; "a.wallet.ticketToken.redeem.selectTickets.title" = "Select %@ To Redeem:";
"a.wallet.ticketToken.redeem.selectTicketQuantity.atLeastOne.title" = "Please select quantity of tickets"; "a.wallet.ticketToken.redeem.selectTicketQuantity.atLeastOne.title" = "Please select quantity of %@";
"a.wallet.ticketToken.redeem.selectTickets.atLeastOne.title" = "Please select a ticket to redeem"; "a.wallet.ticketToken.redeem.selectTickets.atLeastOne.title" = "Please select a %@ to redeem";
"a.wallet.ticketToken.redeem.selectQuantity.title" = "Select Quantity of Tickets"; "a.wallet.ticketToken.redeem.selectQuantity.title" = "Select Quantity of %@";
"a.wallet.ticketToken.redeem.quantity.title" = "QUANTITY OF TICKETS"; "a.wallet.ticketToken.redeem.quantity.title" = "QUANTITY OF %@";
"a.wallet.ticketToken.redeem.showQRCode.title" = "Show QR Code to Redemption Booth"; "a.wallet.ticketToken.redeem.showQRCode.title" = "Show QR Code to Redemption Booth";
"a.wallet.ticketToken.redeem.successful.title" = "Congrats"; "a.wallet.ticketToken.redeem.successful.title" = "Congrats";
"a.wallet.ticketToken.redeem.successful.description" = "You have successfully redeemed your ticket(s)"; "a.wallet.ticketToken.redeem.successful.description" = "You have successfully redeemed your %@";
"a.wallet.ticketToken.sell.button.title" = "Sell"; "a.wallet.ticketToken.sell.button.title" = "Sell";
"a.wallet.ticketToken.sell.selectTickets.title" = "Select Tickets To Sell:"; "a.wallet.ticketToken.sell.selectTickets.title" = "Select %@ To Sell:";
"a.wallet.ticketToken.sell.selectTicketQuantity.atLeastOne.title" = "Please select quantity of tickets"; "a.wallet.ticketToken.sell.selectTicketQuantity.atLeastOne.title" = "Please select quantity of %@";
"a.wallet.ticketToken.sell.price.provide.title" = "Please enter price of tickets"; "a.wallet.ticketToken.sell.price.provide.title" = "Please enter price of %@";
"a.wallet.ticketToken.sell.selectTickets.atLeastOne.title" = "Please select a ticket to sell"; "a.wallet.ticketToken.sell.selectTickets.atLeastOne.title" = "Please select a %@ to sell";
"a.wallet.ticketToken.sell.selectQuantity.title" = "Set a Price"; "a.wallet.ticketToken.sell.selectQuantity.title" = "Set a Price";
"a.wallet.ticketToken.sell.pricePerTicket.title" = "PRICE PER TICKET"; "a.wallet.ticketToken.sell.pricePerTicket.title" = "PRICE PER %@";
"a.wallet.ticketToken.sell.dollarCostLabel.title" = "EQUIVALENT IN USD"; "a.wallet.ticketToken.sell.dollarCostLabel.title" = "EQUIVALENT IN USD";
"a.wallet.ticketToken.sell.quantity.title" = "QUANTITY OF TICKETS"; "a.wallet.ticketToken.sell.quantity.title" = "QUANTITY OF %@";
"a.wallet.ticketToken.sell.enterLinkExpiryDate.title" = "Set MagicLink Expiry"; "a.wallet.ticketToken.sell.enterLinkExpiryDate.title" = "Set MagicLink Expiry";
"a.wallet.ticketToken.sell.singleTicketSelected.title" = "1 Ticket Selected"; "a.wallet.ticketToken.sell.singleTicketSelected.title" = "1 %@ Selected";
"a.wallet.ticketToken.sell.multipleTicketSelected.title" = "%d Tickets Selected"; "a.wallet.ticketToken.sell.multipleTicketSelected.title" = "%d %@ Selected";
"a.wallet.ticketToken.sell.perTicketEthPrice.title" = "%@ ETH/Ticket"; "a.wallet.ticketToken.sell.perTicketEthPrice.title" = "%@ ETH/%@";
"a.wallet.ticketToken.sell.totalEthPrice.title" = "Total: %@ ETH"; "a.wallet.ticketToken.sell.totalEthPrice.title" = "Total: %@ ETH";
"a.wallet.ticketToken.sell.magicLinkDescription.title" = "A MagicLink will be created to allow buyers to purchase your tickets."; "a.wallet.ticketToken.sell.magicLinkDescription.title" = "A MagicLink will be created to allow buyers to purchase your %@.";
"a.wallet.ticketToken.sell.noteTitleLabel.title" = "IMPORTANT"; "a.wallet.ticketToken.sell.noteTitleLabel.title" = "IMPORTANT";
"a.wallet.ticketToken.sell.noteLabel.title" = "Before the link expires, anyone with the MagicLink can purchase your tickets with one click"; "a.wallet.ticketToken.sell.noteLabel.title" = "Before the link expires, anyone with the MagicLink can purchase your %@ with one click";
"a.wallet.ticketToken.sell.linkExpiryDate.title" = "LINK EXPIRY DATE"; "a.wallet.ticketToken.sell.linkExpiryDate.title" = "LINK EXPIRY DATE";
"a.wallet.ticketToken.sell.linkExpiryTime.title" = "LINK EXPIRY TIME"; "a.wallet.ticketToken.sell.linkExpiryTime.title" = "LINK EXPIRY TIME";
"a.wallet.ticketToken.sell.linkExpiryTime.atLeastNow.title" = "Please select a date in the future"; "a.wallet.ticketToken.sell.linkExpiryTime.atLeastNow.title" = "Please select a date in the future";
@ -184,14 +193,14 @@
"a.wallet.ticketToken.sell.confirm.cancel.button.title" = "Cancel"; "a.wallet.ticketToken.sell.confirm.cancel.button.title" = "Cancel";
"a.wallet.ticketToken.sell.confirm.button.title" = "Share MagicLink"; "a.wallet.ticketToken.sell.confirm.button.title" = "Share MagicLink";
"a.wallet.ticketToken.sell.confirm.expiryDateDescription" = "MagicLink expires on: %@"; "a.wallet.ticketToken.sell.confirm.expiryDateDescription" = "MagicLink expires on: %@";
"a.wallet.ticketToken.sell.confirm.singleTicketSelected.title" = "1 Ticket"; "a.wallet.ticketToken.sell.confirm.singleTicketSelected.title" = "1 %@";
"a.wallet.ticketToken.sell.confirm.multipleTicketSelected.title" = "%d Tickets"; "a.wallet.ticketToken.sell.confirm.multipleTicketSelected.title" = "%d %@";
"a.wallet.ticketToken.transfer.button.title" = "Transfer"; "a.wallet.ticketToken.transfer.button.title" = "Transfer";
"a.wallet.ticketToken.transfer.selectTickets.title" = "Select Tickets To Transfer:"; "a.wallet.ticketToken.transfer.selectTickets.title" = "Select %@ To Transfer:";
"a.wallet.ticketToken.transfer.selectTicketQuantity.atLeastOne.title" = "Please select quantity of tickets"; "a.wallet.ticketToken.transfer.selectTicketQuantity.atLeastOne.title" = "Please select quantity of %@";
"a.wallet.ticketToken.transfer.selectTickets.atLeastOne.title" = "Please select a ticket to transfer"; "a.wallet.ticketToken.transfer.selectTickets.atLeastOne.title" = "Please select a %@ to transfer";
"a.wallet.ticketToken.transfer.selectQuantity.title" = "Transfer Tickets"; "a.wallet.ticketToken.transfer.selectQuantity.title" = "Transfer %@";
"a.wallet.ticketToken.transfer.quantity.title" = "QUANTITY OF TICKETS"; "a.wallet.ticketToken.transfer.quantity.title" = "QUANTITY OF %@";
"a.wallet.ticketToken.transfer.mode.magicLink.button.title" = "MagicLink for Picking Up"; "a.wallet.ticketToken.transfer.mode.magicLink.button.title" = "MagicLink for Picking Up";
"a.wallet.ticketToken.transfer.mode.now.button.title" = "Transfer now"; "a.wallet.ticketToken.transfer.mode.now.button.title" = "Transfer now";
"a.wallet.ticketToken.transfer.confirm.title" = "Generate MagicLink"; "a.wallet.ticketToken.transfer.confirm.title" = "Generate MagicLink";
@ -201,9 +210,9 @@
"a.wallet.ticketToken.transfer.linkExpiryTime.atLeastNow.title" = "Please select a date in the future"; "a.wallet.ticketToken.transfer.linkExpiryTime.atLeastNow.title" = "Please select a date in the future";
"a.wallet.ticketToken.transfer" = "PHONE NUMBER"; "a.wallet.ticketToken.transfer" = "PHONE NUMBER";
"a.wallet.ticketToken.transfer.noteLabel.title" = "Before the link expires, anyone with the MagicLink can claim your tickets with one click"; "a.wallet.ticketToken.transfer.noteLabel.title" = "Before the link expires, anyone with the MagicLink can claim your tickets with one click";
"a.wallet.ticketToken.transfer.success.title" = "Your ticket has been transferred"; "a.wallet.ticketToken.transfer.success.title" = "Your %@ has been transferred";
"a.wallet.ticketToken.transfer.failed.title" = "Your ticket was not transferred"; "a.wallet.ticketToken.transfer.failed.title" = "Your %@ was not transferred";
"a.wallet.ticketToken.transfer.inProgress.title" = "Transferring ticket..."; "a.wallet.ticketToken.transfer.inProgress.title" = "Transferring %@...";
"a.wallet.ticketTokenBundle.status.sold.title" = "Sold"; "a.wallet.ticketTokenBundle.status.sold.title" = "Sold";
"a.wallet.ticketTokenBundle.status.redeemed.title" = "Redeemed"; "a.wallet.ticketTokenBundle.status.redeemed.title" = "Redeemed";
"a.wallet.ticketTokenBundle.status.transferred.title" = "Transferred"; "a.wallet.ticketTokenBundle.status.transferred.title" = "Transferred";

@ -90,7 +90,16 @@
"settings.wallets.button.title" = "钱包"; "settings.wallets.button.title" = "钱包";
"Symbol" = "符号"; "Symbol" = "符号";
"Today" = "今天"; "Today" = "今天";
"Tokens" = "通证"; "token.lowercase" = "通证";
"token.titlecase" = "通证";
"tokens.lowercase" = "通证";
"tokens.titlecase" = "通证";
"ticket.lowercase" = "门票";
"ticket.titlecase" = "门票";
"tickets.lowercase" = "门票";
"tickets.titlecase" = "门票";
"cryptokitties.lowercase" = "cryptokitties";
"cryptokitties.titlecase" = "Cryptokitties";
"tokens.newtoken.navigation.title" = "添加自定义通证"; "tokens.newtoken.navigation.title" = "添加自定义通证";
"transaction.cell.error.title" = "错误"; "transaction.cell.error.title" = "错误";
"transaction.cell.received.title" = "已收到"; "transaction.cell.received.title" = "已收到";
@ -150,31 +159,31 @@
"a.wallet.ticketToken.unverifiedContract" = "没有验证"; "a.wallet.ticketToken.unverifiedContract" = "没有验证";
"a.wallet.ticketToken.match.vs" = "%@-%@"; "a.wallet.ticketToken.match.vs" = "%@-%@";
"a.wallet.ticketToken.redeem.button.title" = "兑换"; "a.wallet.ticketToken.redeem.button.title" = "兑换";
"a.wallet.ticketToken.redeem.selectTickets.title" = "选择要兑换的门票:"; "a.wallet.ticketToken.redeem.selectTickets.title" = "选择要兑换的%@:";
"a.wallet.ticketToken.redeem.selectTicketQuantity.atLeastOne.title" = "选择门票数量"; "a.wallet.ticketToken.redeem.selectTicketQuantity.atLeastOne.title" = "选择%@数量";
"a.wallet.ticketToken.redeem.selectTickets.atLeastOne.title" = "选择门票数量"; "a.wallet.ticketToken.redeem.selectTickets.atLeastOne.title" = "选择%@数量";
"a.wallet.ticketToken.redeem.selectQuantity.title" = "选择门票数量"; "a.wallet.ticketToken.redeem.selectQuantity.title" = "选择%@数量";
"a.wallet.ticketToken.redeem.quantity.title" = "门票数量"; "a.wallet.ticketToken.redeem.quantity.title" = "%@数量";
"a.wallet.ticketToken.redeem.showQRCode.title" = "请在兑票柜台展示你的QR码"; "a.wallet.ticketToken.redeem.showQRCode.title" = "请在兑票柜台展示你的QR码";
"a.wallet.ticketToken.redeem.successful.title" = "恭喜"; "a.wallet.ticketToken.redeem.successful.title" = "恭喜";
"a.wallet.ticketToken.redeem.successful.description" = "您刚刚成功的兑换了你的门票"; "a.wallet.ticketToken.redeem.successful.description" = "您刚刚成功的兑换了你的%@";
"a.wallet.ticketToken.sell.button.title" = "出售"; "a.wallet.ticketToken.sell.button.title" = "出售";
"a.wallet.ticketToken.sell.selectTickets.title" = "选择要出售的门票:"; "a.wallet.ticketToken.sell.selectTickets.title" = "选择要出售的%@:";
"a.wallet.ticketToken.sell.selectTicketQuantity.atLeastOne.title" = "选择门票数量"; "a.wallet.ticketToken.sell.selectTicketQuantity.atLeastOne.title" = "选择%@数量";
"a.wallet.ticketToken.sell.price.provide.title" = "请输入价"; "a.wallet.ticketToken.sell.price.provide.title" = "请输入%@价";
"a.wallet.ticketToken.sell.selectTickets.atLeastOne.title" = "选择门票数量"; "a.wallet.ticketToken.sell.selectTickets.atLeastOne.title" = "选择%@数量";
"a.wallet.ticketToken.sell.selectQuantity.title" = "设置一个价格"; "a.wallet.ticketToken.sell.selectQuantity.title" = "设置一个价格";
"a.wallet.ticketToken.sell.pricePerTicket.title" = "门票单价"; "a.wallet.ticketToken.sell.pricePerTicket.title" = "%@单价";
"a.wallet.ticketToken.sell.dollarCostLabel.title" = "相当于USD"; "a.wallet.ticketToken.sell.dollarCostLabel.title" = "相当于USD";
"a.wallet.ticketToken.sell.quantity.title" = "门票数量"; "a.wallet.ticketToken.sell.quantity.title" = "%@数量";
"a.wallet.ticketToken.sell.enterLinkExpiryDate.title" = "设置MagicLink的有效期"; "a.wallet.ticketToken.sell.enterLinkExpiryDate.title" = "设置MagicLink的有效期";
"a.wallet.ticketToken.sell.singleTicketSelected.title" = "已选择1张门票"; "a.wallet.ticketToken.sell.singleTicketSelected.title" = "已选择1张%@";
"a.wallet.ticketToken.sell.multipleTicketSelected.title" = "已选择%d张门票"; "a.wallet.ticketToken.sell.multipleTicketSelected.title" = "已选择%d张%@";
"a.wallet.ticketToken.sell.perTicketEthPrice.title" = "%@ ETH/门票"; "a.wallet.ticketToken.sell.perTicketEthPrice.title" = "%@ ETH/%@";
"a.wallet.ticketToken.sell.totalEthPrice.title" = "总价: %@ ETH"; "a.wallet.ticketToken.sell.totalEthPrice.title" = "总价: %@ ETH";
"a.wallet.ticketToken.sell.magicLinkDescription.title" = "你将创建一个MagicLink销售链接,买家可以通过点击MagicLink来购买你的门票."; "a.wallet.ticketToken.sell.magicLinkDescription.title" = "你将创建一个MagicLink销售链接,买家可以通过点击MagicLink来购买你的%@.";
"a.wallet.ticketToken.sell.noteTitleLabel.title" = "注意"; "a.wallet.ticketToken.sell.noteTitleLabel.title" = "注意";
"a.wallet.ticketToken.sell.noteLabel.title" = "在MagicLink链接失效前,任何人都可以通过点击链接来购买你的门票"; "a.wallet.ticketToken.sell.noteLabel.title" = "在MagicLink链接失效前,任何人都可以通过点击链接来购买你的%@";
"a.wallet.ticketToken.sell.linkExpiryDate.title" = "链接失效日期"; "a.wallet.ticketToken.sell.linkExpiryDate.title" = "链接失效日期";
"a.wallet.ticketToken.sell.linkExpiryTime.title" = "链接失效时间"; "a.wallet.ticketToken.sell.linkExpiryTime.title" = "链接失效时间";
"a.wallet.ticketToken.sell.linkExpiryTime.atLeastNow.title" = "请输入一个未来时间"; "a.wallet.ticketToken.sell.linkExpiryTime.atLeastNow.title" = "请输入一个未来时间";
@ -184,14 +193,14 @@
"a.wallet.ticketToken.sell.confirm.cancel.button.title" = "取消"; "a.wallet.ticketToken.sell.confirm.cancel.button.title" = "取消";
"a.wallet.ticketToken.sell.confirm.button.title" = "分享MagicLink链接"; "a.wallet.ticketToken.sell.confirm.button.title" = "分享MagicLink链接";
"a.wallet.ticketToken.sell.confirm.expiryDateDescription" = "MagicLink有效期至: %@"; "a.wallet.ticketToken.sell.confirm.expiryDateDescription" = "MagicLink有效期至: %@";
"a.wallet.ticketToken.sell.confirm.singleTicketSelected.title" = "1 张门票"; "a.wallet.ticketToken.sell.confirm.singleTicketSelected.title" = "1 张%@";
"a.wallet.ticketToken.sell.confirm.multipleTicketSelected.title" = "%d 张门票"; "a.wallet.ticketToken.sell.confirm.multipleTicketSelected.title" = "%d 张%@";
"a.wallet.ticketToken.transfer.button.title" = "转让"; "a.wallet.ticketToken.transfer.button.title" = "转让";
"a.wallet.ticketToken.transfer.selectTickets.title" = "选择要转让的门票:"; "a.wallet.ticketToken.transfer.selectTickets.title" = "选择要转让的%@:";
"a.wallet.ticketToken.transfer.selectTicketQuantity.atLeastOne.title" = "选择门票数量"; "a.wallet.ticketToken.transfer.selectTicketQuantity.atLeastOne.title" = "选择%@数量";
"a.wallet.ticketToken.transfer.selectTickets.atLeastOne.title" = "选择门票数量"; "a.wallet.ticketToken.transfer.selectTickets.atLeastOne.title" = "选择%@数量";
"a.wallet.ticketToken.transfer.selectQuantity.title" = "转让门票"; "a.wallet.ticketToken.transfer.selectQuantity.title" = "转让%@";
"a.wallet.ticketToken.transfer.quantity.title" = "门票数量"; "a.wallet.ticketToken.transfer.quantity.title" = "%@数量";
"a.wallet.ticketToken.transfer.mode.magicLink.button.title" = "通过MagicLink导出门票"; "a.wallet.ticketToken.transfer.mode.magicLink.button.title" = "通过MagicLink导出门票";
"a.wallet.ticketToken.transfer.mode.now.button.title" = "现在直接转让门票"; "a.wallet.ticketToken.transfer.mode.now.button.title" = "现在直接转让门票";
"a.wallet.ticketToken.transfer.confirm.title" = "MagicLink转让链接"; "a.wallet.ticketToken.transfer.confirm.title" = "MagicLink转让链接";
@ -201,9 +210,9 @@
"a.wallet.ticketToken.transfer.linkExpiryTime.atLeastNow.title" = "请选择一个未来时间"; "a.wallet.ticketToken.transfer.linkExpiryTime.atLeastNow.title" = "请选择一个未来时间";
"a.wallet.ticketToken.transfer" = "电话号码"; "a.wallet.ticketToken.transfer" = "电话号码";
"a.wallet.ticketToken.transfer.noteLabel.title" = "在MagicLink链接失效之前,任何人都可以通过点击MagicLink来导入你的门票"; "a.wallet.ticketToken.transfer.noteLabel.title" = "在MagicLink链接失效之前,任何人都可以通过点击MagicLink来导入你的门票";
"a.wallet.ticketToken.transfer.success.title" = "你的门票已经被转让"; "a.wallet.ticketToken.transfer.success.title" = "你的%@已经被转让";
"a.wallet.ticketToken.transfer.failed.title" = "你的门票没有被转让"; "a.wallet.ticketToken.transfer.failed.title" = "你的%@没有被转让";
"a.wallet.ticketToken.transfer.inProgress.title" = "转让门票中..."; "a.wallet.ticketToken.transfer.inProgress.title" = "转让%@中...";
"a.wallet.ticketTokenBundle.status.sold.title" = "已出售"; "a.wallet.ticketTokenBundle.status.sold.title" = "已出售";
"a.wallet.ticketTokenBundle.status.redeemed.title" = "已兑换"; "a.wallet.ticketTokenBundle.status.redeemed.title" = "已兑换";
"a.wallet.ticketTokenBundle.status.transferred.title" = "已转让"; "a.wallet.ticketTokenBundle.status.transferred.title" = "已转让";

@ -23,7 +23,7 @@ class UniversalLinkCoordinator: Coordinator {
var coordinators: [Coordinator] = [] var coordinators: [Coordinator] = []
private let config: Config private let config: Config
weak var delegate: UniversalLinkCoordinatorDelegate? weak var delegate: UniversalLinkCoordinatorDelegate?
private var importTicketViewController: ImportTokenViewController? private var importTicketViewController: ImportMagicTokenViewController?
private let ethPrice: Subscribable<Double> private let ethPrice: Subscribable<Double>
private let ethBalance: Subscribable<BigInt> private let ethBalance: Subscribable<BigInt>
private var hasCompleted = false private var hasCompleted = false
@ -75,10 +75,11 @@ class UniversalLinkCoordinator: Coordinator {
@discardableResult private func handlePaidImportsImpl(signedOrder: SignedOrder) -> Bool { @discardableResult private func handlePaidImportsImpl(signedOrder: SignedOrder) -> Bool {
guard isShowingImportUserInterface else { return false } guard isShowingImportUserInterface else { return false }
//TODO we might not need to pass a TokenObject. Maybe something simpler? Especially since name and symbol is unused
//TODO: not always ERC875 //TODO: not always ERC875
let tokenObject = TokenObject(contract: signedOrder.order.contractAddress, let tokenObject = TokenObject(contract: signedOrder.order.contractAddress,
name: Constants.event, name: "",
symbol: "FIFA", symbol: "",
decimals: 0, decimals: 0,
value: signedOrder.order.price.description, value: signedOrder.order.price.description,
isCustom: true, isCustom: true,
@ -269,7 +270,7 @@ class UniversalLinkCoordinator: Coordinator {
private func preparingToImportUniversalLink() { private func preparingToImportUniversalLink() {
guard let viewController = delegate?.viewControllerForPresenting(in: self) else { return } guard let viewController = delegate?.viewControllerForPresenting(in: self) else { return }
importTicketViewController = ImportTokenViewController(config: config) importTicketViewController = ImportMagicTokenViewController(config: config)
guard let vc = importTicketViewController else { return } guard let vc = importTicketViewController else { return }
vc.delegate = self vc.delegate = self
vc.configure(viewModel: .init(state: .validating)) vc.configure(viewModel: .init(state: .validating))
@ -378,13 +379,13 @@ class UniversalLinkCoordinator: Coordinator {
} }
} }
extension UniversalLinkCoordinator: ImportTokenViewControllerDelegate { extension UniversalLinkCoordinator: ImportMagicTokenViewControllerDelegate {
func didPressDone(in viewController: ImportTokenViewController) { func didPressDone(in viewController: ImportMagicTokenViewController) {
viewController.dismiss(animated: true) viewController.dismiss(animated: true)
delegate?.completed(in: self) delegate?.completed(in: self)
} }
func didPressImport(in viewController: ImportTokenViewController) { func didPressImport(in viewController: ImportMagicTokenViewController) {
guard let transactionType = transactionType else { return } guard let transactionType = transactionType else { return }
switch transactionType { switch transactionType {
case .freeTransfer(let query, let parameters): case .freeTransfer(let query, let parameters):

@ -1,22 +1,21 @@
// Copyright © 2018 Stormbird PTE. LTD. import Foundation // Copyright © 2018 Stormbird PTE. LTD.
import UIKit import UIKit
import Alamofire import Alamofire
protocol ImportTokenViewControllerDelegate: class { protocol ImportMagicTokenViewControllerDelegate: class {
func didPressDone(in viewController: ImportTokenViewController) func didPressDone(in viewController: ImportMagicTokenViewController)
func didPressImport(in viewController: ImportTokenViewController) func didPressImport(in viewController: ImportMagicTokenViewController)
} }
//class ImportTicketViewController: UIViewController, VerifiableStatusViewController { class ImportMagicTokenViewController: UIViewController, OptionalTokenVerifiableStatusViewController {
class ImportTokenViewController: UIViewController, OptionalTokenVerifiableStatusViewController {
enum State { enum State {
case ready(ImportMagicTokenViewControllerViewModel) case ready(ImportMagicTokenViewControllerViewModel)
case notReady case notReady
} }
let config: Config let config: Config
weak var delegate: ImportTokenViewControllerDelegate? weak var delegate: ImportMagicTokenViewControllerDelegate?
let roundedBackground = RoundedBackground() let roundedBackground = RoundedBackground()
let header = TokensCardViewControllerTitleHeader() let header = TokensCardViewControllerTitleHeader()
let ticketView = TokenCardRowView() let ticketView = TokenCardRowView()

@ -4,8 +4,8 @@ import UIKit
import Alamofire import Alamofire
protocol ImportTokenViewControllerDelegate: class { protocol ImportTokenViewControllerDelegate: class {
func didPressDone(in viewController: ImportTokenViewController) func didPressDone(in viewController: ImportMagicTokenViewController)
func didPressImport(in viewController: ImportTokenViewController) func didPressImport(in viewController: ImportMagicTokenViewController)
} }
//class ImportTokenViewController: UIViewController, VerifiableStatusViewController { //class ImportTokenViewController: UIViewController, VerifiableStatusViewController {
@ -16,7 +16,7 @@ class ImportTokenViewController: UIViewController, OptionalTokenVerifiableStatus
} }
let config: Config let config: Config
weak var delegate: ImportTokenViewControllerDelegate? weak var delegate: ImportMagicTokenViewControllerDelegate?
let roundedBackground = RoundedBackground() let roundedBackground = RoundedBackground()
let header = TokensViewControllerTitleHeader() let header = TokensViewControllerTitleHeader()
let TokenView = TokenRowView() let TokenView = TokenRowView()

@ -221,8 +221,9 @@ struct ImportMagicTokenViewControllerViewModel {
case .free: case .free:
return "" return ""
case .paid(_, let dollarCost): case .paid(_, let dollarCost):
guard let dollarCost = dollarCost else { return "" } guard let dollarCost = dollarCost, let dollarCostAsDouble = Double(dollarCost.description) else { return "" }
return "$\(dollarCost)" let string = StringFormatter().currency(with: dollarCostAsDouble , and: "USD")
return "$\(string)"
} }
} }

@ -22,8 +22,18 @@ public struct Ether {
extension Ether: CustomStringConvertible { extension Ether: CustomStringConvertible {
public var description: String { public var description: String {
return unformattedDescription
}
public var formattedDescription: String {
return EtherNumberFormatter().string(from: ether) return EtherNumberFormatter().string(from: ether)
} }
public var unformattedDescription: String {
let formatter = EtherNumberFormatter()
formatter.groupingSeparator = ""
return formatter.string(from: ether)
}
} }
extension Ether: LosslessStringConvertible { extension Ether: LosslessStringConvertible {

@ -116,8 +116,9 @@ class RedeemTokenCardQuantitySelectionViewController: UIViewController, TokenVer
@objc @objc
func nextButtonTapped() { func nextButtonTapped() {
if quantityStepper.value == 0 { if quantityStepper.value == 0 {
let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
UIAlertController.alert(title: "", UIAlertController.alert(title: "",
message: R.string.localizable.aWalletTicketTokenRedeemSelectTicketQuantityAtLeastOneTitle(), message: R.string.localizable.aWalletTicketTokenRedeemSelectTicketQuantityAtLeastOneTitle(tokenTypeName),
alertButtonTitles: [R.string.localizable.oK()], alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.cancel], alertButtonStyles: [.cancel],
viewController: self, viewController: self,

@ -107,8 +107,9 @@ class RedeemTokenViewController: UIViewController, TokenVerifiableStatusViewCont
func nextButtonTapped() { func nextButtonTapped() {
let selectedTicketHolders = viewModel.ticketHolders.filter { $0.isSelected } let selectedTicketHolders = viewModel.ticketHolders.filter { $0.isSelected }
if selectedTicketHolders.isEmpty { if selectedTicketHolders.isEmpty {
let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.singular, titlecase: .notTitlecase)
UIAlertController.alert(title: "", UIAlertController.alert(title: "",
message: R.string.localizable.aWalletTicketTokenRedeemSelectTicketsAtLeastOneTitle(), message: R.string.localizable.aWalletTicketTokenRedeemSelectTicketsAtLeastOneTitle(tokenTypeName),
alertButtonTitles: [R.string.localizable.oK()], alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.cancel], alertButtonStyles: [.cancel],
viewController: self, viewController: self,

@ -135,8 +135,9 @@ class TokenCardRedemptionViewController: UIViewController, TokenVerifiableStatus
private func showSuccessMessage() { private func showSuccessMessage() {
invalidateTimer() invalidateTimer()
let tokenTypeName = XMLHandler(contract: contract).getTokenTypeName()
UIAlertController.alert(title: R.string.localizable.aWalletTicketTokenRedeemSuccessfulTitle(), UIAlertController.alert(title: R.string.localizable.aWalletTicketTokenRedeemSuccessfulTitle(),
message: R.string.localizable.aWalletTicketTokenRedeemSuccessfulDescription(), message: R.string.localizable.aWalletTicketTokenRedeemSuccessfulDescription(tokenTypeName),
alertButtonTitles: [R.string.localizable.oK()], alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.cancel], alertButtonStyles: [.cancel],
viewController: self, viewController: self,

@ -15,7 +15,8 @@ struct RedeemTokenCardQuantitySelectionViewModel {
var ticketHolder: TokenHolder var ticketHolder: TokenHolder
var headerTitle: String { var headerTitle: String {
return R.string.localizable.aWalletTicketTokenRedeemSelectQuantityTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
return R.string.localizable.aWalletTicketTokenRedeemSelectQuantityTitle(tokenTypeName)
} }
var maxValue: Int { var maxValue: Int {
@ -51,6 +52,7 @@ struct RedeemTokenCardQuantitySelectionViewModel {
} }
var subtitleText: String { var subtitleText: String {
return R.string.localizable.aWalletTicketTokenRedeemQuantityTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
return R.string.localizable.aWalletTicketTokenRedeemQuantityTitle(tokenTypeName.localizedUppercase)
} }
} }

@ -32,7 +32,8 @@ struct RedeemTokenCardViewModel {
} }
var title: String { var title: String {
return R.string.localizable.aWalletTicketTokenRedeemSelectTicketsTitle () let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
return R.string.localizable.aWalletTicketTokenRedeemSelectTicketsTitle(tokenTypeName)
} }
var buttonTitleColor: UIColor { var buttonTitleColor: UIColor {

@ -222,8 +222,9 @@ class EnterSellTokensCardPriceQuantityViewController: UIViewController, TokenVer
@objc @objc
func nextButtonTapped() { func nextButtonTapped() {
guard quantityStepper.value > 0 else { guard quantityStepper.value > 0 else {
let tokenTypeName = XMLHandler(contract: contract).getTokenTypeName()
UIAlertController.alert(title: "", UIAlertController.alert(title: "",
message: R.string.localizable.aWalletTicketTokenSellSelectTicketQuantityAtLeastOneTitle(), message: R.string.localizable.aWalletTicketTokenSellSelectTicketQuantityAtLeastOneTitle(tokenTypeName),
alertButtonTitles: [R.string.localizable.oK()], alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.cancel], alertButtonStyles: [.cancel],
viewController: self, viewController: self,
@ -239,8 +240,9 @@ class EnterSellTokensCardPriceQuantityViewController: UIViewController, TokenVer
} }
guard !noPrice else { guard !noPrice else {
let tokenTypeName = XMLHandler(contract: contract).getTokenTypeName(.plural, titlecase: .notTitlecase)
UIAlertController.alert(title: "", UIAlertController.alert(title: "",
message: R.string.localizable.aWalletTicketTokenSellPriceProvideTitle(), message: R.string.localizable.aWalletTicketTokenSellPriceProvideTitle(tokenTypeName),
alertButtonTitles: [R.string.localizable.oK()], alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.cancel], alertButtonStyles: [.cancel],
viewController: self, viewController: self,

@ -101,8 +101,9 @@ class SellTokensCardViewController: UIViewController, TokenVerifiableStatusViewC
func nextButtonTapped() { func nextButtonTapped() {
let selectedTicketHolders = viewModel.ticketHolders.filter { $0.isSelected } let selectedTicketHolders = viewModel.ticketHolders.filter { $0.isSelected }
if selectedTicketHolders.isEmpty { if selectedTicketHolders.isEmpty {
let tokenTypeName = XMLHandler(contract: contract).getTokenTypeName(.singular, titlecase: .notTitlecase)
UIAlertController.alert(title: "", UIAlertController.alert(title: "",
message: R.string.localizable.aWalletTicketTokenSellSelectTicketsAtLeastOneTitle(), message: R.string.localizable.aWalletTicketTokenSellSelectTicketsAtLeastOneTitle(tokenTypeName),
alertButtonTitles: [R.string.localizable.oK()], alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.cancel], alertButtonStyles: [.cancel],
viewController: self, viewController: self,

@ -47,11 +47,13 @@ struct EnterSellTokensCardPriceQuantityViewControllerViewModel {
} }
var quantityLabelText: String { var quantityLabelText: String {
return R.string.localizable.aWalletTicketTokenSellQuantityTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
return R.string.localizable.aWalletTicketTokenSellQuantityTitle(tokenTypeName.localizedUppercase)
} }
var pricePerTicketLabelText: String { var pricePerTicketLabelText: String {
return R.string.localizable.aWalletTicketTokenSellPricePerTicketTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.singular)
return R.string.localizable.aWalletTicketTokenSellPricePerTicketTitle(tokenTypeName.localizedUppercase)
} }
var linkExpiryDateLabelText: String { var linkExpiryDateLabelText: String {
@ -75,7 +77,7 @@ struct EnterSellTokensCardPriceQuantityViewControllerViewModel {
} }
var ethCostLabelText: String { var ethCostLabelText: String {
return "\(ethCost) ETH" return "\(ethCost.formattedDescription) ETH"
} }
var ethCostLabelColor: UIColor { var ethCostLabelColor: UIColor {

@ -63,19 +63,22 @@ struct GenerateSellMagicLinkViewControllerViewModel {
var ticketCountLabelText: String { var ticketCountLabelText: String {
if ticketCount == 1 { if ticketCount == 1 {
return R.string.localizable.aWalletTicketTokenSellConfirmSingleTicketSelectedTitle() let tokenTypeName = XMLHandler(contract: ticketHolder.contractAddress).getTokenTypeName(.singular, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenSellConfirmSingleTicketSelectedTitle(tokenTypeName)
} else { } else {
return R.string.localizable.aWalletTicketTokenSellConfirmMultipleTicketSelectedTitle(ticketHolder.count) let tokenTypeName = XMLHandler(contract: ticketHolder.contractAddress).getTokenTypeName(.plural, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenSellConfirmMultipleTicketSelectedTitle(ticketHolder.count, tokenTypeName)
} }
} }
var perTicketPriceLabelText: String { var perTicketPriceLabelText: String {
let tokenTypeName = XMLHandler(contract: ticketHolder.contractAddress).getTokenTypeName(.singular, titlecase: .titlecase)
let amount = ethCost / ticketCount let amount = ethCost / ticketCount
return R.string.localizable.aWalletTicketTokenSellPerTicketEthPriceTitle(String(amount)) return R.string.localizable.aWalletTicketTokenSellPerTicketEthPriceTitle(amount.formattedDescription)
} }
var totalEthLabelText: String { var totalEthLabelText: String {
return R.string.localizable.aWalletTicketTokenSellTotalEthPriceTitle(String(ethCost)) return R.string.localizable.aWalletTicketTokenSellTotalEthPriceTitle(ethCost.formattedDescription)
} }
var detailsBackgroundBackgroundColor: UIColor { var detailsBackgroundBackgroundColor: UIColor {

@ -62,9 +62,11 @@ struct GenerateTransferMagicLinkViewControllerViewModel {
var ticketCountLabelText: String { var ticketCountLabelText: String {
if ticketCount == 1 { if ticketCount == 1 {
return R.string.localizable.aWalletTicketTokenSellConfirmSingleTicketSelectedTitle() let tokenTypeName = XMLHandler(contract: ticketHolder.contractAddress).getTokenTypeName(.singular, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenSellConfirmSingleTicketSelectedTitle(tokenTypeName)
} else { } else {
return R.string.localizable.aWalletTicketTokenSellConfirmMultipleTicketSelectedTitle(ticketHolder.count) let tokenTypeName = XMLHandler(contract: ticketHolder.contractAddress).getTokenTypeName(.plural, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenSellConfirmMultipleTicketSelectedTitle(ticketHolder.count, tokenTypeName)
} }
} }

@ -26,7 +26,8 @@ struct SellTokensCardViewModel {
} }
var title: String { var title: String {
return R.string.localizable.aWalletTicketTokenSellSelectTicketsTitle () let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
return R.string.localizable.aWalletTicketTokenSellSelectTicketsTitle(tokenTypeName)
} }
var buttonTitleColor: UIColor { var buttonTitleColor: UIColor {

@ -54,7 +54,8 @@ struct SetSellTokensCardExpiryDateViewControllerViewModel {
} }
var descriptionLabelText: String { var descriptionLabelText: String {
return R.string.localizable.aWalletTicketTokenSellMagicLinkDescriptionTitle() let tokenTypeName = XMLHandler(contract: token.contract).getTokenTypeName(.plural, titlecase: .notTitlecase)
return R.string.localizable.aWalletTicketTokenSellMagicLinkDescriptionTitle(tokenTypeName)
} }
var descriptionLabelFont: UIFont { var descriptionLabelFont: UIFont {
@ -67,19 +68,22 @@ struct SetSellTokensCardExpiryDateViewControllerViewModel {
var ticketCountLabelText: String { var ticketCountLabelText: String {
if ticketCount == 1 { if ticketCount == 1 {
return R.string.localizable.aWalletTicketTokenSellSingleTicketSelectedTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.singular, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenSellSingleTicketSelectedTitle(tokenTypeName)
} else { } else {
return R.string.localizable.aWalletTicketTokenSellMultipleTicketSelectedTitle(ticketHolder.count) let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.plural, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenSellMultipleTicketSelectedTitle(ticketHolder.count, tokenTypeName)
} }
} }
var perTicketPriceLabelText: String { var perTicketPriceLabelText: String {
let tokenTypeName = XMLHandler(contract: token.contract).getTokenTypeName(.singular, titlecase: .titlecase)
let amount = ethCost / ticketCount let amount = ethCost / ticketCount
return R.string.localizable.aWalletTicketTokenSellPerTicketEthPriceTitle(String(amount)) return R.string.localizable.aWalletTicketTokenSellPerTicketEthPriceTitle(amount.formattedDescription)
} }
var totalEthLabelText: String { var totalEthLabelText: String {
return R.string.localizable.aWalletTicketTokenSellTotalEthPriceTitle(String(ethCost)) return R.string.localizable.aWalletTicketTokenSellTotalEthPriceTitle(ethCost.formattedDescription)
} }
var noteTitleLabelText: String { var noteTitleLabelText: String {
@ -95,7 +99,8 @@ struct SetSellTokensCardExpiryDateViewControllerViewModel {
} }
var noteLabelText: String { var noteLabelText: String {
return R.string.localizable.aWalletTicketTokenSellNoteLabelTitle() let tokenTypeName = XMLHandler(contract: token.contract).getTokenTypeName(.plural, titlecase: .notTitlecase)
return R.string.localizable.aWalletTicketTokenSellNoteLabelTitle(tokenTypeName)
} }
var noteLabelFont: UIFont { var noteLabelFont: UIFont {

@ -126,46 +126,21 @@ struct Config {
} }
} }
var ticketContractAddress: String? {
switch server {
case .main:
return "0xA66A3F08068174e8F005112A8b2c7A507a822335"
case .ropsten:
return "0xd8e5f58de3933e1e35f9c65eb72cb188674624f3"
default:
return nil
}
}
///Debugging flag. Set to false to disable auto fetching prices, etc to cut down on network calls ///Debugging flag. Set to false to disable auto fetching prices, etc to cut down on network calls
let isAutoFetchingDisabled = false let isAutoFetchingDisabled = false
func createDefaultTicketToken(forContract contract: String) -> ERCToken? { //TODO move?
func getContractLocalizedName(forContract contract: String) -> String? {
guard let contractAddress = Address(string: contract) else { return nil } guard let contractAddress = Address(string: contract) else { return nil }
let xmlHandler = XMLHandler(contract: contract) let xmlHandler = XMLHandler(contract: contract)
let name = xmlHandler.getName() let name = xmlHandler.getName()
//TODO get symbol from RPC node, but this doesn't provide much benefit as it is a hardcoded //TODO get symbol from RPC node, but this doesn't provide much benefit as it is a hardcoded
//placeholder anyway //placeholder anyway
//GetSymbolCoordinator(web3: Web3Swift()).getSymbol(for: contractAddress) { result in } //GetSymbolCoordinator(web3: Web3Swift()).getSymbol(for: contractAddress) { result in }
let lang = xmlHandler.getLang()
switch server { switch server {
case .main: case .main, .ropsten:
return ERCToken( return name
contract: contractAddress,
name: Constants.event + " " + name,
symbol: "SHANKAI",
decimals: 0,
type: .erc875,
balance: []
)
case .ropsten:
return ERCToken(
contract: contractAddress,
name: name,
symbol: "TEST",
decimals: 0,
type: .erc875,
balance: []
)
case .kovan, .rinkeby, .poa, .sokol, .classic, .callisto, .custom: case .kovan, .rinkeby, .poa, .sokol, .classic, .callisto, .custom:
return nil return nil
} }

@ -32,13 +32,14 @@ public struct Constants {
public static let donationAddress = "0xFE6d4bC2De2D0b0E6FE47f08A28Ed52F9d052A02" public static let donationAddress = "0xFE6d4bC2De2D0b0E6FE47f08A28Ed52F9d052A02"
public static let dappsBrowserURL = "https://www.stateofthedapps.com" public static let dappsBrowserURL = "https://www.stateofthedapps.com"
// FIFA hardcoded FIFA token address. Look for "//FIFA" for relevant changes
public static let ticketContractAddress = "0xA66A3F08068174e8F005112A8b2c7A507a822335"
public static let ticketContractAddressRopsten = "0xD8e5F58DE3933E1E35f9c65eb72cb188674624F3"
public static let nullTicket = "0x0000000000000000000000000000000000000000000000000000000000000000" public static let nullTicket = "0x0000000000000000000000000000000000000000000000000000000000000000"
public static let nullTicketBigUInt = BigUInt(0) public static let nullTicketBigUInt = BigUInt(0)
public static let burnAddressString = "0x000000000000000000000000000000000000dEaD" public static let burnAddressString = "0x000000000000000000000000000000000000dEaD"
public static let event = "FIFA WC2018"
// FIFA hardcoded FIFA token address
public static let ticketContractAddress = "0xA66A3F08068174e8F005112A8b2c7A507a822335"
public static let ticketContractAddressRopsten = "0xD8e5F58DE3933E1E35f9c65eb72cb188674624F3"
public static let fifaWorldCup2018TokenNamePrefix = "FIFA WC2018"
//etherscan APIs //etherscan APIs
public static let mainnetEtherscanAPI = "https://api.etherscan.io/api?module=account&action=txlist&address=" public static let mainnetEtherscanAPI = "https://api.etherscan.io/api?module=account&action=txlist&address="

@ -19,7 +19,7 @@ struct Token {
return Token( return Token(
id: Constants.nullTicketBigUInt, id: Constants.nullTicketBigUInt,
index: 0, index: 0,
name: "FIFA WC", name: R.string.localizable.tokensTitlecase(),
values: [ values: [
"locality": "N/A", "locality": "N/A",
"venue": "N/A", "venue": "N/A",

@ -513,10 +513,8 @@ class TokensDataStore {
public func updateERC875TokensToLocalizedName() { public func updateERC875TokensToLocalizedName() {
assetDefinitionStore.forEachContractWithXML { contract in assetDefinitionStore.forEachContractWithXML { contract in
if let token = config.createDefaultTicketToken(forContract: contract) { if let localizedName = config.getContractLocalizedName(forContract: contract) {
let contract = token.contract.eip55String if let storedTicketToken = enabledObject.first(where: { $0.contract.sameContract(as: contract) }) {
let localizedName = token.name
if let storedTicketToken = enabledObject.first(where: { $0.contract == contract }) {
//TODO multiple realm writes in a loop. Should we group them together? //TODO multiple realm writes in a loop. Should we group them together?
updateTicketTokenName(token: storedTicketToken, to: localizedName) updateTicketTokenName(token: storedTicketToken, to: localizedName)
} }

@ -1,4 +1,4 @@
// Copyright © 2018 Stormbird PTE. LTD. import Foundation // Copyright © 2018 Stormbird PTE. LTD.
import Foundation import Foundation

@ -6,6 +6,6 @@ import UIKit
struct EditTokenViewModel { struct EditTokenViewModel {
var title: String { var title: String {
return R.string.localizable.tokens() return R.string.localizable.tokenTitlecase()
} }
} }

@ -6,11 +6,7 @@ import UIKit
//Must be a class, and not a struct, otherwise changing `filter` will silently create a copy of TokensViewModel when user taps to change the filter in the UI and break filtering //Must be a class, and not a struct, otherwise changing `filter` will silently create a copy of TokensViewModel when user taps to change the filter in the UI and break filtering
class TokensViewModel { class TokensViewModel {
var config: Config var config: Config
var tokens: [TokenObject] = [] { var tokens: [TokenObject] = []
willSet {
tokens = reorderTokensSoFIFAAtIndex1(tokens: newValue)
}
}
var tickers: [String: CoinTicker]? var tickers: [String: CoinTicker]?
var etherTokenContract: String var etherTokenContract: String
var filter: WalletFilter = .all var filter: WalletFilter = .all
@ -91,10 +87,6 @@ class TokensViewModel {
if etherTokenContract == token.contract { if etherTokenContract == token.contract {
return false return false
} }
if let ticketContractAddress = config.ticketContractAddress,
token.contract.lowercased() == ticketContractAddress.lowercased() {
return false
}
return true return true
} }
@ -113,22 +105,7 @@ class TokensViewModel {
) { ) {
self.config = config self.config = config
self.etherTokenContract = TokensDataStore.etherToken(for: config).contract self.etherTokenContract = TokensDataStore.etherToken(for: config).contract
self.tokens = reorderTokensSoFIFAAtIndex1(tokens: tokens) self.tokens = tokens
self.tickers = tickers self.tickers = tickers
} }
//FIFA make the FIFA token be index 1. Can remove the function and replace with the argument when we no longer need this
private func reorderTokensSoFIFAAtIndex1(tokens: [TokenObject]) -> [TokenObject] {
guard let contract = config.ticketContractAddress else { return tokens }
let index = tokens.index { $0.address.eip55String.sameContract(as: contract) }
if let index = index, tokens.count >= 2 {
var reorderedTokens = tokens
let target = reorderedTokens[index]
reorderedTokens.remove(at: index)
reorderedTokens.insert(target, at: 1)
return reorderedTokens
} else {
return tokens
}
}
} }

@ -44,19 +44,20 @@ class TransferNFTCoordinator: Coordinator {
func start() { func start() {
guard let address = validateAddress() else { return } guard let address = validateAddress() else { return }
showProgressViewController() showProgressViewController(address: address)
transfer(address: address) transfer(address: address)
} }
private func showProgressViewController() { private func showProgressViewController(address: Address) {
statusViewController = StatusViewController() statusViewController = StatusViewController()
if let vc = statusViewController { if let vc = statusViewController {
vc.delegate = self vc.delegate = self
let tokenTypeName = XMLHandler(contract: address.eip55String).getTokenTypeName(.singular)
vc.configure(viewModel: .init( vc.configure(viewModel: .init(
state: .processing, state: .processing,
inProgressText: R.string.localizable.aWalletTicketTokenTransferInProgressTitle(), inProgressText: R.string.localizable.aWalletTicketTokenTransferInProgressTitle(tokenTypeName),
succeededTextText: R.string.localizable.aWalletTicketTokenTransferSuccessTitle(), succeededTextText: R.string.localizable.aWalletTicketTokenTransferSuccessTitle(tokenTypeName),
failedText: R.string.localizable.aWalletTicketTokenTransferFailedTitle() failedText: R.string.localizable.aWalletTicketTokenTransferFailedTitle(tokenTypeName)
)) ))
vc.modalPresentationStyle = .overCurrentContext vc.modalPresentationStyle = .overCurrentContext
viewController.present(vc, animated: true) viewController.present(vc, animated: true)

@ -117,8 +117,9 @@ class TransferTokensCardQuantitySelectionViewController: UIViewController, Token
@objc @objc
func nextButtonTapped() { func nextButtonTapped() {
if quantityStepper.value == 0 { if quantityStepper.value == 0 {
let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
UIAlertController.alert(title: "", UIAlertController.alert(title: "",
message: R.string.localizable.aWalletTicketTokenTransferSelectTicketQuantityAtLeastOneTitle(), message: R.string.localizable.aWalletTicketTokenTransferSelectTicketQuantityAtLeastOneTitle(tokenTypeName),
alertButtonTitles: [R.string.localizable.oK()], alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.cancel], alertButtonStyles: [.cancel],
viewController: self, viewController: self,

@ -103,8 +103,9 @@ class TransferTokensCardViewController: UIViewController, TokenVerifiableStatusV
func nextButtonTapped() { func nextButtonTapped() {
let selectedTicketHolders = viewModel.ticketHolders.filter { $0.isSelected } let selectedTicketHolders = viewModel.ticketHolders.filter { $0.isSelected }
if selectedTicketHolders.isEmpty { if selectedTicketHolders.isEmpty {
let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.singular, titlecase: .notTitlecase)
UIAlertController.alert(title: "", UIAlertController.alert(title: "",
message: R.string.localizable.aWalletTicketTokenTransferSelectTicketsAtLeastOneTitle(), message: R.string.localizable.aWalletTicketTokenTransferSelectTicketsAtLeastOneTitle(tokenTypeName),
alertButtonTitles: [R.string.localizable.oK()], alertButtonTitles: [R.string.localizable.oK()],
alertButtonStyles: [.cancel], alertButtonStyles: [.cancel],
viewController: self, viewController: self,

@ -9,7 +9,8 @@ struct ChooseTokenCardTransferModeViewControllerViewModel {
var ticketHolder: TokenHolder var ticketHolder: TokenHolder
var headerTitle: String { var headerTitle: String {
return R.string.localizable.aWalletTicketTokenTransferSelectQuantityTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.plural, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenTransferSelectQuantityTitle(tokenTypeName)
} }
var backgroundColor: UIColor { var backgroundColor: UIColor {

@ -9,7 +9,8 @@ struct SetTransferTokensCardExpiryDateViewControllerViewModel {
var ticketHolder: TokenHolder var ticketHolder: TokenHolder
var headerTitle: String { var headerTitle: String {
return R.string.localizable.aWalletTicketTokenTransferSelectQuantityTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.plural, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenTransferSelectQuantityTitle(tokenTypeName)
} }
var backgroundColor: UIColor { var backgroundColor: UIColor {

@ -9,7 +9,8 @@ struct TransferTokensCardQuantitySelectionViewModel {
var ticketHolder: TokenHolder var ticketHolder: TokenHolder
var headerTitle: String { var headerTitle: String {
return R.string.localizable.aWalletTicketTokenTransferSelectQuantityTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.plural, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenTransferSelectQuantityTitle(tokenTypeName)
} }
var maxValue: Int { var maxValue: Int {
@ -45,6 +46,7 @@ struct TransferTokensCardQuantitySelectionViewModel {
} }
var subtitleText: String { var subtitleText: String {
return R.string.localizable.aWalletTicketTokenTransferQuantityTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
return R.string.localizable.aWalletTicketTokenTransferQuantityTitle(tokenTypeName.localizedUppercase)
} }
} }

@ -9,7 +9,8 @@ struct TransferTokensCardViaWalletAddressViewControllerViewModel {
var ticketHolder: TokenHolder var ticketHolder: TokenHolder
var headerTitle: String { var headerTitle: String {
return R.string.localizable.aWalletTicketTokenTransferSelectQuantityTitle() let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName(.plural, titlecase: .titlecase)
return R.string.localizable.aWalletTicketTokenTransferSelectQuantityTitle(tokenTypeName)
} }
var backgroundColor: UIColor { var backgroundColor: UIColor {

@ -26,7 +26,8 @@ struct TransferTokensCardViewModel {
} }
var title: String { var title: String {
return R.string.localizable.aWalletTicketTokenTransferSelectTicketsTitle () let tokenTypeName = XMLHandler(contract: token.address.eip55String).getTokenTypeName()
return R.string.localizable.aWalletTicketTokenTransferSelectTicketsTitle(tokenTypeName)
} }
var buttonTitleColor: UIColor { var buttonTitleColor: UIColor {

@ -23,7 +23,7 @@ class UniversalLinkHandlerTests: XCTestCase {
func testCreateUniversalLink() { func testCreateUniversalLink() {
var indices = [UInt16]() var indices = [UInt16]()
indices.append(1) indices.append(1)
let contractAddress = Config().ticketContractAddress! let contractAddress = "0x1"
let testOrder1 = Order(price: BigUInt("1000000000")!, let testOrder1 = Order(price: BigUInt("1000000000")!,
indices: indices, indices: indices,
expiry: BigUInt("0")!, expiry: BigUInt("0")!,

@ -12,7 +12,7 @@ class ImportTokenViewControllerTests: FBSnapshotTestCase {
} }
func testImportTokenViewControllerDisplay() { func testImportTokenViewControllerDisplay() {
let controller = ImportTokenViewController(config: Config()) let controller = ImportMagicTokenViewController(config: Config())
var viewModel: ImportMagicTokenViewControllerViewModel = .init(state: .validating) var viewModel: ImportMagicTokenViewControllerViewModel = .init(state: .validating)
let ticket = Token(id: "1", index: 1, name: "", values: ["locality": "", "venue": "", "match": 9, "time": GeneralisedTime(string: "20010203160500+0300")!, "numero": 1, "category": "MATCH CLUB", "countryA": "Team A", "countryB": "Team B"]) let ticket = Token(id: "1", index: 1, name: "", values: ["locality": "", "venue": "", "match": 9, "time": GeneralisedTime(string: "20010203160500+0300")!, "numero": 1, "category": "MATCH CLUB", "countryA": "Team A", "countryB": "Team B"])
let ticketHolder = TokenHolder(tickets: [ticket], status: .available, contractAddress: "0x1") let ticketHolder = TokenHolder(tickets: [ticket], status: .available, contractAddress: "0x1")

@ -14,4 +14,9 @@ class EtherTests: XCTestCase {
XCTAssertEqual(String(e * 10), "12") XCTAssertEqual(String(e * 10), "12")
XCTAssertEqual(String(e / 10), "0.12") XCTAssertEqual(String(e / 10), "0.12")
} }
func testDescriptionShouldNotIncludeFormatting() {
let e = Ether(string: "1000")!
XCTAssertEqual(String(e), "1000")
}
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 115 KiB

@ -3,6 +3,7 @@
import FBSnapshotTestCase import FBSnapshotTestCase
@testable import Trust @testable import Trust
import UIKit import UIKit
import TrustKeystore
class TransferTokensCardQuantitySelectionViewControllerTests: FBSnapshotTestCase { class TransferTokensCardQuantitySelectionViewControllerTests: FBSnapshotTestCase {
override func setUp() { override func setUp() {
@ -12,7 +13,7 @@ class TransferTokensCardQuantitySelectionViewControllerTests: FBSnapshotTestCase
} }
func testTransferTokensCardQuantitySelectionViewControllerCanBeCreated() { func testTransferTokensCardQuantitySelectionViewControllerCanBeCreated() {
let token = TokenObject() let token = TokenObject(contract: "0x0000000000000000000000000000000000000001", name: "", symbol: "", decimals: 0, value: "", isCustom: true, isDisabled: false, type: .erc875)
let type = PaymentFlow.send(type: .ERC875Token(token)) let type = PaymentFlow.send(type: .ERC875Token(token))
let ticket = Token(id: "1", index: 1, name: "", values: ["city": "", "venue": "", "match": 9, "time": GeneralisedTime(string: "20010203160500+0300")!, "numero": 1, "category": "MATCH CLUB", "countryA": "Team A", "countryB": "Team B"]) let ticket = Token(id: "1", index: 1, name: "", values: ["city": "", "venue": "", "match": 9, "time": GeneralisedTime(string: "20010203160500+0300")!, "numero": 1, "category": "MATCH CLUB", "countryA": "Team A", "countryB": "Team B"])
let ticketHolder = TokenHolder(tickets: [ticket], status: .available, contractAddress: "0x1") let ticketHolder = TokenHolder(tickets: [ticket], status: .available, contractAddress: "0x1")

Loading…
Cancel
Save