@ceramicnetwork/3id-did-resolver
Version:
DID Resolver for the 3ID method
70 lines • 2.2 kB
JavaScript
import * as u8a from 'uint8arrays';
import { LRUCache } from 'least-recent';
const THREEBOX_API_URL = 'https://ipfs.3box.io';
const LIMIT = 100;
const fetchCache = new LRUCache(LIMIT);
const fetchJson = async (url) => {
const cached = fetchCache.get(url);
if (cached)
return cached;
const r = await fetch(url);
if (r.ok) {
const json = await r.json();
fetchCache.set(url, json);
return json;
}
else {
throw new Error('Not a valid 3ID');
}
};
const didDocReq = (cid) => `${THREEBOX_API_URL}/did-doc?cid=${encodeURIComponent(cid)}`;
const ipfsMock = {
dag: {
get: async (cid) => fetchJson(didDocReq(cid)),
},
};
const encodeKey = (key, encryption) => {
const bytes = new Uint8Array(key.length + 2);
if (encryption) {
bytes[0] = 0xec;
}
else {
bytes[0] = 0xe7;
}
bytes[1] = 0x01;
bytes.set(key, 2);
return `z${u8a.toString(bytes, 'base58btc')}`;
};
const compressKey = (key) => {
const xpoint = key.slice(2, 66);
const ypoint = key.slice(66, 130);
const prefix = (ypoint & 1) === 0 ? '02' : '03';
return `${prefix}${xpoint}`;
};
class NotValid3IdError extends Error {
constructor() {
super(`Not a valid 3ID`);
}
}
export async function LegacyResolver(didId, ipfs = ipfsMock) {
const doc = (await ipfs.dag.get(didId)).value;
if (!Array.isArray(doc.publicKey)) {
throw new NotValid3IdError();
}
const signingKey = doc.publicKey.find((e) => e.id.endsWith('signingKey'))?.publicKeyHex;
const encryptionKey = doc.publicKey.find((e) => e.id.endsWith('encryptionKey'))?.publicKeyBase64;
if (!signingKey || !encryptionKey) {
throw new NotValid3IdError();
}
const signingKeyCompressed = compressKey(signingKey);
const signing = encodeKey(u8a.fromString(signingKeyCompressed, 'base16'));
const encryption = encodeKey(u8a.fromString(encryptionKey, 'base64pad'), true);
return {
keyDid: `did:key:${signing}`,
publicKeys: {
[signing.slice(-15)]: signing,
[encryption.slice(-15)]: encryption,
},
};
}
//# sourceMappingURL=legacyResolver.js.map