Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add IPFS helper function #86

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
},
"dependencies": {
"@babel/runtime": "^7.1.2",
"axios": "^0.19.0",
"bn.js": "^4.11.8",
"date-fns": "2.0.0-alpha.22",
"web3-eth": "^1.2.1",
Expand Down
7 changes: 5 additions & 2 deletions src/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import formatPct from './formatPct'
import tokenAmount from './tokenAmount'
import transformTime from './transformTime'
import radspec from './radspec'
import parseIpfs from './parseIpfs'

const defaultHelpers = {
formatDate,
Expand All @@ -14,7 +15,8 @@ const defaultHelpers = {
formatPct,
fromHex,
radspec,
echo
echo,
parseIpfs
}

export {
Expand All @@ -27,5 +29,6 @@ export {
fromHex,
radspec,
transformTime,
tokenAmount
tokenAmount,
parseIpfs
}
52 changes: 52 additions & 0 deletions src/helpers/parseIpfs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import axios from 'axios'
import Web3Utils from 'web3-utils'

// default endpoints to be queried
const ipfsEndpoints = ['https://ipfs.autark.xyz:5001/api/v0']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this feature, but I don't think it is a good practice to hardcode the autark ipfs node here.

Copy link
Author

@topocount topocount Feb 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was using that for my own tests, but Aragon One is welcome to add the api endpoints they maintain. I just left it in because @sohkai usually puts together suggested changes for stuff like this, and this way it passes tests upon submission, since it's an endpoint I have server-side access to


export default () =>
async (cid, node = '', ...keys) => {
node && ipfsEndpoints.push(node)
let rejectedPromises = 0
const results = await Promise.all(
ipfsEndpoints.map(async ipfsEndpoint => {
const ipfsQuery = `${ipfsEndpoint}/cat?arg=${cid}`
try {
const { data } = await axios.get(ipfsQuery)
return getValue(data, keys, ipfsQuery)
} catch (err) {
return ++rejectedPromises < ipfsEndpoints.length
? null : {
type: 'string',
value: `failed getting data from IPFS: ${err}`
}
}
})
)
return results.reduce((finalResult, candidate) => candidate || finalResult)
}

const getValue = (data, keys = [], ipfsQuery) => {
const key = keys.shift()
if (!key) {
switch (typeof data) {
case 'string':
return Web3Utils.isAddress(data)
? {
type: 'address',
value: Web3Utils.toChecksumAddress(data)
}
: {
type: 'string',
value: data
}
default:
return {
type: 'string',
value: ipfsQuery
}
}
}

return data[key] ? getValue(data[key], keys, ipfsQuery) : { value: `failed to find value for key: ${key}`, type: 'string' }
}
34 changes: 34 additions & 0 deletions test/examples/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,40 @@ const cases = [
source: "`_bool ? 'h' + _var + 'o' : 'bye'`",
bindings: { _bool: bool(true), _var: string('ell') }
}, 'hello'],
[{
source: 'parse this ipfs hash: `@parseIpfs(test)`',
bindings: { test: string('Qmc3zqKcwzbbvw3MQm3hXdg8BQoFjGdZiGdAfXAyAGGdLi') }
}, 'parse this ipfs hash: Don\'t we all.'],
[{
source: 'get registry address: `@parseIpfs(test,"", "env", "registry")`',
bindings: {
test: string('QmWP9roMebu5LyV6Q4RNooAw6yj18zKUqXqAc5Lxy1YVFh'),
}
}, 'get registry address: 0x5f6F7E8cc7346a11ca2dEf8f827b7a0b612c56a1'],
[{
source: 'works with invalid custom node: `@parseIpfs(test,"http://invalidaddress", "env", "registry")`',
bindings: {
test: string('QmWP9roMebu5LyV6Q4RNooAw6yj18zKUqXqAc5Lxy1YVFh'),
}
}, 'works with invalid custom node: 0x5f6F7E8cc7346a11ca2dEf8f827b7a0b612c56a1'],
[{
source: 'fails to get networkId: `@parseIpfs(test,"", "env", "networkId")` (undefined key)',
bindings: {
test: string('QmWP9roMebu5LyV6Q4RNooAw6yj18zKUqXqAc5Lxy1YVFh'),
}
}, 'fails to get networkId: failed to find value for key: networkId (undefined key)'],
[{
source: 'fails to get registry address: `@parseIpfs(test,"", "env", "registry")` (invalid CID)',
bindings: {
test: string('Qm'),
}
}, 'fails to get registry address: failed getting data from IPFS: Error: Request failed with status code 500 (invalid CID)'],
[{
source: 'returns links for non-string values: `@parseIpfs(test,"", "env")`',
bindings: {
test: string('QmWP9roMebu5LyV6Q4RNooAw6yj18zKUqXqAc5Lxy1YVFh'),
}
}, 'returns links for non-string values: https://ipfs.autark.xyz:5001/api/v0/cat?arg=QmWP9roMebu5LyV6Q4RNooAw6yj18zKUqXqAc5Lxy1YVFh'],

// External calls with multiple return values
[{
Expand Down