Skip to content

Commit

Permalink
Merge pull request #81 from leo42/Visual-fixes
Browse files Browse the repository at this point in the history
Maestro metadata Provider implementation
  • Loading branch information
leo42 authored Feb 8, 2024
2 parents e2b4c45 + 166ed4d commit f7befec
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 21 deletions.
3 changes: 2 additions & 1 deletion Fe/src/components/SettingsModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function SettingsModal(props) {
<input type="text" placeholder="ogmiosUrl" value={providerConnection.ogmiosUrl ? providerConnection.ogmiosUrl : "" } onChange={(event) => setProviderConnection({...providerConnection, ogmiosUrl: event.target.value})} />
</div>
)}
{ provider === "Maestro" &&( <div>
{ (provider === "Maestro" || metadataProvider === "Maestro") &&( <div>
<input type="text" placeholder="apiKey" value={providerConnection.apiKey ? providerConnection.apiKey : ""} onChange={(event) => setProviderConnection({...providerConnection, apiKey: event.target.value})} />
</div>
)}
Expand Down Expand Up @@ -189,6 +189,7 @@ function SettingsModal(props) {
<select onChange={(event) => setMetadataProvider(event.target.value)} value={metadataProvider} defaultValue={metadataProvider}>
<option value="None">None</option>
<option value="Koios">Koios</option>
<option value="Maestro">Maestro</option>
{ provider && <option value="Blockfrost">Blockfrost</option> }
</select>

Expand Down
14 changes: 8 additions & 6 deletions Fe/src/components/TransactionHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ function TransactionHistory (props) {
input.amount.map( (asset) =>
asset.unit in BalancesOut ? BalancesOut[asset.unit] -= parseInt(asset.quantity) : BalancesOut[asset.unit] = -parseInt(asset.quantity)
)}})
transaction.utxos.outputs.map( (input, index) => {
if ( input.address === address && !input.collateral) {
input.amount.map( (asset) =>
transaction.utxos.outputs.map( (output, index) => {
if ( output.address === address && !output.collateral) {
output.amount.map( (asset) =>
asset.unit in BalancesOut ? BalancesOut[asset.unit] += parseInt(asset.quantity) : BalancesOut[asset.unit] = parseInt(asset.quantity)
)}})
const lovelace = BalancesOut.lovelace
const withdraw = transaction.withdrawals? transaction.withdrawals.amount : 0
const lovelace = BalancesOut.lovelace - withdraw
delete BalancesOut["lovelace"]
Object.keys(BalancesOut).map(item => { if(BalancesOut[item] === 0) {delete BalancesOut[item]} })
const tokens = Object.keys(BalancesOut).map((key, index) => (
Expand Down Expand Up @@ -79,8 +80,9 @@ function TransactionHistory (props) {
}

function loadMoreTransactions(){
setPage(page + 1)
let TxH = getTransactionHistory(address, props.root.state.settings, page )
const newPage = page + 1
setPage(newPage)
let TxH = getTransactionHistory(address, props.root.state.settings, newPage )
TxH.then(transactionHistory => {setTransactions(transactions.concat(transactionHistory))
if (transactionHistory.length < 10) setLoadMore(false)}
)
Expand Down
86 changes: 74 additions & 12 deletions Fe/src/helpers/TransactionHistory.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Lucid } from "lucid-cardano";

async function getTransactionHistory(address, settings, page=0 , limit = 10){
if( settings.metadataProvider === "None"){
console.log("getTransactionHistory", address, settings, page, limit)
if( settings.metadataProvider === "None" ){
return []
}

Expand Down Expand Up @@ -31,7 +34,7 @@ async function getTransactionHistory(address, settings, page=0 , limit = 10){
}else if ( settings.metadataProvider === "Blockfrost"){
const api = settings.api.url
const response = await fetch(
`${api}/addresses/${address}/transactions`,
`${api}/addresses/${address}/transactions?order=acs`,
{
method: "GET",
headers: {
Expand All @@ -40,27 +43,45 @@ async function getTransactionHistory(address, settings, page=0 , limit = 10){
}
);
const json = await response.json();
// return the first 10 transactions if page is not specified
// sort by block height
if (json.error)
return []
json.sort((a,b) => b.block_height - a.block_height)
return await getTransactionDetails(json.slice(page*limit,(page+1)*limit), settings)

if (json.error)
return []
json.sort((a,b) => b.block_height - a.block_height)
return await getTransactionDetails(json.slice(page*limit,(page+1)*limit), settings)
}else if(settings.metadataProvider === "Maestro")
{
const MaestroUrl = `https://${settings.network}.gomaestro-api.org`
const MaestroTxHistory = await fetch(
`${MaestroUrl}/v1/addresses/${address}/transactions?count=${limit}&order=desc` + (page > 0 ? `&cursor=${localStorage.getItem('next_cursor')}` : "" ),
{ headers: {
'Accept': 'application/json',
'api-key': settings.api.apiKey,
} },
).then((res) => res.json());
if (MaestroTxHistory.error)
return []
MaestroTxHistory.data.sort((a,b) => b.slot - a.slot)
//write next_cursor to local storage
localStorage.setItem('next_cursor', MaestroTxHistory.next_cursor);



return await getTransactionDetails(MaestroTxHistory.data, settings)
}


}

async function getTransactionDetails(transactionIds, settings){

let transactionInfo = {...JSON.parse(localStorage.getItem('transactionInfo'))};


let fullTransactionsInfo = transactionIds.map( async (transactionId) => {
if (transactionInfo[transactionId.tx_hash] && transactionInfo[transactionId.tx_hash].provider === settings.metadataProvider ){
return (transactionInfo[transactionId.tx_hash])
}else{

return (transactionInfo[transactionId.tx_hash])
}
else
{
if ( settings.metadataProvider === "Koios"){
const api = settings.network === "Mainnet" ? "https://api.koios.rest/api/v0/tx_utxos" : `https://${settings.network}.koios.rest/api/v0/tx_utxos`
const response = await fetch(
Expand Down Expand Up @@ -124,6 +145,36 @@ async function getTransactionDetails(transactionIds, settings){
transactionInfo[transactionId.tx_hash].provider = "Blockfrost"
localStorage.setItem('transactionInfo', JSON.stringify(transactionInfo));
return transactionInfo[transactionId.tx_hash]
}else if (settings.metadataProvider === "Maestro"){

const MaestroUrl = `https://${settings.network}.gomaestro-api.org`
const MaestroTx = await fetch(
`${MaestroUrl}/v1/transactions/${transactionId.tx_hash}`,
{ headers: {
'Accept': 'application/json',
'api-key': settings.api.apiKey,
} },
).then((res) => res.json());

const lucid = await Lucid.new(
null,
settings.network
);

let fullTransactionInfo = {...transactionId};
fullTransactionInfo.utxos = {}
fullTransactionInfo.utxos.inputs = MaestroTx.data.inputs.map(input => maestroUtxoToUtxo(input) )
fullTransactionInfo.utxos.outputs = MaestroTx.data.outputs.map(input => maestroUtxoToUtxo(input) )
transactionInfo[transactionId.tx_hash] = fullTransactionInfo
transactionInfo[transactionId.tx_hash].fetch_time = Date.now()
transactionInfo[transactionId.tx_hash].block_time = lucid.utils.slotToUnixTime(transactionInfo[transactionId.tx_hash].slot);
transactionInfo[transactionId.tx_hash].provider = "Maestro"
transactionInfo[transactionId.tx_hash].withdrawals = MaestroTx.data.withdrawals[0];

localStorage.setItem('transactionInfo', JSON.stringify(transactionInfo));

return transactionInfo[transactionId.tx_hash]

}
}
})
Expand All @@ -134,6 +185,17 @@ async function getTransactionDetails(transactionIds, settings){
return fullTransactionsInfo
}

function maestroUtxoToUtxo(utxo){
return {
address: utxo.address,
amount: utxo.assets.map(asset => ({ "unit": asset.unit, "quantity" : Math.abs(asset.amount) })),
tx_hash: utxo.tx_hash,
tx_index: utxo.tx_index,
tx_output_index: utxo.tx_output_index
}

}

function koiosUtxosToUtxos(lovelace,asset_list){

let utxos = []
Expand Down
40 changes: 38 additions & 2 deletions Fe/src/helpers/tokenInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ async function getTokenInfo(tokenId){
tokenInfo["provider"] = "Koios"
tokenInfo["fingerprint"] = koiosTokenInfo[0].fingerprint
tokenInfo["image"] = typeof tokenInfo["image"] === "object" ? tokenInfo["image"].join('') : tokenInfo["image"]
tokenInfo["image"] = tokenInfo["image"]?.replace("ipfs/",ipfsGateWay).replace("ipfs://",ipfsGateWay)
tokenInfo["image"] = tokenInfo["image"]?.replace("ipfs://ipfs/","ipfs/").replace("ipfs/",ipfsGateWay).replace("ipfs://",ipfsGateWay)
writeToLocalStorage(tokenId,tokenInfo)
return(tokenInfo)

Expand Down Expand Up @@ -146,7 +146,43 @@ async function getTokenInfo(tokenId){
tokenInfo["fingerprint"] = BlockfrostTokenInfo.fingerprint
tokenInfo["isNft"] = (BlockfrostTokenInfo.quantity) === "1"
tokenInfo["image"] = typeof tokenInfo["image"] === "object" ? tokenInfo["image"].join('') : tokenInfo["image"]
tokenInfo["image"] = tokenInfo["image"]?.replace("ipfs/",ipfsGateWay).replace("ipfs://",ipfsGateWay)
tokenInfo["image"] = tokenInfo["image"]?.replace("ipfs://ipfs/","ipfs/").replace("ipfs/",ipfsGateWay).replace("ipfs://",ipfsGateWay)
writeToLocalStorage(tokenId,tokenInfo)
return(tokenInfo)
}else if (settings.metadataProvider === "Maestro"){
const MaestroUrl = `https://${settings.network}.gomaestro-api.org`
const MaestroTokenData = await fetch(
`${MaestroUrl}/v1/assets/${tokenId}`,
{ headers: {
'Accept': 'application/json',
'api-key': settings.api.apiKey,
} },
).then((res) => res.json());
tokenInfo["fetch_time"] = Date.now()
if(MaestroTokenData.data.token_registry_metadata){
tokenInfo["name"] = MaestroTokenData.data.token_registry_metadata.name
tokenInfo["image"] = "data:image/jpeg;base64," + MaestroTokenData.data.token_registry_metadata.logo.replace(/\s/g, ';')
tokenInfo["decimals"] = MaestroTokenData.data.token_registry_metadata.decimals
}
if (MaestroTokenData.data.asset_standards){
if(MaestroTokenData.data.asset_standards.cip25_metadata){
tokenInfo["name"] = MaestroTokenData.data.asset_standards.cip25_metadata.name
tokenInfo["image"] = MaestroTokenData.data.asset_standards.cip25_metadata.image
}else if(MaestroTokenData.data.asset_standards.cip68_metadata){
tokenInfo["name"] =MaestroTokenData.data.asset_standards.cip68_metadata.name
tokenInfo["image"] = MaestroTokenData.data.asset_standards.cip68_metadata.image
}

}else{
tokenInfo["name"] = MaestroTokenData.data.asset_name_ascii

}

tokenInfo["provider"] = "Maestro"
tokenInfo["fingerprint"] = MaestroTokenData.data.fingerprint
tokenInfo["isNft"] = (MaestroTokenData.data.total_supply) === "1"
tokenInfo["image"] = typeof tokenInfo["image"] === "object" ? tokenInfo["image"].join('') : tokenInfo["image"]
tokenInfo["image"] = tokenInfo["image"]?.replace("ipfs://ipfs/","ipfs/").replace("ipfs/",ipfsGateWay).replace("ipfs://",ipfsGateWay)
writeToLocalStorage(tokenId,tokenInfo)
return(tokenInfo)
}
Expand Down

0 comments on commit f7befec

Please sign in to comment.