Compare commits

...

137 commits

Author SHA1 Message Date
Alex Grin
b5eb6fe390
Merge pull request #381 from keikari/patch-2 2022-06-10 14:21:26 -04:00
miko
d8bbdffbf8
Update TCP port default value 2022-06-08 18:18:51 +03:00
Alex Grin
6fd2acdfc2
Merge pull request #380 from lbryio/p2p
LBRY P2P: Settings and troubleshooting
2022-05-24 12:55:25 -04:00
Victor Shyba
3d21394728 refactor confusing paragraph 2022-05-19 18:49:34 -03:00
Victor Shyba
dbb050baa0 improve reachability text 2022-05-19 18:46:56 -03:00
Victor Shyba
9b5c92a722 add wiki reference on hole punching 2022-05-19 18:19:30 -03:00
Victor Shyba
aebef79820 add p2p-seeding.md 2022-05-19 18:15:21 -03:00
Lex Berezhny
a8f9d90f22 added time locked transaction instructions 2022-04-25 09:07:16 -04:00
Alex Grintsvayg
2098f6bbba
improve lbrycrdd service file
inspired by #370  and https://github.com/lbryio/lbrycrd/blob/master/contrib/init/bitcoind.service
2022-02-08 10:32:27 -05:00
Alex Grin
158c49b58f
Merge pull request #370 from derlaft/patch-1 2022-02-08 10:21:14 -05:00
Aleksei Kharlamov
08759225a6
wallet-server: update suggested systemd unit
Use `Type=Forking`. By default, `Type=Simple` is used and it expects that the daemon stays forking in the foreground. However, lbrycrdd does the opposite and forks/goes to background. This confuses systemd a little bit:

```
Dec 09 10:30:28 lbry.devass.club systemd[1]: lbrycrdd.service: Unit process 12237 (lbrycrdd) remains running after unit stopped.
```

So basically it thinks that the unit stops working instantly. When the correct type is used, systemd should be able to handle this situations, along with restarts, properly.

See also: [AUR systemd service](https://aur.archlinux.org/cgit/aur.git/tree/lbrycrd.service?h=lbrycrd)
2021-12-10 01:50:40 +01:00
Alex Grin
2fe727d9c2
Update resources.md 2021-11-08 11:39:35 -05:00
Alex Grin
935ca0694a
Delete regtest-setup.md 2021-11-08 11:39:17 -05:00
Alex Grin
ff9c0dbc8b
Merge pull request #366 from lbryio/update-wallet-server-instructions 2021-11-08 11:23:48 -05:00
Alex Grin
cf6850c89d
Merge pull request #358 from lbryio/odysee-api 2021-11-08 11:22:26 -05:00
Jack Robison
f97bb66eda
update instructions 2021-11-08 09:33:15 -05:00
Alex Grin
04a8ef7d96
Merge pull request #364 from lbryio/dht_bootstrap 2021-10-04 15:02:20 -04:00
Victor Shyba
b46edd2ba0 add section to check the node 2021-09-28 18:55:34 -03:00
Victor Shyba
2eef37c05d DHT bootstrap guide 2021-09-28 18:42:32 -03:00
Alex Grintsvayg
62cbc4edad
fix pgp link 2021-09-28 10:23:23 -04:00
Alex Grin
9be3af9cb5
Update README.md 2021-09-28 10:16:15 -04:00
Thomas Zarebczan
679561b334
Merge pull request #363 from bradley-ray/github-feed-fix-undefined
added case PullRequestReviewEvent to generateEvent function
2021-09-24 09:49:40 -04:00
Bradley Ray
7da3b6dacf
added case PullRequestReviewEvent to generateEvent 2021-09-23 00:10:50 -05:00
Thomas Zarebczan
88bc857a31
Update lbrytv-sdk.js 2021-08-07 01:47:50 -04:00
Thomas Zarebczan
abbebe07d3
update to odysee api 2021-08-07 01:44:10 -04:00
Andrey Beletsky
cd3faa3270 documents/contribute.md 2021-07-20 15:21:05 +07:00
Alex Grin
786be56ed4
Update resources.md 2021-06-28 09:45:17 -04:00
Bryan Lunduke
a9cdfd94ba
Add Hello Satoshi Tutorial to list 2021-06-20 12:49:07 -05:00
Bryan Lunduke
aa79b0ae21
Creating a dedicated page for Hello Satoshi 2021-06-20 12:44:34 -05:00
Bryan Lunduke
53262f300d
Adding a Tutorials option to the navigation bar 2021-06-20 12:28:05 -05:00
Bryan Lunduke
ae51c52240
Create tutorials.md
Setting up the tutorials document which will contain all of the tutorials (and related resources) in categories.
2021-06-17 10:42:31 -05:00
Alex Grin
706b9752e2
Merge pull request #354 from lbryio/web-instance 2021-06-15 15:21:48 -04:00
Alex Grin
34f7842505
Update web-instance.md 2021-06-15 15:21:13 -04:00
Victor Shyba
0e95e6dc72 move prebuilt image section up, add step to clone sdk repo 2021-06-15 16:04:49 -03:00
Victor Shyba
55d0a6df63 format title/description 2021-06-15 14:49:06 -03:00
Victor Shyba
ad1395a5b9 describe how to install a web instance 2021-06-15 14:47:47 -03:00
Bryan Lunduke
0a7955bcdc
Removing Developer program link 2021-06-10 16:22:55 -05:00
Thomas Zarebczan
d7f7612f6d
Merge pull request #344 from e4drcf/patch-1
Update contribute.md
2021-06-10 11:53:08 -04:00
Thomas Zarebczan
d0069e7a51
Merge pull request #352 from lbryio/BryanLunduke-patch-1
Update overview.md
2021-06-09 20:58:09 -04:00
Bryan Lunduke
cb6b72b5b2
Update overview.md
Removing the developer program link.
2021-06-09 13:54:07 -05:00
Florence Jay Munar
7dc4883bf6 Update icons 2021-06-07 10:18:14 -04:00
Alex Grin
ddf43a087c
Merge pull request #348 from lbryio/resync-docs
Explain how to resync ES and expand into two parts
2021-05-18 15:11:25 -04:00
Victor Shyba
a3796248ee
Explain how to resync ES and expand into two parts 2021-05-13 17:45:41 -03:00
Ivan Hranat
c207123556
Update contribute.md 2021-04-21 20:27:21 +03:00
Alex Grintsvayg
507f125727
a few edits 2021-04-20 16:49:30 -04:00
Victor Shyba
7fecb9fcc1
Update wallet-server.md (#339)
Co-authored-by: Alex Grin <lyoshenka@users.noreply.github.com>
2021-04-19 15:21:17 -04:00
Alex Grintsvayg
f282093d24
disable dev program 2021-03-29 09:42:52 -04:00
Thomas Zarebczan
c00f03cbef
Merge pull request #341 from ElectronEsq/patch-3
Missing rule added.
2021-03-18 12:01:54 -04:00
Thomas Zarebczan
a0bc2572a8
Update developer-program.md 2021-03-18 11:45:12 -04:00
Thomas Zarebczan
3ea5e3d261
Update overview.md 2021-03-18 11:44:46 -04:00
Electron - Mark Firth
668e140978
Missing rule added.
Missing rule added.
2021-03-18 18:59:25 +10:00
Thomas Zarebczan
433d05776e
Fix video links 2021-01-04 12:02:18 -05:00
johan456789
e024e7dab7 Update twitter link 2020-12-29 11:31:42 -05:00
Niko
16d59fbf66
Merge pull request #331 from kodxana/master
Fixed docker security
2020-09-28 14:38:49 -04:00
kodxana
91431922f5
Fixed docker security
Running docker as sudo is not the best security.
https://engineering.bitnami.com/articles/why-non-root-containers-are-important-for-security.html

Instead of running container as root add user to docker group and there will no need for using sudo.
2020-09-28 20:22:58 +02:00
Thomas Zarebczan
ae4e43b466
Merge pull request #329 from edrochenski/patch-1
Clarify commit history requirement
2020-08-28 13:17:04 -04:00
Ed Rochenski
55d55ae0f8
Clarify commit history requirement 2020-08-28 12:25:17 -04:00
Thomas Zarebczan
0716a22357
Merge pull request #323 from pavelloz/npm-tasks-bail
Abort if previous task fail
2020-05-20 07:53:22 -04:00
Thomas Zarebczan
991331d2c2
Merge pull request #324 from keikari/patch-1
Update wallet address default values
2020-05-20 07:52:22 -04:00
keikari
59246be540
Update wallet address default values
I noticed that default wallet server addresses were old and didn't worked.
Updated values and added list of default servers into "Description", since listing them in "Default value" made page too wide on preview.
2020-05-17 12:37:12 +03:00
Paweł Kowalski
cd1a2fc70a Abort if previous task fail 2020-05-16 11:34:12 +02:00
Thomas Zarebczan
d7b71a0d1c
Merge pull request #322 from eatdostacos/master
Some More LBRY.tech Small Changes
2020-05-01 13:55:35 -04:00
eatdostacos
a6905a4e96
Consensus.md small changes
The title exactly.
2020-05-01 10:09:21 -07:00
eatdostacos
b4e88a5396
Small Updates to claimtrie.md
See edits.
2020-05-01 10:04:15 -07:00
Thomas Zarebczan
cd4034fa64
Merge pull request #321 from eatdostacos/patch-1
More General Improvements
2020-05-01 09:09:30 -04:00
eatdostacos
92005ee346
Change "sha256" to "SHA256"
Exactly the title.
2020-04-30 22:41:37 -07:00
eatdostacos
99804e5697
Corrected Some Things
Changed some text to make it sound better and be correct.
2020-04-30 22:34:08 -07:00
Thomas Zarebczan
5986a6a59a
Merge pull request #320 from eatdostacos/patch-1
General Improvements
2020-05-01 01:20:49 -04:00
eatdostacos
ecfdbecf2c
Removed the "or," that didn't seem necessary
This bit of text didn't seem like it was needed at the LBRY Credits was already in parenthesizes showing that it is what LBC means.
2020-04-30 22:10:47 -07:00
eatdostacos
2d91e2dd1b
"LBRY" Coin to "LBRY Credits"
For some reason it said LBRY Coin even though that has never been a thing. I also capitalized the C in Credits.
2020-04-30 21:56:31 -07:00
Thomas Zarebczan
0bdc1cf733
Merge pull request #318 from NetOperatorWibby/patch-1
Updates primary contact
2020-04-17 08:08:13 -04:00
netop://ウエハ
dc118bdbf5
Updates primary contact
_I'm assuming your email address, Tom._
2020-04-16 22:31:24 -07:00
Thomas Zarebczan
dc54ce1cf0
Merge pull request #317 from cassidypignatello/fix/code-style-errors
fixes eslint errors
2020-04-14 16:47:01 -04:00
Cassidy
7797f1f42c fixes eslint errors 2020-04-11 14:40:00 +07:00
Jeremy Kauffman
f2833d4a8e
add translating instructions 2020-03-24 19:14:04 -04:00
Jeremy Kauffman
7d67f6700f
lbry-desktop is lbry.tv 2020-03-10 16:08:24 -04:00
Jeremy Kauffman
71d78c40d9
fix broken link 2020-02-28 17:26:01 -05:00
Niko Storni
15a8675bef fix playground 2020-02-26 19:23:25 +01:00
Thomas Zarebczan
72aad4a523
Merge pull request #314 from netapau/patch-1
Update repository-standards.md
2020-02-25 09:20:14 -05:00
Tony Simoes
6fb5915808
Update repository-standards.md
Asterisk 'Italics' inside 'url brackets' generates a 404.

See : [https://lbry.tech/resources/repository-standards](https://lbry.tech/resources/repository-standards).
2020-02-22 13:44:03 +01:00
James Goodrich
04bc129c8e Replaces broken ecosystem-overview links
The Reporting a Bug and Feature Requests sections contained broken links to the Ecosystem Overview. However, the steps containing the broken link were for identifying the correct repository. Therefore, the broken ecosystem-overview links were replaced with repository-overview links with additional updates to the linking text.

Fixes #305
2020-02-06 16:31:02 -05:00
Lex Berezhny
b09820a315
Merge pull request #311 from lbryio/lbry_sdk_directory_refactor
lbry directory in lbry-sdk repo moved up one level
2020-01-02 14:27:12 -05:00
Lex Berezhny
32f64d704d lbry directory in lbry-sdk repo moved up one level 2019-12-31 19:20:37 -05:00
Iykury
0a51e2f652 Edit "There's literally 12^n of us." to be more correct 2019-12-30 13:27:36 -05:00
Alex Grintsvayg
b260fc0624
wallet server maintenance instructions 2019-12-20 12:59:19 -05:00
Alex Grintsvayg
7b11a03e02
wallet server guide 2019-11-27 10:24:09 -05:00
Jeremy Kauffman
7963e5bdd4
no more web-daemon 2019-11-20 16:06:07 -05:00
Niko Storni
6ad1f91862 fix api endpoint 2019-11-14 17:53:04 -05:00
Niko Storni
167587081f add lockfile 2019-11-12 15:25:37 -05:00
Jeremy Kauffman
47da88fe2a
update canonical url glossary 2019-11-11 15:41:32 -05:00
Sean Yesmunt
fed52c65da Allow app to be run locally without github token 2019-10-29 18:46:01 -04:00
Thomas Zarebczan
0ec0dea55d
Merge pull request #308 from sameshl/patch-1
Update repository-standards.md
2019-10-29 13:11:38 -04:00
Samesh Lakhotia
dac8511d1f
Update repository-standards.md
add determiner `a`
2019-10-29 22:36:46 +05:30
Thomas Zarebczan
362c14c83c
Merge pull request #304 from colinfruit/md-link-typo
fix markdown typo in overview
2019-10-26 09:26:41 -04:00
Thomas Zarebczan
053aad7833
Merge pull request #303 from michizhou/patch-1
Fixed broken links and typos in documentation
2019-10-26 09:26:14 -04:00
Thomas Zarebczan
026bb01b81
Merge pull request #302 from vulongm/patch-1
Add "master" to list of tags
2019-10-26 09:25:53 -04:00
colinfruit
e020eb3c13 fix markdown typo in overview 2019-10-24 22:53:06 -04:00
michizhou
1be0995bbf
Fixed broken links and typos in documentation 2019-10-24 20:43:40 -04:00
Long Vu
d8b37ed0e6
Add "master" to list of tags
Resolves #301
2019-10-24 16:39:26 -04:00
Thomas Zarebczan
1b56526711
Merge pull request #300 from ykris45/patch-5
fix broken link on LBRY Tech Repo
2019-10-15 12:16:24 -04:00
YULIUS KURNIAWAN KRISTIANTO
707f616224
Update edit-link.js 2019-10-15 20:11:34 +07:00
YULIUS KURNIAWAN KRISTIANTO
5277050c37
Update download-overview.md 2019-10-15 19:55:47 +07:00
YULIUS KURNIAWAN KRISTIANTO
698222cf32
Update download-overview-new.md 2019-10-15 19:55:19 +07:00
YULIUS KURNIAWAN KRISTIANTO
1c0888e0cf
fix broken links and 404 link 2019-10-15 19:37:38 +07:00
Niko Storni
39ea483f08 fix resolution of claims 2019-09-23 23:01:28 +02:00
Niko Storni
6ae0984edf add trending call
use new resolve and trending
remove old trending func
2019-09-23 19:42:21 +02:00
Niko Storni
d5932ce67c port resolve call to lbrytv 2019-09-23 19:27:04 +02:00
Thomas Zarebczan
777d9f0f83
Yolo fix to rewards
Will run locally if this doesn't work...
2019-09-12 14:48:54 -04:00
Thomas Zarebczan
b3ae6ca0d6
remove auth settings 2019-09-12 12:10:16 -04:00
Thomas Zarebczan
ebbcb02c87
Merge pull request #296 from lbryio/devprogram-fixes
Developer program fixes
2019-09-10 13:29:25 -04:00
netop://ウエハ
cc965191f2 Better error messaging 2019-09-09 17:37:58 -05:00
netop://ウエハ
48190d18be Debugging 2019-09-09 16:59:22 -05:00
netop://ウエハ
201f8a4a09 Closes #291 2019-09-09 16:57:22 -05:00
netop://ウエハ
ed6cfb239a Debugging 2019-09-09 15:55:32 -05:00
Thomas Zarebczan
7beeffd008
add short and canonical url definitions 2019-09-09 14:32:59 -04:00
Thomas Zarebczan
8bfeafa137
Merge pull request #295 from dittaeva/patch-1
Update contribute.md HTMl > HTML
2019-09-09 09:42:34 -04:00
Guttorm Flatabø
85226a20d0
Update contribute.md HTMl > HTML 2019-09-09 15:26:38 +02:00
Niko
ee65417441
Merge pull request #294 from lbryio/fix_some_bugs
Fixed some bugs
2019-09-02 04:44:07 +02:00
Mark Beamer Jr
94136dbb69
Add console error for heroku log.
Fix bug where there was not check on undefined metadata.
Fix bug where claims from list trending are not part of a channel.
2019-09-01 22:33:36 -04:00
netop://ウエハ
5bc4650ad1
Merge pull request #290 from eggplantbren/patch-1
Add streaming_server to table of daemon settings
2019-08-25 20:20:24 -05:00
Brendon J. Brewer
741a672538
Add streaming_server to table of daemon settings
I guessed this option while trying to get LBRY to run when I connect to a VPN. Thought I'd add it to the page.
2019-08-26 13:04:14 +12:00
netop://ウエハ
5949bcb16e Closes #288 2019-08-21 12:54:17 -05:00
Niko Storni
f66349d613 woops... one more 2019-08-06 22:58:53 +02:00
Niko Storni
753deb4723 remove unnecessary logging 2019-08-06 22:58:11 +02:00
Niko Storni
3e2e6afbc7 hide porn
fix missing imports
log better
2019-08-06 22:52:50 +02:00
Thomas Zarebczan
79f81d4267
add streaming options 2019-08-06 10:57:26 -04:00
netop://ウエハ
3e061dbf4b Hotfix: check for tag existence 2019-07-11 17:46:38 -05:00
netop://ウエハ
8b9ca4302b
Merge pull request #283 from lbryio/versionable-apis
Versionable APIs
2019-07-11 17:27:36 -05:00
netop://ウエハ
4045de7c2c Removed commented code 2019-07-11 17:25:55 -05:00
netop://ウエハ
39bf3b56bc Linting 2019-07-11 17:09:36 -05:00
netop://ウエハ
a6b7340e9d Done 2019-07-11 16:20:50 -05:00
netop://ウエハ
4b14cc1a73 Almost done 2019-07-10 16:48:45 -05:00
netop://ウエハ
e260ae0e28 In progress 2019-07-10 12:34:19 -05:00
netop://ウエハ
0c496b33ae Visual fix for input on API pages 2019-07-08 14:30:37 -05:00
netop://ウエハ
fda1e3d800 Updated deps 2019-07-08 14:04:25 -05:00
Thomas Zarebczan
05af3d76a0
Merge pull request #282 from lbryio/lbry_sdk_repo_rename
lbry repo was renamed to lbry-sdk
2019-06-20 23:46:48 -04:00
Lex Berezhny
d673bd6395 lbry repo was renamed to lbry-sdk 2019-06-20 23:43:42 -04:00
59 changed files with 12286 additions and 639 deletions

1
.npmrc
View file

@ -1 +0,0 @@
package-lock=false

View file

@ -25,7 +25,6 @@
## Prerequisites ## Prerequisites
- [lbry/web-daemon](https://github.com/lbryio/web-daemon)
- [Node](https://nodejs.org) (version >= 10) - [Node](https://nodejs.org) (version >= 10)
## Notes ## Notes
@ -58,7 +57,7 @@ This project is MIT licensed. For the full license, see [LICENSE](LICENSE).
## Security ## Security
We take security seriously. Please contact [security@lbry.com](mailto:security@lbry.com) regarding any security issues. We take security seriously. Please contact [security@lbry.com](mailto:security@lbry.com) regarding any security issues.
[Our PGP key is here](https://keybase.io/lbry/key.asc) if you need it. [Our PGP key is here](https://lbry.com/faq/pgp-key) if you need it.
## Contact ## Contact
The primary contact for this project is [Paul Anthony Webb](https://github.com/NetOperatorWibby) (paul+github@lbry.com). The primary contact for this project is [Thomas Zarebczan](https://github.com/tzarebczan) (tom+github@lbry.com).

View file

@ -10,9 +10,9 @@ import html from "choo/html";
// E X P O R T // E X P O R T
export default () => html` export default version => html`
<div class="api-content__body"> <div class="api-content__body">
<h2>lbrycrd APIs</h2> <h2>lbrycrd ${version}</h2>
<p>Methods and signatures provided by the <a href="/glossary#lbrycrd">lbrycrd</a> blockchain daemon are documented below. To build, download, or run lbrycrd, see the project <a href="https://github.com/lbryio/lbrycrd/blob/master/README.md">README</a>.</p> <p>Methods and signatures provided by the <a href="/glossary#lbrycrd">lbrycrd</a> blockchain daemon are documented below. To build, download, or run lbrycrd, see the project <a href="https://github.com/lbryio/lbrycrd/blob/master/README.md">README</a>.</p>
</div> </div>

View file

@ -10,14 +10,14 @@ import html from "choo/html";
// E X P O R T // E X P O R T
export default () => html` export default version => html`
<div class="api-content__body"> <div class="api-content__body">
<h2>lbry-sdk APIs</h2> <h2>lbry-sdk ${version}</h2>
<p>Methods and signatures provided by the <a href="/glossary#lbry-sdk">lbry-sdk</a> daemon are documented below. To build, download, or run the daemon, see the project <a href="https://github.com/lbryio/lbry/blob/master/README.md">README</a>.</p> <p>Methods and signatures provided by the <a href="/glossary#lbry-sdk">lbry-sdk</a> daemon are documented below. To build, download, or run the daemon, see the project <a href="https://github.com/lbryio/lbry-sdk/blob/master/README.md">README</a>.</p>
</div> </div>
<div class="api-content__intro"> <div class="api-content__intro">
<p>You can find the repo for this API on GitHub:</p> <p>You can find the repo for this API on GitHub:</p>
<pre><code>https://github.com/lbryio/lbry</code></pre> <pre><code>https://github.com/lbryio/lbry-sdk</code></pre>
</div> </div>
`; `;

View file

@ -24,7 +24,7 @@ if (window.location.search.includes("?code=")) {
<p>To receive your LBC, you'll need a wallet address. While graphical wallets are available, the recommended path for engineers is to:</p> <p>To receive your LBC, you'll need a wallet address. While graphical wallets are available, the recommended path for engineers is to:</p>
<ol> <ol>
<li>Download <a href="https://github.com/lbryio/lbry/releases">the LBRY SDK</a>.</li> <li>Download <a href="https://github.com/lbryio/lbry-sdk/releases">the LBRY SDK</a>.</li>
<li>Launch the command-line utility (<code>./lbrynet start</code>).</li> <li>Launch the command-line utility (<code>./lbrynet start</code>).</li>
<li>Run <code>./lbrynet address unused</code> and copy the <code>id</code> field.</li> <li>Run <code>./lbrynet address unused</code> and copy the <code>id</code> field.</li>
</ol> </ol>
@ -56,33 +56,40 @@ function syncWithApi(data) { // eslint-disable-line no-unused-vars
const address = data.address; const address = data.address;
const code = data.code; const code = data.code;
if (code === null) if (code === null) {
document.querySelector("developer-program").innerHTML = document.querySelector("developer-program").innerHTML =
"<p><strong>There was an issue with accessing GitHub's API. Please try again later.</strong></p>"; "<p><strong>There was an issue with accessing GitHub's API. Please try again later.</strong></p>";
}
fetch(`https://api.lbry.com/reward/new?github_token=${code}&reward_type=github_developer&wallet_address=${address}`) fetch(`https://api.lbry.com/reward/new?github_token=${code}&reward_type=github_developer&wallet_address=${address}`)
.then(response => response.json()) .then(response => response.json())
.then(result => { .then(result => {
switch(true) { switch(true) {
case result.error === "this reward is limited to 1 per person": case result.error === "This reward is limited to 1 per person":
document.querySelector("developer-program").innerHTML = document.querySelector("developer-program").innerHTML =
"<p>You have already claimed this reward. This reward is limited to <strong>ONE</strong> per person. Your enthusiasm is appreciated.</p>"; "<p>You have already claimed this reward. This reward is limited to <strong>ONE</strong> per person. Your enthusiasm is appreciated.</p>";
break; return;
case Boolean(result.error):
document.querySelector("developer-program").innerHTML =
`<p>${result.error}</p>`;
return;
case result.success: case result.success:
result = result.data; result = result.data;
document.querySelector("developer-program").innerHTML = document.querySelector("developer-program").innerHTML =
`<p><strong>Success!</strong> Your wallet has been credited with ${result.reward_amount} LBC.</p><p>We have a great reference for the <a href="/api/sdk">LBRY SDK here</a> to help you get started.</p><p>You can see proof of this transaction on <a href="https://explorer.lbry.com/tx/${result.transaction_id}">our Blockchain Explorer</a>.</p>`; `<p><strong>Success!</strong> Your wallet has been credited with ${result.reward_amount} LBC.</p><p>We have a great reference for the <a href="/api/sdk">LBRY SDK here</a> to help you get started.</p><p>You can see proof of this transaction on <a href="https://explorer.lbry.com/tx/${result.transaction_id}">our Blockchain Explorer</a>.</p>`;
break; return;
default: default:
console.log(data); // eslint-disable-line no-console console.info(data); // eslint-disable-line no-console
document.querySelector("developer-program").innerHTML = document.querySelector("developer-program").innerHTML =
"<p><strong>The LBRY API might be down. Please try again later.</strong></p>"; "<p><strong>No success or error was received so the LBRY API might be down.<br/>Please try again later.</strong></p>";
break;
} }
}) })
.catch(() => { .catch(error => {
console.error(error);
// Idk what the error would be (probably a 500) so let's just have this message // Idk what the error would be (probably a 500) so let's just have this message
document.querySelector("developer-program").innerHTML = document.querySelector("developer-program").innerHTML =
"<p><strong>LBRY API is down. Please try again later.</strong></p>"; "<p><strong>LBRY API is down. Please try again later.</strong></p>";

View file

@ -249,15 +249,15 @@ curl --header <span class="token string">"Content-Type: application/json"</span>
} }
const handleExamples = debounce(event => { const handleExamples = debounce(event => {
let exampleNumber; const exampleNumber = parseInt(document.querySelector(".playground-navigation__example.active").dataset.example || 0);
const data = event.dataset; const data = event.dataset;
if (!parseInt(document.querySelector(".playground-navigation__example.active").dataset.example)) return; if (!exampleNumber || exampleNumber === 0)
exampleNumber = parseInt(document.querySelector(".playground-navigation__example.active").dataset.example); return;
switch(data.action) { switch(data.action) {
case "choose claim": case "choose claim":
fetchMetadata(exampleNumber, data.claimId); fetchMetadata(exampleNumber, `${data.name}#${data.claimId}`);
if (document.querySelector(".playground-navigation__example:nth-child(3)").classList.contains("active")) if (document.querySelector(".playground-navigation__example:nth-child(3)").classList.contains("active"))
document.getElementById("fetch-claim-uri").value = event.dataset.name + "#" + event.dataset.claimId; document.getElementById("fetch-claim-uri").value = event.dataset.name + "#" + event.dataset.claimId;
@ -398,9 +398,9 @@ function updateCanvas(imageSource) {
if (imageSource) { if (imageSource) {
ctx.drawImage(imageSource, 0, 0, canvasWidth, canvasHeight); ctx.drawImage(imageSource, 0, 0, canvasWidth, canvasHeight);
img.src = imageSource.src; img.src = imageSource.src;
} else { } else
ctx.drawImage(img, 0, 0, canvasWidth, canvasHeight); ctx.drawImage(img, 0, 0, canvasWidth, canvasHeight);
}
positionCanvasText(ctx, canvasHeight, canvasWidth); positionCanvasText(ctx, canvasHeight, canvasWidth);
} }

View file

@ -21,7 +21,7 @@ export default () => `
</span> </span>
<div> <div>
<span><a href="https://github.com/lbryio/lbry">lbrysdk</a></span> <span><a href="https://github.com/lbryio/lbry-sdk">lbrysdk</a></span>
<span><a href="https://github.com/lbryio/types">lbryschema</a></span> <span><a href="https://github.com/lbryio/types">lbryschema</a></span>
</div> </div>
</h2> </h2>

View file

@ -22,8 +22,7 @@ export default () => `
<div> <div>
<span><a href="https://github.com/lbryio/lbrycrd">lbrycrd</a></span> <span><a href="https://github.com/lbryio/lbrycrd">lbrycrd</a></span>
<span><a href="https://github.com/lbryio/torba">torba</a></span> <span><a href="https://github.com/lbryio/lbry-sdk">SDK</a></span>
<span><a href="https://github.com/lbryio/lbryumx">lbryumx</a></span>
</div> </div>
</h2> </h2>

View file

@ -27,11 +27,11 @@ export default pagePath => {
break; break;
case "/api/blockchain": case "/api/blockchain":
githubUrl = "https://github.com/lbryio/lbrycrd/blob/add_api_docs_scripts/contrib/devtools/generated/api_v1.json"; githubUrl = "https://github.com/lbryio/lbrycrd/blob/master/contrib/devtools/generated/api_v1.json";
break; break;
case "/api/sdk": case "/api/sdk":
githubUrl = "https://github.com/lbryio/lbry/blob/master/docs/api.json"; githubUrl = "https://github.com/lbryio/lbry-sdk/blob/master/docs/api.json";
break; break;
default: default:

View file

@ -31,7 +31,7 @@ const links = [
// title: "Join Our Team" // title: "Join Our Team"
// }, // },
{ {
href: "https://twitter.com/lbryio", href: "https://twitter.com/LBRYcom",
image: "https://spee.ch/9c38db124b85736adbcca48cdf34877d2110bbcd/GeoShapes.png", image: "https://spee.ch/9c38db124b85736adbcca48cdf34877d2110bbcd/GeoShapes.png",
title: "Twitter" title: "Twitter"
}, },

View file

@ -68,11 +68,3 @@ export default (state, emit) => {
<script src="/assets/scripts/sockets.js"></script> <script src="/assets/scripts/sockets.js"></script>
`; `;
}; };
// H E L P E R
String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
};

View file

@ -32,6 +32,11 @@ export default currentUrl => {
title: "View LBRY resources", title: "View LBRY resources",
url: "/resources" url: "/resources"
}, },
{
name: "Tutorials",
title: "LBRY Tutorials",
url: "/tutorials"
},
{ {
name: "Community", name: "Community",
title: "Interact with LBRY", title: "Interact with LBRY",

View file

@ -69,9 +69,9 @@ function navigation() {
<li <li
class="playground-navigation__example" class="playground-navigation__example"
data-action="playground, example 3" data-action="playground, example 3"
data-description="In the LBRY app, you can financially support your favorite creators by donating LBRY Coin (LBC). In this example, we are donating LBC in your stead." data-description="In the LBRY app, you can financially support your favorite creators by donating LBRY Credits (LBC). In this example, we are donating LBC in your stead."
data-example="3" data-example="3"
data-success="<strong>Kudos</strong> You've just supported a creator with LBC (or, LBRY credits) with our own stash of LBC (you'd use your own IRL). You're basically saying, 'thanks for this great content, please continue!' and that's awesome. You're awesome." data-success="<strong>Kudos</strong> You've just supported a creator with LBC (LBRY Credits) with our own stash of LBC (you'd use your own IRL). You're basically saying, 'thanks for this great content, please continue!' and that's awesome. You're awesome."
> >
<button type="button">Support</button> <button type="button">Support</button>
<span>Support creators on LBRY with a tip, on us!</span> <span>Support creators on LBRY with a tip, on us!</span>

View file

@ -35,9 +35,4 @@ export default () => linkGrid([{
destination: "/build", destination: "/build",
label: "Build An App", label: "Build An App",
title: "Builder's Guide" title: "Builder's Guide"
}, {
description: "Jumpstart your LBRY development with 100 LBC, on us",
destination: "/developer-program",
label: "Get Credits",
title: "Developer Program"
}]); }]);

View file

@ -9,11 +9,11 @@
"/resources/schema": "/spec#metadata", "/resources/schema": "/spec#metadata",
"/resources/signing-claim": "/resources/claim-signing", "/resources/signing-claim": "/resources/claim-signing",
"/resources/uri": "/spec#urls", "/resources/uri": "/spec#urls",
"/resources/video-lbrysdk": "https://spee.ch/967f99344308f1e90f0620d91b6c93e4dfb240e0/lbrynet-dev-setup", "/resources/video-lbryandroid": "https://odysee.com/video-2018-10-15053403:e",
"/resources/video-lbrycrd": "https://spee.ch/5803b66dca7707584b36fe6b644f278fc39d1adf/intro-to-LBRYcrd", "/resources/video-lbrycrd": "https://odysee.com/intro-to-LBRYcrd:5",
"/resources/video-lbrydesktop": "https://spee.ch/7da73fc508ffc4ff8b2711e3c3950110430b0c5f/LBRYAppDesign", "/resources/video-lbrydesktop": "https://odysee.com/LBRYAppDesign:7",
"/resources/video-lbryandroid": "https://spee.ch/e781060bc708247f07afebc02d5f75cfba8e2c4b/video-2018-10-15053403", "/resources/video-lbrysdk": "https://odysee.com/@lbrytech:1/lbrynet-dev-setup:9",
"/tour": "/playground",
"/specification": "/spec", "/specification": "/spec",
"/tour": "/playground",
"/whitepaper": "/spec" "/whitepaper": "/spec"
} }

View file

@ -1,4 +1 @@
<svg viewBox="0 0 245 240" xmlns="http://www.w3.org/2000/svg" fill="#222"> <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Discord</title><path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/></svg>
<path d="M104.4, 103.9c-5.7, 0 -10.2, 5 -10.2, 11.1c0, 6.1 4.6, 11.1 10.2, 11.1c5.7, 0 10.2, -5 10.2, -11.1c0.1, -6.1 -4.5, -11.1 -10.2, -11.1Zm36.5, 0c-5.7, 0 -10.2, 5 -10.2, 11.1c0, 6.1 4.6, 11.1 10.2, 11.1c5.7, 0 10.2, -5 10.2, -11.1c0, -6.1 -4.5, -11.1 -10.2, -11.1Z"/>
<path d="M189.5, 20l-134, 0c-11.3, 0 -20.5, 9.2 -20.5, 20.6l0, 135.2c0, 11.4 9.2, 20.6 20.5, 20.6l113.4, 0l-5.3, -18.5l12.8, 11.9l12.1, 11.2l21.5, 19l0, -179.4c0, -11.4 -9.2, -20.6 -20.5, -20.6Zm-38.6, 130.6c0, 0 -3.6, -4.3 -6.6, -8.1c13.1, -3.7 18.1, -11.9 18.1, -11.9c-4.1, 2.7 -8, 4.6 -11.5, 5.9c-5, 2.1 -9.8, 3.5 -14.5, 4.3c-9.6, 1.8 -18.4, 1.3 -25.9, -0.1c-5.7, -1.1 -10.6, -2.7 -14.7, -4.3c-2.3, -0.9 -4.8, -2 -7.3, -3.4c-0.3, -0.2 -0.6, -0.3 -0.9, -0.5c-0.2, -0.1 -0.3, -0.2 -0.4, -0.3c-1.8, -1 -2.8, -1.7 -2.8, -1.7c0, 0 4.8, 8 17.5, 11.8c-3, 3.8 -6.7, 8.3 -6.7, 8.3c-22.1, -0.7 -30.5, -15.2 -30.5, -15.2c0, -32.2 14.4, -58.3 14.4, -58.3c14.4, -10.8 28.1, -10.5 28.1, -10.5l1, 1.2c-18, 5.2 -26.3, 13.1 -26.3, 13.1c0, 0 2.2, -1.2 5.9, -2.9c10.7, -4.7 19.2, -6 22.7, -6.3c0.6, -0.1 1.1, -0.2 1.7, -0.2c6.1, -0.8 13, -1 20.2, -0.2c9.5, 1.1 19.7, 3.9 30.1, 9.6c0, 0 -7.9, -7.5 -24.9, -12.7l1.4, -1.6c0, 0 13.7, -0.3 28.1, 10.5c0, 0 14.4, 26.1 14.4, 58.3c0, 0 -8.5, 14.5 -30.6, 15.2Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -1,4 +1 @@
<svg viewBox="0 0 245 240" xmlns="http://www.w3.org/2000/svg"> <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Reddit</title><path d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/></svg>
<circle cx="122.5" cy="120" r="87.5" fill="#222"/>
<path d="M180.833, 120c0, -7.061 -5.731, -12.792 -12.792, -12.792c-3.48, 0 -6.55, 1.33 -8.801, 3.581c-8.699, -6.242 -20.775, -10.336 -34.079, -10.847l5.833, -27.325l18.933, 3.991c0.205, 4.81 4.196, 8.699 9.108, 8.699c5.015, 0 9.108, -4.094 9.108, -9.108c0, -5.015 -4.093, -9.108 -9.108, -9.108c-3.582, 0 -6.652, 2.046 -8.085, 5.117l-21.184, -4.503c-0.614, -0.103 -1.228, 0 -1.74, 0.307c-0.511, 0.307 -0.818, 0.818 -1.023, 1.432l-6.447, 30.498c-13.612, 0.409 -25.79, 4.4 -34.591, 10.847c-2.252, -2.149 -5.424, -3.581 -8.801, -3.581c-7.062, 0 -12.793, 5.731 -12.793, 12.792c0, 5.219 3.071, 9.62 7.573, 11.667c-0.204, 1.228 -0.307, 2.558 -0.307, 3.889c0, 19.649 22.822, 35.511 51.068, 35.511c28.245, 0 51.067, -15.862 51.067, -35.511c0, -1.331 -0.102, -2.559 -0.307, -3.787c4.196, -2.047 7.368, -6.55 7.368, -11.769Zm-87.5, 9.108c0, -5.014 4.094, -9.108 9.109, -9.108c5.014, 0 9.108, 4.094 9.108, 9.108c0, 5.015 -4.094, 9.108 -9.108, 9.108c-5.015, 0 -9.109, -4.093 -9.109, -9.108Zm50.863, 24.05c-6.243, 6.243 -18.114, 6.652 -21.594, 6.652c-3.479, 0 -15.453, -0.512 -21.593, -6.652c-0.921, -0.921 -0.921, -2.456 0, -3.377c0.921, -0.921 2.456, -0.921 3.377, 0c3.889, 3.889 12.281, 5.321 18.319, 5.321c6.038, 0 14.327, -1.432 18.318, -5.321c0.921, -0.921 2.457, -0.921 3.378, 0c0.716, 1.023 0.716, 2.456 -0.205, 3.377Zm-1.638, -14.942c-5.014, 0 -9.108, -4.093 -9.108, -9.108c0, -5.014 4.094, -9.108 9.108, -9.108c5.015, 0 9.109, 4.094 9.109, 9.108c0, 5.015 -4.094, 9.108 -9.109, 9.108Z" fill="#fcfcfc"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -1,65 +1,39 @@
"use strict"; /* global document, Jets, window */ "use strict"; /* global document, Jets, send, window */
// NOTE:
// We declare `contentTag` and `jets` with `var` here so
// when a visitor toggles the API page version, they are
// not incorrectly declared multiple times via `let || const`
// Initiate search functionality // Initiate search functionality
const contentTag = window.location.pathname.split("/").pop() === "sdk" ? if (!contentTag)
var contentTag;
contentTag = window.location.pathname.split("/").pop() === "sdk" ?
".api-toc__section" : ".api-toc__section" :
"#toc"; "#toc";
let jets = new Jets({ if (!jets)
var jets;
jets = new Jets({
contentTag, contentTag,
searchTag: "#input-search" searchTag: "#input-search"
}); });
// Reset search on page load
document.getElementById("input-search").value = "";
// Activate search
document.getElementById("input-search").addEventListener("keyup", () => {
if (document.getElementById("input-search").value)
document.querySelector(".api-toc__search-clear").classList.add("active");
else
document.querySelector(".api-toc__search-clear").classList.remove("active");
});
// Cancel search
document.querySelector(".api-toc__search-clear").addEventListener("click", () => {
document.getElementById("input-search").value = "";
document.querySelector(".api-toc__search-clear").classList.remove("active");
jets.destroy();
reinitJets();
});
// Handle menu toggle for mobile
if (document.getElementById("toggle-menu")) {
document.getElementById("toggle-menu").addEventListener("click", () => {
document.querySelector("body").classList.toggle("disable-scrolling");
document.querySelector(".api-toc").classList.toggle("active");
});
// Handle menu toggle when clicking on commands
document.querySelectorAll(".api-toc__command a").forEach(command => {
command.addEventListener("click", () => {
document.querySelector("body").classList.remove("disable-scrolling");
document.querySelector(".api-toc").classList.remove("active");
});
});
}
// Code toggles
handleApiLanguageToggles("cli");
handleApiLanguageToggles("curl");
handleApiLanguageToggles("lbrynet");
handleApiLanguageToggles("python");
// H E L P E R S // H E L P E R S
function changeDocumentationVersion(desiredVersion) { // eslint-disable-line no-unused-vars
send({
message: "view different documentation version",
version: desiredVersion
});
}
function handleApiLanguageToggles(language) { function handleApiLanguageToggles(language) {
if (!document.getElementById(`toggle-${language}`)) if (!document.getElementById(`toggle-${language}`))
return; return;
@ -77,6 +51,59 @@ function handleApiLanguageToggles(language) {
}); });
} }
function initializeApiFunctionality() { // eslint-disable-line no-unused-vars
// Reset search on page load
document.getElementById("input-search").value = "";
// Activate search
document.getElementById("input-search").addEventListener("keyup", () => {
if (document.getElementById("input-search").value)
document.querySelector(".api-toc__search-clear").classList.add("active");
else
document.querySelector(".api-toc__search-clear").classList.remove("active");
});
// Cancel search
document.querySelector(".api-toc__search-clear").addEventListener("click", () => {
document.getElementById("input-search").value = "";
document.querySelector(".api-toc__search-clear").classList.remove("active");
jets.destroy();
reinitJets();
});
// Handle menu toggle for mobile
if (document.getElementById("toggle-menu")) {
document.getElementById("toggle-menu").addEventListener("click", () => {
document.querySelector("body").classList.toggle("disable-scrolling");
document.querySelector(".api-toc").classList.toggle("active");
});
// Handle menu toggle when clicking on commands
document.querySelectorAll(".api-toc__command a").forEach(command => {
command.addEventListener("click", () => {
document.querySelector("body").classList.remove("disable-scrolling");
document.querySelector(".api-toc").classList.remove("active");
});
});
}
// Code toggles
handleApiLanguageToggles("cli");
handleApiLanguageToggles("curl");
handleApiLanguageToggles("lbrynet");
handleApiLanguageToggles("python");
// Ensure version selector shows correct version, even on page reloads
const currentValue = document.querySelector(".api-content__body h2").textContent.split(/\s/g).pop();
const { children } = document.querySelector(".api-toc__select");
for (const child of children) {
if (currentValue === child.text)
document.querySelector(".api-toc__select").selectedIndex = child.index;
}
}
function reinitJets() { function reinitJets() {
jets = new Jets({ jets = new Jets({
contentTag, contentTag,

View file

@ -4,6 +4,7 @@
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
scrollToElementOnLoad(); scrollToElementOnLoad();
initializeSmoothScroll();
// Automatically open external links in new tabs // Automatically open external links in new tabs
document.querySelectorAll("a[href^=http]").forEach(anchor => { document.querySelectorAll("a[href^=http]").forEach(anchor => {
@ -39,25 +40,27 @@ if (
// Smooth scroll function initializeSmoothScroll() {
document.querySelectorAll("a[href^='#']").forEach(anchor => { // Smooth scroll
if (anchor.classList.contains("no-smooth")) // Ignore smooth scroll functionality document.querySelectorAll("a[href^='#']").forEach(anchor => {
return; if (anchor.classList.contains("no-smooth")) // Ignore smooth scroll functionality
return;
anchor.addEventListener("click", event => { anchor.addEventListener("click", event => {
event.preventDefault(); event.preventDefault();
const element = event.target.href.split("#").pop() const element = event.target.href.split("#").pop()
.toLowerCase(); .toLowerCase();
let elementOffset; let elementOffset;
if (document.getElementById(element)) { if (document.getElementById(element)) {
elementOffset = document.getElementById(element).offsetTop - 150; elementOffset = document.getElementById(element).offsetTop - 150;
window.scroll({ top: elementOffset, behavior: "smooth" }); window.scroll({ top: elementOffset, behavior: "smooth" });
history.pushState({}, "", `#${element}`); // Add hash to URL bar history.pushState({}, "", `#${element}`); // Add hash to URL bar
} }
});
}); });
}); }
// Newsletter // Newsletter
document.getElementById("emailAddress").addEventListener("keyup", event => { document.getElementById("emailAddress").addEventListener("keyup", event => {
@ -88,6 +91,20 @@ document.querySelector("[data-action='subscribe to newsletter']").onclick = () =
// H E L P E R S // H E L P E R S
function runScriptsInDynamicallyInsertedHTML(element, elementHTML) { // eslint-disable-line no-unused-vars
element.innerHTML = elementHTML;
Array.from(element.querySelectorAll("script")).forEach(oldScript => {
const newScript = document.createElement("script");
Array.from(oldScript.attributes)
.forEach(attr => newScript.setAttribute(attr.name, attr.value));
newScript.appendChild(document.createTextNode(oldScript.innerHTML));
oldScript.parentNode.replaceChild(newScript, oldScript);
});
}
function scrollToElementOnLoad() { function scrollToElementOnLoad() {
if (window.location.href.includes("#")) { if (window.location.href.includes("#")) {
setTimeout(() => { // give page time to breathe setTimeout(() => { // give page time to breathe

View file

@ -1,4 +1,4 @@
"use strict"; /* global document, location, WebSocket, window */ "use strict"; /* global document, initializeSmoothScroll, location, runScriptsInDynamicallyInsertedHTML, WebSocket, window */
@ -44,6 +44,26 @@ function initializeWebSocketConnection() {
window.location.href = data.url; window.location.href = data.url;
break; break;
case data.message === "replace html":
// create placeholder
var placeholder = document.createElement("div");
placeholder.setAttribute("id", "__placeholder"); // eslint-disable-line padding-line-between-statements
document.querySelector(data.selector).insertAdjacentElement("afterend", placeholder);
// remove original element
document.querySelector(data.selector).remove();
// add new element and remove placeholder
document.getElementById("__placeholder").insertAdjacentHTML("afterend", data.html);
document.getElementById("__placeholder").remove();
// make our scripts work
runScriptsInDynamicallyInsertedHTML(document.querySelector(data.selector), document.querySelector(data.selector).innerHTML);
// make smooth scroll work on our new content
initializeSmoothScroll();
break;
case data.message === "show result": case data.message === "show result":
if (!data.example) if (!data.example)
return; return;

View file

@ -13,6 +13,8 @@ import stringifyObject from "stringify-object";
import messageSlack from "./slack"; import messageSlack from "./slack";
import publishMeme from "./publish-meme"; import publishMeme from "./publish-meme";
import lbrytvAPI from "~helper/lbrytv-sdk";
import randomString from "./random-string"; import randomString from "./random-string";
import { send } from "~socket"; import { send } from "~socket";
import uploadImage from "./upload-image"; import uploadImage from "./upload-image";
@ -55,10 +57,10 @@ export default async(data, socket) => {
let dataDetails = ""; let dataDetails = "";
let explorerNotice = ""; let explorerNotice = "";
if (data.example === 1 && !data.claim || !data.method) return; if (data.example === 1 && (!data.claim || !data.method)) return;
if (data.example === 2 && !data.data) return; if (data.example === 2 && !data.data) return;
if (data.example === 2) dataDetails = data.data; // file upload if (data.example === 2) dataDetails = data.data; // file upload
if (data.example === 3 && !data.claim || !data.method) return; if (data.example === 3 && (!data.claim || !data.method)) return;
const claimAddress = data.claim; const claimAddress = data.claim;
const resolveMethod = data.method; const resolveMethod = data.method;
@ -76,10 +78,10 @@ export default async(data, socket) => {
switch(true) { switch(resolveMethod) {
// T I P // T I P
// E X A M P L E // E X A M P L E
case resolveMethod === "support_create": case "support_create":
if (!approvedContentIdsForTipping.includes(claimAddress)) { if (!approvedContentIdsForTipping.includes(claimAddress)) {
return send(socket, { return send(socket, {
example: data.example, example: data.example,
@ -103,7 +105,7 @@ export default async(data, socket) => {
// P U B L I S H // P U B L I S H
// E X A M P L E // E X A M P L E
case resolveMethod === "publish": case "publish":
apiRequestMethod = "PUT"; apiRequestMethod = "PUT";
// Required for publishing // Required for publishing
@ -155,9 +157,7 @@ export default async(data, socket) => {
message: "show result", message: "show result",
selector: `#example${data.example}-result` selector: `#example${data.example}-result`
}); });
} } catch(memePublishError) {
catch(memePublishError) {
send(socket, { send(socket, {
details: "Meme publish failed", details: "Meme publish failed",
message: "notification", message: "notification",
@ -174,9 +174,7 @@ export default async(data, socket) => {
return; return;
} }
} } catch(imageUploadError) {
catch(imageUploadError) {
send(socket, { send(socket, {
details: "Image upload failed", details: "Image upload failed",
message: "notification", message: "notification",
@ -198,10 +196,36 @@ export default async(data, socket) => {
// R E S O L V E // R E S O L V E
// E X A M P L E // E X A M P L E
case resolveMethod === "resolve": case "resolve":
apiRequestMethod = "GET"; apiRequestMethod = "GET";
body.uri = claimAddress; body.uri = claimAddress;
try {
const resolveResponse = await lbrytvAPI.resolve([claimAddress]);
if (socket) {
const renderedCode = prism.highlight(
stringifyObject(resolveResponse, { indent: " ", singleQuotes: false }),
prism.languages.json,
"json"
);
return send(socket, {
example: data.example,
html: raw(`
<h3>Response</h3>
${explorerNotice}
<pre><code class="language-json">${renderedCode}</code></pre>
`),
message: "show result",
selector: `#example${data.example}-result`
});
}
} catch(error) {
messageSlack({
message: "```" + error + "```",
title: "DAEMON ERROR: resolve"
});
}
break; break;
@ -258,10 +282,13 @@ export default async(data, socket) => {
}); });
} }
return response.body.result[Object.keys(response.body.result)[0]].claim; // console.log("——");
} // console.log(response.body.result[Object.keys(response.body.result)[0]]);
// console.log("——");
catch(error) { return response.body.result[Object.keys(response.body.result)[0]];
} catch(error) {
console.error(error);
messageSlack({ messageSlack({
message: "```" + error + "```", message: "```" + error + "```",
pretext: "_Someone is going through the Playground and the daemon is not running_", pretext: "_Someone is going through the Playground and the daemon is not running_",

View file

@ -16,16 +16,6 @@ import relativeDate from "~module/relative-date";
let octokit; let octokit;
String.prototype.escape = function() {
const tagsToReplace = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;"
};
return this.replace(/[&<>]/g, tag => tagsToReplace[tag] || tag);
};
// R E D I S // R E D I S
let client; let client;
@ -142,7 +132,7 @@ function generateEvent(event) {
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
title="View this comment on GitHub" title="View this comment on GitHub"
>${event.payload.issue.title.escape()}</a></em> in >${escapeSpecialCharacters(event.payload.issue.title)}</a></em> in
`; `;
} else { } else {
return ` return `
@ -153,7 +143,7 @@ function generateEvent(event) {
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
title="View this comment on GitHub" title="View this comment on GitHub"
>${event.payload.issue.title.escape()}</a></em> in >${escapeSpecialCharacters(event.payload.issue.title)}</a></em> in
`; `;
} }
@ -171,7 +161,7 @@ function generateEvent(event) {
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
title="View this issue on GitHub" title="View this issue on GitHub"
>${event.payload.issue.title.escape()}</a></em> in >${escapeSpecialCharacters(event.payload.issue.title)}</a></em> in
`; `;
case "PullRequestEvent": case "PullRequestEvent":
@ -188,7 +178,24 @@ function generateEvent(event) {
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
title="View this pull request on GitHub" title="View this pull request on GitHub"
>${event.payload.pull_request.title.escape()}</a></em> in >${escapeSpecialCharacters(event.payload.pull_request.title)}</a></em> in
`;
case "PullRequestReviewEvent":
return `
<strong><a
href="${generateUrl("actor", event)}"
rel="noopener noreferrer"
target="_blank"
title="Visit ${event.actor.login}'s profile on GitHub"
>${event.actor.display_login}</a></strong> reviewed pull request
<em><a
href="${generateUrl("pull_request", event)}"
rel="noopener noreferrer"
target="_blank"
title="View this review on GitHub"
>${escapeSpecialCharacters(event.payload.pull_request.title)}</a></em> in
`; `;
case "PullRequestReviewCommentEvent": case "PullRequestReviewCommentEvent":
@ -205,7 +212,7 @@ function generateEvent(event) {
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
title="View this comment on GitHub" title="View this comment on GitHub"
>${event.payload.pull_request.title.escape()}</a></em> in >${escapeSpecialCharacters(event.payload.pull_request.title)}</a></em> in
`; `;
case "PushEvent": case "PushEvent":
@ -346,6 +353,9 @@ function updateGithubFeed() {
const eventString = JSON.stringify(item); const eventString = JSON.stringify(item);
client.zrank("events", eventString, (err, reply) => { client.zrank("events", eventString, (err, reply) => {
if (err)
return;
if (reply === null) if (reply === null)
client.zadd("events", item.id, eventString, callback); client.zadd("events", item.id, eventString, callback);
else else
@ -366,6 +376,16 @@ function updateGithubFeed() {
// H E L P E R // H E L P E R
function escapeSpecialCharacters(contentToEscape) {
const tagsToReplace = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;"
};
return contentToEscape.replace(/[&<>]/g, tag => tagsToReplace[tag] || tag);
}
function refToBranch(ref) { function refToBranch(ref) {
if (ref) if (ref)
return ref.replace("refs/heads/", ""); return ref.replace("refs/heads/", "");

113
app/helpers/lbrytv-sdk.js Normal file
View file

@ -0,0 +1,113 @@
"use strict";
import messageSlack from "./slack";
const request = require("request");
const addSupport = function() {};
const publish = function() {};
const resolve = function(urls) {
return new Promise(function(resolve, reject) {
const options = {
method: "POST",
url: "https://api.na-backend.odysee.com/api/v1/proxy",
headers:
{
"Content-Type": "application/json"
},
body: {
method: "resolve",
params: { urls: urls }
},
json: true
};
request(options, function(error, response, daemonResponse) {
if (error) {
messageSlack({
message: "```" + error + "```",
title: "DAEMON ERROR: resolve"
});
return reject(new Error("DAEMON ERROR: resolve"));
}
if (Object.prototype.hasOwnProperty.call(daemonResponse, "error")) {
messageSlack({
message: "```" + daemonResponse.error + "```",
title: "DAEMON ERROR: resolve"
});
return reject(new Error("DAEMON ERROR: resolve"));
} else
return resolve(daemonResponse.result);
});
});
};
const getTrending = function() {
return new Promise(function(resolve, reject) {
const options = {
method: "POST",
url: "https://api.na-backend.odysee.com/api/v1/proxy",
headers:
{
"Content-Type": "application/json"
},
body:
{
method: "claim_search",
params:
{
page_size: 20,
page: 1,
no_totals: true,
any_tags:
["art",
"automotive",
"blockchain",
"comedy",
"economics",
"education",
"gaming",
"music",
"news",
"science",
"sports",
"technology"],
channel_ids: [],
not_channel_ids: [],
not_tags: ["porn", "porno", "nsfw", "mature", "xxx", "sex", "creampie", "blowjob", "handjob", "vagina", "boobs", "big boobs", "big dick", "pussy", "cumshot", "anal", "hard fucking", "ass", "fuck", "hentai"],
order_by: ["trending_group", "trending_mixed"]
}
},
json: true
};
request(options, function(error, response, daemonResponse) {
if (error) {
messageSlack({
message: "```" + error + "```",
title: "DAEMON ERROR: trending"
});
return reject(new Error("DAEMON ERROR: trending"));
}
if (Object.prototype.hasOwnProperty.call(daemonResponse, "error")) {
messageSlack({
message: "```" + daemonResponse.error + "```",
title: "DAEMON ERROR: trending"
});
return reject(JSON.stringify(daemonResponse));
} else
return resolve(daemonResponse.result.items);
});
});
};
export default {
addSupport,
publish,
resolve,
getTrending
};

View file

@ -4,7 +4,7 @@
// P A C K A G E S // P A C K A G E S
import color from "colorette"; import * as color from "colorette";
import compress from "fastify-compress"; import compress from "fastify-compress";
import cors from "cors"; import cors from "cors";
import fastify from "fastify"; import fastify from "fastify";
@ -22,7 +22,20 @@ import redirects from "~data/redirects.json";
const server = fastify({ const server = fastify({
logger: { logger: {
level: "warn", level: "warn",
prettyPrint: process.env.NODE_ENV === "development" ? true : false prettyPrint: process.env.NODE_ENV === "development",
redact: ["req.headers.authorization"],
serializers: {
req(req) {
return {
headers: req.headers,
hostname: req.hostname,
method: req.method,
remoteAddress: req.ip,
remotePort: req.connection.remotePort,
url: req.url
};
}
}
} }
}); });

View file

@ -16,16 +16,20 @@ function superscript(state, silent) {
const max = state.posMax; const max = state.posMax;
const start = state.pos; const start = state.pos;
let found; let found;
let content;
let token; let token;
if (state.src.charCodeAt(start) !== 0x5E/* ^ */) return false; if (state.src.charCodeAt(start) !== 0x5E/* ^ */)
if (silent) return false; // do not run pairs in validation mode return false;
if (start + 2 >= max) return false;
if (silent)
return false; // do not run pairs in validation mode
if (start + 2 >= max)
return false;
state.pos = start + 1; state.pos = start + 1;
while (state.pos < max) { while(state.pos < max) {
if (state.src.charCodeAt(state.pos) === 0x5E/* ^ */) { if (state.src.charCodeAt(state.pos) === 0x5E/* ^ */) {
found = true; found = true;
break; break;
@ -39,7 +43,7 @@ function superscript(state, silent) {
return false; return false;
} }
content = state.src.slice(start + 1, state.pos); const content = state.src.slice(start + 1, state.pos);
// do not allow unescaped spaces/newlines inside // do not allow unescaped spaces/newlines inside
if (content.match(/(^|[^\\])(\\\\)*\s/)) { if (content.match(/(^|[^\\])(\\\\)*\s/)) {
@ -59,16 +63,14 @@ function superscript(state, silent) {
if (content.match(regexForIds)) { if (content.match(regexForIds)) {
const theLink = supText.match(regexForIds)[0].replace("(#", "").replace(")", ""); const theLink = supText.match(regexForIds)[0].replace("(#", "").replace(")", "");
token.attrPush(["id", theLink]); // eslint-disable-line padding-line-between-statements
token.attrPush([ "id", theLink ]);
} }
token = state.push("text", "", 0); token = state.push("text", "", 0);
if (content.match(regexForIds)) { if (content.match(regexForIds)) {
const theText = supText.match(regexForTextBeforeLink)[0]; const theText = supText.match(regexForTextBeforeLink)[0];
token.content = theText; // eslint-disable-line padding-line-between-statements
token.content = theText;
} else token.content = supText; } else token.content = supText;
token = state.push("sup_close", "sup", -1); token = state.push("sup_close", "sup", -1);
@ -84,6 +86,6 @@ function superscript(state, silent) {
// E X P O R T // E X P O R T
module.exports = exports = function sup_plugin(md) { module.exports = exports = function sup_plugin(md) { // eslint-disable-line camelcase
md.inline.ruler.after("emphasis", "sup", superscript); md.inline.ruler.after("emphasis", "sup", superscript);
}; };

View file

@ -4,7 +4,7 @@
// P R O G R A M // P R O G R A M
const relativeDate = (undefined => { const relativeDate = (() => {
const SECOND = 1000; const SECOND = 1000;
const MINUTE = 60 * SECOND; const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE; const HOUR = 60 * MINUTE;
@ -14,23 +14,23 @@ const relativeDate = (undefined => {
const MONTH = YEAR / 12; const MONTH = YEAR / 12;
const formats = [ const formats = [
[ 0.7 * MINUTE, "just now" ], [0.7 * MINUTE, "just now"],
[ 1.5 * MINUTE, "a minute ago" ], [1.5 * MINUTE, "a minute ago"],
[ 60 * MINUTE, "minutes ago", MINUTE ], [60 * MINUTE, "minutes ago", MINUTE],
[ 1.5 * HOUR, "an hour ago" ], [1.5 * HOUR, "an hour ago"],
[ DAY, "hours ago", HOUR ], [DAY, "hours ago", HOUR],
[ 2 * DAY, "yesterday" ], [2 * DAY, "yesterday"],
[ 7 * DAY, "days ago", DAY ], [7 * DAY, "days ago", DAY],
[ 1.5 * WEEK, "a week ago" ], [1.5 * WEEK, "a week ago"],
[ MONTH, "weeks ago", WEEK ], [MONTH, "weeks ago", WEEK],
[ 1.5 * MONTH, "a month ago" ], [1.5 * MONTH, "a month ago"],
[ YEAR, "months ago", MONTH ], [YEAR, "months ago", MONTH],
[ 1.5 * YEAR, "a year ago" ], [1.5 * YEAR, "a year ago"],
[ Number.MAX_VALUE, "years ago", YEAR ] [Number.MAX_VALUE, "years ago", YEAR]
]; ];
function relativeDate(input, reference) { function relativeDate(input, reference) {
!reference && (reference = (new Date).getTime()); !reference && (reference = (new Date()).getTime());
reference instanceof Date && (reference = reference.getTime()); reference instanceof Date && (reference = reference.getTime());
input instanceof Date && (input = input.getTime()); input instanceof Date && (input = input.getTime());
@ -40,9 +40,8 @@ const relativeDate = (undefined => {
for (let i = -1; ++i < len;) { for (let i = -1; ++i < len;) {
const format = formats[i]; const format = formats[i];
if (delta < format[0]) { if (delta < format[0])
return format[2] === undefined ? format[1] : Math.round(delta / format[2]) + " " + format[1]; return format[2] === undefined ? format[1] : Math.round(delta / format[2]) + " " + format[1];
}
} }
} }
@ -53,6 +52,5 @@ const relativeDate = (undefined => {
// E X P O R T // E X P O R T
if (typeof module !== "undefined" && module.exports) { if (typeof module !== "undefined" && module.exports)
module.exports = exports = relativeDate; module.exports = exports = relativeDate;
}

View file

@ -55,15 +55,27 @@
} }
} }
.api-toc__select,
.api-toc__search-field {
width: 100%;
border-top: none;
border-right: none;
border-bottom: 1px solid $lbry-gray-1;
border-left: none;
}
.api-toc__select {
background-position-x: 95%;
}
.api-toc__search { .api-toc__search {
position: relative; position: relative;
} }
.api-toc__search-field { .api-toc__search-field {
width: 100%;
padding: 0.25rem calc(2rem + 4px) 0.25rem 0.75rem; padding: 0.25rem calc(2rem + 4px) 0.25rem 0.75rem;
border-bottom: 1px solid $lbry-gray-1;
border-radius: 0; // TODO: Put this rule in components on inputs border-radius: 0; // TODO: Put this rule in components on inputs
font-size: 0.8rem; font-size: 0.8rem;
line-height: 2rem; line-height: 2rem;

View file

@ -3,6 +3,21 @@ developer-program {
input-submit { input-submit {
padding-top: 0.5rem; padding-top: 0.5rem;
button {
color: $lbry-white;
padding-right: 1.5rem;
padding-left: 1.5rem;
transition: background-color 0.2s;
&:not(:hover) {
background-color: $lbry-black;
}
&:hover {
background-color: $lbry-teal-4;
}
}
} }
.button { .button {

View file

@ -265,6 +265,7 @@
} }
.playground-content__urlbar { .playground-content__urlbar {
height: 2.5rem;
border: 1px solid $lbry-gray-1; border: 1px solid $lbry-gray-1;
display: flex; display: flex;
margin-bottom: 1rem; margin-bottom: 1rem;
@ -289,6 +290,7 @@
input { input {
width: calc(100% - 9.5rem); width: calc(100% - 9.5rem);
border: none;
font-size: 1rem; font-size: 1rem;
&::placeholder { &::placeholder {
@ -299,12 +301,12 @@
span { span {
@include no-user-select; @include no-user-select;
width: 3.5rem; width: 3.5rem; height: 2.5rem;
color: $lbry-gray-4; color: $lbry-gray-4;
cursor: default; cursor: default;
font-size: 1rem; font-size: 1rem;
line-height: 2rem; line-height: 2.4;
text-align: right; text-align: right;
} }
} }

View file

@ -9,9 +9,12 @@ import html from "choo/html";
// U T I L S // U T I L S
import apiPage from "~view/api";
import fetchMetadata from "~helper/fetch-metadata"; import fetchMetadata from "~helper/fetch-metadata";
import lbrytvAPI from "~helper/lbrytv-sdk";
import { generateGitHubFeed } from "~helper/github"; import { generateGitHubFeed } from "~helper/github";
import messageSlack from "~helper/slack"; import messageSlack from "~helper/slack";
import { URL } from "url";
const githubAppId = process.env.GITHUB_APP_ID; const githubAppId = process.env.GITHUB_APP_ID;
const githubAppSecret = process.env.GITHUB_APP_SECRET; const githubAppSecret = process.env.GITHUB_APP_SECRET;
@ -23,7 +26,7 @@ const githubAppSecret = process.env.GITHUB_APP_SECRET;
// P R O G R A M // P R O G R A M
export default (socket, action) => { export default async(socket, action) => {
if (typeof socket !== "object" && typeof action !== "object") if (typeof socket !== "object" && typeof action !== "object")
return; return;
@ -88,6 +91,22 @@ export default (socket, action) => {
newsletterSubscribe(action, socket); newsletterSubscribe(action, socket);
break; break;
case action.message === "view different documentation version":
send(socket, {
element: "div",
html: await apiPage({
params: {
wildcard: action.version.split("-")[0]
},
tag: action.version.split("-")[1]
}),
message: "replace html",
parentElement: "main",
selector: ".__slate"
});
break;
default: default:
break; break;
} }
@ -99,56 +118,56 @@ export default (socket, action) => {
function generateContent(exampleNumber, displayTrendingContent) { function generateContent(exampleNumber, displayTrendingContent) {
if (exampleNumber === 1) { if (exampleNumber === 1) {
return getTrendingContent().then(response => { return lbrytvAPI.getTrending()
if (!response || !response.success || response.success !== true || !response.data) .then(response => {
return ""; const renderedContentCollection = [];
const urlsToResolve = [];
const rawContentCollection = []; response.forEach(r => {
const renderedContentCollection = []; urlsToResolve.push(r.canonical_url);
const trendingContentData = response.data; });
lbrytvAPI.resolve(urlsToResolve)
.then(resolveResponse => {
if (resolveResponse !== null) {
const responses = Object.values(resolveResponse);
for (const data of trendingContentData) for (const r in responses) {
rawContentCollection.push(fetchMetadata({ const part = responses[r];
claim: data.url,
example: exampleNumber,
method: "resolve"
}));
Promise.all(rawContentCollection).then(collection => { if (part.value && part.value.thumbnail.url) {
for (const part of collection) { renderedContentCollection.push(`
try { <section class="playground-content__trend">
<figure
class="media__thumb"
data-action="choose claim"
data-claim-id="${part.claim_id}"
data-name=${part.name}
style="background-image: url(${makeImageSourceSecure(part.value.thumbnail.url)})">
</figure>
<div class="media__title">
${part.value.title || "Untitled"}
</div>
<div class="media__subtitle">
${part.signing_channel ? part.signing_channel.name : "Anon"}
</div>
</section>
`);
}
}
}
renderedContentCollection.push(` renderedContentCollection.push(`
<section class="playground-content__trend"> <script>
<figure document.getElementById("playground-example-description").innerHTML = document.querySelector("[data-action='playground, example 1']").dataset.description
class="media__thumb" </script>
data-action="choose claim" `);
data-claim-id="${part.name}" displayTrendingContent(renderedContentCollection.join(""));
${part.value.thumbnail.url.length ? `style="background-image: url(${makeImageSourceSecure(part.value.thumbnail.url)})"` : ""} })
></figure> .catch(error => {
console.error(error);
<div class="media__title"> });
${part.value.title}
</div>
<div class="media__subtitle">
${part.channel_name}
</div>
</section>
`);
} catch(err) {
return; // TODO: Return nice error message
}
}
renderedContentCollection.push(`
<script>
document.getElementById("playground-example-description").innerHTML = document.querySelector("[data-action='playground, example 1']").dataset.description
</script>
`);
displayTrendingContent(renderedContentCollection.join(""));
}); });
});
} }
if (exampleNumber === 3) { if (exampleNumber === 3) {
@ -164,51 +183,49 @@ function generateContent(exampleNumber, displayTrendingContent) {
"minecraft-in-real-life-iron-man#758dd6497cdfc401ae1f25984738d024d47b50af", "minecraft-in-real-life-iron-man#758dd6497cdfc401ae1f25984738d024d47b50af",
"ethan-shows-kyle-warframe-skyvault#8a7401b88d5ed0376d98f16808194d4dcb05b284" "ethan-shows-kyle-warframe-skyvault#8a7401b88d5ed0376d98f16808194d4dcb05b284"
]; ];
const rawContentCollection = [];
const renderedContentCollection = []; const renderedContentCollection = [];
for (const url of approvedUrls) lbrytvAPI.resolve(approvedUrls)
rawContentCollection.push(fetchMetadata({ claim: url, method: "resolve", example: 1 })); .then(resolveResponse => {
if (resolveResponse !== null) {
const responses = Object.values(resolveResponse);
return Promise.all(rawContentCollection).then(collection => { for (const r in responses) {
for (const part of collection) { const part = responses[r];
if (
part &&
part.value &&
part.value.thumbnail.url &&
part.channel_name
) {
renderedContentCollection.push(`
<section class="playground-content__trend">
<figure
class="media__thumb"
data-action="choose claim"
data-claim-id="${part.claim_id}"
data-name=${part.name}
style="background-image: url(${makeImageSourceSecure(part.value.thumbnail.url)})">
</figure>
<div class="media__title"> if (part.value && part.value.thumbnail.url) {
${part.value.title} renderedContentCollection.push(`
</div> <section class="playground-content__trend">
<figure
<div class="media__subtitle"> class="media__thumb"
${part.channel_name} data-action="choose claim"
</div> data-claim-id="${part.claim_id}"
</section> data-name=${part.name}
`); style="background-image: url(${makeImageSourceSecure(part.value.thumbnail.url)})">
</figure>
<div class="media__title">
${part.value.title || "Untitled"}
</div>
<div class="media__subtitle">
${part.signing_channel ? part.signing_channel.name : "Anon"}
</div>
</section>
`);
}
}
} }
} renderedContentCollection.push(`
<script>
renderedContentCollection.push(` document.getElementById("playground-example-description").innerHTML = document.querySelector("[data-action='playground, example 3']").dataset.description
<script> </script>
document.getElementById("playground-example-description").innerHTML = document.querySelector("[data-action='playground, example 3']").dataset.description `);
</script> displayTrendingContent(renderedContentCollection.join(""));
`); })
.catch(error => {
displayTrendingContent(renderedContentCollection.join("")); console.error(error);
}); });
} }
} }
@ -349,15 +366,6 @@ function getGitHubUserToken(socket) {
}); });
} }
async function getTrendingContent() {
try {
const response = await got("https://api.lbry.com/file/list_trending");
return JSON.parse(response.body); // eslint-disable-line padding-line-between-statements
} catch(error) {
return error;
}
}
function makeImageSourceSecure(url) { function makeImageSourceSecure(url) {
if (!url || !url.length) if (!url || !url.length)
return url; return url;
@ -434,7 +442,7 @@ async function verifyGitHubToken(data, socket) {
const code = data.code; const code = data.code;
try { try {
let result = await got.post(`https://github.com/login/oauth/access_token?client_id=${githubAppId}&client_secret=${githubAppSecret}&code=${code}`, { json: true }); const result = await got.post(`https://github.com/login/oauth/access_token?client_id=${githubAppId}&client_secret=${githubAppSecret}&code=${code}`, { json: true });
const response = { const response = {
address: data.address, address: data.address,

View file

@ -7,6 +7,7 @@
import asyncHtml from "choo-async/html"; import asyncHtml from "choo-async/html";
import dedent from "dedent"; import dedent from "dedent";
import got from "got"; import got from "got";
import Octokit from "@octokit/rest";
// U T I L S // U T I L S
@ -14,31 +15,45 @@ import headerBlockchain from "~component/api/header-blockchain";
import headerSdk from "~component/api/header-sdk"; import headerSdk from "~component/api/header-sdk";
import redirects from "~data/redirects.json"; import redirects from "~data/redirects.json";
const blockchainApi = "https://raw.githubusercontent.com/lbryio/lbrycrd/master/contrib/devtools/generated/api_v1.json";
const cache = new Map(); const cache = new Map();
const sdkApi = "https://raw.githubusercontent.com/lbryio/lbry/master/docs/api.json"; const filePathBlockchain = "/contrib/devtools/generated/api_v1.json";
const filePathSdk = "/docs/api.json";
const rawGitHubBase = "https://raw.githubusercontent.com/lbryio/";
const octokit = new Octokit({
auth: `token ${process.env.GITHUB_OAUTH_TOKEN}`
});
// E X P O R T // E X P O R T
export default async(state) => { export default async(state) => {
// below is evil, I just inherited it -- Jeremy const { tag } = state;
const apilabel = state.params.wildcard === "sdk" ? const { wildcard } = state.params;
"SDK" :
state.params.wildcard.charAt(0).toLocaleUpperCase() + state.params.wildcard.substring(1); const repository = wildcard === "sdk" ?
"lbry-sdk" :
"lbrycrd";
state.lbry = { state.lbry = {
title: apilabel + " API Documentation", title: tag ? tag + " API Documentation" : "API Documentation",
description: "See API documentation, signatures, and sample calls for the LBRY " + apilabel + " APIs." description: "See API documentation, signatures, and sample calls for the LBRY APIs."
}; };
const tags = await getTags(repository);
const currentTag = tag && tag.length ? tag : tags[0];
try { try {
const apiResponse = await parseApiFile(state.params.wildcard); const apiResponse = await parseApiFile({ repo: repository, tag: currentTag });
return asyncHtml` return asyncHtml`
<div class="__slate"> <div class="__slate">
<aside class="api-toc"> <aside class="api-toc">
<select class="api-toc__select" onchange="changeDocumentationVersion(value);">
${renderVersionSelector(wildcard, tags, tag)}
</select>
<div class="api-toc__search"> <div class="api-toc__search">
<input class="api-toc__search-field" id="input-search" placeholder="Search" type="search"/> <input class="api-toc__search-field" id="input-search" placeholder="Search" type="search"/>
<div class="api-toc__search-clear" id="clear-search" title="Clear search query">&times;</div> <div class="api-toc__search-clear" id="clear-search" title="Clear search query">&times;</div>
@ -46,35 +61,37 @@ export default async(state) => {
</div> </div>
<ul class="api-toc__commands" id="toc" role="navigation"> <ul class="api-toc__commands" id="toc" role="navigation">
${apilabel === "SDK" ? createSdkSidebar(apiResponse) : createApiSidebar(apiResponse)} ${wildcard === "sdk" ? createSdkSidebar(apiResponse) : createApiSidebar(apiResponse)}
</ul> </ul>
</aside> </aside>
<section class="api-content"> <section class="api-content">
<div class="api-documentation" id="toc-content"> <div class="api-documentation" id="toc-content">
<div></div> <div></div>
<nav class="api-content__items"> <nav class="api-content__items">
${renderToggles(apilabel === "SDK")} ${renderCodeLanguageToggles(wildcard)}
</nav> </nav>
${createApiHeader(state.params.wildcard)} ${createApiHeader(wildcard, currentTag)}
${apilabel === "SDK" ? createSdkContent(apiResponse) : createApiContent(apiResponse)} ${wildcard === "sdk" ? createSdkContent(apiResponse) : createApiContent(apiResponse)}
</div> </div>
</section> </section>
<script src="/assets/scripts/plugins/jets.js"></script>
<script src="/assets/scripts/api.js"></script>
<script>
initializeApiFunctionality();
if (window.location.pathname === "/api/blockchain")
document.getElementById("toggle-cli").click();
else
document.getElementById("toggle-curl").click();
</script>
</div> </div>
<script src="/assets/scripts/plugins/jets.js"></script>
<script src="/assets/scripts/api.js"></script>
<script>
if (window.location.pathname === "/api/blockchain")
document.getElementById("toggle-cli").click();
else
document.getElementById("toggle-curl").click();
</script>
`; `;
} } catch(error) {
catch(error) {
const redirectUrl = redirects[state.href]; const redirectUrl = redirects[state.href];
return asyncHtml` return asyncHtml`
@ -134,13 +151,13 @@ function createApiContent(apiDetails) {
return apiContent; return apiContent;
} }
function createApiHeader(slug) { function createApiHeader(slug, apiVersion) {
switch(slug) { switch(slug) {
case "blockchain": case "blockchain":
return headerBlockchain(); return headerBlockchain(apiVersion);
case "sdk": case "sdk":
return headerSdk(); return headerSdk(apiVersion);
default: default:
break; break;
@ -220,24 +237,61 @@ function createSdkSidebar(apiDetails) {
return apiSidebar; return apiSidebar;
} }
async function parseApiFile(urlSlug) { async function getTags(repositoryName) {
let apiFileLink; const { data } = await octokit.repos.listTags({
owner: "lbryio",
repo: repositoryName
});
const tags = ["master"];
// NOTE:
// The versioning in our repos do not make sense so extra
// exclusion code is needed to make this work.
//
// Documentation is only available after specific versions.
switch(true) { switch(true) {
case (urlSlug === "blockchain"): case repositoryName === "lbry-sdk":
apiFileLink = blockchainApi; data.forEach(tag => {
if (tag.name >= "v0.52.0") tags.push(tag.name);
});
break; break;
case (urlSlug === "sdk"): case repositoryName === "lbrycrd":
apiFileLink = sdkApi; data.forEach(tag => {
if (
tag.name >= "v0.17.1.0" &&
tag.name !== "v0.3.16" &&
tag.name !== "v0.3.15" &&
tag.name !== "v0.3-osx" &&
tag.name !== "v0.2-alpha"
) tags.push(tag.name);
});
break; break;
default: default:
break; break;
} }
if (!apiFileLink) return tags;
return Promise.reject(new Error("Failed to fetch API docs")); }
async function parseApiFile({ repo, tag }) {
let apiFileLink = `${rawGitHubBase}${repo}/${tag}`;
switch(true) {
case (repo === "lbrycrd"):
apiFileLink = `${apiFileLink}${filePathBlockchain}`;
break;
case (repo === "lbry-sdk"):
apiFileLink = `${apiFileLink}${filePathSdk}`;
break;
default:
return Promise.reject(new Error("Failed to fetch API docs"));
}
const response = await got(apiFileLink, { cache, json: true }); const response = await got(apiFileLink, { cache, json: true });
@ -259,7 +313,7 @@ function renderArguments(args) {
<li class="api-content__body-argument"> <li class="api-content__body-argument">
<div class="left"> <div class="left">
<strong>${arg.name}</strong><br/> <strong>${arg.name}</strong><br/>
${arg.is_required === true ? "" : "<span>optional</span>" }<span>${arg.type}</span> ${arg.is_required === true ? "" : "<span>optional</span>"}<span>${arg.type}</span>
</div> </div>
<div class="right">${typeof arg.description === "string" ? arg.description.replace(/</g, "&lt;").replace(/>/g, "&gt;") : ""}</div> <div class="right">${typeof arg.description === "string" ? arg.description.replace(/</g, "&lt;").replace(/>/g, "&gt;") : ""}</div>
@ -307,7 +361,33 @@ function renderReturns(args) {
return returnContent; return returnContent;
} }
function renderToggles(onSdkPage) { function renderVersionSelector(pageSlug, versions, desiredTag) {
const options = [
"<option disabled>Select a version</option>"
];
let optionIndex = 0;
versions.forEach(version => {
optionIndex++;
let selectedOption = false;
if (desiredTag && desiredTag === version)
selectedOption = true;
else if (optionIndex === 1)
selectedOption = true;
options.push(
`<option value="${pageSlug}-${version}"${selectedOption ? " selected" : ""}>${version}</option>`
);
});
return options;
}
function renderCodeLanguageToggles(pageSlug) {
const onSdkPage = pageSlug === "sdk";
return [ return [
"<button class='api-content__item menu' id='toggle-menu'>menu</button>", "<button class='api-content__item menu' id='toggle-menu'>menu</button>",
!onSdkPage ? "<button class='api-content__item' id='toggle-cli' type='button'>cli</button>" : "", !onSdkPage ? "<button class='api-content__item' id='toggle-cli' type='button'>cli</button>" : "",

View file

@ -83,7 +83,7 @@ export default () => html`
<section class="community"> <section class="community">
<div class="inner-wrap"> <div class="inner-wrap">
<h3>Community</h3> <h3>Community</h3>
<p>There's literally <a href="https://spee.ch/@lbrytech/dozens.mp4">12<sup>n</sup></a> of us.</p> <p>There's literally <a href="https://lbry.tv/@lbrytech:1/dozens:e">12n</a> of us.</p>
<ul> <ul>
<li><a href="//chat.lbry.com" title="LBRY on Discord">Chat</a></li> <li><a href="//chat.lbry.com" title="LBRY on Discord">Chat</a></li>

View file

@ -37,7 +37,7 @@ export default (state, emit) => { // eslint-disable-line
const customMetadata = {}; const customMetadata = {};
for (const key in markdownFileDetails.attributes.meta) { for (const key in markdownFileDetails.attributes.meta) {
if (markdownFileDetails.attributes.meta.hasOwnProperty(key)) { if (Object.prototype.hasOwnProperty.call(markdownFileDetails.attributes.meta, key)) {
customMetadata[Object.keys(markdownFileDetails.attributes.meta[key])[0]] = customMetadata[Object.keys(markdownFileDetails.attributes.meta[key])[0]] =
markdownFileDetails.attributes.meta[key][Object.keys(markdownFileDetails.attributes.meta[key])[0]]; markdownFileDetails.attributes.meta[key][Object.keys(markdownFileDetails.attributes.meta[key])[0]];
} }

View file

@ -5,7 +5,7 @@ description: Learn how to build your own app via LBRY in this comprehensive guid
## Introduction ## Introduction
Want to build something on top of LBRY? This is the place to get started. If this is your first introduction to LBRY, you should read the [Overview](/overview) first. If you would rather build with us, check out our [Contributing Guide](/contribute). Want to build something on top of LBRY? This is the place to get started. If this is your first introduction to LBRY, you should read the [Overview](./overview.md) first. If you would rather build with us, check out our [Contributing Guide](./contribute.md).
There are exactly 1,000,006 app ideas that could work on the LBRY network, but it doesn't make sense for _everything_ to be built on it. There are exactly 1,000,006 app ideas that could work on the LBRY network, but it doesn't make sense for _everything_ to be built on it.
@ -86,7 +86,7 @@ Unfortunately, most users will want more functionality in an app than typing int
You can build many types of apps. Your app doesn't have to use Electron, nor does it have to be targeted at consumers, use a UI, or even fetch digital content at all! In this section, we'll look into the different types of apps you could build, and the different components needed to build anything you want. You can build many types of apps. Your app doesn't have to use Electron, nor does it have to be targeted at consumers, use a UI, or even fetch digital content at all! In this section, we'll look into the different types of apps you could build, and the different components needed to build anything you want.
Most applications will use the [LBRY SDK](#sdk) as a way of accessing and communicating with the LBRY network. A look at the [APIs](/api/sdk) provided by the SDK will help you understand what it can and can't do. Most applications will use the [LBRY SDK](#sdk) as a way of accessing and communicating with the LBRY network. A look at the [APIs](https://lbry.tech/api/sdk) provided by the SDK will help you understand what it can and can't do.
Some applications do not need to access content available on the network (e.g. a wallet-only app, or a blockchain visualizer). These applications might use [lbrycrd](#lbrycrd), the full-node blockchain daemon, or [chainquery](#chainquery), which parses blockchain data into SQL. Some applications do not need to access content available on the network (e.g. a wallet-only app, or a blockchain visualizer). These applications might use [lbrycrd](#lbrycrd), the full-node blockchain daemon, or [chainquery](#chainquery), which parses blockchain data into SQL.
@ -142,7 +142,7 @@ Regardless of the type of desktop app, you'll want to follow the steps for [usin
The [official LBRY desktop app](https://github.com/lbryio/lbry-desktop) is built with Electron. It is very easy to build with, and allows web developers to easily start creating "native" desktop applications. You can use a plain html document with a `<script>` tag, or build out a large web app. The official desktop app uses [React](https://reactjs.org/). The [official LBRY desktop app](https://github.com/lbryio/lbry-desktop) is built with Electron. It is very easy to build with, and allows web developers to easily start creating "native" desktop applications. You can use a plain html document with a `<script>` tag, or build out a large web app. The official desktop app uses [React](https://reactjs.org/).
If you want to write an electron app, check out the [electron-starter project](https://github.com/lbryio/electron-starter) for a bare bones setup that is very similar to how [lbry-desktop](https://github.com/lbryio/lbry-desktop) is structured. It's also a simple way to explore the [SDK API](<(https://https://lbry.tech/api/sdk)>). If you want to write an electron app, check out the [electron-starter project](https://github.com/lbryio/electron-starter) for a bare bones setup that is very similar to how [lbry-desktop](https://github.com/lbryio/lbry-desktop) is structured. It's also a simple way to explore the [SDK API](https://lbry.tech/api/sdk).
Check out [this video](https://spee.ch/6/lbry-electron-starter) for a brief overview and guide to get it running. If you just want the source code, go [here](https://github.com/lbryio/electron-starter). Or, if you really really want to see it in action _now_, just paste these commands into your terminal: Check out [this video](https://spee.ch/6/lbry-electron-starter) for a brief overview and guide to get it running. If you just want the source code, go [here](https://github.com/lbryio/electron-starter). Or, if you really really want to see it in action _now_, just paste these commands into your terminal:
@ -179,9 +179,9 @@ We do not currently have tooling available to build LBRY apps on iOS.
### SDK ### SDK
The [LBRY SDK](https://github.com/lbryio/lbry) provides an API that enables easy access to all functionality of the LBRY network. Most applications will choose to use the SDK. The [LBRY SDK](https://github.com/lbryio/lbry-sdk) provides an API that enables easy access to all functionality of the LBRY network. Most applications will choose to use the SDK.
You can download the latest version from the [releases page](https://github.com/lbryio/lbry/releases) or via the following URLs, which will always download the latest SDK for each operating system: You can download the latest version from the [releases page](https://github.com/lbryio/lbry-sdk/releases) or via the following URLs, which will always download the latest SDK for each operating system:
| OS | URL | | OS | URL |
| --- | --- | | --- | --- |
@ -195,7 +195,7 @@ Once that is downloaded, there are two steps to get it integrated into your app.
First, run `lbrynet start` in the directory you downloaded the SDK. This starts the API server and connects to the LBRY network. First, run `lbrynet start` in the directory you downloaded the SDK. This starts the API server and connects to the LBRY network.
Then, use an API wrapper to talk to the SDK or write your own. There are a number of simple [api wrappers](https://lbry.tech/resources/api-wrappers) available in several different languages, created by LBRY community members! These allow you to easily send commands to the SDK in the language of your choice. Then, use an API wrapper to talk to the SDK or write your own. There are a number of simple [API wrappers](https://lbry.tech/resources/api-wrappers) available in several different languages, created by LBRY community members! These allow you to easily send commands to the SDK in the language of your choice.
If a wrapper for the language you would like to use doesn't exist, it is still fairly easy to interact with. The SDK provides a JSON-RPC server at `localhost:5279` for interaction. You can call it via `cURL` or the HTTP functionality provided by the language you are using. You can look at an existing wrapper in another language for more detail. If a wrapper for the language you would like to use doesn't exist, it is still fairly easy to interact with. The SDK provides a JSON-RPC server at `localhost:5279` for interaction. You can call it via `cURL` or the HTTP functionality provided by the language you are using. You can look at an existing wrapper in another language for more detail.

View file

@ -22,31 +22,29 @@ If you want to contribute to LBRY, there's definitely something for you! The fir
| Component | Language (Toolset) | What Is It | Intro Video | Component | Language (Toolset) | What Is It | Intro Video
--- | --- | --- | --- --- | --- | --- | ---
| [lbrycrd](https://github.com/lbryio/lbrycrd) | C++ | A full node for the LBRY blockchain, including a standalone wallet. Used by miners and some applications. Most consumer applications do not bundle [[lbrycrd]] directly, and instead bundle [[lbry-sdk]]. | [Video](/resources/video-lbrycrd) | [lbrycrd](https://github.com/lbryio/lbrycrd) | C++ | A full node for the LBRY blockchain, including a standalone wallet. Used by miners and some applications. Most consumer applications do not bundle [[lbrycrd]] directly, and instead bundle [[lbry-sdk]]. | [Video](/resources/video-lbrycrd)
| [lbry-sdk](https://github.com/lbryio/lbry) | Python (asyncio) | A daemon that can be used directly or to develop other applications. Provides convenience [APIs](/api/sdk), bundles an SPV wallet ([[torba]]), and contains an implementation of the LBRY data network. | [Video](/resources/video-lbrysdk) | [lbry-sdk](https://github.com/lbryio/lbry-sdk) | Python (asyncio) | A daemon that can be used directly or to develop other applications. Provides convenience [APIs](/api/sdk), bundles an SPV wallet client and server, and contains an implementation of the LBRY data network. | [Video](/resources/video-lbrysdk)
| [torba](https://github.com/lbryio/torba) | Python | An [[SPV]] (Simple Payment Verification) wallet. Bundled with [[lbry-sdk]]. | [schema](https://github.com/lbryio/lbry-sdk/tree/master/lbry/schema) | Protobuf, Python | Defines the structure of the metadata stored in the LBRY blockchain. | |
| [wallet server](https://github.com/lbryio/lbry/tree/master/lbrynet/extras/wallet/server) | Protobuf, Python | The wallet server used by [[torba]]. | |
| [schema](https://github.com/lbryio/lbry/tree/master/lbrynet/schema) | Protobuf, Python | Defines the structure of the metadata stored in the LBRY blockchain. | |
### Official Applications ### Official Applications
| Application | Language (Toolset) | What Is It | Intro Video | Application | Language (Toolset) | What Is It | Intro Video
--- | --- | --- | --- --- | --- | --- | ---
| [lbry-desktop](https://github.com/lbryio/lbry-desktop) | JavaScript (ReactJS, Electron) | A graphical browser for the LBRY network for Windows, macOS, and Linux. [[lbry-desktop]] is built with [[lbry-sdk]]. | [Video](/resources/video-lbrydesktop) | [lbry-desktop](https://github.com/lbryio/lbry-desktop) (and lbry.tv) | JavaScript (ReactJS, Electron) | A desktop browser for the LBRY network for Windows, macOS, and Linux as well as a web interface on lbry.tv. [[lbry-desktop]] is built with [[lbry-sdk]]. | [Video](/resources/video-lbrydesktop)
| [lbry-android](https://github.com/lbryio/lbry-android) | JavaScript (ReactNative), Python (kivy) | A graphical browser for the LBRY network for Android. [[lbry-android]] is built with [[lbry-sdk]]. | [Video](/resources/video-lbryandroid) | [lbry-android](https://github.com/lbryio/lbry-android) | Java | A graphical browser for the LBRY network for Android. [[lbry-android]] uses [[lbry-sdk]] to interact with the network. | [Video](/resources/video-lbryandroid)
| [odysee-api](https://github.com/lbryio/odysee-api) | Go | An API server for https://odysee.com that reimplements some of the SDK APIs. | |
| [odysee-ios](https://github.com/lbryio/odysee-ios) | Swift | The Odysee IOS app. | |
| [lbry-redux](https://github.com/lbryio/lbry-redux) | JavaScript (Redux) | A common codebase for shared Redux logic between [[lbry-desktop]] and [[lbry-android]]. | | | [lbry-redux](https://github.com/lbryio/lbry-redux) | JavaScript (Redux) | A common codebase for shared Redux logic between [[lbry-desktop]] and [[lbry-android]]. | |
| [spee.ch](https://github.com/lbryio/spee.ch) | JavaScript (Node, ReactJS, Express) | A web-based host for free LBRY content. Usable directly as a content link dump site or as a customized, standalone install. | |
### Websites ### Websites
| Domain | Language (Toolset) | What Is It | Domain | Language (Toolset) | What Is It
--- | --- | --- --- | --- | ---
| [lbry.tech](https://github.com/lbryio/lbry.tech) | JavaScript (Node, Choo) | You're on it. | [lbry.tech](https://github.com/lbryio/lbry.tech) | JavaScript (Node, Choo) | You're on it.
| [lbry.com](https://github.com/lbryio/lbry.com) | PHP (vanilla) | A website for LBRY end-users and creators. | [lbry.com](https://github.com/lbryio/lbry.com) | PHP (vanilla) | A website for LBRY end-users and creators.
| [lbry.fund](https://github.com/lbryio/lbry.fund) | HTML | A website for receiving funding from LBRY, Inc.
### Auxiliary Services and Applications ### Auxiliary Services and Applications
| Domain | Language (Toolset) | What Is It | Domain | Language (Toolset) | What Is It
--- | --- | --- --- | --- | ---
| [chainquery](https://github.com/lbryio/chainquery) | Go | A utility for parsing, extracting, and updating the LBRY blockchain into structured SQL data. Used by several internal tools and useful for 3rd-party application development. | [chainquery](https://github.com/lbryio/chainquery) | Go | A utility for parsing, extracting, and updating the LBRY blockchain into structured SQL data. Used by several internal tools and useful for 3rd-party application development.
| [lighthouse](https://github.com/lbryio/lighthouse) | JavaScript, ElasticSearch | A search service for the LBRY blockchain. | [lighthouse](https://github.com/lbryio/lighthouse) | Go, ElasticSearch | A search service for the LBRY blockchain.
| [wunderbot](https://github.com/lbryio/lbry-wunderbot) | JavaScript (Node) | A chatbot used by the LBRY discord. | [wunderbot](https://github.com/lbryio/lbry-wunderbot) | JavaScript (Node) | A chatbot used by the LBRY discord.
| [block-explorer](https://github.com/lbryio/block-explorer) | PHP (vanilla) | A blockchain explorer for the LBRY blockchain. | [block-explorer](https://github.com/lbryio/block-explorer) | PHP (vanilla) | A blockchain explorer for the LBRY blockchain.
@ -68,7 +66,7 @@ Several hundred extremely good-looking, wise and moral people, as well as our CT
Web and application designers are requested to be able to work directly on CSS in the project they'd be contributing to. Please follow the [Coding](#coding) instructions for any website or application you want to improve. Web and application designers are requested to be able to work directly on CSS in the project they'd be contributing to. Please follow the [Coding](#coding) instructions for any website or application you want to improve.
We're happy to provide assistance if you're used to working in HTMl and CSS but are having trouble getting started. Check out [our chat](https://chat.lbry.com) or [our forum](https://discourse.lbry.com). We're happy to provide assistance if you're used to working in HTML and CSS but are having trouble getting started. Check out [our chat](https://chat.lbry.com) or [our forum](https://discourse.lbry.com).
## Writing ## Writing
@ -78,6 +76,10 @@ Most written content, and especially all technical writing, is checked into sour
1. Search for a quoted phrase of the content you want to change (or use the same technique to identify the folder to create a new document in). 1. Search for a quoted phrase of the content you want to change (or use the same technique to identify the folder to create a new document in).
1. Edit the content via the GitHub interface and submit it as a pull request. 1. Edit the content via the GitHub interface and submit it as a pull request.
### Translating
Translation work is primarily organized through the [LBRY Foundation](https://lbry.org). For the current instructions on participating, see [their article](http://wiki.lbry.org/Translations).
## Testing ## Testing
If you want to contribute without getting directly into the code, one of the best ways you can contribute is testing. If you want to contribute without getting directly into the code, one of the best ways you can contribute is testing.
@ -88,7 +90,7 @@ A number of our code bases ([[lbrycrd]], [[lbry-sdk]], all applications, more...
- "Watch" the repo on GitHub. You will receive an email with release notes whenever a release candidate is out and you can [raise an issue](#raising-issues). - "Watch" the repo on GitHub. You will receive an email with release notes whenever a release candidate is out and you can [raise an issue](#raising-issues).
- Join the #early-testing channel in our [chat](https://chat.lbry.com). - Join the #early-testing channel in our [chat](https://chat.lbry.com).
- For the hardcore, run master from source and/or the latest builds from [build.lbry.com](http://build.lbry.com). - For the hardcore, run master from source and/or the latest builds from [build.lbry.io](http://build.lbry.io).
Opening well-specified issues against release candidates or master builds is extremely useful in helping us create quality software. Opening well-specified issues against release candidates or master builds is extremely useful in helping us create quality software.
@ -105,7 +107,7 @@ If you're about to raise an issue because you've found a problem with LBRY, or y
A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful - thank you! A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful - thank you!
Guidelines for bug reports: Guidelines for bug reports:
1. **Identify the correct repo**. See [ecosystem overview](#ecosystem-overview). While it's okay if you get this wrong, it's a big help to us if you get it right. 1. **Identify the correct repo**. See [repository overview](#repository-overview). While it's okay if you get this wrong, it's a big help to us if you get it right.
2. **Check if the issue exists**. Please do a quick search to see if the issue has been reported (or fixed), including closed tickets. 2. **Check if the issue exists**. Please do a quick search to see if the issue has been reported (or fixed), including closed tickets.
3. **Follow the instructions** - When you open an issue inside of GitHub, each repo contains a template for how to create a good bug report. Santa _loves_ people who follow it. 3. **Follow the instructions** - When you open an issue inside of GitHub, each repo contains a template for how to create a good bug report. Santa _loves_ people who follow it.
@ -115,7 +117,7 @@ Well-specified bug reports save developers lots of time and are [appreciated](#a
Feature requests are welcome. Before you submit one be sure to: Feature requests are welcome. Before you submit one be sure to:
1. **Identify the correct repo**. See [ecosystem overview](#ecosystem-overview). 1. **Identify the correct repo**. See [repository overview](#repository-overview).
2. **Use the Github Issues search** and check the feature hasn't already been requested. Be sure to include closed tickets. 2. **Use the Github Issues search** and check the feature hasn't already been requested. Be sure to include closed tickets.
3. **Consider whether it's feasible** for us to tackle this feature in the next 6-12 months. The LBRY team is currently stretched thin just adding basic functionality. If this is a nice to have rather than a need, it is probably more clutter than helpful. 3. **Consider whether it's feasible** for us to tackle this feature in the next 6-12 months. The LBRY team is currently stretched thin just adding basic functionality. If this is a nice to have rather than a need, it is probably more clutter than helpful.
4. **Make a strong case** to convince the project's leaders of the merits of this feature. Please provide as much detail and context as possible. This means explaining the use case and why it is likely to be common. 4. **Make a strong case** to convince the project's leaders of the merits of this feature. Please provide as much detail and context as possible. This means explaining the use case and why it is likely to be common.

View file

@ -2,12 +2,4 @@
title: Developer Program title: Developer Program
--- ---
LBRY offers a complimentary 100 LBC to qualified engineers to facilitate exploration, development, and testing. This has been disabled at the request of GitHub. We're exploring alternative mechanisms to validate that you are a developer.
To qualify you must:
- have a GitHub account that is at least 90 days old and
- have an active commit history
### Claim LBC
<DeveloperProgram/>

View file

@ -11,7 +11,7 @@ We encourage the submission of changes and additions to this glossary.
### Blob ### Blob
The smallest unit of data in LBRY. Each blob is referenced by its [blob hash](#blob-hash), a SHA-384 hash of the blob contents. When files are uploaded to LBRY, they are split into blobs, which are then shared with other peers. See [Encoding](/spec#encoding) for more details. The smallest unit of data in LBRY. Each blob is referenced by its [blob hash](#blob-hash), an SHA-384 hash of the blob contents. When files are uploaded to LBRY, they are split into blobs, which are then shared with other peers. See [Encoding](/spec#encoding) for more details.
### Blob Exchange Protocol ### Blob Exchange Protocol
@ -39,7 +39,11 @@ The sequence number of a block in the blockchain. The first block is at height 0
### Blockchain ### Blockchain
An open, distributed ledger that records transactions in a verifiable and change-resistant way. The LBRY blockchain serves as an index of the content available on the network, a payment system and record of purchases for priced content, and a source if cryptographic publisher identities. An open, distributed ledger that records transactions in a verifiable and change-resistant way. The LBRY blockchain serves as an index of the content available on the network, a payment system and record of purchases for priced content, and a source of cryptographic publisher identities.
### Canonical URL
Similar to the [Short URL](#short-url), but will include the channel for but for claims that are signed by channels. The canonical URL is generally the recommend URL to use when linking LBRY URLs or displaying URLs to users. Note that it is rarely possible for the canonical URL to change to a shorter version when a competeting channel or claim is abandoned, but even if this happens, older canonical URLs will still work.
### Chainquery ### Chainquery
@ -110,7 +114,7 @@ A change to the consensus rules such that a block that would have been considere
### Hashrate ### Hashrate
A measure of mining hardware performance expressed in hashes per second (GH/s). Click [here](https://www.tokens24.com/cryptopedia/basics/bitcoin-hash-rate) for more details. A measure of mining hardware performance expressed in hashes per second (H/s). Click [here](https://www.tokens24.com/cryptopedia/basics/bitcoin-hash-rate) for more details.
### LBC ### LBC
@ -128,7 +132,7 @@ The SDK is three things:
- components that are not part of the spec but are useful for developing applications using the protocol - components that are not part of the spec but are useful for developing applications using the protocol
- a daemon that participates in the LBRY data network and provides an API for interacting with the protocol - a daemon that participates in the LBRY data network and provides an API for interacting with the protocol
See [the source code](https://github.com/lbryio/lbry) or [the API documentation](/api/sdk). See [the source code](https://github.com/lbryio/lbry-sdk) or [the API documentation](/api/sdk).
### LBRY Credits ### LBRY Credits
@ -172,7 +176,7 @@ A file included with each LBRY project that contains basic information about tha
A long-running node that accepts blobs for upload and rehosts them on the network. A long-running node that accepts blobs for upload and rehosts them on the network.
### Resolve (or URL Resolution) ### Resolve (or URL Resolution) {#resolve}
The process of translating a URL into the associated claim ID and metadata. See [Resolution](/spec#resolution) for details. The process of translating a URL into the associated claim ID and metadata. See [Resolution](/spec#resolution) for details.
@ -184,6 +188,10 @@ A definition of the structure of the metadata that is stored in claims in the bl
A scheme to validate transactions without storing the whole blockchain. A scheme to validate transactions without storing the whole blockchain.
### Short URL
The shortest [URL](https://spec.lbry.com/#urls), not including the [channel](#channel), that will [resolve](#resolve) to the correct claim (i.e. lbry://cats#c, returning lbry://cats#ca43e2b6db155177564e574b09dfedc7588816ef or lbry://@cats#0 returning lbry://@cats#0893dbed95307c4b27aadbcb1cc6cb593810b3f9). This is determined on a first come, first serve basis on claim id collisions. A short URL with more than one identifier may change to include only a single identifier if the previous claim, which had the single identifier, is deleted.
### SPV ### SPV
SPV is an abbreviation for [Simplified Payment Verification](#simplified-payment-verification). SPV is an abbreviation for [Simplified Payment Verification](#simplified-payment-verification).
@ -218,7 +226,7 @@ A parallel LBRY blockchain, used for testing and development. Testnet is like [m
### Torba ### Torba
An [SPV](#spv) wallet for the [blockchain](#blockchain). See the [source code](https://github.com/lbryio/torba). An [SPV](#spv) wallet for the [blockchain](#blockchain). See the [source code](https://github.com/lbryio/lbry-sdk).
### Transaction ### Transaction
@ -230,5 +238,5 @@ The fee paid to a miner for including a transaction in a block. Miners are incen
### Wallet ### Wallet
An application or a service that stores private keys and generates and signs transactions. Wallets do not store LBRY credits themselves (those are recorded as transactions in the global blockchain). "Storing LBC" usually means storing the private keys that control the credits. An application or a service that stores private keys and generates and signs transactions. Wallets do not store LBRY Credits themselves (those are recorded as transactions in the global blockchain). "Storing LBC" usually means storing the private keys that control the credits.

View file

@ -11,8 +11,6 @@ What if anyone in the world could publish digital content, anyone else in the wo
That's a fancy sentence, so here's a plain one: we thought it'd be *damn **cool*** if there was a system that made it easy to discover and distribute as much of the world's information as possible but was owned and controlled by no one. That's a fancy sentence, so here's a plain one: we thought it'd be *damn **cool*** if there was a system that made it easy to discover and distribute as much of the world's information as possible but was owned and controlled by no one.
If you agree with us, feel free to join our [Developer Program](/developer-program) and we'll set you up with 100 LBC to get started.
<sub>^1(#footnote-1)^ In the information theoretic sense, LBRY facilitates distribution of all data, whether it be a video or a spreadsheet.</sub> <sub>^1(#footnote-1)^ In the information theoretic sense, LBRY facilitates distribution of all data, whether it be a video or a spreadsheet.</sub>
<sub>^2(#footnote-2)^ Accessible anywhere in the world on any internet-connected device.</sub> <sub>^2(#footnote-2)^ Accessible anywhere in the world on any internet-connected device.</sub>

View file

@ -2,11 +2,11 @@ While the blockchain is the innovation that makes LBRY _possible_, the [Data Net
At this level: At this level:
- [Metadata](/spec#metadata] stored in the blockchain is interpreted and validated. - [Metadata](/spec#metadata) stored in the blockchain is interpreted and validated.
- [Data referenced by metadata](/spec#data) is accessed and distributed via a peer-to-peer network. - [Data referenced by metadata](/spec#data) is accessed and distributed via a peer-to-peer network.
- [Identities](/spec#channels) are created, signed, and validated. - [Identities](/spec#channels) are created, signed, and validated.
Data network operations are provided by the [lbrysdk](https://github.com/lbryio/lbry). This SDK also provides local wallet functionality and a set of APIs to facilitate building applications. Data network operations are provided by the [lbrysdk](https://github.com/lbryio/lbry-sdk). This SDK also provides local wallet functionality and a set of APIs to facilitate building applications.
### Additional Resources ### Additional Resources

View file

@ -15,6 +15,7 @@ description: Find the LBRY specification, API documentation, our Contributor's g
- [API Wrappers](/resources/api-wrappers) - [API Wrappers](/resources/api-wrappers)
- [LBRY SDK Configuration Settings](/resources/daemon-settings) - [LBRY SDK Configuration Settings](/resources/daemon-settings)
- [Claim Signing](/resources/claim-signing) - [Claim Signing](/resources/claim-signing)
- [Regtest Setup](/resources/regtest-setup)
- [LBRY Android App Build Steps](/resources/android-build) - [LBRY Android App Build Steps](/resources/android-build)
- [Lighthouse (search) API](https://lbryio.github.io/lighthouse) - [Lighthouse (search) API](https://github.com/lbryio/lighthouse)
- [Run Your Own Wallet Server](/resources/wallet-server)
- [Run Your Own lbry.tv](/resources/web-instance)

View file

@ -3,7 +3,7 @@ title: API Wrappers
description: Find LBRY API wrappers for your favorite language. description: Find LBRY API wrappers for your favorite language.
--- ---
This document contains a comprehensive list of all available API wrappers for the LBRY protocol and blockchain. API wrappers allow for easier integration of the LBRY APIs into your codebase. They still require you to run either the [LBRY protocol](https://github.com/lbryio/lbry) or the [LBRY blockchain](https://github.com/lbryio/lbrycrd). This document contains a comprehensive list of all available API wrappers for the LBRY protocol and blockchain. API wrappers allow for easier integration of the LBRY APIs into your codebase. They still require you to run either the [LBRY protocol](https://github.com/lbryio/lbry-sdk) or the [LBRY blockchain](https://github.com/lbryio/lbrycrd).
Interested in creating one for a language not shown below? See our [bounties page](https://lbry.com/bounty/lbry-binding) for details. Interested in creating one for a language not shown below? See our [bounties page](https://lbry.com/bounty/lbry-binding) for details.

View file

@ -72,7 +72,7 @@ Reilly decodes and combines the claim address, the serialized claim value, and t
005a001a41080110011a309b70337f51fe9a4481504059b4220ad4f87378d59ecc87bd924c3f0f23da9442b9f75ffc091b65deefe92477a86a31ea2209766964 005a001a41080110011a309b70337f51fe9a4481504059b4220ad4f87378d59ecc87bd924c3f0f23da9442b9f75ffc091b65deefe92477a86a31ea2209766964
656f2f6d70342996b9a087c18456402b57cba6085b2a8fcc136d 656f2f6d70342996b9a087c18456402b57cba6085b2a8fcc136d
Then he takes the sha256 of the combined string, giving: Then he takes the SHA256 of the combined string, giving:
dea44974ace1893f304cae4073af06a7a6cbb209f97cf8ad5f322216f044304e dea44974ace1893f304cae4073af06a7a6cbb209f97cf8ad5f322216f044304e

View file

@ -20,14 +20,14 @@ You can read more on it [here](https://en.wikipedia.org/wiki/Trie), but for unde
Each block header holds an extra 256 bits value calculated out of the root node of the claim trie at that block height. It's called `nameclaimroot` and is influenced by all children nodes as we will see next. If a blockchain network peer disagrees that a claim name was accepted or who is the winner of each name, its `nameclaimroot` will differ and the block won't form the same chain as the ones that accepted the official rules. This is the same for the traditional Merkle root, which is the root of the [Merkle tree](https://bitcoin.org/en/glossary/merkle-tree), formed by transactions in a block. Each block header holds an extra 256 bits value calculated out of the root node of the claim trie at that block height. It's called `nameclaimroot` and is influenced by all children nodes as we will see next. If a blockchain network peer disagrees that a claim name was accepted or who is the winner of each name, its `nameclaimroot` will differ and the block won't form the same chain as the ones that accepted the official rules. This is the same for the traditional Merkle root, which is the root of the [Merkle tree](https://bitcoin.org/en/glossary/merkle-tree), formed by transactions in a block.
## What's in a leaf? ## What's in a leaf?
The leaf currently holds the winner of that name. Its formed by the transaction hash, output number of the claim in that transaction and the height it was accepted. The leaf currently holds the winner of that name. It's formed by the transaction hash, output number of the claim in that transaction and the height it was accepted.
### Generating the leaf hash ### Generating the leaf hash
So, let's suppose that the winner claim of `mindblown` name was made at transaction output `1` of the transaction hash `67ad533eb2676c9d36bfa100092af5358de747e08ef928c0c54a8b3891c2b76b` and included in the Trie at height `102`. So, let's suppose that the winner claim of `mindblown` name was made at transaction output `1` of the transaction hash `67ad533eb2676c9d36bfa100092af5358de747e08ef928c0c54a8b3891c2b76b` and included in the Trie at height `102`.
1. The transaction hash is converted from [RPC byte order](https://bitcoin.org/en/glossary/rpc-byte-order) to [internal byte order](https://bitcoin.org/en/glossary/internal-byte-order). 1. The transaction hash is converted from [RPC byte order](https://bitcoin.org/en/glossary/rpc-byte-order) to [internal byte order](https://bitcoin.org/en/glossary/internal-byte-order).
2. The output number becomes a simple string. 2. The output number becomes a simple string.
3. The height becomes a big endian 64 bits value. 3. The height becomes a big endian 64 bits value.
4. The node hash is calculated as the double sha-256 hash of the double sha-256 hash of the internal byte order representation of the transaction hash concatenated with the double sha-256 hash of the output number representation concatenated with the double sha-256 hash of the height. 4. The node hash is calculated as the double SHA-256 hash of the double SHA-256 hash of the internal byte order representation of the transaction hash concatenated with the double SHA-256 hash of the output number representation concatenated with the double SHA-256 hash of the height.
This is better represented in the simple python script below: This is better represented in the simple python script below:
```python ```python
@ -54,8 +54,8 @@ print("leaf hash is {}".format(hexlify(hash_leaf(tx, nout, at_height)[::-1])))
Let's start with a ClaimTrie holding a single claim. Let's start with a ClaimTrie holding a single claim.
The claim is named `mindblown` and was included at block 102 with the same details as the last section. It's actually a real claim as [you can see in the block explorer](https://explorer.lbry.com/blocks/102). This block has the first claim ever, so the ClaimTrie was the simple case being explained in here. The claim is named `mindblown` and was included at block 102 with the same details as the last section. It's actually a real claim as [you can see in the block explorer](https://explorer.lbry.com/blocks/102). This block has the first claim ever, so the ClaimTrie was the simple case being explained in here.
We start with the leaf hash: We start with the leaf hash:
1. Hash the leaf hash using double sha-256. 1. Hash the leaf hash using double SHA-256.
2. For each character of the name (nodes of the trie), the hash of a node is the double sha-256 of the node's character concatenated with the children hash. 2. For each character of the name (nodes of the trie), the hash of a node is the double SHA-256 of the node's character concatenated with the children hash.
Continuing with the Python script from the last section, this is how to calculate the root of a claim trie holding a single name: Continuing with the Python script from the last section, this is how to calculate the root of a claim trie holding a single name:
```python ```python

View file

@ -5,7 +5,7 @@ description: How does the LBRY blockchain achieve consensus? This resource page
LBRY uses [proof of work](https://en.bitcoin.it/wiki/Proof_of_work) as a [consensus mechanism](/spec#consensus), the same way that Bitcoin does. LBRY uses [proof of work](https://en.bitcoin.it/wiki/Proof_of_work) as a [consensus mechanism](/spec#consensus), the same way that Bitcoin does.
LBRY has differences in hash function, block targeting, and difficult adjustment. LBRY has differences in hash function, block targeting, and difficulty adjustment.
### Hash Mechanism ### Hash Mechanism
@ -18,4 +18,4 @@ proof = sha256(sha256(left + right)) # concatenate the two halves, and double-s
### Block Targeting & Difficulty Adjustment ### Block Targeting & Difficulty Adjustment
The targeted time of each Lbry block is 2.5 mintues (150 seconds). More information and links to source code [here](https://lbry.tech/spec#consensus). The targeted time of each LBRY block is 2.5 mintues (150 seconds). More information and links to source code [here](https://lbry.tech/spec#consensus).

View file

@ -3,7 +3,7 @@ title: SDK Settings
description: The daemon provided by the LBRY SDK has many settings. This resource lists them all and what they mean. Ready, set, settings! description: The daemon provided by the LBRY SDK has many settings. This resource lists them all and what they mean. Ready, set, settings!
--- ---
This document outlines how to configure SDK daemon settings and what options are available. They can be found on the lbry GitHub repository in [conf.py](https://github.com/lbryio/lbry/blob/master/lbrynet/conf.py). This document outlines how to configure SDK daemon settings and what options are available. They can be found on the lbry GitHub repository in [conf.py](https://github.com/lbryio/lbry-sdk/blob/master/lbry/conf.py).
## Daemon settings configuration ## Daemon settings configuration
@ -12,7 +12,7 @@ The easiest way to configure the settings is by editing the `daemon_settings.yml
Sample daemon_settings.yml file: Sample daemon_settings.yml file:
``` ```
tcp_port: 3335 tcp_port: 3335
lbryum_servers: ['lbryumx1.lbry.com:50001','lbryumx2.lbry.com:50001'] lbryum_servers: ['spv11.lbry.com:50001','spv19.lbry.com:50001']
download_directory: 'c:\lbry\Downloads' download_directory: 'c:\lbry\Downloads'
use_upnp: false use_upnp: false
``` ```
@ -33,7 +33,7 @@ Configuration options are organized by their respective areas: Files, Wallet, Ne
| Setting | Format | Default value | Sample Values | Description | | Setting | Format | Default value | Sample Values | Description |
|-------------------------------|---------|------------------------------------------------------|------------------------------------|---------------------------------------------------------------------------------------------------| |-------------------------------|---------|------------------------------------------------------|------------------------------------|---------------------------------------------------------------------------------------------------|
| blockchain_name | string | 'lbrycrd_main' | 'lbrycrd_regtest' | Blockchain network to connect to | | blockchain_name | string | 'lbrycrd_main' | 'lbrycrd_regtest' | Blockchain network to connect to |
| lbryum_servers | list | ['lbryumx1.lbry.com:50001','lbryumx2.lbry.com:50001'] | ["mylbryum.lbry.com:50001] | SPV wallet server address | | lbryum_servers | list | ['spv11.lbry.com:50001','spv19.lbry.com:50001'] | ["mylbryum.lbry.com:50001] | SPV wallet server address(Default servers are spv11-spv19) |
| wallet_dir | string | [varies by OS](https://lbry.com/faq/lbry-directories) | 'c:\lbry\lbryum\' | Wallet data location | | wallet_dir | string | [varies by OS](https://lbry.com/faq/lbry-directories) | 'c:\lbry\lbryum\' | Wallet data location |
| max_key_fee | json | {'currency': 'USD', 'amount': 50.0} | {'currency': 'LBC', 'amount': 5.0} | Max payment allowed for content | | max_key_fee | json | {'currency': 'USD', 'amount': 50.0} | {'currency': 'LBC', 'amount': 5.0} | Max payment allowed for content |
| wallet | string | 'lbryum' | 'lbrycrd' | Choice of wallet software, SPV (lbryum) vs full node (lbrycrd). Currently only lbryum supported | | wallet | string | 'lbryum' | 'lbrycrd' | Choice of wallet software, SPV (lbryum) vs full node (lbrycrd). Currently only lbryum supported |
@ -42,7 +42,8 @@ Configuration options are organized by their respective areas: Files, Wallet, Ne
### Network ### Network
| Setting | Format | Default value | Sample Values | Description | | Setting | Format | Default value | Sample Values | Description |
|----------------------------|---------|---------------------------|----------------------------|------------------------------------------------------------------------------------| |----------------------------|---------|---------------------------|----------------------------|------------------------------------------------------------------------------------|
| api | string | localhost:5279 | 0:0:0:0:5280 | IP address and port the SDK API will listen on | | api | string | localhost:5279 | 0:0:0:0:5280 | IP address and port the SDK API will listen on |
| streaming_server | string | localhost:5280 | 0:0:0:0:5280 | IP address and port the media/streaming server will listen on |
| cache_time | integer | 150 | 90 | How long to keep resolve data in cache | | cache_time | integer | 150 | 90 | How long to keep resolve data in cache |
| data_rate | float | 0.0001 | 0.05 | What LBC rate, per MB, to offer DHT data at (currently disabled in the protocol) | | data_rate | float | 0.0001 | 0.05 | What LBC rate, per MB, to offer DHT data at (currently disabled in the protocol) |
| udp_port | integer | 4444 | 4445 | UDP port used to announce blobs | | udp_port | integer | 4444 | 4445 | UDP port used to announce blobs |
@ -53,7 +54,7 @@ Configuration options are organized by their respective areas: Files, Wallet, Ne
| known_dht_nodes | list | ['lbrynet1.lbry.com:4444'] | ['myDHT.lbry.com:4444'] | Bootstrap nodes for network connectivity | | known_dht_nodes | list | ['lbrynet1.lbry.com:4444'] | ['myDHT.lbry.com:4444'] | Bootstrap nodes for network connectivity |
| max_connections_per_download | integer | 5 | 10 | Threads used to download blobs | | max_connections_per_download | integer | 5 | 10 | Threads used to download blobs |
| seek_head_blob_first | boolean | true | false | Search for first data blob after downloading sd blob | | seek_head_blob_first | boolean | true | false | Search for first data blob after downloading sd blob |
| tcp_port | integer | 3333 | 3334 | Port the SDK will listen on | | tcp_port | integer | 4444 | 3334 | Port the SDK will listen on |
| concurrent_reflector_uploads| integer | 5 | 10 | Connections to use while uploading data to reflector | | concurrent_reflector_uploads| integer | 5 | 10 | Connections to use while uploading data to reflector |
| reflect_streams | boolean | true | false | Send published data to reflector servers | | reflect_streams | boolean | true | false | Send published data to reflector servers |
| reflector_servers | list | ['reflector.lbry.com'] | ['myreflector.lbry.com'] | Server data will be reflected to | | reflector_servers | list | ['reflector.lbry.com'] | ['myreflector.lbry.com'] | Server data will be reflected to |
@ -62,16 +63,11 @@ Configuration options are organized by their respective areas: Files, Wallet, Ne
| node_rpc_timeout | integer | 5 | 10 | Time, in seconds, to allow connection over DHT | | node_rpc_timeout | integer | 5 | 10 | Time, in seconds, to allow connection over DHT |
| network_interface | string | 0:0:0:0 | 127.0.0.1 | Interface to use for the DHT and blob exchange | | network_interface | string | 0:0:0:0 | 127.0.0.1 | Interface to use for the DHT and blob exchange |
| use_upnp | boolean | true | false | Attempt external port mapping via UPnP | | use_upnp | boolean | true | false | Attempt external port mapping via UPnP |
| streaming_get | boolean | false | true | Allow calling localhost:5280/get/claimname requests |
### Security | save_files | boolean | true | false | Save files with each download |
| save_blobs | boolean | true | false | Save blobs with each download |
| Setting | Format | Default value | Sample Values | Description |
|----------------|---------|---------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------|
| allowed_origin | string | '' | '*' or localhost | IP address to allow API requests from |
| use_auth_http | boolean | false | true | See [authentication instructions](https://github.com/lbryio/lbry/blob/master/lbrynet/daemon/auth/server.py#L179) for details |
### Other ### Other
| Setting | Format | Default value | Sample Values | Description | | Setting | Format | Default value | Sample Values | Description |
|--------------------|---------|---------------|--------------------------------|---------------------------------------------------------------------------------------------------------------| |--------------------|---------|---------------|--------------------------------|---------------------------------------------------------------------------------------------------------------|
| components_to_skip | list | [] | ['reflector','hash_announcer'] | Disable components, [see entire list here](https://github.com/lbryio/lbry/wiki/Component-Dependencies-Table) | | components_to_skip | list | [] | ['reflector','hash_announcer'] | Disable components, [see entire list here](https://github.com/lbryio/lbry-sdk/wiki/Component-Dependencies-Table) |
| share_usage_data | boolean | true | false | Share analytics data | | share_usage_data | boolean | true | false | Share analytics data |

View file

@ -0,0 +1,39 @@
---
title: Hosting a DHT bootstrap node
description: How to setup a bootstrap DHT node
---
This guide will help you setup and maintain a LBRY DHT [bootstrap node](https://en.wikipedia.org/wiki/Bootstrapping_node). Those nodes are important so people can join the network on first startup.
After finishing and checking that it works, if you want to add your node to the SDK bootstrap list just open a PR adding yourself to the [conf file](https://github.com/lbryio/lbry-sdk/blob/master/lbry/conf.py#L694) or an issue on the [SDK repo](https://github.com/lbryio/lbry-sdk/).
## Requirements
- Being reachable over UDP on the internet at some port
- 1GB of memory
- Docker or Python 3.7 (check [pyenv](https://github.com/pyenv/pyenv) if your Linux distribution doesn't offer that version)
## Running directly from Docker
This is the easiest way to run and maintain your node. Just run:
```bash
docker run -d -p 4444:4444 lbry/dht-bootstrap:latest
```
## Installing LBRY SDK from source
The most up to date guide for doing it will always be in the [INSTALL.md file](https://github.com/lbryio/lbry-sdk/blob/master/INSTALL.md). Please refer to it if you run into trouble. Otherwise, this should be enough most of the time (assuming requirements are all there):
```bash
git clone https://github.com/lbryio/lbry-sdk.git
make install
```
### Running a node from source
After installing, just:
```bash
python scripts/dht_node.py
```
### Checking if it is working
From another machine with the SDK installed, run:
```bash
python scripts/dht_node.py --bootstrap_node your-server-domain-here.com:4444
```
After 10-20 seconds, you should see more than 0 peers on the log messages. If that is not the case, check firewall on the bootstrap node and see if it is reachable.

View file

@ -33,7 +33,7 @@ For this example, we will use claim ID `d9317ac7842f88ba442fee749c4f834353c24206
## Parse the Metadata ## Parse the Metadata
Perform a `getclaimbyid` call to lbrycrd using the claim ID for the claim you want to look up. You should get a response with some parameters. The `value` parameter contains the claim contents as a protobuf-encoded binary string. Decode the value using the protobuf definitions in [lbryio/types](https://github.com/lbryio/types/tree/master/proto). You will get a Claim object. Perform a `getclaimbyid` call to lbrycrd using the claim ID for the claim you want to look up. You should get a response with some parameters. The `value` parameter contains the claim contents as a protobuf-encoded binary string. Decode the value using the protobuf definitions in [lbryio/types](https://github.com/lbryio/types/tree/master/v2/proto). You will get a Claim object.
## Get the Stream Hash ## Get the Stream Hash

View file

@ -33,7 +33,7 @@ For this example, we will use claimID `d9317ac7842f88ba442fee749c4f834353c24206`
## Parse the Metadata ## Parse the Metadata
Perform a `getclaimbyid` call to lbrycrd using the claimID for the claim you want to look up. You should get a response with some parameters. The `value` parameter contains the claim contents as a protobuf-encoded binary string. Decode the value using the protobuf definitions in [lbryio/types](https://github.com/lbryio/types/tree/master/proto). You will get a Claim object. Perform a `getclaimbyid` call to lbrycrd using the claimID for the claim you want to look up. You should get a response with some parameters. The `value` parameter contains the claim contents as a protobuf-encoded binary string. Decode the value using the protobuf definitions in [lbryio/types](https://github.com/lbryio/types/tree/master/v2/proto). You will get a Claim object.
## Get the SD Hash ## Get the SD Hash

View file

@ -0,0 +1,65 @@
---
title: LBRY P2P: Settings and troubleshooting
description: Guide on properly setting up P2P nodes and how to diagnose/fix common issues.
---
# LBRY P2P: Settings and troubleshooting
A very important step in supporting the network resilience is hosting content in a decentralized way. This already happens when you stream content using the desktop version of LBRY APP, but sometimes we want to make sure this is working or dedicate larger amounts of resources for this task.
This document aims to explain P2P configuration and troubleshooting from small to large nodes. If you don't know how to change SDK settings, check [this other document first](https://lbry.tech/resources/daemon-settings).
## Reachability
The first priority when seeding content is making sure there is a way for other nodes to reach you across the internet.
### Figuring out your ports
In order to troubleshoot reachability, we start by checking your configuration for the UDP and TCP ports. By default, they will both be set to 4444. Those can be found on the configuration under the keys `udp_port` and `tcp_port`. Please set them both to the same value as this helps connectivity trough [hole punching](https://en.wikipedia.org/wiki/Hole_punching_(networking)) and ease of management.
### Checking for reachability
There are some websites providing generic ways to check ports, like:
- https://www.portcheckers.com/
- https://portchecker.co/check
However, checking the port does not check if LBRY P2P protocol is working behind it. For a better check, we can use a tool hosted by Madiator, a community member.
- To test for UDP (DHT): http://test.madiator.com:60666/dht/<your `udp_port`>
- To test for TCP (P2P): http://test.madiator.com:60666/p2p/<your `tcp_port`>
As a last resource to test a remote machine DHT service, from a local SDK try:
```bash
lbrynet peer ping <DHT node id> <IP> <port>
```
To find out what the `DHT node id` is, on the target machine run `lbrynet status` and look for `node_id` .
### I am unreachable. What now?
VPN users: check with your provider if they feature port forwarding. There are guides specific to each one, like [this one from Mullvad](https://mullvad.net/en/help/port-forwarding-and-mullvad/).
Domestic routers: there are websites like [this one](https://portforward.com/how-to-port-forward/) providing information on popular router models. Unfortunately, this document would be huge if we added port forwarding instructions for every router/firewall.
Servers: check if your firewall is blocking the SDK ports. For ufw on Linux, this is `sudo ufw allow <port>`.
If you still have trouble figuring that out, don't be shy, [ask the LBRY community on Discord!](https://chat.lbry.com/)
## Content blobs storage settings
Files in LBRY are composed by `content blobs`, which can be seen as chunks of binary encrypted data belonging to some content. By default, the SDK enables saving blobs to disk, which then can be served over P2P. To check if that is enabled, look for the `save_blobs` setting.
**The following settings are isolated. The space limit set for one does not apply to the other.**
### Setting up storage space control
By default, content blobs are kept as long as the files are still in your file list. If you wish to allocate a space limit for content blobs and let the SDK decide what to delete, set `blob_storage_limit` to a value in megabytes.
This won't delete your downloads from the file list. Instead, it deletes content blobs associated with older files as space for newer blobs is requested.
### Setting up space for automatic contribution
This section is aimed at fully automatic contribution in background. Normal usage of the SDK with P2P enabled already helps the network, but requires interaction.
LBRY SDK can be configured to help the P2P network by automatically downloading and hosting content. This is ideal for contributing spare disk space and network bandwidth without further interaction.
Enabling: change `network_storage_limit` to the size (in megabytes) that will be used for automatic seeding.
Disabling: setting the space to 0 disables it. The space used will eventually be released automatically. For cleaning immediately, issue a `lbrynet blob clean` from command line.

View file

@ -1,208 +0,0 @@
---
title: Regtest Setup
description: Regtest is a parallel testing network for the LBRY blockchain. Learn how to use it in this resource article.
---
## Why Use Regtest
A regtest server provides for a way to instantly generate blocks so that transactions can be instantaneous, which ultimately means no waiting for confirmations from the blockchain. Also, its not a problem if you accidentally corrupt your wallet, since no real funds are lost! Delete the files and setup a new one.
## Setup
To begin setting up the network, there are a few things you need.
You'll need a Linux or a Mac distribution to run all this. A virtual machine is fine.
Note: These instructions specifically were tested on Ubuntu version 16.04.
### Virtual Environment
First up it's a good idea to create a Python virtual environment. This requires you to have a functional python2.7 setup, with the Python package manager `pip` installed. To create a new virtual environment in a folder `lbry-env`, run this:
`virtualenv -p /usr/bin/python2.7 lbry-env`
To enter the environment, run:
`source lbry-env/bin/activate`.
### lbrycrd
You need to download a build of `lbrycrd` from [here](https://github.com/lbryio/lbrycrd/releases/), no installation required. To configure `lbrycrd` you need to create a file at `~/.lbrycrd/lbrycrd.conf`,
containing the following:
```ini
rpcuser=test
rpcpassword=test
rpcport=18332
regtest=1
server=1
txindex=1
daemon=1
listen=0
discover=0
```
### lbryum-server
To install lbryum-server, you first need to install the package `leveldb`. After that, download the source from [here](https://github.com/lbryio/lbryum-server/releases), and run the following _not_ inside the environment:
```bash
cd lbryum-server
sudo pip2 install -r requirements.txt
```
If you're not running debian/\*buntu or a derivative of those, you need to edit the `configure` file a bit. In line 11, remove the `apt-get` line and manually install the required packages. In line 51, change `adduser` to `useradd` and on the same line, change `--disabled-password` to `-p !`.
```bash
sudo ./configure
sudo python2 setup.py install
```
The `sudo ./configure` command creates a new user in the system by the name "lbryum", which is the user through which we'll be running the server. lbryum-server also needs W/R access to `/var/lbryum-server`.
To do that run:
```bash
sudo chown -R lbryum /var/lbryum-server
```
When installed, append/use the following config options to the `/etc/lbryum.conf` file:
```ini
[lbrycrdd]
lbrycrdd_host = localhost
lbrycrdd_port = 18332
# user and password from lbrycrd.conf
lbrycrdd_user = test
lbrycrdd_password = test
[network]
type=lbrycrd_regtest
```
### lbryum
To install lbryum, first download the source from [here](https://github.com/lbryio/lbryum/releases). To install it, run the following inside the virtual environment:
```bash
cd lbryum
pip2 install -r requirements.txt
pip2 install -e .
```
After installation completes, you must set the config option for lbryum using:
```bash
lbryum setconfig default_servers '{ "localhost": { "t": "50001" }}'
lbryum setconfig chain 'lbrycrd_regtest'
```
Alternatively, you can create a file `touch ~/.lbryum/config` and paste the following config:
```json
{
"chain": "lbrycrd_regtest",
"default_servers": {
"localhost": {
"t": "50001"
}
}
}
```
### lbry
Download source from [here](https://github.com/lbryio/lbry/releases), and run the following inside the environment:
```bash
cd lbry
pip2 install -r requirements.txt
pip2 install -e .
mkdir ~/.lbrynet
touch ~/.lbrynet/daemon_settings.yml
```
Append the following in the newly created `~/.lbrynet/daemon_settings.yml` file:
```yml
blockchain_name: lbrycrd_regtest
lbryum_servers:
- localhost:50001
reflect_uploads: false
share_usage_data: false
use_upnp: false
```
### Last step
Go to the `lbryum` folder once again and run:
```bash
pip2 install -e .
```
This is to ensure that `lbrynet-daemon` uses the correct wallet.
## Firing up the regtest server
### Wallet backup
To start off, if you've already used LBRY on your machine, you need to backup the wallet by copying the folders `~/.lbrynet` and `~/.lbryum` and then deleting them to start from fresh. Run
`mkdir ~/.lbryum`
Now it should be all set-up. Just execute the commands in the following order, and the regtest server should be good to go.
### 1) lbrycrd
To run the `lbrycrd` daemon, run the following in the `lbrycrd` folder:
`./lbrycrdd`
To generate blocks, run `./lbrycrd-cli generate <num_of_blocks>`
You'll need to generate some blocks to get the network going. Start off by generating at least 100.
`./lbrycrd-cli generate 173`
If you'd prefer a more verbose output from lbrycrdd, run lbrycrd using:
`./lbrycrdd -printtoconsole`
### 2) lbryum-server
To run the server, run:
```bash
sudo runuser -l lbryum -c 'lbryum-server --conf=/etc/lbryum.conf'
```
Note: conf flag can be left out if the config is in the default directory(default: `/etc/lbryum.conf`)
### 3) lbryum
To run the lbryum, run:
```bash
lbryum daemon start
```
Generate some more blocks, get a wallet address by running:
`lbryum getunusedaddress`
and then send some credits to your wallet by doing
`./lbrycrd-cli sendtoaddress <address> <num_of_credits>`
### 4) lbry
You can now run `lbrynet-daemon`, and it should connect to the `lbryum`. Now you can use the regtest stack as you would normally use lbryum.
## Shutdown
To stop the network, run `lbrynet-cli daemon_stop`, `lbryum daemon stop`, and kill the `lbryum-server` process and stop lbrycrd by `lbrycrdd-cli stop`. If you want to use your wallet and the official servers again, backup the new regtest wallet, and replace it with your own.
## Note 1
You need to generate a few blocks every time you make a new transaction in the form of send, receive, claim, update, publish, support, tip, etc. for it to show up in the daemon and lbryum, etc.
## Note 2
If something goes wrong and you get a "Block not found" error, remember to delete `/var/lbryum-server` before trying again.
## Cheatsheet
#### Required processes in the correct order
```bash
lbrycrdd
sudo runuser -l lbryum -c 'lbryum-server --conf=/etc/lbryum.conf'
lbryum daemon start
lbrynet-daemon
```
#### Generate blocks
```bash
lbrycrd-cli generate 5
```
#### Get a wallet address
```bash
lbryum getunsusedaddress
```
#### Send credits from lbrycrd to your wallet
```bash
lbrycrd-cli sendtoaddress <address> <num_of_credits>
```

View file

@ -50,7 +50,7 @@ This document exists to introduce a project to a new visitor. It may also serve
### Contributing ### Contributing
* A single header labeled "Contributing" should appear as an h2 * A single header labeled "Contributing" should appear as an h2
* This should be the same message: "Contributions to this project are welcome, encouraged, and compensated. For more details, see [CONTRIBUTING.md](*CONTRIBUTING.md*) * This should be the same message: "Contributions to this project are welcome, encouraged, and compensated. For more details, see *[CONTRIBUTING.md](CONTRIBUTING.md)*.
* If CONTRIBUTING.md does not exist in the project, it should link to [https://lbry.com/faq/contributing](https://lbry.com/faq/contributing) (soon to be lbry.tech/contributing) * If CONTRIBUTING.md does not exist in the project, it should link to [https://lbry.com/faq/contributing](https://lbry.com/faq/contributing) (soon to be lbry.tech/contributing)
### (Additional Headings) ### (Additional Headings)
@ -65,7 +65,7 @@ This document exists to introduce a project to a new visitor. It may also serve
### Security ### Security
* "We take security seriously. Please contact [security@lbry.com](mailto:security@lbry.com) regarding any security issues. Our PGP key is [here](https://keybase.io/lbry/key.asc) if you need it." * "We take security seriously. Please contact [security@lbry.com](mailto:security@lbry.com) regarding any security issues. Our PGP key is [here](https://lbry.com/faq/pgp-key) if you need it."
### Contact ### Contact
@ -86,7 +86,7 @@ This document should cover the following:
* First, it should contain a single sentence: "This project follows the global contributing standards for all LBRY projects, to read those go < here >.” * First, it should contain a single sentence: "This project follows the global contributing standards for all LBRY projects, to read those go < here >.”
* A "Code Overview" section explaining some basic design choices and how to begin stepping through the code. An example would be explaining that Daemon.py is the primary entry point for the daemon code, and one can begin to trace through the code by looking for jsonrpc_xxx, where xxx is one of the api calls listed [here](https://lbry.com/api) * A "Code Overview" section explaining some basic design choices and how to begin stepping through the code. An example would be explaining that Daemon.py is the primary entry point for the daemon code, and one can begin to trace through the code by looking for jsonrpc_xxx, where xxx is one of the api calls listed [here](https://lbry.com/api)
* A "Testing" section explaining how to run tests and stating that tests are necessary * A "Testing" section explaining how to run tests and stating that tests are necessary
* Information on how to submit pull requests, and what to expect afterwards (e.g. a link to our [branching doc](https://github.com/lbryio/lbry/wiki/Branching-and-Merging), commands to run before submitting PR, tests must pass, changelog entry, etc). If you find this gets repetitive, it may be best to link to a global doc * Information on how to submit pull requests, and what to expect afterwards (e.g. a link to our [branching doc](https://github.com/lbryio/lbry-sdk/wiki/Branching-and-Merging), commands to run before submitting PR, tests must pass, changelog entry, etc). If you find this gets repetitive, it may be best to link to a global doc
* Anything else a new visitor to a repository should know about contributing to that specific repository (linting, generating documentation, etc) * Anything else a new visitor to a repository should know about contributing to that specific repository (linting, generating documentation, etc)
## LICENSE ## LICENSE
@ -101,4 +101,4 @@ A template for issues should exist to guide users in correctly filing them.
## Style and Formatting Notes ## Style and Formatting Notes
- Rely on autowrap instead of manually breaking up paragraphs with carriage return. - Rely on autowrap instead of manually breaking up paragraphs with a carriage return.

View file

@ -14,7 +14,7 @@ Check out [our video tutorial](/resources/video-lbrydesktop) to setup the [Deskt
Check out [our video tutorial](/resources/video-lbryandroid) to setup the [Android app](https://github.com/lbryio/lbry-android) development environment. Check out [our video tutorial](/resources/video-lbryandroid) to setup the [Android app](https://github.com/lbryio/lbry-android) development environment.
## LBRY SDK ## LBRY SDK
Check out [our video tutorial](/resources/video-lbrysdk) to setup the [LBRY SDK](https://github.com/lbryio/lbry) development environment. Check out [our video tutorial](/resources/video-lbrysdk) to setup the [LBRY SDK](https://github.com/lbryio/lbry-sdk) development environment.
## LBRY Blockchain ## LBRY Blockchain
Check out [our video tutorial](/resources/video-lbrycrd) to setup the [LBRY Blockchain](https://github.com/lbryio/lbrycrd) development environment. Check out [our video tutorial](/resources/video-lbrycrd) to setup the [LBRY Blockchain](https://github.com/lbryio/lbrycrd) development environment.

View file

@ -0,0 +1,59 @@
# How to spend your time locked transaction
This guide will walk you through the process of claiming a time locked transaction from a USB key. This involves accessing the transaction details on the key, making sure you have the latest version of `lbrynet` and finally using the transaction details to call `account_deposit` to claim your LBC.
## Check `lbrynet` version
If you already have `lbrynet` installed then you can check your version like this:
```
lbrynet version
```
If above command fails, you may need to start `lbrynet` first (and then try above again):
```
lbrynet start
```
If you do not have `lbrynet` installed or your version is less than `v0.108.0` then you can get latest version here:
[https://github.com/lbryio/lbry-sdk/releases](https://github.com/lbryio/lbry-sdk/releases)
## Gather Information
### Transaction ID and Transaction Output Number
1. On the USB key, find a file named `address.txt` and copy the address in this file.
1. Go to [LBRY Explorer](https://explorer.lbry.com/) and enter the address you copied.
1. You should see one transaction containing this address, click on this transaction.
1. You will need two pieces of information on this page, the `transaction id` and the `nout`.
1. The `transaction id` can be found at the top of the page and directly below the text `LBRY Transaction`.
1. The `nout` is the position of the output containing your address, starting with 0. Starting from the top of the list of outputs, count the outputs until you get to your address, then subtract 1 from this count, that is your `nout`.
### Private Key and Redeem Script
1. On the USB key, find a file named `key.zip` and unzip this file using the password emailed to you previously.
1. You should now have a file named `key.txt` which is base64 encoded and contains your `private key` and `redeem script`.
1. To decode the contents of the file you can use a website such as [base64decode.org](https://www.base64decode.org/) (not a secure option) or if you have Python installed you can do this on the command line:
```
python -m base64 -d /path/to/key.txt
```
1. After decoding you will see a key/value mapping of various items, including `privateKey` and `redeemScript`. Take note of these values.
## Redeem
Now that you have gathered the necessary information it is easy to redeem your LBC. Time locked transaction can be redeemed using the `lbrynet account deposit` command (fill in the values you gathered previously):
```
lbrynet account deposit <transaction id> <nout> <redeemScript> <privateKey>
```
If you get an error that says `AssertionError: Cannot find private key for signing output.`, try a different number for `<nout>` (for example, increase or decrease it by 1).
Enjoy your LBC!
## Get in touch
Whether you got to the end without a hiccup or you got stuck along the way, we want to hear from you. [Join our Discord](https://discord.gg/y3W9JuS) to get help, stay updated, and talk to other wallet server operators.

View file

@ -0,0 +1,212 @@
# How To Run Your Own Wallet Server
This guide will walk you through the process of setting up a LBRY wallet server. This involves provisioning a web server and setting up some services (docker, lbrycrd, and the wallet server). At the end, you'll have your own connection to the LBRY network.
**note:** This is early-stage stuff. You may encounter unexpected issues. Please be patient and don't hesitate to [reach out for help](#get-in-touch).
## Start With A Fresh Server
We recommend a quad-core server with at least 16GB RAM, 200GB disk, and a fresh Ubuntu 18.04 install. Memory usage is flexible. 32 GB works best, but 16 GB is enough for a few clients.
Make sure your firewall has ports 9246 and 50001 open. 9246 is the port lbrycrd uses to communicate to other nodes. 50001 is the wallet server RPC port.
## Install lbrycrd
### Download and setup
Download the [latest release of lbrycrd](https://github.com/lbryio/lbrycrd/releases/latest).
Then, create a folder on your home directory called `.lbrycrd` and save the following to `.lbrycrd/lbrycrd.conf`:
```
txindex=1
server=1
daemon=1
rpcuser=lbry
rpcpassword=lbry
dustrelayfee=0.00000001
```
Feel free to change the `rpcuser` or `rpcpassword`. If you do, you'll have to update the `DAEMON_URL` variable later on (in the docker-compose.yml file) to match the user/password you chose.
## Create a service (optional)
You can run lbrycrdd directly using `./lbrycrdd`. However, we recommend creatinga systemd service to manage the process for you.
Create a file at `/etc/systemd/system/lbrycrdd.service` with the following contents:
```
[Unit]
Description="LBRYcrd daemon"
After=network.target
[Service]
ExecStart=/home/<your_user>/lbrycrdd -datadir="/home/<your_user>/.lbrycrd" -pid="/run/lbrycrdd/lbrycrdd.pid"
# Creates /run/lbrycrdd
RuntimeDirectory=lbrycrdd
Type=Forking
PIDFile=/run/lbrycrdd/lbrycrdd.pid
Restart=on-failure
# hardening
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
PrivateDevices=true
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.target
```
Then run `sudo systemctl daemon-reload`.
Now you can start and stop lbrycrd with `sudo service lbrycrdd start` and `sudo service lbrycrdd stop`.
You can watch the lbrycrd log with `tail -f ~/.lbrycrd/debug.log`
## Set Up Docker
### Install Docker & Docker Compose
```
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
sudo apt install -y docker-ce docker-ce-cli containerd.io && \
sudo systemctl enable docker && sudo systemctl start docker && \
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
sudo chmod +x /usr/local/bin/docker-compose
sudo usermod -aG docker $USER
```
### Download our example docker-compose.yml
You can see it [here](https://github.com/lbryio/lbry-sdk/blob/master/docker/docker-compose-wallet-server.yml).
```
curl -L "https://raw.githubusercontent.com/lbryio/lbry-sdk/master/docker/docker-compose-wallet-server.yml" -o docker-compose.yml
```
Make sure the user and password in the `DAEMON_URL` variable (the `lbry@lbry` part) in this docker-compose.yml matches the user/password in your `~/.lbrycrd/lbrycrd.conf` file.
### Download snapshots for elasticsearch and the wallet server (optional)
You can skip the initial sync by starting from a snapshot. The following will download a snapshot of the elasticsearch volume and move it into the default location for docker volumes on ubuntu, on other systems you may need to adjust the path used here. Note: snapshot heights must be the same. The tars can be deleted after setting the volumes up.
```bash
SNAPSHOT_HEIGHT="1049658"
ES_VOLUME_PATH="/var/lib/docker/volumes/${USER}_es01"
ES_SNAPSHOT_TAR_NAME="es_snapshot_${SNAPSHOT_HEIGHT}.tar"
ES_SNAPSHOT_URL="https://snapshots.lbry.com/hub/${ES_SNAPSHOT_TAR_NAME}"
wget $ES_SNAPSHOT_URL
echo "decompressing elasticsearch snapshot"
tar -xf $ES_SNAPSHOT_TAR_NAME
sudo chown -R $USER:root "snapshot_es_${SNAPSHOT_HEIGHT}"
sudo chmod -R 775 "snapshot_es_${SNAPSHOT_HEIGHT}"
sudo mkdir -p $ES_VOLUME_PATH
sudo rm -rf "${ES_VOLUME_PATH}/_data"
sudo mv "snapshot_es_${SNAPSHOT_HEIGHT}" "${ES_VOLUME_PATH}/_data"
```
The following will download the wallet server docker volume and move it into place as well.
```bash
echo "fetching wallet server snapshot"
SNAPSHOT_HEIGHT="1049658"
HUB_VOLUME_PATH="/var/lib/docker/volumes/${USER}_wallet_server"
SNAPSHOT_TAR_NAME="wallet_server_snapshot_${SNAPSHOT_HEIGHT}.tar"
SNAPSHOT_URL="https://snapshots.lbry.com/hub/${SNAPSHOT_TAR_NAME}"
wget $SNAPSHOT_URL
tar -xf $SNAPSHOT_TAR_NAME
sudo mkdir -p $HUB_VOLUME_PATH
sudo rm -rf "${HUB_VOLUME_PATH}/_data"
sudo chown -R 999:999 "snapshot_${SNAPSHOT_HEIGHT}"
sudo mv "snapshot_${SNAPSHOT_HEIGHT}" "${HUB_VOLUME_PATH}/_data"
```
## Turn It On
### Start the servers
```
docker-compose up --detach
```
### Check that everything worked
The first time you start the wallet server, it will take a few minutes to download a recent snapshot of the database and extract it. You can follow the progress with
```
docker-compose logs --follow
```
After the wallet server has caught up, it will bind to port 50001 and start responding to requests. You can check if this happened by running
```
sudo netstat -tlpn | grep 50001
```
If there is no output, the port is ont bound yet and the server is still catching up. Check the logs for more info.
After the wallet server is ready, check that it responds to basic RPC calls:
```
echo '{"id":1,"method":"server.version"}' | timeout 1 curl telnet://localhost:50001
```
You should see a response like `{"jsonrpc": "2.0", "result": ["0.46.1", "0.0"], "id": 1}`. If you do, congratulations! You've set up your own wallet server.
To check Elastic search, there are two commands you can use:
```
curl localhost:9200 # get Elastic status
curl localhost:9200/claims/_count # check how many claims have been synced to Elastic
```
## Maintenance
### Stopping and Restarting
Use the usual docker-compose commands (`start`, `stop`, `pause`, etc) to control the servers. Run `docker-compose --help` to see the
options.
### Updating
To update to the latest wallet server release, run the following:
```
docker pull lbry/wallet-server:latest-release
docker-compose down
docker-compose up --detach
```
### Resyncing
From time to time, we'll release an update that requires recreating one of the databases from scratch. Most of the time we will try to ensure there is an automatic migration, but even then, if you think the server has invalid data you can also try a resync.
The process is similar to an update, but causes the server to be down for much longer.
#### Main database
Holds the raw blockchain data and takes several days to resync from scratch, so be sure to have a snapshot or try that last.
```
docker pull lbry/wallet-server:latest-release
docker-compose down
docker volume rm "$(whoami)_wallet_server"
WALLET_SERVER_SNAPSHOT_URL= docker-compose up --detach
```
#### Elasticsearch
ES does the indexing of claims from the main database. It should take around 6 hours to resync on a fast machine.
```
docker pull lbry/wallet-server:latest-release
docker-compose down
docker volume rm "$(whoami)_es01"
docker-compose up --detach
```
## Get in touch
Whether you got to the end without a hiccup or you got stuck along the way, we want to hear from you. [Join our Discord](https://discord.gg/y3W9JuS) to get help, stay updated, and talk to other wallet server operators.

View file

@ -0,0 +1,79 @@
---
title: Hosting your own LBRY Web Instance
description: Setting up an app instance as a webpage.
---
Run your own instance of https://lbry.tv using Docker images.
## Run the SDK
The LBRY SDK provides RPC and streaming endpoints to interact with the LBRY network. Web users will connect to it directly, so it must be web-accessible. You may have to open ports on your firewall.
```
docker run -d -p 5279:5279 -p 5280:5280 vshyba/websdk
```
This image will not save files to disk. It has the `save_blobs` and `save_files` config options set to `false`. If you want to save files, see [Building your own SDK image](#building-your-own-sdk-image) below.
## Run the web app
Clone and install the app as described in the [lbry-desktop repo README](https://github.com/lbryio/lbry-desktop).
If you want to customize it further, follow the extra steps in `Customize the web app` section. Otherwise:
```
git clone https://github.com/lbryio/lbry-desktop.git
yarn
cp .env.defaults .env
```
Configure .env with the following settings. They must match the SDK ports in the previous section.
```
WEB_SERVER_PORT=8080
SDK_API_PATH=http://localhost:5279
LBRY_WEB_API=http://localhost:5279
LBRY_WEB_STREAMING_API=http://localhost:5280
LBRY_API_URL=http://disabled-api/
LBRY_WEB_BUFFER_API=https://disabled
```
Compile and run
```
NODE_ENV=production yarn compile:web
nodejs web/index.js
```
## Building your own SDK image
If you want to customize the SDK settings, you can
Clone the SDK repo:
```
git clone https://github.com/lbryio/lbry-sdk.git
```
Create a `docker/webconf.yaml` file and modify as you need. This is a good start:
```
allowed_origin: "*"
max_key_fee: "0.0 USD"
save_files: false
save_blobs: false
streaming_server: "0.0.0.0:5280"
api: "0.0.0.0:5279"
data_dir: /tmp
download_dir: /tmp
wallet_dir: /tmp
```
Note that it is required to have `streaming_server` and `api` set to user-accessible IPs. If you want this to be accessible on the open web, that means setting them to `0.0.0.0`.
To build the image, run:
```
docker build -f docker/Dockerfile.web -t <your dockerhub username>/<project name, like 'websdk'> .
docker push <dockerhub username/project name>
```

View file

@ -0,0 +1,73 @@
## Hello Satoshi - The LBRY "Hello World" Tutorial
Let's get started with a simple "Hellow World" tutorial... LBRY style!
This tutorial will guide you through creating a basic [Electron](https://electronjs.org) application that calls to the LBRY network and renders an image returned by the network.
Electron is nice because it allows you to easily create web apps that don't rely on any centralized web servers, but you can absolutely use any tooling or language you would like.
### Prerequisites
This tutoral only has a few simple requirements:
- [npm](https://www.npmjs.com). Learn how to install it [here](https://www.npmjs.com/get-npm).
- [git](https://git-scm.com/).
Once you have those installed (see the links above for downloads and How-To's), you are ready to begin!
#### Step 1. Download and build the starter project
Grab "[electron-starter](https://github.com/lbryio/electron-starter)". This project serves as a base upon which you can build LBRY applications. (Similar to "create-react-app" for React development.)
If you have git and npm installed, run the following lines one at a time:
```
git clone https://github.com/lbryio/electron-starter
cd electron-starter
npm install
npm run dev
```
#### Step 2. Make sure everything works
Before we make any changes, it's a good idea to verify that everything is working correctly.
Try typing a word into the text input and click the button to [resolve](https://lbry.tech/api/sdk#resolve) it.
This performs a [[claim]] lookup, which retrieves metadata the title, thumbnail, and file type from the LBRY blockchain.
Try resolving `lbry://doitlive`.
If you received no errors, move on to Step 3! Otherwise, head back to Step 1 to make sure you have all the requirements installed correctly.
#### Step 3. Make a small change to the code
Now that we have the metadata, let's [get](https://lbry.tech/api/sdk#get) the actual file!
The code to do this is already there, just un-comment these lines in the app's [renderer/index.js](https://github.com/lbryio/electron-starter/blob/master/src/renderer/index.js) file.
```js
claimData.innerText = "Loading...";
Lbry.get({ uri: `lbry://${value}` })
.then(result => {
const filePath = result.download_path;
const image = document.createElement("img");
image.src = filePath;
imageWrapper.appendChild(image);
claimData.innerText = JSON.stringify(result, null, 2);
})
.catch(error => {
claimData.innerText = JSON.stringify(error, null, 2);
});
```
This is the code that actually downloads a file.
There are more robust ways to handle the download progress, but this will work fine for images. After you added that code back, try `get`ing `lbry://doitlive`.
### Success! You Did It!
While our Hello Satoshi app isn't much to look at, it shows how simple it is to connect to the LBRY network and download files!

25
documents/tutorials.md Normal file
View file

@ -0,0 +1,25 @@
---
title: Tutorials
description: Learn how to setup, use, deploy, and develop with LBRY.
---
# LBRY Programming Tutorials
## Tutorial #1 - "Hello Satoshi!"
Learn how to [create and modify a simple LBRY electron application](/tutorial-hellosatoshi) we'll call "[Hello Satoshi](/tutorial-hellosatoshi)".
---
# Setup your Development Environment
## Desktop Application
[Video tutorial](/resources/video-lbrydesktop) to setup the [Desktop app](https://github.com/lbryio/lbry-desktop) development environment.
## Android Application
[Video tutorial](/resources/video-lbryandroid) to setup the [Android app](https://github.com/lbryio/lbry-android) development environment.
## LBRY SDK
[Video tutorial](/resources/video-lbrysdk) to setup the [LBRY SDK](https://github.com/lbryio/lbry-sdk) development environment.
## LBRY Blockchain
[Video tutorial](/resources/video-lbrycrd) to setup the [LBRY Blockchain](https://github.com/lbryio/lbrycrd) development environment.

10961
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -11,71 +11,72 @@
"author": "LBRY Team", "author": "LBRY Team",
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.4.4", "@babel/polyfill": "^7.4.4",
"@inc/fastify-ws": "^1.1.0", "@inc/fastify-ws": "^2019.7.23",
"@octokit/rest": "^16.28.0", "@octokit/rest": "^16.28.7",
"@slack/client": "^5.0.1", "@slack/client": "^5.0.2",
"async": "^3.0.1", "async": "^3.1.0",
"async-es": "^3.0.1", "async-es": "^3.1.0",
"choo": "^6.13.3", "choo": "6.13.3",
"choo-async": "^0.1.1", "choo-async": "^0.1.1",
"choo-devtools": "^2.5.1", "choo-devtools": "^3.0.0",
"choo-ssr": "^0.2.1", "choo-ssr": "^0.2.1",
"choo-websocket": "^2.0.0", "choo-websocket": "^2.0.0",
"colorette": "^1.0.8", "colorette": "^1.1.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"cron": "^1.7.1", "cron": "^1.7.1",
"date-format-lite": "^17.7.0", "date-format-lite": "^17.7.0",
"decamelize": "^3.2.0", "decamelize": "^3.2.0",
"dedent": "^0.7.0", "dedent": "^0.7.0",
"dotenv": "^8.0.0", "dotenv": "^8.0.0",
"fastify": "~2.4.1", "fastify": "~2.7.1",
"fastify-compress": "^0.10.0", "fastify-compress": "^0.10.0",
"fastify-helmet": "^3.0.0", "fastify-helmet": "^3.0.1",
"fastify-static": "^2.4.0", "fastify-static": "^2.5.0",
"front-matter": "^3.0.2", "front-matter": "^3.0.2",
"fs-exists-sync": "^0.1.0", "fs-exists-sync": "^0.1.0",
"got": "^9.6.0", "got": "^9.6.0",
"graceful-fs": "^4.1.15", "graceful-fs": "^4.2.1",
"link-module-alias": "^1.2.0", "link-module-alias": "^1.2.0",
"make-promises-safe": "^5.0.0", "make-promises-safe": "^5.0.0",
"markdown-it": "^8.4.2", "markdown-it": "^9.0.1",
"markdown-it-anchor": "^5.2.4", "markdown-it-anchor": "^5.2.4",
"prismjs": "^1.15.0", "prismjs": "^1.17.1",
"redis": "^2.8.0", "redis": "^2.8.0",
"slack-node": "^0.1.8", "slack-node": "^0.1.8",
"socket.io": "^2.2.0", "socket.io": "^2.2.0",
"stringify-object": "^3.3.0" "stringify-object": "^3.3.0",
"request": "latest"
}, },
"description": "Documentation for the LBRY protocol and associated projects", "description": "Documentation for the LBRY protocol and associated projects",
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.4.4", "@babel/cli": "^7.5.5",
"@babel/core": "^7.4.5", "@babel/core": "^7.5.5",
"@babel/plugin-external-helpers": "7.2.0", "@babel/plugin-external-helpers": "7.2.0",
"@babel/plugin-proposal-class-properties": "7.4.4", "@babel/plugin-proposal-class-properties": "7.5.5",
"@babel/plugin-proposal-decorators": "7.4.4", "@babel/plugin-proposal-decorators": "7.4.4",
"@babel/plugin-proposal-export-namespace-from": "7.2.0", "@babel/plugin-proposal-export-namespace-from": "7.5.2",
"@babel/plugin-proposal-function-sent": "7.2.0", "@babel/plugin-proposal-function-sent": "7.5.0",
"@babel/plugin-proposal-json-strings": "7.2.0", "@babel/plugin-proposal-json-strings": "7.2.0",
"@babel/plugin-proposal-numeric-separator": "7.2.0", "@babel/plugin-proposal-numeric-separator": "7.2.0",
"@babel/plugin-proposal-throw-expressions": "7.2.0", "@babel/plugin-proposal-throw-expressions": "7.2.0",
"@babel/plugin-syntax-dynamic-import": "7.2.0", "@babel/plugin-syntax-dynamic-import": "7.2.0",
"@babel/plugin-syntax-import-meta": "7.2.0", "@babel/plugin-syntax-import-meta": "7.2.0",
"@babel/preset-env": "^7.4.5", "@babel/preset-env": "^7.5.5",
"@babel/register": "^7.4.4", "@babel/register": "^7.5.5",
"@inc/eslint-config": "^1.1.3", "@inc/eslint-config": "^2019.7.23",
"@inc/sasslint-config": "^2019.5.7", "@inc/sasslint-config": "^2019.7.23",
"@lbry/color": "^1.1.1", "@lbry/color": "^1.1.1",
"@lbry/components": "^2.7.2", "@lbry/components": "^2019.6.22",
"eslint": "^5.16.0", "eslint": "^6.1.0",
"husky": "^2.4.0", "husky": "^3.0.2",
"nodemon": "^1.19.1", "nodemon": "^1.19.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"pino-pretty": "^3.1.0", "pino-pretty": "^3.2.0",
"sass": "^1.21.0", "sass": "^1.22.9",
"sass-lint": "^1.13.1", "sass-lint": "^1.13.1",
"snazzy": "^8.0.0", "snazzy": "^8.0.0",
"standardx": "^3.0.1", "standardx": "^4.0.0",
"updates": "^8.1.0" "updates": "^8.5.1"
}, },
"engines": { "engines": {
"node": "10.2.x" "node": "10.2.x"
@ -93,15 +94,15 @@
"private": true, "private": true,
"scripts": { "scripts": {
"css": "sass --load-path=node_modules --update app/sass:app/dist --style compressed", "css": "sass --load-path=node_modules --update app/sass:app/dist --style compressed",
"format": "eslint '**/*.js' --fix --ignore-pattern '/app/dist/'", "format": "eslint . --fix --ignore-pattern '/app/dist/'",
"postinstall": "link-module-alias", "postinstall": "link-module-alias",
"preinstall": "command -v link-module-alias; link-module-alias clean || true", "preinstall": "command -v link-module-alias;link-module-alias clean || true",
"start": "npm i; npm run css; NODE_ENV=production node index.js", "start": "npm i && npm run css && NODE_ENV=production node index.js",
"test": "run-s test:*", "test": "run-s test:*",
"test:dependencies": "updates --update ./ --exclude prismjs", "test:dependencies": "updates --update ./ --exclude prismjs",
"test:lint": "standardx --verbose | snazzy", "test:lint": "standardx --verbose | snazzy",
"test:sass": "sass-lint --config ./node_modules/@inc/sasslint-config/config.json --verbose --no-exit", "test:sass": "sass-lint --config ./node_modules/@inc/sasslint-config/config.json --verbose --no-exit",
"watch": "npm run css; run-p watch:*", "watch": "npm run css && run-p watch:*",
"watch:sass": "sass --load-path=node_modules --watch app/sass:app/dist --style compressed", "watch:sass": "sass --load-path=node_modules --watch app/sass:app/dist --style compressed",
"watch:server": "NODE_ENV=development nodemon --ignore 'app/dist'" "watch:server": "NODE_ENV=development nodemon --ignore 'app/dist'"
}, },
@ -110,5 +111,5 @@
"app/dist" "app/dist"
] ]
}, },
"version": "5.3.1" "version": "5.3.2"
} }