Skip to content
This repository was archived by the owner on Aug 24, 2021. It is now read-only.

feat: add ts types #104

Merged
merged 6 commits into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
name: ci
on: [push, pull_request]
on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
check:
Expand All @@ -8,6 +14,7 @@ jobs:
- uses: actions/checkout@v2
- run: yarn
- run: yarn lint
- uses: gozala/[email protected]
- run: yarn aegir dep-check -- -i aegir
- uses: ipfs/aegir/actions/bundle-size@master
name: size
Expand Down
19 changes: 4 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs)
[![Coverage Status](https://coveralls.io/repos/github/multiformats/js-multihash/badge.svg?branch=master)](https://coveralls.io/github/multiformats/js-multihash?branch=master)
[![Travis CI](https://img.shields.io/travis/multiformats/js-multihash.svg?style=flat-square&branch=master)](https://travis-ci.org/multiformats/js-multihash)
[![Dependency Status](https://david-dm.org/multiformats/js-multihash.svg?style=flat-square)](https://david-dm.org/multiformats/js-multihash)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
[![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
[![codecov](https://img.shields.io/codecov/c/github/multiformats/js-multihash.svg?style=flat-square)](https://codecov.io/gh/multiformats/js-multihash)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/multiformats/js-multihash/ci?label=ci&style=flat-square)](https://github.com/multiformats/js-multihash/actions?query=branch%3Amaster+workflow%3Aci+)

> multihash implementation in node.js

Expand Down Expand Up @@ -36,20 +33,12 @@ so give those a look as well.
### Using npm

```bash
> npm install multihashes # node the name of the module is multihashes
> npm install multihashes # NOTE: The name of the module is multihashes!
```

Once the install is complete, you can require it as a normal dependency

```js
const multihashes = require('multihashes')
```

You can require it and use with your favourite bundler to bundle this package in a browser compatible code.

### Using a `<script>` tag

Loading this module through a script tag will make the ```Multihashes``` obj available in the global namespace.
Loading this module through a script tag will make the `Multihashes` obj available in the global namespace.

```html
<script src="https://unpkg.com/multihashes/dist/index.min.js"></script>
Expand Down
20 changes: 16 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,27 @@
"update-constants": "node update-constants.js"
},
"main": "src/index.js",
"types": "dist/src/index.d.ts",
"typesVersions": {
"*": {
"src/*": [
"dist/src/*",
"dist/src/*/index"
]
}
},
"repository": "github:multiformats/js-multihash",
"dependencies": {
"multibase": "^3.0.0",
"multibase": "^3.1.0",
"uint8arrays": "^1.0.0",
"varint": "^5.0.0"
"varint": "^6.0.0"
},
"devDependencies": {
"aegir": "^25.0.0",
"ipfs-utils": "^2.3.1"
"aegir": "^29.0.1",
"ipfs-utils": "^5.0.0"
},
"eslintConfig": {
"extends": "ipfs"
},
"contributors": [
"David Dias <[email protected]>",
Expand Down
15 changes: 15 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
/* eslint quote-props: off */
'use strict'

/**
* Names for all available hashes
*
* @typedef { "identity" | "sha1" | "sha2-256" | "sha2-512" | "sha3-512" | "sha3-384" | "sha3-256" | "sha3-224" | "shake-128" | "shake-256" | "keccak-224" | "keccak-256" | "keccak-384" | "keccak-512" | "blake3" | "murmur3-128" | "murmur3-32" | "dbl-sha2-256" | "md4" | "md5" | "bmt" | "sha2-256-trunc254-padded" | "ripemd-128" | "ripemd-160" | "ripemd-256" | "ripemd-320" | "x11" | "kangarootwelve" | "sm3-256" | "blake2b-8" | "blake2b-16" | "blake2b-24" | "blake2b-32" | "blake2b-40" | "blake2b-48" | "blake2b-56" | "blake2b-64" | "blake2b-72" | "blake2b-80" | "blake2b-88" | "blake2b-96" | "blake2b-104" | "blake2b-112" | "blake2b-120" | "blake2b-128" | "blake2b-136" | "blake2b-144" | "blake2b-152" | "blake2b-160" | "blake2b-168" | "blake2b-176" | "blake2b-184" | "blake2b-192" | "blake2b-200" | "blake2b-208" | "blake2b-216" | "blake2b-224" | "blake2b-232" | "blake2b-240" | "blake2b-248" | "blake2b-256" | "blake2b-264" | "blake2b-272" | "blake2b-280" | "blake2b-288" | "blake2b-296" | "blake2b-304" | "blake2b-312" | "blake2b-320" | "blake2b-328" | "blake2b-336" | "blake2b-344" | "blake2b-352" | "blake2b-360" | "blake2b-368" | "blake2b-376" | "blake2b-384" | "blake2b-392" | "blake2b-400" | "blake2b-408" | "blake2b-416" | "blake2b-424" | "blake2b-432" | "blake2b-440" | "blake2b-448" | "blake2b-456" | "blake2b-464" | "blake2b-472" | "blake2b-480" | "blake2b-488" | "blake2b-496" | "blake2b-504" | "blake2b-512" | "blake2s-8" | "blake2s-16" | "blake2s-24" | "blake2s-32" | "blake2s-40" | "blake2s-48" | "blake2s-56" | "blake2s-64" | "blake2s-72" | "blake2s-80" | "blake2s-88" | "blake2s-96" | "blake2s-104" | "blake2s-112" | "blake2s-120" | "blake2s-128" | "blake2s-136" | "blake2s-144" | "blake2s-152" | "blake2s-160" | "blake2s-168" | "blake2s-176" | "blake2s-184" | "blake2s-192" | "blake2s-200" | "blake2s-208" | "blake2s-216" | "blake2s-224" | "blake2s-232" | "blake2s-240" | "blake2s-248" | "blake2s-256" | "skein256-8" | "skein256-16" | "skein256-24" | "skein256-32" | "skein256-40" | "skein256-48" | "skein256-56" | "skein256-64" | "skein256-72" | "skein256-80" | "skein256-88" | "skein256-96" | "skein256-104" | "skein256-112" | "skein256-120" | "skein256-128" | "skein256-136" | "skein256-144" | "skein256-152" | "skein256-160" | "skein256-168" | "skein256-176" | "skein256-184" | "skein256-192" | "skein256-200" | "skein256-208" | "skein256-216" | "skein256-224" | "skein256-232" | "skein256-240" | "skein256-248" | "skein256-256" | "skein512-8" | "skein512-16" | "skein512-24" | "skein512-32" | "skein512-40" | "skein512-48" | "skein512-56" | "skein512-64" | "skein512-72" | "skein512-80" | "skein512-88" | "skein512-96" | "skein512-104" | "skein512-112" | "skein512-120" | "skein512-128" | "skein512-136" | "skein512-144" | "skein512-152" | "skein512-160" | "skein512-168" | "skein512-176" | "skein512-184" | "skein512-192" | "skein512-200" | "skein512-208" | "skein512-216" | "skein512-224" | "skein512-232" | "skein512-240" | "skein512-248" | "skein512-256" | "skein512-264" | "skein512-272" | "skein512-280" | "skein512-288" | "skein512-296" | "skein512-304" | "skein512-312" | "skein512-320" | "skein512-328" | "skein512-336" | "skein512-344" | "skein512-352" | "skein512-360" | "skein512-368" | "skein512-376" | "skein512-384" | "skein512-392" | "skein512-400" | "skein512-408" | "skein512-416" | "skein512-424" | "skein512-432" | "skein512-440" | "skein512-448" | "skein512-456" | "skein512-464" | "skein512-472" | "skein512-480" | "skein512-488" | "skein512-496" | "skein512-504" | "skein512-512" | "skein1024-8" | "skein1024-16" | "skein1024-24" | "skein1024-32" | "skein1024-40" | "skein1024-48" | "skein1024-56" | "skein1024-64" | "skein1024-72" | "skein1024-80" | "skein1024-88" | "skein1024-96" | "skein1024-104" | "skein1024-112" | "skein1024-120" | "skein1024-128" | "skein1024-136" | "skein1024-144" | "skein1024-152" | "skein1024-160" | "skein1024-168" | "skein1024-176" | "skein1024-184" | "skein1024-192" | "skein1024-200" | "skein1024-208" | "skein1024-216" | "skein1024-224" | "skein1024-232" | "skein1024-240" | "skein1024-248" | "skein1024-256" | "skein1024-264" | "skein1024-272" | "skein1024-280" | "skein1024-288" | "skein1024-296" | "skein1024-304" | "skein1024-312" | "skein1024-320" | "skein1024-328" | "skein1024-336" | "skein1024-344" | "skein1024-352" | "skein1024-360" | "skein1024-368" | "skein1024-376" | "skein1024-384" | "skein1024-392" | "skein1024-400" | "skein1024-408" | "skein1024-416" | "skein1024-424" | "skein1024-432" | "skein1024-440" | "skein1024-448" | "skein1024-456" | "skein1024-464" | "skein1024-472" | "skein1024-480" | "skein1024-488" | "skein1024-496" | "skein1024-504" | "skein1024-512" | "skein1024-520" | "skein1024-528" | "skein1024-536" | "skein1024-544" | "skein1024-552" | "skein1024-560" | "skein1024-568" | "skein1024-576" | "skein1024-584" | "skein1024-592" | "skein1024-600" | "skein1024-608" | "skein1024-616" | "skein1024-624" | "skein1024-632" | "skein1024-640" | "skein1024-648" | "skein1024-656" | "skein1024-664" | "skein1024-672" | "skein1024-680" | "skein1024-688" | "skein1024-696" | "skein1024-704" | "skein1024-712" | "skein1024-720" | "skein1024-728" | "skein1024-736" | "skein1024-744" | "skein1024-752" | "skein1024-760" | "skein1024-768" | "skein1024-776" | "skein1024-784" | "skein1024-792" | "skein1024-800" | "skein1024-808" | "skein1024-816" | "skein1024-824" | "skein1024-832" | "skein1024-840" | "skein1024-848" | "skein1024-856" | "skein1024-864" | "skein1024-872" | "skein1024-880" | "skein1024-888" | "skein1024-896" | "skein1024-904" | "skein1024-912" | "skein1024-920" | "skein1024-928" | "skein1024-936" | "skein1024-944" | "skein1024-952" | "skein1024-960" | "skein1024-968" | "skein1024-976" | "skein1024-984" | "skein1024-992" | "skein1024-1000" | "skein1024-1008" | "skein1024-1016" | "skein1024-1024" | "poseidon-bls12_381-a2-fc1" | "poseidon-bls12_381-a2-fc1-sc" } HashName
*/
/**
* Codes for all available hashes
*
* @typedef { 0x00 | 0x11 | 0x12 | 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1a | 0x1b | 0x1c | 0x1d | 0x1e | 0x22 | 0x23 | 0x56 | 0xd4 | 0xd5 | 0xd6 | 0x1012 | 0x1052 | 0x1053 | 0x1054 | 0x1055 | 0x1100 | 0x1d01 | 0x534d | 0xb201 | 0xb202 | 0xb203 | 0xb204 | 0xb205 | 0xb206 | 0xb207 | 0xb208 | 0xb209 | 0xb20a | 0xb20b | 0xb20c | 0xb20d | 0xb20e | 0xb20f | 0xb210 | 0xb211 | 0xb212 | 0xb213 | 0xb214 | 0xb215 | 0xb216 | 0xb217 | 0xb218 | 0xb219 | 0xb21a | 0xb21b | 0xb21c | 0xb21d | 0xb21e | 0xb21f | 0xb220 | 0xb221 | 0xb222 | 0xb223 | 0xb224 | 0xb225 | 0xb226 | 0xb227 | 0xb228 | 0xb229 | 0xb22a | 0xb22b | 0xb22c | 0xb22d | 0xb22e | 0xb22f | 0xb230 | 0xb231 | 0xb232 | 0xb233 | 0xb234 | 0xb235 | 0xb236 | 0xb237 | 0xb238 | 0xb239 | 0xb23a | 0xb23b | 0xb23c | 0xb23d | 0xb23e | 0xb23f | 0xb240 | 0xb241 | 0xb242 | 0xb243 | 0xb244 | 0xb245 | 0xb246 | 0xb247 | 0xb248 | 0xb249 | 0xb24a | 0xb24b | 0xb24c | 0xb24d | 0xb24e | 0xb24f | 0xb250 | 0xb251 | 0xb252 | 0xb253 | 0xb254 | 0xb255 | 0xb256 | 0xb257 | 0xb258 | 0xb259 | 0xb25a | 0xb25b | 0xb25c | 0xb25d | 0xb25e | 0xb25f | 0xb260 | 0xb301 | 0xb302 | 0xb303 | 0xb304 | 0xb305 | 0xb306 | 0xb307 | 0xb308 | 0xb309 | 0xb30a | 0xb30b | 0xb30c | 0xb30d | 0xb30e | 0xb30f | 0xb310 | 0xb311 | 0xb312 | 0xb313 | 0xb314 | 0xb315 | 0xb316 | 0xb317 | 0xb318 | 0xb319 | 0xb31a | 0xb31b | 0xb31c | 0xb31d | 0xb31e | 0xb31f | 0xb320 | 0xb321 | 0xb322 | 0xb323 | 0xb324 | 0xb325 | 0xb326 | 0xb327 | 0xb328 | 0xb329 | 0xb32a | 0xb32b | 0xb32c | 0xb32d | 0xb32e | 0xb32f | 0xb330 | 0xb331 | 0xb332 | 0xb333 | 0xb334 | 0xb335 | 0xb336 | 0xb337 | 0xb338 | 0xb339 | 0xb33a | 0xb33b | 0xb33c | 0xb33d | 0xb33e | 0xb33f | 0xb340 | 0xb341 | 0xb342 | 0xb343 | 0xb344 | 0xb345 | 0xb346 | 0xb347 | 0xb348 | 0xb349 | 0xb34a | 0xb34b | 0xb34c | 0xb34d | 0xb34e | 0xb34f | 0xb350 | 0xb351 | 0xb352 | 0xb353 | 0xb354 | 0xb355 | 0xb356 | 0xb357 | 0xb358 | 0xb359 | 0xb35a | 0xb35b | 0xb35c | 0xb35d | 0xb35e | 0xb35f | 0xb360 | 0xb361 | 0xb362 | 0xb363 | 0xb364 | 0xb365 | 0xb366 | 0xb367 | 0xb368 | 0xb369 | 0xb36a | 0xb36b | 0xb36c | 0xb36d | 0xb36e | 0xb36f | 0xb370 | 0xb371 | 0xb372 | 0xb373 | 0xb374 | 0xb375 | 0xb376 | 0xb377 | 0xb378 | 0xb379 | 0xb37a | 0xb37b | 0xb37c | 0xb37d | 0xb37e | 0xb37f | 0xb380 | 0xb381 | 0xb382 | 0xb383 | 0xb384 | 0xb385 | 0xb386 | 0xb387 | 0xb388 | 0xb389 | 0xb38a | 0xb38b | 0xb38c | 0xb38d | 0xb38e | 0xb38f | 0xb390 | 0xb391 | 0xb392 | 0xb393 | 0xb394 | 0xb395 | 0xb396 | 0xb397 | 0xb398 | 0xb399 | 0xb39a | 0xb39b | 0xb39c | 0xb39d | 0xb39e | 0xb39f | 0xb3a0 | 0xb3a1 | 0xb3a2 | 0xb3a3 | 0xb3a4 | 0xb3a5 | 0xb3a6 | 0xb3a7 | 0xb3a8 | 0xb3a9 | 0xb3aa | 0xb3ab | 0xb3ac | 0xb3ad | 0xb3ae | 0xb3af | 0xb3b0 | 0xb3b1 | 0xb3b2 | 0xb3b3 | 0xb3b4 | 0xb3b5 | 0xb3b6 | 0xb3b7 | 0xb3b8 | 0xb3b9 | 0xb3ba | 0xb3bb | 0xb3bc | 0xb3bd | 0xb3be | 0xb3bf | 0xb3c0 | 0xb3c1 | 0xb3c2 | 0xb3c3 | 0xb3c4 | 0xb3c5 | 0xb3c6 | 0xb3c7 | 0xb3c8 | 0xb3c9 | 0xb3ca | 0xb3cb | 0xb3cc | 0xb3cd | 0xb3ce | 0xb3cf | 0xb3d0 | 0xb3d1 | 0xb3d2 | 0xb3d3 | 0xb3d4 | 0xb3d5 | 0xb3d6 | 0xb3d7 | 0xb3d8 | 0xb3d9 | 0xb3da | 0xb3db | 0xb3dc | 0xb3dd | 0xb3de | 0xb3df | 0xb3e0 | 0xb401 | 0xb402 } HashCode
*/

/**
* @type { Object<HashName,HashCode> }
*/
const names = Object.freeze({
'identity': 0x00,
'sha1': 0x11,
Expand Down Expand Up @@ -29,6 +43,7 @@ const names = Object.freeze({
'ripemd-256': 0x1054,
'ripemd-320': 0x1055,
'x11': 0x1100,
'kangarootwelve': 0x1d01,
'sm3-256': 0x534d,
'blake2b-8': 0xb201,
'blake2b-16': 0xb202,
Expand Down
72 changes: 45 additions & 27 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-check
/* eslint-disable guard-for-in */
/**
* Multihash implementation in JavaScript.
*
Expand All @@ -14,21 +12,20 @@ const uint8ArrayToString = require('uint8arrays/to-string')
const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayConcat = require('uint8arrays/concat')

const codes = {}
const codes = /** @type {import('./types').CodeNameMap} */({})

// eslint-disable-next-line guard-for-in
for (const key in names) {
codes[names[key]] = key
}
exports.names = names
exports.codes = Object.freeze(codes)

/**
* Convert the given multihash to a hex encoded string.
*
* @param {Uint8Array} hash
* @returns {string}
*/
exports.toHexString = function toHexString (hash) {
function toHexString (hash) {
if (!(hash instanceof Uint8Array)) {
throw new Error('must be passed a Uint8Array')
}
Expand All @@ -42,7 +39,7 @@ exports.toHexString = function toHexString (hash) {
* @param {string} hash
* @returns {Uint8Array}
*/
exports.fromHexString = function fromHexString (hash) {
function fromHexString (hash) {
return uint8ArrayFromString(hash, 'base16')
}

Expand All @@ -52,7 +49,7 @@ exports.fromHexString = function fromHexString (hash) {
* @param {Uint8Array} hash
* @returns {string}
*/
exports.toB58String = function toB58String (hash) {
function toB58String (hash) {
if (!(hash instanceof Uint8Array)) {
throw new Error('must be passed a Uint8Array')
}
Expand All @@ -66,7 +63,7 @@ exports.toB58String = function toB58String (hash) {
* @param {string|Uint8Array} hash
* @returns {Uint8Array}
*/
exports.fromB58String = function fromB58String (hash) {
function fromB58String (hash) {
const encoded = hash instanceof Uint8Array
? uint8ArrayToString(hash)
: hash
Expand All @@ -78,9 +75,9 @@ exports.fromB58String = function fromB58String (hash) {
* Decode a hash from the given multihash.
*
* @param {Uint8Array} bytes
* @returns {{code: number, name: string, length: number, digest: Uint8Array}} result
* @returns {{code: HashCode, name: HashName, length: number, digest: Uint8Array}} result
*/
exports.decode = function decode (bytes) {
function decode (bytes) {
if (!(bytes instanceof Uint8Array)) {
throw new Error('multihash must be a Uint8Array')
}
Expand All @@ -90,7 +87,7 @@ exports.decode = function decode (bytes) {
}

const code = varint.decode(bytes)
if (!exports.isValidCode(code)) {
if (!isValidCode(code)) {
throw new Error(`multihash unknown function code: 0x${code.toString(16)}`)
}
bytes = bytes.slice(varint.decode.bytes)
Expand All @@ -114,22 +111,22 @@ exports.decode = function decode (bytes) {
}

/**
* Encode a hash digest along with the specified function code.
* Encode a hash digest along with the specified function code.
*
* > **Note:** the length is derived from the length of the digest itself.
*
* @param {Uint8Array} digest
* @param {string|number} code
* @param {HashName | HashCode} code
* @param {number} [length]
* @returns {Uint8Array}
*/
exports.encode = function encode (digest, code, length) {
function encode (digest, code, length) {
if (!digest || code === undefined) {
throw new Error('multihash encode requires at least two args: digest, code')
}

// ensure it's a hashfunction code.
const hashfn = exports.coerceCode(code)
const hashfn = coerceCode(code)

if (!(digest instanceof Uint8Array)) {
throw new Error('digest should be a Uint8Array')
Expand All @@ -151,10 +148,11 @@ exports.encode = function encode (digest, code, length) {
/**
* Converts a hash function name into the matching code.
* If passed a number it will return the number if it's a valid code.
* @param {string|number} name
*
* @param {HashName | number} name
* @returns {number}
*/
exports.coerceCode = function coerceCode (name) {
function coerceCode (name) {
let code = name

if (typeof name === 'string') {
Expand All @@ -168,31 +166,31 @@ exports.coerceCode = function coerceCode (name) {
throw new Error(`Hash function code should be a number. Got: ${code}`)
}

if (codes[code] === undefined && !exports.isAppCode(code)) {
if (codes[code] === undefined && !isAppCode(code)) {
throw new Error(`Unrecognized function code: ${code}`)
}

return code
}

/**
* Checks wether a code is part of the app range
* Checks if a code is part of the app range
*
* @param {number} code
* @returns {boolean}
*/
exports.isAppCode = function appCode (code) {
function isAppCode (code) {
return code > 0 && code < 0x10
}

/**
* Checks whether a multihash code is valid.
*
* @param {number} code
* @param {HashCode} code
* @returns {boolean}
*/
exports.isValidCode = function validCode (code) {
if (exports.isAppCode(code)) {
function isValidCode (code) {
if (isAppCode(code)) {
return true
}

Expand All @@ -211,9 +209,8 @@ exports.isValidCode = function validCode (code) {
* @throws {Error}
*/
function validate (multihash) {
exports.decode(multihash) // throws if bad.
decode(multihash) // throws if bad.
}
exports.validate = validate

/**
* Returns a prefix from a valid multihash. Throws an error if it is not valid.
Expand All @@ -222,8 +219,29 @@ exports.validate = validate
* @returns {Uint8Array}
* @throws {Error}
*/
exports.prefix = function prefix (multihash) {
function prefix (multihash) {
validate(multihash)

return multihash.subarray(0, 2)
}

module.exports = {
names,
codes: Object.freeze(codes),
toHexString,
fromHexString,
toB58String,
fromB58String,
decode,
encode,
coerceCode,
isAppCode,
validate,
prefix,
isValidCode
}

/**
* @typedef { import("./constants").HashCode } HashCode
* @typedef { import("./constants").HashName } HashName
*/
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { HashCode, HashName } from './constants.js'

export type CodeNameMap = Record<HashCode, HashName>
export type NameCodeMap = Record<HashName, HashCode>
Loading