feat(footer): Retrieving IPFS CID from BCH blockchain

This commit is contained in:
Chris Troutner
2022-09-03 12:25:39 -07:00
parent bd4939367a
commit df64714b1d
7 changed files with 175 additions and 38 deletions
+1 -1
View File
@@ -3,6 +3,7 @@
"version": "2.0.1",
"dependencies": {
"axios": "0.27.2",
"bch-message-lib": "2.2.1",
"bootstrap": "5.2.0",
"query-string": "7.1.1",
"react": "18.2.0",
@@ -35,7 +36,6 @@
]
},
"devDependencies": {
"bch-message-lib": "2.2.1",
"minimal-slp-wallet": "5.0.3",
"standard": "17.0.0",
"web3.storage": "4.3.0"
+3 -2
View File
@@ -103,7 +103,8 @@ class App extends React.Component {
// This is a macro object that is passed to all child components. It gathers
// all the data and handlers used throughout the app.
const appData = {
servers: this.state.servers // Alternative back end servers
servers: this.state.servers, // Alternative back end servers
wallet: this.state.wallet
}
return (
@@ -119,7 +120,7 @@ class App extends React.Component {
}
<SelectServerButton menuHandler={this.onMenuClick} />
<Footer />
<Footer appData={appData} />
</>
)
}
-35
View File
@@ -1,35 +0,0 @@
/*
A footer section for the SPA
*/
// Global npm libraries
import React from 'react'
import { Container, Row, Col } from 'react-bootstrap'
const IPFS_CID = 'bafybeibkck6ylwqmpkqglvsvb7wc5xecb65uypg7fbcembuj7u4xuh2evq'
class Footer extends React.Component {
render () {
return (
<Container style={{ backgroundColor: '#ddd' }}>
<Row style={{ padding: '25px' }}>
<Col>
<h6>Site Mirrors</h6>
<ul>
<li><a href={`https://${IPFS_CID}.ipfs.dweb.link/`} target='_blank' rel='noreferrer'>Filecoin</a></li>
</ul>
</Col>
<Col>
<h6>Source Code</h6>
<ul>
<li><a href='https://github.com/Permissionless-Software-Foundation/react-bootstrap-web3-spa' target='_blank' rel='noreferrer'>GitHub</a></li>
</ul>
</Col>
</Row>
</Container>
)
}
}
export default Footer
+70
View File
@@ -0,0 +1,70 @@
/*
This service file contains functions for retrieving an IPFS hash from the
BCH blockchain, in a fasion similar to PS001:
https://github.com/Permissionless-Software-Foundation/specifications/blob/master/ps001-media-sharing.md
*/
// Global npm libraries
import BchMessage from 'bch-message-lib'
// Local libraries
import AppUtil from '../../util'
class Memo {
constructor (config) {
this.config = config
// Encapsulate dependencies
this.util = new AppUtil()
}
// Instantiate the bch-message-lib library.
async initialize (wallet) {
try {
// Throw an error if this class is instantiated without passing a BCH address.
if (!this.config || !this.config.bchAddr) {
throw new Error('Must pass a BCH address to Memo constructor.')
} else {
this.bchAddr = this.config.bchAddr
}
this.wallet = wallet
this.bchMessage = new BchMessage({ wallet })
} catch (err) {
console.error('Error in get-cid.js/initialize(): ', err.message)
// console.log('Waiting 5 seconds before trying again.')
// await this.util.sleep(5000)
// this.initialize()
}
}
// Walk the transactions associated with an address until a proper IPFS hash is
// found. If one is not found, will return false.
async findHash () {
try {
console.log(`Finding latest IPFS hash for address: ${this.bchAddr}...`)
const txs = await this.bchMessage.memo.memoRead(
this.bchAddr,
'IPFS UPDATE'
)
// console.log(`txs: ${JSON.stringify(txs, null, 2)}`)
// If the array is empty, then return false.
if (txs.length === 0) return false
const hash = txs[0].subject
console.log(`...found this IPFS hash: ${hash}`)
// The transactions should automatically be sorted by the bchMessage
// library. So Just return the subject.
return hash
} catch (err) {
console.warn('Could not find IPFS hash in transaction history.')
return false
}
}
}
export default Memo
+75
View File
@@ -0,0 +1,75 @@
/*
A footer section for the SPA
*/
// Global npm libraries
import React, { useEffect, useState } from 'react'
import { Container, Row, Col } from 'react-bootstrap'
// Local libraries
import config from '../../config'
import Memo from './get-cid'
function Footer (props) {
const [ipfsCid, setIpfsCid] = useState(config.ipfsCid)
const wallet = props.appData.wallet
// Retrieve the most up-to-date CID for the app on Filecoin from the BCH blockchain.
useEffect(() => {
async function fetchData () {
try {
const hash = await getUpdatedUrl(wallet)
setIpfsCid(hash)
} catch (err) {
console.error('Error trying to retrieve Filecoin CID for the app from the BCH blockchain.')
}
}
fetchData()
}, [wallet])
return (
<Container style={{ backgroundColor: '#ddd' }}>
<Row style={{ padding: '25px' }}>
<Col>
<h6>Site Mirrors</h6>
<ul>
<li><a href={`https://${ipfsCid}.ipfs.dweb.link/`} target='_blank' rel='noreferrer'>Filecoin</a></li>
</ul>
</Col>
<Col>
<h6>Source Code</h6>
<ul>
<li><a href='https://github.com/Permissionless-Software-Foundation/react-bootstrap-web3-spa' target='_blank' rel='noreferrer'>GitHub</a></li>
</ul>
</Col>
</Row>
</Container>
)
}
async function getUpdatedUrl (wallet) {
try {
// Exit if the wallet is not initialized.
if (!wallet) return
// Initialize the memo library for retrieving data from the BCH blockchain.
const memo = new Memo({ bchAddr: config.appBchAddr })
await memo.initialize(wallet)
const hash = await memo.findHash()
if (!hash) {
console.error(
`Could not find IPFS hash in transactions for address ${config.appBchAddr}`
)
return false
}
// console.log(`latest IPFS hash: ${hash}`)
return hash
} catch (err) {
console.log('Error in getUpdatedUrl(): ', err)
}
}
export default Footer
+13
View File
@@ -0,0 +1,13 @@
/*
Global configuration settings for this app.
*/
const config = {
// Default IPFS CID for the app. This will be overwritten by dynamic lookup.
ipfsCid: 'bafybeibya4cwro6rgqfaazqxckcchy6qo5sz2aqc4dx7ptcvpns5peqcz4',
// BCH address used to point to the latest version of the IPFS CID.
appBchAddr: 'bitcoincash:qztv87ppjh82v527jq2drp4u8rzzn63r5cmhth2zzm'
}
export default config
+13
View File
@@ -0,0 +1,13 @@
/*
A utility library for holding functions that are commonly used by many different
areas of the app.
*/
class AppUtil {
// Returns a promise that resolves 'ms' milliseconds.
sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
}
export default AppUtil