sui-direct
Version:
Decentralized version control system on SUI blockchain
244 lines (243 loc) • 9.4 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* Communication with Node */
const path_1 = require("path");
const fs_1 = require("fs");
const to_string_1 = require("uint8arrays/to-string");
const from_string_1 = require("uint8arrays/from-string");
const json_1 = __importDefault(require("../utils/json"));
const colors_1 = require("../utils/colors");
const helpers_1 = require("../utils/helpers");
async function imports() {
const [{ createLibp2p }, { tcp },
// { ping },
// { kadDHT },
{ identify }, { noise }, { yamux }, { multiaddr }, { createFromJSON, createEd25519PeerId }, { privateKeyFromProtobuf },] = await (0, helpers_1.initDynamicImports)([
"libp2p",
"@libp2p/tcp",
// "@libp2p/ping",
// "@libp2p/kad-dht",
"@libp2p/identify",
"@chainsafe/libp2p-noise",
"@chainsafe/libp2p-yamux",
"@multiformats/multiaddr",
"@libp2p/peer-id-factory",
"@libp2p/crypto/keys",
]);
return {
createLibp2p,
tcp,
// ping,
// kadDHT,
identify,
noise,
yamux,
multiaddr,
createFromJSON,
createEd25519PeerId,
privateKeyFromProtobuf,
};
}
class P2P {
constructor() {
this.nodePeerID = "";
this.peerID = null;
this.peerPrivKey = null;
this.libp2p = null;
this.connection = null;
// Protocols
this.HANDSHAKE_PROTOCOL = "/handshake/1.0.0";
this.NONCE_PROTOCOL = "/nonce/1.0.0";
this.SIGNATURE_PROTOCOL = "/signature/1.0.0";
this.VALIDATE_PROTOCOL = "/validate/1.0.0";
this.PUSH_PROTOCOL = "/push/1.0.0";
this.PULL_PROTOCOL = "/pull/1.0.0";
this.RENAME_PROTOCOL = "/rename/1.0.0";
this.config = json_1.default.getConfig();
}
async sink(stream, data) {
await stream.sink((async function* () {
yield (0, from_string_1.fromString)(data);
})());
}
async parseChunk(stream) {
let data = "";
for await (const chunk of stream.source) {
data += (0, to_string_1.toString)(chunk.subarray());
}
try {
return JSON.parse(data);
}
catch (e) {
return data;
}
}
async generatePeerID() {
if (this.peerID)
return;
const config = json_1.default.getConfig();
const { createFromJSON, privateKeyFromProtobuf, createEd25519PeerId } = await imports();
if (config === null || config === void 0 ? void 0 : config.peerID) {
this.peerID = await createFromJSON(config.peerID);
this.peerPrivKey = await privateKeyFromProtobuf(Buffer.from(config.peerID.privKey, "base64"));
}
else {
this.peerID = (await createEd25519PeerId());
this.peerPrivKey = await privateKeyFromProtobuf(this.peerID.privateKey);
json_1.default.setConfig({
...config,
peerID: {
id: this.peerID.toString(),
privKey: Buffer.from(this.peerID.privateKey).toString("base64"),
pubKey: Buffer.from(this.peerID.publicKey).toString("base64"),
},
});
}
}
async getNodePeerID() {
var _a;
const req = await fetch(`${this.config.nodehttp}/peer-id`);
this.nodePeerID = (_a = (await req.json())) === null || _a === void 0 ? void 0 : _a.id;
if (!this.nodePeerID)
return null;
return this.nodePeerID;
}
async init() {
if (this.libp2p && this.connection)
return {
peerID: this.peerID.toString(),
nodePeerID: this.nodePeerID,
connection: this.connection,
};
return new Promise(async (resolve, reject) => {
const { createLibp2p, tcp, identify, noise, yamux, multiaddr } = await imports();
await this.generatePeerID();
const nodePeerID = this.nodePeerID || (await this.getNodePeerID());
if (!nodePeerID) {
console.log(colors_1.colorize.errorIcon("Node is offline or not reachable."));
return reject();
}
this.libp2p = (await createLibp2p({
privateKey: this.peerPrivKey,
addresses: {
listen: [],
},
transports: [tcp()],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
services: {
identify: identify(),
},
}));
await this.libp2p.start();
// Node address
const ip = this.config.node.split("//")[1].split(":")[0];
const port = this.config.node.split("//")[1].split(":")[1];
const remoteAddr = multiaddr(`/ip4/${ip}/tcp/${port}/p2p/${nodePeerID}`);
this.connection = await this.libp2p.dial(remoteAddr);
// Handshake
const stream = await this.connection.newStream(this.HANDSHAKE_PROTOCOL);
await this.sink(stream, JSON.stringify({ peerID: this.peerID.toString() }));
// Listen for incoming messages
const response = await this.parseChunk(stream);
if ((response === null || response === void 0 ? void 0 : response.status) !== "ok") {
console.error(colors_1.colorize.errorIcon("Failed to connect to node."));
return reject();
}
return resolve({
peerID: this.peerID.toString(),
nodePeerID: this.nodePeerID,
connection: this.connection,
});
});
}
// Helper method to receive streamed content
async receiveStreamedContent(stream) {
const chunks = [];
let totalSize = 0;
for await (const chunk of stream.source) {
console.log(totalSize);
let buffer;
// Handle different chunk types
if (chunk.constructor.name === "Uint8ArrayList") {
if (chunk.bufs && chunk.bufs.length > 0) {
buffer = Buffer.concat(chunk.bufs);
}
else {
buffer = Buffer.from(chunk.slice());
}
}
else if (chunk instanceof Buffer) {
buffer = chunk;
}
else if (chunk instanceof Uint8Array) {
buffer = Buffer.from(chunk);
}
else {
buffer = Buffer.from(chunk);
}
totalSize += buffer.length;
chunks.push(buffer);
}
return Buffer.concat(chunks);
}
// Helper method to process cloned content
async processClonedContent(id, zipBuffer) {
const [{ writeFileSync }, { extractZipToFolder }] = await Promise.all([
Promise.resolve().then(() => __importStar(require("fs"))).then(fs => ({ writeFileSync: fs.writeFileSync })),
Promise.resolve().then(() => __importStar(require("../utils/zip"))).then(zipModule => ({
extractZipToFolder: zipModule.extractZipToFolder,
})),
]);
// Create temporary zip file
const tempZipPath = (0, path_1.join)(process.cwd(), `${id}-temp.zip`);
writeFileSync(tempZipPath, zipBuffer);
// Extract to target directory
const extractPath = (0, path_1.join)(process.cwd(), id);
await extractZipToFolder(tempZipPath, extractPath);
try {
(0, fs_1.rmSync)(tempZipPath, { force: true });
}
catch (e) {
console.log(colors_1.colorize.warning("Failed to clean up temporary zip file"));
console.error(e);
}
}
}
exports.default = P2P;