| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- "use strict";
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- const crypto = require("libp2p-crypto");
- const ws_1 = __importDefault(require("ws"));
- const content_item_1 = require("./content-item");
- const util_1 = require("./util");
- class BankClient {
- constructor(urlBase, ipfsUrlBase, storage, webClient) {
- this.urlBase = urlBase;
- this.ipfsUrlBase = ipfsUrlBase;
- this.storage = storage;
- this.webClient = webClient;
- this.wsUrlBase = urlBase.replace(/^http/i, 'ws');
- }
- static parseBankLink(bankLink) {
- if (!bankLink.startsWith('bank:')) {
- throw new Error('address must start with bank:');
- }
- const deprefixed = bankLink.substring(5);
- let host;
- let address;
- let topic;
- if (deprefixed[0] === '/' && deprefixed[1] === '/') {
- [host, address, topic] = deprefixed.substring(2).split('/');
- }
- else {
- [address, topic] = deprefixed.split('/');
- }
- if (!address || !topic) {
- throw new Error('cannot parse address and topic');
- }
- return { host, address, topic };
- }
- getPub() {
- return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
- yield this.bootstrap();
- this.getPriv().id((idErr, pubHash) => {
- if (idErr) {
- return reject(idErr);
- }
- resolve(pubHash);
- });
- }));
- }
- bootstrap() {
- if (this.bootstrapResult) {
- return Promise.resolve(this.bootstrapResult);
- }
- if (this.bootstrapPromise) {
- return this.bootstrapPromise;
- }
- return this.bootstrapPromise = new Promise((resolve, reject) => {
- this.storage.get('notaprivatekey').then(privateKeyFromStorage => {
- if (privateKeyFromStorage == null) {
- console.log('no private key in storage. generating new');
- crypto.keys.generateKeyPair('RSA', 2048, (generateErr, privateKey) => {
- if (generateErr) {
- return reject(generateErr);
- }
- privateKey.export('password', (exportErr, exportResult) => {
- if (exportErr) {
- return reject(exportErr);
- }
- this.storage.set('notaprivatekey', exportResult).then(err => {
- // whatever
- }).catch(reject);
- this.privateKey = privateKey;
- resolve(true);
- });
- });
- }
- else {
- // console.log('importing privatekey');
- crypto.keys.import(privateKeyFromStorage, 'password', (err, importedPrivateKey) => {
- if (err) {
- return reject(err);
- }
- this.privateKey = importedPrivateKey;
- // console.log(this.getPublicKeyString());
- // console.log(privateKeyFromStorage);
- resolve(true);
- });
- }
- }).catch(reject);
- });
- }
- getNonce() {
- return __awaiter(this, void 0, void 0, function* () {
- const nonce = yield this.webClient.request({
- method: 'GET',
- url: this.urlBase + '/bank/nonce'
- });
- console.log('nonce', nonce);
- return Number(nonce);
- });
- }
- getBalance() {
- return __awaiter(this, void 0, void 0, function* () {
- const nonce = yield this.getNonce();
- const retrieveRequest = yield this.makePlaintextPayload(JSON.stringify({
- _date: new Date().toISOString(),
- _nonce: nonce
- }));
- const topicURL = this.urlBase + '/bank/getbalance';
- const postResponse = yield this.webClient.requestJSON({
- body: retrieveRequest,
- method: 'POST',
- url: topicURL
- });
- return postResponse.balance;
- });
- }
- upload(params) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = this.urlBase + '/bank/upload';
- const formData = {};
- if (params.fileData) {
- formData.file = {
- value: params.fileData,
- options: {
- filename: params.fileName
- }
- };
- }
- if (params.thumbFileData) {
- formData.thumb = {
- value: params.thumbFileData,
- options: {
- filename: params.thumbFileName
- }
- };
- }
- if (params.links) {
- formData.links = JSON.stringify(params.links);
- }
- for (const attr of ['title', 'text', 'type']) {
- if (params[attr] != null) {
- formData[attr] = params[attr];
- }
- }
- // console.log('formData', formData);
- const uploadResponse = yield this.webClient.requestJSON({
- formData,
- method: 'POST',
- url
- });
- // console.log('uploadResponse', uploadResponse);
- return uploadResponse.hash;
- });
- }
- uploadSlimJSON(item) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = this.urlBase + '/bank/upload/slim';
- const uploadResponse = yield this.webClient.requestJSON({
- body: item,
- method: 'POST',
- url
- });
- // console.log('uploadResponse', uploadResponse);
- return uploadResponse.hash;
- });
- }
- uploadSlimText(item) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = this.urlBase + '/bank/upload/slim';
- const uploadResponse = JSON.parse(yield this.webClient.request({
- body: item,
- headers: {
- 'content-type': 'text/plain'
- },
- method: 'POST',
- url
- }));
- // console.log('uploadResponse', uploadResponse);
- return uploadResponse.hash;
- });
- }
- appendPrivate(dontLogToAll, peerAddr, topic, hash, replaceHash, deleteHash) {
- return __awaiter(this, void 0, void 0, function* () {
- const nonce = yield this.getNonce();
- const payload = yield this.makePlaintextPayload(JSON.stringify({
- _date: new Date().toISOString(),
- _nonce: nonce,
- deleteHash,
- hash,
- replaceHash,
- }));
- const topicURL = this.urlBase + '/bank/private/' + encodeURIComponent(peerAddr) + '/' + encodeURIComponent(topic);
- const result = yield this.webClient.request({
- body: JSON.stringify(payload),
- headers: {
- 'content-type': 'application/json'
- },
- method: 'PUT',
- url: topicURL
- });
- if (!dontLogToAll && topic !== 'all' && !deleteHash) {
- yield this.appendPrivate(true, peerAddr, 'all', hash, undefined, undefined);
- }
- });
- }
- retrievePrivate(peerAddr, topic) {
- return __awaiter(this, void 0, void 0, function* () {
- const nonce = yield this.getNonce();
- const retrieveRequest = yield this.makePlaintextPayload(JSON.stringify({
- _date: new Date().toISOString(),
- _nonce: nonce
- }));
- const topicURL = this.urlBase + '/bank/private/' + encodeURIComponent(peerAddr) + '/' + encodeURIComponent(topic);
- const result = yield this.webClient.request({
- body: JSON.stringify(retrieveRequest),
- headers: {
- 'content-type': 'application/json'
- },
- method: 'POST',
- url: topicURL
- });
- return result;
- });
- }
- subscribePrivate(peerAddr, topic, connectCallback, messageCallback) {
- return __awaiter(this, void 0, void 0, function* () {
- yield this.connectWebsocket(peerAddr, topic, connectCallback, messageCallback);
- });
- }
- getOrCreateContact(peerId, contactAddr) {
- return __awaiter(this, void 0, void 0, function* () {
- const contactList = yield this.retrievePrivate(peerId, '📇');
- const itemList = yield this.getItemsForCommaList(contactList);
- // console.log('contact hash for', contact, type, 'is', contactHash);
- const existing = itemList.filter(item => item.addrs && item.addrs.includes(contactAddr))[0];
- if (existing != null) {
- return existing;
- }
- const newItem = {
- addrs: [
- contactAddr
- ],
- id: util_1.uuid()
- };
- const newItemHash = yield this.uploadSlimJSON(newItem);
- yield this.appendPrivate(true, peerId, '📇', newItemHash);
- return newItem;
- });
- }
- getContactById(peerId, contactId) {
- return __awaiter(this, void 0, void 0, function* () {
- const contactList = yield this.retrievePrivate(peerId, '📇');
- const itemList = yield this.getItemsForCommaList(contactList);
- const existing = itemList.filter(item => item.id === contactId)[0];
- if (!existing) {
- throw new Error('Cannot find contact with id ' + contactId);
- }
- return existing;
- });
- }
- updateContact(peerId, contactId, newProperties) {
- return __awaiter(this, void 0, void 0, function* () {
- const existing = yield this.getContactById(peerId, contactId);
- const newProps = util_1.mergeDeep({}, newProperties);
- delete newProps.id;
- const newItem = util_1.mergeDeep(existing, newProps);
- delete newItem.hash;
- const newItemHash = yield this.uploadSlimJSON(newItem);
- yield this.appendPrivate(true, peerId, '📇', newItemHash, existing.hash);
- return yield this.getContactById(peerId, contactId);
- });
- }
- getContentItemByHash(hash) {
- return __awaiter(this, void 0, void 0, function* () {
- if (hash.startsWith('/ipfs/')) {
- hash = hash.split('/').pop();
- }
- const contentParams = (yield this.webClient.requestJSON({
- method: 'get',
- url: this.ipfsUrlBase + '/ipfs/' + hash + '/content.json'
- }));
- return new content_item_1.ContentItem(hash, contentParams);
- });
- }
- getItemsForCommaList(commaList) {
- return __awaiter(this, void 0, void 0, function* () {
- const itemHashes = commaList.split(',').filter(x => x.trim() !== '');
- const items = yield Promise.all(itemHashes.map(itemId => {
- return this.webClient.requestJSON({
- method: 'get',
- url: this.ipfsUrlBase + '/ipfs/' + itemId,
- });
- }));
- for (const item of items) {
- item.hash = itemHashes.shift();
- }
- return items;
- });
- }
- connectWebsocket(peerAddr, topic, connectCallback, messageCallback) {
- return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
- const nonce = yield this.getNonce();
- const retrieveRequest = yield this.makePlaintextPayload(JSON.stringify({
- _date: new Date().toISOString(),
- _nonce: nonce,
- addr: peerAddr,
- topic: topic
- }));
- const jsonOutput = JSON.stringify(retrieveRequest);
- const base64ed = Buffer.from(jsonOutput).toString('base64');
- const encoded = encodeURIComponent(base64ed);
- const ws = new ws_1.default(this.wsUrlBase + '/bank/ws?arg=' + encoded);
- ws.on('open', () => {
- connectCallback();
- });
- ws.on('message', data => {
- messageCallback(data);
- });
- const reconnect = () => {
- console.log('reconnect');
- try {
- ws.terminate();
- }
- finally {
- console.log('reconnecting in 5s');
- setTimeout(() => {
- this.connectWebsocket(peerAddr, topic, connectCallback, messageCallback);
- }, 5000);
- }
- };
- ws.on('error', err => {
- console.error('websocket error', err);
- });
- ws.on('close', err => {
- reconnect();
- });
- resolve();
- }));
- }
- getPriv() {
- if (!this.privateKey) {
- throw new Error('missing private key');
- }
- return this.privateKey;
- }
- makePlaintextPayload(message) {
- const messageBytes = Buffer.from(message, 'utf-8');
- return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
- yield this.bootstrap();
- this.privateKey.sign(messageBytes, (signErr, signatureBytes) => __awaiter(this, void 0, void 0, function* () {
- if (signErr) {
- reject(signErr);
- return;
- }
- const publicDERBytes = this.privateKey.public.bytes;
- this.privateKey.id((idErr, pubHash) => {
- if (idErr) {
- reject(idErr);
- return;
- }
- const result = {
- date: new Date().toISOString(),
- msg: util_1.encodeHex(messageBytes),
- pub: util_1.encodeHex(publicDERBytes),
- pubHash,
- sig: util_1.encodeHex(signatureBytes),
- };
- // console.log('result', result, signatureBytes);
- resolve(result);
- });
- }));
- }));
- }
- }
- exports.BankClient = BankClient;
- //# sourceMappingURL=index.js.map
|