From 0b52644edfedea6dfc66da6a371848a9611b50ba Mon Sep 17 00:00:00 2001 From: nazeh Date: Tue, 31 May 2022 14:24:10 +0300 Subject: [PATCH] feat(sdk): resolve slashtag from dns human readable address --- examples/README.md | 9 + examples/dns/README.md | 23 ++ examples/dns/client.js | 17 ++ examples/dns/package.json | 7 + examples/dns/server.js | 27 +++ package-lock.json | 334 +++++++++++++++++++++----- package.json | 3 +- packages/sdk/README.md | 9 + packages/sdk/src/sdk.js | 31 +++ packages/sdk/test/dns-address.spec.js | 67 ++++++ 10 files changed, 468 insertions(+), 59 deletions(-) create mode 100644 examples/dns/README.md create mode 100644 examples/dns/client.js create mode 100644 examples/dns/package.json create mode 100644 examples/dns/server.js create mode 100644 packages/sdk/test/dns-address.spec.js diff --git a/examples/README.md b/examples/README.md index 9494e01b..176e0d46 100644 --- a/examples/README.md +++ b/examples/README.md @@ -7,3 +7,12 @@ A collection of examples that demonstrate how to use the Slashtags SDK. At the root directory of this monorepo, run `npm install` If you made any changes to this monorepo during devolpment, make sure to run `npm run link` at the root directory, and clean the temporary storage directory by running `npm run clean` in this directory. + +## Examples + +Available examples and their purpose: + +- [auth](./auth/) Demonstrates Auth protocol. +- [drives/watch](./drives/wathc/) Demonstrates watching live updates to a remote drive. +- [dns](./drives/) Demonstrates resolving a Slashtag key from a DNS address. +- [primaryKey](./primaryKey/) Demonstrates generating a primaryKey from a mnemonic seed. diff --git a/examples/dns/README.md b/examples/dns/README.md new file mode 100644 index 00000000..21b41158 --- /dev/null +++ b/examples/dns/README.md @@ -0,0 +1,23 @@ +# Slashtags Address + +Demonstrates retrieving a Slashtag from DNS based human readable address like `alice@example.com`. + +## Usage + +Run server side: + +```bash +npm run serve +``` + +Resolve the Slashtag profile from `alice@localhost:9999` + +```bash +npm run fetch +``` + +Or for root level address `localhost:9999` + +```bash +npm run fetch localhost:9999 +``` diff --git a/examples/dns/client.js b/examples/dns/client.js new file mode 100644 index 00000000..c67ed604 --- /dev/null +++ b/examples/dns/client.js @@ -0,0 +1,17 @@ +import { SDK } from '@synonymdev/slashtags-sdk' +import fetch from 'node-fetch' + +const address = process.argv[2] || 'alice@localhost:9999' + +const sdk = await SDK.init({ persist: false }) + +const slashtag = await sdk.fromDNS(address, { + protocol: 'http://', + fetch +}) + +const profile = await slashtag.getProfile() + +console.log('Resolved profile', profile) + +sdk.close() diff --git a/examples/dns/package.json b/examples/dns/package.json new file mode 100644 index 00000000..18d02a99 --- /dev/null +++ b/examples/dns/package.json @@ -0,0 +1,7 @@ +{ + "type": "module", + "scripts": { + "serve": "node server.js", + "fetch": "node client.js" + } +} \ No newline at end of file diff --git a/examples/dns/server.js b/examples/dns/server.js new file mode 100644 index 00000000..c2b721e7 --- /dev/null +++ b/examples/dns/server.js @@ -0,0 +1,27 @@ +import http from 'http' +import { SDK } from '@synonymdev/slashtags-sdk' + +const sdk = await SDK.init({ persist: false }) + +const alice = sdk.slashtag({ name: 'alice' }) +await alice.setProfile({ name: 'Alice' }) + +const root = sdk.slashtag({ name: 'root' }) +await root.setProfile({ name: 'Root' }) + +const server = http.createServer((req, res) => { + if (!req.url.startsWith('/.well-known/slashtags')) return + + res.setHeader('Content-Type', 'application/json') + res.setHeader('Access-Control-Allow-Origin', '*') + res.end( + JSON.stringify({ + _: root.url, + alice: alice.url + }) + ) +}) + +server.listen(9999, () => { + console.log('Server listening on localhost:' + 9999) +}) diff --git a/package-lock.json b/package-lock.json index 5e82702b..72091e73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "dht-universal": "^0.4.1", "graceful-goodbye": "^1.0.0", "lerna": "^4.0.0", + "node-fetch": "^3.2.4", "pm2": "^5.2.0", "standard": "^17.0.0" }, @@ -2079,6 +2080,48 @@ "node": ">= 10.18.0" } }, + "node_modules/@lerna/gitlab-client/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@lerna/gitlab-client/node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/@lerna/gitlab-client/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/@lerna/gitlab-client/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, "node_modules/@lerna/global-options": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-4.0.0.tgz", @@ -2967,6 +3010,48 @@ "once": "^1.4.0" } }, + "node_modules/@octokit/request/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@octokit/request/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/@octokit/request/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/@octokit/request/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/@octokit/rest": { "version": "18.12.0", "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", @@ -10127,6 +10212,29 @@ "pend": "~1.2.0" } }, + "node_modules/fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -10346,6 +10454,18 @@ "node": ">= 0.12" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -14894,6 +15014,25 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -14904,45 +15043,30 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.4.tgz", + "integrity": "sha512-WvYJRN7mMyOLurFR2YpysQGuwYrJN+qrrpHjJDuKMcSPdfFccRUla/kng2mz6HWSBxJcqPbvatS6Gb4RhOzCJw==", "dev": true, "dependencies": { - "whatwg-url": "^5.0.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "node_modules/node-fetch/node_modules/data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "engines": { + "node": ">= 12" } }, "node_modules/node-gyp": { @@ -24989,6 +25113,15 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -25598,7 +25731,7 @@ }, "packages/sdk": { "name": "@synonymdev/slashtags-sdk", - "version": "1.0.0-alpha.0", + "version": "1.0.0-alpha.1", "license": "MIT", "dependencies": { "@synonymdev/slashauth": "^1.0.0-alpha.0", @@ -25618,7 +25751,7 @@ }, "packages/slashtag": { "name": "@synonymdev/slashtag", - "version": "1.0.0-alpha.0", + "version": "1.0.0-alpha.1", "license": "MIT", "dependencies": { "@synonymdev/slashdrive": "^1.0.0-alpha.0", @@ -27179,6 +27312,41 @@ "node-fetch": "^2.6.1", "npmlog": "^4.1.2", "whatwg-url": "^8.4.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + } } }, "@lerna/global-options": { @@ -27906,6 +28074,39 @@ "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } } }, "@octokit/request-error": { @@ -28602,7 +28803,7 @@ "graceful-goodbye": "^1.0.0", "random-access-memory": "^4.0.0", "random-access-web": "^2.0.3", - "sodium-universal": "*", + "sodium-universal": "^3.1.0", "turbo-hash-map": "^1.0.3" } }, @@ -33265,6 +33466,16 @@ "pend": "~1.2.0" } }, + "fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "dev": true, + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -33418,6 +33629,15 @@ "mime-types": "^2.1.12" } }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "requires": { + "fetch-blob": "^3.1.2" + } + }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -36957,6 +37177,12 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true + }, "node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -36967,35 +37193,21 @@ } }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.4.tgz", + "integrity": "sha512-WvYJRN7mMyOLurFR2YpysQGuwYrJN+qrrpHjJDuKMcSPdfFccRUla/kng2mz6HWSBxJcqPbvatS6Gb4RhOzCJw==", "dev": true, "requires": { - "whatwg-url": "^5.0.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "dependencies": { - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } } } }, @@ -44469,6 +44681,12 @@ "defaults": "^1.0.3" } }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "dev": true + }, "webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", diff --git a/package.json b/package.json index de382ed8..38d94e7f 100644 --- a/package.json +++ b/package.json @@ -44,10 +44,11 @@ "dht-universal": "^0.4.1", "graceful-goodbye": "^1.0.0", "lerna": "^4.0.0", + "node-fetch": "^3.2.4", "pm2": "^5.2.0", "standard": "^17.0.0" }, "workspaces": [ "./packages/*" ] -} \ No newline at end of file +} diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 9cf50f29..961b68c0 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -98,6 +98,15 @@ Create a [Slashtag](../slashtag/) instance. Closes all Slahstags created by this SDK as well as any other resources managed by the SDK to enable graceful shutdown. +#### `await sdk.fromDNS(address, [opts])` + +Create a [Slashtag](../slashtag/) from dns address like `alice@example.com`. + +`options` includes: + +- `fetch` [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) compatible function, useful for testing, or passing `node-fetch` if necessary. +- `protocol` `https://` by default. helpful to allow `http://` while testing. + #### `SDK.protocols` A map of all the builtin [SlashProtocols](../slashtag/README.md#slashprotocol) that are available in the SDK by default. diff --git a/packages/sdk/src/sdk.js b/packages/sdk/src/sdk.js index 84791667..3c8280ff 100644 --- a/packages/sdk/src/sdk.js +++ b/packages/sdk/src/sdk.js @@ -12,6 +12,7 @@ import { hash } from './crypto.js' const debug = Debug('slashtags:sdk') const ROOT_SLASHTAG_NAME = '@slashtags-sdk/root' +const WELLKNOWN_PATH = '/.well-known/slashtags' export class SDK { /** * @@ -138,4 +139,34 @@ export class SDK { static get DERIVATION_PATH () { return "m/123456'" } + + /** + * + * @param {string} address + * @param {object} [opts] + * @param {string} [opts.protocol] + * @param {import ('node-fetch').default} [opts.fetch] + * @returns {Promise} + */ + async fromDNS (address, opts) { + const split = address.split('@') + const domain = split.pop() + const name = split.pop() || '_' + + const _fetch = opts?.fetch || fetch + + const response = await _fetch( + (opts?.protocol || 'https://') + + domain + + WELLKNOWN_PATH + + '?name=' + + name + ) + const names = await response.json() + const url = names[name] + + if (!url) return null + + return this.slashtag({ url }) + } } diff --git a/packages/sdk/test/dns-address.spec.js b/packages/sdk/test/dns-address.spec.js new file mode 100644 index 00000000..1d8123d4 --- /dev/null +++ b/packages/sdk/test/dns-address.spec.js @@ -0,0 +1,67 @@ +import { expect } from 'aegir/chai'; +import { sdk } from './helpers/setup-sdk.js'; + +const wellKnownPath = '/.well-known/slashtags'; + +describe('dns-address', () => { + it('should parse slashtags address correctly alice@example.com', async () => { + const sdkA = await sdk(); + + const url = sdkA._root.url.toString(); + + const slashtag = await sdkA.fromDNS('alice@example.com', { + fetch: async (...args) => { + expect(args[0]).to.eql( + 'https://example.com' + wellKnownPath + '?name=alice', + ); + return { json: async () => ({ alice: url }) }; + }, + }); + + expect(slashtag.url.toString()).to.eql(url); + expect(slashtag.remote).to.be.true(); + + sdkA.close(); + }); + + it('should parse slashtags address correctly alice.com (root domain)', async () => { + const sdkA = await sdk(); + + const url = sdkA._root.url.toString(); + + const slashtag = await sdkA.fromDNS('example.com', { + fetch: async (...args) => { + expect(args[0]).to.eql( + 'https://example.com' + wellKnownPath + '?name=_', + ); + return { json: async () => ({ _: url }) }; + }, + }); + + expect(slashtag.url.toString()).to.eql(url); + expect(slashtag.remote).to.be.true(); + + sdkA.close(); + }); + + it('should allow custom protocol (support http for testing)', async () => { + const sdkA = await sdk(); + + const url = sdkA._root.url.toString(); + + const slashtag = await sdkA.fromDNS('example.com', { + fetch: async (...args) => { + expect(args[0]).to.eql( + 'http://example.com' + wellKnownPath + '?name=_', + ); + return { json: async () => ({ _: url }) }; + }, + protocol: 'http://', + }); + + expect(slashtag.url.toString()).to.eql(url); + expect(slashtag.remote).to.be.true(); + + sdkA.close(); + }); +});