dwnpm
Version:
Decentralized Registry Package Manager (DRPM) helps developers publish, install, find and manage Decentralized Packages (DPKs) published to Decentralized Web Nodes (DWNs). DRPM does this by looking up a Decentralized Identifier (DID) to find its DID docum
156 lines (139 loc) • 5.03 kB
text/typescript
import { Web5 } from '@web5/api';
import { Web5UserAgent } from '@web5/user-agent';
import fsx from 'fs-extra';
import { DRPM_HOME } from '../../config.js';
import { Logger } from '../../utils/logger.js';
import { cleanEndpoint, createPassword, scuid } from '../../utils/misc.js';
import { DhtProfileConnectParams, DidDhtCreateParams, PartialProfileJson } from '../../utils/types.js';
import { Profile } from '../profile.js';
// import cuid from '@bugsnag/cuid';
export class DhtAgent {
userAgent: Web5UserAgent;
recoveryPhrase?: string;
connectedDid?: string;
constructor({ userAgent }: { userAgent: Web5UserAgent }) {
this.userAgent = userAgent;
}
static async create({ dataPath }: { dataPath: string }): Promise<DhtAgent> {
const userAgent = await Web5UserAgent.create({ dataPath });
return new DhtAgent({ userAgent });
}
async launch({ password }: { password: string }): Promise<void> {
try {
if(await this.userAgent.firstLaunch()) {
this.recoveryPhrase = await this.userAgent.initialize({ password });
}
await this.userAgent.start({ password });
} catch (error: any) {
Logger.error(`Failed to setup agent: ${error.message}`);
process.exit(1);
}
}
json(): { userAgent: Web5UserAgent; recoveryPhrase: string; connectedDid: string } {
return {
userAgent : this.userAgent,
recoveryPhrase : this.recoveryPhrase!,
connectedDid : this.connectedDid!
};
}
async identity({ dwnEndpoints }: { dwnEndpoints: string[]; recoveryPhrase: string }): Promise<string> {
try {
const identity = await this.userAgent.identity.create({
didMethod : 'dht',
metadata : { name: 'DRPM' },
didOptions : {
services : [
{
id : 'dwn',
type : 'DecentralizedWebNode',
serviceEndpoint : dwnEndpoints,
enc : '#enc',
sig : '#sig',
}
],
verificationMethods : [
{
algorithm : 'Ed25519',
id : 'sig',
purposes : ['assertionMethod', 'authentication']
},
{
algorithm : 'secp256k1',
id : 'enc',
purposes : ['keyAgreement']
}
]
}
});
this.connectedDid = identity.metadata.connectedDid ?? identity.did.uri;
return this.connectedDid;
} catch (error: any) {
Logger.error(`Failed to create agent identity: ${error.message}`);
process.exit(1);
}
}
}
export class DhtProfile {
// Used by cli drpm profile create to create new DHT profile
static async create(params: DidDhtCreateParams): Promise<PartialProfileJson> {
try {
const dwnEndpoints = params.dwnEndpoints.split(',');
const endpoints = dwnEndpoints
.map((dwnEndpoint) => cleanEndpoint(dwnEndpoint))
.filter(endpoint => !fsx.existsSync(`${DRPM_HOME}/DHT/${endpoint}`));
const endpointPath = endpoints.length
? `${endpoints[0]}/0/DATA/AGENT`
: `${cleanEndpoint(dwnEndpoints[0])}/${scuid()}/DATA/AGENT`;
const dataPath = `${DRPM_HOME}/DHT/${endpointPath}`;
const web5DataPath = params.web5DataPath ?? dataPath;
const password = params.password ?? createPassword();
const dhtAgent = await DhtAgent.create({ dataPath: web5DataPath });
await dhtAgent.launch({ password });
const { recoveryPhrase } = dhtAgent.json() ?? Profile.json.dht.recoveryPhrase;
const connectedDid = await dhtAgent.identity({ dwnEndpoints, recoveryPhrase });
const agent = dhtAgent.userAgent;
const { did } = await Web5.connect({
agent,
password,
connectedDid,
sync : 'off',
didCreateOptions : { dwnEndpoints },
});
Logger.info('Syncing dwn, please wait ...');
await agent.sync.sync();
Logger.info('Syncing complete!');
return {
name : 'dht',
dht : {
did,
password,
web5DataPath,
dwnEndpoints,
recoveryPhrase,
}
};
} catch (error: any) {
Logger.error(`Failed to create DHT profile: ${error.message}`);
throw error;
}
}
// Used by cli in various contexts to use the existing profile to connect to Web5
static async connect({
did, password, dwnEndpoints, web5DataPath
}: DhtProfileConnectParams): Promise<any> {
try {
const dhtAgent = await DhtAgent.create({ dataPath: web5DataPath });
await dhtAgent.launch({ password });
return await Web5.connect({
password,
connectedDid : did,
sync : '30s',
didCreateOptions : { dwnEndpoints },
agent : dhtAgent.userAgent,
});
} catch (error: any) {
Logger.error(`Failed to connect to DHT profile: ${error.message}`);
throw error;
}
}
}