From f32405e8e85aaca5965acfddd41feed1925fa39b Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 09:56:41 -0800 Subject: [PATCH 1/9] feat: create w3name docs --- src/pages/docs/how-to/w3name.mdx | 155 +++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/pages/docs/how-to/w3name.mdx diff --git a/src/pages/docs/how-to/w3name.mdx b/src/pages/docs/how-to/w3name.mdx new file mode 100644 index 0000000..3e05161 --- /dev/null +++ b/src/pages/docs/how-to/w3name.mdx @@ -0,0 +1,155 @@ +# Update your data with w3name + +All the data you [store on web3.storage](upload) is [content-addressed](../concepts/content-addressing), which means that you always get location-independent, cryptographically verifiable links to your content. + +Content addressing is a very powerful tool, but because the address is directly derived from the content, it is limited by definition to content that already exists, and any changes to the content will result in an entirely new address. + +When you need to refer to something that might change over time, or that may not exist yet at all, content addressing alone isn't enough. You also need a way to update things as they change without breaking all of your links and references. + +[w3name](https://github.com/web3-storage/w3name) is a service that provides secure, stable identifiers for data that changes over time (also known as "mutable" data). It uses the [IPNS](https://docs.ipfs.tech/concepts/ipns/) protocol to seamlessly interoperate with the IPFS network, so the links you create with w3name can be used with any IPFS client software or HTTP gateway. + +All records created and updated using w3name are signed locally with each user's private publishing key. This means that the w3name service never sees your keys, and it also doesn't require any authentication to use - no account or API keys required! + +In this guide, we'll discover how to use the JavaScript `w3name` package to create and manage name records for data stored with web3.storage. + + + IPNS is a secure, local-first protocol, but does not always resolve performantly when needing to fetch the absolute latest update to a name (which is a requirement for most application use-cases) from the public IPFS network (e.g., over a local Kubo instance or public gateway). You can read more about this [here.](https://docs.ipfs.tech/concepts/ipns/#tradeoffs-between-consistency-vs-availability). As a result, w3name's recommended usage for use cases where performance and consistency are both important is [via an endpoint hosted by web3.storage](#getting-the-latest-revision). We plan on offering a new naming protocol at some point that can be used for application use cases without relying on any centralized infrastructure. + + +# What's in a name? + +w3name is similar to the Domain Name System (DNS), in that it allows you to query for an identifier and resolve the latest value. Unlike DNS, however, you cannot choose your own identifiers, and the "names" produced by IPNS and w3name are not human-readable, like `web3.storage` or `ipfs.io`. + +The "names" in IPNS and w3name are unique identifiers, and each one is a string representation of the public half of a cryptographic key-pair. + +Each "name" maps to a "record", which contains: +- The CID of the IPFS content that the name is pointing to. +- A sequence number and validity date. +- A verification signature, created using the private key, providing proof that this record was generated by the key holder. + +Because the verification key is embedded in the name, all names created with w3name are "self-certifying," meaning that you can validate any record published to that name without needing any other authority or "source of truth" than the name itself. + +# Getting started + +The easiest way to use the [w3name](https://www.npmjs.com/package/w3name) service is with the w3name JavaScript library, which provides methods for creating, signing, publishing and resolving records. + +## Install client library + +The [w3name npm package](https://www.npmjs.com/package/w3name) provides a JavaScript / TypeScript API for creating and managing IPNS name records. + +Install the library into your project. + +```sh +npm install w3name +``` + +## Creating a new name + +You can create a new IPNS name with the Name.create function: + +```javascript +const name = await Name.create(); +``` + +This example above uses the [`await` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await), because `Name.create()` returns a `Promise`. To use `await`, the code must be placed inside an [`async` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). Alternatively, you can resolve the promise using `.then()`, for example: + +```javascript +Name.create().then(name => { + // do something with name here. +}); +``` + +You can see the name as a string by calling .toString() on it: + +```javascript +console.log('created new name: ', name.toString()); +// will print something similar to: +// created new name: k51qzi5uqu5di9agapykyjh3tqrf7i14a7fjq46oo0f6dxiimj62knq13059lt +``` + + +So far, the signing key for your new name only exists in memory. To save it for publishing updates, see [Saving and loading keys](#saving-and-loading-keys) below. + + +# Publishing the first revision + +We created a name, but so far there's no value associated with it. + +To publish a value, we need to create a "revision." A revision contains a value that can be published to w3name, along with some IPNS metadata. All revisions have a sequence number that gets incremented each time the name is updated with a new value. + +To create the initial revision for a name, use the `Name.v0` function: + +```javascript +// value is an IPFS path to the content we want to publish +const value = '/ipfs/bafkreiem4twkqzsq2aj4shbycd4yvoj2cx72vezicletlhi7dijjciqpui'; +// since we don't have a previous revision, we use Name.v0 to create the initial revision +const revision = await Name.v0(name, value); +``` + +We now have a `revision` object that's ready to publish, but so far it's only in memory on our local machine. To publish the value to the network, use `Name.publish`: + +```javascript +await Name.publish(revision, name.key); +``` + +# Publishing an updated revision + +Each revision contains a sequence number, which must be incremented when publishing a new revision. Once you've published the initial revision, you can use the `Name.increment` function to create a new revision based on the previously published one. + +For example, if our initial revision is stored in a variable called `revision`, we can create a new revision `nextRevision` using `Name.increment`: + +```javascript +const nextValue = '/ipfs/bafybeiauyddeo2axgargy56kwxirquxaxso3nobtjtjvoqu552oqciudrm'; +// Make a revision to the current record (increments sequence number and sets value) +const nextRevision = await Name.increment(revision, nextValue); +``` + +Publication works the same as with the initial revision: + +```javascript +await Name.publish(nextRevision, name.key); +``` + +If you no longer have the old revision locally, you can [resolve the current value](#getting-the-latest-version) and use the returned revision as input to `Name.increment`. + +Note that you must have the original signing key in order to publish updates. See [Saving and loading keys](#saving-and-loading-keys) below to learn about key management. + +# Getting the latest revision +You can resolve the current value for any name using the `Name.resolve` function. + +```javascript +const name = Name.parse('k51qzi5uqu5di9agapykyjh3tqrf7i14a7fjq46oo0f6dxiimj62knq13059lt'); +const revision = await Name.resolve(name); +console.log('Resolved value:', revision.value); +``` + +# Saving and loading keys +To create revisions to a name after publication, you'll need the original signing key. You can get the binary representation of a name with the `key.bytes` property, which can then be saved to disk or stored in a secure key management system. + +```javascript +import fs from 'fs'; + +async function saveSigningKey(name, outputFilename) { + const bytes = name.key.bytes; + await fs.promises.writeFile(outputFilename, bytes); +} +``` + +Later, you can use `Name.from` to convert from the binary representation to an object suitable for publishing revisions. + +```javascript +import fs from 'fs'; + +async function loadSigningKey(filename) { + const bytes = await fs.promises.readFile(filename); + const name = await Name.from(bytes); + return name; +} +``` + + + Be careful where you save your keys! Your private signing keys allow the holder to update your published records. Be careful to save your keys to a secure location, and never store your private keys in a source code repository. + + +# Rate limits +The w3name API is rate limited at 30 requests per 10 seconds per IP. From 33ed68633f0b8fd44a50025c2c9acdb7bfbace03 Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 09:59:01 -0800 Subject: [PATCH 2/9] fix: import callout --- src/pages/docs/how-to/w3name.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/docs/how-to/w3name.mdx b/src/pages/docs/how-to/w3name.mdx index 3e05161..cec8953 100644 --- a/src/pages/docs/how-to/w3name.mdx +++ b/src/pages/docs/how-to/w3name.mdx @@ -1,3 +1,5 @@ +import { Callout } from 'nextra/components' + # Update your data with w3name All the data you [store on web3.storage](upload) is [content-addressed](../concepts/content-addressing), which means that you always get location-independent, cryptographically verifiable links to your content. From d43a92f0574f23f2ebe9996d9b1ddc6dc1df8a4b Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 10:02:28 -0800 Subject: [PATCH 3/9] fix: header types --- src/pages/docs/how-to/w3name.mdx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/pages/docs/how-to/w3name.mdx b/src/pages/docs/how-to/w3name.mdx index cec8953..abd0d34 100644 --- a/src/pages/docs/how-to/w3name.mdx +++ b/src/pages/docs/how-to/w3name.mdx @@ -18,7 +18,7 @@ In this guide, we'll discover how to use the JavaScript `w3name` package to crea IPNS is a secure, local-first protocol, but does not always resolve performantly when needing to fetch the absolute latest update to a name (which is a requirement for most application use-cases) from the public IPFS network (e.g., over a local Kubo instance or public gateway). You can read more about this [here.](https://docs.ipfs.tech/concepts/ipns/#tradeoffs-between-consistency-vs-availability). As a result, w3name's recommended usage for use cases where performance and consistency are both important is [via an endpoint hosted by web3.storage](#getting-the-latest-revision). We plan on offering a new naming protocol at some point that can be used for application use cases without relying on any centralized infrastructure. -# What's in a name? +## What's in a name? w3name is similar to the Domain Name System (DNS), in that it allows you to query for an identifier and resolve the latest value. Unlike DNS, however, you cannot choose your own identifiers, and the "names" produced by IPNS and w3name are not human-readable, like `web3.storage` or `ipfs.io`. @@ -31,7 +31,7 @@ Each "name" maps to a "record", which contains: Because the verification key is embedded in the name, all names created with w3name are "self-certifying," meaning that you can validate any record published to that name without needing any other authority or "source of truth" than the name itself. -# Getting started +## Getting started The easiest way to use the [w3name](https://www.npmjs.com/package/w3name) service is with the w3name JavaScript library, which provides methods for creating, signing, publishing and resolving records. @@ -73,7 +73,7 @@ console.log('created new name: ', name.toString()); So far, the signing key for your new name only exists in memory. To save it for publishing updates, see [Saving and loading keys](#saving-and-loading-keys) below. -# Publishing the first revision +## Publishing the first revision We created a name, but so far there's no value associated with it. @@ -94,7 +94,7 @@ We now have a `revision` object that's ready to publish, but so far it's only in await Name.publish(revision, name.key); ``` -# Publishing an updated revision +## Publishing an updated revision Each revision contains a sequence number, which must be incremented when publishing a new revision. Once you've published the initial revision, you can use the `Name.increment` function to create a new revision based on the previously published one. @@ -125,7 +125,8 @@ const revision = await Name.resolve(name); console.log('Resolved value:', revision.value); ``` -# Saving and loading keys +## Saving and loading keys + To create revisions to a name after publication, you'll need the original signing key. You can get the binary representation of a name with the `key.bytes` property, which can then be saved to disk or stored in a secure key management system. ```javascript @@ -153,5 +154,5 @@ async function loadSigningKey(filename) { Be careful where you save your keys! Your private signing keys allow the holder to update your published records. Be careful to save your keys to a secure location, and never store your private keys in a source code repository. -# Rate limits +## Rate limits The w3name API is rate limited at 30 requests per 10 seconds per IP. From a24322a795a5442ccc58fea96f84b80876a13076 Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 10:05:36 -0800 Subject: [PATCH 4/9] fix: change title in sidebar --- src/pages/docs/how-to/_meta.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/docs/how-to/_meta.json b/src/pages/docs/how-to/_meta.json index c0171bb..e1d0421 100644 --- a/src/pages/docs/how-to/_meta.json +++ b/src/pages/docs/how-to/_meta.json @@ -13,5 +13,6 @@ "title": "Query UCAN receipts", "display": "hidden" }, - "filecoin-info": "Get Filecoin info" + "filecoin-info": "Get Filecoin info", + "w3name": "Mutate pointers" } From 2164f6480d5017ad5c736fa058738e009137b8bd Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 14:14:36 -0800 Subject: [PATCH 5/9] Update src/pages/docs/how-to/w3name.mdx Co-authored-by: Alan Shaw --- src/pages/docs/how-to/w3name.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/docs/how-to/w3name.mdx b/src/pages/docs/how-to/w3name.mdx index abd0d34..c016b1d 100644 --- a/src/pages/docs/how-to/w3name.mdx +++ b/src/pages/docs/how-to/w3name.mdx @@ -14,7 +14,7 @@ All records created and updated using w3name are signed locally with each user's In this guide, we'll discover how to use the JavaScript `w3name` package to create and manage name records for data stored with web3.storage. - + IPNS is a secure, local-first protocol, but does not always resolve performantly when needing to fetch the absolute latest update to a name (which is a requirement for most application use-cases) from the public IPFS network (e.g., over a local Kubo instance or public gateway). You can read more about this [here.](https://docs.ipfs.tech/concepts/ipns/#tradeoffs-between-consistency-vs-availability). As a result, w3name's recommended usage for use cases where performance and consistency are both important is [via an endpoint hosted by web3.storage](#getting-the-latest-revision). We plan on offering a new naming protocol at some point that can be used for application use cases without relying on any centralized infrastructure. From ff245a94587beff1358f403a2c09cfad58606bda Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 14:14:44 -0800 Subject: [PATCH 6/9] Update src/pages/docs/how-to/w3name.mdx Co-authored-by: Alan Shaw --- src/pages/docs/how-to/w3name.mdx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/pages/docs/how-to/w3name.mdx b/src/pages/docs/how-to/w3name.mdx index c016b1d..df90f69 100644 --- a/src/pages/docs/how-to/w3name.mdx +++ b/src/pages/docs/how-to/w3name.mdx @@ -53,13 +53,6 @@ You can create a new IPNS name with the Name.create function: const name = await Name.create(); ``` -This example above uses the [`await` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await), because `Name.create()` returns a `Promise`. To use `await`, the code must be placed inside an [`async` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). Alternatively, you can resolve the promise using `.then()`, for example: - -```javascript -Name.create().then(name => { - // do something with name here. -}); -``` You can see the name as a string by calling .toString() on it: From aa0d6b79c20ab974f96d438fed33ab34331e9fb2 Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 14:15:08 -0800 Subject: [PATCH 7/9] Update src/pages/docs/how-to/w3name.mdx Co-authored-by: Alan Shaw --- src/pages/docs/how-to/w3name.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/docs/how-to/w3name.mdx b/src/pages/docs/how-to/w3name.mdx index df90f69..fa115ba 100644 --- a/src/pages/docs/how-to/w3name.mdx +++ b/src/pages/docs/how-to/w3name.mdx @@ -62,7 +62,7 @@ console.log('created new name: ', name.toString()); // created new name: k51qzi5uqu5di9agapykyjh3tqrf7i14a7fjq46oo0f6dxiimj62knq13059lt ``` - + So far, the signing key for your new name only exists in memory. To save it for publishing updates, see [Saving and loading keys](#saving-and-loading-keys) below. From 4b381fc939de6c3a23b598cee406bd14f6499350 Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 14:15:12 -0800 Subject: [PATCH 8/9] Update src/pages/docs/how-to/w3name.mdx Co-authored-by: Alan Shaw --- src/pages/docs/how-to/w3name.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/docs/how-to/w3name.mdx b/src/pages/docs/how-to/w3name.mdx index fa115ba..ce21e6c 100644 --- a/src/pages/docs/how-to/w3name.mdx +++ b/src/pages/docs/how-to/w3name.mdx @@ -143,7 +143,7 @@ async function loadSigningKey(filename) { } ``` - + Be careful where you save your keys! Your private signing keys allow the holder to update your published records. Be careful to save your keys to a secure location, and never store your private keys in a source code repository. From 8020be83f971ebd3ec9e88fcd4124febef4b4b57 Mon Sep 17 00:00:00 2001 From: David Choi Date: Wed, 13 Dec 2023 14:15:15 -0800 Subject: [PATCH 9/9] Update src/pages/docs/how-to/_meta.json Co-authored-by: Alan Shaw --- src/pages/docs/how-to/_meta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/docs/how-to/_meta.json b/src/pages/docs/how-to/_meta.json index e1d0421..b4f3833 100644 --- a/src/pages/docs/how-to/_meta.json +++ b/src/pages/docs/how-to/_meta.json @@ -14,5 +14,5 @@ "display": "hidden" }, "filecoin-info": "Get Filecoin info", - "w3name": "Mutate pointers" + "w3name": "Publish IPNS names" }