Skip to content

Commit 673dc59

Browse files
committedFeb 24, 2019
feat: isIPFS.peerMultiaddr(input)
This adds `peerMultiaddr` check for easy validation of IPFS peer addresses. It is a think wrapper on top of generic `multiaddr` check coupled with `mafmt.IPFS.matches(multiaddr)` Details behind `mafmt.IPFS` can be found at https://github.com/multiformats/js-mafmt#api License: MIT Signed-off-by: Marcin Rataj <lidel@lidel.org>
1 parent 820d475 commit 673dc59

File tree

4 files changed

+107
-7
lines changed

4 files changed

+107
-7
lines changed
 

‎README.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ isIPFS.multiaddr('/ip4/127.0.0.1/udp/1234/http') // true
102102
isIPFS.multiaddr('/ip6/::1/udp/1234') // true
103103
isIPFS.multiaddr('ip6/::1/udp/1234') // false
104104
isIPFS.multiaddr('/yoloinvalid/::1/udp/1234') // false
105+
106+
isIPFS.peerMultiaddr('/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4') // true
107+
isIPFS.peerMultiaddr('/ip4/127.0.0.1/tcp/1234/ws/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj') // true
108+
isIPFS.peerMultiaddr('/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4/p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj') // true
109+
isIPFS.peerMultiaddr('/ip4/127.0.0.1/udp/1234') // false
105110
```
106111

107112
# API
@@ -121,7 +126,7 @@ Returns `true` if the provided string is a valid `multihash` or `false` otherwis
121126

122127
### `isIPFS.cid(hash)`
123128

124-
Returns `true` if the provided string or [`CID`](https://github.com/ipld/js-cid) is a valid [CID](https://docs.ipfs.io/guides/concepts/cid/) or `false` otherwise.
129+
Returns `true` if the provided string or [`CID`](https://github.com/ipld/js-cid) represents a valid [CID](https://docs.ipfs.io/guides/concepts/cid/) or `false` otherwise.
125130

126131
### `isIPFS.base32cid(hash)`
127132

@@ -182,7 +187,11 @@ Returns `true` if the provided string includes a valid IPNS subdomain or `false`
182187

183188
### `isIPFS.multiaddr(addr)`
184189

185-
Returns `true` if the provided `string`, [`Multiaddr`](https://github.com/multiformats/js-multiaddr) or `Buffer` includes a valid [multiaddr](https://multiformats.io/multiaddr/) or `false` otherwise.
190+
Returns `true` if the provided `string`, [`Multiaddr`](https://github.com/multiformats/js-multiaddr) or `Buffer` represents a valid [multiaddr](https://multiformats.io/multiaddr/) or `false` otherwise.
191+
192+
### `isIPFS.peerMultiaddr(addr)`
193+
194+
Returns `true` if the provided `string`, [`Multiaddr`](https://github.com/multiformats/js-multiaddr) or `Buffer` represents a valid "IPFS Peer" multiaddr (matching [`IPFS` format from `mafmt`](https://github.com/multiformats/js-mafmt#api)) or `false` otherwise.
186195

187196
# License
188197

‎package.json

+6-5
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,17 @@
3030
"author": "Francisco Dias <francisco@baiodias.com> (http://franciscodias.net/)",
3131
"license": "MIT",
3232
"dependencies": {
33-
"bs58": "4.0.1",
33+
"bs58": "^4.0.1",
3434
"cids": "~0.5.6",
35-
"multiaddr": "6.0.4",
35+
"mafmt": "^6.0.6",
36+
"multiaddr": "^6.0.4",
3637
"multibase": "~0.6.0",
3738
"multihashes": "~0.4.13"
3839
},
3940
"devDependencies": {
40-
"aegir": "15.0.1",
41-
"chai": "4.1.2",
42-
"pre-commit": "1.2.2"
41+
"aegir": "^18.2.0",
42+
"chai": "^4.2.0",
43+
"pre-commit": "^1.2.2"
4344
},
4445
"repository": {
4546
"type": "git",

‎src/index.js

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const base58 = require('bs58')
44
const multihash = require('multihashes')
55
const multibase = require('multibase')
66
const Multiaddr = require('multiaddr')
7+
const mafmt = require('mafmt')
78
const CID = require('cids')
89

910
const urlPattern = /^https?:\/\/[^/]+\/(ip(f|n)s)\/((\w+).*)/
@@ -57,6 +58,15 @@ function isMultiaddr (input) {
5758
return false
5859
}
5960

61+
function isPeerMultiaddr (input) {
62+
if (!isMultiaddr(input)) return false
63+
if (input instanceof Buffer) {
64+
// mafmt does not support Buffer input
65+
input = new Multiaddr(input)
66+
}
67+
return mafmt.IPFS.matches(input)
68+
}
69+
6070
function isIpfs (input, pattern, protocolMatch = defaultProtocolMatch, hashMatch = defaultHashMath) {
6171
const formatted = convertToString(input)
6272
if (!formatted) {
@@ -132,6 +142,7 @@ const ipnsSubdomain = (url) => isIpns(url, fqdnPattern, fqdnProtocolMatch, fqdnH
132142
module.exports = {
133143
multihash: isMultihash,
134144
multiaddr: isMultiaddr,
145+
peerMultiaddr: isPeerMultiaddr,
135146
cid: isCID,
136147
base32cid: (cid) => (isMultibase(cid) === 'base32' && isCID(cid)),
137148
ipfsSubdomain: ipfsSubdomain,

‎test/test-multiaddr.spec.js

+79
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,82 @@ describe('ipfs multiaddr', () => {
6262
done()
6363
})
6464
})
65+
66+
describe('ipfs peerMultiaddr', () => {
67+
// https://github.com/multiformats/js-mafmt/blob/v6.0.6/test/index.spec.js#L137
68+
const goodCircuit = [
69+
'/p2p-circuit',
70+
'/p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
71+
'/p2p-circuit/ip4/127.0.0.1/tcp/20008/ws/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
72+
'/p2p-circuit/ip4/1.2.3.4/tcp/3456/ws/p2p-webrtc-star/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
73+
'/p2p-circuit/ip4/1.2.3.4/tcp/3456/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
74+
'/p2p-circuit/ip4/127.0.0.1/tcp/4002/ipfs/QmddWMcQX6orJGHpETYMyPgXrCXCtYANMFVDCvhKoDwLqA',
75+
'/p2p-circuit/ipfs/QmddWMcQX6orJGHpETYMyPgXrCXCtYANMFVDCvhKoDwLqA',
76+
'/p2p-circuit/ip4/127.0.0.1/tcp/20008/ws/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj/' +
77+
'p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj'
78+
]
79+
// https://github.com/multiformats/js-mafmt/blob/v6.0.6/test/index.spec.js#L157
80+
const validPeerMultiaddrs = [
81+
'/ip4/127.0.0.1/tcp/20008/ws/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj',
82+
'/ip4/1.2.3.4/tcp/3456/ws/p2p-webrtc-star/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
83+
'/ip4/1.2.3.4/tcp/3456/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4',
84+
'/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4/p2p-circuit',
85+
'/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4/p2p-circuit/ipfs/QmUjNmr8TgJCn1Ao7DvMy4cjoZU15b9bwSCBLE3vwXiwgj'
86+
].concat(goodCircuit)
87+
88+
it('isIPFS.peerMultiaddr should match a string with a valid IPFS peer', (done) => {
89+
for (let addr of validPeerMultiaddrs) {
90+
const actual = isIPFS.peerMultiaddr(addr)
91+
expect(actual, `isIPFS.peerMultiaddr(${addr})`).to.equal(true)
92+
}
93+
done()
94+
})
95+
96+
it('isIPFS.peerMultiaddr should match a valid Multiaddr instance', (done) => {
97+
for (let addr of validPeerMultiaddrs) {
98+
const ma = new Multiaddr(addr)
99+
const actual = isIPFS.peerMultiaddr(ma)
100+
expect(actual, `isIPFS.peerMultiaddr(${addr})`).to.equal(true)
101+
}
102+
done()
103+
})
104+
105+
it('isIPFS.peerMultiaddr should match a Buffer with multiaddr', (done) => {
106+
for (let addr of validPeerMultiaddrs) {
107+
const ma = new Multiaddr(addr)
108+
const actual = isIPFS.peerMultiaddr((Buffer.from(ma.buffer)))
109+
expect(actual, `isIPFS.peerMultiaddr(${addr})`).to.equal(true)
110+
}
111+
done()
112+
})
113+
114+
it('isIPFS.peerMultiaddr should not match random Buffer', (done) => {
115+
const actual = isIPFS.peerMultiaddr(Buffer.from('randombuffer'))
116+
expect(actual).to.equal(false)
117+
done()
118+
})
119+
120+
it('isIPFS.peerMultiaddr should not match an invalid multiaddr (no initial slash)', (done) => {
121+
const actual = isIPFS.peerMultiaddr('ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4')
122+
expect(actual).to.equal(false)
123+
done()
124+
})
125+
126+
it('isIPFS.peerMultiaddr should not match an invalid multiaddr (unknown namespace)', (done) => {
127+
const actual = isIPFS.peerMultiaddr('/yoloinvalid/1.2.3.4/tcp/3456/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSoooo4')
128+
expect(actual).to.equal(false)
129+
done()
130+
})
131+
132+
it('isIPFS.peerMultiaddr should not match an invalid multiaddr', (done) => {
133+
const actual = isIPFS.peerMultiaddr('noop')
134+
expect(actual).to.equal(false)
135+
done()
136+
})
137+
138+
it('isIPFS.peerMultiaddr should not match an invalid multiaddr data type', (done) => {
139+
const actual = isIPFS.peerMultiaddr(4)
140+
expect(actual).to.equal(false)
141+
done()
142+
})
143+
})

0 commit comments

Comments
 (0)
Please sign in to comment.