From 0e234e227d21c5149b53c39482a41d16a89228c5 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Tue, 6 Aug 2019 12:16:20 -0400 Subject: [PATCH 1/9] Remove jsdoc types from network.ts --- src/network.ts | 112 ++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/network.ts b/src/network.ts index 4df1aedce..5e8c5be10 100644 --- a/src/network.ts +++ b/src/network.ts @@ -105,8 +105,8 @@ export class BlockstackNetwork { /** * Get the price of a name via the legacy /v1/prices API endpoint. - * @param {String} fullyQualifiedName the name to query - * @return {Promise} a promise to an Object with { units: String, amount: BigInteger } + * @param fullyQualifiedName the name to query + * @return a promise to an Object with { units: String, amount: BigInteger } * @private */ getNamePriceV1(fullyQualifiedName: string): Promise<{units: string, amount: BN}> { @@ -139,8 +139,8 @@ export class BlockstackNetwork { /** * Get the price of a namespace via the legacy /v1/prices API endpoint. - * @param {String} namespaceID the namespace to query - * @return {Promise} a promise to an Object with { units: String, amount: BigInteger } + * @param namespaceID the namespace to query + * @return a promise to an Object with { units: String, amount: BigInteger } * @private */ getNamespacePriceV1(namespaceID: string): Promise<{units: string, amount: BN}> { @@ -170,8 +170,8 @@ export class BlockstackNetwork { /** * Get the price of a name via the /v2/prices API endpoint. - * @param {String} fullyQualifiedName the name to query - * @return {Promise} a promise to an Object with { units: String, amount: BigInteger } + * @param fullyQualifiedName the name to query + * @return a promise to an Object with { units: String, amount: BigInteger } * @private */ getNamePriceV2(fullyQualifiedName: string): Promise<{units: string, amount: BN}> { @@ -208,8 +208,8 @@ export class BlockstackNetwork { /** * Get the price of a namespace via the /v2/prices API endpoint. - * @param {String} namespaceID the namespace to query - * @return {Promise} a promise to an Object with { units: String, amount: BigInteger } + * @param namespaceID the namespace to query + * @return a promise to an Object with { units: String, amount: BigInteger } * @private */ getNamespacePriceV2(namespaceID: string): Promise<{units: string, amount: BN}> { @@ -243,8 +243,8 @@ export class BlockstackNetwork { /** * Get the price of a name. - * @param {String} fullyQualifiedName the name to query - * @return {Promise} a promise to an Object with { units: String, amount: BigInteger }, where + * @param fullyQualifiedName the name to query + * @return a promise to an Object with { units: String, amount: BigInteger }, where * .units encodes the cryptocurrency units to pay (e.g. BTC, STACKS), and * .amount encodes the number of units, in the smallest denominiated amount * (e.g. if .units is BTC, .amount will be satoshis; if .units is STACKS, @@ -258,8 +258,8 @@ export class BlockstackNetwork { /** * Get the price of a namespace - * @param {String} namespaceID the namespace to query - * @return {Promise} a promise to an Object with { units: String, amount: BigInteger }, where + * @param namespaceID the namespace to query + * @return a promise to an Object with { units: String, amount: BigInteger }, where * .units encodes the cryptocurrency units to pay (e.g. BTC, STACKS), and * .amount encodes the number of units, in the smallest denominiated amount * (e.g. if .units is BTC, .amount will be satoshis; if .units is STACKS, @@ -274,8 +274,8 @@ export class BlockstackNetwork { /** * How many blocks can pass between a name expiring and the name being able to be * re-registered by a different owner? - * @param {string} fullyQualifiedName unused - * @return {Promise} a promise to the number of blocks + * @param fullyQualifiedName unused + * @return a promise to the number of blocks */ getGracePeriod(fullyQualifiedName?: string) { return Promise.resolve(5000) @@ -283,8 +283,8 @@ export class BlockstackNetwork { /** * Get the names -- both on-chain and off-chain -- owned by an address. - * @param {String} address the blockchain address (the hash of the owner public key) - * @return {Promise} a promise that resolves to a list of names (Strings) + * @param address the blockchain address (the hash of the owner public key) + * @return a promise that resolves to a list of names (Strings) */ getNamesOwned(address: string): Promise { const networkAddress = this.coerceAddress(address) @@ -296,8 +296,8 @@ export class BlockstackNetwork { /** * Get the blockchain address to which a name's registration fee must be sent * (the address will depend on the namespace in which it is registered.) - * @param {String} namespace the namespace ID - * @return {Promise} a promise that resolves to an address (String) + * @param namespace the namespace ID + * @return a promise that resolves to an address (String) */ getNamespaceBurnAddress(namespace: string) { return Promise.all([ @@ -327,8 +327,8 @@ export class BlockstackNetwork { /** * Get WHOIS-like information for a name, including the address that owns it, * the block at which it expires, and the zone file anchored to it (if available). - * @param {String} fullyQualifiedName the name to query. Can be on-chain of off-chain. - * @return {Promise} a promise that resolves to the WHOIS-like information + * @param fullyQualifiedName the name to query. Can be on-chain of off-chain. + * @return a promise that resolves to the WHOIS-like information */ getNameInfo(fullyQualifiedName: string) { Logger.debug(this.blockstackAPIUrl) @@ -358,8 +358,8 @@ export class BlockstackNetwork { /** * Get the pricing parameters and creation history of a namespace. - * @param {String} namespaceID the namespace to query - * @return {Promise} a promise that resolves to the namespace information. + * @param namespaceID the namespace to query + * @return a promise that resolves to the namespace information. */ getNamespaceInfo(namespaceID: string) { return fetchPrivate(`${this.blockstackAPIUrl}/v1/namespaces/${namespaceID}`) @@ -390,8 +390,8 @@ export class BlockstackNetwork { /** * Get a zone file, given its hash. Throws an exception if the zone file * obtained does not match the hash. - * @param {String} zonefileHash the ripemd160(sha256) hash of the zone file - * @return {Promise} a promise that resolves to the zone file's text + * @param zonefileHash the ripemd160(sha256) hash of the zone file + * @return a promise that resolves to the zone file's text */ getZonefile(zonefileHash: string) { return fetchPrivate(`${this.blockstackAPIUrl}/v1/zonefiles/${zonefileHash}`) @@ -415,9 +415,9 @@ export class BlockstackNetwork { /** * Get the status of an account for a particular token holding. This includes its total number of * expenditures and credits, lockup times, last txid, and so on. - * @param {String} address the account - * @param {String} tokenType the token type to query - * @return {Promise} a promise that resolves to an object representing the state of the account + * @param address the account + * @param tokenType the token type to query + * @return a promise that resolves to an object representing the state of the account * for this token */ getAccountStatus(address: string, tokenType: string) { @@ -444,9 +444,9 @@ export class BlockstackNetwork { /** * Get a page of an account's transaction history. - * @param {String} address the account's address - * @param {number} page the page number. Page 0 is the most recent transactions - * @return {Promise} a promise that resolves to an Array of Objects, where each Object encodes + * @param address the account's address + * @param page the page number. Page 0 is the most recent transactions + * @return a promise that resolves to an Array of Objects, where each Object encodes * states of the account at various block heights (e.g. prior balances, txids, etc) */ getAccountHistoryPage(address: string, @@ -480,9 +480,9 @@ export class BlockstackNetwork { * Get the state(s) of an account at a particular block height. This includes the state of the * account beginning with this block's transactions, as well as all of the states the account * passed through when this block was processed (if any). - * @param {String} address the account's address - * @param {Integer} blockHeight the block to query - * @return {Promise} a promise that resolves to an Array of Objects, where each Object encodes + * @param address the account's address + * @param blockHeight the block to query + * @return a promise that resolves to an Array of Objects, where each Object encodes * states of the account at this block. */ getAccountAt(address: string, blockHeight: number): Promise { @@ -513,8 +513,8 @@ export class BlockstackNetwork { /** * Get the set of token types that this account owns - * @param {String} address the account's address - * @return {Promise} a promise that resolves to an Array of Strings, where each item encodes the + * @param address the account's address + * @return a promise that resolves to an Array of Strings, where each item encodes the * type of token this account holds (excluding the underlying blockchain's tokens) */ getAccountTokens(address: string): Promise<{tokens: string[]}> { @@ -539,9 +539,9 @@ export class BlockstackNetwork { /** * Get the number of tokens owned by an account. If the account does not exist or has no * tokens of this type, then 0 will be returned. - * @param {String} address the account's address - * @param {String} tokenType the type of token to query. - * @return {Promise} a promise that resolves to a BigInteger that encodes the number of tokens + * @param address the account's address + * @param tokenType the type of token to query. + * @return a promise that resolves to a BigInteger that encodes the number of tokens * held by this account. */ getAccountBalance(address: string, tokenType: string): Promise { @@ -571,9 +571,9 @@ export class BlockstackNetwork { /** * Performs a POST request to the given URL - * @param {String} endpoint the name of - * @param {String} body [description] - * @return {Promise} Returns a `Promise` that resolves to the object requested. + * @param endpoint the name of + * @param body [description] + * @return Returns a `Promise` that resolves to the object requested. * In the event of an error, it rejects with: * * a `RemoteServiceError` if there is a problem * with the transaction broadcast service @@ -609,12 +609,12 @@ export class BlockstackNetwork { * Broadcasts a signed bitcoin transaction to the network optionally waiting to broadcast the * transaction until a second transaction has a certain number of confirmations. * - * @param {string} transaction the hex-encoded transaction to broadcast - * @param {string} transactionToWatch the hex transaction id of the transaction to watch for + * @param transaction the hex-encoded transaction to broadcast + * @param transactionToWatch the hex transaction id of the transaction to watch for * the specified number of confirmations before broadcasting the `transaction` - * @param {number} confirmations the number of confirmations `transactionToWatch` must have + * @param confirmations the number of confirmations `transactionToWatch` must have * before broadcasting `transaction`. - * @return {Promise} Returns a Promise that resolves to an object with a + * @return Returns a Promise that resolves to an object with a * `transaction_hash` key containing the transaction hash of the broadcasted transaction. * * In the event of an error, it rejects with: @@ -666,10 +666,10 @@ export class BlockstackNetwork { /** * Broadcasts a zone file to the Atlas network via the transaction broadcast service. * - * @param {String} zoneFile the zone file to be broadcast to the Atlas network - * @param {String} transactionToWatch the hex transaction id of the transaction + * @param zoneFile the zone file to be broadcast to the Atlas network + * @param transactionToWatch the hex transaction id of the transaction * to watch for confirmation before broadcasting the zone file to the Atlas network - * @return {Promise} Returns a Promise that resolves to an object with a + * @return Returns a Promise that resolves to an object with a * `transaction_hash` key containing the transaction hash of the broadcasted transaction. * * In the event of an error, it rejects with: @@ -749,12 +749,12 @@ export class BlockstackNetwork { * * broadcasts the zone file to the Atlas network after the register transaction * has an appropriate number of confirmations * - * @param {String} preorderTransaction the hex-encoded, signed preorder transaction generated + * @param preorderTransaction the hex-encoded, signed preorder transaction generated * using the `makePreorder` function - * @param {String} registerTransaction the hex-encoded, signed register transaction generated + * @param registerTransaction the hex-encoded, signed register transaction generated * using the `makeRegister` function - * @param {String} zoneFile the zone file to be broadcast to the Atlas network - * @return {Promise} Returns a Promise that resolves to an object with a + * @param zoneFile the zone file to be broadcast to the Atlas network + * @return Returns a Promise that resolves to an object with a * `transaction_hash` key containing the transaction hash of the broadcasted transaction. * * In the event of an error, it rejects with: @@ -853,8 +853,8 @@ export class BlockstackNetwork { * This will modify the network's utxo set to include UTXOs * from the given transaction and exclude UTXOs *spent* in * that transaction - * @param {String} txHex - the hex-encoded transaction to use - * @return {void} no return value, this modifies the UTXO config state + * @param txHex - the hex-encoded transaction to use + * @return no return value, this modifies the UTXO config state * @private * @ignore */ @@ -1247,8 +1247,8 @@ const MAINNET_DEFAULT = new BlockstackNetwork( /** * Get WHOIS-like information for a name, including the address that owns it, * the block at which it expires, and the zone file anchored to it (if available). - * @param {String} fullyQualifiedName the name to query. Can be on-chain of off-chain. - * @return {Promise} a promise that resolves to the WHOIS-like information + * @param fullyQualifiedName the name to query. Can be on-chain of off-chain. + * @return a promise that resolves to the WHOIS-like information */ export function getNameInfo(fullyQualifiedName: string) { return config.network.getNameInfo(fullyQualifiedName) From 2105c2c424cedf78f9d293f4b1c681c237b45c2b Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Tue, 6 Aug 2019 13:22:30 -0400 Subject: [PATCH 2/9] Expose the `BlockstackNetwork` class and the default instance, update typedoc and typescript minor versions --- package-lock.json | 229 +++++++++++++++++++++++----------------------- package.json | 4 +- src/network.ts | 127 +++++++++++++------------ src/utils.ts | 4 +- 4 files changed, 187 insertions(+), 177 deletions(-) diff --git a/package-lock.json b/package-lock.json index fa90c3f14..e1236a5d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "blockstack", - "version": "19.2.2-beta.1", + "version": "19.2.5", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -972,12 +972,6 @@ "@types/bn.js": "*" } }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, "@types/fetch-mock": { "version": "5.12.2", "resolved": "https://registry.npmjs.org/@types/fetch-mock/-/fetch-mock-5.12.2.tgz", @@ -993,59 +987,12 @@ "@types/node": "*" } }, - "@types/fs-extra": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.5.tgz", - "integrity": "sha512-w7iqhDH9mN8eLClQOYTkhdYUOSpp25eXxfc6VbFOGtzxW34JcvctH2bKjj4jD4++z4R5iO5D+pg48W2e03I65A==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/handlebars": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.1.0.tgz", - "integrity": "sha512-gq9YweFKNNB1uFK71eRqsd4niVkXrxHugqWFQkeLRJvGjnxsLr16bYtcsG4tOFwmYi0Bax+wCkbf1reUfdl4kA==", - "dev": true, - "requires": { - "handlebars": "*" - } - }, - "@types/highlight.js": { - "version": "9.12.3", - "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", - "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", - "dev": true - }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, - "@types/lodash": { - "version": "4.14.123", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz", - "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==", - "dev": true - }, - "@types/marked": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.4.2.tgz", - "integrity": "sha512-cDB930/7MbzaGF6U3IwSQp6XBru8xWajF5PV2YZZeV8DyiliTuld11afVztGI9+yJZ29il5E+NpGA6ooV/Cjkg==", - "dev": true - }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -1072,16 +1019,6 @@ "@types/node": "*" } }, - "@types/shelljs": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.4.tgz", - "integrity": "sha512-UNACC6scKFVljWEvO3rHBkbbKXu3QkKPBOMCisxI7au9cnFK7tjOGPsKh5OjedAPLmtsKSarmk+YeehKTQSKtg==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, "@types/sinon": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.0.11.tgz", @@ -1632,6 +1569,15 @@ "test-exclude": "^5.0.0" } }, + "backbone": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz", + "integrity": "sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ==", + "dev": true, + "requires": { + "underscore": ">=1.8.3" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -3952,14 +3898,22 @@ } }, "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", + "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.1.tgz", + "integrity": "sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw==", + "dev": true + } } }, "fs-readdir-recursive": { @@ -4032,7 +3986,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -4053,12 +4008,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4073,17 +4030,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4200,7 +4160,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4212,6 +4173,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4226,6 +4188,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4233,12 +4196,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4257,6 +4222,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4337,7 +4303,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4349,6 +4316,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4434,7 +4402,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4470,6 +4439,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4489,6 +4459,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4532,12 +4503,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -4688,9 +4661,9 @@ } }, "handlebars": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", - "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -4798,9 +4771,9 @@ } }, "highlight.js": { - "version": "9.15.6", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.6.tgz", - "integrity": "sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==", + "version": "9.15.9", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.9.tgz", + "integrity": "sha512-M0zZvfLr5p0keDMCAhNBp03XJbKBxUx5AfyfufMdFMEP4N/Xj6dh0IqC75ys7BAzceR34NgcvXjupRVaHBPPVQ==", "dev": true }, "hmac-drbg": { @@ -5319,6 +5292,12 @@ "semver": "^5.5.0" } }, + "jquery": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", + "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==", + "dev": true + }, "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", @@ -5654,6 +5633,12 @@ "yallist": "^3.0.2" } }, + "lunr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.6.tgz", + "integrity": "sha512-swStvEyDqQ85MGpABCMBclZcLI/pBIlu8FFDtmX197+oEgKloJ67QnB+Tidh0340HmLMs39c4GrkPY3cmkXp6Q==", + "dev": true + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -5701,9 +5686,9 @@ } }, "marked": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.4.0.tgz", - "integrity": "sha512-tMsdNBgOsrUophCAFQl0XPe6Zqk/uy9gnue+jIIKhykO51hxyu6uNx7zBPy0+y/WKYVZZMspV9YeXLNdKk+iYw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", + "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", "dev": true }, "md5.js": { @@ -9418,30 +9403,30 @@ "dev": true }, "typedoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.14.2.tgz", - "integrity": "sha512-aEbgJXV8/KqaVhcedT7xG6d2r+mOvB5ep3eIz1KuB5sc4fDYXcepEEMdU7XSqLFO5hVPu0nllHi1QxX2h/QlpQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.15.0.tgz", + "integrity": "sha512-NOtfq5Tis4EFt+J2ozhVq9RCeUnfEYMFKoU6nCXCXUULJz1UQynOM+yH3TkfZCPLzigbqB0tQYGVlktUWweKlw==", "dev": true, "requires": { - "@types/fs-extra": "^5.0.3", - "@types/handlebars": "^4.0.38", - "@types/highlight.js": "^9.12.3", - "@types/lodash": "^4.14.110", - "@types/marked": "^0.4.0", "@types/minimatch": "3.0.3", - "@types/shelljs": "^0.8.0", - "fs-extra": "^7.0.0", - "handlebars": "^4.0.6", - "highlight.js": "^9.13.1", - "lodash": "^4.17.10", - "marked": "^0.4.0", + "fs-extra": "^8.1.0", + "handlebars": "^4.1.2", + "highlight.js": "^9.15.8", + "lodash": "^4.17.15", + "marked": "^0.7.0", "minimatch": "^3.0.0", - "progress": "^2.0.0", - "shelljs": "^0.8.2", - "typedoc-default-themes": "^0.5.0", - "typescript": "3.2.x" + "progress": "^2.0.3", + "shelljs": "^0.8.3", + "typedoc-default-themes": "^0.6.0", + "typescript": "3.5.x" }, "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -9449,18 +9434,24 @@ "dev": true }, "typescript": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", - "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", + "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", "dev": true } } }, "typedoc-default-themes": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz", - "integrity": "sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic=", - "dev": true + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.6.0.tgz", + "integrity": "sha512-MdTROOojxod78CEv22rIA69o7crMPLnVZPefuDLt/WepXqJwgiSu8Xxq+H36x0Jj3YGc7lOglI2vPJ2GhoOybw==", + "dev": true, + "requires": { + "backbone": "^1.4.0", + "jquery": "^3.4.1", + "lunr": "^2.3.6", + "underscore": "^1.9.1" + } }, "typeforce": { "version": "1.18.0", @@ -9468,9 +9459,9 @@ "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" }, "typescript": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.2.tgz", - "integrity": "sha512-Og2Vn6Mk7JAuWA1hQdDQN/Ekm/SchX80VzLhjKN9ETYrIepBFAd8PkOdOTK2nKt0FCkmMZKBJvQ1dV1gIxPu/A==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", + "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", "dev": true }, "uglify-js": { @@ -9482,6 +9473,12 @@ "source-map": "~0.6.1" } }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", diff --git a/package.json b/package.json index aec587fec..54454b02d 100644 --- a/package.json +++ b/package.json @@ -121,8 +121,8 @@ "tape-promise": "^4.0.0", "ts-loader": "^5.3.3", "ts-node": "^8.0.2", - "typedoc": "^0.14.2", - "typescript": "^3.3.3333", + "typedoc": "^0.15.0", + "typescript": "^3.5.3", "webpack": "^4.29.6", "webpack-assets-manifest": "^3.1.1", "webpack-bundle-analyzer": "^3.1.0", diff --git a/src/network.ts b/src/network.ts index 5e8c5be10..1649e24ca 100644 --- a/src/network.ts +++ b/src/network.ts @@ -7,14 +7,25 @@ import { Logger } from './logger' import { config } from './config' import { fetchPrivate } from './fetchUtil' -/** - * @ignore - */ -export type UTXO = { - value?: number, - confirmations?: number, - tx_hash: string, - tx_output_n: number +export interface UTXO { + value?: number; + confirmations?: number; + tx_hash: string; + tx_output_n: number; +} + +export interface PriceInfo { + units: string; + amount: BN; +} + +export interface AccountTokens { + tokens: string[]; +} + +export interface TransactionInfo { + block_height: number; + [key: string]: any; } const SATOSHIS_PER_BTC = 1e8 @@ -35,18 +46,17 @@ export class BitcoinNetwork { return Promise.reject(new Error('Not implemented, getBlockHeight()')) } - getTransactionInfo(txid: string): Promise<{block_height: number}> { + getTransactionInfo(txid: string): Promise { return Promise.reject(new Error(`Not implemented, getTransactionInfo(${txid})`)) } - getNetworkedUTXOs(address: string): Promise> { + getNetworkedUTXOs(address: string): Promise { return Promise.reject(new Error(`Not implemented, getNetworkedUTXOs(${address})`)) } } /** - * @private - * @ignore + * */ export class BlockstackNetwork { blockstackAPIUrl: string @@ -59,7 +69,7 @@ export class BlockstackNetwork { includeUtxoMap: {[address: string]: UTXO[]} - excludeUtxoSet: Array + excludeUtxoSet: UTXO[] btc: BitcoinNetwork @@ -79,6 +89,9 @@ export class BlockstackNetwork { this.MAGIC_BYTES = 'id' } + /** + * @ignore + */ coerceAddress(address: string) { const { hash, version } = bjsAddress.fromBase58Check(address) const scriptHashes = [networks.bitcoin.scriptHash, @@ -96,9 +109,6 @@ export class BlockstackNetwork { return bjsAddress.toBase58Check(hash, coercedVersion) } - /** - * @ignore - */ getDefaultBurnAddress() { return this.coerceAddress('1111111111111111111114oLvT2') } @@ -109,7 +119,7 @@ export class BlockstackNetwork { * @return a promise to an Object with { units: String, amount: BigInteger } * @private */ - getNamePriceV1(fullyQualifiedName: string): Promise<{units: string, amount: BN}> { + getNamePriceV1(fullyQualifiedName: string): Promise { // legacy code path return fetchPrivate(`${this.blockstackAPIUrl}/v1/prices/names/${fullyQualifiedName}`) .then((resp) => { @@ -143,7 +153,7 @@ export class BlockstackNetwork { * @return a promise to an Object with { units: String, amount: BigInteger } * @private */ - getNamespacePriceV1(namespaceID: string): Promise<{units: string, amount: BN}> { + getNamespacePriceV1(namespaceID: string): Promise { // legacy code path return fetchPrivate(`${this.blockstackAPIUrl}/v1/prices/namespaces/${namespaceID}`) .then((resp) => { @@ -174,7 +184,7 @@ export class BlockstackNetwork { * @return a promise to an Object with { units: String, amount: BigInteger } * @private */ - getNamePriceV2(fullyQualifiedName: string): Promise<{units: string, amount: BN}> { + getNamePriceV2(fullyQualifiedName: string): Promise { return fetchPrivate(`${this.blockstackAPIUrl}/v2/prices/names/${fullyQualifiedName}`) .then((resp) => { if (resp.status !== 200) { @@ -212,7 +222,7 @@ export class BlockstackNetwork { * @return a promise to an Object with { units: String, amount: BigInteger } * @private */ - getNamespacePriceV2(namespaceID: string): Promise<{units: string, amount: BN}> { + getNamespacePriceV2(namespaceID: string): Promise { return fetchPrivate(`${this.blockstackAPIUrl}/v2/prices/namespaces/${namespaceID}`) .then((resp) => { if (resp.status !== 200) { @@ -250,7 +260,7 @@ export class BlockstackNetwork { * (e.g. if .units is BTC, .amount will be satoshis; if .units is STACKS, * .amount will be microStacks) */ - getNamePrice(fullyQualifiedName: string): Promise<{units: string, amount: BN}> { + getNamePrice(fullyQualifiedName: string): Promise { // handle v1 or v2 return Promise.resolve().then(() => this.getNamePriceV2(fullyQualifiedName)) .catch(() => this.getNamePriceV1(fullyQualifiedName)) @@ -265,7 +275,7 @@ export class BlockstackNetwork { * (e.g. if .units is BTC, .amount will be satoshis; if .units is STACKS, * .amount will be microStacks) */ - getNamespacePrice(namespaceID: string): Promise<{units: string, amount: BN}> { + getNamespacePrice(namespaceID: string): Promise { // handle v1 or v2 return Promise.resolve().then(() => this.getNamespacePriceV2(namespaceID)) .catch(() => this.getNamespacePriceV1(namespaceID)) @@ -299,7 +309,7 @@ export class BlockstackNetwork { * @param namespace the namespace ID * @return a promise that resolves to an address (String) */ - getNamespaceBurnAddress(namespace: string) { + getNamespaceBurnAddress(namespace: string): Promise { return Promise.all([ fetchPrivate(`${this.blockstackAPIUrl}/v1/namespaces/${namespace}`), this.getBlockHeight() @@ -393,7 +403,7 @@ export class BlockstackNetwork { * @param zonefileHash the ripemd160(sha256) hash of the zone file * @return a promise that resolves to the zone file's text */ - getZonefile(zonefileHash: string) { + getZonefile(zonefileHash: string): Promise { return fetchPrivate(`${this.blockstackAPIUrl}/v1/zonefiles/${zonefileHash}`) .then((resp) => { if (resp.status === 200) { @@ -517,7 +527,7 @@ export class BlockstackNetwork { * @return a promise that resolves to an Array of Strings, where each item encodes the * type of token this account holds (excluding the underlying blockchain's tokens) */ - getAccountTokens(address: string): Promise<{tokens: string[]}> { + getAccountTokens(address: string): Promise { return fetchPrivate(`${this.blockstackAPIUrl}/v1/accounts/${address}/tokens`) .then((resp) => { if (resp.status === 404) { @@ -606,24 +616,24 @@ export class BlockstackNetwork { } /** - * Broadcasts a signed bitcoin transaction to the network optionally waiting to broadcast the - * transaction until a second transaction has a certain number of confirmations. - * - * @param transaction the hex-encoded transaction to broadcast - * @param transactionToWatch the hex transaction id of the transaction to watch for - * the specified number of confirmations before broadcasting the `transaction` - * @param confirmations the number of confirmations `transactionToWatch` must have - * before broadcasting `transaction`. - * @return Returns a Promise that resolves to an object with a - * `transaction_hash` key containing the transaction hash of the broadcasted transaction. - * - * In the event of an error, it rejects with: - * * a `RemoteServiceError` if there is a problem - * with the transaction broadcast service - * * `MissingParameterError` if you call the function without a required - * parameter - * @private - */ + * Broadcasts a signed bitcoin transaction to the network optionally waiting to broadcast the + * transaction until a second transaction has a certain number of confirmations. + * + * @param transaction the hex-encoded transaction to broadcast + * @param transactionToWatch the hex transaction id of the transaction to watch for + * the specified number of confirmations before broadcasting the `transaction` + * @param confirmations the number of confirmations `transactionToWatch` must have + * before broadcasting `transaction`. + * @return Returns a Promise that resolves to an object with a + * `transaction_hash` key containing the transaction hash of the broadcasted transaction. + * + * In the event of an error, it rejects with: + * * a `RemoteServiceError` if there is a problem + * with the transaction broadcast service + * * `MissingParameterError` if you call the function without a required + * parameter + * @private + */ broadcastTransaction( transaction: string, transactionToWatch: string = null, @@ -824,7 +834,7 @@ export class BlockstackNetwork { /** * @ignore */ - getUTXOs(address: string): Promise> { + getUTXOs(address: string): Promise { return this.getNetworkedUTXOs(address) .then((networkedUTXOs) => { let returnSet = networkedUTXOs.concat() @@ -861,7 +871,7 @@ export class BlockstackNetwork { modifyUTXOSetFrom(txHex: string) { const tx = Transaction.fromHex(txHex) - const excludeSet: Array = this.excludeUtxoSet.concat() + const excludeSet: UTXO[] = this.excludeUtxoSet.concat() tx.ins.forEach((utxoUsed) => { const reverseHash = Buffer.from(utxoUsed.hash) @@ -906,21 +916,24 @@ export class BlockstackNetwork { }) } + /** + * @ignore + */ resetUTXOs(address: string) { delete this.includeUtxoMap[address] this.excludeUtxoSet = [] } /** - * @ignore - */ + * @ignore + */ getConsensusHash() { return fetchPrivate(`${this.blockstackAPIUrl}/v1/blockchains/bitcoin/consensus`) .then(resp => resp.json()) .then(x => x.consensus_hash) } - getTransactionInfo(txHash: string): Promise<{block_height: number}> { + getTransactionInfo(txHash: string): Promise { return this.btc.getTransactionInfo(txHash) } @@ -931,7 +944,7 @@ export class BlockstackNetwork { return this.btc.getBlockHeight() } - getNetworkedUTXOs(address: string): Promise> { + getNetworkedUTXOs(address: string): Promise { return this.btc.getNetworkedUTXOs(address) } } @@ -1002,7 +1015,7 @@ export class BitcoindAPI extends BitcoinNetwork { .then(respObj => respObj.result) } - getTransactionInfo(txHash: string): Promise<{block_height: number}> { + getTransactionInfo(txHash: string): Promise { const jsonRPC = { jsonrpc: '1.0', method: 'gettransaction', @@ -1043,7 +1056,7 @@ export class BitcoindAPI extends BitcoinNetwork { }) } - getNetworkedUTXOs(address: string): Promise> { + getNetworkedUTXOs(address: string): Promise { const jsonRPCImport = { jsonrpc: '1.0', method: 'importaddress', @@ -1114,7 +1127,7 @@ export class InsightClient extends BitcoinNetwork { .then(status => status.blocks) } - getTransactionInfo(txHash: string): Promise<{block_height: number}> { + getTransactionInfo(txHash: string): Promise { return fetchPrivate(`${this.apiUrl}/tx/${txHash}`) .then(resp => resp.json()) .then((transactionInfo) => { @@ -1127,7 +1140,7 @@ export class InsightClient extends BitcoinNetwork { .then(blockInfo => ({ block_height: blockInfo.height })) } - getNetworkedUTXOs(address: string): Promise> { + getNetworkedUTXOs(address: string): Promise { return fetchPrivate(`${this.apiUrl}/addr/${address}/utxo`) .then(resp => resp.json()) .then(utxos => utxos.map( @@ -1159,7 +1172,7 @@ export class BlockchainInfoApi extends BitcoinNetwork { .then(blockObj => blockObj.height) } - getNetworkedUTXOs(address: string): Promise> { + getNetworkedUTXOs(address: string): Promise { return fetchPrivate(`${this.utxoProviderUrl}/unspent?format=json&active=${address}&cors=true`) .then((resp) => { if (resp.status === 500) { @@ -1185,7 +1198,7 @@ export class BlockchainInfoApi extends BitcoinNetwork { )) } - getTransactionInfo(txHash: string): Promise<{block_height: number}> { + getTransactionInfo(txHash: string): Promise { return fetchPrivate(`${this.utxoProviderUrl}/rawtx/${txHash}?cors=true`) .then((resp) => { if (resp.status === 200) { @@ -1236,9 +1249,9 @@ const LOCAL_REGTEST = new LocalRegtest( ) /** -* @ignore +* Instance of [[BlockstackNetwork]] set to the default endpoints. */ -const MAINNET_DEFAULT = new BlockstackNetwork( +export const MAINNET_DEFAULT = new BlockstackNetwork( 'https://core.blockstack.org', 'https://broadcast.blockstack.org', new BlockchainInfoApi() diff --git a/src/utils.ts b/src/utils.ts index d4da7169f..e9e25d580 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -252,7 +252,7 @@ interface GetGlobalObjectOptions { * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/self * @ignore */ -export function getGlobalObject( +export function getGlobalObject>( name: K, { throwIfUnavailable, usageDesc, returnEmptyObject }: GetGlobalObjectOptions = { } ): Window[K] { @@ -287,7 +287,7 @@ export function getGlobalObject( * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/self * @ignore */ -export function getGlobalObjects( +export function getGlobalObjects>( names: K[], { throwIfUnavailable, usageDesc, returnEmptyObject }: GetGlobalObjectOptions = {} ): Pick { From 1c9a3609e0f3f9288ce55b85dc92e82c739cd77b Mon Sep 17 00:00:00 2001 From: Mary Anthony Date: Tue, 6 Aug 2019 18:55:00 -0700 Subject: [PATCH 3/9] Exposing the Blockstack network. Adding the caveat to the getName* "This is intended for use in third-party wallets or in DApps that register names." Also, this exposes AuthScope. Signed-off-by: Mary Anthony --- mdincludes/script-dist-file.md | 2 +- src/network.ts | 21 ++++++++++++++------- tsconfig.typedoc.json | 1 + 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/mdincludes/script-dist-file.md b/mdincludes/script-dist-file.md index 9dfade5dd..3d857def9 100644 --- a/mdincludes/script-dist-file.md +++ b/mdincludes/script-dist-file.md @@ -1,3 +1,3 @@ ```html - + ``` \ No newline at end of file diff --git a/src/network.ts b/src/network.ts index 1649e24ca..21b14990f 100644 --- a/src/network.ts +++ b/src/network.ts @@ -148,7 +148,8 @@ export class BlockstackNetwork { } /** - * Get the price of a namespace via the legacy /v1/prices API endpoint. + * Get the price of a namespace via the legacy /v1/prices API endpoint. This is intended for + * use in third-party wallets or in DApps that register names. * @param namespaceID the namespace to query * @return a promise to an Object with { units: String, amount: BigInteger } * @private @@ -252,7 +253,8 @@ export class BlockstackNetwork { } /** - * Get the price of a name. + * Get the price of a name. This is intended for + * use in third-party wallets or in DApps that register names. * @param fullyQualifiedName the name to query * @return a promise to an Object with { units: String, amount: BigInteger }, where * .units encodes the cryptocurrency units to pay (e.g. BTC, STACKS), and @@ -283,7 +285,8 @@ export class BlockstackNetwork { /** * How many blocks can pass between a name expiring and the name being able to be - * re-registered by a different owner? + * re-registered by a different owner. This is intended for + * use in third-party wallets or in DApps that register names. * @param fullyQualifiedName unused * @return a promise to the number of blocks */ @@ -292,7 +295,8 @@ export class BlockstackNetwork { } /** - * Get the names -- both on-chain and off-chain -- owned by an address. + * Get the names -- both on-chain and off-chain -- owned by an address. This is intended for + * use in third-party wallets or in DApps that register names. * @param address the blockchain address (the hash of the owner public key) * @return a promise that resolves to a list of names (Strings) */ @@ -305,7 +309,8 @@ export class BlockstackNetwork { /** * Get the blockchain address to which a name's registration fee must be sent - * (the address will depend on the namespace in which it is registered.) + * (the address will depend on the namespace in which it is registered.) This is intended for + * use in third-party wallets or in DApps that register names. * @param namespace the namespace ID * @return a promise that resolves to an address (String) */ @@ -367,7 +372,8 @@ export class BlockstackNetwork { } /** - * Get the pricing parameters and creation history of a namespace. + * Get the pricing parameters and creation history of a namespace. This is intended for + * use in third-party wallets or in DApps that register names. * @param namespaceID the namespace to query * @return a promise that resolves to the namespace information. */ @@ -1259,7 +1265,8 @@ export const MAINNET_DEFAULT = new BlockstackNetwork( /** * Get WHOIS-like information for a name, including the address that owns it, - * the block at which it expires, and the zone file anchored to it (if available). + * the block at which it expires, and the zone file anchored to it (if available). This is intended for + * use in third-party wallets or in DApps that register names. * @param fullyQualifiedName the name to query. Can be on-chain of off-chain. * @return a promise that resolves to the WHOIS-like information */ diff --git a/tsconfig.typedoc.json b/tsconfig.typedoc.json index d53bfc72b..9429e597a 100644 --- a/tsconfig.typedoc.json +++ b/tsconfig.typedoc.json @@ -18,6 +18,7 @@ "excludePrivate": true, "excludeProtected": true, "excludeExternals": true, + "excludeNotExported": false, "includes" : "mdincludes", "includeDeclarations": false, "gitRevision": "master", From abc2cb0f75b97996c6d21fa1e0e9c2963c2ab161 Mon Sep 17 00:00:00 2001 From: Mary Anthony Date: Tue, 6 Aug 2019 19:02:21 -0700 Subject: [PATCH 4/9] Fixing line length Signed-off-by: Mary Anthony --- src/network.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network.ts b/src/network.ts index 21b14990f..1d91c2223 100644 --- a/src/network.ts +++ b/src/network.ts @@ -1265,8 +1265,8 @@ export const MAINNET_DEFAULT = new BlockstackNetwork( /** * Get WHOIS-like information for a name, including the address that owns it, - * the block at which it expires, and the zone file anchored to it (if available). This is intended for - * use in third-party wallets or in DApps that register names. + * the block at which it expires, and the zone file anchored to it (if available). + * This is intended for use in third-party wallets or in DApps that register names. * @param fullyQualifiedName the name to query. Can be on-chain of off-chain. * @return a promise that resolves to the WHOIS-like information */ From 6687f36ea9886b981e24a2a5a1f5a9af7f9191cc Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Mon, 12 Aug 2019 14:22:44 -0400 Subject: [PATCH 5/9] Fix deleteFile not using fetchPrivate --- src/storage/hub.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/hub.ts b/src/storage/hub.ts index 2884a99da..b2f7419dc 100644 --- a/src/storage/hub.ts +++ b/src/storage/hub.ts @@ -63,7 +63,7 @@ export async function deleteFromGaiaHub( hubConfig: GaiaHubConfig ): Promise { Logger.debug(`deleteFromGaiaHub: deleting ${filename} from ${hubConfig.server}`) - const response = await fetch( + const response = await fetchPrivate( `${hubConfig.server}/delete/${hubConfig.address}/${filename}`, { method: 'DELETE', headers: { From ade8820bd079a325f2be00f470b55c6d15dab564 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Mon, 12 Aug 2019 16:21:51 -0400 Subject: [PATCH 6/9] Support passing Blobs and TypedArrays to `putFile` --- package-lock.json | 44 +++++++++++----------- package.json | 3 +- src/auth/userSession.ts | 6 ++- src/fetchUtil.ts | 10 +++-- src/storage/hub.ts | 2 +- src/storage/index.ts | 83 ++++++++++++++++++++++++++++++++++++----- 6 files changed, 107 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index a4ca55c44..bc4ca01bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2474,19 +2474,12 @@ } }, "cross-fetch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", - "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.4.tgz", + "integrity": "sha512-MSHgpjQqgbT/94D4CyADeNoYh52zMkCX4pcJvPP5WqPsLFMKjr2TCMg381ox5qI0ii2dPwaLx/00477knXqXVw==", "requires": { - "node-fetch": "2.1.2", - "whatwg-fetch": "2.0.4" - }, - "dependencies": { - "node-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" - } + "node-fetch": "2.6.0", + "whatwg-fetch": "3.0.0" } }, "cross-spawn": { @@ -3630,6 +3623,16 @@ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, "path-to-regexp": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", @@ -6093,14 +6096,9 @@ } }, "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, "node-libs-browser": { "version": "2.2.0", @@ -9892,9 +9890,9 @@ } }, "whatwg-fetch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" }, "which": { "version": "1.3.1", diff --git a/package.json b/package.json index 359e720bc..483d8ed06 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,6 @@ "express": "^4.16.4", "fetch-mock": "^5.5.0", "mock-local-storage": "^1.1.8", - "node-fetch": "^1.6.3", "nyc": "^13.3.0", "opn": "^4.0.2", "proxyquire": "^2.1.0", @@ -135,7 +134,7 @@ "bitcoinjs-lib": "^5.1.2", "bn.js": "^4.11.8", "cheerio": "^0.22.0", - "cross-fetch": "^2.2.2", + "cross-fetch": "^3.0.4", "elliptic": "^6.4.1", "form-data": "^2.3.3", "jsontokens": "^2.0.2", diff --git a/src/auth/userSession.ts b/src/auth/userSession.ts index e28d0acaf..73fafde9b 100644 --- a/src/auth/userSession.ts +++ b/src/auth/userSession.ts @@ -294,7 +294,11 @@ export class UserSession { * @returns {Promise} that resolves if the operation succeed and rejects * if it failed */ - putFile(path: string, content: string | Buffer, options?: import('../storage').PutFileOptions) { + putFile( + path: string, + content: string | Buffer | ArrayBufferView | Blob, + options?: import('../storage').PutFileOptions + ) { return storage.putFile(path, content, options, this) } diff --git a/src/fetchUtil.ts b/src/fetchUtil.ts index 5a08121d3..be48b809b 100644 --- a/src/fetchUtil.ts +++ b/src/fetchUtil.ts @@ -1,7 +1,9 @@ +import 'cross-fetch/polyfill' /** @ignore */ -export function fetchPrivate(input: RequestInfo, init?: RequestInit): Promise { - init = init || { } - init.referrerPolicy = 'no-referrer' - return fetch(input, init) +export async function fetchPrivate(input: RequestInfo, init?: RequestInit): Promise { + const fetchOpts = init || { } + fetchOpts.referrerPolicy = 'no-referrer' + const fetchResult = await fetch(input, fetchOpts) + return fetchResult } diff --git a/src/storage/hub.ts b/src/storage/hub.ts index b2f7419dc..440dcfbff 100644 --- a/src/storage/hub.ts +++ b/src/storage/hub.ts @@ -35,7 +35,7 @@ export interface GaiaHubConfig { * @ignore */ export async function uploadToGaiaHub( - filename: string, contents: any, + filename: string, contents: Blob | Buffer | ArrayBufferView | string, hubConfig: GaiaHubConfig, contentType: string = 'application/octet-stream' ): Promise { diff --git a/src/storage/index.ts b/src/storage/index.ts index 438031249..4200426b4 100644 --- a/src/storage/index.ts +++ b/src/storage/index.ts @@ -468,6 +468,61 @@ export function getFile( }) } +/** @ignore */ +type PutFileContent = string | Buffer | ArrayBufferView | Blob + +/** @ignore */ +class FileContentLoader { + content: PutFileContent + + loadedData?: Promise + + constructor(content: PutFileContent) { + this.content = content + } + + getContentType(): string { + if (typeof this.content === 'string') { + return 'text/plain; charset=utf-8' + } else if (typeof Blob !== 'undefined' && this.content instanceof Blob && this.content.type) { + return this.content.type + } else { + return 'application/octet-stream' + } + } + + private async loadContent(): Promise { + if (typeof this.content === 'string') { + return this.content + } else if (ArrayBuffer.isView(this.content)) { + return Buffer.from(this.content.buffer) + } else if (typeof Blob !== 'undefined' && this.content instanceof Blob) { + const reader = new FileReader() + const readPromise = new Promise((resolve, reject) => { + reader.onerror = (err) => { + reject(err) + } + reader.onload = () => { + const arrayBuffer = reader.result as ArrayBuffer + resolve(Buffer.from(arrayBuffer)) + } + reader.readAsArrayBuffer(this.content as Blob) + }) + const result = await readPromise + return result + } + const typeName = Object.prototype.toString.call(this.content) + throw new Error(`Unsupported content object type: ${typeName}`) + } + + load(): Promise { + if (this.loadedData === undefined) { + this.loadedData = this.loadContent() + } + return this.loadedData + } +} + /** * Stores the data provided in the app's data store to to the file specified. * @param {String} path - the path to store the data in @@ -477,10 +532,12 @@ export function getFile( */ export async function putFile( path: string, - content: string | Buffer, + content: string | Buffer | ArrayBufferView | Blob, options?: PutFileOptions, caller?: UserSession, ): Promise { + const contentLoader = new FileContentLoader(content) + const defaults: PutFileOptions = { encrypt: true, sign: false, @@ -491,7 +548,7 @@ export async function putFile( let { contentType } = opt if (!contentType) { - contentType = (typeof (content) === 'string') ? 'text/plain; charset=utf-8' : 'application/octet-stream' + contentType = contentLoader.getContentType() } if (!caller) { @@ -525,13 +582,14 @@ export async function putFile( // we perform two uploads. So the control-flow // here will return there. if (!opt.encrypt && opt.sign) { - const signatureObject = signECDSA(privateKey, content) + const contentData = await contentLoader.load() + const signatureObject = signECDSA(privateKey, contentData) const signatureContent = JSON.stringify(signatureObject) const gaiaHubConfig = await caller.getOrSetLocalGaiaHubConnection() try { const fileUrls = await Promise.all([ - uploadToGaiaHub(path, content, gaiaHubConfig, contentType), + uploadToGaiaHub(path, contentData, gaiaHubConfig, contentType), uploadToGaiaHub(`${path}${SIGNATURE_FILE_SUFFIX}`, signatureContent, gaiaHubConfig, 'application/json') ]) @@ -539,7 +597,7 @@ export async function putFile( } catch (error) { const freshHubConfig = await caller.setLocalGaiaHubConnection() const fileUrls = await Promise.all([ - uploadToGaiaHub(path, content, freshHubConfig, contentType), + uploadToGaiaHub(path, contentData, freshHubConfig, contentType), uploadToGaiaHub(`${path}${SIGNATURE_FILE_SUFFIX}`, signatureContent, freshHubConfig, 'application/json') ]) @@ -548,26 +606,31 @@ export async function putFile( } // In all other cases, we only need one upload. + let contentForUpload: Blob | Buffer | ArrayBufferView | string if (opt.encrypt && !opt.sign) { - content = encryptContent(content, { publicKey }) + const contentData = await contentLoader.load() + contentForUpload = encryptContent(contentData, { publicKey }) contentType = 'application/json' } else if (opt.encrypt && opt.sign) { - const cipherText = encryptContent(content, { publicKey }) + const contentData = await contentLoader.load() + const cipherText = encryptContent(contentData, { publicKey }) const signatureObject = signECDSA(privateKey, cipherText) const signedCipherObject = { signature: signatureObject.signature, publicKey: signatureObject.publicKey, cipherText } - content = JSON.stringify(signedCipherObject) + contentForUpload = JSON.stringify(signedCipherObject) contentType = 'application/json' + } else { + contentForUpload = content } const gaiaHubConfig = await caller.getOrSetLocalGaiaHubConnection() try { - return await uploadToGaiaHub(path, content, gaiaHubConfig, contentType) + return await uploadToGaiaHub(path, contentForUpload, gaiaHubConfig, contentType) } catch (error) { const freshHubConfig = await caller.setLocalGaiaHubConnection() - const file = await uploadToGaiaHub(path, content, freshHubConfig, contentType) + const file = await uploadToGaiaHub(path, contentForUpload, freshHubConfig, contentType) return file } } From 4cafb8f26e94129f7de835665258a8e264c77724 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Mon, 12 Aug 2019 17:56:44 -0400 Subject: [PATCH 7/9] Unit tests for using the DOM File API in putFile --- .vscode/launch.json | 16 ++ package-lock.json | 318 ++++++++++++++++++++++++ package.json | 2 + src/storage/hub.ts | 3 +- tests/unitTests/src/unitTestsStorage.ts | 127 +++++++++- 5 files changed, 464 insertions(+), 2 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..611000fae --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "unitTests", + "args": ["${workspaceFolder}/tests/unitTests/src/index.ts"], + "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"], + "outputCapture": "std" + } + ] +} diff --git a/package-lock.json b/package-lock.json index bc4ca01bc..441747dde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -985,6 +985,25 @@ "@types/node": "*" } }, + "@types/jsdom": { + "version": "12.2.4", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-12.2.4.tgz", + "integrity": "sha512-q+De3S/Ri6U9uPx89YA1XuC+QIBgndIfvBaaJG0pRT8Oqa75k4Mr7G9CRZjIvlbLGIukO/31DFGFJYlQBmXf/A==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^4.0.0" + }, + "dependencies": { + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + } + } + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1032,6 +1051,12 @@ "@types/node": "*" } }, + "@types/tough-cookie": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz", + "integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==", + "dev": true + }, "@types/triplesec": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/triplesec/-/triplesec-3.0.0.tgz", @@ -1270,6 +1295,12 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, "accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", @@ -1292,6 +1323,16 @@ "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", "dev": true }, + "acorn-globals": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.3.tgz", + "integrity": "sha512-vkR40VwS2SYO98AIeFvzWWh+xyc2qi9s7OoXSFEGIP/rOJKzjnhykaZJNnHdoq4BL2gGxI5EZOU16z896EYnOQ==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + } + }, "acorn-jsx": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", @@ -1421,6 +1462,12 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -1863,6 +1910,12 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -2530,6 +2583,21 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, "cyclist": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", @@ -2544,6 +2612,17 @@ "assert-plus": "^1.0.0" } }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -2729,6 +2808,15 @@ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, "domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", @@ -2967,6 +3055,27 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } + } + }, "eslint": { "version": "5.16.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", @@ -4820,6 +4929,15 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, "htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", @@ -5054,6 +5172,12 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, "ipaddr.js": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", @@ -5338,6 +5462,62 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "jsdom": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.1.1.tgz", + "integrity": "sha512-cQZRBB33arrDAeCrAEWn1U3SvrvC8XysBua9Oqg1yWrsY/gYcusloJC3RZJXuY5eehSCmws8f2YeliCqGSkrtQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^6.1.1", + "acorn-globals": "^4.3.2", + "array-equal": "^1.0.0", + "cssom": "^0.3.6", + "cssstyle": "^1.2.2", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.1", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.1.4", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.7", + "saxes": "^3.1.9", + "symbol-tree": "^3.2.2", + "tough-cookie": "^3.0.1", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^7.0.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "tough-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "dev": true, + "requires": { + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "ws": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz", + "integrity": "sha512-gftXq3XI81cJCgkUiAVixA0raD9IVmXqsylCrjRygw4+UOOGzPoxnQ6r/CnVL9i+mDncJo94tSkyrtuuQVBmrg==", + "dev": true, + "requires": { + "async-limiter": "^1.0.0" + } + } + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -5639,6 +5819,12 @@ "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, "lodash.unescape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", @@ -6227,6 +6413,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nwsapi": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", + "dev": true + }, "nyc": { "version": "13.3.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-13.3.0.tgz", @@ -7613,6 +7805,12 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", @@ -7746,6 +7944,12 @@ "find-up": "^3.0.0" } }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -8169,6 +8373,26 @@ "uuid": "^3.3.2" } }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8324,6 +8548,15 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "saxes": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", + "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "dev": true, + "requires": { + "xmlchars": "^2.1.1" + } + }, "schema-inspector": { "version": "1.6.8", "resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-1.6.8.tgz", @@ -8813,6 +9046,12 @@ "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "dev": true }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -8974,6 +9213,12 @@ "has-flag": "^3.0.0" } }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "table": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", @@ -9277,6 +9522,15 @@ } } }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", @@ -9767,6 +10021,26 @@ "indexof": "0.0.1" } }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "w3c-xmlserializer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "dev": true, + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", @@ -9778,6 +10052,12 @@ "neo-async": "^2.5.0" } }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, "webpack": { "version": "4.29.6", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.6.tgz", @@ -9889,11 +10169,37 @@ "source-map": "~0.6.1" } }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, "whatwg-fetch": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -10003,6 +10309,18 @@ "async-limiter": "~1.0.0" } }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xmlchars": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.1.1.tgz", + "integrity": "sha512-7hew1RPJ1iIuje/Y01bGD/mXokXxegAgVS+e+E0wSi2ILHQkYAH1+JXARwTjZSM4Z4Z+c73aKspEcqj+zPPL/w==", + "dev": true + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index 483d8ed06..bdc654fb1 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "@types/cheerio": "^0.22.10", "@types/fetch-mock": "^5.8.0", "@types/form-data": "^2.2.1", + "@types/jsdom": "^12.2.4", "@types/node": "^10", "@types/proxyquire": "^1.3.28", "@types/ripemd160": "^2.0.0", @@ -107,6 +108,7 @@ "eslint-plugin-import": "^2.16.0", "express": "^4.16.4", "fetch-mock": "^5.5.0", + "jsdom": "^15.1.1", "mock-local-storage": "^1.1.8", "nyc": "^13.3.0", "opn": "^4.0.2", diff --git a/src/storage/hub.ts b/src/storage/hub.ts index 440dcfbff..16fc572a1 100644 --- a/src/storage/hub.ts +++ b/src/storage/hub.ts @@ -35,7 +35,8 @@ export interface GaiaHubConfig { * @ignore */ export async function uploadToGaiaHub( - filename: string, contents: Blob | Buffer | ArrayBufferView | string, + filename: string, + contents: Blob | Buffer | ArrayBufferView | string, hubConfig: GaiaHubConfig, contentType: string = 'application/octet-stream' ): Promise { diff --git a/tests/unitTests/src/unitTestsStorage.ts b/tests/unitTests/src/unitTestsStorage.ts index bb569d76e..56c4dd6fe 100644 --- a/tests/unitTests/src/unitTestsStorage.ts +++ b/tests/unitTests/src/unitTestsStorage.ts @@ -1,4 +1,4 @@ -import * as test from 'tape' +import * as test from 'tape-promise/tape' import * as FetchMock from 'fetch-mock' import * as proxyquire from 'proxyquire' import * as sinon from 'sinon' @@ -14,6 +14,9 @@ import { getPublicKeyFromPrivate } from '../../../src/keys' import { UserSession, AppConfig } from '../../../src' +import * as jsdom from 'jsdom' + + // class LocalStorage { // constructor() { // this.data = {} @@ -387,6 +390,128 @@ export function runStorageTests() { t.equal(content, deciphered) }) + test('putFile unencrypted, using Blob content', async (t) => { + const path = 'file.json' + const gaiaHubConfig = { + address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U', + server: 'https://hub.blockstack.org', + token: '', + url_prefix: 'gaia.testblockstack.org/hub/' + } + + const appConfig = new AppConfig(['store_write'], 'http://localhost:3000') + const blockstack = new UserSession({ appConfig }) + blockstack.store.getSessionData().userData = { + gaiaHubConfig + } + + const dom = new jsdom.JSDOM('', {}).window + const globalAPIs: {[key: string]: any } = { + File: dom.File, + Blob: dom.Blob, + FileReader: (dom as any).FileReader as FileReader + } + for (const globalAPI of Object.keys(globalAPIs)) { + (global as any)[globalAPI] = globalAPIs[globalAPI] + } + try { + const fileContent = new dom.File(['file content test'], 'filenametest.txt', { type: 'text/example' }) + const fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json' + + let uploadContentType: any + const uploadToGaiaHub = ( + filename: string, + contents: any, + hubConfig: any, + contentType: string) => { + uploadContentType = contentType + return Promise.resolve(fullReadUrl) + }; + + const { putFile } = proxyquire('../../../src/storage', { + './hub': { uploadToGaiaHub } + }) + + const options = { encrypt: false } + + const publicURL = await putFile(path, fileContent, options, blockstack) + t.equal(publicURL, fullReadUrl) + t.equal(uploadContentType, 'text/example') + } finally { + for (const globalAPI of Object.keys(globalAPIs)) { + delete (global as any)[globalAPI] + } + } + }) + + test('putFile encrypted, using Blob content, encrypted', async (t) => { + const dom = new jsdom.JSDOM('', {}).window + const globalAPIs: {[key: string]: any } = { + File: dom.File, + Blob: dom.Blob, + FileReader: (dom as any).FileReader as FileReader + } + for (const globalAPI of Object.keys(globalAPIs)) { + (global as any)[globalAPI] = globalAPIs[globalAPI] + } + try { + const contentDataString = 'file content test' + const fileContent = new dom.File([contentDataString], 'filenametest.txt', { type: 'text/example' }) + + const privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229' + const appConfig = new AppConfig(['store_write'], 'http://localhost:3000') + const blockstack = new UserSession({ appConfig }) + + const path = 'file.json' + const gaiaHubConfig = { + address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U', + server: 'https://hub.blockstack.org', + token: '', + url_prefix: 'https://gaia.testblockstack.org/hub/' + } + + blockstack.store.getSessionData().userData = { + appPrivateKey: privateKey, + gaiaHubConfig + } // manually set private key for testing + + const fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8A/file.json' + + let encryptedContent: any + const uploadToGaiaHub = ( + filename: string, + contents: any, + hubConfig: any, + contentType: string) => { + encryptedContent = contents + return Promise.resolve(fullReadUrl) + }; + const getFullReadUrl = sinon.stub().resolves(fullReadUrl) // eslint-disable-line no-shadow + + const { putFile } = proxyquire('../../../src/storage', { + './hub': { uploadToGaiaHub } + }) + const { getFile } = proxyquire('../../../src/storage', { // eslint-disable-line no-shadow + './hub': { getFullReadUrl } + }) + + const encryptOptions = { encrypt: true } + const decryptOptions = { decrypt: true } + // put and encrypt the file + const publicURL = await putFile(path, fileContent, encryptOptions, blockstack) + t.equal(publicURL, fullReadUrl) + FetchMock.get(fullReadUrl, encryptedContent) + const readContent = await getFile(path, decryptOptions, blockstack) + const readContentStr = readContent.toString() + t.equal(readContentStr, contentDataString) + } finally { + for (const globalAPI of Object.keys(globalAPIs)) { + delete (global as any)[globalAPI] + } + FetchMock.restore() + } + }) + test('putFile unencrypted, not signed', (t) => { t.plan(1) From 8b9ee0ffad83b4723314d8e3f9dd1ca602c34b7d Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Mon, 12 Aug 2019 18:25:17 -0400 Subject: [PATCH 8/9] Tests for using TypedArray with putFile --- tests/unitTests/src/unitTestsStorage.ts | 118 +++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/tests/unitTests/src/unitTestsStorage.ts b/tests/unitTests/src/unitTestsStorage.ts index 56c4dd6fe..2399bf8c6 100644 --- a/tests/unitTests/src/unitTestsStorage.ts +++ b/tests/unitTests/src/unitTestsStorage.ts @@ -13,7 +13,7 @@ import { getFile, getFileUrl, putFile, listFiles, deleteFile } from '../../../sr import { getPublicKeyFromPrivate } from '../../../src/keys' import { UserSession, AppConfig } from '../../../src' - +import * as util from 'util' import * as jsdom from 'jsdom' @@ -512,6 +512,122 @@ export function runStorageTests() { } }) + test('putFile unencrypted, using TypedArray content, encrypted', async (t) => { + try { + const contentDataString = 'file content test1234567' + const textEncoder = new util.TextEncoder() + const encodedArray = textEncoder.encode(contentDataString) + const fileContent = new Uint32Array(encodedArray.buffer) + + const privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229' + const appConfig = new AppConfig(['store_write'], 'http://localhost:3000') + const blockstack = new UserSession({ appConfig }) + + const path = 'file.json' + const gaiaHubConfig = { + address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U', + server: 'https://hub.blockstack.org', + token: '', + url_prefix: 'https://gaia.testblockstack.org/hub/' + } + + blockstack.store.getSessionData().userData = { + appPrivateKey: privateKey, + gaiaHubConfig + } // manually set private key for testing + + const fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8A/file.json' + + let postedContent: any + const uploadToGaiaHub = ( + filename: string, + contents: any, + hubConfig: any, + contentType: string) => { + postedContent = Buffer.from(contents.buffer).toString() + return Promise.resolve(fullReadUrl) + }; + const getFullReadUrl = sinon.stub().resolves(fullReadUrl) // eslint-disable-line no-shadow + + const { putFile } = proxyquire('../../../src/storage', { + './hub': { uploadToGaiaHub } + }) + const { getFile } = proxyquire('../../../src/storage', { // eslint-disable-line no-shadow + './hub': { getFullReadUrl } + }) + + const encryptOptions = { encrypt: false, contentType: 'text/plain; charset=utf-8' } + const decryptOptions = { decrypt: false } + // put and encrypt the file + const publicURL = await putFile(path, fileContent, encryptOptions, blockstack) + t.equal(publicURL, fullReadUrl) + FetchMock.get(fullReadUrl, { status: 200, body: postedContent, headers: {'Content-Type': 'text/plain; charset=utf-8' } }) + const readContent = await getFile(path, decryptOptions, blockstack) + const readContentStr = readContent.toString() + t.equal(readContentStr, contentDataString) + } finally { + FetchMock.restore() + } + }) + + test('putFile encrypted, using TypedArray content, encrypted', async (t) => { + try { + const contentDataString = 'file content test1234567' + const textEncoder = new util.TextEncoder() + const encodedArray = textEncoder.encode(contentDataString) + const fileContent = new Uint32Array(encodedArray.buffer) + + const privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229' + const appConfig = new AppConfig(['store_write'], 'http://localhost:3000') + const blockstack = new UserSession({ appConfig }) + + const path = 'file.json' + const gaiaHubConfig = { + address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U', + server: 'https://hub.blockstack.org', + token: '', + url_prefix: 'https://gaia.testblockstack.org/hub/' + } + + blockstack.store.getSessionData().userData = { + appPrivateKey: privateKey, + gaiaHubConfig + } // manually set private key for testing + + const fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8A/file.json' + + let encryptedContent: any + const uploadToGaiaHub = ( + filename: string, + contents: any, + hubConfig: any, + contentType: string) => { + encryptedContent = contents + return Promise.resolve(fullReadUrl) + }; + const getFullReadUrl = sinon.stub().resolves(fullReadUrl) // eslint-disable-line no-shadow + + const { putFile } = proxyquire('../../../src/storage', { + './hub': { uploadToGaiaHub } + }) + const { getFile } = proxyquire('../../../src/storage', { // eslint-disable-line no-shadow + './hub': { getFullReadUrl } + }) + + const encryptOptions = { encrypt: true } + const decryptOptions = { decrypt: true } + // put and encrypt the file + const publicURL = await putFile(path, fileContent, encryptOptions, blockstack) + t.equal(publicURL, fullReadUrl) + FetchMock.get(fullReadUrl, encryptedContent) + const readContent = await getFile(path, decryptOptions, blockstack) + const readContentStr = readContent.toString() + t.equal(readContentStr, contentDataString) + } finally { + FetchMock.restore() + } + }) + test('putFile unencrypted, not signed', (t) => { t.plan(1) From 586ed8c15b456fcb811f940db108e097ce1cfa12 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Fri, 23 Aug 2019 13:01:31 -0400 Subject: [PATCH 9/9] Revert doc PR changes --- src/network.ts | 252 +++++++++++++++++++----------------------- tsconfig.typedoc.json | 1 - 2 files changed, 116 insertions(+), 137 deletions(-) diff --git a/src/network.ts b/src/network.ts index b15a5435d..5d1c890e9 100644 --- a/src/network.ts +++ b/src/network.ts @@ -8,25 +8,14 @@ import { Logger } from './logger' import { config } from './config' import { fetchPrivate } from './fetchUtil' -export interface UTXO { - value?: number; - confirmations?: number; - tx_hash: string; - tx_output_n: number; -} - -export interface PriceInfo { - units: string; - amount: BN; -} - -export interface AccountTokens { - tokens: string[]; -} - -export interface TransactionInfo { - block_height: number; - [key: string]: any; +/** + * @ignore + */ +export type UTXO = { + value?: number, + confirmations?: number, + tx_hash: string, + tx_output_n: number } const SATOSHIS_PER_BTC = 1e8 @@ -47,17 +36,18 @@ export class BitcoinNetwork { return Promise.reject(new Error('Not implemented, getBlockHeight()')) } - getTransactionInfo(txid: string): Promise { + getTransactionInfo(txid: string): Promise<{block_height: number}> { return Promise.reject(new Error(`Not implemented, getTransactionInfo(${txid})`)) } - getNetworkedUTXOs(address: string): Promise { + getNetworkedUTXOs(address: string): Promise> { return Promise.reject(new Error(`Not implemented, getNetworkedUTXOs(${address})`)) } } /** - * + * @private + * @ignore */ export class BlockstackNetwork { blockstackAPIUrl: string @@ -70,7 +60,7 @@ export class BlockstackNetwork { includeUtxoMap: {[address: string]: UTXO[]} - excludeUtxoSet: UTXO[] + excludeUtxoSet: Array btc: BitcoinNetwork @@ -90,9 +80,6 @@ export class BlockstackNetwork { this.MAGIC_BYTES = 'id' } - /** - * @ignore - */ coerceAddress(address: string) { const { hash, version } = bjsAddress.fromBase58Check(address) const scriptHashes = [networks.bitcoin.scriptHash, @@ -110,17 +97,20 @@ export class BlockstackNetwork { return bjsAddress.toBase58Check(hash, coercedVersion) } + /** + * @ignore + */ getDefaultBurnAddress() { return this.coerceAddress('1111111111111111111114oLvT2') } /** * Get the price of a name via the legacy /v1/prices API endpoint. - * @param fullyQualifiedName the name to query - * @return a promise to an Object with { units: String, amount: BigInteger } + * @param {String} fullyQualifiedName the name to query + * @return {Promise} a promise to an Object with { units: String, amount: BigInteger } * @private */ - getNamePriceV1(fullyQualifiedName: string): Promise { + getNamePriceV1(fullyQualifiedName: string): Promise<{units: string, amount: BN}> { // legacy code path return fetchPrivate(`${this.blockstackAPIUrl}/v1/prices/names/${fullyQualifiedName}`) .then((resp) => { @@ -149,13 +139,12 @@ export class BlockstackNetwork { } /** - * Get the price of a namespace via the legacy /v1/prices API endpoint. This is intended for - * use in third-party wallets or in DApps that register names. - * @param namespaceID the namespace to query - * @return a promise to an Object with { units: String, amount: BigInteger } + * Get the price of a namespace via the legacy /v1/prices API endpoint. + * @param {String} namespaceID the namespace to query + * @return {Promise} a promise to an Object with { units: String, amount: BigInteger } * @private */ - getNamespacePriceV1(namespaceID: string): Promise { + getNamespacePriceV1(namespaceID: string): Promise<{units: string, amount: BN}> { // legacy code path return fetchPrivate(`${this.blockstackAPIUrl}/v1/prices/namespaces/${namespaceID}`) .then((resp) => { @@ -182,11 +171,11 @@ export class BlockstackNetwork { /** * Get the price of a name via the /v2/prices API endpoint. - * @param fullyQualifiedName the name to query - * @return a promise to an Object with { units: String, amount: BigInteger } + * @param {String} fullyQualifiedName the name to query + * @return {Promise} a promise to an Object with { units: String, amount: BigInteger } * @private */ - getNamePriceV2(fullyQualifiedName: string): Promise { + getNamePriceV2(fullyQualifiedName: string): Promise<{units: string, amount: BN}> { return fetchPrivate(`${this.blockstackAPIUrl}/v2/prices/names/${fullyQualifiedName}`) .then((resp) => { if (resp.status !== 200) { @@ -220,11 +209,11 @@ export class BlockstackNetwork { /** * Get the price of a namespace via the /v2/prices API endpoint. - * @param namespaceID the namespace to query - * @return a promise to an Object with { units: String, amount: BigInteger } + * @param {String} namespaceID the namespace to query + * @return {Promise} a promise to an Object with { units: String, amount: BigInteger } * @private */ - getNamespacePriceV2(namespaceID: string): Promise { + getNamespacePriceV2(namespaceID: string): Promise<{units: string, amount: BN}> { return fetchPrivate(`${this.blockstackAPIUrl}/v2/prices/namespaces/${namespaceID}`) .then((resp) => { if (resp.status !== 200) { @@ -254,16 +243,15 @@ export class BlockstackNetwork { } /** - * Get the price of a name. This is intended for - * use in third-party wallets or in DApps that register names. - * @param fullyQualifiedName the name to query - * @return a promise to an Object with { units: String, amount: BigInteger }, where + * Get the price of a name. + * @param {String} fullyQualifiedName the name to query + * @return {Promise} a promise to an Object with { units: String, amount: BigInteger }, where * .units encodes the cryptocurrency units to pay (e.g. BTC, STACKS), and * .amount encodes the number of units, in the smallest denominiated amount * (e.g. if .units is BTC, .amount will be satoshis; if .units is STACKS, * .amount will be microStacks) */ - getNamePrice(fullyQualifiedName: string): Promise { + getNamePrice(fullyQualifiedName: string): Promise<{units: string, amount: BN}> { // handle v1 or v2 return Promise.resolve().then(() => this.getNamePriceV2(fullyQualifiedName)) .catch(() => this.getNamePriceV1(fullyQualifiedName)) @@ -271,14 +259,14 @@ export class BlockstackNetwork { /** * Get the price of a namespace - * @param namespaceID the namespace to query - * @return a promise to an Object with { units: String, amount: BigInteger }, where + * @param {String} namespaceID the namespace to query + * @return {Promise} a promise to an Object with { units: String, amount: BigInteger }, where * .units encodes the cryptocurrency units to pay (e.g. BTC, STACKS), and * .amount encodes the number of units, in the smallest denominiated amount * (e.g. if .units is BTC, .amount will be satoshis; if .units is STACKS, * .amount will be microStacks) */ - getNamespacePrice(namespaceID: string): Promise { + getNamespacePrice(namespaceID: string): Promise<{units: string, amount: BN}> { // handle v1 or v2 return Promise.resolve().then(() => this.getNamespacePriceV2(namespaceID)) .catch(() => this.getNamespacePriceV1(namespaceID)) @@ -286,20 +274,18 @@ export class BlockstackNetwork { /** * How many blocks can pass between a name expiring and the name being able to be - * re-registered by a different owner. This is intended for - * use in third-party wallets or in DApps that register names. - * @param fullyQualifiedName unused - * @return a promise to the number of blocks + * re-registered by a different owner? + * @param {string} fullyQualifiedName unused + * @return {Promise} a promise to the number of blocks */ getGracePeriod(fullyQualifiedName?: string) { return Promise.resolve(5000) } /** - * Get the names -- both on-chain and off-chain -- owned by an address. This is intended for - * use in third-party wallets or in DApps that register names. - * @param address the blockchain address (the hash of the owner public key) - * @return a promise that resolves to a list of names (Strings) + * Get the names -- both on-chain and off-chain -- owned by an address. + * @param {String} address the blockchain address (the hash of the owner public key) + * @return {Promise} a promise that resolves to a list of names (Strings) */ getNamesOwned(address: string): Promise { const networkAddress = this.coerceAddress(address) @@ -310,12 +296,11 @@ export class BlockstackNetwork { /** * Get the blockchain address to which a name's registration fee must be sent - * (the address will depend on the namespace in which it is registered.) This is intended for - * use in third-party wallets or in DApps that register names. - * @param namespace the namespace ID - * @return a promise that resolves to an address (String) + * (the address will depend on the namespace in which it is registered.) + * @param {String} namespace the namespace ID + * @return {Promise} a promise that resolves to an address (String) */ - getNamespaceBurnAddress(namespace: string): Promise { + getNamespaceBurnAddress(namespace: string) { return Promise.all([ fetchPrivate(`${this.blockstackAPIUrl}/v1/namespaces/${namespace}`), this.getBlockHeight() @@ -343,8 +328,8 @@ export class BlockstackNetwork { /** * Get WHOIS-like information for a name, including the address that owns it, * the block at which it expires, and the zone file anchored to it (if available). - * @param fullyQualifiedName the name to query. Can be on-chain of off-chain. - * @return a promise that resolves to the WHOIS-like information + * @param {String} fullyQualifiedName the name to query. Can be on-chain of off-chain. + * @return {Promise} a promise that resolves to the WHOIS-like information */ getNameInfo(fullyQualifiedName: string) { Logger.debug(this.blockstackAPIUrl) @@ -373,10 +358,9 @@ export class BlockstackNetwork { } /** - * Get the pricing parameters and creation history of a namespace. This is intended for - * use in third-party wallets or in DApps that register names. - * @param namespaceID the namespace to query - * @return a promise that resolves to the namespace information. + * Get the pricing parameters and creation history of a namespace. + * @param {String} namespaceID the namespace to query + * @return {Promise} a promise that resolves to the namespace information. */ getNamespaceInfo(namespaceID: string) { return fetchPrivate(`${this.blockstackAPIUrl}/v1/namespaces/${namespaceID}`) @@ -407,10 +391,10 @@ export class BlockstackNetwork { /** * Get a zone file, given its hash. Throws an exception if the zone file * obtained does not match the hash. - * @param zonefileHash the ripemd160(sha256) hash of the zone file - * @return a promise that resolves to the zone file's text + * @param {String} zonefileHash the ripemd160(sha256) hash of the zone file + * @return {Promise} a promise that resolves to the zone file's text */ - getZonefile(zonefileHash: string): Promise { + getZonefile(zonefileHash: string) { return fetchPrivate(`${this.blockstackAPIUrl}/v1/zonefiles/${zonefileHash}`) .then((resp) => { if (resp.status === 200) { @@ -432,9 +416,9 @@ export class BlockstackNetwork { /** * Get the status of an account for a particular token holding. This includes its total number of * expenditures and credits, lockup times, last txid, and so on. - * @param address the account - * @param tokenType the token type to query - * @return a promise that resolves to an object representing the state of the account + * @param {String} address the account + * @param {String} tokenType the token type to query + * @return {Promise} a promise that resolves to an object representing the state of the account * for this token */ getAccountStatus(address: string, tokenType: string) { @@ -461,9 +445,9 @@ export class BlockstackNetwork { /** * Get a page of an account's transaction history. - * @param address the account's address - * @param page the page number. Page 0 is the most recent transactions - * @return a promise that resolves to an Array of Objects, where each Object encodes + * @param {String} address the account's address + * @param {number} page the page number. Page 0 is the most recent transactions + * @return {Promise} a promise that resolves to an Array of Objects, where each Object encodes * states of the account at various block heights (e.g. prior balances, txids, etc) */ getAccountHistoryPage(address: string, @@ -497,9 +481,9 @@ export class BlockstackNetwork { * Get the state(s) of an account at a particular block height. This includes the state of the * account beginning with this block's transactions, as well as all of the states the account * passed through when this block was processed (if any). - * @param address the account's address - * @param blockHeight the block to query - * @return a promise that resolves to an Array of Objects, where each Object encodes + * @param {String} address the account's address + * @param {Integer} blockHeight the block to query + * @return {Promise} a promise that resolves to an Array of Objects, where each Object encodes * states of the account at this block. */ getAccountAt(address: string, blockHeight: number): Promise { @@ -530,11 +514,11 @@ export class BlockstackNetwork { /** * Get the set of token types that this account owns - * @param address the account's address - * @return a promise that resolves to an Array of Strings, where each item encodes the + * @param {String} address the account's address + * @return {Promise} a promise that resolves to an Array of Strings, where each item encodes the * type of token this account holds (excluding the underlying blockchain's tokens) */ - getAccountTokens(address: string): Promise { + getAccountTokens(address: string): Promise<{tokens: string[]}> { return fetchPrivate(`${this.blockstackAPIUrl}/v1/accounts/${address}/tokens`) .then((resp) => { if (resp.status === 404) { @@ -556,9 +540,9 @@ export class BlockstackNetwork { /** * Get the number of tokens owned by an account. If the account does not exist or has no * tokens of this type, then 0 will be returned. - * @param address the account's address - * @param tokenType the type of token to query. - * @return a promise that resolves to a BigInteger that encodes the number of tokens + * @param {String} address the account's address + * @param {String} tokenType the type of token to query. + * @return {Promise} a promise that resolves to a BigInteger that encodes the number of tokens * held by this account. */ getAccountBalance(address: string, tokenType: string): Promise { @@ -588,9 +572,9 @@ export class BlockstackNetwork { /** * Performs a POST request to the given URL - * @param endpoint the name of - * @param body [description] - * @return Returns a `Promise` that resolves to the object requested. + * @param {String} endpoint the name of + * @param {String} body [description] + * @return {Promise} Returns a `Promise` that resolves to the object requested. * In the event of an error, it rejects with: * * a `RemoteServiceError` if there is a problem * with the transaction broadcast service @@ -623,24 +607,24 @@ export class BlockstackNetwork { } /** - * Broadcasts a signed bitcoin transaction to the network optionally waiting to broadcast the - * transaction until a second transaction has a certain number of confirmations. - * - * @param transaction the hex-encoded transaction to broadcast - * @param transactionToWatch the hex transaction id of the transaction to watch for - * the specified number of confirmations before broadcasting the `transaction` - * @param confirmations the number of confirmations `transactionToWatch` must have - * before broadcasting `transaction`. - * @return Returns a Promise that resolves to an object with a - * `transaction_hash` key containing the transaction hash of the broadcasted transaction. - * - * In the event of an error, it rejects with: - * * a `RemoteServiceError` if there is a problem - * with the transaction broadcast service - * * `MissingParameterError` if you call the function without a required - * parameter - * @private - */ + * Broadcasts a signed bitcoin transaction to the network optionally waiting to broadcast the + * transaction until a second transaction has a certain number of confirmations. + * + * @param {string} transaction the hex-encoded transaction to broadcast + * @param {string} transactionToWatch the hex transaction id of the transaction to watch for + * the specified number of confirmations before broadcasting the `transaction` + * @param {number} confirmations the number of confirmations `transactionToWatch` must have + * before broadcasting `transaction`. + * @return {Promise} Returns a Promise that resolves to an object with a + * `transaction_hash` key containing the transaction hash of the broadcasted transaction. + * + * In the event of an error, it rejects with: + * * a `RemoteServiceError` if there is a problem + * with the transaction broadcast service + * * `MissingParameterError` if you call the function without a required + * parameter + * @private + */ broadcastTransaction( transaction: string, transactionToWatch: string = null, @@ -683,10 +667,10 @@ export class BlockstackNetwork { /** * Broadcasts a zone file to the Atlas network via the transaction broadcast service. * - * @param zoneFile the zone file to be broadcast to the Atlas network - * @param transactionToWatch the hex transaction id of the transaction + * @param {String} zoneFile the zone file to be broadcast to the Atlas network + * @param {String} transactionToWatch the hex transaction id of the transaction * to watch for confirmation before broadcasting the zone file to the Atlas network - * @return Returns a Promise that resolves to an object with a + * @return {Promise} Returns a Promise that resolves to an object with a * `transaction_hash` key containing the transaction hash of the broadcasted transaction. * * In the event of an error, it rejects with: @@ -766,12 +750,12 @@ export class BlockstackNetwork { * * broadcasts the zone file to the Atlas network after the register transaction * has an appropriate number of confirmations * - * @param preorderTransaction the hex-encoded, signed preorder transaction generated + * @param {String} preorderTransaction the hex-encoded, signed preorder transaction generated * using the `makePreorder` function - * @param registerTransaction the hex-encoded, signed register transaction generated + * @param {String} registerTransaction the hex-encoded, signed register transaction generated * using the `makeRegister` function - * @param zoneFile the zone file to be broadcast to the Atlas network - * @return Returns a Promise that resolves to an object with a + * @param {String} zoneFile the zone file to be broadcast to the Atlas network + * @return {Promise} Returns a Promise that resolves to an object with a * `transaction_hash` key containing the transaction hash of the broadcasted transaction. * * In the event of an error, it rejects with: @@ -841,7 +825,7 @@ export class BlockstackNetwork { /** * @ignore */ - getUTXOs(address: string): Promise { + getUTXOs(address: string): Promise> { return this.getNetworkedUTXOs(address) .then((networkedUTXOs) => { let returnSet = networkedUTXOs.concat() @@ -870,15 +854,15 @@ export class BlockstackNetwork { * This will modify the network's utxo set to include UTXOs * from the given transaction and exclude UTXOs *spent* in * that transaction - * @param txHex - the hex-encoded transaction to use - * @return no return value, this modifies the UTXO config state + * @param {String} txHex - the hex-encoded transaction to use + * @return {void} no return value, this modifies the UTXO config state * @private * @ignore */ modifyUTXOSetFrom(txHex: string) { const tx = Transaction.fromHex(txHex) - const excludeSet: UTXO[] = this.excludeUtxoSet.concat() + const excludeSet: Array = this.excludeUtxoSet.concat() tx.ins.forEach((utxoUsed) => { const reverseHash = Buffer.from(utxoUsed.hash) @@ -923,24 +907,21 @@ export class BlockstackNetwork { }) } - /** - * @ignore - */ resetUTXOs(address: string) { delete this.includeUtxoMap[address] this.excludeUtxoSet = [] } /** - * @ignore - */ + * @ignore + */ getConsensusHash() { return fetchPrivate(`${this.blockstackAPIUrl}/v1/blockchains/bitcoin/consensus`) .then(resp => resp.json()) .then(x => x.consensus_hash) } - getTransactionInfo(txHash: string): Promise { + getTransactionInfo(txHash: string): Promise<{block_height: number}> { return this.btc.getTransactionInfo(txHash) } @@ -951,7 +932,7 @@ export class BlockstackNetwork { return this.btc.getBlockHeight() } - getNetworkedUTXOs(address: string): Promise { + getNetworkedUTXOs(address: string): Promise> { return this.btc.getNetworkedUTXOs(address) } } @@ -1022,7 +1003,7 @@ export class BitcoindAPI extends BitcoinNetwork { .then(respObj => respObj.result) } - getTransactionInfo(txHash: string): Promise { + getTransactionInfo(txHash: string): Promise<{block_height: number}> { const jsonRPC = { jsonrpc: '1.0', method: 'gettransaction', @@ -1063,7 +1044,7 @@ export class BitcoindAPI extends BitcoinNetwork { }) } - getNetworkedUTXOs(address: string): Promise { + getNetworkedUTXOs(address: string): Promise> { const jsonRPCImport = { jsonrpc: '1.0', method: 'importaddress', @@ -1134,7 +1115,7 @@ export class InsightClient extends BitcoinNetwork { .then(status => status.blocks) } - getTransactionInfo(txHash: string): Promise { + getTransactionInfo(txHash: string): Promise<{block_height: number}> { return fetchPrivate(`${this.apiUrl}/tx/${txHash}`) .then(resp => resp.json()) .then((transactionInfo) => { @@ -1147,7 +1128,7 @@ export class InsightClient extends BitcoinNetwork { .then(blockInfo => ({ block_height: blockInfo.height })) } - getNetworkedUTXOs(address: string): Promise { + getNetworkedUTXOs(address: string): Promise> { return fetchPrivate(`${this.apiUrl}/addr/${address}/utxo`) .then(resp => resp.json()) .then(utxos => utxos.map( @@ -1179,7 +1160,7 @@ export class BlockchainInfoApi extends BitcoinNetwork { .then(blockObj => blockObj.height) } - getNetworkedUTXOs(address: string): Promise { + getNetworkedUTXOs(address: string): Promise> { return fetchPrivate(`${this.utxoProviderUrl}/unspent?format=json&active=${address}&cors=true`) .then((resp) => { if (resp.status === 500) { @@ -1205,7 +1186,7 @@ export class BlockchainInfoApi extends BitcoinNetwork { )) } - getTransactionInfo(txHash: string): Promise { + getTransactionInfo(txHash: string): Promise<{block_height: number}> { return fetchPrivate(`${this.utxoProviderUrl}/rawtx/${txHash}?cors=true`) .then((resp) => { if (resp.status === 200) { @@ -1256,9 +1237,9 @@ const LOCAL_REGTEST = new LocalRegtest( ) /** -* Instance of [[BlockstackNetwork]] set to the default endpoints. +* @ignore */ -export const MAINNET_DEFAULT = new BlockstackNetwork( +const MAINNET_DEFAULT = new BlockstackNetwork( 'https://core.blockstack.org', 'https://broadcast.blockstack.org', new BlockchainInfoApi() @@ -1266,10 +1247,9 @@ export const MAINNET_DEFAULT = new BlockstackNetwork( /** * Get WHOIS-like information for a name, including the address that owns it, - * the block at which it expires, and the zone file anchored to it (if available). - * This is intended for use in third-party wallets or in DApps that register names. - * @param fullyQualifiedName the name to query. Can be on-chain of off-chain. - * @return a promise that resolves to the WHOIS-like information + * the block at which it expires, and the zone file anchored to it (if available). + * @param {String} fullyQualifiedName the name to query. Can be on-chain of off-chain. + * @return {Promise} a promise that resolves to the WHOIS-like information */ export function getNameInfo(fullyQualifiedName: string) { return config.network.getNameInfo(fullyQualifiedName) diff --git a/tsconfig.typedoc.json b/tsconfig.typedoc.json index 6fd252e3b..66e81c26b 100644 --- a/tsconfig.typedoc.json +++ b/tsconfig.typedoc.json @@ -18,7 +18,6 @@ "excludePrivate": true, "excludeProtected": true, "excludeExternals": true, - "excludeNotExported": false, "includes" : "mdincludes", "includeDeclarations": false, "gitRevision": "master",