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
119 lines (106 loc) • 4.07 kB
text/typescript
import cuid from '@bugsnag/cuid';
import { AgentDidApi, AgentDidResolverCache, DwnDidStore } from '@web5/agent';
import { Web5 } from '@web5/api';
import { BearerDid, DidDht, DidJwk } from '@web5/dids';
import { Web5UserAgent } from '@web5/user-agent';
import { exists } from 'fs-extra';
import { DRPM_HOME } from '../../config.js';
import { DidWebFacade } from '../../utils/did/did-web-facade.js';
import { Logger } from '../../utils/logger.js';
import { createPassword } from '../../utils/misc.js';
import { DidWebConnectOptions, DidWebCreateParams, ProfileJson } from '../../utils/types.js';
export class WebAgent {
userAgent: Web5UserAgent;
recoveryPhrase?: string;
connectedDid?: string;
constructor({ userAgent }: { userAgent: Web5UserAgent }) {
this.userAgent = userAgent;
}
static async create({ dataPath }: { dataPath: string }): Promise<WebAgent> {
const agentDid = await BearerDid.import({ portableDid: await DidJwk.create() });
const didApi = new AgentDidApi({
store : new DwnDidStore(),
didMethods : [DidDht, DidJwk, DidWebFacade],
resolverCache : new AgentDidResolverCache({ location: `${dataPath}/DID_RESOLVERCACHE` }),
});
const userAgent = await Web5UserAgent.create({ dataPath, agentDid, didApi});
return new WebAgent({ 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!
};
}
}
export class WebProfile {
// Helper function to create a new Web profile
static async create(params: DidWebCreateParams): Promise<Partial<ProfileJson>> {
try {
const password = params.password ?? createPassword();
const connectedDid = params.did;
const dataPath = `${DRPM_HOME}/DATA/WEB/AGENT/${connectedDid}`;
const dwnEndpoints = params.dwnEndpoints.split(',');
const altDataPath = await exists(dataPath) ? `${dataPath}/${cuid()}` : `${dataPath}/MAIN`;
const web5DataPath = params.web5DataPath ?? altDataPath;
const webAgent = await WebAgent.create({ dataPath: web5DataPath });
await webAgent.launch({ password });
const { recoveryPhrase: aPhrase } = webAgent.json();
const agent = webAgent.userAgent;
const { did, recoveryPhrase: cPhrase } = 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 {
current : 'web',
web : {
did,
password,
web5DataPath,
dwnEndpoints,
recoveryPhrase : aPhrase ?? cPhrase
}
};
} catch (error: any) {
Logger.error(`Failed to create WEB 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
}: DidWebConnectOptions): Promise<any> {
try {
const webAgent = await WebAgent.create({ dataPath: web5DataPath });
await webAgent.launch({ password });
return await Web5.connect({
password,
connectedDid : did,
sync : '30s',
didCreateOptions : { dwnEndpoints },
agent : webAgent.userAgent,
});
} catch (error: any) {
Logger.error(`Failed to connect to WEB profile: ${error.message}`);
throw error;
}
}
}