3box
Version:
Interact with user data
1,495 lines (1,218 loc) • 59.9 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function () { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
var localstorage = require('store');
var IPFS = require('ipfs');
var _require = require('3id-blockchain-utils'),
createLink = _require.createLink,
validateLink = _require.validateLink;
var ThreeId = require('./3id');
var Replicator = require('./replicator');
var PublicStore = require('./publicStore');
var PrivateStore = require('./privateStore');
var Verified = require('./verified');
var Space = require('./space');
var utils = require('./utils/index');
var idUtils = require('./utils/id');
var config = require('./config.js');
var BoxApi = require('./api');
var IPFSRepo = require('ipfs-repo');
var LevelStore = require('datastore-level');
var didJWT = require('did-jwt');
var ThreeIdConnect = require('3id-connect').ThreeIdConnect;
var PINNING_NODE = config.pinning_node;
var ADDRESS_SERVER_URL = config.address_server_url;
var IPFS_OPTIONS = config.ipfs_options;
var IFRAME_STORE_URL = 'https://connect.3box.io';
var globalIPFS, globalIPFSPromise, threeIdConnect;
var browserHuh = typeof window !== 'undefined' && typeof document !== 'undefined';
if (browserHuh) threeIdConnect = new ThreeIdConnect(IFRAME_STORE_URL);
/**
* @extends BoxApi
*/
var Box = /*#__PURE__*/function (_BoxApi) {
(0, _inherits2["default"])(Box, _BoxApi);
var _super = _createSuper(Box);
/**
* Please use the **openBox** method to instantiate a 3Box
* @constructor
*/
function Box(provider, ipfs) {
var _this;
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
(0, _classCallCheck2["default"])(this, Box);
_this = _super.call(this);
_this._provider = provider;
_this._ipfs = ipfs;
_this._serverUrl = opts.addressServer || ADDRESS_SERVER_URL;
/**
* @property {KeyValueStore} public access the profile store of the users 3Box
*/
_this["public"] = null;
/**
* @property {KeyValueStore} private access the private store of the users 3Box
*/
_this["private"] = null;
/**
* @property {Verified} verified check and create verifications
*/
_this.verified = new Verified((0, _assertThisInitialized2["default"])(_this));
/**
* @property {Object} spaces an object containing all open spaces indexed by their name.
*/
_this.spaces = {};
/**
* @property {Promise} syncDone A promise that is resolved when the box is synced
*/
_this.syncDone = null;
_this.hasPublishedLink = {};
return _this;
}
(0, _createClass2["default"])(Box, [{
key: "_init",
value: function () {
var _init2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(opts) {
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return Replicator.create(this._ipfs, opts);
case 2:
this.replicator = _context.sent;
case 3:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function _init(_x) {
return _init2.apply(this, arguments);
}
return _init;
}()
}, {
key: "_load",
value: function () {
var _load2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() {
var _this2 = this;
var opts,
address,
_ref,
rootStoreAddress,
did,
authData,
rootstoreName,
key,
_args2 = arguments;
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
opts = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : {};
_context2.t0 = opts.address;
if (_context2.t0) {
_context2.next = 6;
break;
}
_context2.next = 5;
return this._3id.getAddress();
case 5:
_context2.t0 = _context2.sent;
case 6:
address = _context2.t0;
if (!address) {
_context2.next = 13;
break;
}
_context2.next = 10;
return this._getLinkedData(address);
case 10:
_context2.t1 = _context2.sent;
_context2.next = 14;
break;
case 13:
_context2.t1 = {};
case 14:
_ref = _context2.t1;
rootStoreAddress = _ref.rootStoreAddress;
did = _ref.did;
if (!rootStoreAddress) {
_context2.next = 29;
break;
}
_context2.next = 20;
return this.replicator.start(rootStoreAddress, did, {
profile: true
});
case 20:
_context2.next = 22;
return this.replicator.rootstoreSyncDone;
case 22:
_context2.next = 24;
return this.replicator.getAuthData();
case 24:
authData = _context2.sent;
_context2.next = 27;
return this._3id.authenticate(opts.spaces, {
authData: authData,
address: address
});
case 27:
_context2.next = 38;
break;
case 29:
_context2.next = 31;
return this._3id.authenticate(opts.spaces, {
address: address
});
case 31:
rootstoreName = this._3id.muportFingerprint + '.root';
_context2.next = 34;
return this._3id.getPublicKeys(null, true);
case 34:
key = _context2.sent.signingKey;
_context2.next = 37;
return this.replicator["new"](rootstoreName, key, this._3id.DID);
case 37:
this._publishRootStore(this.replicator.rootstore.address.toString());
case 38:
_context2.t2 = this.replicator.rootstore;
_context2.next = 41;
return this._3id.getOdbId();
case 41:
_context2.t3 = _context2.sent;
_context2.t2.setIdentity.call(_context2.t2, _context2.t3);
this.syncDone = this.replicator.syncDone;
this._3id.events.on('new-auth-method', function (authData) {
_this2._writeRootstoreEntry(Replicator.entryTypes.AUTH_DATA, authData);
});
this._3id.events.on('new-link-proof', function (proof) {
_this2._writeAddressLink(proof);
});
this._3id.startUpdatePolling();
this["public"] = new PublicStore(this._3id.muportFingerprint + '.public', this._linkProfile.bind(this), this.replicator, this._3id);
this["private"] = new PrivateStore(this._3id.muportFingerprint + '.private', this.replicator, this._3id);
_context2.next = 51;
return this["public"]._load();
case 51:
_context2.next = 53;
return this["private"]._load();
case 53:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
function _load() {
return _load2.apply(this, arguments);
}
return _load;
}()
/**
* Creates an instance of 3Box
*
* @param {provider} provider A 3ID provider, or ethereum provider
* @param {Object} opts Optional parameters
* @param {String} opts.pinningNode A string with an ipfs multi-address to a 3box pinning node
* @param {Object} opts.ipfs A js-ipfs ipfs object
* @param {String} opts.addressServer URL of the Address Server
* @return {Box} the 3Box session instance
*/
}, {
key: "auth",
/**
* Authenticate the user
*
* @param {Array<String>} spaces A list of spaces to authenticate (optional)
* @param {Object} opts Optional parameters
* @param {String} opts.address An ethereum address
* @param {Function} opts.consentCallback A function that will be called when the user has consented to opening the box
*/
value: function () {
var _auth = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4() {
var _this3 = this;
var spaces,
opts,
_args4 = arguments;
return _regenerator["default"].wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
spaces = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : [];
opts = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : {};
opts.address = opts.address ? opts.address.toLowerCase() : opts.address;
this._3idEthAddress = opts.address; // Enabled once becomes default
// if (!this._provider.is3idProvider && threeIdConnect) {
// this._provider = await threeIdConnect.get3idProvider()
// }
if (this._3id) {
_context4.next = 14;
break;
}
if (!(!this._provider.is3idProvider && !opts.address)) {
_context4.next = 7;
break;
}
throw new Error('auth: address needed when 3ID provider is not used');
case 7:
_context4.next = 9;
return ThreeId.getIdFromEthAddress(opts.address, this._provider, this._ipfs, this.replicator._orbitdb.keystore, opts);
case 9:
this._3id = _context4.sent;
_context4.next = 12;
return this._load(Object.assign(opts, {
spaces: spaces
}));
case 12:
_context4.next = 18;
break;
case 14:
if (!(this._provider.threeIdConnect && this._provider.migration && !opts.address)) {
_context4.next = 16;
break;
}
throw new Error('auth: address needed when 3ID provider not given');
case 16:
_context4.next = 18;
return this._3id.authenticate(spaces, {
address: opts.address
});
case 18:
_context4.next = 20;
return Promise.all(spaces.map( /*#__PURE__*/function () {
var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(space) {
return _regenerator["default"].wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
if (!_this3.spaces[space]) {
_context3.next = 3;
break;
}
_context3.next = 3;
return _this3.spaces[space]._authThreads(_this3._3id);
case 3:
case "end":
return _context3.stop();
}
}
}, _callee3);
}));
return function (_x2) {
return _ref2.apply(this, arguments);
};
}()));
case 20:
case "end":
return _context4.stop();
}
}
}, _callee4, this);
}));
function auth() {
return _auth.apply(this, arguments);
}
return auth;
}()
/**
* Opens the 3Box associated with the given address
*
* @param {String} address An ethereum address
* @param {provider} provider An ethereum or 3ID provider
* @param {Object} opts Optional parameters
* @param {Function} opts.consentCallback A function that will be called when the user has consented to opening the box
* @param {String} opts.pinningNode A string with an ipfs multi-address to a 3box pinning node
* @param {Object} opts.ipfs A js-ipfs ipfs object
* @param {String} opts.addressServer URL of the Address Server
* @param {String} opts.contentSignature A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message
* @return {Box} the 3Box instance for the given address
*/
}, {
key: "openSpace",
/**
* Opens the space with the given name in the users 3Box
*
* @param {String} name The name of the space
* @param {Object} opts Optional parameters
* @param {Function} opts.consentCallback A function that will be called when the user has consented to opening the box
* @param {Function} opts.onSyncDone A function that will be called when the space has finished syncing with the pinning node
* @return {Space} the Space instance for the given space name
*/
value: function () {
var _openSpace = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(name) {
var opts,
_args5 = arguments;
return _regenerator["default"].wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
opts = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : {};
opts = Object.assign(opts, {
address: this._3idEthAddress
});
if (!name.includes('.')) {
_context5.next = 4;
break;
}
throw new Error('Invalid name: character "." not allowed');
case 4:
if (this._3id) {
_context5.next = 6;
break;
}
throw new Error('openSpace: auth required');
case 6:
if (!this.spaces[name]) {
this.spaces[name] = new Space(name, this.replicator);
}
if (this.spaces[name].isOpen) {
_context5.next = 27;
break;
}
_context5.prev = 8;
_context5.next = 11;
return this.spaces[name].open(this._3id, opts);
case 11:
_context5.next = 13;
return this.isAddressLinked();
case 13:
if (_context5.sent) {
_context5.next = 15;
break;
}
this.linkAddress();
case 15:
_context5.next = 25;
break;
case 17:
_context5.prev = 17;
_context5.t0 = _context5["catch"](8);
delete this.spaces[name];
if (!_context5.t0.message.includes('User denied message signature.')) {
_context5.next = 24;
break;
}
throw new Error('User denied space consent.');
case 24:
throw new Error('An error occured while opening space: ', _context5.t0.message);
case 25:
_context5.next = 28;
break;
case 27:
if (opts.onSyncDone) {
// since the space is already open we can call onSyncDone directly
opts.onSyncDone();
}
case 28:
return _context5.abrupt("return", this.spaces[name]);
case 29:
case "end":
return _context5.stop();
}
}
}, _callee5, this, [[8, 17]]);
}));
function openSpace(_x3) {
return _openSpace.apply(this, arguments);
}
return openSpace;
}()
/**
* Open a thread. Use this to start receiving updates
*
* @param {String} space The name of the space for this thread
* @param {String} name The name of the thread
* @param {Object} opts Optional parameters
* @param {String} opts.firstModerator DID of first moderator of a thread, by default, user is first moderator
* @param {Boolean} opts.members join a members only thread, which only members can post in, defaults to open thread
* @param {Boolean} opts.noAutoSub Disable auto subscription to the thread when posting to it (default false)
* @param {Boolean} opts.ghost Enable ephemeral messaging via Ghost Thread
* @param {Number} opts.ghostBacklogLimit The number of posts to maintain in the ghost backlog
* @param {Array<Function>} opts.ghostFilters Array of functions for filtering messages
*
* @return {Thread} An instance of the thread class for the joined thread
*/
}, {
key: "openThread",
value: function () {
var _openThread = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(space, name, opts) {
return _regenerator["default"].wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
if (!this.spaces[space]) {
this.spaces[space] = new Space(space, this.replicator);
}
return _context6.abrupt("return", this.spaces[space].joinThread(name, opts));
case 2:
case "end":
return _context6.stop();
}
}
}, _callee6, this);
}));
function openThread(_x4, _x5, _x6) {
return _openThread.apply(this, arguments);
}
return openThread;
}()
/**
* Sets the callback function that will be called once when the box is fully synced.
*
* @param {Function} syncDone The function that will be called
* @return {Promise} A promise that is fulfilled when the box is syned
*/
}, {
key: "onSyncDone",
value: function () {
var _onSyncDone = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee7(syncDone) {
return _regenerator["default"].wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
_context7.next = 2;
return this.syncDone;
case 2:
syncDone();
case 3:
case "end":
return _context7.stop();
}
}
}, _callee7, this);
}));
function onSyncDone(_x7) {
return _onSyncDone.apply(this, arguments);
}
return onSyncDone;
}()
}, {
key: "_publishRootStore",
value: function () {
var _publishRootStore2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee9(rootStoreAddress) {
var _this4 = this;
var addressToken, publish;
return _regenerator["default"].wrap(function _callee9$(_context9) {
while (1) {
switch (_context9.prev = _context9.next) {
case 0:
_context9.next = 2;
return this._3id.signJWT({
rootStoreAddress: rootStoreAddress
});
case 2:
addressToken = _context9.sent;
// Store odbAddress on 3box-address-server
publish = /*#__PURE__*/function () {
var _ref3 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee8(token) {
return _regenerator["default"].wrap(function _callee8$(_context8) {
while (1) {
switch (_context8.prev = _context8.next) {
case 0:
_context8.prev = 0;
_context8.next = 3;
return utils.fetchJson(_this4._serverUrl + '/odbAddress', {
address_token: token
});
case 3:
_context8.next = 14;
break;
case 5:
_context8.prev = 5;
_context8.t0 = _context8["catch"](0);
if (!(_context8.t0.message === 'Invalid JWT')) {
_context8.next = 12;
break;
}
_context8.next = 10;
return new Promise(function (resolve) {
return setTimeout(resolve, 300);
});
case 10:
_context8.next = 12;
return publish(token);
case 12:
if (_context8.t0.statusCode) {
_context8.next = 14;
break;
}
throw new Error(_context8.t0);
case 14:
case "end":
return _context8.stop();
}
}
}, _callee8, null, [[0, 5]]);
}));
return function publish(_x9) {
return _ref3.apply(this, arguments);
};
}();
_context9.next = 6;
return publish(addressToken);
case 6:
return _context9.abrupt("return", true);
case 7:
case "end":
return _context9.stop();
}
}
}, _callee9, this);
}));
function _publishRootStore(_x8) {
return _publishRootStore2.apply(this, arguments);
}
return _publishRootStore;
}()
}, {
key: "_getLinkedData",
value: function () {
var _getLinkedData2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee10(ethereumAddress) {
var _yield$utils$fetchJso, rootStoreAddress, did;
return _regenerator["default"].wrap(function _callee10$(_context10) {
while (1) {
switch (_context10.prev = _context10.next) {
case 0:
_context10.prev = 0;
_context10.next = 3;
return utils.fetchJson("".concat(this._serverUrl, "/odbAddress/").concat(ethereumAddress));
case 3:
_yield$utils$fetchJso = _context10.sent.data;
rootStoreAddress = _yield$utils$fetchJso.rootStoreAddress;
did = _yield$utils$fetchJso.did;
return _context10.abrupt("return", {
rootStoreAddress: rootStoreAddress,
did: did
});
case 9:
_context10.prev = 9;
_context10.t0 = _context10["catch"](0);
if (!(_context10.t0.statusCode === 404)) {
_context10.next = 13;
break;
}
return _context10.abrupt("return", {});
case 13:
throw new Error('Error while getting rootstore', _context10.t0);
case 14:
case "end":
return _context10.stop();
}
}
}, _callee10, this, [[0, 9]]);
}));
function _getLinkedData(_x10) {
return _getLinkedData2.apply(this, arguments);
}
return _getLinkedData;
}()
/**
* @property {String} DID the DID of the user
*/
}, {
key: "linkAddress",
/**
* Creates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.
*
* @param {Object} [link] Optional link object with type or proof
* @param {Object} [link.proof] Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md)
*/
value: function () {
var _linkAddress = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee11() {
var link,
_args11 = arguments;
return _regenerator["default"].wrap(function _callee11$(_context11) {
while (1) {
switch (_context11.prev = _context11.next) {
case 0:
link = _args11.length > 0 && _args11[0] !== undefined ? _args11[0] : {};
if (this._3id) {
_context11.next = 3;
break;
}
throw new Error('linkAddress: auth required');
case 3:
if (!link.proof) {
_context11.next = 8;
break;
}
_context11.next = 6;
return this._writeAddressLink(link.proof);
case 6:
_context11.next = 10;
break;
case 8:
_context11.next = 10;
return this._linkProfile();
case 10:
case "end":
return _context11.stop();
}
}
}, _callee11, this);
}));
function linkAddress() {
return _linkAddress.apply(this, arguments);
}
return linkAddress;
}()
/**
* Remove given address link, returns true if successful
*
* @param {String} address address that is linked
*/
}, {
key: "removeAddressLink",
value: function () {
var _removeAddressLink = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee12(address) {
var linkExist, payload, oneHour, deleteToken;
return _regenerator["default"].wrap(function _callee12$(_context12) {
while (1) {
switch (_context12.prev = _context12.next) {
case 0:
if (this._3id) {
_context12.next = 2;
break;
}
throw new Error('removeAddressLink: auth required');
case 2:
address = address.toLowerCase();
_context12.next = 5;
return this.isAddressLinked({
address: address
});
case 5:
linkExist = _context12.sent;
if (linkExist) {
_context12.next = 8;
break;
}
throw new Error('removeAddressLink: link for given address does not exist');
case 8:
payload = {
address: address,
type: 'delete-address-link'
};
oneHour = 60 * 60;
_context12.next = 12;
return this._3id.signJWT(payload, {
expiresIn: oneHour
});
case 12:
deleteToken = _context12.sent;
_context12.prev = 13;
_context12.next = 16;
return utils.fetchJson(this._serverUrl + '/linkdelete', {
delete_token: deleteToken
});
case 16:
_context12.next = 22;
break;
case 18:
_context12.prev = 18;
_context12.t0 = _context12["catch"](13);
if (_context12.t0.statusCode) {
_context12.next = 22;
break;
}
throw new Error(_context12.t0);
case 22:
_context12.next = 24;
return this._deleteAddressLink(address);
case 24:
return _context12.abrupt("return", true);
case 25:
case "end":
return _context12.stop();
}
}
}, _callee12, this, [[13, 18]]);
}));
function removeAddressLink(_x11) {
return _removeAddressLink.apply(this, arguments);
}
return removeAddressLink;
}()
/**
* Checks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true
*
* @param {Object} [query] Optional object with address and/or type.
* @param {String} [query.type] Does the given type of link exist
* @param {String} [query.address] Is the given adressed linked
*/
}, {
key: "isAddressLinked",
value: function () {
var _isAddressLinked = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee13() {
var query,
links,
linksQuery,
_args13 = arguments;
return _regenerator["default"].wrap(function _callee13$(_context13) {
while (1) {
switch (_context13.prev = _context13.next) {
case 0:
query = _args13.length > 0 && _args13[0] !== undefined ? _args13[0] : {};
if (this._3id) {
_context13.next = 3;
break;
}
throw new Error('isAddressLinked: auth required');
case 3:
if (query.address) query.address = query.address.toLowerCase();
_context13.next = 6;
return this._readAddressLinks();
case 6:
links = _context13.sent;
linksQuery = links.find(function (link) {
var res = query.address ? link.address.toLowerCase() === query.address : true;
return query.type ? res && link.type === query.type : res;
});
return _context13.abrupt("return", Boolean(linksQuery));
case 9:
case "end":
return _context13.stop();
}
}
}, _callee13, this);
}));
function isAddressLinked() {
return _isAddressLinked.apply(this, arguments);
}
return isAddressLinked;
}()
/**
* Lists address links associated with this 3Box
*
* @return {Array} An array of link objects
*/
}, {
key: "listAddressLinks",
value: function () {
var _listAddressLinks = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee14() {
var entries;
return _regenerator["default"].wrap(function _callee14$(_context14) {
while (1) {
switch (_context14.prev = _context14.next) {
case 0:
if (this._3id) {
_context14.next = 2;
break;
}
throw new Error('listAddressLinks: auth required');
case 2:
_context14.next = 4;
return this._readAddressLinks();
case 4:
entries = _context14.sent;
return _context14.abrupt("return", entries.reduce(function (list, entry) {
var item = Object.assign({}, entry);
item.linkId = item.entry.hash;
delete item.entry;
list.push(item);
return list;
}, []));
case 6:
case "end":
return _context14.stop();
}
}
}, _callee14, this);
}));
function listAddressLinks() {
return _listAddressLinks.apply(this, arguments);
}
return listAddressLinks;
}()
}, {
key: "_writeAddressLink",
value: function () {
var _writeAddressLink2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee15(proof) {
var validProof;
return _regenerator["default"].wrap(function _callee15$(_context15) {
while (1) {
switch (_context15.prev = _context15.next) {
case 0:
_context15.next = 2;
return validateLink(proof);
case 2:
validProof = _context15.sent;
if (validProof) {
_context15.next = 5;
break;
}
throw new Error('tried to write invalid link proof', proof);
case 5:
_context15.next = 7;
return this.isAddressLinked({
address: validProof.address
});
case 7:
if (!_context15.sent) {
_context15.next = 9;
break;
}
return _context15.abrupt("return", true);
case 9:
_context15.next = 11;
return this._writeRootstoreEntry(Replicator.entryTypes.ADDRESS_LINK, proof);
case 11:
_context15.next = 13;
return utils.fetchJson(this._serverUrl + '/link', proof);
case 13:
case "end":
return _context15.stop();
}
}
}, _callee15, this);
}));
function _writeAddressLink(_x12) {
return _writeAddressLink2.apply(this, arguments);
}
return _writeAddressLink;
}()
}, {
key: "_linkProfile",
value: function () {
var _linkProfile2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee16() {
var address, proof, proofdid, issuer, jwt;
return _regenerator["default"].wrap(function _callee16$(_context16) {
while (1) {
switch (_context16.prev = _context16.next) {
case 0:
_context16.next = 2;
return this._3id.getAddress();
case 2:
address = _context16.sent;
_context16.next = 5;
return this._readAddressLink(address);
case 5:
proof = _context16.sent;
if (proof) {
_context16.next = 34;
break;
}
_context16.prev = 7;
if (this._provider.is3idProvider) {
_context16.next = 14;
break;
}
_context16.next = 11;
return createLink(this._3id.DID, address, this._provider);
case 11:
proof = _context16.sent;
_context16.next = 18;
break;
case 14:
if (!(this._provider.threeIdConnect && this._provider.migration)) {
_context16.next = 18;
break;
}
_context16.next = 17;
return this._3id.linkManagementAddress();
case 17:
proof = _context16.sent;
case 18:
_context16.next = 23;
break;
case 20:
_context16.prev = 20;
_context16.t0 = _context16["catch"](7);
throw new Error('Link consent message must be signed before adding data, to link address to store', _context16.t0);
case 23:
_context16.prev = 23;
if (this._provider.is3idProvider) {
_context16.next = 27;
break;
}
_context16.next = 27;
return this._writeAddressLink(proof);
case 27:
_context16.next = 32;
break;
case 29:
_context16.prev = 29;
_context16.t1 = _context16["catch"](23);
throw new Error('An error occured while publishing link:', _context16.t1);
case 32:
_context16.next = 44;
break;
case 34:
if (this.hasPublishedLink[proof.signature]) {
_context16.next = 44;
break;
}
// Don't want to publish on every call to _linkProfile
this.hasPublishedLink[proof.signature] = true;
_context16.prev = 36;
_context16.next = 39;
return utils.fetchJson(this._serverUrl + '/link', proof);
case 39:
_context16.next = 44;
break;
case 41:
_context16.prev = 41;
_context16.t2 = _context16["catch"](36);
throw new Error('An error occured while publishing link:', _context16.t2);
case 44:
_context16.next = 46;
return this["public"].get('proof_did');
case 46:
proofdid = _context16.sent;
if (!proofdid) {
_context16.next = 60;
break;
}
// if prior muport, re publish with 3id including muport
issuer = didJWT.decodeJWT(proofdid).payload.iss;
if (!issuer.includes('muport')) {
_context16.next = 58;
break;
}
jwt = {
muport: proofdid
};
_context16.t3 = this["public"];
_context16.next = 54;
return this._3id.signJWT(jwt);
case 54:
_context16.t4 = _context16.sent;
_context16.t5 = {
noLink: true
};
_context16.next = 58;
return _context16.t3.set.call(_context16.t3, 'proof_did', _context16.t4, _context16.t5);
case 58:
_context16.next = 67;
break;
case 60:
_context16.t6 = this["public"];
_context16.next = 63;
return this._3id.signJWT();
case 63:
_context16.t7 = _context16.sent;
_context16.t8 = {
noLink: true
};
_context16.next = 67;
return _context16.t6.set.call(_context16.t6, 'proof_did', _context16.t7, _context16.t8);
case 67:
case "end":
return _context16.stop();
}
}
}, _callee16, this, [[7, 20], [23, 29], [36, 41]]);
}));
function _linkProfile() {
return _linkProfile2.apply(this, arguments);
}
return _linkProfile;
}()
}, {
key: "_writeRootstoreEntry",
value: function () {
var _writeRootstoreEntry2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee18(type, payload) {
var _this5 = this;
var cid, entryExist, entry, prev;
return _regenerator["default"].wrap(function _callee18$(_context18) {
while (1) {
switch (_context18.prev = _context18.next) {
case 0:
_context18.next = 2;
return this._ipfs.dag.put(payload);
case 2:
cid = _context18.sent.toBaseEncodedString();
_context18.next = 5;
return this._ipfs.pin.add(cid);
case 5:
_context18.next = 7;
return this._typeCIDExists(type, cid);
case 7:
entryExist = _context18.sent;
if (!entryExist) {
_context18.next = 10;
break;
}
return _context18.abrupt("return");
case 10:
entry = {
type: type,
data: cid
}; // the below code prevents multiple simultaneous writes,
// which orbitdb doesn't support
prev = this._rootstoreQueue;
this._rootstoreQueue = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee17() {
return _regenerator["default"].wrap(function _callee17$(_context17) {
while (1) {
switch (_context17.prev = _context17.next) {
case 0:
if (!prev) {
_context17.next = 3;
break;
}
_context17.next = 3;
return prev;
case 3:
_context17.next = 5;
return _this5.replicator.rootstore.add(entry);
case 5:
case "end":
return _context17.stop();
}
}
}, _callee17);
}))();
case 13:
case "end":
return _context18.stop();
}
}
}, _callee18, this);
}));
function _writeRootstoreEntry(_x13, _x14) {
return _writeRootstoreEntry2.apply(this, arguments);
}
return _writeRootstoreEntry;
}()
}, {
key: "_typeCIDExists",
value: function () {
var _typeCIDExists2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee19(type, cid) {
var entries, typeEntries;
return _regenerator["default"].wrap(function _callee19$(_context19) {
while (1) {
switch (_context19.prev = _context19.next) {
case 0:
_context19.next = 2;
return this.replicator.rootstore.iterator({
limit: -1
}).collect();
case 2:
entries = _context19.sent;
typeEntries = entries.filter(function (e) {
return e.payload.value.type === type;
});
return _context19.abrupt("return", Boolean(typeEntries.find(function (entry) {
return entry.data === cid;
})));
case 5:
case "end":
return _context19.stop();
}
}
}, _callee19, this);
}));
function _typeCIDExists(_x15, _x16) {
return _typeCIDExists2.apply(this, arguments);
}
return _typeCIDExists;
}()
}, {
key: "_deleteAddressLink",
value: function () {
var _deleteAddressLink2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee20(address) {
var link;
return _regenerator["default"].wrap(function _callee20$(_context20) {
while (1) {
switch (_context20.prev = _context20.next) {
case 0:
address = address.toLowerCase();
_context20.next = 3;
return this._readAddressLink(address);
case 3:
link = _context20.sent;
if (link) {
_context20.next = 6;
break;
}
throw new Error('_deleteAddressLink: link for given address does not exist');
case 6:
return _context20.abrupt("return", this.replicator.rootstore.remove(link.entry.hash));
case 7:
case "end":
return _context20.stop();
}
}
}, _callee20, this);
}));
function _deleteAddressLink(_x17) {
return _deleteAddressLink2.apply(this, arguments);
}
return _deleteAddressLink;
}()
}, {
key: "_readAddressLinks",
value: function () {
var _readAddressLinks2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee21() {
var links, allLinks;
return _regenerator["default"].wrap(function _callee21$(_context21) {
while (1) {
switch (_context21.prev = _context21.next) {
case 0:
_context21.next = 2;
return this.replicator.getAddressLinks();
case 2:
links = _context21.sent;
_context21.next = 5;
return Promise.all(links.map(validateLink));
case 5:
allLinks = _context21.sent;
return _context21.abrupt("return", allLinks.filter(Boolean));
case 7:
case "end":
return _context21.stop();
}
}
}, _callee21, this);
}));
function _readAddressLinks() {
return _readAddressLinks2.apply(this, arguments);
}
return _readAddressLinks;
}()
}, {
key: "_readAddressLink",
value: function () {
var _readAddressLink2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee22(address) {
var links;
return _regenerator["default"].wrap(function _callee22$(_context22) {
while (1) {
switch (_context22.prev = _context22.next) {
case 0:
address = address.toLowerCase();
_context22.next = 3;
return this._readAddressLinks();
case 3:
links = _context22.sent;
return _context22.abrupt("return", links.find(function (link) {
return link.address.toLowerCase() === address;
}));
case 5:
case "end":
return _context22.stop();
}
}
}, _callee22, this);
}));
function _readAddressLink(_x18) {
return _readAddressLink2.apply(this, arguments);
}
return _readAddressLink;
}()
}, {
key: "close",
value: function () {
var _close = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee23() {
return _regenerator