UNPKG

@stacks/cli

Version:
191 lines • 9.16 kB
"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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getGaiaAddressFromProfile = exports.getGaiaAddressFromURL = exports.gaiaUploadProfileAll = exports.gaiaUploadProfile = exports.gaiaConnect = exports.gaiaAuth = exports.makeAssociationToken = void 0; const blockstack = __importStar(require("blockstack")); const URL = __importStar(require("url")); const crypto = __importStar(require("crypto")); const jsontokens = __importStar(require("jsontokens")); const ZoneFile = require('zone-file'); const utils_1 = require("./utils"); const common_1 = require("./common"); const storage_1 = require("@stacks/storage"); function makeFakeAuthResponseToken(appPrivateKey, hubURL, associationToken) { const ownerPrivateKey = '24004db06ef6d26cdd2b0fa30b332a1b10fa0ba2b07e63505ffc2a9ed7df22b4'; const transitPrivateKey = 'f33fb466154023aba2003c17158985aa6603db68db0f1afc0fcf1d641ea6c2cb'; const transitPublicKey = '0496345da77fb5e06757b9c4fd656bf830a3b293f245a6cc2f11f8334ebb690f1' + '9582124f4b07172eb61187afba4514828f866a8a223e0d5c539b2e38a59ab8bb3'; window.localStorage.setItem('blockstack-transit-private-key', transitPrivateKey); const authResponse = blockstack.makeAuthResponse(ownerPrivateKey, { type: '@Person', accounts: [] }, null, {}, null, appPrivateKey, undefined, transitPublicKey, hubURL, blockstack.config.network.blockstackAPIUrl, associationToken); return authResponse; } function makeAssociationToken(appPrivateKey, identityKey) { const appPublicKey = (0, utils_1.getPublicKeyFromPrivateKey)(`${(0, utils_1.canonicalPrivateKey)(appPrivateKey)}01`); const FOUR_MONTH_SECONDS = 60 * 60 * 24 * 31 * 4; const salt = crypto.randomBytes(16).toString('hex'); const identityPublicKey = (0, utils_1.getPublicKeyFromPrivateKey)(identityKey); const associationTokenClaim = { childToAssociate: appPublicKey, iss: identityPublicKey, exp: FOUR_MONTH_SECONDS + new Date().getTime() / 1000, salt, }; const associationToken = new jsontokens.TokenSigner('ES256K', identityKey).sign(associationTokenClaim); return associationToken; } exports.makeAssociationToken = makeAssociationToken; function gaiaAuth(network, appPrivateKey, hubUrl, ownerPrivateKey) { if (!network.isMainnet()) { throw new Error('Gaia only works with mainnet networks.'); } let associationToken; if (ownerPrivateKey && appPrivateKey) { associationToken = makeAssociationToken(appPrivateKey, ownerPrivateKey); } const authSessionToken = makeFakeAuthResponseToken(appPrivateKey, hubUrl, associationToken); const nameLookupUrl = `${network.legacyNetwork.blockstackAPIUrl}/v1/names/`; const transitPrivateKey = 'f33fb466154023aba2003c17158985aa6603db68db0f1afc0fcf1d641ea6c2cb'; return blockstack.handlePendingSignIn(nameLookupUrl, authSessionToken, transitPrivateKey); } exports.gaiaAuth = gaiaAuth; function gaiaConnect(network, gaiaHubUrl, privateKey, ownerPrivateKey) { const addressMainnet = network.coerceMainnetAddress((0, common_1.getPrivateKeyAddress)(network, `${(0, utils_1.canonicalPrivateKey)(privateKey)}01`)); const addressMainnetCanonical = network.coerceMainnetAddress((0, common_1.getPrivateKeyAddress)(network, (0, utils_1.canonicalPrivateKey)(privateKey))); let associationToken; if (ownerPrivateKey) { associationToken = makeAssociationToken(privateKey, ownerPrivateKey); } return (0, storage_1.connectToGaiaHub)(gaiaHubUrl, (0, utils_1.canonicalPrivateKey)(privateKey), associationToken).then(hubConfig => { if (network.coerceMainnetAddress(hubConfig.address) === addressMainnet) { hubConfig.address = addressMainnet; } else if (network.coerceMainnetAddress(hubConfig.address) === addressMainnetCanonical) { hubConfig.address = addressMainnetCanonical; } else { throw new Error('Invalid private key: ' + `${network.coerceMainnetAddress(hubConfig.address)} is neither ` + `${addressMainnet} or ${addressMainnetCanonical}`); } return hubConfig; }); } exports.gaiaConnect = gaiaConnect; function gaiaFindProfileName(network, hubConfig, blockstackID) { if (!blockstackID || blockstackID === null || blockstackID === undefined) { return Promise.resolve().then(() => 'profile.json'); } else { return network.getNameInfo(blockstackID).then((nameInfo) => { let profileUrl; try { const zonefileJSON = ZoneFile.parseZoneFile(nameInfo.zonefile); if (zonefileJSON.uri && zonefileJSON.hasOwnProperty('$origin')) { profileUrl = blockstack.getTokenFileUrl(zonefileJSON); } } catch (e) { throw new Error(`Could not determine profile URL for ${String(blockstackID)}: could not parse zone file`); } if (profileUrl === null || profileUrl === undefined) { throw new Error(`Could not determine profile URL for ${String(blockstackID)}: no URL in zone file`); } const gaiaReadPrefix = `${hubConfig.url_prefix}${hubConfig.address}`; const gaiaReadUrlPath = String(URL.parse(gaiaReadPrefix).path); const profileUrlPath = String(URL.parse(profileUrl).path); if (!profileUrlPath.startsWith(gaiaReadUrlPath)) { throw new Error(`Could not determine profile URL for ${String(blockstackID)}: wrong Gaia hub` + ` (${gaiaReadPrefix} does not correspond to ${profileUrl})`); } const profilePath = profileUrlPath.substring(gaiaReadUrlPath.length + 1); return profilePath; }); } } function gaiaUploadProfile(network, gaiaHubURL, gaiaData, privateKey, blockstackID) { let hubConfig; return gaiaConnect(network, gaiaHubURL, privateKey) .then((hubconf) => { hubConfig = hubconf; return gaiaFindProfileName(network, hubConfig, blockstackID); }) .then((profilePath) => { return blockstack.uploadToGaiaHub(profilePath, gaiaData, hubConfig); }); } exports.gaiaUploadProfile = gaiaUploadProfile; function gaiaUploadProfileAll(network, gaiaUrls, gaiaData, privateKey, blockstackID) { const sanitizedGaiaUrls = gaiaUrls .map(gaiaUrl => { const urlInfo = URL.parse(gaiaUrl); if (!urlInfo.protocol) { return ''; } if (!urlInfo.host) { return ''; } return `${String(urlInfo.protocol)}//${String(urlInfo.host)}`; }) .filter(gaiaUrl => gaiaUrl.length > 0); const uploadPromises = sanitizedGaiaUrls.map(gaiaUrl => gaiaUploadProfile(network, gaiaUrl, gaiaData, privateKey, blockstackID)); return Promise.all(uploadPromises) .then(publicUrls => { return { error: null, dataUrls: publicUrls }; }) .catch(e => { return { error: `Failed to upload: ${e.message}`, dataUrls: null }; }); } exports.gaiaUploadProfileAll = gaiaUploadProfileAll; function getGaiaAddressFromURL(appUrl) { const matches = appUrl.match(/([13][a-km-zA-HJ-NP-Z0-9]{26,35})/); if (!matches) { throw new Error('Failed to parse gaia address'); } return matches[matches.length - 1]; } exports.getGaiaAddressFromURL = getGaiaAddressFromURL; function getGaiaAddressFromProfile(network, profile, appOrigin) { if (!profile) { throw new Error('No profile'); } if (!profile.apps) { throw new Error('No profile apps'); } if (!profile.apps[appOrigin]) { throw new Error(`No app entry for ${appOrigin}`); } const appUrl = profile.apps[appOrigin]; let existingAppAddress; try { existingAppAddress = network.coerceMainnetAddress(getGaiaAddressFromURL(appUrl)); } catch (e) { throw new Error(`Failed to parse app URL ${appUrl}`); } return existingAppAddress; } exports.getGaiaAddressFromProfile = getGaiaAddressFromProfile; //# sourceMappingURL=data.js.map