@ -59,6 +59,8 @@ defmodule Explorer.Token.InstanceMetadataRetriever do
@no_uri_error " no uri "
@no_uri_error " no uri "
@vm_execution_error " VM execution error "
@vm_execution_error " VM execution error "
@ipfs_protocol " ipfs:// "
@ipfs_link " https://ipfs.io/ipfs/ "
# https://eips.ethereum.org/EIPS/eip-1155#metadata
# https://eips.ethereum.org/EIPS/eip-1155#metadata
@erc1155_token_id_placeholder " {id} "
@erc1155_token_id_placeholder " {id} "
@ -100,65 +102,64 @@ defmodule Explorer.Token.InstanceMetadataRetriever do
{ :ok , %{ error : @no_uri_error } }
{ :ok , %{ error : @no_uri_error } }
end
end
def fetch_json ( uri , _hex_token_id )
def fetch_json ( %{ @token_uri = > uri } , hex_token_id ) do
when uri in [
fetch_json_from_uri ( uri , hex_token_id )
%{ @token_uri = > { :error , " (-32015) VM execution error. " } } ,
%{ @uri = > { :error , " (-32015) VM execution error. " } } ,
%{ @token_uri = > { :error , " (-32000) execution reverted " } } ,
%{ @uri = > { :error , " (-32000) execution reverted " } }
] do
{ :ok , %{ error : @vm_execution_error } }
end
end
def fetch_json ( %{ @token_ uri = > { :error , " (-32015) VM execution error. " <> _ } } , _ hex_token_id) do
def fetch_json ( %{ @uri = > uri } , hex_token_id ) do
{ :ok , %{ error : @vm_execution_error } }
fetch_json_from_uri ( uri , hex_token_id )
end
end
def fetch_json ( %{ @uri = > { :error , " (-32015) VM execution error. " <> _ } } , _hex_token_id ) do
# CIDv0 IPFS links # https://docs.ipfs.tech/concepts/content-addressing/#version-0-v0
{ :ok , %{ error : @vm_execution_error } }
def fetch_json ( " Qm " <> _ = result , hex_token_id ) do
end
if String . length ( result ) == 46 do
fetch_json_from_uri ( { :ok , [ @ipfs_link <> result ] } , hex_token_id )
else
Logger . debug ( [ " Unknown metadata format result #{ inspect ( result ) } . " ] , fetcher : :token_instances )
def fetch_json ( %{ @token_uri = > { :error , " (-32000) execution reverted " <> _ } } , _hex_token_id ) do
{ :error , result }
{ :ok , %{ error : @vm_execution_error } }
end
end
end
def fetch_json ( %{ @uri = > { :error , " (-32000) execution reverted " <> _ } } , _hex_token_id ) do
def fetch_json ( result , hex_token_id ) do
{ :ok , %{ error : @vm_execution_error } }
case URI . parse ( result ) do
end
% URI { host : nil } ->
Logger . debug ( [ " Unknown metadata format #{ inspect ( result ) } . " ] , fetcher : :token_instances )
def fetch_json ( %{ @token_uri = > { :ok , [ " http:// " <> _ = token_uri ] } } , hex_token_id ) do
{ :error , result }
fetch_metadata_inner ( token_uri , hex_token_id )
_ ->
fetch_json_from_uri ( { :ok , [ result ] } , hex_token_id )
end
end
end
def fetch_json ( %{ @uri = > { :ok , [ " http:// " <> _ = token_uri ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :error , error } , _hex_token_id ) do
fetch_metadata_inner ( token_uri , hex_token_id )
if error =~ " execution reverted " or error =~ @vm_execution_error do
{ :ok , %{ error : @vm_execution_error } }
else
Logger . debug ( [ " Unknown metadata format error #{ inspect ( error ) } . " ] , fetcher : :token_instances )
{ :error , error }
end
end
end
def fetch_json ( %{ @token_uri = > { :ok , [ " https:// " <> _ = token_uri ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :ok , [ " ' " <> token_uri ] } , hex_token_id ) do
token_uri = token_uri |> String . split ( " ' " ) |> List . first ( )
fetch_metadata_inner ( token_uri , hex_token_id )
fetch_metadata_inner ( token_uri , hex_token_id )
end
end
def fetch_json ( %{ @uri = > { :ok , [ " https :// " <> _ = token_uri ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :ok , [ " http:// " <> _ = token_uri ] } , hex_token_id ) do
fetch_metadata_inner ( token_uri , hex_token_id )
fetch_metadata_inner ( token_uri , hex_token_id )
end
end
def fetch_json ( %{ @token_uri = > { :ok , [ " data:application/json, " <> json ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :ok , [ " https:// " <> _ = token_uri ] } , hex_token_id ) do
decoded_json = URI . decode ( json )
fetch_metadata_inner ( token_uri , hex_token_id )
fetch_json ( %{ @token_uri = > { :ok , [ decoded_json ] } } , hex_token_id )
rescue
e ->
Logger . debug ( [ " Unknown metadata format #{ inspect ( json ) } . " , Exception . format ( :error , e , __STACKTRACE__ ) ] ,
fetcher : :token_instances
)
{ :error , json }
end
end
def fetch_json ( %{ @uri = > { :ok , [ " data:application/json, " <> json ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :ok , [ " data:application/json, " <> json ] } , hex_token_id ) do
decoded_json = URI . decode ( json )
decoded_json = URI . decode ( json )
fetch_json ( %{ @uri = > { :ok , [ decoded_json ] } } , hex_token_id )
fetch_json_from_uri ( { :ok , [ decoded_json ] } , hex_token_id )
rescue
rescue
e ->
e ->
Logger . debug ( [ " Unknown metadata format #{ inspect ( json ) } . " , Exception . format ( :error , e , __STACKTRACE__ ) ] ,
Logger . debug ( [ " Unknown metadata format #{ inspect ( json ) } . " , Exception . format ( :error , e , __STACKTRACE__ ) ] ,
@ -168,10 +169,10 @@ defmodule Explorer.Token.InstanceMetadataRetriever do
{ :error , json }
{ :error , json }
end
end
def fetch_json ( %{ @token_uri = > { :ok , [ " data:application/json;base64, " <> base64_encoded_json ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :ok , [ " data:application/json;base64, " <> base64_encoded_json ] } , hex_token_id ) do
case Base . decode64 ( base64_encoded_json ) do
case Base . decode64 ( base64_encoded_json ) do
{ :ok , base64_decoded } ->
{ :ok , base64_decoded } ->
fetch_json ( %{ @token_uri = > { :ok , [ base64_decoded ] } } , hex_token_id )
fetch_json_from_uri ( { :ok , [ base64_decoded ] } , hex_token_id )
_ ->
_ ->
{ :error , base64_encoded_json }
{ :error , base64_encoded_json }
@ -189,54 +190,15 @@ defmodule Explorer.Token.InstanceMetadataRetriever do
{ :error , base64_encoded_json }
{ :error , base64_encoded_json }
end
end
def fetch_json ( %{ @uri = > { :ok , [ " data:application/json;base64, " <> base64_encoded_json ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :ok , [ " #{ @ipfs_protocol } ipfs/ " <> right ] } , hex_token_id ) do
case Base . decode64 ( base64_encoded_json ) do
{ :ok , base64_decoded } ->
fetch_json ( %{ @uri = > { :ok , [ base64_decoded ] } } , hex_token_id )
_ ->
{ :error , base64_encoded_json }
end
rescue
e ->
Logger . debug (
[ " Unknown metadata format base64 #{ inspect ( base64_encoded_json ) } " , Exception . format ( :error , e , __STACKTRACE__ ) ] ,
fetcher : :token_instances
)
{ :error , base64_encoded_json }
end
def fetch_json ( %{ @token_uri = > { :ok , [ " ipfs://ipfs/ " <> right ] } } , hex_token_id ) do
fetch_from_ipfs ( right , hex_token_id )
fetch_from_ipfs ( right , hex_token_id )
end
end
def fetch_json ( %{ @uri = > { :ok , [ " ipfs://ipfs/ " <> right ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :ok , [ @ipfs_protocol <> right ] } , hex_token_id ) do
fetch_from_ipfs ( right , hex_token_id )
fetch_from_ipfs ( right , hex_token_id )
end
end
def fetch_json ( %{ @token_uri = > { :ok , [ " ipfs:// " <> right ] } } , hex_token_id ) do
defp fetch_json_from_uri ( { :ok , [ json ] } , hex_token_id ) do
fetch_from_ipfs ( right , hex_token_id )
end
def fetch_json ( %{ @uri = > { :ok , [ " ipfs:// " <> right ] } } , hex_token_id ) do
fetch_from_ipfs ( right , hex_token_id )
end
def fetch_json ( %{ @token_uri = > { :ok , [ json ] } } , hex_token_id ) do
{ :ok , json } = decode_json ( json )
check_type ( json , hex_token_id )
rescue
e ->
Logger . debug ( [ " Unknown metadata format #{ inspect ( json ) } . " , Exception . format ( :error , e , __STACKTRACE__ ) ] ,
fetcher : :token_instances
)
{ :error , json }
end
def fetch_json ( %{ @uri = > { :ok , [ json ] } } , hex_token_id ) do
{ :ok , json } = decode_json ( json )
{ :ok , json } = decode_json ( json )
check_type ( json , hex_token_id )
check_type ( json , hex_token_id )
@ -249,14 +211,14 @@ defmodule Explorer.Token.InstanceMetadataRetriever do
{ :error , json }
{ :error , json }
end
end
def fetch_json ( result , _hex_token_id ) do
defp fetch_json_from_uri ( uri , _hex_token_id ) do
Logger . debug ( [ " Unknown metadata format #{ inspect ( result ) } . " ] , fetcher : :token_instances )
Logger . debug ( [ " Unknown metadata uri format #{ inspect ( uri ) } . " ] , fetcher : :token_instances )
{ :error , result }
{ :error , uri }
end
end
defp fetch_from_ipfs ( ipfs_uid , hex_token_id ) do
defp fetch_from_ipfs ( ipfs_uid , hex_token_id ) do
ipfs_url = " https://ipfs.io/ipfs/ " <> ipfs_uid
ipfs_url = @ipfs_link <> ipfs_uid
fetch_metadata_inner ( ipfs_url , hex_token_id )
fetch_metadata_inner ( ipfs_url , hex_token_id )
end
end