@ -109,10 +109,10 @@ enum RPCServer: Hashable, CaseIterable {
}
}
var g etE therscanURL: URL ? {
var etherscanURLForGeneralTransactionHistory : URL ? {
switch self {
case . main , . ropsten , . rinkeby , . kovan , . poa , . classic , . goerli , . xDai , . artis_sigma1 , . artis_tau1 , . polygon , . binance_smart_chain , . binance_smart_chain_testnet , . sokol , . callisto :
return etherscanRoot . appendingQueryString ( " module=account&action=txlist " )
return etherscanApi Root . appendingQueryString ( " module=account&action=txlist " )
case . heco : return nil
case . heco_testnet : return nil
case . custom : return nil
@ -124,35 +124,48 @@ enum RPCServer: Hashable, CaseIterable {
}
}
var getEtherscanURLERC20Events : String ? {
switch self {
case . main : return Constants . mainnetEtherscanAPIErc20Events
case . ropsten : return Constants . ropstenEtherscanAPIErc20Events
case . rinkeby : return Constants . rinkebyEtherscanAPIErc20Events
case . kovan : return Constants . kovanEtherscanAPIErc20Events
case . poa : return Constants . poaNetworkCoreAPIErc20Events
case . sokol : return nil
case . classic : return Constants . classicAPIErc20Events
case . callisto : return nil
case . goerli : return Constants . goerliEtherscanAPIErc20Events
case . xDai : return Constants . xDaiAPIErc20Events
case . artis_sigma1 : return nil
case . artis_tau1 : return nil
case . binance_smart_chain : return nil
case . binance_smart_chain_testnet : return nil
case . heco : return nil
case . heco_testnet : return nil
case . custom : return nil
case . fantom : return nil
case . fantom_testnet : return nil
case . avalanche : return nil
case . avalanche_testnet : return nil
case . polygon : return " https://explorer-mainnet.maticvigil.com/api/v2/transactions?module=account&action=tokentx&address= "
case . mumbai_testnet : return nil
// / e t h e r s c a n - c o m p a t i b l e e r c 2 0 t r a n s a c t i o n e v e n t A P I s
// / T h e f e t c h E R C 2 0 t r a n s a c t i o n s e n d p o i n t f r o m E t h e r s c a n r e t u r n s o n l y E R C 2 0 t o k e n t r a n s a c t i o n s b u t t h e B l o c k s c o u t v e r s i o n a l s o i n c l u d e s E R C 7 2 1 t r a n s a c t i o n s t o o ( s o i t ' s l i k e l y o t h e r t y p e s t h a t i t c a n d e t e c t w i l l b e r e t u r n e d t o o ) ; t h u s w e s h o u l d c h e c k t h e t o k e n t y p e r a t h e r t h a n a s s u m e t h a t t h e y a r e a l l E R C 2 0
var etherscanURLForTokenTransactionHistory : URL ? {
switch etherscanCompatibleType {
case . etherscan , . blockscout :
return etherscanApiRoot . appendingQueryString ( " module=account&action=tokentx " )
case . unknown :
return nil
}
}
var etherscanRoot : URL {
var etherscanWebpageRoot : URL ? {
let urlString : String ? = {
switch self {
case . main : return " https://cn.etherscan.com "
case . ropsten : return " https://ropsten.etherscan.io "
case . rinkeby : return " https://rinkeby.etherscan.io "
case . kovan : return " https://kovan.etherscan.io "
case . goerli : return " https://goerli.etherscan.io "
case . heco_testnet : return " https://scan-testnet.hecochain.com "
case . heco : return " https://scan.hecochain.com "
case . fantom : return " https://ftmscan.com "
case . xDai : return " https://blockscout.com/poa/dai "
case . poa : return " https://blockscout.com/poa/core "
case . sokol : return " https://blockscout.com/poa/sokol "
case . classic : return " https://blockscout.com/etc/mainnet "
case . callisto : return " https://blockscout.com/callisto/mainnet "
case . artis_sigma1 : return " https://explorer.sigma1.artis.network "
case . artis_tau1 : return " https://explorer.tau1.artis.network "
case . binance_smart_chain : return " https://bscscan.com "
case . binance_smart_chain_testnet : return " https://testnet.bscscan.com "
case . polygon : return " https://explorer-mainnet.maticvigil.com "
case . mumbai_testnet : return " https://explorer-mumbai.maticvigil.com "
case . custom : return nil
case . fantom_testnet , . avalanche , . avalanche_testnet :
return nil
}
} ( )
return urlString . flatMap { URL ( string : $0 ) }
}
var etherscanApiRoot : URL {
let urlString : String = {
switch self {
case . main : return " https://api-cn.etherscan.com/api "
@ -179,7 +192,7 @@ enum RPCServer: Hashable, CaseIterable {
case . avalanche : return " https://cchain.explorer.avax.network/tx/api "
// T O D O f i x e t h e r s c a n - c o m p a t i b l e A P I e n d p o i n t
case . avalanche_testnet : return " https://cchain.explorer.avax-test.network/tx/api "
case . polygon : return " https://explorer-mainnet.maticvigil.com/api/v2/ "
case . polygon : return " https://explorer-mainnet.maticvigil.com/api/v2 "
case . mumbai_testnet : return " https://explorer-mumbai.maticvigil.com/api/v2 "
}
} ( )
@ -187,56 +200,18 @@ enum RPCServer: Hashable, CaseIterable {
}
// I f E t h e r s c a n , a c t i o n = t o k e n t x f o r E R C 2 0 a n d a c t i o n = t o k e n n f t t x f o r E R C 7 2 1 . I f B l o c k s c o u t - c o m p a t i b l e , a c t i o n = t o k e n t x i n c l u d e s b o t h E R C 2 0 a n d E R C 7 2 1 . t o k e n n f t t x i s n o t s u p p o r t e d .
var getEtherscanURLERC721Events : URL ? {
switch erc721TransactionHistory Type {
var etherscanURLForERC721TransactionHistory : URL ? {
switch etherscanCompatible Type {
case . etherscan :
return etherscanRoot . appendingQueryString ( " module=account&action=tokennfttx " )
return etherscanApi Root . appendingQueryString ( " module=account&action=tokennfttx " )
case . blockscout :
return etherscanRoot . appendingPathComponent ( " transactions " ) . appendingQueryString ( " module=account&action=tokentx " )
return etherscanApiRoot . appendingQueryString ( " module=account&action=tokentx " )
case . unknown :
return nil
}
}
var etherscanContractDetailsWebPageURL : String {
switch self {
case . main : return Constants . mainnetEtherscanContractDetailsWebPageURL
case . ropsten : return Constants . ropstenEtherscanContractDetailsWebPageURL
case . rinkeby : return Constants . rinkebyEtherscanContractDetailsWebPageURL
case . kovan : return Constants . kovanEtherscanContractDetailsWebPageURL
case . xDai : return Constants . xDaiContractPage
case . goerli : return Constants . goerliContractPage
case . poa : return Constants . poaContractPage
case . sokol : return Constants . sokolContractPage
case . classic : return Constants . etcContractPage
case . callisto : return Constants . callistoContractPage
case . artis_sigma1 : return Constants . artisSigma1ContractPage
case . artis_tau1 : return Constants . artisTau1ContractPage
case . binance_smart_chain : return Constants . binanceContractPage
case . binance_smart_chain_testnet : return Constants . binanceTestnetContractPage
case . custom : return Constants . mainnetEtherscanContractDetailsWebPageURL
case . heco_testnet : return Constants . hecoTestnetContractPage
case . heco : return Constants . hecoContractPage
case . fantom : return Constants . fantomContractPage
case . fantom_testnet : return Constants . fantomTestnetContractPage
case . avalanche : return Constants . avalancheContractPage
case . avalanche_testnet : return Constants . avalancheTestnetContractPage
case . polygon : return Constants . maticContractPage
case . mumbai_testnet : return Constants . mumbaiContractPage
}
}
// W e a s s u m e t h a t o n l y E t h e r s c a n s u p p o r t s t h i s a n d o n l y f o r E t h e r e u m m a i n n e t : T h e t o k e n p a g e i n s t e a d o f c o n t r a c t p a g e
var etherscanTokenDetailsWebPageURL : String {
switch self {
case . main :
return Constants . mainnetEtherscanTokenDetailsWebPageURL
case . ropsten , . rinkeby , . kovan , . xDai , . goerli , . poa , . sokol , . classic , . callisto , . artis_sigma1 , . artis_tau1 , . binance_smart_chain , . binance_smart_chain_testnet , . custom , . heco , . heco_testnet , . fantom , . fantom_testnet , . avalanche , . avalanche_testnet , . polygon , . mumbai_testnet :
return etherscanContractDetailsWebPageURL
}
}
private var erc721TransactionHistoryType : EtherscanCompatibleType {
private var etherscanCompatibleType : EtherscanCompatibleType {
switch self {
case . main , . ropsten , . rinkeby , . kovan , . goerli , . fantom , . heco , . heco_testnet :
return . etherscan
@ -247,8 +222,8 @@ enum RPCServer: Hashable, CaseIterable {
}
}
func etherscanAPIURLForTransactionList ( for address : AlphaWallet . Address , startBlock : Int ? ) -> URL ? {
g etE therscanURL. flatMap {
func getEtherscanURLForGeneralTransactionHistory ( for address : AlphaWallet . Address , startBlock : Int ? ) -> URL ? {
etherscanURLForGeneralTransactionHistory . flatMap {
let url = $0 . appendingQueryString ( " address= \( address . eip55String ) &apikey= \( Constants . Credentials . etherscanKey ) " )
if let startBlock = startBlock {
return url ? . appendingQueryString ( " startBlock= \( startBlock ) " )
@ -258,18 +233,19 @@ enum RPCServer: Hashable, CaseIterable {
}
}
func etherscanAPIURLForERC20TxList ( for address : AlphaWallet . Address , startBlock : Int ? ) -> URL ? {
getEtherscanURLERC20Events . flatMap {
var url = " \( $0 ) \( address . eip55String ) &apikey= \( Constants . Credentials . etherscanKey ) "
func getEtherscanURLForTokenTransactionHistory ( for address : AlphaWallet . Address , startBlock : Int ? ) -> URL ? {
etherscanURLForTokenTransactionHistory . flatMap {
let url = $0 . appendingQueryString ( " address= \( address . eip55String ) &apikey= \( Constants . Credentials . etherscanKey ) " )
if let startBlock = startBlock {
url = " \( url ) &startBlock= \( startBlock ) "
return url ? . appendingQueryString ( " startBlock= \( startBlock ) " )
} else {
return url
}
return URL ( string : url )
}
}
func etherscanAPIURLForERC721TxList ( for address : AlphaWallet . Address , startBlock : Int ? ) -> URL ? {
getEtherscanURLERC721Events . flatMap {
func getEtherscanURLForERC721TransactionHistory ( for address : AlphaWallet . Address , startBlock : Int ? ) -> URL ? {
etherscanURLForERC721TransactionHistory . flatMap {
let url = $0 . appendingQueryString ( " address= \( address . eip55String ) &apikey= \( Constants . Credentials . etherscanKey ) " )
if let startBlock = startBlock {
return url ? . appendingQueryString ( " startBlock= \( startBlock ) " )
@ -279,12 +255,28 @@ enum RPCServer: Hashable, CaseIterable {
}
}
func etherscanContractDetailsWebPageURL ( for address : AlphaWallet . Address ) -> URL {
return URL ( string : etherscanContractDetailsWebPageURL + address . eip55String ) !
// C a n ' t u s e h t t p s : / / b l o c k s c o u t . c o m / p o a / d a i / a d d r e s s / e v e n t h o u g h i t u l t i m a t e l y r e d i r e c t s t h e r e b e c a u s e b l o c k s c o u t ( t e s t e d o n 2 0 1 9 0 6 2 0 ) , b l o c k s c o u t . c o m i s o n l y a b l e t o s h o w t h a t U R L a f t e r t h e a d d r e s s h a s b e e n s e a r c h e d ( w i t h t h e ? q = U R L )
func etherscanContractDetailsWebPageURL ( for address : AlphaWallet . Address ) -> URL ? {
switch etherscanCompatibleType {
case . etherscan :
return etherscanWebpageRoot ? . appendingPathComponent ( " address " ) . appendingPathComponent ( address . eip55String )
case . blockscout :
return etherscanWebpageRoot ? . appendingPathComponent ( " search " ) . appendingQueryString ( " q= \( address . eip55String ) " )
case . unknown :
return nil
}
}
func etherscanTokenDetailsWebPageURL ( for address : AlphaWallet . Address ) -> URL {
return URL ( string : etherscanTokenDetailsWebPageURL + address . eip55String ) !
// W e a s s u m e t h a t o n l y E t h e r s c a n s u p p o r t s t h i s a n d o n l y f o r E t h e r e u m m a i n n e t : T h e t o k e n p a g e i n s t e a d o f c o n t r a c t p a g e
// T O D O c h e c k i f o t h e r E t h e r s c a n n e t w o r k s c a n s u p p o r t t h i s
// T O D O c h e c k i f B l o c k s c o u t c a n s u p p o r t t h i s
func etherscanTokenDetailsWebPageURL ( for address : AlphaWallet . Address ) -> URL ? {
switch self {
case . main :
return etherscanWebpageRoot ? . appendingPathComponent ( " token " ) . appendingPathComponent ( address . eip55String )
case . ropsten , . rinkeby , . kovan , . xDai , . goerli , . poa , . sokol , . classic , . callisto , . artis_sigma1 , . artis_tau1 , . binance_smart_chain , . binance_smart_chain_testnet , . custom , . heco , . heco_testnet , . fantom , . fantom_testnet , . avalanche , . avalanche_testnet , . polygon , . mumbai_testnet :
return etherscanContractDetailsWebPageURL ( for : address )
}
}
var priceID : AlphaWallet . Address {
@ -452,7 +444,7 @@ enum RPCServer: Hashable, CaseIterable {
let urlString : String = {
switch self {
case . main , . kovan , . ropsten , . rinkeby , . goerli , . classic , . poa , . xDai , . sokol , . artis_sigma1 , . artis_tau1 , . binance_smart_chain , . binance_smart_chain_testnet , . fantom , . polygon , . heco , . heco_testnet , . callisto :
return etherscanRoot . absoluteString
return etherscanApi Root . absoluteString
case . custom : return " " // E n a b l e ? m a k e o p t i o n a l
case . fantom_testnet : return " https://explorer.testnet.fantom.network/tx/ "
case . avalanche : return " https://cchain.explorer.avax.network/tx/ "